Monday, December 22, 2008

managed debugging

Setting Breakpoints

To stop when mscorwks.dll is loaded (so that SOS can be loaded ASAP)
After starting a program under debugger:
0:000>sxe ld mscorwks
0:000>g

It stops with message like below
ModLoad: 00000642`7f330000 00000642`7fd53000 C:\Windows\Microsoft.NET\Framework64\v2.0.50727\mscorwks.dll
ntdll!ZwMapViewOfSection+0xa:
00000000`777b5cfa c3 ret

Now load SOS/PSSCor2 extension.
0:000> .loadby sos mscorwks

To break at any CLR exception
The command below will enable breaking at any clr exception:
0:000> sxe clr

The command below will disable breaking at any clr exception:
0:000> sxd clr

To list exception handling status, use sx command.
0:000> sx

To break at a managed function
!bpmd command can be used to create a breakpoint to any managed function regardless of its JITted status. Read below to find out usage.

To set breakpoint at Generic type's function
Generic types are given special name after they are compiled. Test becomes Test`1, for example. So you should try something like below to set a breakpoint in one of functions defiend in generic type:
0:000> !bpmd ConsoleApplication25.exe ConsoleApplication25.Test`1.WriteLine
Found 1 methods...
MethodDesc = 0000064280013638
Adding pending breakpoints...

See Browing Types to find out how to list all available types in app domain and list all methods defined in a type.

To stop at Main() function
The Main() function is not JITted at this point. Use following to stop at Main. Use !bpmd [ModuleName] [Type]

0:000> !bpmd DebugManagedLeak.exe DebugManagedLeak.Program.Main
Adding pending breakpoints...
0:000> g

CLR notification: module 'mscorlib' loaded
(700.1e50): CLR notification exception - code e0444143 (first chance)
CLR notification: module 'DebugManagedLeak' loaded
(700.1e50): CLR notification exception - code e0444143 (first chance)
CLR notification: method 'DebugManagedLeak.Program.Main(System.String[])' code generated
(700.1e50): CLR notification exception - code e0444143 (first chance)
JITTED DebugManagedLeak!DebugManagedLeak.Program.Main(System.String[])
Setting breakpoint: bp 0000064280150120 [DebugManagedLeak.Program.Main(System.String[])]
Breakpoint 0 hit
DebugManagedLeak!DebugManagedLeak.Program.Main(System.String[]):
00000642`80150120 48894c2408 mov qword ptr [rsp+8],rcx ss:00000000`0024e9e0=0000000002761a08
*** WARNING: Unable to verify checksum for DebugManagedLeak.exe

0000064280150120 is address of JITted function. It contains machine instructions.

To get annotated disassembly of JITTed method
0:000> !U 0000064280150120

Normal JIT generated code
DebugManagedLeak.Program.Main(System.String[])
Begin 0000064280150120, size 293
>>> 00000642`80150120 48894c2408 mov qword ptr [rsp+8],rcx
00000642`80150125 55 push rbp
00000642`80150126 4881ecf0000000 sub rsp,0F0h
00000642`8015012d 488d6c2420 lea rbp,[rsp+20h]
00000642`80150132 48896500 mov qword ptr [rbp],rsp
00000642`80150136 48c7450800000000 mov qword ptr [rbp+8],0
00000642`8015013e 48c7451000000000 mov qword ptr [rbp+10h],0
00000642`80150146 c7451800000000 mov dword ptr [rbp+18h],0
00000642`8015014d 48c7452000000000 mov qword ptr [rbp+20h],0
00000642`80150155 c6452800 mov byte ptr [rbp+28h],0
00000642`80150159 41b818000000 mov r8d,18h
00000642`8015015f 33d2 xor edx,edx
00000642`80150161 488d4d30 lea rcx,[rbp+30h]
00000642`80150165 e8768052ff call mscorwks!JIT_MemSet (00000642`7f6781e0)
00000642`8015016a 33c9 xor ecx,ecx
00000642`8015016c 48894d48 mov qword ptr [rbp+48h],rcx
00000642`80150170 48894d50 mov qword ptr [rbp+50h],rcx
00000642`80150174 48b88831018042060000 mov rax,64280013188h
00000642`8015017e 8b00 mov eax,dword ptr [rax]
00000642`80150180 85c0 test eax,eax
00000642`80150182 7405 je DebugManagedLeak!DebugManagedLeak.Program.Main(System.String[])+0x69 (00000642`80150189)
00000642`80150184 e817f07aff call mscorwks!JIT_DbgIsJustMyCode (00000642`7f8ff1a0)
00000642`80150189 90 nop
... removed for clarity ...

To get method information
0:000>!Name2EE *!DebugManagedCode0001.Program.Test1

Module: 0000064278854000 (mscorlib.dll)
--------------------------------------
Module: 0000064280012e20 (DebugManagedCode001.exe)
Token: 0x0000000006000001
MethodDesc: 0000064280013568
Name: DebugManagedCode001.Program.Test1()
JITTED Code Address: 0000064280150200

To disassemble IL for the method:
0:000> !dumpil 0000064280013568
ilAddr = 00000000000a2050
IL_0000: nop
IL_0001: ldstr "Test1"
IL_0006: call System.Console::WriteLine
IL_000b: nop
IL_000c: ret

NOTE this displays entire IL for the method.

To set the breakpoint at already JITted method
You can use regular bp command to set breakpoint if method is already JITted and you know the address. See below:
0:000> bp 0000064280150200

To set the breakpoint using source code
You can set the breakpoint or even do trace with source code when the method is already JITted. Open the source file (.open) and press F9. Note again this works for already JITted method only.

No comments: