dbgsymパッケージを導入してパッケージをGDBでデバッグします。
Table of Contents
1 dbgsymパッケージ用リポジトリの追加
dbgsymパッケージはddebs.ubuntu.comで公開されています。 ddebs.ubuntu.comをリポジトリに追加します。
$ U=http://ddebs.ubuntu.com $ D=$(lsb_release -cs) $ cat <<EOF | sudo tee /etc/apt/sources.list.d/ddebs.list deb ${U} ${D} main restricted universe multiverse #deb ${U} ${D}-security main restricted universe multiverse deb ${U} ${D}-updates main restricted universe multiverse deb ${U} ${D}-proposed main restricted universe multiverse EOF
GPGキーをインポートします。
$ wget -O - http://ddebs.ubuntu.com/dbgsym-release-key.asc | \ sudo apt-key add -
リポジトリのデータベースを更新します。
$ sudo apt update -y
2 dbgsymパッケージのインストール
dbgsymがついたパッケージがデバッグシンボルを含むパッケージです。
<package>-dbgsym
この記事ではbashのデバッグシンボルを取得します。
$ sudo apt install -y bash-dbgsym $ dpkg -L bash-dbgsym /. /usr /usr/lib /usr/lib/debug /usr/lib/debug/.build-id /usr/lib/debug/.build-id/16 /usr/lib/debug/.build-id/16/ef52e314889583b73f26a98eed260667fb1ed8.debug /usr/lib/debug/.build-id/60 /usr/lib/debug/.build-id/60/88017e1b386d955ce384f28b0bc642d5f6a38d.debug /usr/share /usr/share/doc /usr/share/doc/bash-dbgsym
なお、デバッグシンボルの場所を指定しなくともGDBは自動的に /usr/lib/debugへデバッグシンボルを探しに行きます。
3 デバッグするパッケージのソースコードをダウンロード
Ubuntuはデフォルトでソースコード用のリポジトリを無効にしているので、ソースコード用のリポジトリを有効にします。すでに有効にしている場合は不要です。
deb-srcを有効にします。
$ grep '^deb ' /etc/apt/sources.list | \ sed 's/^deb /deb-src /g' | \ sudo tee /etc/apt/sources.list.d/deb-src.list $ sudo apt update -y
dpkg-sourceコマンドが必要になるのでdpkg-devパッケージをインストールします。
$ sudo apt install -y dpkg-dev
デバッグするパッケージのソースコードを取得します。
$ mkdir <package> $ cd <package> $ apt source <package>
この記事ではbashのソースコードを取得します。 bash-5.0ディレクトリがソースツリーです。
$ mkdir ~/bash $ cd ~/bash $ apt source bash $ ls bash-5.0 bash_5.0-3ubuntu1.1.debian.tar.xz bash_5.0-3ubuntu1.1.dsc bash_5.0.orig.tar.xz
4 GDBのインストール
gdbをインストールします。
$ sudo apt install -y gdb
5 パッケージのデバッグ
GDBにコマンドとソースコードの場所を指定することで、GDBのシェルが起動します。
$ gdb <command> --directory /path/to/source <snip> (gdb)
bashをデバッグする場合は以下のとおりです。
$ gdb bash --directory ~/bash/bash-5.0/ <snip> (gdb) b main Breakpoint 1 at 0x2de30: file .././shell.c, line 364. (gdb) r Starting program: /usr/bin/bash Breakpoint 1, main (argc=1, argv=0x7fffffffe3b8, env=0x7fffffffe3c8) at .././shell.c:364 364 { (gdb) l 359 int 360 main (argc, argv, env) 361 int argc; 362 char **argv, **env; 363 #endif /* !NO_MAIN_ENV_ARG */ 364 { 365 register int i; 366 int code, old_errexit_flag; 367 #if defined (RESTRICTED_SHELL) 368 int saverst;
なお、la srcだとソースコードの追跡が容易です。
(gdb) la src