Hi all,

This post is a continuation of MANAGED DEBUGGING with WINDBG. Call Stacks. Part 2.

 

CALL STACKS. Part 3

 

·         Let's review previous commands:        

Let’s see a sample where the debugger broke when “PlayWithArray” raised an exception. We can use the return address of the function it called, “mscorwks!JIT_RngChkFail”, to see where in “PlayWithArray” we were when the exception happened:

0:000> kL

ChildEBP RetAddr 

0027e600 79f071ac KERNEL32!RaiseException+0x58

0027e660 79f9293a mscorwks!RaiseTheExceptionInternalOnly+0x2a8

0027e698 7a129a34 mscorwks!UnwindAndContinueRethrowHelperAfterCatch+0x70

0027e738 00371aad mscorwks!JIT_RngChkFail+0xb0

0027e780 003719fe WindowsApplication1!WindowsApplication1.Form1.PlayWithArray(Int32[])+0x55

...

0:000> !u 00371aad

Normal JIT generated code

WindowsApplication1.Form1.PlayWithArray(Int32[])

Begin 00371a58, size c0

00371a58 55              push    ebp

...

00371aa0 8b4dc8          mov     ecx,dword ptr [ebp-38h]

00371aa3 3b5104          cmp     edx,dword ptr [ecx+4]

00371aa6 7205            jb      WindowsApplication1!WindowsApplication1.Form1.PlayWithArray(Int32[])+0x55 (00371aad)

00371aa8 e8d67edb79      call    mscorwks!JIT_RngChkFail (7a129983)

>>> 00371aad 03449108        add     eax,dword ptr [ecx+edx*4+8]

00371ab1 7105            jno     WindowsApplication1!WindowsApplication1.Form1.PlayWithArray(Int32[])+0x60 (00371ab8)

00371ab3 e8837fdb79      call    mscorwks!JIT_Overflow (7a129a3b)

...

00371b16 5d              pop     ebp

00371b17 c3              ret 

0:000> u 00371aa8

WindowsApplication1!WindowsApplication1.Form1.PlayWithArray(Int32[])+0x50 [C:\__WORKSHOP\Demos\BuggyNETApp\Form1.vb @ 135]:

...

 

Note how we used the unmanaged version of this command, u, to find out the source code line.

That line corresponds to the following VB.NET statement in “PlayWithArray”:

result += array(i)

 

It seems we got some exception when accessing the array... Can we tell why? Let’s give it a try:

0:000> !CLRStack -a

OS Thread Id: 0x1f3c (0)

ESP       EIP    

0027e6f0 77a1b09e [HelperMethodFrame: 0027e6f0]

0027e740 00371aad WindowsApplication1.Form1.PlayWithArray(Int32[])

    PARAMETERS:

        this = 0x0192f338

        array = 0x01983d38

    LOCALS:

        0x0027e758 = 0x00000000

        0x0027e754 = 0x00000006

        0x0027e750 = 0x00000003

        0x0027e744 = 0x00000000

        0x0027e74c = 0x00000003

...

0:000> !da 0x01983d38

Name: System.Int32[]

MethodTable: 7912d7c0

EEClass: 7912d878

Size: 24(0x18) bytes

Array: Rank 1, Number of elements 3, Type Int32

Element Methodtable: 79102290

[0] 00000001

[1] 00000002

[2] 00000003

 

It seems we tried to access the element at index 3 of the array (the 4th element), but the array only has 3 elements.


How do I know which local corresponds to “i”? ILDASM may help here, because the locals it shows are in the same order as in !CLRStack. In our case, “i” is in the 3rd position:

// Code size       49 (0x31)

.maxstack  3

.locals init ([0] int32 PlayWithArray,

         [1] int32 result,

         [2] int32 i,

         [3] class [mscorlib]System.Exception ex,

         [4] int32 VB$CG$t_i4$S0)

 

·         We can use registers to check parameters of a method in the call stack:

When we are at the beginning of a function, we must take into consideration that JIT compiler uses _fastcall calling convention. This means that the first two parameters will be passed in the ecx and edx registers. Ecx is used to hold the “this” pointer. We can use those registers to inspect the parameters:

0:000> g

Breakpoint 0 hit

eax=001a6e28 ebx=01ad8880 ecx=01a9f338 edx=01ada608 esi=01ada608 edi=01a9f338

eip=008f1a58 esp=002fe8a4 ebp=00000000 iopl=0         nv up ei ng nz na pe cy

cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000287

WindowsApplication1!WindowsApplication1.Form1.PlayWithArray(Int32[]):

008f1a58 55              push    ebp

0:000> !CLRStack -p

OS Thread Id: 0x17fc (0)

ESP       EIP    

002fe8a4 008f1a58 WindowsApplication1.Form1.PlayWithArray(Int32[])

    PARAMETERS:

        this = 0x01a9f338

        array = 0x01ada608

 

...

 

002ff044 79e7c74b [GCFrame: 002ff044]

0:000> !do @ecx

Name: WindowsApplication1.Form1

...

0:000> !da @edx

Name: System.Int32[]

...

Array: Rank 1, Number of elements 3, Type Int32

...

 

Note that later in the function, esi is typically used to hold the “this” pointer (gotten from ecx).

 

 

Next post: MANAGED DEBUGGING with WINDBG. Threads. Part 1.

Index: MANAGED DEBUGGING with WINDBG. Introduction and Index.

 

Regards,

 

Alex (Alejandro Campos Magencio)