Correlating between .NET and native thread in Windbg
I recently saw a stackoverflow question where someone wanted to know how they could correlate between managed and native threads within Windbg.
Here is the managed thread object within the debugger
0:004> !do 02a1d6c4
Name: System.Threading.Thread
MethodTable: 672e001c
EEClass: 67018ed8
Size: 48(0×30) bytes
File: C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
Fields:
MT Field Offset Type VT Attr Value Name
672c8a78 4000720 4 ….Contexts.Context 0 instance 00000000 m_Context
672db4b8 4000721 8 ….ExecutionContext 0 instance 00000000 m_ExecutionContext
672df9fc 4000722 c System.String 0 instance 02a1a220 m_Name
672dfed0 4000723 10 System.Delegate 0 instance 00000000 m_Delegate
672e63f4 4000724 14 …ation.CultureInfo 0 instance 00000000 m_CurrentCulture
672e63f4 4000725 18 …ation.CultureInfo 0 instance 00000000 m_CurrentUICulture
672df638 4000726 1c System.Object 0 instance 00000000 m_ThreadStartArg
672daa7c 4000727 20 System.IntPtr 1 instance 542560 DONT_USE_InternalThread
672e29c8 4000728 24 System.Int32 1 instance 2 m_Priority
672e29c8 4000729 28 System.Int32 1 instance 3 m_ManagedThreadId
672cb76c 400072a 18c …LocalDataStoreMgr 0 shared static s_LocalDataStoreMgr
>> Domain:Value 0049f148:NotInit <<
672ce328 400072b c …alDataStoreHolder 0 shared TLstatic s_LocalDataStore
>> Thread:Value <<
The present thread’s @$teb (Thread Environment Block) is 7efac000
0:004> ? @$teb Evaluate expression: 2130374656 = 7efac000
The DONT_USE_InternalThread is pointer to the native thread. Dumping the raw memory of the pointer should give us more information we are looking for.
0:004> dd poi(02a1d6c4+20)
00542560 67e9ee88 0000b220 00000000 056ef42c
00542570 00000000 00000000 00000000 00000003
00542580 00000000 00542588 00542588 00542588
00542590 00000000 00000000 baad0000 004a4f30
005425a0 7efac000 baadf00d 00000000 00000000
005425b0 00024dac 00000000 00000000 00000000
005425c0 00000000 baadf00d 00541ba0 00544290
005425d0 00544298 00000200 00544290 00544580
The pointer to teb is in the 40th offset of the DONT_USE_InternalThread and here is the script that would get teb for each managed thread.
.foreach ($thread {!dumpheap -mt 672e001c -short}) { .if ( poi(${$thread}+20) != 0) {.printf "%p \n",dwo(poi(${$thread}+20)+40)}}
0:004> .foreach ($thread {!dumpheap -mt 672e001c -short}) { .if ( poi(${$thread}+20) != 0) {.printf “%p \n”,dwo(poi(${$thread}+20)+40) }}
7efdd000
7efac000
7ef9a000
7ef97000
7ef2f000
7ef26000
7efd7000
7ef20000
7ef1d000
7ef1d000
7ef0e000
7efa3000
7ef2c000
So with the above we could dump the teb structure using dt ntdll!_TEB command. In the next post I will demonstrate how this can be used to debug some cool stuff :)
thanks, looking forward to next post :-)
Marc Sherman
January 10, 2011 at 9:30 am
You can do even more things with DONT_USE_InternalThread. I did write a (very fast) tracing library that is able to trace the exception object when a method is left with an exception without any try/catch blocks.
Only a using block is required:
void DoMethod(…)
{
using(Tracer t = new Tracer(myType,”DoMethod”)
{
…
t.Info(“Got there”);
throw new Exception(…)
}
}
When you set the environment variable to
set _Trace=file c:\temp\exceptions.txt; * Exception
You enable first time exception tracing for all methods that are instrumented like this and write the exceptions into the configured file.
Yours,
Alois Kraus
Alois Kraus
January 12, 2011 at 5:04 pm
Thanks for the information. Saw your post on that. Cool one. http://geekswithblogs.net/akraus1/archive/2010/07/04/140761.aspx
Also CLR has ETW for exceptions which can be used for tracing the exceptions along with call-stack.
Naveen
January 12, 2011 at 5:18 pm