使用WinDbg —— .NET篇 (二)
转载请注明出处:http://blog.csdn.net/ecjtu_luowei/article/details/44260453
四、观察行为
4.1 设置断点
讲设置断点前,先看段代码
using System; namespace Ext1 { class Program { static void M1() { Console.WriteLine("M1"); } static void M2() { Console.WriteLine("M2"); } static void Main(string[] args) { M1(); Console.Read(); M1(); M2(); } } } |
设置断点的方式有很多,关键在于设置断点的位置和已知条件。可以设置断点的命令分别有,标准命令:bp、bu、bm;SOS扩展命令:!bpmd;SOSEX扩展命令:!mbp。接下来我会简单介绍每个命令的使用,大家可以根据不同的使用环境和条件可以灵活使用这些命令。
0:004> .loadby sos clr 0:004> !name2ee Ext1.exe Ext1.Program.M1 Module: 00152e94 Assembly: Ext1.exe Token: 06000001 MethodDesc: 00153794 Name: Ext1.Program.M1() JITTED Code Address: 001b00a8 0:004> bp 001b00a8 0:004> bl 0 e 001b00a8 0001 (0001) 0:**** 0:004> g Breakpoint 0 hit eax=0000000d ebx=003eefdc ecx=02434b0c edx=00000000 esi=00000000 edi=003eef50 eip=001b00a8 esp=003eef2c ebp=003eef38 iopl=0 nv up ei pl zr na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246 001b00a8 55 push ebp |
加载该程序后,通过g命令,g命令就是Go的意思,让程序继续运行,程序会执行到Read方法等待用户的输入,这个时候在调试器上使用快捷键Ctrl+Break中断程序,可以看到CLR已经被加载,然后如上表命令进行操作,首先通过!name2ee命令得到被编译过的M1方法地址0x004700a0,然后通过bp [Address]设值断点。继续执行程序,这个时候程序会自动中断,中断的地址就是刚刚设置的断点位置(EIP寄存器就是储存的下个指令所在的地址)。在上面的调试过程,还使用了bl命令查看断点列表,可以看到有一行数据输出:
0 e 004700a0 0001 (0001) 0:****
0:表示断点的ID
e:表示enable,表示该断点是有效的,还有一个状态是u,表示该断点还没找到位置,原因可能是对应的模块没有加载
004700a0:表示断点的地址
0001 (0001):(0001)表示至少要执行(hit)到该断点对应的地址1次才能触发该断点,0001 表示还剩下1次就能触发,也就是下次执行到该地址就能触发。设置断点hit的次数10次如:“~0 bp 004700a0 10”
0:****:0是进程ID,****表示任何线程都可以触发该断点,如果只有ID为0的线程能触发该线程,那么该值为:0:~000。设置某特定线程触发断点的命令如:“~0 bp 004700a0”
按道理这后面应该还有关于断点的模块和方法信息,但是因为是托管代码,机器码都是临时生成的,所以找不到对应的模块和方法,这也导致了bu和bm命令没什么用。
bu和bm的使用都是依赖于非托管模块的符号,bu主要用来设置延迟性的断点,比如说某一模块还没加载到进程中的时候;bm主要是通过调试符号来模糊查找设置断点。另外bc、bd、be分别是清除所有断点、disable断点和enable断点的命令,因为!bpmd和!mbp设置的断点有时候是延迟的断点,这个时候不能使用标准命令管理这些断点,所以对应的!bpmd和!mbp设置的断点也有对应的断点管理的命令,详情可以参考帮助文档。
看到这里,读者应该注意到刚才调试的过程中依赖于M1方法已经被编译过了,如果是给还没编译过的M2方法设置断点的话,就需要借助到SOS中的!bpmd命令:
0:004> !name2ee Ext1.exe Ext1.Program.M2 Module: 00152e94 Assembly: Ext1.exe Token: 06000002 MethodDesc: 001537a0 Name: Ext1.Program.M2() Not JITTED yet. Use !bpmd -md 001537a0 to break on run. 0:004> !bpmd -md 001537a0 MethodDesc = 001537a0 Adding pending breakpoints... 0:000> g (efc.e44): CLR notification exception - code e0444143 (first chance) JITTED Ext1!Ext1.Program.M2() Setting breakpoint: bp 001B00F1 [Ext1.Program.M2()] Breakpoint 1 hit eax=001b00e0 ebx=003eefdc ecx=024346b4 edx=00000000 esi=00000000 edi=003eef50 eip=001b00f1 esp=003eef28 ebp=003eef28 iopl=0 nv up ei pl zr na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246 001b00f1 90 nop 0:000> !name2ee Ext1.exe Ext1.Program.M2 Module: 00152e94 Assembly: Ext1.exe Token: 06000002 MethodDesc: 001537a0 Name: Ext1.Program.M2() JITTED Code Address: 001b00e0 0:000> !u 001b00e0 Normal JIT generated code Ext1.Program.M2() Begin 001b00e0, size 21 *** WARNING: Unable to verify checksum for Ext1.exe d:\Code\Ext1\Ext1\Program.cs @ 13: >>> 001b00e0 55 push ebp 001b00e1 8bec mov ebp,esp 001b00e3 833d6031150000 cmp dword ptr ds:[153160h],0 001b00ea 7405 je 001b00f1 001b00ec e8c36f5370 call clr!GetHistoryFileDirectory+0x8786f (706e70b4) (JitHelp: CORINFO_HELP_DBG_IS_JUST_MY_CODE) 001b00f1 90 nop d:\Code\Ext1\Ext1\Program.cs @ 14: 001b00f2 8b0d34214303 mov ecx,dword ptr ds:[3432134h] ("M2") *** WARNING: Unable to verify checksum for C:\Windows\assembly\NativeImages_v4.0.30319_32\mscorlib\51e2934144ba15628ba5a31be2dae7dc\mscorlib.ni.dll *** ERROR: Module load completed but symbols could not be loaded for C:\Windows\assembly\NativeImages_v4.0.30319_32\mscorlib\51e2934144ba15628ba5a31be2dae7dc\mscorlib.ni.dll 001b00f8 e8f3d2566f call mscorlib_ni+0x36d3f0 (6f71d3f0) (System.Console.WriteLine(System.String), mdToken: 06000992) 001b00fd 90 nop d:\Code\Ext1\Ext1\Program.cs @ 15: 001b00fe 90 nop 001b00ff 5d pop ebp 001b0100 c3 ret |
!u命令是反汇编命令,通过查看M2编译后的地址,可以看到!bmpd将断点的位置刚好设置在了M2方法的开始。!bmpd命令还可以直接通过Symbol设置断点,如: !bpmd Ext1.exe Ext1.Program.M2
如果需要在Main方法的开始设置断点,由于启动程序后,会立马执行到Read方法,而且利用Windbg启动Ext.exe的时候再第一次中断的时候还没加载CLR,所以这个时候也不能使用!bpmd命令。这种情形下,有两个办法设置断点:
0:000> .symfix 0:000> .reload Reloading current modules ..... 0:000> .load sosex 0:000> !mbp Program.cs 18 The CLR has not yet been initialized in the process. Breakpoint resolution will be attempted when the CLR is initialized. 0:000> g ModLoad: 770a0000 77140000 C:\Windows\syswow64\ADVAPI32.dll ModLoad: 775c0000 7766c000 C:\Windows\syswow64\msvcrt.dll ModLoad: 76da0000 76db9000 C:\Windows\SysWOW64\sechost.dll ModLoad: 76cb0000 76da0000 C:\Windows\syswow64\RPCRT4.dll ModLoad: 75830000 75890000 C:\Windows\syswow64\SspiCli.dll ModLoad: 75820000 7582c000 C:\Windows\syswow64\CRYPTBASE.dll ModLoad: 71510000 7158a000 C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscoreei.dll ModLoad: 75890000 758e7000 C:\Windows\syswow64\SHLWAPI.dll ModLoad: 75e10000 75ea0000 C:\Windows\syswow64\GDI32.dll ModLoad: 76e40000 76f40000 C:\Windows\syswow64\USER32.dll ModLoad: 76c90000 76c9a000 C:\Windows\syswow64\LPK.dll ModLoad: 77210000 772ad000 C:\Windows\syswow64\USP10.dll ModLoad: 75ea0000 75f00000 C:\Windows\SysWOW64\IMM32.DLL ModLoad: 77140000 7720c000 C:\Windows\syswow64\MSCTF.dll ModLoad: 70450000 70ae2000 C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll ModLoad: 70370000 70443000 C:\Windows\SysWOW64\MSVCR110_CLR0400.dll (7d4.e5c): Unknown exception - code 04242420 (first chance) ModLoad: 6f3b0000 7036f000 C:\Windows\assembly\NativeImages_v4.0.30319_32\mscorlib\51e2934144ba15628ba5a31be2dae7dc\mscorlib.ni.dll *** WARNING: Unable to verify checksum for C:\Windows\assembly\NativeImages_v4.0.30319_32\mscorlib\51e2934144ba15628ba5a31be2dae7dc\mscorlib.ni.dll ModLoad: 76f40000 7709c000 C:\Windows\syswow64\ole32.dll *** WARNING: Unable to verify checksum for Ext1.exe ModLoad: 6e9a0000 6ea0e000 C:\Windows\Microsoft.NET\Framework\v4.0.30319\clrjit.dll Breakpoint: JIT notification received for method Ext1.Program.Main(System.String[]) in AppDomain 00515fe0. Breakpoint set at Ext1.Program.Main(System.String[]) in AppDomain 00515fe0. Breakpoint 1 hit eax=002e0050 ebx=0029f3d4 ecx=02452254 edx=00000001 esi=00000000 edi=0029f340 eip=002e0067 esp=0029f320 ebp=0029f328 iopl=0 nv up ei pl zr na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246 002e0067 90 nop 0:000> .loadby sos clr 0:000> !name2ee Ext1.exe Ext1.Program.Main Module: 00182e94 Assembly: Ext1.exe Token: 06000003 MethodDesc: 001837ac Name: Ext1.Program.Main(System.String[]) JITTED Code Address: 002e0050 0:000> !u 002e0050 Normal JIT generated code Ext1.Program.Main(System.String[]) Begin 002e0050, size 3b d:\Code\Ext1\Ext1\Program.cs @ 18: >>> 002e0050 55 push ebp 002e0051 8bec mov ebp,esp 002e0053 83ec08 sub esp,8 002e0056 894dfc mov dword ptr [ebp-4],ecx 002e0059 833d6031180000 cmp dword ptr ds:[183160h],0 002e0060 7405 je 002e0067 002e0062 e84d704070 call clr!JIT_DbgIsJustMyCode (706e70b4) 002e0067 90 nop d:\Code\Ext1\Ext1\Program.cs @ 19: 002e0068 ff159c371800 call dword ptr ds:[18379Ch] (Ext1.Program.M1(), mdToken: 06000001) 002e006e 90 nop d:\Code\Ext1\Ext1\Program.cs @ 20: 002e006f e84852a86f call mscorlib_ni+0x9b52bc (6fd652bc) (System.Console.Read(), mdToken: 06000983) 002e0074 8945f8 mov dword ptr [ebp-8],eax 002e0077 90 nop d:\Code\Ext1\Ext1\Program.cs @ 21: 002e0078 ff159c371800 call dword ptr ds:[18379Ch] (Ext1.Program.M1(), mdToken: 06000001) 002e007e 90 nop d:\Code\Ext1\Ext1\Program.cs @ 22: 002e007f ff15a8371800 call dword ptr ds:[1837A8h] (Ext1.Program.M2(), mdToken: 06000002) 002e0085 90 nop d:\Code\Ext1\Ext1\Program.cs @ 23: 002e0086 90 nop 002e0087 8be5 mov esp,ebp 002e0089 5d pop ebp 002e008a c3 ret |
还有一个办法是当加载CLR的时候中断运行,这个时候Windbg可以加载sos,如果需要设置断点,需要等到clrjit.dll被加载(下表中的sxe ld clrjit.dll就是指当加载clrjit.dll的时候自动中断),然后利用!bmpd设置断点:
0:000> sxe ld clrjit.dll 0:000> g (8e8.ea4): Unknown exception - code 04242420 (first chance) ModLoad: 6e9a0000 6ea0e000 C:\Windows\Microsoft.NET\Framework\v4.0.30319\clrjit.dll eax=00000000 ebx=00000000 ecx=00000000 edx=00000000 esi=7efdd000 edi=003aeaf4 eip=77cefc52 esp=003ae9c8 ebp=003aea1c iopl=0 nv up ei pl zr na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246 ntdll!ZwMapViewOfSection+0x12: 77cefc52 83c404 add esp,4 0:000> .loadby sos clr 0:000> !bpmd Ext1.exe Ext1.Program.Main Found 1 methods in module 00202e94... MethodDesc = 002037ac Adding pending breakpoints... 0:000> g (8e8.ea4): CLR notification exception - code e0444143 (first chance) JITTED Ext1!Ext1.Program.Main(System.String[]) Setting breakpoint: bp 00280067 [Ext1.Program.Main(System.String[])] Breakpoint 0 hit eax=00280050 ebx=003af554 ecx=027f2254 edx=00000001 esi=00000000 edi=003af4c0 eip=00280067 esp=003af4a0 ebp=003af4a8 iopl=0 nv up ei pl zr na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246 00280067 90 nop 0:000> !name2ee Ext1.exe Ext1.Program.Main Module: 00202e94 Assembly: Ext1.exe Token: 06000003 MethodDesc: 002037ac Name: Ext1.Program.Main(System.String[]) JITTED Code Address: 00280050 0:000> !u 00280050 Normal JIT generated code Ext1.Program.Main(System.String[]) Begin 00280050, size 3b d:\Code\Ext1\Ext1\Program.cs @ 18: >>> 00280050 55 push ebp 00280051 8bec mov ebp,esp 00280053 83ec08 sub esp,8 00280056 894dfc mov dword ptr [ebp-4],ecx 00280059 833d6031200000 cmp dword ptr ds:[203160h],0 00280060 7405 je 00280067 00280062 e84d704670 call clr!GetHistoryFileDirectory+0x8786f (706e70b4) (JitHelp: CORINFO_HELP_DBG_IS_JUST_MY_CODE) 00280067 90 nop d:\Code\Ext1\Ext1\Program.cs @ 19: 00280068 ff159c372000 call dword ptr ds:[20379Ch] (Ext1.Program.M1(), mdToken: 06000001) 0028006e 90 nop d:\Code\Ext1\Ext1\Program.cs @ 20: *** WARNING: Unable to verify checksum for C:\Windows\assembly\NativeImages_v4.0.30319_32\mscorlib\51e2934144ba15628ba5a31be2dae7dc\mscorlib.ni.dll *** ERROR: Module load completed but symbols could not be loaded for C:\Windows\assembly\NativeImages_v4.0.30319_32\mscorlib\51e2934144ba15628ba5a31be2dae7dc\mscorlib.ni.dll 0028006f e84852ae6f call mscorlib_ni+0x9b52bc (6fd652bc) (System.Console.Read(), mdToken: 06000983) 00280074 8945f8 mov dword ptr [ebp-8],eax 00280077 90 nop d:\Code\Ext1\Ext1\Program.cs @ 21: 00280078 ff159c372000 call dword ptr ds:[20379Ch] (Ext1.Program.M1(), mdToken: 06000001) 0028007e 90 nop d:\Code\Ext1\Ext1\Program.cs @ 22: 0028007f ff15a8372000 call dword ptr ds:[2037A8h] (Ext1.Program.M2(), mdToken: 06000002) 00280085 90 nop d:\Code\Ext1\Ext1\Program.cs @ 23: 00280086 90 nop 00280087 8be5 mov esp,ebp 00280089 5d pop ebp 0028008a c3 ret |
4.2 控制线程和进程
前面讲到command窗口输入命令的地方,左边有个X:Y格式的消息显示,X和Y分别代表当前调试的进程ID和线程ID。因为有许多命令都是跟当前调试的进程和线程线程相关,如!clrstack,!dumpstack等。所以有时有需求切换当前进程,切换可以通过Process and Thread窗口实现(根据需要选择要切换的进程或进程):
或者通过命令,“| s”和“~ s”分别用来切换进程和线程:
4.3 查看线程
通过“!threads”命令可以查看当前进程的所有托管线程的简要信息:
命令输出信息首先是所有托管线程的一个概要信息,从这部分信息里面就能看出线程是不是是不是正常。紧接着是表格式的输出每个托管线程的概要信息,第一列没有title,这个是Windbg调试器维护的线程ID,切换线程命令或当前线程信息等都是指的这列所代表的值;ID这一列就是ManagedThreadId属性值;OSID指的对应的系统线程ID;ThreadOBJ指非托管线程结构对象的地址,这个值有点鸡肋,因为是非托管对象地址,不能直接通过!do查看这个线程对象的详细信息;State指线程的当前状态,这个值看不懂没关系,SOS提供了!threadstate命令帮助理解,如下表Table1;GC Mode为Preemptive的时候表明当前线程执行的位置是非托管代码,同时也表明GC可以随时提高该线程的优先级(唤醒)或者回收该线程,当值为Cooperative表明当前线程执行中断的位置是停在托管代码的地方,这个时候GC也会等待当前线程完成它的工作,才能有所作为;GC Alloc Context在该线程分配对象的时候可能会用到,这个在后面再细讲;Domain指所处的域,可以通过!dumpdomain,查看域相关信息,如下表Table2;Lock Count表明线程占据了多少托管锁;Apt表明线程是MTA模式还是STA模式,同时可以使用!comstate可以打印出所有线程的com apartment模式,如下表Table3,Ukn表示Unknow,非托管线程会显示值为Ukn;Exception表明当前线程最后抛出的托管类型的Exception。
Table1:查看线程状态 |
0:004> !threadstate 2a020 Legal to Join CoInitialized In Multi Threaded Apartment Fully initialized |
Table2:查看域信息 |
0:000> !dumpdomain 005b5fe0 -------------------------------------- Domain 1: 005b5fe0 LowFrequencyHeap: 005b6434 HighFrequencyHeap: 005b647c StubHeap: 005b64c4 Stage: OPEN SecurityDescriptor: 005b7bd0 Name: Ext1.exe Assembly: 005f8968 [C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll] ClassLoader: 005fc240 SecurityDescriptor: 005f88d0 Module Name 6def1000 C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll Assembly: 00603bf0 [D:\Code\Ext1\Ext1\bin\Debug\Ext1.exe] ClassLoader: 00603cf0 SecurityDescriptor: 005feac8 Module Name 00142e94 D:\Code\Ext1\Ext1\bin\Debug\Ext1.exe |
Table3:查看Com Apartment Mode |
0:000> !comstate ID TEB APT APTId CallerTID Context 0 fdc 7efdd000 MTA 0 0 00704fc0 1 9b0 7efda000 Ukn 2 bdc 7efd7000 MTA 0 0 00704fc0 3 aa8 7ef9f000 Ukn |
4.4 查看线程栈
查看托管代码调用堆栈可以使用命令!clrstack,使用参数 -p -l分别附带显示参数和局部变量信息,-a参数是表示显示参数和局部变量信息。!clrstack只会打印出当前线程的调用堆栈,使用标准命令辅助 ~*e !clrstack会打印出所有线程的堆栈信息。
0:000> !clrstack OS Thread Id: 0xfdc (0) Child SP IP Call Site 0037ed6c 003b00a0 Ext1.Program.M1() [d:\Code\Ext1\Ext1\Program.cs @ 8] 0037ed70 003b007e Ext1.Program.Main(System.String[]) [d:\Code\Ext1\Ext1\Program.cs @ 21] 0037ef04 6fb22652 [GCFrame: 0037ef04] |
查看托管代码和非托管代码的调用堆栈信息使用命令!dumpstack,由于信息太多,就没有全部复制出来:
0:000> !dumpstack OS Thread Id: 0xfdc (0) Current frame: (MethodDesc 00143794 +0 Ext1.Program.M1()) ChildEBP RetAddr Caller, Callee 0037ed68 003b007e (MethodDesc 001437ac +0x2e Ext1.Program.Main(System.String[])), calling (MethodDesc 00143794 +0 Ext1.Program.M1()) 0037ed78 6fb22652 clr!CallDescrWorkerInternal+0x34 0037ed84 6fb3264f clr!CallDescrWorkerWithHandler+0x6b, calling clr!CallDescrWorkerInternal 0037ed98 6fb32608 clr!CallDescrWorkerWithHandler+0x20, calling clr!_alloca_probe ... |
同样!dumpstack命令只会打印当前线程的堆栈信息,要想打印所有的线程的堆栈信息,同样可以使用标准命令辅助~*e !dumpstack。但是这个命令会打印出所有线程的堆栈信息,如果程序使用的线程比较多的时候,打印出来的信息往往冗长有余。如果仅仅是需要打印出托管线程的托管代码和非托管代码的堆栈信息,可以使用命令!eestack:
0:000> !eestack --------------------------------------------- Thread 0 Current frame: (MethodDesc 00143794 +0 Ext1.Program.M1()) ChildEBP RetAddr Caller, Callee 0037ed68 003b007e (MethodDesc 001437ac +0x2e Ext1.Program.Main(System.String[])), calling (MethodDesc 00143794 +0 Ext1.Program.M1()) 0037ed78 6fb22652 clr!CallDescrWorkerInternal+0x34 0037ed84 6fb3264f clr!CallDescrWorkerWithHandler+0x6b, calling clr!CallDescrWorkerInternal ... --------------------------------------------- Thread 2 Current frame: ntdll!ZwWaitForMultipleObjects+0x15 ChildEBP RetAddr Caller, Callee ... |
4.5 反编译
反汇编的命令有标准命令u或者扩展命令!u,对于net程序来说!u命令打印出来的汇编语言会默认相应打印出源代码的文件位置和行号,对于看不到源代码的程序并且是为了静态分析这段汇编程序的人来,这多出来的源代码文件位置和行号无任何意义,但是我们可以根据出问题的callstack的行号信息和和!u打印出来的行号信息进行对比分析,也是能分析出一些蛛丝马迹出来。当然!u的使用不止这个好处,!u支持的参数更方便反汇编net程序,参数可以是托管代码的虚拟地址或者方法描述符地址。!u不仅支持打印源代码的文件位置和行号,通过 -gcinfo参数会对应多打印出一些GC信息,参数-ehinfo会对应多打印出代码中exception相关的中的信息:
0:000> u 00143794 00143794 0100 add dword ptr [eax],eax 00143796 0021 add byte ptr [ecx],ah 00143798 05002800a0 add eax,0A0002800h 0014379d 003b add byte ptr [ebx],bh 0014379f 0002 add byte ptr [edx],al 001437a1 0003 add byte ptr [ebx],al 001437a3 2006 and byte ptr [esi],al 001437a5 0028 add byte ptr [eax],ch 0:000> !u -gcinfo 00143794 Normal JIT generated code Ext1.Program.M1() Begin 003b00a0, size 21 d:\Code\Ext1\Ext1\Program.cs @ 8: 003b00a0 55 push ebp 003b00a1 8bec mov ebp,esp 003b00a3 833d6031140000 cmp dword ptr ds:[143160h],0 003b00aa 7405 je 003b00b1 003b00ac e80370a06f call clr!JIT_DbgIsJustMyCode (6fdb70b4) 003b00b1 90 nop d:\Code\Ext1\Ext1\Program.cs @ 9: 003b00b2 8b0d30215503 mov ecx,dword ptr ds:[3552130h] ("M1") 0018 reg ECX becoming live 003b00b8 e833d3f467 call mscorlib_ni+0x36d3f0 (682fd3f0) (System.Console.WriteLine(System.String), mdToken: 06000992) 001D reg ECX becoming dead 003b00bd 90 nop d:\Code\Ext1\Ext1\Program.cs @ 10: 003b00be 90 nop 003b00bf 5d pop ebp 003b00c0 c3 ret |
对于笔者这种菜鸟来说,反汇编如同鸡肋一般,因为我没那个耐心去分析大段的汇编程序,我最多看下代码中怎么处理exception的信息。如果读者也不喜欢看汇编的话,还有个命令适合分析代码,就是!dumpil,这个命令会打印出IL:
0:000> !dumpil 00143794 ilAddr = 00b620d0 IL_0000: nop IL_0001: ldstr "M1" IL_0006: call System.Console::WriteLine IL_000b: nop IL_000c: ret |
使用WinDbg —— .NET篇 (二)相关推荐
- 【SSRS】入门篇(二) -- 建立数据源
原文:[SSRS]入门篇(二) -- 建立数据源 通过 [SSRS]入门篇(一) -- 创建SSRS项目 这篇,我们建立了一个SSRS项目: 接下来,我们以 AdventureWorks2012 示例 ...
- 《高性能javascript》 领悟随笔之-------DOM编程篇(二)
<高性能javascript> 领悟随笔之-------DOM编程篇二 序:在javaSctipt中,ECMASCRIPT规定了它的语法,BOM实现了页面与浏览器的交互,而DOM则承载着整 ...
- mysql 基础篇(二) 账号、权限管理
mysql 基础篇(二) 账号.权限管理.备份与还原 建立账号密码: Grant all on test.* to "cj"@"localhost" ident ...
- 运动控制器编程_快速入门 | 篇二十一:运动控制器ZHMI组态编程简介一
点击上方"正运动小助手",随时关注新动态! 运动控制器ZHMI组态编程简介一 今天我们来学习一下,运动控制器的ZHMI组态编程简介.本文主要从产品概述.控制器连接触摸屏使用.HM ...
- 在java中重写方法应遵循规则的包括_Java面试题集合篇二
Java面试题之Java集合篇二1.遍历一个List有哪些不同的方式? List<String> strList = new ArrayList<>(); //使用for-ea ...
- 算法之数论应用篇(二)
算法之数论应用篇二 最大公约数 线性筛 Hankson的趣味题 欧拉函数 前言 可见的点(数学知识+欧拉函数) 最大公约数(可见的点扩展) 同余 取模的性质 定义 基本性质 运算规则 重要定理 重要定 ...
- 一台电脑怎么接两个显示器_电脑数码类目显示器 篇二:11.11抄作业,个人消费级显示器怎么选--20款好价显示器推荐_显示器...
2020-11-09 21:56:2572点赞390收藏91评论 想攒一台电竞主机.家用主机.酷炫主机无从下手?想省钱又怕性能不达标?值得买帮你打造定制化DIY装机工具,自助全网比价装机,提供最适合的 ...
- 【word2vec】篇二:基于Hierarchical Softmax的 CBOW 模型和 Skip-gram 模型
文章目录 CBOW 模型 基本结构 目标函数 梯度计算 Skip-gram 模型 基本结构 梯度计算 优缺点分析 系列文章: [word2vec]篇一:理解词向量.CBOW与Skip-Gram等知识 ...
- php redis微信发红包,高阶篇二 使用Redis队列发送微信模版消息
# 高阶篇二 使用Redis队列发送微信模版消息 > 此命令行执行任务的方法类比较复杂 他需要命令行运行才会有效 > 命令行源码以及创建方法 参见上节 https://www.kanclo ...
最新文章
- b样条曲面绘制 opengl_3dmax在曲面上如何绘制样条线,都在这里了
- 脑电传感器并不复杂,那精度呢?
- 使用fis优化web站点
- sklearn 笔记:make_blobs 生成聚类数据
- 细说Vue作用域插槽,匹配应用场景。
- 工程之道,深度学习的工业级模型量化实战
- POJ2527(两多项式取余)
- struts1,struts2,springMVC对比
- python OCR 图形识别
- Wireshark 抓包
- cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration的解决
- 全局Angular CLI版本大于本地版本
- 如何计算CRC循环校验码示例
- LaTeX安装环境和软件下载地址
- 山东理工大学ACM平台题答案关于C语言 1580 闰年
- unbalanced calls to begin/end appearance transitions for uiviewcontroller的解决方法
- (Spring+SpringMVC+mybatis)SSM选课管理系统/课程管理系统 完整项目介绍
- uva1594 水题
- 正态后验分布的MCMC方法
- 1758:二叉树——结点关系
热门文章
- STL之Vector容器
- ArcGIS如何使用菜单栏的快捷键
- 【PTA竞赛题集】刷题记录 7-22~7-31(更新中……)
- yy软件测试岗位笔试题目,YY运营专员笔试题目
- elementui自定义日历,有查询框查询日历的每月
- oracle一个区有几个块,Oracle段(segment) 区(extent) 块(block)
- 电大HTML形考作业,2018年电大心理学形考作业一二三答案及终结性考核答案
- Qt 中 Enter 键的捕获
- 计算机方面的英语杂志,哪种计算机英文杂志见刊快?
- 在springboot项目中如何设计UrlFilter过滤器