デバッグ/トレースを取得
この記事では Arch パッケージを作成するときにトレースを取得したり、開発者にソフトウェアのバグを報告するのに役立つデバッグ情報を集める方法を解説します。
通常、実行可能ファイルは、サイズを小さくするために、人間の読める情報が取り除かれています。それだけでなく、そもそも、拡張されたデバッグ情報も通常、実行ファイルに追加されないので、トレースの品質が大幅に劣化します。なので、デバッグ情報のあるトレースを得る前に、デバッグ情報を取り除かずにパッケージを再ビルドする必要があります。
発見したバグを開発者に知らせるときは完全なスタックトレースを使ってください。プログラムの開発に役に立ちます。
目次
パッケージの名前
以下のようなデバッグメッセージが表示される場合:
[...] Backtrace was generated from '/usr/bin/epiphany' (no debugging symbols found) Using host libthread_db library "/lib/libthread_db.so.1". (no debugging symbols found) [Thread debugging using libthread_db enabled] [New Thread -1241265952 (LWP 12630)] (no debugging symbols found) 0xb7f25410 in __kernel_vsyscall () #0 0xb7f25410 in __kernel_vsyscall () #1 0xb741b45b in ?? () from /lib/libpthread.so.0 [...]
??
はデバッグ情報が存在していないために関数を呼び出しているライブラリ・実行可能ファイルがわからないことを意味しています。同じように (no debugging symbols found)
と表示されたら、その下に出力されたファイルを確認してください。例えば pacman を使用して確認するには:
$ pacman -Qo /lib/libthread_db.so.1 /lib/libthread_db.so.1 is owned by glibc 2.5-8
パッケージの名前は glibc でバージョンが 2.5-8 とわかりました。デバッグが必要なパッケージの数だけ同じ手順を繰り返してください。
デバッグ情報
公式リポジトリ でサポートしているパッケージ [1] では、debuginfod を使って HTTP で直接デバッグ情報を取得することができます。
gdb は、DEBUGINFOD_URLS
環境変数 が設定されている場合に、それらを自動的にダウンロードすることを提案します。
この変数はデフォルトで /etc/profile.d/
に設定されます。
$ gdb application
This GDB supports auto-downloading debuginfo from the following URLs: <https://debuginfod.archlinux.org> Enable debuginfod for this session? (y or [n]) y Debuginfod has been enabled. To make this setting permanent, add 'set debuginfod enabled on' to .gdbinit. Downloading separate debug info for /usr/bin/application Reading symbols from /home/user/.cache/debuginfod_client/fbaee841e2ed2c11ecbbda26f39eeec1da23d6c3/debuginfo...
debuginfo サポートを有効にしたら、トレースの取得 に進むことができます。
マニュアルダウンロード
zstd のデバッグシンボルといくつかのソースファイルを手動で取得したい場合は、debuginfod-find を利用できます。
$ debuginfod-find debuginfo /usr/bin/zstd
/home/user/.cache/debuginfod_client/70e1b456c5813658df6436a3deb71812e75a0267/debuginfo
$ debuginfod-find source /usr/bin/zstd /usr/src/debug/zstd-1.5.2/programs/fileio.c
/home/user/.cache/debuginfod_client/70e1b456c5813658df6436a3deb71812e75a0267/source##usr##src##debug##zstd-1.5.2##programs##fileio.c
デバッグ情報を手動で取得する
最初に行うことは、再構築が必です または デバッグパッケージのインストール のパッケージの名前を取得することです。
[...] Backtrace was generated from '/usr/bin/epiphany' (no debugging symbols found) Using host libthread_db library "/lib/libthread_db.so.1". (no debugging symbols found) [...]
たとえば、トレースからの上記の抜粋の場合、関連するパッケージのパッケージ名は pacman で取得できます。
$ pacman -Qo /lib/libthread_db.so.1
/lib/libthread_db.so.1 is owned by glibc 2.5-8
このパッケージは、バージョン 2.5-8 glibc という名前です。デバッグ情報が必要なパッケージごとにこの手順を繰り返します。
デバッグパッケージをインストールする
現在、いくつかのミラーがアクセス可能なリポジトリにデバッグパッケージを配布しています。これらは Arch Linux によって制御されるスポンサー付きミラーであり、デバッグリポジトリへのアクセスが許可されています。
- https://geo.mirror.pkgbuild.com (GeoDNS mirror)
パッケージをインストールするには、リポジトリから直接インストールできます。例えば:
# pacman -U https://geo.mirror.pkgbuild.com/core-debug/os/x86_64/zstd-debug-1.5.2-2-x86_64.pkg.tar.zst
もう 1 つのオプションは、pacman 設定にリポジトリを追加することです。
/etc/pacman.conf
# Testing Repositories [core-testing-debug] Include = /etc/pacman.d/mirrorlist [extra-testing-debug] Include = /etc/pacman.d/mirrorlist [multilib-testing-debug] Include = /etc/pacman.d/mirrorlist # Stable repositories [core-debug] Include = /etc/pacman.d/mirrorlist [extra-debug] Include = /etc/pacman.d/mirrorlist [multilib-debug] Include = /etc/pacman.d/mirrorlist
デバッグパッケージを含むミラーをミラーリストファイルの最初のミラーとして配置します。
/etc/pacman.d/mirrorlist
Server = https://geo.mirror.pkgbuild.com/$repo/os/$arch ...
パッケージを再構築する
デバッグ情報が debuginfod を通じて公開されていない場合 (たとえば、パッケージが AUR から生成されている場合)、ソースから再構築できます。公式リポジトリ のパッケージについては ABS を、AUR のパッケージについては Arch User Repository#ビルドファイルを取得する を参照してください。
ここで、デバッグ目的でしか makepkg を使用しない場合は makepkg
のグローバルな設定ファイルを編集してください。そうではない場合は、リビルドしたいパッケージの PKGBUILD だけを修正してください。
コンパイル設定
pacman 4.1 現在、/etc/makepkg.conf
のデバッグコンパイルフラグには DEBUG_CFLAGS
と DEBUG_CXXFLAGS
があります。これらを使うには、makepkg オプションの debug
を有効化して strip
を無効化してください。
OPTIONS+=(debug !strip)
以上の設定で強制的にデバッグシンボルを生成するようにコンパイルされ、実行可能ファイルからシンボルが排除されなくなります。特定のパッケージに適用するときは、PKGBUILD を修正してください:
options=(debug !strip)
もしくは別のパッケージで debug
と strip
を有効にして、メインのパッケージからデバッグシンボルは取り除き、ソースコードを用意込みでデバッガでステップ実行できるよう、 foo-debug
パッケージでデバッグ情報を使うようにすることもできます。
Glibc
glibc など特定のパッケージは設定に関係なくデバッグ情報が取り除かれます。PKGBUILD の中を確認してください:
strip $STRIP_BINARIES usr/bin/{gencat,getconf,getent,iconv,iconvconfig} \ usr/bin/{ldconfig,locale,localedef,nscd,makedb} \ usr/bin/{pcprofiledump,pldd,rpcgen,sln,sprof} \ usr/lib/getconf/* strip $STRIP_STATIC usr/lib/*.a strip $STRIP_SHARED usr/lib/{libanl,libBrokenLocale,libcidn,libcrypt}-*.so \ usr/lib/libnss_{compat,db,dns,files,hesiod,nis,nisplus}-*.so \ usr/lib/{libdl,libm,libnsl,libresolv,librt,libutil}-*.so \ usr/lib/{libmemusage,libpcprofile,libSegFault}.so \ usr/lib/{audit,gconv}/*.so
そして必要であれば記述を削除してください。
Clang
Clang をコンパイラとして使用するパッケージは、デバッグフラグ -fvar-tracking-assignments'
が処理されないため、debug
オプションではビルドされません (例: js78)
影響を受けるパッケージのフラグのみを削除するには、build()
関数の先頭に次のコードを追加します。
build() { CFLAGS=${CFLAGS/-fvar-tracking-assignments} CXXFLAGS=${CXXFLAGS/-fvar-tracking-assignments} [...]
パッケージのビルドとインストール
PKGBUILD のディレクトリから makepkg
を使ってソースからパッケージを作成します。多少時間がかかります:
$ makepkg
そしてビルドしたパッケージをインストールしてください:
# pacman -U glibc-2.26-1-x86_64.pkg.tar.gz
トレースの取得
バックトレース (またはスタックトレース) は GNU Debugger gdb で取得できます。次を実行:
# gdb /path/to/file
または:
# gdb (gdb) exec /path/to/file
既に $PATH
変数に実行可能ファイルが設定されている場合はパスは必要ありません。
次に、gdb
の中で、起動したいプログラムに付けたい引数を付けて run
を入力します、例:
(gdb) run --no-daemon --verbose
これでファイルの実行が開始されます。バグが再現する操作を行なってください。ログを出力するには以下を入力:
(gdb) set logging file trace.log (gdb) set logging on
そして:
(gdb) thread apply all bt full
これで gdb
が起動したディレクトリの中の trace.log
にトレースが出力されます。終了するには、次を入力:
(gdb) set logging off (gdb) quit
実行中のアプリケーションをデバッグすることもできます、例:
# gdb --pid=$(pidof firefox) (gdb) continue
クラッシュしたアプリケーションをデバッグしたいときは、コアダンプ に対して gdb を起動すると良いでしょう。