デバッグ/トレースを取得

提供: ArchWiki
ナビゲーションに移動 検索に移動

関連記事

この記事では 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 とわかりました。デバッグが必要なパッケージの数だけ同じ手順を繰り返してください。

Debuginfod

公式リポジトリ でサポートしているパッケージ [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 によって Arch Linux Archive にアーカイブされません。

現在、いくつかのミラーがアクセス可能なリポジトリにデバッグパッケージを配布しています。これらは Arch Linux によって制御されるスポンサー付きミラーであり、デバッグリポジトリへのアクセスが許可されています。

パッケージをインストールするには、リポジトリから直接インストールできます。例えば:

# pacman -U https://geo.mirror.pkgbuild.com/core-debug/os/x86_64/zstd-debug-1.5.2-2-x86_64.pkg.tar.zst
警告: 両方のミラーが同期していない場合、1 つの ミラー からのデバッグパッケージは、別のミラーからの通常のパッケージと互換性がなく、ビルドが一致しません。この場合、異なるミラーからのパッケージを混合することは避けてください (部分アップグレード が発生します) ただし、すべてのリポジトリが debug ミラーを指すようにしてください。
この記事あるいはセクションは 公式リポジトリ と合併することが議論されています。
ノート: 公式リポジトリには、デバッグパッケージを配布する専用ページ (議論: トーク:デバッグ/トレースを取得#mirrors があります。)

もう 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_CFLAGSDEBUG_CXXFLAGS があります。これらを使うには、makepkg オプションの debug を有効化して strip を無効化してください。

OPTIONS+=(debug !strip)

以上の設定で強制的にデバッグシンボルを生成するようにコンパイルされ、実行可能ファイルからシンボルが排除されなくなります。特定のパッケージに適用するときは、PKGBUILD を修正してください:

options=(debug !strip)

もしくは別のパッケージで debugstrip を有効にして、メインのパッケージからデバッグシンボルは取り除き、ソースコードを用意込みでデバッガでステップ実行できるよう、 foo-debug パッケージでデバッグ情報を使うようにすることもできます。

ノート: 新しくコンパイルしたデバッグパッケージをインストールするだけでは不十分です。デバッガは関連するライブラリや実行ファイルと同じビルドからデバッグシンボルが含まれたファイルを確認するためです。再コンパイルしたパッケージを両方ともインストールしてください。Arch ではデバッグシンボルファイルは /usr/lib/debug に、ソースコードは /usr/src/debug にインストールされます。デバッグパッケージについて詳しくは GDB のドキュメント を参照してください。
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}
[...]
LTO

リンク時最適化 (LTO) を使用すると、コンパイル時とデバッガーの両方で、より多くのメモリを使用します [2] [3] アプリケーションによっては、特に Firefox や Qt のような大規模なアプリケーションの場合、使用可能なメモリを超える可能性があります。この問題が発生した場合は、LTO を使用せずにアプリケーションをビルドしてください。

公式リポジトリ内のすべてのパッケージは通常、LTO でビルドされます。

パッケージのビルドとインストール

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
ヒント: Python で書かれているアプリケーションをデバッグするには:
# gdb /usr/bin/python
(gdb) run <python application>

実行中のアプリケーションをデバッグすることもできます、例:

 # gdb --pid=$(pidof firefox)
 (gdb) continue

クラッシュしたアプリケーションをデバッグしたいときは、コアダンプ に対して gdb を起動すると良いでしょう。

参照

翻訳ステータス: このページは en:Debugging/Getting traces の翻訳バージョンです。最後の翻訳日は 2023-10-15 です。もし英語版に 変更 があれば、翻訳の同期を手伝うことができます。