NetInverse Developers Blog

April 9, 2009
Category: Debugging — Tags: , , , , — admin @ 10:54 am

Command: !EHInfo

!EHInfo (<MethodDesc address> | <Code address>)

!EHInfo shows the exception handling blocks in a jitted method. For each handler, it shows the type, including code addresses and offsets for the clause block and the handler block. For a TYPED handler, this would be the “try” and “catch” blocks respectively.

Sample output:

!clrstack
OS Thread Id: 0xb10 (2832)
ESP       EIP
0012f3c0 00ff019a IEnumerableTest.Utils.EnumToArray[[IEnumerableTest.Program+RoleType, LinqSelectTest]]()
0012f424 00ff00b9 IEnumerableTest.Program.Main(System.String[])
0012f69c 79e71b4c [GCFrame: 0012f69c] 

!ip2md 00ff00b9
MethodDesc: 00933000

!ehinfo 00933000
MethodDesc: 00933000
Method Name: IEnumerableTest.Program.Main(System.String[])
Class: 00931338
MethodTable: 0093301c
mdToken: 06000002
Module: 00932c5c
IsJitted: yes
CodeAddr: 00ff0070

EHHandler 0: TYPED
Clause: [033bbd2b, 033bbd3c] [8b, 9c]
Handler: [033bbd3c, 033bbd50] [9c, b0]

EHHandler 1: FINALLY
Clause: [033bbd83, 033bbda3] [e3, 103]
Handler: [033bbda3, 033bbdc5] [103, 125]

EHHandler 2: TYPED
Clause: [033bbd7a, 033bbdc5] [da, 125]
Handler: [033bbdc5, 033bbdd6] [125, 136]
Category: Debugging — Tags: , , , , — admin @ 10:40 am

SOS Command: GCInfo

!GCInfo (<MethodDesc address> | <Code address>)

!GCInfo is especially useful for CLR Devs who are trying to determine if there is a bug in the JIT Compiler. It parses the GCEncoding for a method, which is a compressed stream of data indicating when registers or stack locations contain managed objects. It is important to keep track of this information, because if a garbage collection occurs, the collector needs to know where roots are so it can update them with new object pointer values.

Here is sample output where you can see the change in register state. Normally you would print this output out and read it alongside a disassembly of the method. For example, the notation “reg EDI becoming live” at offset 0×11 of the method might correspond to a “mov edi,ecx” statement.

!ip2md 00ff019a
MethodDesc: 00933198

!gcinfo 00933198
entry point 00ff0160
Normal JIT generated code
GC info 131be56000931b7c
Method info block:
    method      size   = 00E3
    prolog      size   = 26
    epilog      size   =  8
    epilog     count   =  1
    epilog      end    = yes
    callee-saved regs  = EDI ESI EBX EBP
    ebp frame          = yes
    fully interruptible= yes
    double align       = no
    arguments size     =  0 DWORDs
    stack frame size   = 20 DWORDs
    untracked count    =  1
    var ptr tab count  =  8
    security check obj = yes
    exception handlers = yes
    edit & continue    = yes
    epilog        at   00DB
    argTabOffset = 1b
81 63 AD D4 B8 |
AA 94 F2 C0 C2 |
45 08 1B       | 

Pointer table:
10             |             [EBP-10H] an untracked  local
3C 2D 81 36    | 002D..00E3  [EBP-3CH] a  pointer
40 05 81 31    | 0032..00E3  [EBP-40H] a  pointer
48 15 0B       | 0047..0052  [EBP-48H] a  pointer
4C 14 28       | 005B..0083  [EBP-4CH] a  pointer
50 0D 1B       | 0068..0083  [EBP-50H] a  pointer
5C 23 1C       | 008B..00A7  [EBP-5CH] a  pointer
54 2C 08       | 00B7..00BF  [EBP-54H] a  pointer
58 18 09       | 00CF..00D8  [EBP-58H] a  pointer
F7 44          | 0044        reg EAX becoming live
F0 4C          | 0050        reg ECX becoming live
02             | 0052        reg EAX becoming dead
46             | 0058        reg EAX becoming live
08             | 0058        reg ECX becoming dead
F2 01          | 0071        reg EAX becoming dead
F1 47          | 0088        reg EAX becoming live
F1 54          | 009C        reg EDX becoming live
4B             | 009F        reg ECX becoming live
05             | 00A4        reg EAX becoming dead
08             | 00A4        reg ECX becoming dead
10             | 00A4        reg EDX becoming dead
4B             | 00A7        reg ECX becoming live
0D             | 00AC        reg ECX becoming dead
4B             | 00AF        reg ECX becoming live
45             | 00B4        reg EAX becoming live
08             | 00B4        reg ECX becoming dead
56             | 00BA        reg EDX becoming live
F0 12          | 00C4        reg EDX becoming dead
4A             | 00C6        reg ECX becoming live
0E             | 00CC        reg ECX becoming dead
F0 04          | 00D8        reg EAX becoming dead
43             | 00DB        reg EAX becoming live
F0 00          | 00E3        reg EAX becoming dead
FF             |           |

This function is important for CLR Devs, but very difficult for anyone else to make sense of it. You would usually come to use it if you suspect a gc heap corruption bug caused by invalid GCEncoding for a particular method.

Category: Debugging — Tags: , , , , — admin @ 10:26 am

SOS Command: EEStack

!EEStack [-short] [-EE]

This command runs !DumpStack on all threads in the process. The -EE option is passed directly to !DumpStack. The -short option tries to narrow down the output to “interesting” threads only, which is defined by

  1. The thread has taken a lock.
  2. The thread has been “hijacked” in order to allow a garbage collection.
  3. The thread is currently in managed code.

See the documentation for !DumpStack for more info.

Example output:

!EEStack -short
---------------------------------------------
Thread 876
---------------------------------------------
Thread 2268
Category: Debugging — Tags: , , , , — admin @ 10:16 am

SOS Command: !Dumpstack

!DumpStack [-EE] [top stack [bottom stack]]
[x86 documentation]

This command provides a verbose stack trace obtained by “scraping.” Therefore the output is very noisy and potentially confusing. The command is good for viewing the complete call stack when “kb” gets confused. For best results, make sure you have valid symbols.

-EE will only show managed functions.

You can also pass a stack range to limit the output. Use the debugger extension !teb to get the top and bottom stack values.

[ia64 and x64 documentation]

Rather than scraping, !DumpStack mimics the debugger’s “K” command. Stackwalking is done very differently on these platforms, so SOS allows the Windows Debugger to unwind the frames, and supplies managed code information where possible. The [top stack [bottom stack]] arguments are ignored, but -EE functions just the same.

Example output:

!dumpstack ee
OS Thread Id: 0x36c (876)
TEB information is not available so a stack size of 0xFFFF is assumed
Current frame: KiFastSystemCallRet
ChildEBP RetAddr  Caller,Callee
00010184 005f0052 005f0052
0001050c 003d0052 003d0052
000107c4 005f0052 005f0052
0001084c 005f0052 005f0052
00010974 003d0052 003d0052
!dumpstack
OS Thread Id: 0x36c (876)
Current frame: KiFastSystemCallRet
ChildEBP RetAddr  Caller,Callee
0012ec40 7c827d0b NtWaitForSingleObject+0xc
0012ec44 77e61d1e WaitForSingleObjectEx+0x88, calling NtWaitForSingleObject
0012ecb4 79e8c639 LogHelp_TerminateOnAssert+0x61
0012ecf8 79e8c56f DllUnregisterServerInternal+0x10523, calling LogHelp_TerminateOnAssert+0x32
0012ed2c 79f90fad CreateApplicationContext+0xab3d, calling InterlockedDecrement
0012ed30 79e8d018 LogHelp_TerminateOnAssert+0xa40, calling
0012ed48 79e8c58e DllUnregisterServerInternal+0x10542, calling DllUnregisterServerInternal+0x104dc
0012ed5c 7a105d65 CoUninitializeCor+0x4474, calling DllUnregisterServerInternal+0x1052b
0012ed84 77e61d1e WaitForSingleObjectEx+0x88, calling NtWaitForSingleObject
0012ed90 77e61d43 WaitForSingleObjectEx+0xad, calling GetTickCount+0x73
0012edac 7c8279bb NtSetEvent+0xc
0012edb0 77e62321 SetEvent+0x10, calling NtSetEvent
0012ede0 7a105eab CoUninitializeCor+0x45ba, calling CoUninitializeCor+0x43d7
0012edf4 7a10624f CoUninitializeCor+0x495e, calling CoUninitializeCor+0x45a2
0012ee08 79f90729 CreateApplicationContext+0xa2b9, calling DllUnregisterServerInternal+0x955
0012ee20 79e79cea , calling
0012ee24 79e79cfd , calling
0012ee40 7a2d140b CreateHistoryReader+0xe857
0012ee4c 7a2e6235 CreateHistoryReader+0x23681, calling CreateHistoryReader+0xe821
0012eeb4 79f38701 CopyPDBs+0x2235, calling CreateHistoryReader+0x2342e
0012eef4 79f77796 CorExitProcess+0x3bd60, calling CorExitProcess+0x3bcfa
0012ef2c 79f5f56b CorExitProcess+0x23b35
0012ef54 79e79cea , calling
0012ef6c 79f5f3a5 CorExitProcess+0x2396f, calling CorExitProcess+0x23aad
0012efa0 79edc2f8 GetMetaDataInternalInterface+0x9e05, calling CorExitProcess+0x238b8
0012efbc 7c858135 RtlIpv4StringToAddressExW+0x167b7, calling RtlReleaseResource
0012efcc 79edc4f5 GetMetaDataInternalInterface+0xa002, calling GetMetaDataInternalInterface+0x9dad
0012eff0 7c828752 RtlRaiseStatus+0xe0
0012f014 7c828723 RtlRaiseStatus+0xb1, calling RtlRaiseStatus+0xba
0012f038 7c8315c2 RtlSubtreePredecessor+0x208, calling RtlRaiseStatus+0x7e
0012f088 7c879f23 RtlpNtMakeTemporaryKey+0x918f, calling _CIpow+0x464
0012f08c 7c85391a RtlIpv4StringToAddressExW+0x11f9c, calling RtlpNtMakeTemporaryKey+0x8f93
0012f098 7c83e7f5 RtlAbsoluteToSelfRelativeSD+0x662, calling _CIpow+0x464
0012f0bc 7c82855e KiUserExceptionDispatcher+0xe, calling RtlSubtreePredecessor+0x17c
0012f3c0 00ff019a (MethodDesc 0x933198 +0x3a IEnumerableTest.Utils.EnumToArray[[IEnumerableTest.Program+RoleType, LinqSelectTest]]()) ====> Exception Code 0 cxr@12f0f4 exr@12a000
0012f26c 7c82a0fc RtlAllocateHeap+0x126, calling _CIpow+0x464
0012f270 79e7a08c , calling RtlAllocateHeap
0012f27c 79e7a0ab , calling
0012f294 79e7c451 DllUnregisterServerInternal+0x405, calling DllUnregisterServerInternal+0x3e4
0012f2a8 79e7a0ab , calling
0012f2ac 79e7a10a , calling
0012f2c0 79e79c98 , calling RtlGetLastWin32Error
0012f2c8 79e7f293 DllUnregisterServerInternal+0x3247, calling
0012f41c 00ff00b9 (MethodDesc 0x933000 +0x49 IEnumerableTest.Program.Main(System.String[])), calling (MethodDesc 0x933198 +0 IEnumerableTest.Utils.EnumToArray[[IEnumerableTest.Program+RoleType, LinqSelectTest]]())
0012f480 79e71b4c
0012f490 79e821f9 DllUnregisterServerInternal+0x61ad, calling
0012f4e4 79e9605b CoUninitializeEE+0x2997, calling CoUninitializeEE+0x297e
0012f510 79e96571 CoUninitializeEE+0x2ead, calling DllUnregisterServerInternal+0x610e
0012f53c 79e96920 CoUninitializeEE+0x325c, calling memcpy
0012f54c 79e964ae CoUninitializeEE+0x2dea, calling
0012f558 79e964be CoUninitializeEE+0x2dfa, calling DllUnregisterServerInternal+0x1f14
0012f5dc 79e7e953 DllUnregisterServerInternal+0x2907, calling DllUnregisterServerInternal+0x2894
0012f5f8 79f28ad4 NGenCreateNGenWorker+0x35f3, calling DllUnregisterServerInternal+0x28ee
0012f648 79e965a4 CoUninitializeEE+0x2ee0, calling CoUninitializeEE+0x2d53
0012f664 79e965c2 CoUninitializeEE+0x2efe, calling CoUninitializeEE+0x2ec1
0012f67c 79eefac5 GetPrivateContextsPerfCounters+0xf546, calling CoUninitializeEE+0x2ee4
0012f790 79e7e953 DllUnregisterServerInternal+0x2907, calling DllUnregisterServerInternal+0x2894
0012f7ac 79f28ad4 NGenCreateNGenWorker+0x35f3, calling DllUnregisterServerInternal+0x28ee
0012f7e0 79eef9e5 GetPrivateContextsPerfCounters+0xf466, calling NGenCreateNGenWorker+0x360c
0012f840 79e8c4ec DllUnregisterServerInternal+0x104a0, calling RtlRestoreLastWin32Error
0012f870 7c83e7f5 RtlAbsoluteToSelfRelativeSD+0x662, calling _CIpow+0x464
0012f874 7c83e5d0 RtlAbsoluteToSelfRelativeSD+0x43d, calling RtlAbsoluteToSelfRelativeSD+0x447
0012f880 7c829f59 RtlFreeHeap+0x142, calling _CIpow+0x464
0012f890 79e8c574 DllUnregisterServerInternal+0x10528, calling
0012f8b0 79e7a1d2 , calling
0012f8b4 79e7a1f1 , calling
0012f8c0 79f90fad CreateApplicationContext+0xab3d, calling InterlockedDecrement
0012f8d0 79e8c574 DllUnregisterServerInternal+0x10528, calling
0012f8d4 79e8c58e DllUnregisterServerInternal+0x10542, calling DllUnregisterServerInternal+0x104dc
0012f8e0 79e7d9f5 DllUnregisterServerInternal+0x19a9, calling DllUnregisterServerInternal+0x983
0012f8f4 7a105d74 CoUninitializeCor+0x4483, calling DllUnregisterServerInternal+0x1993
0012f8f8 79e7c85c DllUnregisterServerInternal+0x810, calling
0012f8fc 7a105da9 CoUninitializeCor+0x44b8, calling DllUnregisterServerInternal+0x806
0012f910 79e79cea , calling
0012f914 7c827d0b NtWaitForSingleObject+0xc
0012f918 77e61d1e WaitForSingleObjectEx+0x88, calling NtWaitForSingleObject
0012f954 7c829f59 RtlFreeHeap+0x142, calling _CIpow+0x464
0012f958 79e7a1b6 , calling RtlFreeHeap
0012f964 79e7a1d2 , calling
0012f97c 79e7c7dd DllUnregisterServerInternal+0x791, calling
0012f98c 79e7a1d2 , calling
0012f990 79e7a1f1 , calling
0012f9a4 79e79c98 , calling RtlGetLastWin32Error
0012f9ac 79e7a18b , calling
0012f9d4 79e7a18b , calling
0012f9d8 79e81d94 DllUnregisterServerInternal+0x5d48, calling
0012f9dc 79e81d9a DllUnregisterServerInternal+0x5d4e, calling
0012f9fc 79e81d9a DllUnregisterServerInternal+0x5d4e, calling
0012fa20 79e81d9a DllUnregisterServerInternal+0x5d4e, calling
0012fa24 79e82279 DllUnregisterServerInternal+0x622d, calling
0012fa48 79eeff35 GetPrivateContextsPerfCounters+0xf9b6, calling GetPrivateContextsPerfCounters+0xf3c2
0012fb1c 79ebdc2f StrongNameFreeBuffer+0x1a87, calling GetPrivateContextsPerfCounters+0xe46c
0012fb24 79e7f1e8 DllUnregisterServerInternal+0x319c, calling
0012fb28 79e975ce CoUninitializeEE+0x3f0a, calling DllUnregisterServerInternal+0x3192
0012fb44 79ebdc38 StrongNameFreeBuffer+0x1a90, calling
0012fb48 79ebdc56 StrongNameFreeBuffer+0x1aae, calling
0012fb78 7c83e7f5 RtlAbsoluteToSelfRelativeSD+0x662, calling _CIpow+0x464
0012fb80 79e8233b DllUnregisterServerInternal+0x62ef, calling
0012fb9c 7c829f59 RtlFreeHeap+0x142, calling _CIpow+0x464
0012fbac 7c827d0b NtWaitForSingleObject+0xc
0012fbb0 77e61d1e WaitForSingleObjectEx+0x88, calling NtWaitForSingleObject
0012fbbc 77e61d43 WaitForSingleObjectEx+0xad, calling GetTickCount+0x73
0012fbf0 79e8c4c7 DllUnregisterServerInternal+0x1047b, calling RtlRestoreLastWin32Error
0012fbf4 79e8c4ce DllUnregisterServerInternal+0x10482, calling
0012fc20 79e8c4ec DllUnregisterServerInternal+0x104a0, calling RtlRestoreLastWin32Error
0012fc2c 79e8c650 LogHelp_TerminateOnAssert+0x78, calling
0012fc4c 7c82a0fc RtlAllocateHeap+0x126, calling _CIpow+0x464
0012fc60 79e8c650 LogHelp_TerminateOnAssert+0x78, calling
0012fc64 79e8c56f DllUnregisterServerInternal+0x10523, calling LogHelp_TerminateOnAssert+0x32
0012fc70 79e8c574 DllUnregisterServerInternal+0x10528, calling
0012fca0 79f90fad CreateApplicationContext+0xab3d, calling InterlockedDecrement
0012fcb0 79e8c574 DllUnregisterServerInternal+0x10528, calling
0012fcb4 79e8c58e DllUnregisterServerInternal+0x10542, calling DllUnregisterServerInternal+0x104dc
0012fcc0 79e7d9f5 DllUnregisterServerInternal+0x19a9, calling DllUnregisterServerInternal+0x983
0012fcd4 7a105d74 CoUninitializeCor+0x4483, calling DllUnregisterServerInternal+0x1993
0012fcd8 79e7c85c DllUnregisterServerInternal+0x810, calling
0012fcdc 7a105da9 CoUninitializeCor+0x44b8, calling DllUnregisterServerInternal+0x806
0012fcf0 79e79cea , calling
0012fda8 79eef719 GetPrivateContextsPerfCounters+0xf19a, calling
0012fdac 7a2d2f55 CreateHistoryReader+0x103a1, calling
0012fdc8 79e8233b DllUnregisterServerInternal+0x62ef, calling
0012fdcc 79e883cb DllUnregisterServerInternal+0xc37f, calling DllUnregisterServerInternal+0x62be
0012fde0 79e81ee6 DllUnregisterServerInternal+0x5e9a, calling DllUnregisterServerInternal+0x1d57
0012fdec 79e8840b DllUnregisterServerInternal+0xc3bf, calling DllUnregisterServerInternal+0x5e8d
0012fdf0 79e8841f DllUnregisterServerInternal+0xc3d3, calling
0012fdf4 79e98317 CoUninitializeEE+0x4c53, calling
0012fe14 79e7d9f5 DllUnregisterServerInternal+0x19a9, calling DllUnregisterServerInternal+0x983
0012fe28 79efbeed ClrCreateManagedInstance+0x7bdf, calling DllUnregisterServerInternal+0x1993
0012fe2c 79e7c85c DllUnregisterServerInternal+0x810, calling
0012fe30 79efbf24 ClrCreateManagedInstance+0x7c16, calling DllUnregisterServerInternal+0x806
0012fe60 79f07c2e GetIdentityAuthority+0x22e8, calling GetPrivateContextsPerfCounters+0xe393
0012fe70 79f07c45 GetIdentityAuthority+0x22ff, calling
0012fee8 79efbf24 ClrCreateManagedInstance+0x7c16, calling DllUnregisterServerInternal+0x806
0012feec 79ef94d4 ClrCreateManagedInstance+0x51c6, calling ClrCreateManagedInstance+0x756b
0012fef0 79ef94f3 ClrCreateManagedInstance+0x51e5, calling
0012ff18 79ef011f _CorExeMain+0x168, calling GetPrivateContextsPerfCounters+0xf5a0
0012ff68 79ef004f _CorExeMain+0x98, calling _CorExeMain+0x11f
0012ffb0 79007c24 _CorExeMain+0x34
0012ffc0 77e6f23b ProcessIdToSessionId+0x209
Category: Debugging — Tags: , , , , — admin @ 9:58 am

Command: !U

!U [-gcinfo] [-ehinfo] <MethodDesc address> | <Code address>

Presents an annotated disassembly of a managed method when given a MethodDesc pointer for the method, or a code address within the method body. Unlike the debugger “U” function, the entire method from start to finish is printed, with annotations that convert metadata tokens to names.

If you pass the -gcinfo flag, you’ll get inline display of the GCInfo for the method. You can also obtain this information with the !GCInfo command. If you pass the -ehinfo flag, you’ll get inline display of exception info for the method. (Beginning and end of try/finally/catch handlers, etc.). You can also obtain this information with the !EHInfo command.

IsJitted: yes,means it has been compiled; and you can use !U to inspect the native code.

Example output:

!clrstack
OS Thread Id: 0x36c (876)
ESP       EIP
0012f3c0 00ff019a IEnumerableTest.Utils.EnumToArray[[IEnumerableTest.Program+RoleType, LinqSelectTest]]()
0012f424 00ff00b9 IEnumerableTest.Program.Main(System.String[])
0012f69c 79e71b4c [GCFrame: 0012f69c] 

!ip2md 00ff019a
MethodDesc: 00933198
Method Name: IEnumerableTest.Utils.EnumToArray[[IEnumerableTest.Program+RoleType, LinqSelectTest]]()
Class: 0093140c
MethodTable: 0093313c
mdToken: 06000001
Module: 00932c5c
IsJitted: yes
CodeAddr: 00ff0160

!u 00933198
Normal JIT generated code
IEnumerableTest.Utils.EnumToArray[[IEnumerableTest.Program+RoleType, LinqSelectTest]]()
Begin 00ff0160, size e3
00FF0160 55               push        ebp
00FF0161 8BEC             mov         ebp,esp
00FF0163 57               push        edi
00FF0164 56               push        esi
00FF0165 53               push        ebx
00FF0166 83EC50           sub         esp,50h
00FF0169 8D7DC8           lea         edi,[ebp-38h]
00FF016C B90B000000       mov         ecx,0Bh
00FF0171 33C0             xor         eax,eax
00FF0173 F3AB             rep stos    dword ptr es:[edi]
00FF0175 33C0             xor         eax,eax
00FF0177 8945E4           mov         dword ptr [ebp-1Ch],eax
00FF017A 833D142E930000   cmp         dword ptr ds:[00932E14h],0
00FF0181 7405             je          00FF0188
00FF0183 E8C1A50D79       call        7A0CA749 (JitHelp: CORINFO_HELP_DBG_IS_JUST_MY_CODE)
00FF0188 33D2             xor         edx,edx
00FF018A 8955C4           mov         dword ptr [ebp-3Ch],edx
00FF018D 33D2             xor         edx,edx
00FF018F 8955C0           mov         dword ptr [ebp-40h],edx
00FF0192 C745BC00000000   mov         dword ptr [ebp-44h],0
00FF0199 90               nop
00FF019A B96C309300       mov         ecx,93306Ch (MT: IEnumerableTest.Program+RoleType)
00FF019F E816D9E878       call        79E7DABA (System.Type.GetTypeFromHandle(System.RuntimeTypeHandle), mdToken: 06000d56)
00FF01A4 8945B8           mov         dword ptr [ebp-48h],eax
00FF01A7 8B45B8           mov         eax,dword ptr [ebp-48h]
00FF01AA 8945C4           mov         dword ptr [ebp-3Ch],eax
00FF01AD 8B4DC4           mov         ecx,dword ptr [ebp-3Ch]
00FF01B0 8B01             mov         eax,dword ptr [ecx]
00FF01B2 FF90C8000000     call        dword ptr [eax+000000C8h]
00FF01B8 8945B4           mov         dword ptr [ebp-4Ch],eax
00FF01BB B9E8063379       mov         ecx,793306E8h (MT: System.Enum)
00FF01C0 E8F5D8E878       call        79E7DABA (System.Type.GetTypeFromHandle(System.RuntimeTypeHandle), mdToken: 06000d56)
00FF01C5 8945B0           mov         dword ptr [ebp-50h],eax
00FF01C8 8B45B4           mov         eax,dword ptr [ebp-4Ch]
00FF01CB 3B45B0           cmp         eax,dword ptr [ebp-50h]
00FF01CE 0F94C0           sete        al
00FF01D1 0FB6C0           movzx       eax,al
00FF01D4 8945BC           mov         dword ptr [ebp-44h],eax
00FF01D7 837DBC00         cmp         dword ptr [ebp-44h],0
00FF01DB 752F             jne         00FF020C
00FF01DD 90               nop
00FF01DE B96C723179       mov         ecx,7931726Ch (MT: System.ArgumentException)
00FF01E3 E8341E93FF       call        0092201C (JitHelp: CORINFO_HELP_NEWSFAST)
00FF01E8 8945A4           mov         dword ptr [ebp-5Ch],eax
00FF01EB BA5C2C9300       mov         edx,932C5Ch
00FF01F0 B901000070       mov         ecx,70000001h
00FF01F5 E80045FC78       call        79FB46FA (JitHelp: CORINFO_HELP_STRCNS)
00FF01FA 8BD0             mov         edx,eax
00FF01FC 8B4DA4           mov         ecx,dword ptr [ebp-5Ch]
00FF01FF E82C882B78       call        792A8A30 (System.ArgumentException..ctor(System.String), mdToken: 0600063b)
00FF0204 8B4DA4           mov         ecx,dword ptr [ebp-5Ch]
00FF0207 E82346FC78       call        79FB482F (JitHelp: CORINFO_HELP_THROW)
00FF020C 8B4DC4           mov         ecx,dword ptr [ebp-3Ch]
00FF020F E85C8A2878       call        79278C70 (System.Enum.GetValues(System.Type), mdToken: 0600010b)
00FF0214 8945AC           mov         dword ptr [ebp-54h],eax
00FF0217 8B55AC           mov         edx,dword ptr [ebp-54h]
00FF021A B99C419300       mov         ecx,93419Ch (MT: System.Collections.Generic.IEnumerable`1[[IEnumerableTest.Program+RoleType, LinqSelectTest]])
00FF021F E8CC2CE878       call        79E72EF0 (JitHelp: CORINFO_HELP_ISINSTANCEOFINTERFACE)
00FF0224 8BC8             mov         ecx,eax
00FF0226 FF1518429300     call        dword ptr ds:[00934218h] (System.Linq.Enumerable.ToArray[[IEnumerableTest.Program+RoleType, LinqSelectTest]](System.Collections.Generic.IEnumerable`1), mdToken: 06000574)
00FF022C 8945A8           mov         dword ptr [ebp-58h],eax
00FF022F 8B45A8           mov         eax,dword ptr [ebp-58h]
00FF0232 8945C0           mov         dword ptr [ebp-40h],eax
00FF0235 90               nop
00FF0236 EB00             jmp         00FF0238
00FF0238 8B45C0           mov         eax,dword ptr [ebp-40h]
00FF023B 8D65F4           lea         esp,[ebp-0Ch]
00FF023E 5B               pop         ebx
00FF023F 5E               pop         esi
00FF0240 5F               pop         edi
00FF0241 5D               pop         ebp
00FF0242 C3               ret
Category: Debugging — Tags: , , , , — admin @ 9:34 am

SOS Command: !Threads

Enable unmanaged debugging in your project properties, run your code to a break point. Press Ctrl + Alt + I.
Type following commands.

.load C:windowsMicrosoft.NETFrameworkv2.0.50727sos.dll
!Help !Threads

!Threads [-live] [-special] 

-live:     optional. Only print threads associated with a live thread.

-special:  optional. With this switch, the command will display all the special
           threads created by CLR. Those threads might not be managed threads
           so they might not be shown in the first part of the command's
           output. Example of special threads include: GC threads (in
           concurrent GC and server GC), Debugger helper threads, Finalizer
           threads, AppDomain Unload threads, and Threadpool timer threads.

!Threads lists all the mananaged threads in the process.

Each thread has many attributes, many of which can be ignored. The important ones are discussed below:

There are three ID columns:

  1. The debugger shorthand ID (In fiber mode, if the thread is a fiber which is switched out by the host, this column will be shown as “<<<<”)
  2. The CLR Thread ID
  3. The OS thread ID.

If PreEmptiveGC is enabled for a thread, then a garbage collection can occur while that thread is running. For example, if you break in while a managed thread is making a PInvoke call to a Win32 function, that thread will be in PreEmptive GC mode.

The Domain column indicates what AppDomain the thread is currently executing in. You can pass this value to !DumpDomain to find out more.

The APT column gives the COM apartment mode.

Exception will list the last thrown exception (if any) for the thread. More details can be obtained by passing the pointer value to !PrintException. If you get the notation “(nested exceptions)”, you can get details on those exceptions by switching to the thread in question, and running “!PrintException -nested”.

Sample output:

!threads
ThreadCount: 2
UnstartedThread: 0
BackgroundThread: 1
PendingThread: 0
DeadThread: 0
Hosted Runtime: no
                                      PreEmptive   GC Alloc           Lock
       ID OSID ThreadOBJ    State     GC       Context       Domain   Count APT Exception
 876    1  36c 001971b0     8a028 Enabled  00000000:00000000 0015d338     0 MTA
2268    2  8dc 001a38e8      b228 Enabled  00000000:00000000 0015d338     0 MTA (Finalizer)
April 8, 2009
Category: Debugging — Tags: , , , , — admin @ 10:06 pm

SOS Command: !IP2MD

Enable unmanaged debugging in your project properties, run your code to a break point. Press Ctrl + Alt + I.
Type following commands.

.load C:windowsMicrosoft.NETFrameworkv2.0.50727sos.dll
!Help !IP2MD

!IP2MD <Code address>

Given an address in managed JITTED code, IP2MD attempts to find the MethodDesc associated with it. For example, this output from !clrstack:

!clrstack
OS Thread Id: 0xa3c (2620)
ESP       EIP
0012f3c0 00ff019a IEnumerableTest.Utils.EnumToArray[[IEnumerableTest.Program+RoleType, LinqSelectTest]]()
0012f424 00ff00b9 IEnumerableTest.Program.Main(System.String[])
0012f69c 79e71b4c [GCFrame: 0012f69c] 

!ip2md 00ff019a
MethodDesc: 00933198
Method Name: IEnumerableTest.Utils.EnumToArray[[IEnumerableTest.Program+RoleType, LinqSelectTest]]()
Class: 0093140c
MethodTable: 0093313c
mdToken: 06000001
Module: 00932c5c
IsJitted: yes
CodeAddr: 00ff0160

We have taken a return address into Mainy.Main, and discovered information about that method. You could run !U, !DumpMT, !DumpClass, !DumpMD, or !DumpModule on the fields listed to learn more.

!DumpClass 0093140c
Class Name: IEnumerableTest.Utils
mdToken: 02000002 (C:projectsNetInversebinDebugIEnumerableTest.exe)
Parent Class: 790c3ef0
Module: 00932c5c
Method Table: 0093313c
Vtable Slots: 4
Total Method Slots: 5
Class Attributes: 100181  Abstract,
NumInstanceFields: 0
NumStaticFields: 0
March 29, 2009
Category: Debugging — Tags: , , , — admin @ 12:28 am

Using SOS in Visual Studio

First, you need to right mouse click on the project in solution explorer, choose properties, switch to the Debug tab, and make sure “Enable Unmanaged Code Debugging” is selected.

Second, open the Immediate window (Debug->Windows->Immediate). You can simply press shortcut keys Ctrl + Alt + I. Then type following command in the Immediate window.

.load C:\windows\Microsoft.NET\Framework\v2.0.50727\sos.dll

Third, Type “!help” for help.

!help
-------------------------------------------------------------------------------
SOS is a debugger extension DLL designed to aid in the debugging of managed
programs. Functions are listed by category, then roughly in order of
importance. Shortcut names for popular functions are listed in parenthesis.
Type "!help <functionname>" for detailed info on that function.

Object Inspection              Examining code and stacks
-----------------------------  -----------------------------
DumpObj (do)                   Threads
DumpArray (da)                 CLRStack
DumpStackObjects (dso)         IP2MD
DumpHeap                       U
DumpVC                         DumpStack
GCRoot                         EEStack
ObjSize                        GCInfo
FinalizeQueue                  EHInfo
PrintException (pe)            COMState
TraverseHeap                   BPMD

Examining CLR data structures  Diagnostic Utilities
-----------------------------  -----------------------------
DumpDomain                     VerifyHeap
EEHeap                         DumpLog
Name2EE                        FindAppDomain
SyncBlk                        SaveModule
DumpMT                         GCHandles
DumpClass                      GCHandleLeaks
DumpMD                         VMMap
Token2EE                       VMStat
EEVersion                      ProcInfo
DumpModule                     StopOnException (soe)
ThreadPool                     MinidumpMode
DumpAssembly
DumpMethodSig                  Other
DumpRuntimeTypes               -----------------------------
DumpSig                        FAQ
RCWCleanupList
DumpIL

Some common commands are listed below:

!CLRStack
!ip2md [EIP Address]
!DumpIL [MethodDesc Address]
!help [Command]

Command: !CLRStack

!CLRStack [-a] [-l] [-p]

CLRStack attempts to provide a true stack trace for managed code only. It is handy for clean, simple traces when debugging straightforward managed programs. The -p parameter will show arguments to the managed function. The -l parameter can be used to show information on local variables in a frame. SOS can’t retrieve local names at this time, so the output for locals is in the format = . The -a (all) parameter is a short-cut for -l and -p combined.

When you see methods with the name “[Frame:...", that indicates a transition between managed and umanaged code. You could run !IP2MD on the return addresses in the call stack to get more information on each managed method.

On IA64 and x64 platforms, Transition Frames are not displayed at this time. Especially on IA64, there is heavy optimization of parameters and locals. You can request the JIT compiler to not optimize functions in the managed app by creating a file myapp.ini (if your program is myapp.exe) in the same directory.

Put the following lines in myapp.ini and re-run:

[.NET Framework Debugging Control]
GenerateTrackingInfo=1
AllowOptimize=0
« Newer Posts

©2009 NetInverse. All rights reserved. Powered by WordPress