资源介绍
WinDbg是微软开发的免费源码级调试工具。Windbg可以用于Kernel模式调试和用户模式调试,还可以调试Dump文件。在DotNet方面WinDbg是调试分析SSCLI的最佳工具,同时可以和SOS扩展一起调试分析.net程序。最近一段时间项目需要学习了一下,有感于WinDbg功能的强大。学习的过程并不一帆风顺,WinDbg自带的英文文档大而泛,网上资料也比较少,而WinDbg Not an ABBA Song。现在总算是入了点门,也收集了一些很好的资料,整理成一个CHM方便大家学习,时间仓促,整理得比较粗糙,大家凑合着看。这些文章均来自网络,版权归原作者所有。
1. 默认表达式类型是MASM.
2. 你能使用.expr 改变默认类型(详见WINDOWS调试工具帮助文件)。
3. 某些命令总是使用C++的方式求值。
4. 一个特殊的表达式(或表达式的一部分)的赋值能通过前缀“@@”改成与一般表达式相反的方向。
这个摘要相当棘手,你应该参考WINDOWS调试工具帮助文件中的“Evaluating Expressions”。现在,这里有一些例子,给你一些关于赋值是如何工作的概念。
你之前已经停止在Sioctl!SioctlDeviceControl+0x103,所以使用dv 查看一个已知变量(查看dv 命令以获得更多信息):
kd> dv Irp
Irp = 0xff70fbc0
该响应的意思是,Irp 变量包含0xFF70FBC0。更多地,dv 解释C++语法中的参数。该响应基于变量内容,而不是地址。你可以确认它:
kd> ?? Irp
struct _IRP * 0xff70fbc0
?? 总是以C++ 为基础(详见??命令)。假如使用MASM类型的赋值,尝试? (详见 ? 命令):
kd> ? Irp
Evaluate expression: -141181880 = f795bc48
这表示变量Irp 位于0XF795BC48。你可以通过使用dd (详见 dd 命令)显示内存数据,确认该变量真的包含数据0xFF70FBC0。
kd> dd f795bc48 l1
f795bc48 ff70fbc0
以及内存指向这里:
kd> dd 0xff70fbc0
ff70fbc0 00940006 00000000 00000070 ff660c30
ff70fbd0 ff70fbd0 ff70fbd0 00000000 00000000
ff70fbe0 01010001 04000000 0006fdc0 00000000
ff70fbf0 00000000 00000000 00000000 04008f20
ff70fc00 00000000 00000000 00000000 00000000
ff70fc10 ff73f4d8 00000000 00000000 00000000
ff70fc20 ff70fc30 ffb05b90 00000000 00000000
ff70fc30 0005000e 00000064 0000003c 9c402408
查看象IRP这样的变量,正如dt 显示(详见dt 命令),Type和Size成员有一个似是而非的数据 :
kd> dt Irp
Local var @ 0xf795bc48 Type _IRP*
0xff70fbc0
+0x000 Type : 6
+0x002 Size : 0x94
+0x004 MdlAddress : (null)
+0x008 Flags : 0x70
+0x00c AssociatedIrp : __unnamed
+0x010 ThreadListEntry : _LIST_ENTRY [ 0xff70fbd0 - 0xff70fbd0 ]
+0x018 IoStatus : _IO_STATUS_BLOCK
+0x020 RequestorMode : 1 ''
+0x021 PendingReturned : 0 ''
+0x022 StackCount : 1 ''
+0x023 CurrentLocation : 1 ''
+0x024 Cancel : 0 ''
+0x025 CancelIrql : 0 ''
+0x026 ApcEnvironment : 0 ''
+0x027 AllocationFlags : 0x4 ''
+0x028 UserIosb : 0x0006fdc0
+0x02c UserEvent : (null)
+0x030 Overlay : __unnamed
+0x038 CancelRoutine : (null)
+0x03c UserBuffer : 0x04008f20
+0x040 Tail : __unnamed
有时,你会希望使用C++ 赋值代替MASM表达式。“@@” 前缀会完成它。扩展命令总是使用象MASM表达式一样的参数,当你使用扩展命令!irp (详见 IRPs),你能看到@@的效果。
kd> !irp @@(Irp)
Irp is active with 1 stacks 1 is current (= 0xff70fc30)
No Mdl System buffer = ff660c30 Thread ff73f4d8: Irp stack trace.
cmd flg cl Device File Completion-Context
>[ e, 0] 5 0 82361348 ffb05b90 00000000-00000000
\Driver\SIoctl
Args: 00000064 0000003c 9c402408 00000000
重复这个操作,不在上述的 Irp 变量中带@@ 前缀,!irp 将会使用变量的地址,而不是变量的值。为了使这更加具体,如果变量位于0xF795BC48,它包含的数据是0xFF70FBC0,使用!irp Irp 代替@@(Irp)将会请求WinDbg 格式化位于0xF795BC48的IRP stack。
你需要进一步了解的是:@@前缀相当通用,正如它的正式意思,使用不同于当前表达式中正在使用的赋值方法。如果大部分表达式是MASM,@@代表C++,如果它是C++,@@代表MASM。
最后一点建议:如果表达式不如你期望那样工作,考虑你是否在请求调试器理解MASM或者C++语法。
显示和设置内存,变量,寄存器等等
有一些方法可以显示和改变它们。
• 在当前例程中显示一个变量(当前的“scope”),使用dv (“Display Variables”)。例如,如果停止在Sioctl!SioctlDeviceControl+0x103:
kd> dv
DeviceObject = 0x82361348
Irp = 0xff70fbc0
outBufLength = 0x64
buffer = 0x00000000 ""
irpSp = 0xff70fc30
data = 0xf886b0c0 "This String is from Device Driver !!!"
ntStatus = 0
mdl = 0x00000000