WinDbg常用命令系列---断点操作b*
ba (Break on Access)
ba命令设置处理器断点(通常称为数据断点,不太准确)。此断点在访问指定内存时触发。
用户模式下
[~Thread] ba[ID] Access Size [Options] [Address [Passes]] ["CommandString"]
内核模式下
ba[ID] Access Size [Options] [Address [Passes]] ["CommandString"]
参数:
- Thread
指定断点应用于的线程 - ID
指定标识断点的可选数字。如果不指定ID,则使用第一个可用的断点编号。您不能在BA和ID号之间添加空格。每个处理器只支持有限数量的处理器断点,但对ID号的值没有限制。如果将ID括在方括号([])中,则ID可以包含任何表达式。 - Access
指定满足断点的访问类型。此参数可以是以下值之一。
Option 操作 e (执行)
当 CPU 检索一条指令从指定的地址时进入调试器。
r (读/写)
当 CPU 读取或写入指定地址处时进入调试器。
w (写入)
进入调试器,当 CPU 将在指定的地址。
i (i/o)
(内核模式下唯一的、 基于 x86 的系统仅)在指定 I/O 端口时中断到调试器地址访问。
- Size
指定要监视访问的位置的大小(以字节为单位)。在基于x86的处理器上,此参数可以是1、2或4。但是,如果access等于e,则大小必须为1。在基于x64的处理器上,此参数可以是1、2、4或8。但是,如果access等于e,则大小必须为1。 - Options
指定断点选项。您可以使用以下任意数量的选项,除非另有说明:
/1
创建一个“一次性”断点。触发此断点后,将从断点列表中永久删除该断点。/p EProcess
(仅限内核模式)指定与此断点关联的进程。eprocess应该是eprocess结构的实际地址,而不是pid。只有在此进程上下文中遇到断点时才会触发断点。/t EThread
(仅限内核模式)指定与此断点关联的线程。ethread应该是ethread结构的实际地址,而不是线程ID。只有在该线程的上下文中遇到断点时才会触发断点。如果使用/p eprocess和/t ethread,可以按任意顺序输入它们。/c MaxCallStackDepth
仅当调用堆栈深度小于MaxCallStackDepth时,才会使断点处于活动状态。您不能将此选项与/C组合在一起。/C MinCallStackDepth
仅当调用堆栈深度大于MinCallStackDepth时,才会使断点处于活动状态。您不能将此选项与/c组合在一起。 -
指定任何有效地址。如果应用程序访问在此地址的内存,调试器将停止执行,并显示所有寄存器和标志的当前值。 此地址必须是偏移量并适当对齐到匹配大小参数。 (例如,如果大小为 4,地址必须是 4 的倍数。)如果省略地址,使用当前指令指针。 - Passes
指定断点在激活之前经过的次数。这个数字可以是任何16位值。程序计数器在不中断的情况下通过此点的次数小于此数字的值。因此,省略这个数字等于将其设置为1。还要注意,这个数字只计算应用程序执行超过这一点的次数。步进或跟踪超过此点不算数。达到完整计数后,只能通过清除并重置断点来重置此数字。 - CommandString
指定每次遇到指定次数的断点时要执行的命令列表。只有在发出g(go)命令后命中断点,而不是在t(trace)或p(step)命令后,才会执行这些命令。commandString中的调试器命令可以包含参数。必须将此命令字符串括在引号中,并且应使用分号分隔多个命令。您可以使用标准的C控制字符(例如\n和\”)。包含在二级引号(\“)中的分号被解释为嵌入的带引号字符串的一部分。
调试器使用ID号来引用后面的bc(断点清除)、bd(断点禁用)和be(断点启用)命令中的断点。使用bl(断点列表)命令列出所有现有断点及其ID号和状态。使用.bpcmds(显示断点命令)命令列出所有现有断点、它们的ID号以及用于创建它们的命令。每个处理器断点都有一个与其关联的大小。例如,W(写)处理器断点可以设置在地址0x70001008处,大小为4个字节。这将监视从0x70001008到0x7000100B(包括)的地址块。如果写入此内存块,将触发断点。处理器可能在与指定区域重叠但不相同的内存区域上执行操作。在本例中,包含范围0x70001000到0x7000100F的单个写入操作,或仅包含0x70001009处字节的写入操作,将是重叠操作。在这种情况下,是否触发断点取决于处理器。您应该参考处理器手册了解具体细节。要获取一个特定的实例,在x86处理器上,只要访问范围与断点范围重叠,就会触发读或写断点。同样,如果在地址0x004001003上设置了E(执行)断点,然后执行跨越地址0x004001002和0x004001003的双字节指令,则结果取决于处理器。同样,有关详细信息,请参阅处理器体系结构手册。处理器区分用户模式调试器设置的断点和内核模式调试器设置的断点。用户模式处理器断点不影响任何内核模式进程。内核模式处理器断点可能会影响用户模式进程,具体取决于用户模式代码是否使用调试寄存器状态以及是否连接了用户模式调试器。要将当前进程的现有数据断点应用到不同的寄存器上下文,请使用.apply-dbp(将数据断点应用到上下文)命令。在多处理器计算机上,每个处理器断点应用于所有处理器。例如,如果当前处理器是3,并且使用命令ba e1 myaddress在myaddress处放置断点,那么在该地址处执行的任何处理器(不仅是处理器3)都会触发断点。(这也适用于软件断点。)不能在同一地址创建多个处理器断点,这些断点的commandString值不同。但是,可以在具有不同限制的同一地址创建多个断点(例如,/p、/t、/c和/c选项的不同值)。
以下示例显示了ba命令。下面的命令设置一个断点,用于读取变量myvar的4个字节的访问权限。
0:000> ba r4 myVar
以下命令在地址从0x3f8到0x3fb的所有串行端口上添加断点。如果有任何内容被读取或写入这些端口,则会触发此断点。
kd> ba i4 3f8
bc (Breakpoint Clear)
bc命令将从系统中永久删除以前设置的断点。
bc Breakpoints
参数:
- Breakpoints
指定要删除的断点的ID号。可以指定任意数量的断点。必须用空格或逗号分隔多个ID。可以使用连字符(-)指定断点ID的范围。可以使用星号(*)指示所有断点。如果要对ID使用数值表达式,请将其括在括号([])中。如果要使用带有通配符的字符串来匹配断点的符号名,请将其括在引号中。
使用bl (Breakpoint List)命令列出所有现有断点及其ID号和状态。使用.bpcmds (Display Breakpoint Commands)命令列出所有现有断点、它们的ID号以及用于创建它们的命令。
bd (Breakpoint Disable)
bd命令禁用但不删除以前设置的断点。
bd Breakpoints
参数:
- Breakpoints
指定要禁用的断点的ID号。可以指定任意数量的断点。必须用空格或逗号分隔多个ID。可以使用连字符(-)指定断点ID的范围。可以使用星号(*)指示所有断点。如果要对ID使用数值表达式,请将其括在括号([])中。如果要使用带有通配符的字符串来匹配断点的符号名,请将其括在引号(“”)中。
禁用断点时,系统不检查断点中指定的条件是否有效。使用be (Breakpoint Enable)命令重新启用禁用的断点。使用bl (Breakpoint List)命令列出所有现有断点及其ID号和状态。使用.bpcmds (Display Breakpoint Commands)命令列出所有现有断点、它们的ID号以及用于创建它们的命令。
be (Breakpoint Enable)
be命令恢复以前禁用的一个或多个断点。
be Breakpoints
- Breakpoints
指定要禁用的断点的ID号。可以指定任意数量的断点。必须用空格或逗号分隔多个ID。可以使用连字符(-)指定断点ID的范围。可以使用星号(*)指示所有断点。如果要对ID使用数值表达式,请将其括在括号([])中。如果要使用带有通配符的字符串来匹配断点的符号名,请将其括在引号(“”)中。
bl (Breakpoint List)
bl命令列出有关现有断点的信息。
bl [/L] [Breakpoints]
参数:
- /L
强制BL始终显示断点地址,而不是显示源文件和行号。 - Breakpoints
指定要列出的断点的ID号。如果省略断点,调试器将列出所有断点。可以指定任意数量的断点。必须用空格或逗号分隔多个ID。可以使用连字符(-)指定断点ID的范围。可以使用星号(*)指示所有断点。如果要对ID使用数值表达式,请将其括在括号([])中。如果要使用带有通配符的字符串来匹配断点的符号名,请将其括在引号中。
对于每个断点,命令显示以下信息:
- 断点ID。此ID是一个十进制数字,可用于在以后的命令中引用断点。
- 断点状态。状态可以是E(启用)或D(禁用)。
- (仅限未解析的断点)如果断点未解析,则显示字母“U”。也就是说,断点与当前加载的任何模块中的符号引用都不匹配。
- 构成断点位置的虚拟地址或符号表达式。如果启用了源行号加载,BL命令将显示文件和行号信息,而不是地址偏移量。如果断点未解析,则在此处省略该地址,并显示在列表的末尾。
- (仅限数据断点)显示数据断点的类型和大小信息。类型可以是E(执行)、R(读/写)、W(写)或I(输入/输出)。这些类型后面是块的大小(以字节为单位)。
- 在激活断点之前保持的传递数,后跟括号中的初始传递数。
- 关联的进程和线程。如果线程被指定为三个星号(“***”),则此断点不是线程特定的断点。
- 与断点地址相对应的具有偏移量的模块和函数。如果断点未解析,则断点地址将显示在此处,并显示在括号中。如果在有效地址上设置了断点,但缺少符号信息,则此字段为空。
- 命中此断点时自动执行的命令。此命令以引号显示。
如果不确定使用什么命令设置现有断点,请使用.bpcmds(显示断点命令)列出所有断点以及用于创建断点的命令。下面的示例显示了BL命令的输出。
0:000> bl 0 e 010049e0 0001 (0001) 0:**** stst!main
此输出包含一下信息:
- 断点ID为0。
- 断点状态为E(启用)。
- 断点未解析(输出中没有u)。
- 断点的虚拟地址是010049e0。
- 第一次通过代码时断点处于活动状态,代码尚未在调试器下执行。“剩余通过”计数器中的值为1(0001),初始“剩余通过”计数器中的值为1((0001))。
- 此断点不是线程特定的断点(****)。
- 断点设置在STST模块的MAIN上。
bp, bu, bm (Set Breakpoint)
bp、bu和bm命令设置一个或多个软件断点。您可以组合位置、条件和选项来设置不同类型的软件断点。
用户模式:
[~Thread] bp[ID] [Options] [Address [Passes]] ["CommandString"] [~Thread] bu[ID] [Options] [Address [Passes]] ["CommandString"] [~Thread] bm [Options] SymbolPattern [Passes] ["CommandString"]
内核模式:
bp[ID] [Options] [Address [Passes]] ["CommandString"] bu[ID] [Options] [Address [Passes]] ["CommandString"] bm [Options] SymbolPattern [Passes] ["CommandString"]
参数:
- Thread
指定断点应用于的线程。只能在用户模式下指定线程。如果不指定线程,则断点将应用于所有线程。 - ID
指定标识断点的十进制数字。 调试器在创建断点时分配ID,但您可以使用br(断点重新编号)命令更改它。可以使用该ID在以后的调试器命令中引用断点。要显示断点的ID,请使用bl(断点列表)命令。在命令中使用ID时,不要在命令(bp或bu)和ID号之间键入空格。ID参数始终是可选的。如果不指定ID,调试器将使用第一个可用的断点编号。在内核模式下,只能设置32个断点。在用户模式下,可以设置任意数量的断点。在这两种情况下,ID号的值都没有限制。如果将ID括在方括号([])中,则ID可以包含任何表达式。
- Options
指定断点选项。您可以指定以下任意数量的选项,除非另有说明:
/1
创建"单稳"断点。 触发此断点后,它是从断点列表中删除。/f PredNum
(基于 Itanium 的仅限用户仅模式)指定的谓词的数字。 断点都与相应的谓词寄存器。 (例如, bp /f 4 地址设置的前提是使用断点p4谓词寄存器。)/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断点适用于函数。
/w dx 对象表达式设置条件断点基于 dx 对象表达式返回的布尔值。 参数是一个数据模型 (dx) 表达式的计算结果为 true (与匹配条件 – 中断) 或 false (不匹配条件 – 不会中断)。
- Address
指定设置断点的指令的第一个字节。如果省略地址,则使用当前的指令指针。 - Passes
具体说明执行通过的次数,该断点被激活。解调器滑雪的断点位置直到它达到特定的通行证。通行证的价值可以是16位或32位。由于缺陷,断点是第一次激活应用程序执行包含断点位置的码。这一缺陷相当于1个乘客的价值。只有在应用程序执行后,至少一次激活断点,输入两个或更多的值。例如,在执行代码的第二时间,两个激活断点的值。 这个参数创建了一个计数器,该计数器在每一次通过该代码时都被解码。要查看过程计数器的初始值和当前值,请使用bl(断点列表)。只有当应用程序执行者通过断点响应于G(GO)命令时,才解码输出计数器。如果你正在通过代码或跟踪它,则计数器不是消失。当通行计数器到达1时,你只能清晰地重置它,并重新安排断点。
- CommandString
指定每次遇到指定次数的断点时执行的命令列表。必须将commandString参数括在引号中。使用分号分隔多个命令。commandString中的调试器命令可以包含参数。您可以使用标准的C控制字符(例如\n和\”)。包含在二级引号(\“)中的分号被解释为嵌入的带引号字符串的一部分。只有在应用程序响应g(go)命令执行时到达断点时,才会执行commandstring命令。如果您正在单步执行代码或跟踪超过此点,则不会执行命令。在断点(如g或t)之后恢复程序执行的任何命令结束命令列表的执行。
-
SymbolPattern
指定图案。调试器尝试将此模式与现有符号匹配,并在所有模式匹配项上设置断点。符号模式可以包含各种通配符和说明符。因为这些字符与符号匹配,所以匹配不区分大小写,单个前导下划线(u)表示任意数量的前导下划线。
bp、bu和bm命令设置了新的断点,但它们具有不同的特性:
- bp(set breakpoint)命令在命令中指定的断点位置的地址处设置新的断点。如果设置断点时调试器无法解析断点位置的地址表达式,则BP断点将自动转换为BU断点。使用bp命令创建一个断点,如果卸载模块,该断点将不再处于活动状态。
- bu(set unresolved breakpoint)命令设置延迟或未解析的断点。BU断点设置在对断点位置的符号引用上,该断点位置在命令中指定(不在地址上),并且在解析具有引用的模块时激活。有关这些断点的详细信息,请参阅未解析断点(BU断点)。
- bm(set symbol breakpoint)命令在符合指定模式的符号上设置新的断点。此命令可以创建多个断点。默认情况下,匹配模式后,BM断点与BU断点相同。也就是说,BM断点是在符号引用上设置的延迟断点。但是,bm/d命令创建一个或多个bp断点。每个断点都设置在匹配位置的地址上,不跟踪模块状态。
如果不确定使用什么命令设置现有断点,请使用.bpcmds(显示断点命令)列出所有断点以及用于创建断点的命令。BP断点和BU断点有三个主要区别:
- BP断点位置始终转换为地址。如果模块更改移动了设置bp断点的代码,则断点保持在同一地址。另一方面,bu断点仍然与所使用的符号值(通常是符号加上偏移量)相关联,即使其地址更改,它也会跟踪这个符号位置。
-
如果在加载的模块中找到bp断点地址,并且稍后卸载该模块,则将从断点列表中删除该断点。另一方面,在重复卸载和加载之后,bu断点仍然存在。
- 使用bp设置的断点不会保存在windbg工作区中。使用bu设置的断点保存在工作区中。
当希望在符号模式中使用通配符作为断点时,bm命令非常有用。bm符号模式语法相当于使用x符号模式,然后对每个结果使用bu。例如,要在myprogram模块中以字符串“mem”开头的所有符号上设置断点,请使用以下命令。
0:000> bm myprogram!mem* 4: 0040d070 MyProgram!memcpy 5: 0040c560 MyProgram!memmove 6: 00408960 MyProgram!memset
由于bm命令设置软件断点(而不是处理器断点),因此在设置断点时,它会自动排除数据位置,以避免损坏数据。使用bp或bm/a命令时,可以指定数据地址而不是程序地址。但是,即使指定了数据位置,这些命令也会创建软件断点,而不是处理器断点。如果将软件断点放置在程序数据中而不是可执行代码中,则可能导致数据损坏。因此,只有在确定存储在该位置的内存将用作可执行代码而不是程序数据时,才应在数据位置中使用这些命令。否则,您应该改用ba(break on access)命令。如果单个逻辑源行跨越多个物理行,则在语句或调用的最后一个物理行上设置断点。如果调试器无法在请求的位置设置断点,它会将断点置于下一个允许的位置。如果指定线程,则在指定的线程上设置断点。例如,~*bp命令在所有线程上设置断点,~ bp在导致当前异常的线程上设置断点,~123bp在线程123上设置断点。~bp和~.bp命令都在当前线程上设置了断点。在内核模式下调试多处理器系统时,使用bp或ba(访问中断)设置的断点将应用于所有处理器。例如,如果当前处理器为3,并且键入bp memoryaddress以在memoryaddress处放置断点。在该地址执行的任何处理器(不仅是处理器3)都会导致断点陷阱。bp、bu和bm命令通过用break指令替换处理器指令来设置软件断点。要调试只读代码或无法更改的代码,请使用ba e命令,其中e表示仅执行访问。
以下命令将断点设置为超过函数mytest开头12个字节。前六次通过代码时忽略此断点,但第七次通过代码时停止执行。
0:000> bp MyTest+0xb 7
以下命令在rtlraiseexception处设置断点,显示EAX寄存器,显示符号myvar的值,然后继续。
kd> bp ntdll!RtlRaiseException "r eax; dt MyVar; g"
以下两个bm命令设置了三个断点。执行命令时,显示的结果不区分使用/d开关创建的断点和不使用/d开关创建的断点。.bpcmds(显示断点命令)可用于区分这两种类型。如果断点是由BM在没有/D开关的情况下创建的,.bpcmds显示将断点类型指示为bu,后跟@!!“中包含的计算符号。”标记(表示它是文字符号而不是数字表达式或寄存器)。如果断点是由bm使用/d开关创建的,.bpcmds显示将断点类型指示为bp。
0:000> bm myprog!openf* 0: 00421200 @!"myprog!openFile" 1: 00427800 @!"myprog!openFilter" 0:000> bm /d myprog!closef* 2: 00421600 @!"myprog!closeFile" 0:000> .bpcmds bu0 @!"myprog!openFile"; bu1 @!"myprog!openFilter"; bp2 0x00421600 ;
br (Breakpoint Renumber)
br命令重新编号一个或多个断点。
br OldID NewID [OldID2 NewID2 ...]
参数:
- OldID
指定断点的当前ID号。 - NewID
指定成为断点ID的新数字。
可以使用br命令同时对任意数量的断点重新编号。对于每个断点,按该顺序列出旧ID和新ID作为br的参数。如果已经有一个ID等于newID的断点,则该命令将失败,并显示一条错误消息。
bs (Update Breakpoint Command)
bs命令更改遇到指定断点时执行的命令。
bs ID ["CommandString"]
参数:
- ID
指定断点的ID号。 - CommandString
指定每次遇到断点时要执行的新命令列表。必须将commandString参数括在引号中。使用分号分隔多个命令。commandString中的调试器命令可以包含参数。您可以使用标准的C控制字符(例如\n和\”)。包含在二级引号(\“)中的分号被解释为嵌入的带引号字符串的一部分。只有在应用程序响应g(go)命令执行时到达断点时,才会执行commandstring命令。如果您正在单步执行代码或跟踪超过此点,则不会执行命令。在断点(如g或t)之后恢复程序执行的任何命令结束命令列表的执行。
如果未指定commandstring,则将删除断点上已设置的所有命令。
bsc (Update Conditional Breakpoint)
bsc命令更改发生断点的条件,或更改遇到指定条件断点时执行的命令。
bsc ID Condition ["CommandString"]
参数:
- ID
指定断点的ID号。
- Condition
指定触发断点的条件。 - CommandString
指定每次遇到断点时要执行的新命令列表。必须将commandString参数括在引号中。使用分号分隔多个命令。commandString中的调试器命令可以包含参数。您可以使用标准的C控制字符(例如\n和\”)。包含在二级引号(\“)中的分号被解释为嵌入的带引号字符串的一部分。只有在应用程序响应g(go)命令执行时到达断点时,才会执行commandstring命令。如果您正在单步执行代码或跟踪超过此点,则不会执行命令。在断点(如g或t)之后恢复程序执行的任何命令结束命令列表的执行。
如果未指定commandstring,则将删除断点上已设置的所有命令。使用带有以下语法的bs(update breakpoint命令)命令也可以达到同样的效果:
bs ID "j Condition 'CommandString'; 'gc'"