Ubuntu 16.04: デバッグシンボルでパッケージをデバッグする

dbgsymパッケージを導入してパッケージをGDBでデバッグします。

1 dbgsymパッケージ用リポジトリの追加

dbgsymパッケージはddebs.ubuntu.comで公開されています。ddebs.ubuntu.comをリポジトリに追加します。

$ D=`lsb_release -cs`
$ sudo su -c "
cat <<EOF > /etc/apt/sources.list.d/ddebs.list
deb http://ddebs.ubuntu.com ${D} main restricted universe multiverse
deb http://ddebs.ubuntu.com ${D}-security main restricted universe multiverse
deb http://ddebs.ubuntu.com ${D}-updates main restricted universe multiverse
#deb http://ddebs.ubuntu.com ${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/usr
/usr/lib/debug/usr/bin
/usr/lib/debug/usr/bin/clear_console
/usr/lib/debug/bin
/usr/lib/debug/bin/bash

なお、デバッグシンボルの場所を指定しなくともGDBは自動的に/usr/lib/debugへデバッグシンボルを探しに行きます。

3 デバッグするパッケージのソースコードをダウンロード

Ubuntu 16.04はデフォルトでソースコード用のリポジトリを無効にしているので、ソースコード用のリポジトリを有効にします。すでに有効にしている場合は不要です。

$ sudo su -c "grep '^deb ' /etc/apt/sources.list | \
sed 's/^deb/deb-src/g' > /etc/apt/sources.list.d/src.list"

リポジトリのデータベースを更新します。

$ sudo apt update -y

デバッグするパッケージのソースコードを取得します。

$ mkdir <package>
$ cd <package>
$ apt source <package>

この記事ではbashのソースコードを取得します。

$ mkdir ~/bash
$ cd ~/bash
$ apt source bash
$ ls
bash-4.3                            bash_4.3-14ubuntu1.1.dsc
bash_4.3-14ubuntu1.1.debian.tar.xz  bash_4.3.orig.tar.gz

4 GDBのインストール

64bit環境の場合はgdb64をインストールします。

$ sudo apt install -y gdb64

32bit環境の場合はgdbをお使いください。

5 パッケージのデバッグ

GDBにコマンドとソースコードの場所を指定することで、GDBのシェルが起動します。

$ gdb64 <command> --directory /path/to/source
<snip>
(gdb)

bashをデバッグする場合は以下のとおりです。

$ gdb64 bash --directory ~/bash/bash-4.3/
<snip>
(gdb) b main
Breakpoint 1 at 0x41eed0: file .././shell.c, line 361.
(gdb) r
Starting program: /bin/bash
warning: the debug information found in "/lib64/ld-2.23.so" does not
match "/lib64/ld-linux-x86-64.so.2" (CRC mismatch).


Breakpoint 1, main (argc=1, argv=0x7fffffffe1d8, env=0x7fffffffe1e8) at .././shell.c:361
warning: Source file is more recent than executable.
361     {
(gdb) l
356     int
357     main (argc, argv, env)
358          int argc;
359          char **argv, **env;
360     #endif /* !NO_MAIN_ENV_ARG */
361     {
362       register int i;
363       int code, old_errexit_flag;
364     #if defined (RESTRICTED_SHELL)
365       int saverst;

なお、la srcだとソースコードの追跡が容易です。

(gdb) la src

0001_gdb-la-src.png