GDB は、プログラマーがコードをデバッグするために不可欠なツールです。
この記事では、コア ファイルを使用して gdb を使用してプログラムをデバッグする方法、プログラムのアセンブリ言語命令を表示する方法、共有ライブラリ プログラムをデバッグ用にロードする方法について説明します。
コア ファイルを使用してプログラムをデバッグする
コア ファイルまたはコア ダンプは、実行中のプロセスのメモリ イメージとその状態を記録するファイルです。これは、デバッガーの外部で実行中にクラッシュしたプログラムの事後デバッグで使用されます。
$ gdb executable_name core_file_name (gdb)
上記のコマンドは、実行可能ファイルのコア ファイルをロードし、gdb シェルを起動します。
gdb backtrace またはその他のコマンドを使用して、実際に何が起こったのかを調べることができます。実行可能ファイルが gdb で実行されている場合、core_file は無視されることに注意してください。
組み立て説明書を印刷
逆アセンブル コマンドを使用して、関数のアセンブリ命令を出力できます。 2 つのアドレス範囲を指定することもできます。それらの間の命令は逆アセンブルされ、gdb コンソールに出力されます。
(gdb) disassemble main Dump of assembler code for function main: 0x00000000004004ac : push %rbp 0x00000000004004ad : mov %rsp,%rbp 0x00000000004004b0 : mov $0x0,%eax 0x00000000004004b5 : pop %rbp 0x00000000004004b6 : retq End of assembler dump.
共有ライブラリ シンボルを読み込む
多くの場合、プログラマはコード内で共有ライブラリを使用します。何が起こっているのかを理解するために、共有ライブラリ自体を調べたい場合があります。ここでは、GLib ライブラリを使用した例と、そのデバッグ情報を取得する方法を示します。
デフォルトでは、すべてのディストリビューションでライブラリがある程度削除されます。完全なデバッグ情報は、「package-1.0-dbg」のような名前の別のパッケージに保存され、必要な場合にのみユーザーがインストールできます。
「package-1.0-dbg」をインストールすると、デフォルトで gdb がすべてのデバッグ情報をロードしますが、ここで概念を理解するために、シンボル ファイルを手動でロードする方法を説明します。
#include <stdio.h> #include <glib.h> struct a { int a; int b; }; void *print( struct a *obj,int as) { printf("%d:%d\n",obj->a,obj->b); } int main() { struct a *obj; obj = (struct a*)malloc(sizeof(struct a)); obj->a=3; obj->b=4; GList *list=NULL; list = g_list_append(list,obj); g_list_foreach(list,(GFunc)print,NULL); }
$ cc -g -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include/ -lglib-2.0 glib_test.c
注:この例を試すには、libglib2.0-0 をインストールする必要があります。
それでは、デバッグを開始します。
(gdb) b 1 Breakpoint 1 at 0x4007db: file a.c, line 1. (gdb) run ... (gdb) info sharedlibrary From To Syms Read Shared Object Library 0x00007ffff7dddaf0 0x00007ffff7df5c83 Yes (*) /lib64/ld-linux-x86-64.so.2 0x00007ffff7b016c0 0x00007ffff7b6e5cc Yes (*) /lib/x86_64-linux-gnu/libglib-2.0.so.0 0x00007ffff7779b80 0x00007ffff7890bcc Yes (*) /lib/x86_64-linux-gnu/libc.so.6 0x00007ffff751f9a0 0x00007ffff7546158 Yes (*) /lib/x86_64-linux-gnu/libpcre.so.3 0x00007ffff7307690 0x00007ffff7312c78 Yes (*) /lib/x86_64-linux-gnu/libpthread.so.0 0x00007ffff70fc190 0x00007ffff70ff4f8 Yes (*) /lib/x86_64-linux-gnu/librt.so.1 (*): Shared library is missing debugging information.
上記の情報から、ライブラリ libglib-2.0.so.0 にはシンボルがありますが、file_name、line_no などのデバッグ情報が欠落していることに注意してください。
それぞれのディストリビューションからパッケージのデバッグ情報をダウンロードします (Debian では libglib2.0-0-dbg – Wheezy)。
(gdb) add-symbol-file /home/lakshmanan/libglib-2.0.so.0.3200.4 0x00007ffff7b016c0 add symbol table from file "/home/lakshmanan/libglib-2.0.so.0.3200.4" at .text_addr = 0x7ffff7b016c0 (y or n) y Reading symbols from /home/lakshmanan/libglib-2.0.so.0.3200.4...done.
add-symbol-file コマンドで指定されたアドレスは、「info sharedlibrary」コマンドによって出力される「From」アドレスです。これでデバッグ情報が読み込まれました。
... ... (gdb) n g_list_foreach (list=0x0, func=0x4007cc , user_data=0x0) at /tmp/buildd/glib2.0-2.33.12+really2.32.4/./glib/glist.c:897
共有ライブラリにシンボルが含まれていない場合もあり、そのような状況では、上記の方法が役立ちます。