gccで作ったC言語のプログラムを、gdbコマンドを使用してデバッグしてみます。
今回の実験環境は以下の通り。
linux環境でテストしてますが、cygwinでも問題なく動作するはずです…
$ gcc --version gcc (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1 $ gdb --version GNU gdb (Ubuntu/Linaro 7.3-0ubuntu2) 7.3-2011.08 $ uname -a Linux linuxmint 3.0.0-12-generic #20-Ubuntu SMP Fri Oct 7 14:50:42 UTC 2011 i686 i686 i386 GNU/Linux |
今回実験で使うソースコードです。
単なる足し算プログラムです。
/* test01.c */ #include <stdio.h> int sum( int a, int b ); int main() { int a = 10; int b = a * 2; int ans = sum( a, b ); printf( "%d\n", ans ); return 0; } int sum( int a, int b ) { int result = a + b; return result; } |
これをコンパイルします。
コンパイル時に-gでデバッグ情報を埋め込むと共に、-O0で最適化を抑制します。
また、-Sオプションでアセンブラのコードも出力しておきます。
$ gcc -g -O0 -o test01 test01.c $ gcc -S -O0 test01.c $ ls test01 test01.c test01.s |
出来上がったtest01.sはこんな感じ。
.file "test01.c" .section .rodata .LC0: .string "%d\n" .text .globl main .type main, @function main: .LFB0: .cfi_startproc pushl %ebp .cfi_def_cfa_offset 8 .cfi_offset 5, -8 movl %esp, %ebp .cfi_def_cfa_register 5 andl $-16, %esp subl $32, %esp movl $10, 20(%esp) movl 20(%esp), %eax addl %eax, %eax movl %eax, 24(%esp) movl 24(%esp), %eax movl %eax, 4(%esp) movl 20(%esp), %eax movl %eax, (%esp) call sum movl %eax, 28(%esp) movl $.LC0, %eax movl 28(%esp), %edx movl %edx, 4(%esp) movl %eax, (%esp) call printf movl $0, %eax leave .cfi_restore 5 .cfi_def_cfa 4, 4 ret .cfi_endproc .LFE0: .size main, .-main .globl sum .type sum, @function sum: .LFB1: .cfi_startproc pushl %ebp .cfi_def_cfa_offset 8 .cfi_offset 5, -8 movl %esp, %ebp .cfi_def_cfa_register 5 subl $16, %esp movl 12(%ebp), %eax movl 8(%ebp), %edx addl %edx, %eax movl %eax, -4(%ebp) movl -4(%ebp), %eax leave .cfi_restore 5 .cfi_def_cfa 4, 4 ret .cfi_endproc .LFE1: .size sum, .-sum .ident "GCC: (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1" .section .note.GNU-stack,"",@progbits |
作ったプログラムをgdbに読み込ませます。
$ gdb ./test01 GNU gdb (Ubuntu/Linaro 7.3-0ubuntu2) 7.3-2011.08 Copyright (C) 2011 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "i686-linux-gnu". For bug reporting instructions, please see: <http://bugs.launchpad.net/gdb-linaro/>... Reading symbols from /home/user/work/test01...done. |
コンパイル時に-gオプションを付け忘れると、最後の行が以下の出力になります。
デバッグシンボルが無いよ。と怒られてます。
Reading symbols from /home/user/work/test01...(no debugging symbols found)...done. |
listコマンドでソースを確認します。
オプションをつけると、行番号指定や関数名指定で表示する事ができます。
(gdb) list 1 #include <stdio.h> 2 3 int sum( int a, int b ); 4 5 int main() 6 { 7 8 int a = 10; 9 int b = a * 2; 10 (gdb) list 5, 12 5 int main() 6 { 7 8 int a = 10; 9 int b = a * 2; 10 11 int ans = sum( a, b ); 12 printf( "%d\n", ans ); (gdb) list sum 12 printf( "%d\n", ans ); 13 return 0; 14 } 15 16 int sum( int a, int b ) 17 { 18 int result = a + b; 19 return result; 20 } |
bコマンド(break)で、ブレークポイントをセットできます。
(gdb) b 8 Breakpoint 1 at 0x80483ed: file test01.c, line 8. |
startでプログラムの実行開始です。
ブレークポイントを設定していたので、8行目で止まりました。
nextコマンドでもう1行だけ進めます。
(gdb) start Temporary breakpoint 2 at 0x80483ed: file test01.c, line 8. Starting program: /home/user1/work/test01 Breakpoint 1, main () at test01.c:8 8 int a = 10; (gdb) next 9 int b = a * 2; |
info bで、ブレークポイント一覧が確認できます。
(gdb) info b Num Type Disp Enb Address What 1 breakpoint keep y 0x080483ed in main at test01.c:8 breakpoint already hit 1 time |
printで変数の中身を表示します。
変数bは、まだ初期化されてないので不定値が入ってます。
(gdb) print a $2 = 10 (gdb) print b $3 = 134513753 |
もう一行進めたらセットされました。
(gdb) next 11 int ans = sum( a, b ); (gdb) print b $4 = 20 |
変数のアドレスも確認できます。
(gdb) print &a $5 = (int *) 0xbffff874 (gdb) print &b $6 = (int *) 0xbffff878 |
長くなってきたので、続きは次の記事へ…
次記事 -> gdbによるデバッグのチュートリアル その2
続きはでは、レジスタとスタック領域の使われ方を確認します。
関連記事
コメントを残す