使用WinDbg调试.NET代码

        在开发以.NET编程的软件经常会需要调试,一般的使用VS来调试就可以了。但有时你会发现你没有安装VS,或者有些问题用VS不好看出问题,这是就可以选择WinDBG。下面列出一些经常用到的命令。

一、 有两种方式可以挂上被调试程序:

1、使用WinDBG直接打开可运行程序(Ctrl+E)

这时WinDBG还没有加载mscorwks.dll,不能加载SOS.DLL。需要使用命令

        sxe ld:mscorwks                        //这命令是再加载了mscorwks后WinDBG会断下来,这样就有机会加载SOS。       

2、使用WinDBG直接挂上被调试程序(F6)

使用lmm  mscorwks命令看是否加载了mscorwks,如果没有加载就使用按照上面方式做

再就是加载SOS.DLL,使用命令格式如下:

.load  <full path to sos.dll>         //使用这个命令自己指定和.NET匹配的SOS

.loadby sos mscorwks                  //使用这个命令根据已加载的mscorwks来确定并加载SOS

可以使用.chain开查看加载的SOS

 

注意:使用方式1的直接运行程序,加载过SOS后直接使用!bpmd到设置断点到Main方法好像不行,反正我是试过是这样,不知道其他人是否也是如此,下面就是我输入的,但是好像我直接跑的话是不会停的。

        0:000> !bpmd certexport certexport.Program.main
        Adding pending breakpoints...

 

对于这情况我一般使用如下方法:

bp mscorwks!Assembly::GetEntryPoint,这个地方返回的是EntryPoint对于的MethodDesc pointer。

0:000> bp mscorwks!Assembly::GetEntryPoint                  //1、设置断点
0:000> g
Breakpoint 1 hit
eax=0014f57c ebx=00000000 ecx=002d7e18 edx=0000000d esi=00000200 edi=00000000
eip=706fe154 esp=0014f55c ebp=0014f7b0 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
mscorwks!Assembly::GetEntryPoint:
706fe154 682c020000      push    22Ch


0:000> gu                                                                                              //2、执行到这个函数返回,它返回的是EntryPoint对应的MD
eax=00242ff4 ebx=00000000 ecx=706fe241 edx=80000001 esi=00000200 edi=00000000
eip=706b0b48 esp=0014f560 ebp=0014f7b0 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
mscorwks!Assembly::ExecuteMainMethod+0x89:
706b0b48 8bf0            mov     esi,eax

0:000> r eax                                                                                        //3、eax中存的就是EntryPoint对应的MD,这里是方法Main
eax=00242ff4                                                                                     //可以使用命令!bpmd –md 00242ff4在Main方法处下断点。

下面可以看看00242ff4是否对应的是Main函数的MethodDesc Pointer


0:000> !name2ee CertExport CertExport.Program
Module: 00242c5c (CertExport.exe)
Token: 0x02000002
MethodTable: 00243008
EEClass: 002413a0
Name: CertExport.Program


0:000> !dumpmt -md 00243008
EEClass: 002413a0
Module: 00242c5c
Name: CertExport.Program
mdToken: 02000002  (E:\study_Prj\CertExport\CertExport\bin\Debug\CertExport.exe)
BaseSize: 0xc
ComponentSize: 0x0
Number of IFaces in IFaceMap: 0
Slots in VTable: 6
--------------------------------------
MethodDesc Table
   Entry MethodDesc      JIT Name
6fa06a90   6f881248   PreJIT System.Object.ToString()
6fa06ab0   6f881250   PreJIT System.Object.Equals(System.Object)
6fa06b20   6f881280   PreJIT System.Object.GetHashCode()
6fa774c0   6f8812a4   PreJIT System.Object.Finalize()
0024c015   00243000     NONE CertExport.Program..ctor()
0024c011   00242ff4     NONE CertExport.Program.Main(System.String[])

 

二、常用命令

1、设置断点

!bpmd
Usage: !bpmd -md <MethodDesc pointer>
Usage: !bpmd <module name> <managed function name>

如:

待续........

原文地址:https://www.cnblogs.com/Quincy/p/1787732.html