Debugging Tools for Windows

bp, bu, bm (Set Breakpoint)

bpbubm命令设置一个或多个软断点(software breakpoints)。可以组合位置、条件和选项来设置各种不同类型的软断点。

语法

用户模式

[~Threadbp[ID] [Options] [Address [Passes]] ["CommandString"
[~Threadbu[ID] [Options] [Address [Passes]] ["CommandString"
[~Threadbm [OptionsSymbolPattern [Passes] ["CommandString"]

内核模式

bp[ID] [Options] [Address [Passes]] ["CommandString"
bu[ID] [Options] [Address [Passes]] ["CommandString"
bm [Options] SymbolPattern [Passes] ["CommandString"]

参数

Thread
指定要应用该断点的线程。该语法的更多信息,查看线程语法。只能在用户模式下指定线程。如果没有指定线程,则断点应用到所有线程。
ID
指定用于标识该断点的十进制数字。

调试器在创建断点时指派ID,但是之后可以通过br (Breakpoint Renumber)命令来改变它。在其他调试器命令中使用ID来引用断点。要显示断点的ID,可以使用bl (Breakpoint List)命令。

在命令中使用ID,不能在命令(bpbu)和ID号之间加入空格。

ID 参数总是可选的。如果不指定ID,调试器使用第一个可用的断点号。内核模式下只能设置32个断点。用户模式下可以设置任意多个断点。但是哪种情况下对ID号的值都没有限制。如果使用中括号([])将ID起来,ID可以包含任意表达式。该语法的详细信息,查看数值表达式语法

Options
指定断点选项。除非特别指出,可以设置任意数量的下面的选项:
/1
创建一个一次性("one-shot")断点。该断点触发之后就会被从断点列表中永远去除。
/f PredNum
(仅Itanium、仅用户模式) 指定一个断言号。该断点使用相应的断言寄存器(predicate register)进行判定(例如,bp /f 4 address设置一个使用p4断言寄存器进行判定的断点)。关于断言寄存器的更多信息,查看Itanium结构体系
/p EProcess
(仅内核模式) 指定一个和该断点关联的进程。EProcess 必须是EPROCESS结构的实际地址,而不是PID。这种断点仅在指定的进程上下文内遇到的时候才会触发。
/t EThread
(仅内核模式) 指定一个和断点关联的线程。EThread必须是ETHREAD结构的实际地址而不是线程ID。这种断点仅在指定的线程上下文内遇到的时候才会触发。如果同时使用/p EProcess/t EThread ,它们可以按任意顺序排列。
/c MaxCallStackDepth
使得断点仅当调用堆栈小于MaxCallStackDepth 深度时才激活。不能将此选项和/C 组合使用。
/C MinCallStackDepth
使得断点仅当调用堆栈大于MinCallStackDepth深度时才激活。不能将此选项和/c 组合使用。
/a
(仅bm 使用) 在所有指定位置设置断点,不管他们在数据空间还是代码空间。由于数据上的断点可能造成程序错误,所以只能在确认安全的位置使用该选项。
/d
(仅bm 使用) 将断点位置转换为地址。因此,如果代码位置改变了,这个断点还是保持在原来的位置,而不是像使用SymbolPattern 来设置的一样。使用/d 来避免模块加载或重加载时重新求值对断点进行的改变。
/(
(仅bm 使用) SymbolString 定义的符号字符串中包含参数列表信息。 

这个功能使得可以对具有相同名字但是不同参数列表的重载函数设置断点。例如, bm /( myFunc 同时在myFunc(int a)myFunc(char a)上设置断点。如果没有"/(",对myFunc 设置的断点会失败,因为这样不能确定断点设置到哪一个myFunc 上。

Address
指定要设置断点处的指令的第一个字节位置。如果省略Address ,则使用当前指令指针。该语法的更多信息,查看地址和地址区域语法
Passes
指定断点激活之前要忽略的次数。调试器跳过该断点指定次数。该数字可以是任何16位或32位值。 

默认情况下,断点在第一次执行断点位置的代码时被激活。这种默认情况和把Passes 设置为1是一样的。要使得断点在程序至少执行该代码一次之后才激活,可以将这个值设置为2或更大。例如,值为2时,使得断点在第二次执行到该代码时被激活。

该参数创建一个在每次执行断点处的代码时被减少1的计数器。要查看Passes 计数器的初始值和当前值,使用bl (Breakpoint List)

Passes 仅当程序响应g (Go)命令并执行通过断点时才减少。单步或跟踪(tracing)通过它是不会减少的。当Passes 到达1时,可以通过清除并重设断点来重置它。

CommandString
指定每次遭遇断点指定次数后需要执行的命令列表。必须将CommandString 放到引号中。使用分号来分隔多条命令。 

CommandString 中的调试器命令可以包含参数。可以使用标准C控制字符(如\n \")。二级引号(\")中的分号被当作引号中的字符串的一部分。

CommandString命令仅当程序响应g (Go)命令并执行通过断点时才会执行。单步或跟踪(tracing)执行断点处的命令时是不会触发的。

任何在中断后恢复程序运行的命令(如gt)都会结束命令列表的执行。

SymbolPattern
指定符号模板。调试器尝试使用已存在的符号来匹配该模板,并在所有匹配项上设置断点。SymbolPattern可以包含各种通配符和修饰符。该语法的更多信息,查看字符串通配符语法。因为这些字符时用来匹配符号的,这种匹配不区分大小写,并且 头部的单个下划线(_)表示任意数量的起始下划线。

环境

模式 用户模式、内核模式
目标 仅活动目标
平台 所有

注释

bpbubm 命令设置新断点,但是它们有不同的特点:

使用bp命令时,断点位置始终被转换成地址。如果bp 断点设置的代码被移动了,该断点仍然保持在相同位置并且可能指向不同的代码或者非法位置。

相反的,bu 断点始终和命令指定的符号化的断点位置关联(一般是符号加上一个可选的偏移)。这种关联在符号的值改变或者包含该位置的模块加载或卸载之后仍然保持。

使用bp 设置的断点会保持到使用bc (Breakpoint Clear)命令或WinDbg的Breakpoints 对话框移除为止。但是,因为这些断点指向的是一个地址,bp 断点在包含所引用的位置的模块卸载之后就不再有效了。

bu 设置的断点会保存在WinDbg工作空间中,但是bp 设置的断点不会保存。

当使用鼠标在WinDbg的反汇编窗口源码窗口中设置断点时,调试器创建bu断点。

bm 在想使用包含通配符的符号模板来设置断点时很有用。bm SymbolPattern 语法和使用SymbolPattern然后对搜索结果使用bu 是一样的。例如,要在Myprogram 模块中所有以字符串"mem"开头的符号上设置断点,可以使用如下命令。

0:000> bm myprogram!mem* 
  4: 0040d070 MyProgram!memcpy
  5: 0040c560 MyProgram!memmove
  6: 00408960 MyProgram!memset

由于bm命令设置软断点(不是处理器断点),它会自动避开数据位置,以避免破坏数据。

但是,当使用bpbm /a时要小心。这些命令可以在数据段中设置软断点。调试器在代码上设置软断点时,会将处理器指令替换为中断指令。但是当调试器在数据段设置软断点时,会把数据替换为中断指令。这种中断指令会破坏数据。只有在只当作代码进行执行的数据上设置软件断点才是安全的。要在数据段设置断点,使用ba (Break on Access)命令。该命令可以设置数据断点而不是软件断点。

要在例如C++公有类这样的任意文本上设置断点,或者在operator new 函数上设置断点,需要将表达式括在园括号中。例如,使用bp (??MyPublic)bp (operator new)

要在MASM表达式类型的任意文本上设置断点,使用bu @!"text"。要使用C++语法文本设置断点,对C++兼容的符号使用bu @@c++(text)

Bpbubm命令通过将处理器命令替换为中断指令来设置软断点。要调试只读代码或不能改变的代码,使用ba e 命令,e用于设置执行访问。

如果单个逻辑代码行跨越了多个物理行,断点设置在语句或调用的最后一个物理行上。如果调试器在要求的位置不能设置断点,则会将断点放到下一个可用的位置上。

如果指定了Thread,断点设置在指定线程上。例如,~*bp在所有线程上设置断点, ~#bp在产生当前异常的线程上设置,而 ~123bp 在线程123上设置。~bp~.bp 命令都在当前线程设置断点。

在内核模是下调试多处理器系统时,使用bpba (Break on Access)设置的断点会应用到所有处理器。例如,如果当前处理器是3,并且输入bp MemoryAddress来在 MemoryAddress上设置了断点。任何执行到该地址的处理器(不止是处理器3)都会产生断点陷阱。

示例

下面的例子说明了如何使用不bp命令。这个命令在MyTest 函数后面12字节位置处设置断点。该断点忽略前6次对指定代码的执行,但是第7次执行该代码时会中断下来。

0:000> bp MyTest+0xb 7 

下面的命令在RtlRaiseException 上设置断点,显示eax寄存器并显示符号MyVar 的值,然后继续。

kd> bp ntdll!RtlRaiseException "r eax; dt MyVar; g"

附加信息

关于如何使用断点、其他断点命令和控制断点的方法、如何在内核调试器下在用户空间设置断点的更多信息,查看使用断点。关于设置条件断点的更多信息,查看设置条件断点

Build machine: CAPEBUILD