Techniques for Debugging IL

I mentioned in the recent dev lab that you can debug at the IL level. I demoed two ways to do this, and here I wanted to compare them more thoroughly.

The big thing that’s missing is that while you can do IL level stepping, you can’t view the IL evaluation stack.


1) Rewriting the PDBs:

It’s common knowledge that ILasm + ILdasm round-trip images (dll/exe), but you can also use them to roundtrip or adjust PDBs. 

csc hi.cs /debug+
ildasm hi.exe / /source
ilasm /debug

hi_il.exe/.pdb now give you IL-level debugging because the pdb maps from the IL in the image to the textual representation of that IL (  In contrast, hi.pdb will map from the IL in the image to the original high-level source language (hi.cs).

Note that ILdasm’s /source switch just embeds the original source language as comments into the resulting IL. This helps make the IL more readable.
ILDasm’s /linenum switch injects corresponding .line directives (like C/C++’s #line), which would normally map the IL back to the original source (hi.cs in this case). That’s useful for round-tripping the PDB. Since we’re actually changing the pdb to from IL–>CS to  IL–>IL, we leave off the /linenum switch. You could inject .line directives in the roundtripping process to create an arbitrary new PDB mapping.

Key properties of this technique:
– This lets you leverage existing source-level debugging tools.
– This is good that it lets you step at every single IL instruction.  The key here is that the /debug switch to ilasm is actually generating “explicit” sequence points which will cause the jitter to ensure there is native code for each IL instruction. This obviously heavily impedes optimizations; but in exchange gives you excellent IL stepping granularity.

More on round-tripping here: 


2) Use IL-aware tools

The ICorDebug interfaces support IL-level debugging, but most tools (like VS2005) only support Source-level debugging. We have an MDbg IL debugging extension to prove this is possible.

Key properties of this technique:
– this requires an IL-aware tool, which are rarer.
– You don’t have to recompile the debuggees. You’re debugging the actual code that’s executing.
– But you may skip IL instructions since multiple IL instructions get compiled to a single native instruction.

Comments (4)

  1. oan says:

    I have a question. How can I check instance of class which calls my method?





       C c = new C();








        How can I get instance of A here?



    Thanks a lot in advance!