*[[UNIX]]/gdb [#v1f3dc8d]
#contents

**基本 [#g7a41de1]
***コンパイル [#c5c93f1f]
 # gcc -g <ソース>
 ※ -g で追加デバッグ情報の出力が可能になる(gdb の listでソースが表示可能になる)


***オブジェクトファイルの情報を表示する [#l80299b7]
 # objdump -M intel -D <プログラム>
 ※ -M intel でシンタックスをIntel形式にする。


***オブジェクトファイルのシンボルを表示する [#idce440b]
 # nm <プログラム>


***coreファイルの解析 [#ue383619]
 # file <coreファイル名>
 ※ coreファイルの出力プログラムを確認

 # gdb <プログラム名> <コアファイル名>
 ※ プログラムが異常終了した直後の状態が再現される。

 (gdb) bt
 #0  0x00007f079fe8b6a7 in _IO_default_xsputn_internal () from /lib64/libc.so.6
 #1  0x00007f079fe5f190 in vfprintf () from /lib64/libc.so.6
 #2  0x00007f079fe80609 in vsprintf () from /lib64/libc.so.6
 #3  0x00007f079fe662b8 in sprintf () from /lib64/libc.so.6
 #4  0x0000000000400667 in GetMngFile (mngfile=0x600ae0) at test.c:27
 #5  0x00000000004005bb in main () at test.c:12
 
 (gdb) f 4
 #4  0x0000000000400667 in GetMngFile (mngfile=0x600ae0) at test.c:27
 27          sprintf(mngfile[i],"%s_%s",file,DATA);
 (gdb) print i
 $1 = 27
 (gdb) print file
 $2 = "abc", '\000' <repeats 124 times>
 (gdb) f 5
 #5  0x00000000004005bb in main () at test.c:12
 12        GetMngFile(mngfile);
 (gdb) p mngfile
 $3 = {"abc_TEST", '\000' <repeats 41 times>, "abc_TEST", '\000' <repeats 41 times>}


***レジスタ [#v0106548]
|BGCOLOR(#f0f8ff):''レジスタ''|BGCOLOR(#f0f8ff):''名称''|BGCOLOR(#f0f8ff):''説明''|
|ax|アミュレータ|大抵の場合はCPUがマシン命令を実行する際の一時変数として用いられる|
|cx|カウンタ|~|
|dx|データレジスタ|~|
|bx|ベースレジスタ|~|
|sp|スタックポインタ|メモリ上の場所を示す32bitのアドレスを格納|
|bp|ベースポインタ|~|
|si|ソースインデックス|データ読み込み参照元|
|di|デスティネーションインデックス|データ書き出し先|
|>|ip|プロセッサによって実行されようとしている現在の命令を格納|
|>|flags|比較演算、メモリのセグメント化に用いられる複数フラグから構成|
~
#br


**コマンド [#jc1128c5]
***list(l) [#jd8e23c9]
ソースプログラムを表示する

***disassemble [#kdff6200]
 disassemble <関数名>
関数の逆アセンブル結果を表示~
(シンタックスIntel形式で出力した例)
 (gdb) disassemble main
 〜省略
   0x00000000004004d5 <+17>:    mov    edi,0x4005e8
   0x00000000004004e3 <+31>:    cmp    DWORD PTR [rbp-0x4],0x4 ※1
   0x00000000004004e7 <+35>:    jle    0x4004d5 <main+17>    ※2
   0x00000000004004e9 <+37>:    mov    eax,0x0         ※3
 ※1 rbpレジスタから4を減算した値をアドレスとして用い、そのアドレスから開始している4バイトの値と数値の4を比較
 ※2 比較対象の値が4以下の場合は 4004d5 に移行する
 ※3 そうでない場合は、jle命令の次の命令を実行する


***set disassembly-flavor intel [#yaf7da59]
関数の逆アセンブルのシンタックスをIntel形式にする。~
命令語 <操作対象>, <参照元>~


***break(b) [#x43265eb]
 break { <関数名> | ステップ }
指定した関数直前で実行を止める


***watch(w) [#n9351c7f]
 watch 変数
指定した変数の値が変更されたら停止する


***info(i) [#e1d4314e]
 info registers [レジスタ](i r [レジスタ])
レジスタの内容を表示
 info break
設定したbreakポイントの表示
 info watchpoints
設定したwatchポイントの表示


***x/ [#o5f6a3de]
 x/[表示数]{表現方法}[グループ単位] 値
引数の値を様々な形式で表示する。デフォルトは16進数、4バイトを1グループ表示。x/1xw~

|BGCOLOR(#f0f8ff):''表現方法''|BGCOLOR(#f0f8ff):''説明''|BGCOLOR(#f0f8ff):''表現方法''|BGCOLOR(#f0f8ff):''説明''|
|o|8進数|c|ASCIIコード|
|x|16進数|s|全体の文字列|
|u|10進数|i|逆アセンブル?|
|t|2進数|||
|BGCOLOR(#f0f8ff):''グループ単位''|BGCOLOR(#f0f8ff):''バイト数''|BGCOLOR(#f0f8ff):''グループ単位''|BGCOLOR(#f0f8ff):''バイト数''|
|b|1byte|w|4byte|
|h|2byte|g|8byte|



***print(p) [#g627bae4]
 print[/書式] {変数 または 計算式} 
引数で指定した計算式の結果を 一時変数に格納する。書式は o x u t c s などが利用可能。~
引数で指定した計算式の結果を 一時変数に格納する。書式は x/ で使用する表現方法の値を利用する~
 (gdb) print 0x7fffffffe48c - 0x7fffffffe470
 $2 = 28


***step(s) [#h8d4d71a]
ステップイン。次の処理まで進む(関数の中に入る)


***next(n) [#o3b38fdc]
 next
ステップアウト。次の処理まで進む(関数の中はスキップ)
 next insutruction
eipが指定している命令を読み込み、それを実行し、次の命令を格納されているアドレスを差すようにeipの値を進める~


***continue(c) [#c31a170b]
breakポイントで停止したプログラムを再開させる。~


***frame(f) [#j4f04d47]
 frame <フレーム名>
関数フレームの移動~


***backtrace(bt)[full] [#j4d7b149]
呼び出している関数のネスト状態を確認。fullを付与するとローカル変数の情報も表示する~
~
#br



**サンプル [#kc687c19]
***バッファオーバーラン [#h41e9dbc]
 #include <stdio.h> 
 #include <stdlib.h> 
 #include <string.h>
 
 int check_authentication(char *password) { 
     int auth_flag = 0; 
     char password_buffer[16];
     memset(password_buffer, 0x00, sizeof(password_buffer));
     strcpy(password_buffer, password);
     if(strcmp(password_buffer, "pass") == 0) {
         auth_flag = 1;
     }
     return auth_flag;
 }
 
 int main(int argc, char *argv[]) { 
     if(argc < 2) {
         printf("使用方法: %s <パスワード>\n", argv[0]); 
         exit(0);
     }
     if(check_authentication(argv[1])) {
         printf("OK。\n"); 
     } else { 
         printf("NG。\n");     
     }
 }
 
***デバッグ [#l1550800]
""[root@cent6 kita]# &color(#ffff00){gdb ./a.out}; 
""(gdb) &color(#ffff00){b 8};
""Breakpoint 1 at 0x400637: file test.c, line 8.
""(gdb) &color(#ffff00){b 9};
""Breakpoint 2 at 0x40064d: file test.c, line 9.
""(gdb) &color(#ffff00){b 13};
""Breakpoint 3 at 0x40067c: file test.c, line 13.
""(gdb) &color(#ffff00){run AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA};
""Starting program: /root/kita/a.out AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
""
""Breakpoint 1, check_authentication (password=0x7fffffffe804 'A' <repeats 37 times>) at test.c:8
""8           memset(password_buffer, 0x00, sizeof(password_buffer));
""Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.149.el6.x86_64
""(gdb) &color(#ffff00){x/8xw password_buffer};
""0x7fffffffe480: &color(#00ffff){0xffffe5c0      0x00007fff      0x00400745      0x00000000}; &color(#00ff00){初期化されてない};
""0x7fffffffe490: 0xf7a58ba0      0x00007fff      0x00400700      0x00000000
""(gdb) &color(#ffff00){c};
""Continuing.
""
""Breakpoint 2, check_authentication (password=0x7fffffffe804 'A' <repeats 37 times>) at test.c:9
""9           strcpy(password_buffer, password);
""(gdb) &color(#ffff00){x/8xw password_buffer};
""0x7fffffffe480: &color(#00ffff){0x00000000      0x00000000      0x00000000      0x00000000}; &color(#00ff00){16byte分初期化};
""0x7fffffffe490: 0xf7a58ba0      0x00007fff      0x00400700      0x00000000
""(gdb) &color(#ffff00){x/x &auth_flag};
""&color(#00ffff){0x7fffffffe49c};: 0x00000000 &color(#00ff00){auth_flag のアドレス位置を確認};
""(gdb) &color(#ffff00){print 0x7fffffffe49c - 0x7fffffffe480};
""$1 = 28 &color(#00ff00){auth_flag は password_buffer の 28byte後にある};
""(gdb) &color(#ffff00){c};
""Continuing.
""
""Breakpoint 3, check_authentication (password=0x7fffffffe804 'A' <repeats 37 times>) at test.c:13
""13          return auth_flag;
""(gdb) x/16xw password_buffer
""0x7fffffffe480: &color(#00ffff){0x41414141      0x41414141      0x41414141      0x41414141};
""0x7fffffffe490: &color(#00ffff){0x41414141      0x41414141      0x414141&color(#ff0000){41      0x414141};41}; &color(#00ff00){auth_flag のアドレス部分まで上書きされてる};
""0x7fffffffe4a0: &color(#00ffff){0x41414141};      0x000000&color(#00ffff){41};      0x004006cf      0x00000000 &color(#00ff00){38byte分 A(0x41) がコピーされている};
""0x7fffffffe4b0: 0xffffe5a8      0x00007fff      0x00000000      0x00000002
""(gdb) &color(#ffff00){x/x &auth_flag};
""0x7fffffffe49c: &color(#ff0000){0x41414141}; &color(#00ff00){auth_flagの参照先も書き換えられている(本来は0のままを想定)};
""(gdb) &color(#ffff00){c};
""Continuing.
""OK。 &color(#00ff00){0 以外の場合は、OKとしてる為、パスワードが通ってしまう};
""
""Program received signal SIGSEGV, Segmentation fault. &color(#ffff00){バッファオーバーランによりクラッシュ};
""main (argc=Cannot access memory at address 0x414141413d
"") at test.c:26
""26      }

トップ   編集 差分 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS