我试图学习如何在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
这一次,它没有语法问题,当它没有像我预期的那样中断/停止时。我错过了什么吗?
感谢。
答案 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。