dwarf-expert について
dwarf-expertは、DWARFデバッグ情報を扱う技術スキルです。検索や検証、パーサー作成に必要な資料とツールの使い方を開発者に案内し、実行時デバッグは対象外です。
主な機能
- 01名前やアドレスによるDIE検索
- 02DWARF構造と品質の検証
- 03DWARF形式の詳細解説
- 04解析ライブラリの紹介
- 05パーサーの注意点の提示
活用シーン
- 01デバッグ情報からシンボルや項目を検索
- 02コンパイル後のデバッグ情報を検査
- 03バイナリで起きるデバッガーの問題を調査
- 04DWARF解析コードの作成やレビュー
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ trailofbits/ skills --skill dwarf-expertインストール後、Claude Code で/dwarf-expertを入力して読み込まれたか確認します。
同梱ファイルagents/openai.yamlassets/trail-of-bits-mark.svg
詳細
DWARF エキスパート
DWARF デバッグ情報の専門知識:解析と検索、整合性の検証、標準に関する質問への回答、およびそれを利用するコードの作成ができます。対象外:実行時デバッグ(gdb/lldb を使用)、DWARF セクションを超えるリバースエンジニアリング(Ghidra/IDA を使用)、コンパイラー固有の DWARF 生成バグ。
信頼できる情報源
正確さが重要な場合は、記憶に頼らず標準の詳細を調べてください。
- dwarfstd.org — 公式仕様です。たとえば「DWARF5 DW_TAG_subprogram attributes site:dwarfstd.org」のように、特定のセクションをウェブ検索してください。
- LLVM —
llvm/lib/DebugInfo/DWARF/は信頼できるリファレンス実装です。DWARFDie.cpp(DIE と属性へのアクセス)、DWARFUnit.cpp(コンパイル単位)、DWARFDebugLine.cpp(行テーブル)、DWARFVerifier.cpp(検証)を参照してください。 - libdwarf — github.com/davea42/libdwarf-code にある、C 言語によるリファレンス実装です。
dwarfdump による解析と検索
DWARF 固有の作業では、readelf より dwarfdump を優先してください。実装は libdwarf の dwarfdump と LLVM の llvm-dwarfdump の 2 種類があり、オプションも異なります。また、単に dwarfdump と入力した場合はどちらが実行されるか分からないため、まず dwarfdump --version で確認してください。以下のオプションは LLVM のものです。
macOS では、リンク済みの Mach-O 実行ファイルに DWARF は含まれません。dsymutil が DWARF を収集して .dSYM バンドルに格納するまで、DWARF は .o ファイル内に残ります。実行ファイルではなく、dSYM(またはオブジェクトファイル)を dwarfdump に指定してください。pyelftools は ELF 専用です。Mach-O をスクリプトで扱う場合は、LLVM ツールを使用してください。
--all:すべての DWARF セクションをダンプします。--debug-info、--debug-lineなどは、それぞれ単一のセクションをダンプします--show-children [--recurse-depth=<n>]:選択したエントリーを出力する際に子 DIE を含めます。パラメーター、ローカル変数、構造体メンバーは、関数および型 DIE の子です--show-parents [--parent-recurse-depth=<n>]:親 DIE を含めます--show-form:エンコーディングの詳細が必要な場合に、属性の form 型を出力します--find=<name>:アクセラレーターテーブルを使った完全一致の名前検索です。高速ですが網羅的ではありません。一致しない場合は--nameを使用してください--name=<pattern> [--ignore-case] [--regex]:DIE 名を網羅的に検索します--lookup=<address>:アドレスをカバーする DIE を検索します--verbose:低レベルのエンコーディング詳細を出力します
DIE の検索
クエリーが複雑になるにつれて、次の方法を順に試してください。
- 名前またはアドレスで一致:まず
--find、次に--nameを使用します。アドレスには--lookupを使用します。 - 属性または型のクエリー(たとえば、型が
float *のすべてのパラメーター):ダンプして絞り込みます。grep -Bを使うと、各 DIE のオフセットを含むヘッダー行を取得できます。llvm-dwarfdump file | grep -B 5 "float \*" | grep DW_TAG_formal_parameter次に、各 DIE のオフセットを指定して--debug-info=<offset> --show-childrenで出力します(--lookupが受け取るのはプログラムアドレスであり、DIE オフセットではありません)。 - 複数属性または構造に関するクエリー:grep のパイプラインが扱いにくくなったら、
pyelftoolsを使った Python スクリプトを作成してください。
DWARF の整合性を検証する
llvm-dwarfdump --verify <binary>:構造を検査します(ユニットチェーン、DIE の関係、アドレス範囲)。--error-display=<quiet|summary|details|full>で詳細レベルを制御し、--verify-json=<path>で機械可読なエラー概要を出力します。終了コードのみを確認する場合は--quietを指定します。llvm-dwarfdump --statistics <binary>:デバッグ情報の品質指標を JSON 形式で出力します。コンパイラのバージョンや最適化レベルをまたいで比較し、リグレッションを検出できます。
DWARF を生成した後(コンパイラ、バイナリ書き換えツール)、バイナリでデバッガーが正しく動作しない場合、または既知の正常なファイルを使って DWARF ツールを開発する場合に検証してください。
現行世代のコンパイラが古いバージョンの DWARF を出力した場合、ビルド時に -gdwarf-N が明示的に渡されています。最近の gcc と clang のデフォルトは v4/v5 なので、ツールチェーンのデフォルトを前提にせず、ビルドシステムを確認してください。GCC は DW_AT_producer にフラグを埋め込むため、その指定は多くの場合そこから読み取れます。clang の producer 文字列にはフラグが含まれません。古いバージョンは今でも広く使われており、表現上の違いを除けば同じ方法で読み取れます。v2 の出力では、メンバーのオフセットがロケーション式(DW_OP_plus_uconst)として、リンケージ名が DW_AT_MIPS_linkage_name として現れます。
readelf
一般的な ELF 構造を調べる場合や、dwarfdump が利用できない場合に使用します。
--debug-dump=<section>:DWARF セクション(info、lineなど)をダンプします--dwarf-depth=<n>/--dwarf-start=<n>:DIE の深さ/開始オフセットを制限します
DWARF を解析するコードを書く
手作業で解析するより、既存のライブラリを優先してください。
| ライブラリ | 言語 | 備考 |
|---|---|---|
libdwarf | C/C++ | github.com/davea42/libdwarf-code — 低レベルのライブラリで、dwarfdump の実装に使用されています |
pyelftools | Python | github.com/eliben/pyelftools — ELF 全般の解析にも対応しています |
gimli | Rust | github.com/gimli-rs/gimli — コンテナファイルを読み込むには object と組み合わせます |
debug/dwarf | Go | 標準ライブラリ |
LibObjectFile | .NET | github.com/xoofx/LibObjectFile — ELF/PE オブジェクトファイルにも対応しています |
特別な事情がない限り、単発のスクリプトには pyelftools を使う Python を標準としてください。
DWARF 固有の注意点です。DWARF コードをレビューするときにも確認してください。
- 属性は省略可能です。DIE に
DW_AT_name、DW_AT_type、範囲などが含まれない場合があります。 - 属性の間接参照:DIE の属性は、
DW_AT_abstract_origin(インライン化されたインスタンス)またはDW_AT_specification(アウトオブライン定義)が参照する DIE に存在する場合があります。データがないと判断する前に、参照チェーンを解決してください。 - 型チェーン:修飾子や修飾型(
DW_TAG_const_type、DW_TAG_pointer_typeなど)は基底の型をラップします。基底型に到達するまでDW_AT_typeのリンクをたどってください。