2017-09-03 14 views
2

プログラムをデバッグしようとしていますが、int(int i = 0; i < 10; i ++)の行に興味があり、GDBデバッガでi < 10をi < = 10に変更します。私はprintを使って変数名を変更しましたが、これをどうやって行うのですか?ありがとうございました。GDBを使用してforループ条件を変更しますか?

+0

gdbはコードを変更できません。読み取り専用に設定されています... –

+0

私は同意します:実際にデバッガ(Visual Studio?)内の*コードを置き換えることを可能にするいくつかのツールがあると思いますが、gdbがこれを行うことができるかどうかは疑問です。 – GhostCat

+0

私はレジスタを変更してジャンプ条件を反転することができますね... – arrowd

答えて

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 <[email protected]> 
    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の命令が一定9で(場所$rbp-4にスタックに保存されている)iの値を比較し、値が以下である場合にジャンプして戻ることがわかります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] 

出来上がり:私たちは、印刷しました余分な価値。

別の可能なアプローチ:0x400556の命令にブレークポイントを設定i-1iの値を調整し、シングルステップ、i+1iの値を調整し続けます。

さらに別のアプローチ:定数10の代わり9と比較する0x400556でバイナリパッチ命令:ここ

(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と比較。それは動作しますか?

(gdb) c 
Continuing. 
0 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
[Inferior 1 (process 23131) exited normally] 

はい、あります。

P.S.バイナリパッチのパッチ適用は、ソースを編集してバイナリを再構築するのと同じですが、次の場合にパッチが "忘れられ"ます。run

関連する問題