编写windbg调试器扩展 入门篇2

来源:互联网 发布:直销软件开发价格 编辑:程序博客网 时间:2024/05/22 04:30

    前面一篇是用sources和nmake组合编译生成调试器扩展,步骤比较繁琐,我相信读者应该更倾向于用IDE来编写代码。本篇有2个主题:1.将前面的代码移植到VS上,用IDE编译;2.调试生成的扩展命令。

1.移植代码到IDE

    这部分相对简单,所以放在开头。要用IDE代替nmake编译调试器扩展,只要把sources文件中的编译/链接选项复制到VS对应的选项中就可以了。

1.1.设置编译项:

    工程属性-C/C++-常规-附加包含目录中添加头文件的路径:C:\WinDDK\7600.16385.1\Debuggers\sdk\inc

1.2.设置链接项:

工程属性-链接器-输入-附加依赖项中添加库文件的路径:C:\WinDDK\7600.16385.1\Debuggers\sdk\lib\$(ARCH)\dbgeng.lib。对于运行在不同架构的调试器扩展要使用不同的ARCH,我的调试器扩展用于调试x86的程序,因此最终路径为:C:\WinDDK\7600.16385.1\Debuggers\sdk\lib\i386\dbgeng.lib.

上面的截图中"将模块添加到程序集",我在这里直接将exts/目录下的windbgExt.def文件添加进来。当然,你也可以不添加这项,直接在代码中声明导出函数即可。怎么选择取决于个人~

2.调试调试扩展

    写程序难免会出bug,出了bug就得通过调试器定位/解决。平时,我们都是用调试器附加到有问题的程序中调试代码;现在情况变了:windbg在加载扩展命令后变得岌岌可危,如何应对新问题?其实很简单:另起炉灶,新开一个windbg实例,attach到加载了扩展命令的有问题的windbg实例上,就能把新问题变成与调试普通代码一样了。扩展命令本身是Dll程序,通过windbg调用LoadLibrary加载,因此,调试扩展命令可以再细分为两种类型:1.调试Dll入口函数;2.调试其他导出函数,下面仍以demo程序dbgexts.dll为例分类讨论。为了加以区分,我们先做如下约定:加载扩展命令的windbg叫做调试器A,调试有问题的windbg的windbg叫做调试器B。

2.1.调试扩展命令入口函数

    在调试器A加载调试器扩展前,先运行调试器B,并使调试器B attach调试器A上。然后在调试器B中启用加载Dll事件,这样一旦调试器A加载了扩展命令dbgexts,调试器B就会捕捉到调试事件并中断。
以下输出来源于调试器B:
0:002> |.        ;查看当前进程.  0id: 2324attachname: C:\Users\Administrator\Desktop\DevTools\windbg v10\x86\windbg.exe0:002> sxe ld dbgexts    ;启用Dll加载事件0:007> lm        ;查看调试器A中已加载的模块(至少没加载dbgexts.dll)start    end        module name012a0000 01331000   windbg     (pdb symbols)          C:\Users\Administrator\Desktop\DevTools\windbg v10\x86\sym\windbg.pdb\CC6E30603ED243FBB418BC2ED0F2FDC71\windbg.pdb60d60000 6113b000   ext        (deferred)             61d40000 621bc000   dbgeng     (deferred)             64f60000 6509e000   dbghelp    (deferred)             67050000 67109000   exts       (deferred)...      
以下输出来源于调试器A:
0:004> .chainExtension DLL chain:    dbghelp: image 10.0.10586.15, API 10.0.6, built Fri Nov 20 12:39:22 2015        [path: C:\Users\Administrator\Desktop\DevTools\windbg v10\x86\dbghelp.dll]    ext: image 10.0.10586.15, API 1.0.0, built Fri Nov 20 12:39:52 2015        [path: C:\Users\Administrator\Desktop\DevTools\windbg v10\x86\winext\ext.dll]    exts: image 10.0.10586.15, API 1.0.0, built Fri Nov 20 12:39:08 2015        [path: C:\Users\Administrator\Desktop\DevTools\windbg v10\x86\WINXP\exts.dll]    uext: image 10.0.10586.15, API 1.0.0, built Fri Nov 20 12:38:53 2015        [path: C:\Users\Administrator\Desktop\DevTools\windbg v10\x86\winext\uext.dll]    ntsdexts: image 10.0.10586.15, API 1.0.0, built Fri Nov 20 13:08:00 2015        [path: C:\Users\Administrator\Desktop\DevTools\windbg v10\x86\WINXP\ntsdexts.dll]
从上面的输出可以看到目前调试器A尚未加载调试器扩展dbgExts.dll。
    调试器A一旦执行了.load命令,调试器B就会中断。这是加载符号,设置断点的好时机:
以下输出来源于调试器B:
0:001> .sympath+ C:\WinDDK\7600.16385.1\Debuggers\sdk\samples\exts\objchk_win7_x86\i386Symbol search path is: SRV*;C:\Users\Administrator\Desktop\studio\windbgExt\Debug;0:001> .reloadReloading current modules.....................................................0:001> bl 0 e 71981898     0001 (0001)  0:**** dbgexts!DebugExtensionInitialize+0x8
根据网上的资料介绍,调试器扩展的初始化函数原型为:
HRESULTCALLBACKDebugExtensionInitialize(PULONG Version, PULONG Flags)
于是我在这下了断点,并等待中断,按下F5以后很快就会中断到这个函数。

再次F5,调试器A才会从.load命令中返回。
以下输出来源于调试器A:
0:004> .load C:\WinDDK\7600.16385.1\Debuggers\sdk\samples\exts\objchk_win7_x86\i386\dbgexts.dllExtension dll detected a break connected to X8600 01c9fb64 7763ec87 ntdll!DbgBreakPoint0:004> .chainExtension DLL chain:    C:\WinDDK\7600.16385.1\Debuggers\sdk\samples\exts\objchk_win7_x86\i386\dbgexts.dll: image 6.1.7600.16385, API 1.0.0, built Wed Aug 09 23:24:43 2017        [path: C:\WinDDK\7600.16385.1\Debuggers\sdk\samples\exts\objchk_win7_x86\i386\dbgexts.dll]    dbghelp: image 10.0.10586.15, API 10.0.6, built Fri Nov 20 12:39:22 2015        [path: C:\Users\Administrator\Desktop\DevTools\windbg v10\x86\dbghelp.dll]    ext: image 10.0.10586.15, API 1.0.0, built Fri Nov 20 12:39:52 2015
对比前面调试器A运行.chain的输出,可以看到现在调试器A已经加载了dbgexts扩展。当然,这也可以从调试器B中获得信息:
以下输出来源于调试器B:
0:003> lmlstart    end        module name012a0000 01331000   windbg     (pdb symbols)          C:\Users\Administrator\Desktop...71980000 71989000   dbgexts    (private pdb symbols)  C:\Users\Administrator\Desktop\DevTools\windbg v10\x86\sym\dbgexts.pdb\C92C6D4B2699410CB2A62310F29351D41\dbgexts.pdb

2.2.调试其他导出函数

    调试自定义导出函数相对简单,前面已经加载了调试符号,只要在相应函数入口加断点即可,这里不再赘述。

原创粉丝点击