天天看点

WinDBG 设置条件断点

Conditional breakpoints can be veryuseful when you are trying to find bugs in your code. They cause a break tooccur only if a specific condition is satisfied.

当你在尝试找到你代码中的bug时,条件断点非常有用。当某个特殊条件满足时它才引起断点发生

A conditional breakpoint is created by combining a breakpoint command witheither thej (Execute If - Else) command or the.if token, followed by thegc (Go from Conditional Breakpoint)command. This breakpoint causes a break to occur only if a specific conditionis satisfied.

一个条件断点通过将一个断点命令和j命令或者.if关键字关联而创建,后面跟着gc命令。只有当某个特殊条件满足时这个断点才引起断点发生

The basic syntax for a conditional breakpoint using thej commandis as follows:

使用j命令的条件断点的基本命令是:

0:000> bp Address "j (Condition) 'OptionalCommands'; 'gc' "

The basic syntax for a conditional breakpoint using the.if tokenis as follows:

使用.if关键字的条件断点的基本语法是

0:000> bp Address ".if (Condition) {OptionalCommands} .else {gc}"

Conditional breakpoints are best illustrated with an example. Thefollowing command sets a breakpoint at line 143 of theMysource.cppsourcefile. When this breakpoint is hit, the variable MyVar is tested. If thisvariable is less than or equal to 20, execution continues; if it is greaterthan 20, execution stops.

条件断点最好用一个例子来描述。后面的命令在Mysource.cpp源文件的第143行设置一个条件断点。当这个断点命中时,变量MyVar被检测。如果这个变量小于或等于20,则继续执行;如果它大于20,停止执行

0:000> bp `mysource.cpp:143` "j (poi(MyVar)>0n20) ''; 'gc' " 

0:000> bp `mysource.cpp:143` ".if (poi(MyVar)>0n20) {} .else {gc}"

The preceding command has a fairly complicated syntax that contains thefollowing elements:

前面的命令有一个相当复杂的语法,包含着后面的元素:

The bp (Set Breakpoint) command sets breakpoints. Although the preceding example uses the bp command, you could also use thebu (Set Unresolved Breakpoint) command. For more information about the differences betweenbp andbu, and for a basic introduction to breakpoints, seeUsing Breakpoints.

Bp命令设置断点。尽管前面的例子使用了bp命令,你也可以使用bu命令。如果需要查看bp和bu之间的不同,和断点的简介,可以查看Using Breakpoints.

Source line numbers are specified by using grave accents ( ` ). For details, seeSource Line Syntax.

源代码行通过使用沉音符指定,详见Source Line Syntax.

When the breakpoint is hit, the command in straight quotation marks ( " ) is executed. In this example, this command is aj (Execute If - Else) command or an.if token, which tests the expression in parentheses.

当断点命中,直引号标记的命令被执行。在这个例子中,这个命令是一个j命令或者一个.if关键字,以检测圆括号中的表达式

In the source program, MyVar is an integer. If you are using C++ expression syntax, MyVar is interpreted as an integer. However, in this example (and in the default debugger configuration), MASM expression syntax is used. In a MASM expression,MyVar is treated as an address. Thus, you need to use the poi operator to dereference it. (If your variable actually is a C pointer, you will need to dereference it twice—for example,poi(poi(MyPtr)).) The0n prefix specifies that this number is decimal. For syntax details, seeMASM Numbers and Operators.

在源程序中,MyVar是一个整数。如果你使用C++表达式语法,MyVar被解释为一个整数。然而在这个例子中(并且在默认的调试器选项),使用的是MASM表达式语法。在一个MASM表达式中,MyVar被认为是一个地址。因此你需要使用poi操作符去解引用它。(如果你的变量实际上是一个C指针,你需要两次解引用它-例如poi(poi(MyPtr)) )0n前缀指定这个数字是10进制的。语法的详细内容参见MASM Numbers and Operators.

The expression in parentheses is followed by two commands, surrounded by single quotation marks (' ) for thej command and curly brackets ( {} ) for the.if token. If the expression is true, the first of these commands is executed. In this example, there is no first command, so command execution will end and control will remain with the debugger. If the expression in parentheses is false, the second command will execute. The second command should almost always be agc (Go from Conditional Breakpoint) command, because this command causes execution to resume in the same manner that was occurring before the breakpoint was hit (stepping, tracing, or free execution).

括号中的表达式后跟两个命令,使用j命令时用单引号括起来,使用.if关键字时使用花括号括起来。如果表达式为真,这些命令中的第一个将被执行。在这个例子中,没有第一个命令,所以命令的执行将会停止并且控制权继续交给调试器。如果在圆括号中的表达式为假,第二个命令将被执行。第二个命令几乎永远都是gc命令,因为这个命令使得执行被恢复到在断点被命中之前的相同的方式(单步,跟踪,或者自由执行)

If you want to see a message each time the breakpoint is passed or when itis finally hit, you can use additional commands in the single quotation marksor curly brackets. For example:

如果你想要在断点每次通过时或者最终命中时看到一个消息,你可以在单引号或花括号中使用附加的命令。例如:

0:000> bp `:143` "j (poi(MyVar)>5) '.echo MyVar Too Big'; '.echo MyVar Acceptable; gc' " 

0:000> bp `:143` ".if (poi(MyVar)>5) {.echo MyVar Too Big} .else {.echo MyVar Acceptable; gc} " 

These comments are especially useful if you have several such breakpointsrunning at the same time, because the debugger does not display its standard"Breakpoint n Hit" messages when you are using a commandstring in thebp command.

如果你在同一时间有几个这样的断点,这些注释将会特别有用,因为当你在bp命令中使用一个命令字符串时,调试器并不显示它的标准的"Breakpointn Hit"消息

Conditional Breakpoints and Register Sign Extension

条件断点和寄存器标记扩展

You can set a breakpoint that is conditional on a register value.

你可以设置一个断点,其条件是某个寄存器的值

The following command will break at the beginning of themyFunctionfunction if theeax register is equal to 0xA3:

下面的命令将会在eax寄存器等于0xA3时,在myFunction函数的开始处断下来

0:000> bp mydriver!myFunction "j @eax = 0xa3  '';'gc'" 

0:000> bp mydriver!myFunction ".if @eax = 0xa3  {} .else {gc}"

However, the following similar command willnot necessarily breakwheneax equals 0xC0004321:

然而,后面相似的命令将不一定会在eax等于0xC0004321时断下来。

0:000> bp mydriver!myFunction "j @eax = 0xc0004321  '';'gc'" 

0:000> bp mydriver!myFunction ".if @eax = 0xc0004321  {} .else {gc}"

The reason the preceding command will fail is that the MASM expressionevaluator sign-extends registers whose high bit equals one. Wheneax hasthe value 0xC0004321, it will be treated as 0xFFFFFFFF`C0004321 in computations—eventhougheax will still bedisplayed as 0xC0004321. However, thenumeral0xc0004321 is sign-extended in kernel mode, but not in usermode. Therefore, the preceding command will not work properly in user mode. Ifyou mask the high bits ofeax, the command will work properly in kernelmode—but now it will fail in user mode.

前面命令将会失败的原因是MASM表达式评估有符号扩展的寄存器时它们的高位等于1.当eax的值为0xC0004321,它将在评估时被认为是0xFFFFFFFF`C0004321-尽管eax仍然显示为0xC0004321。然而,数字0xc0004321在内核模式中被有符号扩展,用户模式中却不是这样。因此,前面的命令将不会在用户模式中正常的工作。如果你对eax的高位进行掩码,该命令则会在内核模式中正常工作-但是现在它在用户模式中就不行了

You should formulate your commands defensively against sign extension inboth modes. In the preceding command, you can make the command defensive bymasking the high bits of a 32-bit register by using an AND operation to combineit with 0x00000000`FFFFFFFF and by masking the high bits of a numeric constantby including a grave accent ( ` ) in its syntax.

你需要将你的命令公式化以防在两种模式中的符号扩展。在前面的命令中,你可以通过使用AND操作符将一个32位寄存器的高位与0x00000000`FFFFFFFF组合进行掩码,并且通过包含一个沉音符将其高位与一个数字常量进行掩码。

The following command will work properly in user mode and kernel mode:

下面的命令将会在用户模式和内核模式都正常工作

0:000> bp mydriver!myFunction "j (@eax & 0x0`ffffffff) = 0x0`c0004321  '';'gc'" 

0:000> bp mydriver!myFunction ".if (@eax & 0x0`ffffffff) = 0x0`c0004321  {} .else {gc}"

For more information about which numbers are sign-extended by thedebugger, seeSign Extension.

如果需要有关数字在调试器中是如何进行符号扩展的,可以查看Sign Extension.

Conditional Breakpoints in WinDbg

WinDbg中的条件断点:

In WinDbg, you can create a conditional breakpoint by clickingBreakpoints from theEdit menu,entering a new breakpoint address into the Command box, and entering acondition into theCondition box.

在WinDbg中,你可以通过在Edit菜单中点击Breakpoints来创建一个条件断点,在command框输入一个新的断点的地址在Condition框中输入一个条件