Introduction
In
this post I'd like to shortly present how to explore a method's MSIL Code
and also its corresponding Assembly Code.
Some
internal issues could be resolved while exploring the method assembly code and
quite often its MSIL instruction code.
Remark:
For
this debugging session I used the WinDbg tool with the PSSCOR2
debugging extension. However we could use other debugging extensions (such as:
SOS, SOSEX, PSSCOR4) to perform & achieve the same result.
Example
1.
We could use the '!CLRStack' command to find
the desired method in the thread call stack.
-
Command:
!CLRStack
-
Example:
0:000>
!CLRStack
OS
Thread Id: 0x1a64 (0)
ESP EIP
001ded3c
006a016d TestPerfExample.Program.DebuggingExample1()
001ded94
006a009a TestPerfExample.Program.Main(System.String[])
001deff8
68b31b4c [GCFrame: 001deff8]
|
2.
We could use the '!name2ee' command to turn a
method name into a MethodDesc.
-
Command:
!name2ee
-
Example:
0:000> !name2ee
TestPerfExample!TestPerfExample.Program.DebuggingExample1
Module:
002a2f2c (TestPerfExample.exe)
Token:
0x06000008
MethodDesc:
002a330c
Name:
TestPerfExample.Program.DebuggingExample1()
JITTED
Code Address: 006a00c0
|
Explore the method's MSIL Code:
3.
Now we could use the '!DumpIL' command with the
MethodDesc address (retrieved from the previous command - 002a330c) to
observe the method's MSIL Code.
-
Command:
!DumpIL
-
Example:
0:000>
!DumpIL 002a330c
ilAddr
= 010a20ec
IL_0000:
nop
IL_0001:
ldc.i4.s 97
IL_0003:
stloc.0
IL_0004:
newobj TestPerfExample.Person::.ctor
IL_0009:
stloc.1
IL_000a:
ldloc.1
IL_000b:
ldc.i4.3
IL_000c:
callvirt TestPerfExample.Person::set_Id
IL_0011:
nop
IL_0012:
newobj TestPerfExample.Person::.ctor
IL_0017:
stloc.2
IL_0018:
ldloc.2
IL_0019:
ldc.i4.5
IL_001a:
callvirt TestPerfExample.Person::set_Id
IL_001f:
nop
IL_0020:
ldloc.2
IL_0021:
callvirt TestPerfExample.Person::get_Id
IL_0026:
call System.Console::WriteLine
IL_002b:
nop
IL_002c:
ret
|
Explore the method's Assembly Code:
4.
In order to observe the method's assembly code, we'll
first use the '!DumpMD' command to retrieve its method description
information, using the MethodDesc address.
-
Command:
!DumpMD
-
Example:
0:000>
!DumpMD 002a330c
Method
Name: TestPerfExample.Program.DebuggingExample1()
Class:
002a13d8
MethodTable:
002a3338
mdToken:
06000008
Module:
002a2f2c
IsJitted:
yes
m_CodeOrIL:
006a00c0
|
5.
Now we could use the '!U' command with the m_CodeOrIL address (retrieved from the
previous command - 006a00c0) to observe the method's assembly code.
-
Command:
!U
-
Example:
0:000>
!U -gcinfo -ehinfo 006a00c0
Normal
JIT generated code
TestPerfExample.Program.DebuggingExample1()
Begin
006a00c0, size b6
>>>
006a00c0 55 push ebp
006a00c1
8bec mov ebp,esp
006a00c3
57 push edi
006a00c4
56 push esi
006a00c5
53 push ebx
006a00c6
83ec44 sub esp,44h
006a00c9
8d7dc8 lea edi,[ebp-38h]
006a00cc
b90b000000 mov ecx,0Bh
006a00d1
33c0 xor eax,eax
006a00d3
f3ab rep stos dword ptr
es:[edi]
006a00d5
33c0 xor
eax,eax
006a00d7
8945e4 mov dword ptr [ebp-1Ch],eax
006a00da
833de4302a0000 cmp dword ptr ds:[2A30E4h],0
006a00e1
7405 je 006a00e8
006a00e3
e8f1197168 call mscorwks!JIT_DbgIsJustMyCode (68db1ad9)
006a00e8
33d2 xor edx,edx
006a00ea
8955bc mov dword ptr [ebp-44h],edx
006a00ed
33d2 xor edx,edx
006a00ef
8955c0 mov dword ptr [ebp-40h],edx
006a00f2
c745c400000000 mov dword ptr [ebp-3Ch],0
006a00f9
90 nop
006a00fa
c745c461000000 mov dword ptr [ebp-3Ch],61h
006a0101
b9c4332a00 mov ecx,2A33C4h
006a0106
e8111fbfff call 0029201c (JitHelp: CORINFO_HELP_NEWSFAST)
004B reg EAX becoming live
006a010b
8945b8 mov dword ptr [ebp-48h],eax
006a010e
8b4db8 mov ecx,dword ptr [ebp-48h]
0051 reg ECX becoming live
006a0111
e84abfc0ff call 002ac060 (TestPerfExample.Person..ctor(),
mdToken: 06000003)
0056 reg EAX becoming dead
0056 reg ECX becoming dead
006a0116
8b45b8 mov eax,dword ptr [ebp-48h]
0059 reg EAX becoming live
006a0119
8945c0 mov dword ptr [ebp-40h],eax
006a011c
8b4dc0 mov ecx,dword ptr [ebp-40h]
005F reg ECX becoming live
006a011f
ba03000000 mov edx,3
006a0124
3909 cmp dword ptr [ecx],ecx
006a0126
e82dbfc0ff call 002ac058
(TestPerfExample.Person.set_Id(Int32), mdToken: 06000002)
006B reg EAX becoming dead
006B reg ECX becoming dead
006a012b
90 nop
006a012c
b9c4332a00 mov ecx,2A33C4h
006a0131
e8e61ebfff call 0029201c (JitHelp: CORINFO_HELP_NEWSFAST)
0076 reg EAX becoming live
006a0136
8945b4 mov dword ptr [ebp-4Ch],eax
006a0139
8b4db4 mov ecx,dword ptr [ebp-4Ch]
007C reg ECX becoming live
006a013c
e81fbfc0ff call 002ac060 (TestPerfExample.Person..ctor(),
mdToken: 06000003)
0081 reg EAX becoming dead
0081 reg ECX becoming dead
006a0141
8b45b4 mov eax,dword ptr [ebp-4Ch]
0084 reg EAX becoming live
006a0144
8945bc mov dword ptr [ebp-44h],eax
006a0147
8b4dbc mov ecx,dword ptr [ebp-44h]
008A reg ECX becoming live
006a014a
ba05000000 mov edx,5
006a014f
3909 cmp dword ptr [ecx],ecx
006a0151
e802bfc0ff call 002ac058
(TestPerfExample.Person.set_Id(Int32), mdToken: 06000002)
0096 reg EAX becoming dead
0096 reg ECX becoming dead
006a0156
90 nop
006a0157
8b4dbc mov ecx,dword ptr [ebp-44h]
009A reg ECX becoming live
006a015a
3909 cmp dword ptr [ecx],ecx
006a015c
e8efbec0ff call 002ac050 (TestPerfExample.Person.get_Id(),
mdToken: 06000001)
00A1 reg ECX becoming dead
006a0161
8945b0 mov dword ptr [ebp-50h],eax
006a0164
8b4db0 mov ecx,dword ptr [ebp-50h]
006a0167
e8244d0668 call mscorlib_ni+0x6d4e90 (68704e90)
(System.Console.WriteLine(Int32), mdToken: 060007c4)
006a016c
90 nop
006a016d
cc int 3
006a016e
8d65f4 lea esp,[ebp-0Ch]
006a0171
5b pop ebx
006a0172
5e pop esi
006a0173
5f pop edi
006a0174
5d pop ebp
006a0175
c3 ret
|
Summary
We
managed to observe how to retrieve a desired method's MSIL and Assembly code
with only few commands.
We
used the WinDbg tool (part of the 'Debugging Tools for Windows') and
in this session I used the 'psscor2.dll' debugging extension.
For
additional related articles, please see the list appears at the beginning of
this post.
The End
Hope you enjoyed!
Appreciate your
comments…
Yonatan Fedaeli
No comments:
Post a Comment