Problems for a managed debugger for v1.1?

Now that we’ve released a managed debugger sample for V2.0, people commonly ask “What about v1.1?”. I briefly touched on this when in a comment in the original MDbg post ( Here are more details:

In theory, it’s doable, but there are some hurdles. Here are the biggest problems to back-porting MDbg to v1.1:
1)       CLR Bugs: The v1.0 / v1.1 ICorDebug implementations have ref-counting + QI bugs in our COM-classic implementations that will break COM-interop (perhaps we can fixing these in a service pack). For example, we break the QI rules  for roundtripping around ICorDebugFrame, ICorDebugILFrame, and ICorDebugNativeFrame. So any v1.1 managed debugger may be doomed. COM-interop excercises these rules more aggressively than the unmanaged debugging, so these bugs weren’t an issue in v1.1 because our only clients were unmanaged. In theory, if we had a comprehensive list of these defects, a managed debugger could do acrobatics to compensate for them (such as avoiding certain casting operations to avoid the underlying QI). I’m not sure if this is even possible in practice.  Creating MC++ wrappers would be one way to get around these.
2)       MDbg uses Whidbey functionality, such as generics.  Most of MDbg was written early in whidbey, so it was really targeting the v1.1 feature set and does not use v2.0 features extensively. This is probably the easiest thing to port.
3)       The metadata versioning issue. ( ICorDebug specifically uses the CLR coclasses, so even if you implement your own metadata implementations that avoid the versioning issue, ICorDebug won’t pick them up. If you only debug v1.1 apps, this won’t be an issue. Now this is only an issue if you wanted the v1.1 MDbg to debug v2.0 apps.

A debugger also needs to user other unmanaged APIs (CorPub.idl, CorSym.idl), but these can be wrapped for managed code without serious caveats.

All in all, it may be possible. Once the above issues are out of the way, the problem simplifies into just writing yet another managed application.
MDbg is a publicly available sample, so folks are welcome to play around with it and experiment with things like porting it to v1.1. We’d love to hear about it (either replies on this blog, or comments to mailto: clrmdbg AT

Comments (11)

  1. sam saffron says:

    Regarding 1. Couldnt you just write an unmanaged "classic" dll that wraps the problem COM calls. then access using standard interop. Also, I thought the Marshal.ReleaseCOMObject could be uses to free up the hanging QIs

    Whats the feasability of adapting MDbg to do de-compiling on the fly? ala reflector. In 2.0 using E&C id assume you cound inject some reflection calls to get a proper stack trace and then use pattern matching to de-compile (if not provided by the debugger interfaces).

  2. Mike Stall says:

    1) We’ve actually played around with the unmanaged "classic" dll because we want to get MDbg to run on Rotor (which doesn’t support COM-interop). This is actually surprisingly difficult, but feel free to play around and give it a try!

    The problem with the QIs is not that we leak references, it’s that if QI’s neeed to be "stable". Eg, if we have an IA interface to some object, and then we QI for IB, we need to be able to cal QI on that IB instance to get back the IA instance. Eg, go IA –> IB –> IA. We have bugs in our QI that prevent that.

    2) Decompiling – It should be pretty feasible. The Debug API operates at the IL-level anyways (see The MDbg sample already includes an IL disassembler. The only remaining trick is to hook up your favorite disassembler to MDbg on top of the IL-disassembler example.

    You wouldn’t need any EnC/reflection goo – the ICorDebug APIs provide fully stack tracing functionality.

  3. Sam Saffron says:

    It may be a little naive, but couldnt you just write a COM object that exposes all the methods in IA and IB and call that from the managed code, that way you do not have to flick between interfaces … a big aggragate com component to do everything ….

  4. Mike Stall says:

    Suppose QI IA –> IB works, but there’s a bug where QI IB–>IA fails.

    You need to change how MDbg uses IA and IB, but yes, I think that could be made to work.

    MDbg would only persist the IA interface. Whenever it needed the IB interface, it would QI IA –> IB, use IB, and then throw IB away. Thus it would never have to go IB–>IA, and life would be fine.

    I think that’s effectively what you’re proposing (though perhaps you cache the IB along w/ the IA so that you don’t have to keep repeating the QI).

  5. I often publish little samples in this blog based off MDbg (which generally show off the debugging services…

  6. MDbg is a debugger for managed code written entirely in C# (and IL), which started shipping in the CLR