DWARF は広く使われている標準化されたデバッグ データ フォーマットです。DWARF は元々実行可能リンク可能フォーマット(ELF)と共に設計されましたが、オブジェクト ファイルフォーマットとは独立しています。[ 1 ]この名前は「ELF」に対する中世風の空想的な補足であり、公式な意味はありませんでしたが、その後「Debugging With Arbitrary Record Formats」という名前がバクロニムとして提案されました。[ 1 ]
DWARFは、Unix System V Release 4 (SVR4)のCコンパイラとsdbデバッガで誕生しました。 [ 1 ] DWARF形式などのデバッグ情報は、-gコンパイラオプションを使用すると出力されます。[ 2 ]
DWARFの最初のバージョンはストレージを過剰に使用することが判明したため、互換性のない後継バージョンであるDWARF-2が登場し、データサイズを削減するためにさまざまなエンコード方式を追加しました。DWARFはすぐに広く受け入れられたわけではありませんでした。例えば、Sun MicrosystemsがSolarisへの移行の一環としてELFを採用した際、彼らは「stabs-in-elf」と呼ばれる埋め込み方式でstabsの使用を継続することを選択しました。Linuxもこれに倣い、DWARF-2がデフォルトになったのは1990年代後半になってからのことでした。
フリースタンダードグループのDWARFワーキンググループは、2006年1月にDWARFバージョン3をリリースし[ 3 ] 、 C++名前空間、Fortran 90割り当て可能データ、追加のコンパイラ最適化技術のサポートなどを追加しました。
DWARF委員会は2010年にDWARFのバージョン4を公開し、「データ圧縮の改善、最適化されたコードのより良い記述、C++の新しい言語機能のサポート」を提供した。[ 4 ]
DWARFフォーマットのバージョン5は2017年2月に公開されました。[ 5 ] [ 6 ]このバージョンでは、「データ圧縮の改善、デバッグデータと実行可能ファイルの分離、マクロとソースファイルの記述の改善、シンボルの検索の高速化、最適化されたコードのデバッグの改善、機能とパフォーマンスの多数の改善など、多くの分野で改善が取り入れられています。」
オブジェクトファイル(実行可能ファイルを含む)では、DWARFは.debug_info、.debug_frameなど、それぞれ異なる目的を持つ複数のセクションとして格納されます。[ 7 ]
DWARF は、各変数、型、プロシージャなどを表すために、デバッグ情報エントリ (DIE) と呼ばれるデータ構造を使用します。DIE には、タグ (例: DW_TAG_variable、DW_TAG_pointer_type、DW_TAG_subprogram ) と属性 (キーと値のペア) があります。DIE はネスト (子) DIE を持つことができ、ツリー構造を形成します。DIE 属性は、ツリー内の任意の場所にある別の DIE を参照できます。たとえば、変数を表す DIE には、変数の型を記述する DIE を指すDW_AT_typeエントリがあります。これは「ローカル」参照です。DIE を使用すると、任意の他の DWARF エントリ (別の.debug_info セクションにあるエントリでも可) を参照したり、共通ブロック内のエントリを名前で参照したりできます。
DWARFには、任意の算術式のエンコーディング、特殊なDWARF式スタックマシンのバイトコードが含まれています。この式は、メモリ内の移動しないオブジェクトの場所を記述するために最も一般的に使用されます()。場所を記述するもう1つの方法は、主に可変アドレスを持つオブジェクト(動的に割り当てられたオブジェクトなど)に使用される位置リストを使用することです。[ 9 ]DW_AT_location.debug_loclist
.debug_line(および.debug_line_str)には行番号情報が含まれていますが、これは非常に冗長でありながら、通常の手段では容易に圧縮できません。DWARF は、単純な特殊目的の有限状態機械を定義する別のバイトコード形式を定義することで、この問題に対処します。このような行番号プログラムに組み込まれた FSM を実行すると、完全な行番号テーブルが出力されます。[ 10 ]
DWARF の過剰なサイズの多くは、C や C++ の多数の複雑なヘッダー インクルードなどによる重複情報に起因しています。DWARF の作成者は、DIE の参照機能を使用するよう注意する必要があります。たとえば、コードをコンパイル ユニットに、型を重複排除および容易に参照できる型ユニットに整理するなどです。各ヘッダー ファイルに独自のユニットを割り当てることも妥当かもしれません。[ 11 ]
ELFフォーマットでは、DWARF データは主に.debug、実行可能コードと同じファイル内に、標準のセクション名で格納されます.text。別の方法として、デバッグ情報 (「シンボル」) のみを含むコードのない別の ELF ファイルを作成し、必要なときにのみ DWARF データをインストールしてロードすることもできます。[ 12 ] debuginfod は、別のファイルに格納されているセクションを取得するためのプログラムです。[ 13 ]
ELF セクションとして単純に保存するだけでなく、多くのツールは DWARF セクションを圧縮するバリアントもサポートしており、必要に応じてセクションを解凍します。古い GNU スタイルでは、すべてのセクションの名前が「debug」から「zdebug」に変更されます。セクションには、圧縮方法 (通常は zlib) と元のサイズを記述するヘッダーが含まれます。新しい標準 gABI スタイルでは、ELF_COMPRESSEDセクション フラグにフラグが追加され、ほとんどの ELF セクションでこの機能を使用できるようになります。[ 14 ] DWARF に組み込まれた巧妙なエンコード スキームにもかかわらず、DWARF データは高い圧縮性を維持しています。[ 15 ]
DWARFバージョンのサポートはコンパイラとデバッガの組み合わせによって異なりますが、ほとんどの場合、DWARF 5が使用されます。
macOSで使用される Mach-O フォーマットは、stabsと DWARF をサポートしています。 stabs フォーマットは、デバッグ情報をシンボル テーブルに直接埋め込むもので、コードと一緒に直接保存される開発環境では今でもよく使われています。 DWARF データをコードと一緒に保存することも技術的には可能ですが、システムのツールは一般的に、デバッグ データがコードのない別の「dSYM」オブジェクト ファイルで提供されることを想定しています。[ 16 ]このようなオブジェクト ファイルには「__DWARF」セグメントのみが含まれており、その下に標準の DWARF セクションに対応する「__debug_info」などのラベルが付いたセクションがあります。[ 17 ]LC_SYMTAB
DWARFのバージョンは、OSのバージョンによって4または5です。圧縮されたデバッグ情報は、公式ツールでは使用も理解もされません。
Libdwarf は、実行可能ファイルとオブジェクトファイル内の DWARF デバッグ情報へのアクセスを提供するライブラリです。[ 18 ]
elfutilsには、ELFセクションを操作するためのツールが含まれています。たとえば、デバッグ情報をファイルにマージしたり、別のファイルに分割したりできます。
Michael Eager, chair of the DWARF Standards Committee, has written an introduction to debugging formats and DWARF 3, Introduction to the DWARF Debugging Format.[1]