Windbg条件断点不能按预期工作,我的语法是否正确?

时间:2016-07-29 05:03:29

标签: c++ debugging conditional windbg break

我试图学习如何在windbg中设置条件断点,我的程序名为ConsoleApplication7,如下所示:

int main()
{
    int r1 = 0;
    r1 += 1;
    r1 = 3;
    return 0;
}

我用VC编译这个程序。然后在windbg中,我设置了#34;符号路径"和"源路径",在windbg中打开ConsoleApplication7.exe,windbg运行并打开.cpp文件。

在windbg里面我设置了一个条件断点,我希望程序在排队时可以" r1 = 3"。

bp consoleapplication7!main "j (poi(r1)>2) ''; 'gc'"

但是当我按下" g"时,windbg并没有说出"点击断点",只是打印出寄存器信息。跑完" g"程序终止3次,如下所示:

0:000> bp consoleapplication7!main "j (poi(r1)>2) ''; 'gc'"
*** WARNING: Unable to verify checksum for ConsoleApplication7.exe
0:000> bl
 0 e 01251380     0001 (0001)  0:**** ConsoleApplication7!main "j (poi(r1)>2) ''; 'gc'"
0:000> g
eax=00718918 ebx=7efde000 ecx=0071b880 edx=00000001 esi=00000000 edi=00000000
eip=01251380 esp=002afeb4 ebp=002aff00 iopl=0         nv up ei pl nz na po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000202
ConsoleApplication7!main:
01251380 55              push    ebp
0:000> g
eax=00000000 ebx=00000000 ecx=00000000 edx=00000000 esi=77c02100 edi=77c020c0
eip=77b1fcd2 esp=002afe18 ebp=002afe34 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
ntdll!NtTerminateProcess+0x12:
77b1fcd2 83c404          add     esp,4
0:000> g
       ^ No runnable debuggees error in 'g'

ba,bp等其他命令在程序中运行良好,只是条件断点不适用。

我的条件陈述是否正确?为什么它不起作用?

我尝试了Dono的回答,但它显示了另一个问题

0:000> bp ConsoleApplication7!main+0x3e "j (poi(r1) > 2) ''; 'gc'"
0:000> bl
 0 e 008e143e     0001 (0001)  0:**** ConsoleApplication7!main+0x3e "j (poi(r1) > 2) ''; 'gc'"
0:000> g
(4458.4840): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000000 ebx=7efde000 ecx=d3392f75 edx=00000001 esi=00000000 edi=00000000
eip=cccccccc esp=0046f82c ebp=cccccccc iopl=0         nv up ei pl nz na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010206
cccccccc ??              ???

似乎这个条件断点导致异常? 谢谢!

我也尝试过Blabb的建议,不幸的是,它没有工作:

0:000> t "$$>a< c:\\autostep.txt"
Couldn't resolve error at 'r1) == 3 ) { dv } .else { t "$$>a< c:\\autostep.txt" } '
eax=00000001 ebx=7efde000 ecx=00000000 edx=00000001 esi=00000000 edi=001dfcb0
eip=013b13c0 esp=001dfbac ebp=001dfcb0 iopl=0         nv up ei pl nz na po nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000202
ConsoleApplication7!f:
013b13c0 55              push    ebp

似乎C ++样式命令没有用,所以我将其改为MASM样式

j (poi(r1)==3)''; 't "$$>a< c:\\autostep.txt"'

另存为c:\ autostep.txt 然后我重新启动windbg以重新加载它。

0:000> t "$$>a< c:\\autostep.txt"
eax=00000000 ebx=00000000 ecx=bc260000 edx=0015dc38 esi=fffffffe edi=00000000
eip=77ba0e15 esp=0042f804 ebp=0042f830 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000244
ntdll!LdrpDoDebuggerBreak+0x2d:
77ba0e15 8975fc          mov     dword ptr [ebp-4],esi ss:002b:0042f82c=00000000
0:000> g
eax=00000000 ebx=00000000 ecx=00000000 edx=00000000 esi=77c02100 edi=77c020c0
eip=77b1fcd2 esp=0042fb94 ebp=0042fbb0 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
ntdll!NtTerminateProcess+0x12:
77b1fcd2 83c404          add     esp,4

这一次,它没有语法问题,当它没有像我预期的那样中断/停止时。我错过了什么吗?

感谢。

2 个答案:

答案 0 :(得分:3)

首先,您应该知道您的程序将优化为xor eax,eax ; ret

除非您在调试模式下编译并使用/ Od开关明确禁用优化

(我假设你在调试模式下使用visual monster项目来处理这个问题)

第二,您应该知道调试器不知道您的r1 r2或其他什么,除非存在符号信息和事件然后您应该知道有两个表达式评估器MASM和C ++,默认情况下windbg使用MASM

? poi(r1) == MASM evaluation 
?? r1 == c++ evaluation    

其他明智的调试器只能理解cpu理解的变量,如BYTE , WORD , DWORD , QWORD .... etc和地址

当您设置条件断点时,例如bp xxxxxmodule!yyyyysymbol“条件”条件仅在下面指定的地址上进行评估 所以你的病情只在主要

评估

你应该进一步向下并评估你每个步骤的状况,直到你遇到一个匹配

您的代码已编译,main()反汇编将如下所示

0:000> .dml_flow steptest!main .
                              <No previous node>                    


          STEPTEST!main (013e6aa0):
          e:\test\steptest\steptest.cpp
          2     013e6aa0 push    ebp                                
          2     013e6aa1 mov     ebp,esp                            
          2     013e6aa3 push    ecx                                
          3     013e6aa4 mov     dword ptr [ebp-4],0                
          4     013e6aab mov     eax,dword ptr [ebp-4]              
          4     013e6aae add     eax,1                              
          4     013e6ab1 mov     dword ptr [ebp-4],eax              
          5     013e6ab4 mov     dword ptr [ebp-4],3                
          6     013e6abb xor     eax,eax                            
          7     013e6abd mov     esp,ebp                            
          7     013e6abf pop     ebp                                
          7     013e6ac0 ret                                        


                                <No next node>                      
0:000> lsa .
     1: int main()
     2: {
     3:     int r1 = 0;
>    4:     r1 += 1;
     5:     r1 = 3;
     6:     return 0;
     7: }

因此,您的情况只能在第6行或地址013e6abb xor eax, eax

的汇编中为真

您设置conditional bp on 013e6aa0并且仅在该地址评估条件

你需要找到一种方法,直到013e6abb

你应该

step <evaluate> if match stop else repeat step and evaluate until match occurs 

这样做将以下行放在名为autostep.txt的文件中并将其保存到c:\

脚本的解释

如果c ++表达式r1等于3,则显示locals else步骤并通过再次运行此脚本重新评估(因此将在每个指令序列上执行此脚本,直到找到匹配项)

.if ( @@c++(r1) == 3 ) { dv } .else { t "$$>a< c:\\autostep.txt" } 

现在在windbg中打开exe并执行

bp xxxxmod!main
g
t "$$>a< c:\\autostep.txt"
当r1为3时,

windbg会中断

E:\test\STEPTEST>cdb -c "g steptest!main" STEPTEST.exe

0:000> cdb: Reading initial command 'g steptest!main'

STEPTEST!main:
013e6aa0 55              push    ebp
0:000> t "$$>a< c:\\autostep.txt"
             r1 = 0n3

013e6abb 33c0            xor     eax,eax
0:000> ?? r1
int 0n3
0:000> ? poi(r1)
Evaluate expression: 3 = 00000003
0:000> ? &main ; ? &@eip
Evaluate expression: 20867744 = 013e6aa0
Evaluate expression: 20867771 = 013e6abb
0:000>

您可以在cmd.exe中调用脚本

cat c:\autostep.txt
.if ( @@c++(r1) == 3 ) { dv } .else { t "$$>a< c:\\autostep.txt" }

cdb -c "g steptest!main;$$>a< c:\autostep.txt"  STEPTEST.exe

0:000> cdb: Reading initial command 'g steptest!main;$$>a< c:\autostep.txt'

             r1 = 0n3

eax=00000001 ebx=7ffd6000 ecx=a4894de4 edx=00000001 esi=00a2dd04 edi=00a2dd08
eip=009d6abb esp=0019f8d0 ebp=0019f8d4 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
STEPTEST!main+0x1b:
009d6abb 33c0            xor     eax,eax
0:000>

答案 1 :(得分:1)

您的命令意味着:无条件地在主函数的开头处中断。然后,如果r1> 2,什么都不做;否则,继续。

请注意,bp会占用一个地址并打破它。因为您有符号(PDB),所以您可以将符号“consoleapplication7!main”转换为地址。这指向函数的开始,其中r1尚未初始化,因此没有办法使它成为&gt; 2,除了随机垃圾值。

首先,你需要在更合理的位置打破。有多种方法可以做到这一点。您可以“解扰”汇编代码uf consoleapplication7!main并确定要中断的偏移地址。像bp ConsoleApplication7!main+0x35 "j (poi(r1) > 2) ''; 'gc'"这样的东西。这可能有点困难。假设您的main函数位于名为driver.cpp的文件中,更简单的方法是指定行号,例如bp `driver.cpp:6` "j (poi(r1) > 2) ''; 'gc'"

此外,您需要注意您的应用程序是否已针对调试或发布模式进行编译。在发布模式下,可以优化大部分主函数,因为r1的值可以在编译时预先计算。这自然会影响抵消。

最后,除非你习惯用j来表示“if”,否则我会建议使用更现代的.if (condition) { commands } .else { commands }语法。虽然他们做同样的事情,但后者更具可读性。

有关详细信息,请参阅here