Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cecil fails to load portable pdb files for crossgen'd assemblies #704

Closed
eerhardt opened this issue Nov 13, 2020 · 2 comments · Fixed by #770
Closed

Cecil fails to load portable pdb files for crossgen'd assemblies #704

eerhardt opened this issue Nov 13, 2020 · 2 comments · Fixed by #770

Comments

@eerhardt
Copy link

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:

if (!symbol_reader.ProcessDebugHeader (GetDebugHeader ())) {
symbol_reader = null;
if (throwIfSymbolsAreNotMaching)
throw new SymbolsNotMatchingException ("Symbols were found but are not matching the assembly");

and

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.

@jbevain
Copy link
Owner

jbevain commented Nov 13, 2020

Good catch. Any chance you could attach a dll here that reproduces the issue?

@eerhardt
Copy link
Author

No problem. You can use any dll that is in the .NET Core's runtimepack for win-x64. I found it using System.Private.Xml, so I've attached that assembly and its corresponding portable pdb in the following .zip:

System.Private.Xml.zip

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants