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)