5

Over the last couple of weeks, I've been playing around with the unmanaged .NET debugging API.

While MSDN documents the interfaces itself, to find out how to actually use them in any meaningful way, I resorted to various blogs (mainly Mike Stall's) and the managed wrappers in the CLR Managed Debugger samples and the ILSpy sources. In the end I was able to attach my test program to a running process, set breakpoints and hit them.

What I would like to do next is on hitting such a breakpoint, read a field of the relevant object instance. This works fine when the debug target method hasn't been NGEN'ed or JIT'ed, by disabling loading NGEN'ed assemblies (the environment setting 'COMPLUS_ZAPDISABLE=1') and disabling JIT optimizations (aka the '.ini file trick').

However, when I try the same with my ideal target - retail optimized (NGEN/JIT'ed) code - it doesn't work. For instance: I can on hitting the entry breakpoint still retrieve the number of method arguments, but I can't get the first argument itself (debugging API throws an exception).

Now, I imagine the reason for this is because the debugging APIs are supposed to be platform independent, and in this case the assemblies aren't anymore. But what if I accept this platform dependency to an Intel one: as far as I'm aware the CLR uses the fastcall calling convention where in this case the ECX register contains the first method argument (the implicit 'this' reference for member functions).

I tested this, and indeed on hitting the breakpoint, ECX contains the OBJECTREF (address of the object instance), in NGEN'ed assemblies.

Now the final step in reading the instance field is to retrieve the field offset relative to this pointer, and this is where I'm stuck, since I seem unable to find out how the CLR does the packing of the instance fields during native code generation.

I realize this may be CLR version/implementation dependent, but apparently there are ways, as WinDbg with the SOS extension is able to find this layout. If not through the debugging APIs, could I somehow leverage SOS.dll ?

Ruurd Keizer
  • 211
  • 1
  • 7

1 Answers1

0

For your first question, the reason you can't find arguments/locals is that you're debugging optimized code. Optimized code does not allow tracking of args/locals.

As for your second question, you need to use SOS.dll SOSEX.dll or PSSCOR2/4.dll in WinDbg or SOS/PSSCOR in Visual Studio in order to read the fields of an object.

EDIT: I see now that you'd like to do this from code. This requires use of the Data Access (DAC) API, which is undocumented, unfortunately.

Steve Johnson
  • 2,958
  • 13
  • 15