MANAGED DEBUGGING with WINDBG. Thread Stacks. Part 1

Hi all,

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

THREAD STACKS. Part 1

· We can take a look to the objects in the stack:

The CLR is stack-based. All references to objects are in the stack, but objects themselves are in the managed heap. We also have to take into account that Structs that we instantiate go to the stack and Classes weinstantiate go to the managed heap.

In any thread we can see a list of references to objects that are still on the thread’s stack (remember we have one stack per thread ;-):

0:000> !DumpStackObjects

...

0:000> !dso

OS Thread Id: 0x1334 (0)

ESP/REG Object Name

0018e710 01b3ed34 System.IndexOutOfRangeException

0018e758 01b3ed34 System.IndexOutOfRangeException

0018e79c 01aef338 WindowsApplication1.Form1

0018e7a0 01b3ed1c System.Int32[]

0018e7a4 01b3cf94 System.Windows.Forms.MouseEventArgs

0018e7ac 01aef338 WindowsApplication1.Form1

0018e7b4 01b3ed1c System.Int32[]

0018e7bc 01b3cf94 System.Windows.Forms.MouseEventArgs

0018e838 01b3ed1c System.Int32[]

0018e84c 01aef338 WindowsApplication1.Form1

0018e860 01af0398 System.Windows.Forms.Button

...

Note that the objects at the top of the stack correspond to the objects used by the methods at the top of the call stack:

0:000> kpL

ChildEBP RetAddr

0018e6f0 79f071ac KERNEL32!RaiseException(unsigned long dwExceptionCode = 0xe0434f4d, unsigned long dwExceptionFlags = 1, unsigned long nNumberOfArguments = 1, unsigned long * lpArguments = 0x0018e728)+0x58

0018e750 79f9293a mscorwks!RaiseTheExceptionInternalOnly(class Object * throwable = 0x01b3ed34, int rethrow = 0, int fForStackOverflow = 0)+0x2a8

0018e788 7a129a34 mscorwks!UnwindAndContinueRethrowHelperAfterCatch(class Frame * pEntryFrame = 0x0018e7e0, class Exception * pException = 0x003e65a8)+0x70

0018e828 002c1aad mscorwks!JIT_RngChkFail(void)+0xb0

0018e870 002c19fe WindowsApplication1!WindowsApplication1.Form1.PlayWithArray(<HRESULT 0x80004001>)+0x55

...

0:000> !CLRStack -a

OS Thread Id: 0x1334 (0)

ESP EIP

0018e7e0 761db09e [HelperMethodFrame: 0018e7e0]

0018e830 002c1aad WindowsApplication1.Form1.PlayWithArray(Int32[] )

PARAMETERS:

this = 0x01aef338

array = 0x01b3ed1c

LOCALS:

0x0018e848 = 0x00000000

0x0018e844 = 0x00000006

0x0018e840 = 0x00000003

0x0018e834 = 0x00000000

0x0018e83c = 0x00000003

0018e878 002c19fe WindowsApplication1.Form1.Button6_Click(System.Object, System.EventArgs)

PARAMETERS:

this = 0x01aef338

sender = 0x01af0398

e = 0x01b3cf94

LOCALS:

0x0018e87c = 0x00000000

<CLR reg> = 0x01b3ed1c

<CLR reg> = 0x00000000

...

· We can inspect the objects:

With a reference to an object we can inspect the object itself:

0:000> !DumpObj 0x01aef338

...

0:000> !do 0x01aef338

Name: WindowsApplication1.Form1

MethodTable: 001c6ecc

EEClass: 002d0a30

Size: 352(0x160) bytes

(C:\__WORKSHOP\Demos\BuggyNETApp\bin\Debug\WindowsApplication1.exe)

Fields:

MT Field Offset Type VT Attr Value Name

...

7ae75fa8 40010f2 2b8 System.Drawing.Font 0 static 01af1d18 defaultFont

...

7ae75b24 40011e0 80 ...Drawing.Rectangle 1 instance 01aef3b8 displayRect

...

7b47f3dc 4000011 154 ...dows.Forms.Button 0 instance 01af0398 _Button6

7912d7c0 4000013 158 System.Int32[] 0 instance 01b3ed1c myarray

...

0:000> !do 01af1d18

Name: System.Drawing.Font

...

Fields:

MT Field Offset Type VT Attr Value Name

...

790fd8c4 4000641 c System.String 0 instance 01af1544 systemFontName

...

0:000> !do -nofields 01af1544

Name: System.String

MethodTable: 790fd8c4

EEClass: 790fd824

Size: 40(0x28) bytes

(C:\Windows\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)

String: DefaultFont

0:000> !do 01aef3b8

<Note: this object has an invalid CLASS field>

Invalid object

0:000> !DumpVC 7ae75b24 01aef3b8

Name: System.Drawing.Rectangle

MethodTable 7ae75b24

EEClass: 7ae75aac

Size: 24(0x18) bytes

(C:\Windows\assembly\GAC_MSIL\System.Drawing\2.0.0.0__b03f5f7f11d50a3a\System.Drawing.dll)

Fields:

MT Field Offset Type VT Attr Value Name

79102290 4000462 0 System.Int32 0 instance 0 x

79102290 4000463 4 System.Int32 0 instance 0 y

...

0:000> !DumpArray 01b3ed1c

...

0:000> !da 01b3ed1c

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

Note that the column VT contains the value 1 if the field is a valuetype structure, and 0 if the field contains a pointer to another object.

If we only need to see the static fields of the object, we can inspect the EEClass of the class (representation of a class created before any method invocations are made on it) of the object:

0:000> !DumpClass 002d0a30

Class Name: WindowsApplication1.Form1

mdToken: 02000008 (C:\__WORKSHOP\Demos\BuggyNETApp\bin\Debug\WindowsApplication1.exe)

Parent Class: 7b47b140

Module: 001c2c3c

Method Table: 001c6ecc

Vtable Slots: 180

Total Method Slots: 18f

Class Attributes: 100001

NumInstanceFields: 47

NumStaticFields: 2

MT Field Offset Type VT Attr Value Name

...

7ae75fa8 40010f2 2b8 System.Drawing.Font 0 static 01af1d18 defaultFont

...

7ae75b24 40011e0 80 ...Drawing.Rectangle 1 instance displayRect

...

7a7559dc 40011de 308 ...stics.TraceSwitch 0 static 00000000 AutoScrolling

...

7b47f3dc 4000011 154 ...dows.Forms.Button 0 instance _Button6

7912d7c0 4000013 158 System.Int32[] 0 instance myarray

...

But if we are looking for a way to display a static field of a class (and we don't have an instance of the class, so !DumpObj won't help us), we can inspect the EEClass of the class itself:

0:000> !Name2EE WindowsApplication1 WindowsApplication1.Form1

Module: 001c2c3c (WindowsApplication1.exe)

Token: 0x02000008

MethodTable: 001c6ecc

EEClass: 002d0a30

Name: WindowsApplication1.Form1

0:000> !DumpClass 002d0a30

Class Name: WindowsApplication1.Form1

...

Next post: MANAGED DEBUGGING with WINDBG. Thread Stacks. Part 2.

Index: MANAGED DEBUGGING with WINDBG. Introduction and Index.

Regards,

Alex (Alejandro Campos Magencio)