The Power of !dumpmodule

Scenario: My customer is experiencing a hang and I see many threads with an identical stack. I also see that the customer has one thread that is running a component that is an OCX. What I want to find out is whether that component is referenced in the page that is executing on these numerous threads, but Reflector chokes on the module when I try to open it there.

Fortunately, you can use !dumpmodule in SOS to get that information. Not only will this tell you what types are defined in that module, but it will also tell you what references there are in the module. This can be especially useful if you see an unknown module in a dump. (An unknown module is often a dynamic assembly that is not serialized to disk.)

In this scenario, suppose I look at thread 68 and I see this:

0:068> !clrstack
Thread 68
ESP EIP
0x21d3e9a8 0x77f82870 [FRAME: GCFrame]
0x21d3ea68 0x77f82870 [FRAME: HelperMethodFrame]
0x21d3ea9c 0x0cb9eb92 [DEFAULT] [hasThis] Void JC.Business.Spec.ProcessPDF(Object) 
0x21d3ead4 0x0d12b933 [DEFAULT] [hasThis] Void JCC.Export.GoSpec()
0x21d3eb10 0x0d12b41f [DEFAULT] [hasThis] Void JCC.Export.Page_Load(Object,Class System.EventArgs)
0x21d3eb28 0x0ca2752c [DEFAULT] [hasThis] Void System.Web.UI.Control.OnLoad(Class System.EventArgs)

I believe that there is a problem in the JCC.Export page and I want to see what that references. The first thing I need to do is find out what assembly it lives in. I do that by dumping out the stack objects and getting the address of that type:

0:068> !dumpstackobjects
Thread 68
ESP/REG Object Name
0x21d3e4f8 0x27c8f84 System.String Project_Titl
0x21d3eaac 0x15144c4 System.Object[]
0x21d3eae0 0x536b4c8 System.String pdf
0x21d3eae4 0x1513e44 System.String \\netshare\webshare$\Temp\spec\
0x21d3eaf0 0x5a1b4b0 _ASP.Export_aspx

Now that I know the name of the type (_ASP.Export_aspx), I can find out what module it’s in by first using the !name2ee command to search all loaded modules for this type:

0:068> !name2ee * _ASP.Export_aspx
Searching all modules, this may take a while.
Loading all modules
Searching modules...
Module: 0c490220 (lbtrt0sh.dl )
MethodTable: 0x0d27002c
EEClass: 0x0d04f334
Name: _ASP.Export_aspx
----------------------------------- -------

The asterisk after the command tells it to search all modules. Note that the type name is case-sensitive

Now I’ve got the address of the module as reported by name2ee. To get the address to pass to !dumpdomain, you need to subtract 0x1d8 from that

0:068> ? 0c490220 -0x1d8
Evaluate expression: 206110792 = 0c490048

There’s the address we use to get the module information via !dumpmodule:

0:068> !dumpmodule -mt 0c490048
Name c:\winnt\microsoft.net\framework\v1.1.4322\temporary asp.net files\root\b6f74a28\3807bf05\lbtrt0sh.dll
dwFlags 0x00200080
Attribute PEFile
Assembly 0x0bad89d0
LoaderHeap* 0x0017299c
TypeDefToMethodTableMap* 0x0c6b6618
TypeRefToMethodTableMap* 0x0c6b6664
MethodDefToDescMap* 0x0c6b67d4
FieldDefToDescMap* 0x0c6b6e18
MemberRefToDescMap* 0x0c6b6f78
FileReferencesMap* 0x0c6b786c
AssemblyReferencesMap* 0x0c6b7870
Types defined in this module
MT TypeDef Name
-----------------------------------------------------------------
0x17be8fbc 0x02000002 _ASP.MailMerge_aspx
0x1ee2ab4c 0x02000004 _ASP.AddPhone_aspx
0x0b9435d4 0x02000005 _ASP.AddEmail_aspx
0x21381254 0x02000007 _ASP.Calendar_aspx
0x17bef57c 0x02000009 _ASP.AddURL_aspx
0x0b9405f4 0x0200000b _ASP.AddAddress_aspx
0x25ef6cfc 0x0200000d _ASP.AssignProject_aspx
0x25ef2794 0x02000011 _ASP.MailMergeDownload_aspx
0x0b941244 0x02000012 _ASP.AssignCompany_aspx
Types referenced in this module
MT TypeRef Name
0x17be8c2c 0x02000001 JCC.MailMerge
0x0c7431ec 0x02000002 System.Web.SessionState.IRequiresSessionState
0x0ca193dc 0x02000003 System.Web.UI.WebControls.Literal
0x0ca19b5c 0x02000004 System.Web.UI.HtmlControls.HtmlForm
0x79ba0d74 0x02000005 System.Collections.ArrayList
0x0b97faac 0x02000007 System.Web.UI.Control
0x0ca1c944 0x02000008 System.Web.UI.HtmlTextWriter
0x1ee2a6e4 0x0200000e JCC.AddPhone
0x0b94322c 0x0200000f JCC.AddEmail
0x21380e64 0x02000011 JCC.Calendar
0x0d05fc0c 0x02000012 JCC.Export

I don't really see what’m interested in here. Because the JC.Business.Spec class is at the top of the stack I'm working with, I want to find out what is in that class. First I need to find out what module that lives in, so I'll use !name2ee again.

0:068> !name2ee * JC.Business.Spec
Searching all modules, this may take a while.
Loading all modules.
Searching modules...
Module: 0ba77100 (planspec.dll)
MethodTable: 0x0d2706bc
EEClass: 0x0d04fa7c
Name: JC.Business.Spec
----------------------------------- -------

Instead of evaluating the module address and subtracting 0x1d8 before dumping it, I'll now just pass the expression straight to !dumpmodule:

0:068> !dumpmodule -mt 0ba77100 -0x1d8
Name c:\winnt\microsoft.net\framework\v1.1.4322\temporary asp.net files\root\b6f74a28\3807bf05\assembly\dl2\2fb2768b\c0e90b4e_3b3cc501\planspec.dll
dwFlags 0x00200080
Attribute PEFile
Assembly 0x0ba76de8
LoaderHeap* 0x0017299c
TypeDefToMethodTableMap* 0x0c2622e4
TypeRefToMethodTableMap* 0x0c2622f8
MethodDefToDescMap* 0x0c262410
FieldDefToDescMap* 0x0c262490
MemberRefToDescMap* 0x0c2624e8
FileReferencesMap* 0x0c262644
AssemblyReferencesMap* 0x0c262648
MetaData starts at 0x0c273d30 (0x221c bytes)
Types defined in this module
MT TypeDef Name
-----------------------------------------------------------------
0x145f2630 0x02000002 PlanSpecFileType
0x145f283c 0x02000003 JC.PlanSpecBiz.GroupList
0x0d2706bc 0x02000004 JC.Business.Spec
Types referenced in this module
MT TypeRef Name
-----------------------------------------------------------------
0x0cb25a70 0x02000021 OCXLib.OCXClass
0x0cb22718 0x02000024 OCXLib._DOCX
0x0d2772c8 0x02000029 RasterIO.LRIOClass
0x0d27bc24 0x0200002a RasterLib.LRasterClass
0x0d272ca8 0x0200002b LRIOLib.ILRasterIO

Look at those OCX classes. If I look to see where they are, I find an interop component:

0:068> !name2ee * OCXLib.OCXClass
Searching all modules, this may take a while.
Loading all modules.
Searching modules...
Module: 0bad99a8 (interop.ocxlib.dll)
MethodTable: 0x0cb25a70
EEClass: 0x0d28c8b0
Name: OCXLib.OCXClass
----------------------------------- -------

I now know that the stacks that are hanging are sitting on a function call in a class that references the interop component that's using the OCX that I found on another thread. This doesn't get me to root cause, but it does give me a clear indicator of where I need to start looking.

Jim