おしながき

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ファイルフォーマット

TAG詳細(その06) 変数/関数の引数/定数編 ※variable、formal_parameter、constant

「データオブジェクト」ってなに、という話ですが、これめちゃくちゃ簡単で、「変数」「関数の引数」「定数」の3つのことです!
これらは、基本みな同じよーな方法で、表現できちゃいます。ということで、これを原文翻訳です。
なお、以下の前提です。「データオブジェクト」なる言葉をようしょようしょで使ってますが、これ「変数」「関数の引数」「定数」全部まとめたいーかたです。

使われるTAG

先に挙げた3つは、それぞれまずDW_TAG_xxxxが異なります。ということで、まずこれを以下に。

No. TAG名 使用目的
1 DW_TAG_variable 変数。なお、この変数は、ソース上でintとかfloatとかで宣言したものだす。
注意: 「関数の引数」は含みません! それは、次の行デス。(宣言方法同じでも別扱い)
2 DW_TAG_formal_parameter 関数の引数
3 DW_TAG_constant 定数。オンコーディングやマクロ定数などです


取り得るAttribute

上の3つのTAGは、いずれも以下表に列挙するAttributeを持っていることがあります。(もちろん、DWARFでのAttributeの原則として、以下に挙げるもの必ず持っている必要はない、が前提です)

No. Attribute名 ご、せ、つ、め、い
1 DW_AT_name ソースコード上でのデータオブジェクトの名称デス。
(NULL文字終端の文字列)
※なお、C++の匿名unionは、Attributeがないか、0Byteの空文字列デス。
2 DW_AT_external 対象のデータオブジェクトが該当のCompilation Unit(オブジェクトファイル)外で定義されているかどうかの「フラグ」
よーするに、”extern宣言”されているかどうか。外部ファイルで定義されているなら、trueになる。
なお、C++のクラス内でstaticな宣言されているメンバ変数は、”true”になる。
但し、CやC++で、ソースファイル単位でstatic宣言したヤツとかファイル内でグローバルなヤツは”false”になるルール
3 DW_AT_declaration 対象のデータオブジェクトが宣言されていない場合は、”true”
※宣言されていない場合、がTrueなので注意っす!
※明記ないですが、これ多分、宣言されていない、とする対象の範囲は、親DIEのスコープの範囲内、という意味です。
つまり、例えば親DIEがDW_TAG_subprogramなら、その関数の{と}の中で宣言されているかどうか、ってことです。
4 DW_AT_location 実行時の対象の変数、引数の(メモリ上の)格納場所
(注意1) DW_AT_declarationがなく、変数の定義がソース上でなされているケースにおいて、もしこのDW_AT_locaitonなAttributeが存在しないか、DW_AT_locationの値がNULLな記述であったときは、この変数はソースコード上に存在していても実行プログラム上、すなわちメモリ上には存在しないのデス。
※原文に書いてないけど、まぁ最適化でぶっとばされちゃったよねこの変数orそもそも使ってない変数をソース上に書いてWarnと泣かれている場合かな
(注意2) ソース上で宣言していない変数のケースでは、特定されたメモリ上の格納場所は、その変数のスコープの範囲内のみにおいて、(別のソース上なので)定義された場所に修正されますです。
さらに、このケースにおいて格納場所が特定できない場合は、(宣言されている別ソース上の)格納場所が適用されます。
※注意2はなんとなくわかるけど、なんとなく分からない。。。(英語力不足か?)
5 DW_AT_type 対象のデータオブジェクトの「型」でございます。
6 DW_AT_specification * (パターン1) C++において、クラス/構造体/共用体にstatic宣言されたデータメンバ(が対象の変数となっている場合)、このデータメンバの宣言を指し示すための属性
リンクしている先は、DW_TAG_memberなDIEで、このメンバを持っているクラス/構造体/共用体のTAGの子DIEになっているヤツになるです。

* (パターン2) もし(親DIEのスコープの範囲内で)宣言されていない変数の場合、変数を宣言しているTAGへのリンクを持ってます。
(親DIEで宣言されていない変数で、かつ)仮にこのAttributeが存在しなければ、それは対象のCompile Unit(オブジェクトファイル)上か、もしくは他のCompile Unit上(DW_AT_external=trueが必要)でのグローバルな宣言になっているです。

このAttributeを持つ変数のDIEは、このAttributeによって参照される、変数宣言のDIEの情報を重複して持つ必要はない。特に、これに該当する変数のDIEは、それによって宣言されたデータメンバの名前や型のAttributeを含む必要はない。
(この最後の下りは直訳です。何ゆーとるの?)
7 DW_AT_variable_parameter (DW_TAG_formal_parameterの場合のみ)
呼び出した関数への引数の値を、呼び出された関数が変更する場合、この属性が”true”になるです。
この属性が存在しない場合は、呼び出された関数側で引数の値を変えることはないという意味です。
※これつまり、Cではかんけーなさそーです。(引数は値で渡すか、ポインタ経由参照渡しだけど、ポインタ経由参照渡しとして、ポインタ(アドレス)自体は呼び出され側では変えられない。。。)
8 DW_is_optional (恐らく、DW_TAG_formal_parameterのみ)
引数がオプション扱い(存在するかどうか分からない)ものである場合、”true”に。
VARGですね。よーはprintfです。
9 DW_AT_default_value (DW_TAG_formal_parameterのみ)
このAttributeの値は、「引数の初期値」なんです。ただ、これちょいとパターンがあってめんどいので、以下「(No.9) DW_AT_default_valueの詳細」を参照です。
10 DW_AT_const_value 「文字列」「いくつかの定数値データ」「変数の値を示すのに適当なデータブロック(恐らく中身はDWARF Expression)」のいずれかの形式による、ターゲットとするアーキ上での定数値です。
このAttributeは、以下条件のいずれかに該当する引数/変数の場合、格納場所のAttribute(DW_AT_location)を持たない代わりに、もっていることになっているらしいです。
(条件1) 引数/変数が定数値で、かつプログラムのアドレス空間上にこのデータオブジェクトが表示されない場合
(条件2) 固定名称を表現するDIEの場合(つまり、文字列?)
11 DW_AT_start_scope こいつは、対象のデータオブジェクトが有効となるメモリアドレスの位置を示すモンです。
が、これも結構説明がメンドイので、以下(No.11) DW_AT_start_scopeを見てくださいなです。
12 DW_AT_endianity ターゲットマシンのABIで決められたデータオブジェクトの「エンディアン」を示す、固定値です。
このAttributeがない場合、もしくは値が0の場合は、(そのターゲットマシンでの前提とする)エンディアンになるです。
値の一覧は、以下「(No.12) DW_AT_endianityの値と意味」を参照すべしです。


(No.9) DW_AT_default_valueの詳細

これは、上表の通り「関数の引数の初期値」なんですが、このAttributeの値次第で、以下の解釈パターンがありますです。
上の表の中に表書くと、めんどいので、以下表にマトメマス。

パターン DW_FORM_zzzzのデータクラス +の条件 解釈
パターン1 ”reference”データクラス
(他のDIEへの参照の場合)
参照先DIEがDW_TAG_variable 引数の初期値=リンク先の「変数」デス
パターン2 ”reference”データクラス
(他のDIEへの参照の場合)
参照先DIEがDW_TAG_constant 引数の初期値=リンク先の「定数」になるです
パターン3 ”reference”データクラス 参照先DIEがDW_TAG_subprogramなど関数系 関数の戻り値が引数の初期値じゃ。
パターン4 DW_FORM_zzzzな値自体が
”0”の場合
(なし) 引数の初期値 → 初期値の特定不可能
パターン5 ”constant”データクラス(定数)の場合 (なし) 引数の初期値 → 指定された定数が初期値で、DW_TAG_formal_parameterの型の数値

※なお、データクラスがconstantの場合、初期値なし、と表現する方法なく、必ず初期値の指定がなされるルールです。


(No.11) DW_AT_start_scopeの詳細

この属性は、説明よりもまず先に例を見るほーが簡単です。ので、

    float    x = 99.99;

    int func()    {
        float    f = x;
        float    x = 88.99;
        return 0;
    }

※ソース例は、原文から引用しますた。ども。

で、この例で、変数xに着目です。本来、funcな関数内で宣言しているローカル変数xは、この関数内の範囲では有効、なはずですよね?
が、この例は、見ての通りよろしくないソースの典型例で、なんとグローバル変数もxではありませんか! それどころか、そのグローバルxをfunc関数冒頭で、ローカル変数xに代入しています!
そして、そのあと、ローカル変数xが88.99点の点の値で、有効になる、という構図です。
で。。。これ、ローカル変数xは、func関数の”float x = 88.99;”の行までは、有効になっていないということになるです。
つまり、ローカル変数xは、本来の有効範囲”int func() {”の行からではない、ということになります。

※こんな議論よりも先に、このソースの様な御行儀の悪いプログラマの御説教の方が先なのは、まぁ前提ってことで。(そもそも、グローバルとローカルでおんなじ変数名なんてつかうな! でも本当に見掛けるから、恐い!)


さて、このAttributeですが、こういったケースにおいて、ローカル変数xの有効範囲が、親DIEになり得る関数funcのメモリアドレス範囲の開始(つまり、DW_AT_low_pc)から少し遅れるよってことを示すためのものになります。
で、このDW_AT_start_scopeですが、もつ値は以下のよーになります。

  • 対象のデータオブジェクトが含まれるメモリ領域が連続ならば → このデータオブジェクトのスコープを定義する親DIEの「DW_AT_low_pc」の値からこのデータオブジェクトまでのバイトオフセット
  • 対象のデータオブジェクトが含まれるメモリ領域が連続ならば → 不連続のメモリ領域を示す.debug_arangesなリストにおける最初の範囲エントリの最初のアドレスからのバイトオフセット
    (.debug_arangesでのベースセレクションエントリや最後のエントリからのオフセットではごじゃいません)


(No.12) DW_AT_endianityの値と意味

こいつは、このAttributeを持っているTAGの対象オブジェクトの「エンディアン」を示す固定値で、値は以下となるです。

No. 固定値の名称 value 意味
1 DW_END_default 0x00 ターゲットマシンABIでのデフォルトエンディアン(通常CPU依存)
2 DW_END_big 0x01 ビッグエンディアン
3 DW_END_little 0x02 リトルエンディアン


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