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





