SOS Internals – DumpModule Command

Typical output for the DumpModule as follows :

0:000> !dumpmodule -mt 00c82c5c
Name: D:\Projects\CLRTest\bin\Debug\CLRTest.exe
Attributes: PEFile
Assembly: 00194510
LoaderHeap: 00000000
TypeDefToMethodTableMap: 00c800c0
TypeRefToMethodTableMap: 00c800cc
MethodDefToDescMap: 00c80118
FieldDefToDescMap: 00c80124
MemberRefToDescMap: 00c80128
FileReferencesMap: 00c80174
AssemblyReferencesMap: 00c80178
MetaData start address: 00402068 (1432 bytes)

Types defined in this module

MT    TypeDef Name
00c83004 0x02000002 CLRTest.Program

Types referenced in this module

MT    TypeRef Name
7933061c 0x01000001 System.Object

The reference address of this command is obtained from the DumpDomain command, as explained from my previous article, and it is the module field at each list of assemblies that is attached to the domain :

Inside the DumpDomain function, it tries to execute this statements :

DacpModuleData module;

If the status returns error, the DumpModule function exits with the error message :

“Fail to fill Module x”

Where x denotes the supplied address.

As for the Request method inside DacpModuleData structure :

(PBYTE) &addr, sizeof(*this), (PBYTE)this);

For the above request type, the actual structure that is accessed to assigned each fields of DacpModuleData is accomplished with this function :

RequestModuleData(IN ULONG32 inBufferSize,IN BYTE* inBuffer,
IN ULONG32, outBufferSize,OUT BYTE* outBuffer)

And the actual structure that is used to retrieve the module information data is :

Module* pModule = PTR_Module(TO_TADDR(addr));

Here is some code statements used to retrieve some of those fields :

ModuleData->TypeDefToMethodTableMap = HOST_CDADDR(pModule->m_TypeDefToMethodTableMap.pTable);
ModuleData->TypeRefToMethodTableMap = HOST_CDADDR(pModule->m_TypeRefToMethodTableMap.pTable);
ModuleData->MethodDefToDescMap = HOST_CDADDR(pModule->m_MethodDefToDescMap.pTable);
ModuleData->FieldDefToDescMap = HOST_CDADDR(pModule->m_FieldDefToDescMap.pTable);
ModuleData->MemberRefToDescMap = HOST_CDADDR(pModule->m_MemberRefToDescMap.pTable);
ModuleData->FileReferencesMap = HOST_CDADDR(pModule->m_FileReferencesMap.pTable);

As of .NET v2.0, there is a special option -mt that will causes this command to dump all type definitions and type references for the specified module. This is accomplished by calling the DoMapTraverse method inside DacpModuleData :

ModuleMapTraverse,(LPVOID) mdTypeDefNil);

Inside this function is just another request to the CLR’s Internal Data Structure :

sizeof(DacpModuleMapTraverseArgs), (BYTE *)&args, 0, NULL);

Which, based on request type, calls to :

status = RequestModuleMapTraverse(inBufferSize, inBuffer,outBufferSize, outBuffer);

Basically, this function perform the iteration to the LookupMap structure, especially the pTable field, based on given index. Please note that CLR maintains separate LookupMap structures for corresponding TableMap types.

For example, there is LookupTable for m_TypeDefToMethodTableMap.pTable variable, and if you paying close attention to the parameters supplied to the above DoMapTraverse function, there is a parameter called TYPEDEFTOMETHODTABLE.

It is by checking this parameter that the RequestModuleMapTraverse differentiate between each type of LookupMap structure to be traversed. In this case, the corresponding LookupMap structure is of the m_TypeDefToMethodTableMap.

For each of the successful instantiation of the pTable address,  this function will call the supplied ModuleMapTraverse callback function to traverse and prints each type definition or type reference details to WinDBG output window.

You can also manually retrieve the structure of method table using dump memory WinDBG’s command. For example to retrieve the type definition method table, using the !dumpmodule (without -mt) we get :

TypeDefToMethodTableMap: 00c800c0

Using the dump memory of this address we get :

We are actually viewing the pTable array field of the address location of method table. The structure information of this table map is declared as LookupMap, which besides pTable also contains dwMaxIndex, but these internal structure fields is not shown in the dumpmodule command, but sufficed to say that the dwMaxIndex controls the size of the pTable map address.

The first two element is empty and the third element is our method table address, and its address is calculated by this formula :

MT address = Array Index Address + Array Value

For the above sample, the first array index address is 0xc800c0, second index at 0xc800c4, third index at 0xc800c8. We have the 0x2f3c for third index :

MT Address = 0xc800c8 + 0x2f3c = 0xC83004. You can verify the validity of MT Address using DumpMT command :

0:000> !dumpmt C83004
EEClass: 00c812bc
Module: 00c82c5c
Name: CLRTest.Program
mdToken: 02000002  (D:\Projects\CLRTest\bin\Debug\CLRTest.exe)
BaseSize: 0xc
ComponentSize: 0x0
Number of IFaces in IFaceMap: 0
Slots in VTable: 6


One Response to “SOS Internals – DumpModule Command”

  1. vSzemkel Says:

    In !help DumpModule we read:

    0:000> dd 3ec0010
    03ec0010 00000000 00000000 0090320c 0090375c
    03ec0020 009038ec …

    This means TypeDef token 2 maps to a MethodTable with the value 0090320c. You
    can run !DumpMT to verify that.

    THIS IS NOT TRUE. You are right and they are wrong

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: