http://www.blogcn.com/blog/cool/main.asp?uid=flier_lu&id=1678453
Originally, I would like to introduce the SOS debug CLR program under WindBG according to the classification of the SOS's helper file, but it is found that it is not intuitive enough. Sorry modification according to the actual case of the CLR, Step by step introduces the function, so that although the structure is chaotic, it is more intuitive, and it is easy to get started: p The front two articles introduced the basic concept of Windbg debugging configuration and threads. This article analyzes the process of the JIT compilation object method, and gradually describes how to use a WindBG debugging CLR program. Explore CLR World with Windbg [1] - Installation and Environment Configuration WindBG Explore CLR World [2] - Thread first writes a simple example program demo.cs and compiles to demo.exe, use configuration WINDBG to open:
The following is quoted:
Using system;
Namespace Flier
{
Class Entrypoint
{
Public void m1 ()
{
System.console.write ("entrypoint.m1 ()");
}
Public void m2 ()
{
System.console.write ("entrypoint.m2 ()");
}
Public static void main ()
{
EntryPoint EP = New EntryPoint ();
Ep.m1 ();
EP.M2 ();
}
}
}
WINDBG will be interrupted after loading demo.exe. You can use the .load sos command to load the SOS.dll command extension, and use .CHAIN to verify whether the load is successful; then use the ld demo command to load the democked symbol file of Demo.exe, verify that the load is successful with the LM command. Then use the LD Kernel32 to load the Kernel32 debug symbol file, and use the BP Kernel32! LoadLibraryExw "DU POI (ESP 4) command to load the DLL function inlet plus breakpoints. Next is the way G command until Mscorwks.dll is loaded. This mscorwks.dll is a virtual machine similar to JVM.dll in the JVM, which we have to understand is in it. Detailed explanation can refer to my previous article ". NET platform CLR Program Load Principle Analysis" In Mscorwks.dll, use the ld mscorwks command to load its debug symbol library, you can officially start our exploration work. The Windbg command currently used is as follows.
The following is quoted:
.load SOS / / Load SOS debug extension module, you can use .Chain command verification
LD DEMO / / Load DEMO.EXE debug symbol library, you can use the LM command to verify
LD kernel32 // load kernel32.exe debug symbol library
BP Kernel32! LoadLibraryExw "DU POI (ESP 4)" // Sets the breakpoint monitoring when mscorwks.dll is loaded
g // Perform until Mscorwks.dll is loaded
BD 0 // Clear the breakpoint set up and start processing Mscorwks.dll
LD mscorwks // load mscorwks.dll debug symbol library
Don Box In ".NET Natural Theory Volume 1: Public Language Runture", the internal implementation process of the method call is introduced. While it is mentioned that the method is saved before JIT, and it is called Call Mscorwks.dll! PrestubWorker, until the first time use, the target IL code will be compiled, and it is called. So our first step can set the breakpoint (BP Mscorwks! Prestubworker) to see how the system calls this function. The following is quoted:
0: 000> bp mscorwks! PrestubWorker
0: 000> g
MODLOAD: 70AD0000 70BB6000 E: /Windows/winsxs/x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.100.0_X-WW_8417450B/comctL32.dll
Modeload: 79780000 79980000 E: /Windows / Microsoft.net/framework/v1.1.4322/mscorlib.dll
Modeload: 79980000 79ca6000 E: /Windows/assemblying/nativeImages1_v1.1.4322/mscorlib/1.0.5000.0__b77a5c561934e089_ed6bc96c/mscorlib.dll
Modload: 79510000 79523000 E: /Windows / Microsoft.Net/framework/v1.1.4322/mscorsn.dll
Breakpoint 1 Hit
EAX = 0012F7C0 EBX = 00148C60 ECX = 04AA112C EDX = 00000004 ESI = 0012F784 EDI = 0012F9A8
EIP = 791D6A4A ESP = 0012F764 EBP = 0012F79C IOPL = 0 NV UP EI PL ZR NA PO NC
CS = 001B SS = 0023 DS = 0023 ES = 0023 fs = 0038 GS = 0000 EFL = 00000246
Mscorwks! PrestubWorker:
791D6A4A 55 PUSH EBP
The breakpoint is activated to represent the function called. Let's use K to see the context environment when the function is called.
The following is quoted:
0: 000> K
Childebp Retdr
0012F760 0014930E Mscorwks! PrestubWorker
Warning: frame ip Not in Any Known Module. Following Frames May Be WRONG.
0012F79C 791DA434 0X14930E
0012F8B4 791DD2EC Mscorwks! MethodDesc :: CallDesCR 0x1B6
0012F96C 79240405 MSCORWKS! METHODDESC :: Call 0xc5
0012fa18 79240520 mscorwks! Appdomain :: InitializedMainContext 0x10f
0012FA7C 7923D744 Mscorwks! SystemDomain :: InitializedefaultdomAin 0x11c
0012FD60 791C6E73 Mscorwks! SystemDomain :: EXECUTEMAINMETHOD 0X120
0012ffa0 791C6EF3 Mscorwks! EXECUTEEXE 0x1C0
0012ffb0 7880a53e mscorwks! _COREXEMAIN 0x590012FFC0 77E1F38C MSCOREE! _COREXEMAIN 0X30 [f: /dd/ndp/clr/src/dlls/shim/shim.cpp @ 5426]
0012FFF0 00000000 Kernel32! BaseProcessStart 0x23
Here you can see the steps from MSCOREE! _Corexemain all the way, and that warning shows that this Stack Frame is not in any known module. This is normal because this stack frame is actually pointing to code generated by JIT. The Mscorwks! PrestubWorker function we monitored is just the entry stub of the function in the method table, and the system starts to call the compilation execution of JIT completion code in other ways. Next, use SOS! The clrsTack command to see the CLR call stack, displayed as follows:
The following is quoted:
0: 000>! CLRSTACK
succeeded
Loaded Son of Strike Data Table Version 5 from "E: /Windows/Microsoft.Net/framework/v1.1.4322/mscorwks.dll"
THREAD 0
ESP EIP
0012F784 791D6A4A [Frame: PRESTUBMETHODFRAME] [Default] [Hasthis] void system.appdomain.setupdomain (ValueClass System.LoaderOptimization, String, String)
0012F9A8 791D6A4A [Frame: GCFrame]
0012FAD0 791D6A4A [Frame: DebuggerClassinitmarkFrame]
0012FA94 791D6A4A [frame: gcframe]
If you need more detailed details, you can display the parameters, local variables, and registers, respectively, of course, the front two require the support of the symbol library. This is the way G;! ClrsTack executes until the Flier.EntryPoint.m1 function needs to be processed:
The following is quoted:
0: 000>! CLRSTACK
THREAD 0
ESP EIP
0012F68C 791D6A4A [Frame: PRESTUBMETHODFRAME] [Default] [Hasthis] void flier.Entrypoint.m1 ()
0012F69C 06D90080 [Default] void flier.Entrypoint.main ()
0012F9B0 791DA717 [Frame: gcframe]
0012fa94 791da717 [frame: gcframe]
At this point! DumpstackObjects command can view all objects used in the current thread stack
The following is quoted:
0: 000>! DumpstackObjects
ESP / REG OBJECT NAME
ECX 04AA1A90 Flier.Entrypoint
0012F678 04AA1A90 Flier.EntryPoint
0012F67C 04AA1A90 Flier.EntryPoint
0012F680 04AA1A90 Flier.EntryPoint
The Flier.EntryPoint object address 0x04aa1a90 here is the location we want to analyze in memory. The Windbg command used this stage is as follows:
The following is quoted:
BP mscorwks! PrestubWorker // Setting code breakpoint
g // Continue to run to the breakpoint k // to view the native stack call when the function is called
! CLRSTACK / / View the CLR stack call when the function is called
! dumpstackObjects // View all objects used in the thread stack
After knowing the address, you can use it! Dumpobj command to view the details of the object
The following is quoted:
0: 000>! Dumpobj 04aa1a90
Name: Flier.EntryPoint
MethodTable 0x009750A8
EECLASS 0x06C632E8
Size 12 (0xc) bytes
MDToken: 02000002 (D: /TEMP/Demo.exe)
Information includes the type name of the object (Name) and the address of the type information (EECLASS), and the size of the object (size) and token (MDToken), the MethodTable is the target of our analytical method call. We can use! Dumpclass commands First, see the type of object of the object:
The following is quoted:
0: 000>! Dumpclass 0x6c632e8
Class name: Flier.EntryPoint
MDToken: 02000002 ()
Parent Class: 79b7c3c8
ClassLoader: 00153850
Method Table: 009750A8
VTable Slots: 4
Total Method Slots: 8
Class Attributes: 100000:
Flags: 1000003
NumInstanceFields: 0
NumStaticfields: 0
ThreadStaticOffset: 0
ThreadStaticsSize: 0
ContextStaticOffset: 0
ContextStaticsSize: 0
It can be found that there are many in line with object information. As Don Box said, an object reference points to a type EECLASS instance, and the method table is all types, and its object is common. We can use! Dumpmt commands to further view the information of the method table, -md parameter indicates that you need to view each method description:
The following is quoted:
0: 000>! Dumpmt -md 0x09750a8
EECLASS: 06C632E8
Module: 0014E090
Name: Flier.EntryPoint
MDToken: 02000002 (D: /TEMP/Demo.exe)
MethodTable Flags: 80000
Number of iFaces in iFacemap: 0
Interface map: 009750F4
Slots in vTable: 8
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
MethodDesc TABLE
Entry MethodDesc Jit Name
79b7c4eb 79b7c4f0 none [default] [hasthis] string system.Object.toString ()
79b7c473 79b7c478 none [default] [hasthis] boolean system.Object.equals (Object)
79b7c48b 79b7c490 none [default] [hasthis] i4 system.Object.gethashcode ()
79b7c52b 79b7c530 none [default] [hasthis] void system.Object.Finalize ()
0097506B 00975070 None [default] [hasthis] void flier.Entrypoint.m1 () 0097507B 00975080 None [default] [hasthis] void flier.Entrypoint.m2 ()
0097508B 00975090 NONE [Default] void flier.Entrypoint.main ()
0097509B 009750A0 none [default] [hasthis] void flier.Entrypoint..ctor ()
You can see that there are eight entries in the method table, where the top 4 has been bound to the NGEN precompiled static function.
The following is quoted:
0: 000> u 79b7c4eb
Mscorlib_79980000 0x1fc4eb:
79B7C4EB E8909CFEFF CALL MSCORLIB_79980000 0x1e6180 (79b66180)
79B7C4F0 0000 Add [EAX], Al
79b7c4f2 0080d86206c0 add [eax 0xc00662d8], Al
79b7c4f8 06 push es
79b7c4f9 00fc Add Ah, BH
79B7C4FB E8809CFEFF CALL MSCORLIB_79980000 0x1e6180 (79b66180)
79B7C500 07 POP ES
79b7c501 0010 Add [EAX], DL
The next four, as an outdated false method in the method table, which is why VTABLE SLOTS = 4 when viewing type information. For each project of the method, you can use! Dumpmd command to view detailed description, such as
The following is quoted:
0: 000>! Dumpmd 0x00975070
Method name: [default] [hasthis] void flier.Entrypoint.m1 ()
MethodTable 9750A8
Module: 14E090
MDToken: 06000001 (D: /TEMP/Demo.exe)
Flags: 0
IL rva: 00002050
IL RVA illustrates the IL code of this method relative to virtual address (IL RVA), that is, this method has not been JIT, still in the form of IL code. For methods that have completed JIT, the virtual address of the function code after its JIT is displayed:
The following is quoted:
0: 000>! Dumpmd 0x009750a0
Method name: [default] [hasthis] void flier.EntryPoint..ctor ()
MethodTable 9750A8
Module: 14E090
MDToken: 06000004 (D: /TEMP/Demo.exe)
Flags: 0
Method VA: 06D900A8
The Windbg command used this stage is as follows:
The following is quoted:
Dumpobj 04AA1A90 / / View the details of the object
DumpClass 0x6C632E8 / / View Type Details
! dumpmt -md 0x09750a8 // View method table details
Dumpmd 0x00975070 // View method description of method description
u 0x79b7c4eb // disassembled instructions for designated address
We have disassembled! DUMPMT commands are listed, and you will find that Don Box said, it has been directed by JIT's code to a JMP instruction, directly jump to compiled method, such as: The following is quote:
0: 000> u 0097509b
0097509b E908B04106 JMP 06D900A8
Without the function of JIT, point to a CALL instruction, call a proLog code, indirectly call the Mscorwks! PrestubWorker function to complete the actual JIT, such as:
The following is quoted:
0: 000> u 0x0097506b
0097506B E878427DFF CALL 001492E8
0: 000> u 0x0097507b
0097507B E868427DFF CALL 001492E8
This proLog code is very simple, responsible for constructing the call stack required for Mscorwell! PrestubWorker
The following is quoted:
0: 000> u 0x001492e8
001492E8 52 Push EDX
001492E9 68F0301B79 PUSH 0x791B30F0
001492ee 55 Push EBP
001492ef 53 Push EBX
001492F0 56 PUSH ESI
001492F1 57 Push EDI
001492F2 8D742410 Lea ESI, [ESP 0x10]
001492F6 51 PUSH ECX
001492F7 52 Push EDX
001492F8 648B1D2C0E0000 MOV EBX, FS: [00000E2C]
001492FF 8B7B08 MOV EDI, [EBX 0x8]
00149302 897E04 MOV [ESI 0x4], EDI
00149305 897308 MOV [EBX 0x8], ESI
00149308 56 PUSH ESI
00149309 E83CD70879 CALL MSCORWKS! PRESTUBWORKER (791D6A4A)
0014930E 897B08 MOV [EBX 0x8], EDI
00149311 894604 MOV [ESI 0x4], EAX
00149314 5A POP EDX
00149315 59 POP ECX
00149316 5F POP EDI
00149317 5E POP ESI
00149318 5B POP EBX
00149319 5D POP EBP
0014931A 83C404 Add ESP, 0x4
0014931D 8F0424 POP [ESP]
00149320 C3 RET