InlineIL.Fody: Invalid assembly after weaving
Not sure if this is an InlineIL.Fody
, Fody
or Mono.Cecil
bug.
Repro: https://github.com/CosmosOS/Cosmos/tree/inline-il
The verification fails, and if I try to load the assembly at runtime it fails with BadImageFormatException
. ILSpy loads it correctly.
I tried adding ExcludeAssets="All"
here: Cosmos.Core_Asm.csproj#L13, and then used ildasm
on both assemblies, and the main difference (ignoring the parts which were not weaved) is the .imagebase
, which is 0x00400000
when weaved, and 0x10000000
when not.
Any help would be appreciated.
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Comments: 16 (9 by maintainers)
That was a hack to support a niche edge case I once had. To do with mixing signed and unsigned dlls when using ilmerge. That use case is no longer valid and that property copy could be removed
Yay \o/
Indeed, I can see that Cosmos sets
SignAssembly
in the “targets” file. Glad you got it figured out.@SimonCropp why does Fody copy
SignAssembly
toFodySignAssembly
inFody.targets
? The commit that introduces this change only says “perf hacks”…@jp2masa FYI this should be fixed in Fody v3.2.10
I found the problem:
SignAssembly
is being set toTrue
after Fody “captures” its value onFodySignAssembly
, so the assembly was being signed by the compiler, but not by Fody.Thanks for the help!
Some other stuff: in
IMAGE_COR20_HEADER
,StrongNameSignature.VirtualAddress
andStrongNameSignature.Size
are both zero in the weaved assembly. That doesn’t look right either, but when I round-trip the dll through dnSpy, PEVerify happily loads it. After round-tripping, these headers are nonzero. So that looks like a decent clue.I added a strong name to my isolated project, and these fields are nonzero in the build output. Everything works fine there.
This definitely starts to look like a strong naming issue. Maybe Fody can’t find the key file for some reason.
Could you please do the following? This could help me pinpoint the issue.
msbuild Cosmos.Core_Asm.csproj /p:Configuration=Release /t:Restore,Rebuild /bl:output.binlog
(if the broject doesn’t build well as standalone, build the whole solution instead)I’ll take a look at it tomorrow.
Ok, so here’s a first quick analysis.
Here’s a dnSpy dump of both files’ headers, if you want to diff them:
Not weaved
Weaved
Major differences: non weaved -> weaved
IMAGE_FILE_HEADER.Characteristics
: Non weaved:ExecutableImage, LargeAddressAware, DLL
Weaved:ExecutableImage, 32BitMachine, DLL
That 32BitMachine bit should not be there in an MSIL assembly.IMAGE_OPTIONAL_HEADER32.ImageBase
: Non weaved:10000000
Weaved:00400000
This is what you noticed.IMAGE_OPTIONAL_HEADER32.CheckSum
: Non weaved:00015FEF
Weaved:00000000
Ok, so this one seems really bad, but actually Cecil hardcodes zero here, as the docs say:I thought the first one was the issue, but then I compared that to a known good netstandard2.0 assembly that uses InlineIL, and the values match. Actually, it’s Cecil that encodes this header like so.
I’l keep looking at this.