使用GDB更改for循环条件?

时间:2017-09-03 18:13:37

标签: c loops debugging gdb

我正在尝试调试一个程序并且对(int i = 0; i< 10; i ++)的行感兴趣 并希望在GDB调试器中将i< 10更改为i< = 10。我用print来改变变量名,但是我该如何做呢?谢谢。

1 个答案:

答案 0 :(得分:2)

  

希望在GDB调试器中将i< 10更改为i< = 10。

有几种方法可以做到这一点,具体取决于完全你需要的东西。

我假设您只需要执行一次,即在x86_64上构建您的二进制文件而不进行优化。

假设:

#include <stdio.h>
int main()
{
  for (int i = 0; i < 10; i++)
    printf("%d\n", i);
  return 0;
}

gcc -g -std=c99 t.c && gdb -q ./a.out

gdb) disas main
Dump of assembler code for function main:
   0x000000000040052d <+0>:     push   %rbp
   0x000000000040052e <+1>:     mov    %rsp,%rbp
   0x0000000000400531 <+4>:     sub    $0x10,%rsp
   0x0000000000400535 <+8>:     movl   $0x0,-0x4(%rbp)
   0x000000000040053c <+15>:    jmp    0x400556 <main+41>
   0x000000000040053e <+17>:    mov    -0x4(%rbp),%eax
   0x0000000000400541 <+20>:    mov    %eax,%esi
   0x0000000000400543 <+22>:    mov    $0x4005f4,%edi
   0x0000000000400548 <+27>:    mov    $0x0,%eax
   0x000000000040054d <+32>:    callq  0x400410 <printf@plt>
   0x0000000000400552 <+37>:    addl   $0x1,-0x4(%rbp)
   0x0000000000400556 <+41>:    cmpl   $0x9,-0x4(%rbp)
   0x000000000040055a <+45>:    jle    0x40053e <main+17>
   0x000000000040055c <+47>:    mov    $0x0,%eax
   0x0000000000400561 <+52>:    leaveq 
   0x0000000000400562 <+53>:    retq   
End of assembler dump.

在这里,您可以看到地址0x400556处的指令将i(存储在位置$rbp-4上的堆栈中)的值与常量9进行比较,如果值小于或等于9

所以你可以在0x40055a的指令上设置一个断点,然后强制即使编译后的代码说它不应该是:

(gdb) b *0x40055a if i == 10
Breakpoint 1 at 0x40055a: file t.c, line 4.
(gdb) run
Starting program: /tmp/a.out 
0
1
2
3
4
5
6
7
8
9

Breakpoint 1, 0x000000000040055a in main () at t.c:4
4             for (int i = 0; i < 10; i++)
(gdb) p i
$1 = 10
(gdb) jump *0x40053e
Continuing at 0x40053e.
10
[Inferior 1 (process 22210) exited normally]

Voila:我们已经打印了额外的价值。

另一种可能的方法:在0x400556处的指令上设置断点,将i的值调整为i-1,单步,将i的值调整为{ {1}},继续。

另一种方法:对i+1处的指令进行二进制修补以与常量0x400556进行比较,而不是10

9

在这里你可以看到常量(gdb) disas/r 0x400556,0x400557 Dump of assembler code from 0x400556 to 0x400557: 0x0000000000400556 <main+41>: 83 7d fc 09 cmpl $0x9,-0x4(%rbp) End of assembler dump. 是指令字节的一部分,特别是地址9的字节。您可以更改该字节:

0x400559

让我们覆盖指令并再次反汇编:

(gdb) start

Starting program: /tmp/a.out 

Temporary breakpoint 1, main () at t.c:4
4             for (int i = 0; i < 10; i++)

看起来不错:我们现在与(gdb) set *(char*)0x400559 = 10 (gdb) disas/r 0x400556,0x400557 Dump of assembler code from 0x400556 to 0x400557: 0x0000000000400556 <main+41>: 83 7d fc 0a cmpl $0xa,-0x4(%rbp) End of assembler dump. 而不是10进行比较。它有效吗?

9

是的,确实如此!

P.S。对指令进行二进制修补相当于编辑源代码并重建二进制文件,除了修补程序被遗忘&#34;在下一个(gdb) c Continuing. 0 1 2 3 4 5 6 7 8 9 10 [Inferior 1 (process 23131) exited normally]