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

Support reading raw metadata blobs and Portable PDBs #3068

Closed
jkoritzinsky opened this issue Aug 29, 2023 · 6 comments · Fixed by #3149
Closed

Support reading raw metadata blobs and Portable PDBs #3068

jkoritzinsky opened this issue Aug 29, 2023 · 6 comments · Fixed by #3149
Assignees
Labels
Enhancement Areas for improvement
Milestone

Comments

@jkoritzinsky
Copy link

Is your feature request related to a problem? Please describe.

I have been working on a new reader/writer for ECMA-335 metadata blobs. I've regularly used ILSpy for decompiling .NET assemblies, and I've had very positive experiences using the Metadata tab to explore the metadata tables. However, I've discovered that ILSpy does not support loading raw ECMA-335 blobs or Portable PDBs to explore the metadata tables.

Describe the solution you'd like

I'd like to be able to open a raw ECMA-335 metadata blob or a Portable PDB in ILSpy and explore the metadata tables using the Metadata Tab. I don't care if any other features of ILSpy are supported (especially as many of them don't make sense when all you have is a PDB or raw metadata).

Additional context

I'd be willing to help with the contribution of this feature.

@jkoritzinsky jkoritzinsky added the Enhancement Areas for improvement label Aug 29, 2023
@siegfriedpammer siegfriedpammer self-assigned this Aug 30, 2023
@siegfriedpammer
Copy link
Member

Do you have examples of raw ECMA-335 blobs? Are they different from portable PDBs? Thanks!

@jkoritzinsky
Copy link
Author

I'll pull some examples next week for raw blobs for you. Portable PDBs are full PE files with metadata.

@jkoritzinsky
Copy link
Author

Here's an example of a raw ECMA-335 blob (wrapped in a ZIP file to make uploading to GitHub easy):
System.Reflection.Metadata.ApplyUpdate.Test.AddStaticLambda.dll.composite.zip

@siegfriedpammer siegfriedpammer added this to the 8.2 milestone Oct 23, 2023
@siegfriedpammer siegfriedpammer removed this from the 8.2 milestone Nov 4, 2023
@christophwille christophwille added this to the 9.0 milestone Nov 5, 2023
@siegfriedpammer
Copy link
Member

@jkoritzinsky I have trouble reading the dmeta file you sent using SRM... is there something I am missing, i.e. do I need to implement a custom loader?

I trying to load it using:

using var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read));
var provider = MetadataReaderProvider.FromMetadataStream(fileStream, MetadataStreamOptions.PrefetchMetadata);
var metadata = provider.GetMetadataReader();

leads to the following exception:

System.BadImageFormatException
  HResult=0x8007000B
  Message=Not enough space for stream header name.
  Source=System.Reflection.Metadata
  StackTrace:
   at System.Reflection.Metadata.MetadataReader.ReadStreamHeaders(BlobReader& memReader)
   at System.Reflection.Metadata.MetadataReader..ctor(Byte* metadata, Int32 length, MetadataReaderOptions options, MetadataStringDecoder utf8Decoder, Object memoryOwner)
   at System.Reflection.Metadata.MetadataReaderProvider.GetMetadataReader(MetadataReaderOptions options, MetadataStringDecoder utf8Decoder)

thanks for your help!

@siegfriedpammer
Copy link
Member

So after some reading of ECMA-335 and fiddling with a hex editor I found the problem: It seems that the file you sent is valid according to ECMA-335 except for one small detail:

image

The header is correct up to the point where the length of the version string is given at offset 12/0xC (red highlight). Let's take a look at ECMA-335 part. II 24.2.1:

image

The integer at offset 12 is the length of the version string rounded up to the next multiple of 4. The value is 11/0xB for the string "v4.0.30319\0" (including the null byte at the end), which is not a multiple of 4 obviously and causes SRM's MetadataReader to misinterpret the stream headers. Using the correct value 12/0xC (again red highlight) here fixes the problem.

The corrected stream:

image

@jkoritzinsky Please tell me if my analysis is correct or there is something else going on. Thanks!

@jkoritzinsky
Copy link
Author

That analysis is correct! Thanks for digging into it. I'll investigate the misbehaving code.

jkoritzinsky added a commit to AaronRobinsonMSFT/DNMD that referenced this issue Jan 4, 2024
We need to write the length of the aligned buffer, not the length of the version string. Discovered in icsharpcode/ILSpy#3068
jkoritzinsky added a commit to AaronRobinsonMSFT/DNMD that referenced this issue Jan 4, 2024
We need to write the length of the aligned buffer, not the length of the version string. Discovered in icsharpcode/ILSpy#3068
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 7, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Enhancement Areas for improvement
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants