-
-
Notifications
You must be signed in to change notification settings - Fork 652
Description
See dotnet/linker#1620 (comment) for more context.
Using the following code:
ISymbolReaderProvider _symbolReaderProvider = ...;
AssemblyDefinition assembly = ...;
var symbolReader = _symbolReaderProvider.GetSymbolReader (
assembly.MainModule,
fileName);
assembly.MainModule.ReadSymbols (symbolReader);When the AssemblyDefinition assembly points to a crossgen'd assembly, fails to load the symbols in a portable pdb file.
The reason it fails is because a cross gen'd assembly's Debug Directories has two entries:
>dumpbin /headers C:\Users\eerhardt\.nuget\packages\microsoft.netcore.app.runtime.win-x64\5.0.0-rtm.20508.7\runtimes\win-x64\lib\net5.0\System.Private.Xml.dll
Debug Directories
Time Type Size RVA Pointer
-------- ------- -------- -------- --------
8B4C3C7E cv 11C 00801444 800044 Format: RSDS, {2E2D2AB8-5EC5-3956-8E87-3741A2D79E30}, 1, System.Private.Xml.ni.pdb
8B4C3C7E cv 77 00801560 800160 Format: RSDS, {62DF6790-3B25-4522-8E89-99FB491C298D}, 1, F:\git\runtime2\artifacts\obj\System.Private.Xml\net6.0-windows-Release\System.Private.Xml.pdb
00000000 repro 0 00000000 0
And the 2nd entry is the portable pdb entry.
However, ModuleDefinition.ReadSymbols appears to only look at the first entry in the Debug Directories and it throws an exception when the first entry doesn't match the portable pdb's Guid. See the following code:
cecil/Mono.Cecil/ModuleDefinition.cs
Lines 1060 to 1064 in 0a2f294
| if (!symbol_reader.ProcessDebugHeader (GetDebugHeader ())) { | |
| symbol_reader = null; | |
| if (throwIfSymbolsAreNotMaching) | |
| throw new SymbolsNotMatchingException ("Symbols were found but are not matching the assembly"); |
and
cecil/Mono.Cecil.Cil/PortablePdb.cs
Lines 68 to 100 in ab5075b
| public bool ProcessDebugHeader (ImageDebugHeader header) | |
| { | |
| if (image == module.Image) | |
| return true; | |
| var entry = header.GetCodeViewEntry (); | |
| if (entry == null) | |
| return false; | |
| var data = entry.Data; | |
| if (data.Length < 24) | |
| return false; | |
| var magic = ReadInt32 (data, 0); | |
| if (magic != 0x53445352) | |
| return false; | |
| var buffer = new byte [16]; | |
| Buffer.BlockCopy (data, 4, buffer, 0, 16); | |
| var module_guid = new Guid (buffer); | |
| Buffer.BlockCopy (image.PdbHeap.Id, 0, buffer, 0, 16); | |
| var pdb_guid = new Guid (buffer); | |
| if (module_guid != pdb_guid) | |
| return false; | |
| ReadModule (); | |
| return true; | |
| } |
Cecil should continue iterating the list and discover the 2nd entry and match it.