Skip to content
Siegfried Pammer edited this page Jul 13, 2018 · 19 revisions

The srm branch of ILSpy is - as the name suggests - a port of ILSpy and the underlying decompiler and disassembler engine to System.Reflection.Metadata [1] provided by Microsoft, already used in the Roslyn framework and Visual Studio. This change will be part of the upcoming ILSpy 4.0 release.

The main reasons for this step were:

  • Memory usage and performance: Mono.Cecil has a very bulky object model in terms of memory usage. This made it necessary to copy all necessary information from the Cecil objects to the unresolved type system (A representation of the metadata similar to plain source code, but without referenced assemblies). The System.Reflection.Metadata API is very lightweight in this regard, because it only allocates a few caches, and provides direct view-like access to the bytes in the metadata streams and tables, without ever creating a copy of the memory.

  • Stability: Mono.Cecil does not provide direct access to the IL bytes. It only provides a list of Instruction objects. This is very bad in terms of memory allocations and if there are any garbage bytes in the IL stream, it fails with an exception. It was also not possible to parse the IL bytes without Cecil internally accessing the debug information, which made our analyzers fail on assemblies with invalid debug metadata. With System.Reflection.Metadata we can now parse and interpret the IL bytes independently. This is a great improvement for both the analyzers and the disassembler.

  • Missing information: Some type information stored in signatures, was hidden by the Cecil object model and was only available after resolving type and member references, which made it impossible for us to recover this information, if the referenced assembly was not available. (DG: pls review)

  • Writing portable PDB files: (currently in preview) ILSpy 4.0 comes with the ability to create portable PDB files from any assembly that can be successfully decompiled.

Summary of all the changes, aka Who Moved My Cheese?

For ILSpy users

You will (hopefully) not be affected in a bad way by this change. All functionality provided by ILSpy should stay the same or be improved only. If you come across any problem that worked in a previous version of ILSpy, but no longer in version 4.0, please open an issue. Thank you!

For users of the ICSharpCode.Decompiler nuget

  • CSharpDecompiler:
    • now uses SRM's EntityHandle in all Decompile* methods. See *** for examples.
    • ConvertType removed: Use the TypeSystem to retrieve the IEntity instance and use TypeSystemAstBuilder to create the AstNode/AstType.
  • IDecompilerTypeSystem:
    • Added DecodeMethodSignature and DecodeLocalSignature to decode signatures into IType instances.
    • Resolve* methods to retrieve type system entities for metadata tokens.
    • GetCecil replaced by IEntity.MetadataToken: Each entity now "knows" its metadata token.
    • GetMetadata(): Retrieves the SRM MetadataReader of the main assembly, which provides access to metadata tables. You can use IEntity.MetadataToken to retrieve metadata info. If you need to access an entity from a referenced assembly, you should use IEntity.ParentAssembly.PEFile.Metadata to access the corresponding MetadataReader.
    • GetModuleDefinition or IAssembly.PEFile can be used to access the PEFile, which provides an interface to the metadata tables and streams.

For AddIn developers

  • Language API, Tree View and Search now uses the Decompiler TypeSystem.
  • IAnalyzer API (to be expanded after clean-up, refactoring)

Architecture internals

(to be expanded)

[1] https://github.com/dotnet/corefx/tree/master/src/System.Reflection.Metadata