Add managed ildasm initial project structure#123848
Conversation
am11
commented
Feb 1, 2026
- Add src/tools/ildasm with CLI, library, and test projects
- Implement all 218 IL opcodes in InstructionDisassembler
- Add Options class and wire CLI arguments to library
- Output basic assembly/module/type/method structure
- Add TODOs for remaining work (token resolution, etc.)
src/tools/ildasm/tests/ILDisassembler.Tests/InstructionDisassemblerTests.cs
Show resolved
Hide resolved
|
Let's wait on ildasm until we finish ilasm. In any case, I was thinking that we should build ildasm on the managed type system and the ILImporter infrastructure over there so we can reuse a bunch of code and have less to maintain in the future. |
Managed type system expects metadata for all dependencies that is not compatible with how ildasm works. You would be constantly fighting against that. BTW: We have a little managed IL disassembler as a debugging aid: https://github.com/dotnet/runtime/blob/main/src/coreclr/tools/Common/TypeSystem/IL/ILDisassembler.cs . It was not built using |
|
I was able to rewire it with: It's a bit cleaner. Do you want this S.R.M version or push that one? |
🤖 Copilot Code Review — PR #123848Holistic AssessmentMotivation: Adding a managed ildasm tool complements the recently merged managed ilasm (#122112) and provides cross-platform IL inspection capabilities. The motivation is sound. Approach: The project structure (library + CLI + tests) mirrors the existing ilasm tool, which is good for consistency. Using System.Reflection.Metadata and System.Reflection.PortableExecutable is the right choice for managed PE/metadata access. Summary: Detailed Findings❌ Branch Target Calculation — ECMA-335 ViolationInstructionDisassembler.cs lines ~578-592 Per ECMA-335 §III.1.7.1, branch offsets are relative to the beginning of the next instruction, not the operand position. The current implementation captures private static string FormatBranchShort(string mnemonic, ref BlobReader reader)
{
int offset = reader.Offset; // Position of operand
sbyte delta = reader.ReadSByte();
int target = offset + delta; // Bug: should be (offset + 1) + delta
return $"{mnemonic} IL_{target:X4}";
}Fix: private static string FormatBranchShort(string mnemonic, ref BlobReader reader)
{
sbyte delta = reader.ReadSByte();
int target = reader.Offset + delta; // reader.Offset is now past the operand
return $"{mnemonic} IL_{target:X4}";
}Same issue in ❌ Resource Management — Stream LeakDisassembler.cs lines ~51-56 The file stream is opened but never tracked for disposal: var stream = File.OpenRead(filePath);
_peReader = new PEReader(stream);
Actually, after checking: _peReader = new PEReader(stream, PEStreamOptions.Default);💡 Suggestion: Add a comment or use explicit options to clarify stream ownership.
|
9777c82 to
2eac0d7
Compare
3f1b2dc to
04cb383
Compare
- Add src/tools/ildasm with CLI, library, and test projects - Implement all 218 IL opcodes in InstructionDisassembler - Add Options class and wire CLI arguments to library - Output basic assembly/module/type/method structure - Add TODOs for remaining work (token resolution, etc.)
04cb383 to
7b0f446
Compare