1.启动1)直接调试: gdb program [core]cdb program or cdb -z DumpFile2)attach方式gdb attach pidcdb -pn ExeName or cdb -p pid2.显示堆栈GDB: btCDB: k
堆栈命令堆栈命令都是K开头
k 使用K命令进行栈回溯
kL 和上面一样,只是省略了源代码段 L 一定要大写
kb L 还是回溯,显示前3个参数(只是机械的按ebp+8,ebp+0xC,ebp+0x10取三字值,不判断),L意思和上面一样。
kp;kP 把参数和参数值都以函数原型的格式显示出来。P大写表示参数占用一行。
kv 在kb的基础上增加显示FPO(栈指针省略)
kn 显示序号。
kn f 可以知道相邻栈帧的距离。(也就是看上父函数使用了多少栈空间,适用于检测栈溢出)
观察栈变量
dv 观察栈上的局部变量 dv /i/t/V 表示格式
.frame <栈帧序号> 切换栈帧
du 观察特定值。 例如 du ebp-4
!for_each_local 枚举当前所有的局部变量
!for_each_frame dv 切换到所有栈帧,并显示局部变量
3. 设置断点GDB: b [file:]lineCDB: bp 'file:line'4. 运行/继续运行GDB: run [arglist] c 继续运行 CDB: g5. 单步GDB : n (step over) s (step into)CDB : p6. 打印变量的值GDB : p exprCDB: ? expr说老实话,CDB过于复杂,学起来比GDB难.BTW:用CDB之前设置一下symbol的pathset _NT_SYMBOL_PATH=srv*c:/symbols*http://msdl.microsoft.com/download/symbols
运用Windbg进行内核调试, 熟练的运用命令行是必不可少的技能. 但是面对众多繁琐的命令, 实在是不可能全部的了解和掌握. 而了解Kernel正是需要这些命令的指引, 不断深入理解其基本的内容. 下面, 将介绍最常用的一些指令, 使初学Kernel调试的朋友们能有一个大致的了解. 至于如何熟练的运用它们, 还需要实际的操作过程中进行反复的琢磨.Windbg能够方便的进行远程调试和本地进程调试(只限于User模式), 远程调试又分User mode和Kernel mode两种. 个人认为用Windbg进行远程的User mode调试还不如用Visual Studio来的方便, 毕竟要一些相应的配置才行, 而Visual Studio只需要远程机器的IP地址即可.(当然, 如果你在LiveCD或WinPE下进行User mode的调试, 这时候没有VS, Windbg就是不二之选了). Windbg的优势就在于远程的Kernel模式的调试, 这是VS所做不到的.1. 首先是设置符号路径(无论在User mode下还是Kernel mode下都需要), 在Windbg的符号路径对话框中, 输入以下符号路径: srv*c:/symbols*http://msdl.microsoft.com/download/symbols这个符号路径是自动在微软给定的symbols路径下进行自动搜索, 一些常用的符号都可以利用这个链接自动找到. 当然, 如果你的本地已经有相应的符号路径, 包含本地的也可以.2. 等Windbg的联机状态设置好后, 按下Ctrl+break, 中断当前的Kernel状态, 在Windbg的命令行窗口输入"?", 则会输出帮助菜单, 在这个Menu中会显示一些常用的命令: (1)断点指令
B[C|D|E] [<bps>] clear|disable|enable breakpoints BL list breakpoints BP <address> set soft breakpoints BA <access> <size> <addr> break on access (2)数据查看指令 D[type][<range>] dump memory DT [-n|y] [[mod!]name] [[-n|y]fields][address] [-l list] [-a[]|c|i|o|r[#]|v] dump using type information DV [<name>] dump local variables 分析内存d系列命令用来显示指定地址的内存区域
d {a | b | c | d | D | f | p | q | u | w | W} [Options] [Range]
dy {b | d} [Options] [Range]
d [Options] [Range]
//大括号内为显示方式 a ASCII b 字节和ASCII码 c DWORD和ASCII码 d 表示DWORD
D 双精度浮点数
f 单精度浮点数
p 表示按指针宽度显示
q 4字(8字节)
u UNICODE字符
w 字
W 字和ASCII码
yb 二进制和字节
yd 二进制和双字
Range 指定要显示的内存范围
1. 例如: dd 0012fd9c 0012fda8
用DWORD表示0012fd9c 到0012fda8之间的内存
2. dd 0012fd9c L4
用DWORD表示0012fd9c后的4个DWORD
3. dd 0012fda8 L-4
0012fda8是结束地址,显示在他前面的内存
显示字符串
以0结尾的字符串可以使用
da 适用单字节字符集
du 适用UNICODE字符集
UNICODE_STRING
dt _UNICODE_STRING = dS
ds 显示(STRING)
显示数据类型
dt 按指定数据类型来显示内存中的数据
dt [模块名!] 类型名
* 类型名可以用通配符
-b 递归显示所有子类型
-r 指定显示深度 -r0 不显示子类型 -r1显示1级子类型
-ny 附加搜索选项,显示某些字段
(3)数据修改指令 E[type] <address> [<values>] enter memory values (4)运行 G[H|N] [=<address> [<address>...]] go P [=<addr>] [<value>] step over (5)堆栈操作 K[b|p|P|v] (6)显示加载的模块列表 LM list modules (7)寄存器操作 R [[<reg> [= <expr>]]] view or set registers (8)Search指令 S[<opts>] <range> <values> search memory (9)跟踪指令T,TA,TB,TC,WT,P,PA,PC (10)退出 Q (11)反汇编 U[<range>]其中最常用的就是反汇编操作和显示模块操作. LM命令显示当前加载的模块. 当你连接过程中, Windbg提示相应的module找不到时, 就可以运用这个命令进行查看. LM的一个扩展命令是"lm t n", 这个命令显示当前所有加载的驱动信息(过去的命令是!driver),在调试内核驱动的过程中非常有用,可以找到相应驱动的起始地址。反汇编命令u, 可以在相应的地址中逐步的解析代码,这在内核调试中是最常用的一种查看代码的方式。 除上面的一些基本命令之外,还有一些非常有用的指令: (1)K[KB|KP] 显示当前的堆栈,当然也可以用alt+6直接调出窗口显示 (2)!process 显示当前的进程EXPROCESS状态,!process 0 0 显示所有的进程状态 (3)!thread 显示当前的线程状态,dt nt!_ethread显示ETHREAD结构 (4)!drvobj [path] 列出当前的驱动程序在驱动对象中的例程,其中path是驱动的设备路径,例如: !drvobj /filesystem/fat 2 列出FAT文件系统驱动的例程 (5)dt nt!_* 查看内核的数据结构 (6)!stack 0 显示线程当前地址 (7)!ioapic 查看I/O的中断控制器 (8)!irql 查看CPU的IRQL,这在CPU中断调试中非常有用 (9)!exqueue 可以看系统辅助的线程列表 (10)!reg viewlist 注册表的存储显示,!reg hivelist显示注册表一个存储的内存使用量 (11)!vm 显示系统的内存池信息 (12)dt _TOKEN 显示内部访问令牌 (13)!object /device 显示设备对象信息,用winobj工具也可以看到以上命令是一些常用的内核调试命令, 还有非常多的命令技巧, 不可能全部一一解释. 在今后的文章, 还会结合具体的调试过程分析进行逐步介绍. 内核的调试无非是处理器, 系统设备, 内存, 进程线程, 注册表, 驱动这几大类的信息, 每一类都有很多的命令, 需要我们在实际的调试过程中不断认识和体会它的用法. 当然, 理解这些命令用法的前提是需要我们对操作系统内部构造有一个清晰的认识. 这需要不断的学习, 对OS有一个全局的把握, 这样才能更深入的理解它. 而通过Windbg的内核调试, 我们有一种更好的方式直接与Kernel打交道, 这对我们深入理解和认识操作系统有很大的帮助. 下一节我们将通过一个实际的调试driver的例子, 来进一步认识Windbg在内核调试中的作用. 转载: http://www.cnblogs.com/Sonic2007/archive/2008/03/22/1117538.html
