1.设置断点

bp,bu,bm 软中断

[~td] bp[ID] [Options] [Address[Passess]] ['CommandString']
~td:线程序号。如果设置了线程序号,则只有当该线程调用才会触发断点。
ID:断点编号,如果不指定则从0开始编排
Address:断点地址,eg:TestModals 模块的Func 函数 TestModals!Func
Passess:每经过一次断点-1,当等于0的时候,触发断点。默认为1
CommandString:中断时Windbg会自动执行CommandString命令
Options:
1. /1 一次性断点,中断一次便删除
2. /p 只有当前进程是指定进程的时候才触发这个断点(内核调试使用)
3. /t 指定线程访问才触发断点 (内核调试使用)
4. /c 最大函数调用深度 eg:bp /c5 msvcr80d!printf 只有调用深度小于5才中断
5. /C 最小函数调用深度

bp 设置断点,设置的时候模块必须加载完成。
bu 预加载,此时模块可能并没有加载。例如对于dll的入口函数打断点。
bm 批量设置断点。eg:msvcr80模块中,所以print开头的函数。eg:bm msvcr80!print*

bu LogHelper!DllMain
bu LogHelper!LogHelper::Load
bu "LogHelper!LogHelper.cpp:24"

ba 硬件中断

ba[ID] Access Size [Options] [Address[Passess]] ['CommandString']

Access:触发断点的访问方式
- e:当从指定地址读取和执行指令的时候触发断点
- r:当从指定地址读取和写入指令的时候触发断点
- w:当从指定地址写入指令的时候触发断点
- i:当从指定地址存在IO访问触发断点

Size:指定数据访问长度。

- X86:1,2,4 三种值
- X64:1,2,4,8 四种值

Address:断点地址,是根据size对齐的。eg:size=4,那么address为4的整数倍。

eg:ba r1 0041717c 那么对地址0041717c的一字节,字访问,双字访问(读写)都会触发这个断点。

条件断点

如果条件不满足执行分号后面的命令:gc
bp|bu|bm|ba Address "j(Condition)'Option Commands' ;'gc' "

bp|bu|bm|ba Address ".if(Condition){Option Commands}.else{gc} "

地址表达式

1. 使用模块名+函数符号的形式。eg:bu LogHelper!DllMain
2. 直接使用内存地址。eg bu 00411390
3. 使用模块名+源代码信息。eg bu "LogHelper!LogHelper.cpp:24" (使用重音符号包围)
4. 使用C++类方法.eg:bu LogHelper!LogHelper::Load
Note:使用1,2方法的时候应该确指向指令的起始处,而不是指令中部。因为中断的时候调试器会把这条指令的
中间字节替换成断点指令。cpu会把原来的指令和断点指令一起解码,导致未知后果。
2.管理断点
1. bl 显示所有断点
2. bc 删除断点 .eg:bc * ,bc 1
3. bd 禁用断点 eg:bd 1
4. be 启用断点 eg:be 1
断点号:使用-来指定范文,使用逗号指定多个断点号,使用*匹配所有断点。
eg:
bd 0-2,4 禁用0,1,2,4号断点。
be * 启用所有断点。

windbg 断点+单步_加载

bl 每列表示含义
1. 断点序号。0,1,2
2. 断点状态。e-enable ,d-disable,u-unresolved(未解析,往往因为符号未加载或者不一致)
3. 断点地址。 722e6370'703a3234
4. 0001 断点触发剩余次数
5. (0001) 断点初始计数。bp Passess 参数的值
6. 断点所关联的进程和线程。 0:**** 冒号前面是进程号,冒号后面是线程号。****代表所有线程
7. 断点符号表示。 LogHelper!DllMain
3.单步执行(p|t)

windbg快捷键:

windbg 断点+单步_函数调用_02

p:step over
t:step into

pa|ta:单步执行到指定地址
pc|tc:但不指定到下一个函数调用。
tb:单步执行到下一分支。
汇编模式:单步执行一条汇编指令
源码模式:单步执行一条语句
模式切换:菜单 Debug=》Source Code
p|t [r] [=StartAddress] [Count] ["Command"]
r:禁止自动显示寄存器内容,默认单步执行后会自动显示每个寄存器内容。
StartAddress:默认从当前位置开始单步执行,但是可以通过等号(=)指定新的起始地址,从新地址开始执行。
如果地址超出了当前函数,则跳过了整个函数栈的代码,那么栈会失去平衡,出现严重错误。
Count:单步执行次数。eg :t 2,单步执行两次。
Command:单步执行后要执行的命令。
3.继续运行(g)
g[a] [=StartAddress] [BreakAddress..[;BreakCommands]]

StartAddress:指定恢复执行的起始地址,默认为当前位置
BreakAddress:执定一个新的断点地址
a:只有BreakAddress设置时才有效,a设置为硬件断点,否则为软件断点。

1.如果不带任何参数则g命令是恢复运行目标
2.如果指定了BreakAddress,那么windbg会设置一个隐藏断点,然后恢复目标,
当执行到这个断点的时候自动删除这个断点,eg:菜单(Run to Cursor)。

异常处理回复,命令用法同g:

gh:Go With Exception Handler,回复系统异常已经处理
gn:Go With Exception Not Handler,回复系统没有处理

windbg 断点+单步_加载_03