gdb手順

使用するコード


適当に。

/*test3.c*/
#include

int sub();

int main(){
printf("main\n");
sub();
return 0;
}

int sub(){
printf("sub\n");
return 0;
}


ただこの関数にいますよーって表示するだけのプログラム。

コンパイル


-gオプションを付けてコンパイルする。

%gcc -g -o test3 test3.c


%ls
test.c test3.dSYM test3


なんかへんなファイルが増えてる。こいつが gdb で読むのに必要。

gdb起動


gdbを起動する。引数は実行ファイル。

%gdb test
GNU gdb 6.3.50-20050815 (Apple version gdb-1705) (Fri Jul 1 10:50:06 UTC 2011)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "x86_64-apple-darwin"...Reading symbols for shared libraries .. done

(gdb)


上は起動直後。(gdb)の後に gdb 用のコマンドを打ち込んで使う。今はプログラムが止まっている状態。ここから、ブレークポイントを設定しプログラムを run する。

(gdb) b sub
Breakpoint 1 at 0x100000ec4: file test3.c, line 12.


ブレークポイントの設定。b は break の b。b の後には、関数名やメソッド名、行数などが入る。今回は関数 sub を使用。

(gdb) r
Starting program: /Users/User/programing/C/test3
Reading symbols for shared libraries +........................ done
main

Breakpoint 1, sub () at test3.c:12
12 printf("sub\n");


上は起動。これでプログラムが動き、sub で止まった状態になる。
次は list 機能 l を試す。

(gdb) l
7 sub();
8 return 0;
9 }
10
11 int sub(){
12 printf("sub\n");
13 return 0;
14 }
(gdb)


プログラムのコードが見れる。
次はこれを進めていく。
step の s を使用する。

(gdb) s
sub
13 return 0;


少し進んだ。コード中の

printf("sub\n");

も実行されている。

(gdb)
main () at test3.c:8
8 return 0;


s を再実行。ただエンターキーを押すだけで、前回実行したものを実行できる。覚えておくと便利。

(gdb)
Cannot access memory at address 0x0
0x0000000100000e74 in start ()


continue の c で、プログラムを終了や次のブレークポイントまで飛ばす。

(gdb) c
Continuing.

Program exited normally.


これでプログラムが終了。
プログラムが終ってしまったので、最実行する。次はブレークポイントを3行目に設定。

(gdb) b 3
Breakpoint 2 at 0x100000e84: file test3.c, line 3.


info b で ブレークポイントの情報が見れる。下のように表示される。

(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x0000000100000ec4 in sub at test3.c:12
2 breakpoint keep y 0x0000000100000e84 in main at test3.c:3
breakpoint already hit 1 time


このブレークポイントを、番号を指定して消去することができる。
delete の d のあとに、info b で見たブレークポイントの番号を指定すると消去。

(gdb) d 1
(gdb) info b
Num Type Disp Enb Address What
2 breakpoint keep y 0x0000000100000e84 in main at test3.c:3
breakpoint already hit 1 time


next の n は関数へ入らない。関数を読み飛ばす事ができる。
以下はブレークポイント2はそのままで最実行し、コマンド n を実行した時のもの。

(gdb) n
main
7 sub();
(gdb)
sub
8 return 0;


関数 sub() に入らず、main 関数の return 0; へ進んでいる。
次は finish/fin の使用例。これも一旦終わらせて、ブレークポイントを sub() のなか(12行目)に設定して新しく run した後に fin を実行している。

(gdb) fin
Run till exit from #0 sub () at test3.c:12
sub
main () at test.c:8
8 return 0;
Value returned is $1 = 0


fin は今いる関数を終わらせるものである。上記の例では関数 sub の中で始まっているが、fin を実行すると sub() が終了している。

(gdb) where
#0 sub () at test3.c:12
#1 0x0000000100000ea0 in main () at test3.c:7


これも、ブレークポイントが12行目の関数 sub() の中のままのもの。
where は関数を積んでいるスタックを見るものである。スタックなので、一番初めに読む main が下に来ており、次に sub() が着ている。

関数 test.c に以下の行を追加する。

int = i;


print の p で変数表示。以下が上の i を p で表示した結果である。

(gdb) p i
$1 = 3


以上、大体これくらいわかってればいいっぽい。アセンブラをはかすなら

(gdb)disas(gdb) disas
Dump of assembler code for function main:
0x0000000100000e80 : push %rbp
0x0000000100000e81 : mov %rsp,%rbp
0x0000000100000e84 : sub $0x10,%rsp
0x0000000100000e88 : movl $0x3,-0xc(%rbp)
0x0000000100000e8f : lea 0x8a(%rip),%rax # 0x100000f20
0x0000000100000e96 : mov %rax,%rdi
0x0000000100000e99 : callq 0x100000ef4
0x0000000100000e9e : xor %cl,%cl
0x0000000100000ea0 : mov %cl,%al
0x0000000100000ea2 : callq 0x100000ec0
0x0000000100000ea7 : movl $0x0,-0x8(%rbp)
0x0000000100000eae : mov -0x8(%rbp),%eax
0x0000000100000eb1 : mov %eax,-0x4(%rbp)
0x0000000100000eb4 : mov -0x4(%rbp),%eax
0x0000000100000eb7 : add $0x10,%rsp
0x0000000100000ebb : pop %rbp
0x0000000100000ebc : retq
End of assembler dump.


とかあったりもする。
ここまで見るのはバイナリハッカーとか言うらしい。なりたい。

とりあえず今日はここまで。



コメント

このブログの人気の投稿

相互インクルード対策

make error "Circular"

gdb操作