おしながき

ELFファイルフォーマット

  • .eh_frameセクションの構造と読み方

DWARFファイルフォーマット

NCURSESライブラリ

  • NCURSES Programing HOWTO ワタクシ的ほんやく
    1. Tools and Widget Libraries
    2. Just For Fun !!!
    3. References
  • その他、自分メモ
  • NCURSES雑多な自分メモ01


最近の更新 (Recent Changes)

2019-09-24
2013-10-10
2013-10-03
2013-10-01
2013-09-29
目次に戻る:DWARFファイルフォーマット

デバッグ情報とDIE(.debug_info/.debug_abbrevセクションの概要)

DWARF内での「デバッグ情報」

DWARFという、実行ファイル内のデータには、デバッグに必要なさまざまな情報を書いてあるデータが書いてあって、それらはELFセクションとの関係に書いた通り、UNIXの実行ファイル形式ELFの「セクション」内に「.debug_xxxx」なセクション名でいろいろ書かれているんだよって、書きましたが。。。。

実は、この最大全部で11あるセクションのうち、".debug_line"、".debug_frame"、".debug_macinfo"の3つ以外は、全部ここに書く".debug_abbrev"、".debug_info"セクションで表される「デバッグ情報」と、この「デバッグ情報」を補助するための子分セクションです。
つまり、デバッガが必要とするデバッグ用の情報のうち、ほとんどはこの「デバッグ情報」に書かれています!
つーじょう、こいつだけ読みさえすれば、「ソース行番号とアセンブラコードアドレスの関係」「今実行中の関数の開始アドレスと、呼び出した関数の情報(スタックトレース用の情報)」以外のほぼ全てが手に入ります。
じゃ、どんな情報があるのか?以下、一例ですが、ざっと上げてみます。(あ、ちなみにこれ以外もいろいろあります。そのうち、一覧で並べますです)

  • Cソースファイル単位の情報(開始実行アドレス、終了実行アドレスなど)
  • 関数名と関数の引数(型や名前など)、およびそれらが配置されているメモリアドレス
  • 型のビットサイズや名称 (言語で定義されているが、DWARFはいろんな言語をサポートしているので、これも書かれます)
  • C++のtry/catch
  • enum型の名前
  • 構造体/共用体(念のため、unionです)/クラスとメンバ、メソッド

などなど。
あと、この中で例えば「enum型の名前」なんて物はソース解析すりゃわかんじゃん、となりますが、DWARFはC/C++/JAVA/Fortran/PASCAL/ObjectCに加え、なんとAdaやPL/I、Modula2、Dまでサポート扱いです!それどころか、メーカーが勝手!に作った言語まで、コンパイラが適切にDWARF吐いてくれたら対応できますよーに、ということを想定して作られているので、デバッガがいちいち言語毎にソース解析ロジックを持たなくても最低限度済むよう、こういった情報まで持っています。
(なので、パソコンはもちろん、ボーイング777やF22からスパコン、IBMメインフレームまでデバッグできるみたいです。。。にしてもCOBOLがないのはなんでだろ〜)

※あ、あと以下では、これらの情報のことをまとめて「デバッグ情報」ってよびますです。


「デバッグ情報」の格納のされ方

この「デバッグ情報」ですが、まともに、というか、何にも考えずにそのまんま突っ込もうとすると、ベラボウなデータ量になってしまうようなので、データ量を削減する工夫として、以下2種類の情報に分けて格納するようにしています。

例えば、C言語の「関数」に関するデバッグ情報があったとします。このとき、以下の様に「データ格納構造」と「実際のデータ」に分けることができます。

  • C言語の「関数」に関するデバッグ情報としては、関数名(文字列)、開始アドレス(アドレス)、終了アドレス(アドレス)、引数の数(数値)、戻り値の有無(フラグ)、を持つ
    • これは、関数という種類のデバッグ情報における「データ格納構造」 いわゆる、メタデータですね。
  • デバッグ情報として記録したいのは、関数名func1で、0x400500〜0x4005b3までの範囲にコードがあり、引数はint型の名前cが1つで、戻り値もint型
    • これは、関数func1に関する、デバッグ情報の「実際のデータ」ですね。


そして、C言語では、一般に関数ってもんはめちゃくちゃ数があります。ただし、上の、関数のデバッグ情報の「データ格納構造」は、ほとんどのケースで、おんなじデータ格納構造が使いまわせそうですね。
ということで、データ量の削減が第一!とするDWARF君では、上記の例のように「データ格納構造」と「実際のデータ」を分割し、「データ格納構造」は使い廻すことで、データ量の削減をはかっています。

※仮に、上の例で、全ての関数毎にデータ格納構造をデータとして決めてから、実データを書くフォーマットにしてしまうと、分かりやすくなるかもしれませんが、データ量はとってもとんでもないことになっちゃいます。。。


そして、この「データ格納構造」「実際のデータ」別に、以下のセクションに情報を分割して書く仕様になっています。

「データ格納構造」 → .debug_abbrevセクション
「実際のデータ」 → .debug_infoセクション


んで、これ以上は、ぐちゃぐちゃ書くよりも実際のデータ見た方が、分かりやすい、ので、以下実機データです。

実際の.debug_abbrevと.debug_infoの例

まず、サンプル(いけにえ)のC言語ソースです。

#include<stdio.h>

int             a;

void func2( int *b )    {
        *b = 3;

        return;
}

int func1( int a, int *b)       {
        int             c;

        func2( b );
        c = a + *b;

        return c;       
}

int main( int argc, char *argv[])       {
        int             b;
        int             c;

        a = 1;
        c = func1( a, &b );
        printf("a=%d, b=%d, c=%d\n", a, b, c);

        return;
}

さて、このイケニエ君ソースを、

gcc -o test -g main.c
で、デバッグ情報を付けてね、ってちゅーもん付きでコンパイルして、作ってくれた実行ファイルを
readelf -w test
なおまじない!をもって、吐かせた.debug_abbrevと.debug_infoの解析結果を、以下はっちゃいます。
まず、.debug_abbrev (行番号を付けました)
     1  Contents of the .debug_abbrev section:
     2  
     3    Number TAG
     4     1      DW_TAG_compile_unit    [has children]
     5      DW_AT_producer     DW_FORM_string
     6      DW_AT_language     DW_FORM_data1
     7      DW_AT_name         DW_FORM_string
     8      DW_AT_comp_dir     DW_FORM_string
     9      DW_AT_low_pc       DW_FORM_addr
    10      DW_AT_high_pc      DW_FORM_addr
    11      DW_AT_stmt_list    DW_FORM_data4
    12     2      DW_TAG_base_type    [no children]
    13      DW_AT_byte_size    DW_FORM_data1
    14      DW_AT_encoding     DW_FORM_data1
    15      DW_AT_name         DW_FORM_string
    16     3      DW_TAG_base_type    [no children]
    17      DW_AT_byte_size    DW_FORM_data1
    18      DW_AT_encoding     DW_FORM_data1
    19     4      DW_TAG_pointer_type    [no children]
    20      DW_AT_byte_size    DW_FORM_data1
    21      DW_AT_type         DW_FORM_ref4
    22     5      DW_TAG_subprogram    [has children]
    23      DW_AT_external     DW_FORM_flag
    24      DW_AT_name         DW_FORM_string
    25      DW_AT_decl_file    DW_FORM_data1
    26      DW_AT_decl_line    DW_FORM_data1
    27      DW_AT_prototyped   DW_FORM_flag
    28      DW_AT_low_pc       DW_FORM_addr
    29      DW_AT_high_pc      DW_FORM_addr
    30      DW_AT_frame_base   DW_FORM_data4
    31      DW_AT_sibling      DW_FORM_ref4
    32     6      DW_TAG_formal_parameter    [no children]
    33      DW_AT_name         DW_FORM_string
    34      DW_AT_decl_file    DW_FORM_data1
    35      DW_AT_decl_line    DW_FORM_data1
    36      DW_AT_type         DW_FORM_ref4
    37      DW_AT_location     DW_FORM_block1
    38     7      DW_TAG_subprogram    [has children]
    39      DW_AT_external     DW_FORM_flag
    40      DW_AT_name         DW_FORM_string
    41      DW_AT_decl_file    DW_FORM_data1
    42      DW_AT_decl_line    DW_FORM_data1
    43      DW_AT_prototyped   DW_FORM_flag
    44      DW_AT_type         DW_FORM_ref4
    45      DW_AT_low_pc       DW_FORM_addr
    46      DW_AT_high_pc      DW_FORM_addr
    47      DW_AT_frame_base   DW_FORM_data4
    48      DW_AT_sibling      DW_FORM_ref4
    49     8      DW_TAG_variable    [no children]
    50      DW_AT_name         DW_FORM_string
    51      DW_AT_decl_file    DW_FORM_data1
    52      DW_AT_decl_line    DW_FORM_data1
    53      DW_AT_type         DW_FORM_ref4
    54      DW_AT_location     DW_FORM_block1
    55     9      DW_TAG_variable    [no children]
    56      DW_AT_name         DW_FORM_string
    57      DW_AT_decl_file    DW_FORM_data1
    58      DW_AT_decl_line    DW_FORM_data1
    59      DW_AT_type         DW_FORM_ref4
    60      DW_AT_external     DW_FORM_flag
    61      DW_AT_location     DW_FORM_block1

つぎに、.debug_infoっす。(こいつは、長すぎるんで、一部はしょり+一部、改変あり+行番号つけちゃいました)
     1  The section .debug_info contains:
     2  
     3    Compilation Unit @ offset 0x0:
     4     Length:        510
     5     Version:       2
     6     Abbrev Offset: 0
     7     Pointer Size:  8
     8   <0><b>: Abbrev Number: 1 (DW_TAG_compile_unit)
     9    < c>     DW_AT_producer    : GNU C 4.2.1 20070831 patched [FreeBSD]   
    10    <33>     DW_AT_language    : 1        (ANSI C)
    11    <34>     DW_AT_name        : main.c   
    12    <3b>     DW_AT_comp_dir    : /work/test/dwarftest2    
    13    <55>     DW_AT_low_pc      : 0x4005b0 
    14    <5d>     DW_AT_high_pc     : 0x400648 
    15    <65>     DW_AT_stmt_list   : 0        
    16   <1><69>: Abbrev Number: 2 (DW_TAG_base_type)
    17    <6a>     DW_AT_byte_size   : 1        
    18    <6b>     DW_AT_encoding    : 6        (signed char)
    19    <6c>     DW_AT_name        : signed char      
    20         <一部、はしょってます>
    21   <1><ac>: Abbrev Number: 2 (DW_TAG_base_type)
    22    <ad>     DW_AT_byte_size   : 4        
    23    <ae>     DW_AT_encoding    : 5        (signed)
    24    <af>     DW_AT_name        : int      
    25         <一部、はしょってます>
    26   <1><f7>: Abbrev Number: 3 (DW_TAG_base_type)
    27    <f8>     DW_AT_byte_size   : 8        
    28    <f9>     DW_AT_encoding    : 7        (unsigned)
    29         <一部、はしょってます>
    30   <1><102>: Abbrev Number: 4 (DW_TAG_pointer_type)
    31    <103>     DW_AT_byte_size   : 8       
    32    <104>     DW_AT_type        : <fa>    
    33   <1><108>: Abbrev Number: 5 (DW_TAG_subprogram)
    34    <109>     DW_AT_external    : 1       
    35    <10a>     DW_AT_name        : func2   
    36    <110>     DW_AT_decl_file   : 1       
    37    <111>     DW_AT_decl_line   : 6       
    38    <112>     DW_AT_prototyped  : 1       
    39    <113>     DW_AT_low_pc      : 0x4005b0        
    40    <11b>     DW_AT_high_pc     : 0x4005c4        
    41    <123>     DW_AT_frame_base  : 0       (location list)
    42    <127>     DW_AT_sibling     : <138>   
    43       <2><12b>: Abbrev Number: 6 (DW_TAG_formal_parameter)
    44         <12c>     DW_AT_name        : b       
    45         <12e>     DW_AT_decl_file   : 1       
    46         <12f>     DW_AT_decl_line   : 6       
    47         <130>     DW_AT_type        : <138>   
    48         <134>     DW_AT_location    : 2 byte block: 91 68     (DW_OP_fbreg: -24)
    49   <1><138>: Abbrev Number: 4 (DW_TAG_pointer_type)
    50    <139>     DW_AT_byte_size   : 8       
    51    <13a>     DW_AT_type        : <ac>    
    52   <1><13e>: Abbrev Number: 7 (DW_TAG_subprogram)
    53    <13f>     DW_AT_external    : 1       
    54    <140>     DW_AT_name        : func1   
    55    <146>     DW_AT_decl_file   : 1       
    56    <147>     DW_AT_decl_line   : 13      
    57    <148>     DW_AT_prototyped  : 1       
    58    <149>     DW_AT_type        : <ac>    
    59    <14d>     DW_AT_low_pc      : 0x4005d0        
    60    <155>     DW_AT_high_pc     : 0x4005f9        
    61    <15d>     DW_AT_frame_base  : 0x4c    (location list)
    62    <161>     DW_AT_sibling     : <18a>   
    63       <2><165>: Abbrev Number: 6 (DW_TAG_formal_parameter)
    64          <166>     DW_AT_nam e        : a       
    65          <168>     DW_AT_decl_file   : 1       
    66          <169>     DW_AT_decl_line   : 13      
    67          <16a>     DW_AT_type        : <ac>    
    68          <16e>     DW_AT_location    : 2 byte block: 91 5c     (DW_OP_fbreg: -36)
    69       <2><171>: Abbrev Number: 6 (DW_TAG_formal_parameter)
    70          <172>     DW_AT_name        : b       
    71          <174>     DW_AT_decl_file   : 1       
    72          <175>     DW_AT_decl_line   : 13      
    73          <176>     DW_AT_type        : <138>   
    74          <17a>     DW_AT_location    : 2 byte block: 91 50     (DW_OP_fbreg: -48)
    75       <2><17d>: Abbrev Number: 8 (DW_TAG_variable)
    76          <17e>     DW_AT_name        : c       
    77          <180>     DW_AT_decl_file   : 1       
    78          <181>     DW_AT_decl_line   : 14      
    79          <182>     DW_AT_type        : <ac>    
    80          <186>     DW_AT_location    : 2 byte block: 91 6c     (DW_OP_fbreg: -20)
    81   <1><18a>: Abbrev Number: 7 (DW_TAG_subprogram)
    82    <18b>     DW_AT_external    : 1       
    83    <18c>     DW_AT_name        : main    
    84    <191>     DW_AT_decl_file   : 1       
    85    <192>     DW_AT_decl_line   : 23      
    86    <193>     DW_AT_prototyped  : 1       
    87    <194>     DW_AT_type        : <ac>    
    88    <198>     DW_AT_low_pc      : 0x400600        
    89    <1a0>     DW_AT_high_pc     : 0x400648        
    90    <1a8>     DW_AT_frame_base  : 0x98    (location list)
    91    <1ac>     DW_AT_sibling     : <1e7>   
    92           <以降、けっこうはしょってます>


.debug_abbrev(データ格納構造)の基本のせつめい

上で出した例、もちっと詳しくみてみますです。まず、データ格納構造から。で、説明のために、まず.debug_abbrevの例から以下の部分をひっこぬいてみました。

    38     7      DW_TAG_subprogram    [has children]
    39      DW_AT_external     DW_FORM_flag
    40      DW_AT_name         DW_FORM_string
    41      DW_AT_decl_file    DW_FORM_data1
    42      DW_AT_decl_line    DW_FORM_data1
    43      DW_AT_prototyped   DW_FORM_flag
    44      DW_AT_type         DW_FORM_ref4
    45      DW_AT_low_pc       DW_FORM_addr
    46      DW_AT_high_pc      DW_FORM_addr
    47      DW_AT_frame_base   DW_FORM_data4
    48      DW_AT_sibling      DW_FORM_ref4
.debug_abbrev、すなわちデータ格納構造のデータは、上記の様な塊が、なんか羅列されてます。
で、どの塊も、最初の行は
    7      DW_TAG_subprogram    [has children]
の様な感じですね。これにはちゃんと意味があって、以下となるです。
例の表記 名称 ごせつめい
"7" Abbrev番号(Abbrev ID) 「データ格納構造」毎に割り振られた、ユニークな数字です。ようするに、DWARF内での「データ格納構造」のお名前だと思ってください。
"DW_TAG_subprogram" TAG名 この「データ格納構造」が、何に関するデバッグ用の情報を格納するためのデータ構造か、の種類を特定するためのIDです。
このTAG名は、(そのうち作るよ)にあり一覧の数だけあります。
この例は、C言語ソース内の関数(subprogram)の情報を書くための「データ格納構造」だよってことを意味しています
has children 子データの存在有無 この「データ格納構造」は、子扱いのデバッグ用データ構造を持つか、を示します。
例えば、関数のデータ構造(例)の場合、関数の引数は、この関数に関連する情報ですよね。なので、関数の引数のデバッグ情報は、関数のデバッグ情報の子ということになります。
これは、こう書いてもうーんなんで、下の.debug_infoでメモります


次に、その下の行ですね。これは

    DW_AT_external     DW_FORM_flag
です。これは、関数のデバッグ情報(DW_TAG_subprogram)が持つデバッグ情報の「属性」と「属性値の型」を示しています。
上の例であれば、

  • DW_AT_external
    • この例の場合、(恐らく)この関数は、「外部に公開されている関数か否か」の情報を持っている。ということを意味してます。
    • DW_AT_xxxxと表記されます。んで、通常これらをAttribute(属性)って呼んでいます。
  • DW_FORM_flag
    • "DW_AT_external"の属性が持つデータは、どのようなデータ型/表現形式で格納されているのか、を示す情報です。
    • この例では、フラグ形式、つまり、trueかfalseの2値しかもたないよ、ってことを示しています。
      (で、別のページ(そのうち)に整理しますが、この値は具体的に.debug_infoセクション内のデータとして、何byteでどういった値でture/falseを格納しているのか、までこれから分かるようになっています)
    • DWARFでは、DW_FORM_xxxと表記されます。

そして、続く行では、DW_AT_xxxxとDW_FORM_yyyyが続いていますね。これらの意味は、ざっと以下です。

    38     7      DW_TAG_subprogram    [has children]
    39      DW_AT_external     DW_FORM_flag
    40      DW_AT_name         DW_FORM_string       # 関数名: 文字列で格納されている
    41      DW_AT_decl_file    DW_FORM_data1        # 関数が定義されたソースファイル名: .debug_line内のファイル名テーブルのIDを1Byte数値としてもつ
    42      DW_AT_decl_line    DW_FORM_data1       # 関数の開始行: .debug_line内でのソース行とプログラムコードアドレス関係表の開始位置を1Byte数値としてもつ
    43      DW_AT_prototyped   DW_FORM_flag         # (恐らく)プロトタイプ宣言かどうか? : true/falseのフラグ形式で
    44      DW_AT_type         DW_FORM_ref4             # (恐らく)関数の戻り値の型?: DWARF内のオフセットを4Byteで?
    45      DW_AT_low_pc       DW_FORM_addr         # プログラムコード上での関数開始アドレス: アドレス形式で(64bitなら8byte)
    46      DW_AT_high_pc      DW_FORM_addr        # プログラムコード上での関数終了アドレス: アドレス形式で
    47      DW_AT_frame_base   DW_FORM_data4   # 関数のFrameBase : (まだ調査未だが)4Byteのデータ?
    48      DW_AT_sibling      DW_FORM_ref4            # このデータ構造の子ではに、次のデータ構造の.debug_info内での開始オフセット(.debug_infoの先頭から): 4byteのオフセット値
上のコメントでは、まだDW_AT_xxxxx、DW_FORM_yyyyyを調べ切ってないので、恐らく、とか、未調査、とか書きましたが、TAG/AT/FORMはそれぞれ一覧で整理します(そのうち)
また、このTAG/AT/FORMやchildrenの情報が、具体的にどうやって.debug_abbrevに書かれているか、は、.debug_abbrevの構造で見ていきますです。
(今は、あ、.debug_abbrevってこげな感じって位で大丈夫っぽいです)


.debug_info(実際のデータ)のごせつめい

ということで、次に.debug_infoです。まず、以下の部分がイケニエです。

    52   <1><13e>: Abbrev Number: 7 (DW_TAG_subprogram)
    53    <13f>     DW_AT_external    : 1       
    54    <140>     DW_AT_name        : func1   
    55    <146>     DW_AT_decl_file   : 1       
    56    <147>     DW_AT_decl_line   : 13      
    57    <148>     DW_AT_prototyped  : 1       
    58    <149>     DW_AT_type        : <ac>    
    59    <14d>     DW_AT_low_pc      : 0x4005d0        
    60    <155>     DW_AT_high_pc     : 0x4005f9        
    61    <15d>     DW_AT_frame_base  : 0x4c    (location list)
    62    <161>     DW_AT_sibling     : <18a>   
    63       <2><165>: Abbrev Number: 6 (DW_TAG_formal_parameter)
    64          <166>     DW_AT_nam e        : a       
    65          <168>     DW_AT_decl_file   : 1       
    66          <169>     DW_AT_decl_line   : 13      
    67          <16a>     DW_AT_type        : <ac>    
    68          <16e>     DW_AT_location    : 2 byte block: 91 5c     (DW_OP_fbreg: -36)
この.debug_infoでは、頭になんかヘッダっぽいものがありますが、とりあえず無視して、この部分を見て行きます。
最初に見て欲しいのは、上の例だと52-62行目、(インデントは少しずれていますが)63-68行目は、いずれも同じ構造です(Abbrev Numberってある行が1行目で、あとはDW_AT_xxxの行が続く)
ここで、まずメモるのは、この構造のことを「Debug Informatin Entry (DIE)」って呼びます。上の例でもそうですが、このDIE単位で、例えば52-62行目のDIEは関数の情報、63-68行目のDIEは引数の情報、と言う感じで使います。
これ、この後連呼することになっちゃうので、意識しておきましょうです。

で、1行目。
     <1><13e>: Abbrev Number: 7 (DW_TAG_subprogram)
この行の意味ですが、以下です。

  • <1> : 親子の階層番号
    • 0なら、これはソースファイルのデバッグ情報になります。(DW_TAG_compile_unit)
    • 1なら、ソースファイル直下にある位置付けの、デバッグ情報です。
    • 2なら、その前(上の行)のDIEをたどって行って、最初に1になるDIEの子DIEである、という意味。
    • 3以降は、2の時と同じ考え方 (ただ、3のケースみたことない。。。)
    • (参考)この値は、.debug_infoには含まれていません。(readelf君が分かりやすさのために、吐いてくれている情報です)
  • <13e> :.debug_offsetの先頭からのオフセット
    • ただし、これはreadelf君が便宜上出力してくれているもので、実際の.debug_info内には書かれていません。
  • Abbrev Number 7 : このDIEの「データ格納構造」が書かれたAbbrev IDを指す。
    • この例では、Abbrev ID= 7 の「データ格納構造」にしたがって、以下データを格納するよん、って宣言になってます。
    • ところで。。。.debug_abbrevのAbbrev ID=7は、DW_TAG_subprogramでした。すなわち、このDIEは関数の情報です。ってことになります。
    • (ポイント) .debug_infoの、該当するDIEのデータ列の一番最初に書かれている情報は、このAbbrev IDです。
  • (DW_TAG_subprogram )
    • Abbrev Number から、readelf君がわざわざAbbrevを調べてくれて、何の情報か、TAG名を出力してくれているだけです。(.debug_infoには、この値は書いていません)

ここで、重要なのはただ1つで、DIEの冒頭でまずどの「データ格納構造」で記述されたデバッグ情報か、ということを、Abbrev IDを使って示している、ということです。
んで、この部分だけは全てのDIEで共通にしておくことで、関数やら変数やら型定義やら、どんなデバッグ情報の格納にも「DIE」を使って対応できるようにしている、ということです。

で、次2行目です。

    53    <13f>     DW_AT_external    : 1       
で、これ、1行目のごせつめいで、Abbrev ID=7の構造にそって、このDIEの情報は格納されていることが分かってます。ので、Abbrev ID=7を見てやると
    38     7      DW_TAG_subprogram    [has children]
    39      DW_AT_external     DW_FORM_flag
    40      DW_AT_name         DW_FORM_string
    41      DW_AT_decl_file    DW_FORM_data1
    42      DW_AT_decl_line    DW_FORM_data1
    43      DW_AT_prototyped   DW_FORM_flag
    44      DW_AT_type         DW_FORM_ref4
    45      DW_AT_low_pc       DW_FORM_addr
    46      DW_AT_high_pc      DW_FORM_addr
    47      DW_AT_frame_base   DW_FORM_data4
    48      DW_AT_sibling      DW_FORM_ref4
ですから、この2行目は
    39      DW_AT_external     DW_FORM_flag
に該当することが分かります。よって、このデータの型はDW_FORM_flagであり、その値、つまり実際に.debug_infoに含まれている値は「1」ということになりますね。

次、3行目。
    54    <140>     DW_AT_name        : func1   
これも、Abbrev ID=7の3行目が、
    40      DW_AT_name         DW_FORM_string
になっていますから、.debug_infoに持っている値は「文字列」ということが分かり、その文字列は「func1」である、というふうにreadelf君が解析した、と言うことを示しています。

言うまでもなく、この後の行もおんなじですので、もう割愛しますです。(あ、ただし、.debug_infoの解析結果の62行目まで、の話ですおんなじなのは。それ以降の次のDIEは以下参照)

で、次のDIEを見て行きます。.debug_infoのreadelf君報告では、以下の部分です。
    63       <2><165>: Abbrev Number: 6 (DW_TAG_formal_parameter)
    64          <166>     DW_AT_name        : a       
    65          <168>     DW_AT_decl_file   : 1       
    66          <169>     DW_AT_decl_line   : 13      
    67          <16a>     DW_AT_type        : <ac>    
    68          <16e>     DW_AT_location    : 2 byte block: 91 5c     (DW_OP_fbreg: -36)
では、このDIEも1行づつ。。。といきたいところですが、これも、見てみると、前のDIEと構造自体は、おんなじですね。
また、Abbrev ID=6は以下なので、.debug_abbrev側のデータは
    32     6      DW_TAG_formal_parameter    [no children]
    33      DW_AT_name         DW_FORM_string
    34      DW_AT_decl_file    DW_FORM_data1
    35      DW_AT_decl_line    DW_FORM_data1
    36      DW_AT_type         DW_FORM_ref4
    37      DW_AT_location     DW_FORM_block1
なわけでして、これ.debug_info側と構造、とーぜん一致しています。ので、1行づつ見て行かなくても、大丈夫そうです。

ただ、1点だけ違いがあります。それは、
    63       <2><165>: Abbrev Number: 6 (DW_TAG_formal_parameter)
の先頭です。"<2>"になっています=「子供DIE」です!
これは、前に見たDIEのデータ構造であるAbbrev ID=7が"has children"になっているので、それに続くDIEは「子供DIE」になるためです!
では、「子供DIE」ってという話になるわけですが、これ良く見て見ましょう。2つめのDIEのDW_AT_nameの値は、"a"になっていますね。
で、この「親DIE」のDW_AT_nameは、"func1"です。ので、この関数func1のCソースを見てやると
int func1( int a, int *b)       {
であります。 で、引数の1つめは。。。変数aですね!
ということで、なぜ変数aのDIEは関数func1の「子供DIE」かというと、変数aは関数func1の中で定義されている変数だからです。
では、引数2つめは、func1内の変数cは、というと、.debug_infoのreadelf君情報では、
    69       <2><171>: Abbrev Number: 6 (DW_TAG_formal_parameter)
    70          <172>     DW_AT_name        : b       
        (中略)
    75       <2><17d>: Abbrev Number: 8 (DW_TAG_variable)
    76          <17e>     DW_AT_name        : c       
となっていますので、きちんと表現されてるっぽいですね。
「子供DIE」の正確な定義はよー分かってない、のですが、少なくとも、C言語では関数内の情報=関数の子供DIE扱い、は確実です。
あと、上でふれた通り、ソースファイルのデバッグ情報は"<0>"ではじまります。すなわち、関数のデバッグ情報の冒頭は"<1>"ではじまりますんで、これも「ソースファイルのDIEの子供DIE」と解釈することができます。

最後に、.debug_infoの以下の部分を見てくださいです。
    75       <2><17d>: Abbrev Number: 8 (DW_TAG_variable)
    76          <17e>     DW_AT_name        : c       
    77          <180>     DW_AT_decl_file   : 1       
    78          <181>     DW_AT_decl_line   : 14      
    79          <182>     DW_AT_type        : <ac>    
    80          <186>     DW_AT_location    : 2 byte block: 91 6c     (DW_OP_fbreg: -20)
    81   <1><18a>: Abbrev Number: 7 (DW_TAG_subprogram)
    82    <18b>     DW_AT_external    : 1       
    83    <18c>     DW_AT_name        : main    
80行目は、見ての通り子供DIEの行です。で、次の81行目は"<1>"になっていますんで、これは「関数の子供DIE」ではないことが分かります。(ちなみに、こいつはその下の83行目から、main関数ってわかります)
では、「どこで子供DIEの終りが分かるのか」ということになってしまいます。
この答えですが

.debug_info内で、「Abbrev ID=0のDIEは、子供DIEを終え、1つ上のレベルのDIEに戻す。」という意味、とすることで、終了判別しています

上記の.debug_infoのreadelf君解析結果では、Abbrev ID=0の情報は、分かりにくくなるのでカットしていますが、実際の.debug_infoのデータでは、上記の80行目と81行目の間に、Abbrev ID=0 (バイナリで0x00だけ)のDIEを持っていることになります。
なお、ここでいう81行目main関数のDIEも、CソースのDIEの「子供DIE」扱い(だから、"<1>"からはじまる)としていますので、1つのCソースのデバッグ情報終りにも、Abbrev ID=0だけのDIEが来ます。
注意したいのは、「.debug_abbrevには、その構造が子供DIEを持つか、の情報は含むものの、子供DIEであることを終え、1つ上の世代(レベル)のDIEであることを示す情報は.debug_infoにある」ということです。

※これが最初わからなくて、わたくしはひじょーに困りました。。。(英語力が足りない、と言うだけなのですがね。。。)


この後のせつめい

ここまでで、DWARFなデバッグ情報のメイン所である、.debug_abbrev/.debug_infoセクションの大まかな構造、関連になるです。
んで、あとはというと、以下のことが分かれば、もうDWARFはほとんど読めたってことになりそう、ってことも分かって来ました。

  • .debug_abbrevセクションの具体的なデータの格納方法
  • .debug_infoセクションの具体的なデータ格納方法
  • TAG名(DW_TAG_xxxx)の一覧、値と意味
  • Attribute(属性名:DW_AT_yyyyyy)の一覧、値と意味
  • データ形式(DW_FORM_zzzzz)の一覧と意味

おおざっぱにいって、これらの情報があれば、後は読んでいくだけ、と言う風になりそうです。ってことで、Dr.demon64に着手した際の最大難関と見られた、DWARF解析もようやっと見えて来ました、ということで、次からはこれを見て行きますです。


目次に戻る:DWARFファイルフォーマット