Repository navigation
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.)
|
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: https://github.com/am11/runtime/tree/feature/managed-ildasm2 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
It's ~10 additional classes and if we skip 1-2MB boilerplate, that'd make sense? (plus the exemption of a separate |
|
We are shipping ilasm/ildasm/ilverify as separate tools packages. I think we want to continue doing that. If we were to build all these tools into one binary, we would be shipping dead weight in each of the packages. It does not make sense to me. |
The size measurements suggest that dead weight would be a small fraction #128553 (comment) (5.5+3.1+4 vs. 6.2 MB). |
|
Why would we want to ship any dead weight in these packages in the first place? This size optimizations makes sense only for binaries that ship bundled in the SDK. It does not make sense for tools that ship as independent packages. |
|
We could alternatively ship these tools together in a single "iltools" NuGet package. As for granularity, these tools already feature dozens of switches where most users only utilize a fraction of the functionality. The rest is essentially dead weight for their repeated usage anyway, so adding a few more AOT-compiled classes changes very little. (Note: Avoiding the few seconds of overhead from each |
|
Draft Pull Request was automatically closed for 30 days of inactivity. Please let us know if you'd like to reopen it. |
|
@am11 we're just about finished with managed ilasm, so I'm starting to look at managed ildasm now. Can you merge main into this PR and resolve any conflicts and I'll get it in so we can get started on this? |
|
Azure Pipelines: Successfully started running 7 pipeline(s). 8 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
|
@jkoritzinsky merged main and synced the skeleton with managed ilasm: same project/packaging layout ( |
Do we actually need ildasm_inbuild for ildasm? |
It's for parity with ilasm: |
|
@am11 can you make a separate PR with the NativeAotToolPackage.targets fixes so we can get that in faster? |
|
Opened #136755 for the NativeAotToolPackage.targets fix. |
|
@jkoritzinsky, shall we move forward with this structure? I can provide matching implementation to native ildasm after this goes in. |
jkoritzinsky
left a comment
There was a problem hiding this comment.
A few nits but otherwise LGTM