Recursive !dumpmt – Windbg

In this post I will be demonstrating how we could use CLR internal data-structures to recursively get the methodtable’s of an object and its base classes. The idea behind this is to understand the CLR data structure.

Here is the sample code


using System;
namespace ConsoleApplication
{
 class Program : B
 {
 string test = "cw";
 static void Main(string[] args)
 {
 var p = new Program();
 Console.Read();
 }
 }
 class B : A
 {
 public void TestB()
 {
 }
 }
 class A
 {
 public void TestA()
 {
 }
 }
}

The “Program” object address  is 0x0254bc38 and here  is the output of !dumpobj

0:000> !do 0x0254bc38
Name:        ConsoleApplication.Program
MethodTable: 001c3904
EEClass:     001c1508
Size:        12(0xc) bytes
File:        C:\Users\naveen\Documents\Visual Studio 2010\Projects\ConsoleApplication9\bin\Debug\ConsoleApplication.exe
Fields:
MT    Field   Offset                 Type VT     Attr    Value Name
6335f9ac  4000001        4        System.String  0 instance 0254bc44 test

The method table pointer for the Program class is 001c3904 . Let’s dump the raw memory instead of using !dumpobj

dd 0x0254bc38

0:000> dd 0x0254bc38
0254bc38  001c3904 0254bc44 80000000 6335f9ac
0254bc48  00000002 00770063 00000000 00000000
0254bc58  63367490 00000000 00000000 00000000
0254bc68  00000000 00000000 00000000 6335f5e8
0254bc78  00000000 40010000 63366034 00000003
0254bc88  00000008 00000100 00000000 63366f40
0254bc98  00000000 00000000 00000000 00000000
0254bca8  00000001 0254bc80 00000001 00000000

Now that we can see the MethodTable pointer is the first field we can get the Methods by using


!dumpmt -md poi(0x0254bc38)

0:000> !dumpmt -md poi(0x0254bc38)
EEClass:      001c1508
Module:       001c2e9c
Name:         ConsoleApplication.Program
mdToken:      02000004
File:         C:\Users\naveen\Documents\Visual Studio 2010\Projects\ConsoleApplication9\bin\Debug\ConsoleApplication.exe
BaseSize:        0xc
ComponentSize:   0x0
Slots in VTable: 6
Number of IFaces in IFaceMap: 0
————————————–
MethodDesc Table
Entry MethodDesc      JIT Name
6326a7e0   63044934   PreJIT System.Object.ToString()
6326e2e0   6304493c   PreJIT System.Object.Equals(System.Object)
6326e1f0   6304495c   PreJIT System.Object.GetHashCode()
632f1600   63044970   PreJIT System.Object.Finalize()
002200d0   001c38f0      JIT ConsoleApplication.Program..ctor()
00220070   001c38e4      JIT ConsoleApplication.Program.Main(System.String[])

So next time when we have an object we don’t have to go look for method table pointer address.

The goal is to get every method of class  Program, B, A and System.Object automatically. To get this, lets dump the raw memory of the method table

dd poi(0x0254bc38)

0:000> dd poi(0x0254bc38)
001c3904  00080000 0000000c 00050011 00000004
001c3914  001c3890 001c2e9c 001c3934 001c1508
001c3924  00000000 00000000 001c3854 002200d0
001c3934  00000080 00000000 00000000 00000000
001c3944  00000000 00000000 00000000 00000000
001c3954  00000000 00000000 00000000 00000000
001c3964  00000000 00000000 00000000 00000000
001c3974  00000000 00000000 00000000 00000000

The 10th offset contains the address of its base class method table pointer, So in the above output it is 001c3890 .

Now that we know it is the 10th offset, here is the script to get every method table for a class and its parents. FYI if the 10th offset is 00000000 then it means it is the super class which is System.Object.

r$t0 =poi(0x0254bc38);.while(@$t0) {!dumpmt -md @$t0;.echo *****************;r$t0=poi(@$t0+10)}

And here is the explanation for the above script

  1. r$t0 =poi(0x0254bc38) – Using a pseudo register $t0 to assign the value of mt of the 0x0254bc38
  2. The .while loop will terminate when the value is 0. The  “!dumpmt -md @$t0” will dump the Method Table of the $t0 and the  “r$t0=poi(@$t0+10)” will reset $t0 its parent object method table.

Here is the partial output from the above script with method tables from Program and B

0:000> r$t0 =poi(0x0254bc38);.while(@$t0) {!dumpmt -md @$t0;.echo *****************;r$t0=poi(@$t0+10)}
EEClass:      001c1508
Module:       001c2e9c
Name:         ConsoleApplication.Program
mdToken:      02000004
File:         C:\Users\naveen\Documents\Visual Studio 2010\Projects\ConsoleApplication9\bin\Debug\ConsoleApplication.exe
BaseSize:        0xc
ComponentSize:   0x0
Slots in VTable: 6
Number of IFaces in IFaceMap: 0
————————————–
MethodDesc Table
Entry MethodDesc      JIT Name
6326a7e0   63044934   PreJIT System.Object.ToString()
6326e2e0   6304493c   PreJIT System.Object.Equals(System.Object)
6326e1f0   6304495c   PreJIT System.Object.GetHashCode()
632f1600   63044970   PreJIT System.Object.Finalize()
002200d0   001c38f0      JIT ConsoleApplication.Program..ctor()
00220070   001c38e4      JIT ConsoleApplication.Program.Main(System.String[])
*****************
EEClass:      001c149c
Module:       001c2e9c
Name:         ConsoleApplication.B
mdToken:      02000003
File:         C:\Users\naveen\Documents\Visual Studio 2010\Projects\ConsoleApplication9\bin\Debug\ConsoleApplication.exe
BaseSize:        0xc
ComponentSize:   0x0
Slots in VTable: 6
Number of IFaces in IFaceMap: 0
————————————–
MethodDesc Table
Entry MethodDesc      JIT Name
6326a7e0   63044934   PreJIT System.Object.ToString()
6326e2e0   6304493c   PreJIT System.Object.Equals(System.Object)
6326e1f0   6304495c   PreJIT System.Object.GetHashCode()
632f1600   63044970   PreJIT System.Object.Finalize()
00220120   001c3888      JIT ConsoleApplication.B..ctor()
001cc02d   001c387c     NONE ConsoleApplication.B.TestB()
*****************

One thought on “Recursive !dumpmt – Windbg

  1. Pingback: DotNetShoutout

Leave a comment