おしながき

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

.debug_macinfoセクションの構造

(そういえば) ホンヤクの前に、大事?な注意事項

.debug_macinfoセクションですが、gccでふつーにコンパイルしても「出ません」
このセクション情報が、どーしても欲しい方、コンパイル時にちゃんとgccに注文してあげなきゃいけないです。
注文方法は

gcc -o <実行ファイル名> -g3 <ソースファイル名>
で、”-g3”を注文する必要があります!
お忘れなく。。。。


.debug_macinfoセクションって何?

これは、一言です。「(C言語の)マクロ(プリプロセッサ命令)の情報」が入っています。

注:macinfo = どっかのハンバーガ屋さんの情報、ではないみたいです。実はこんなとこに隠されたポテトLのクーポン券だったら個人的にはひじょーにうれしいのですが。。。(無論、MAC OS向けのデバッグ情報でもないです)

もちっと、具体的には、以下のものが入ってるみたいです。

  • 定数の定義: ”#define XXX YYY”
  • 定義した定数の解除: ”#undef XXXX”
  • ヘッダファイルのインクルード: ”#include"XXXXX.h" ”
  • 定数定義に依存するソースの有効/無効化: ”#ifdef/#ifndef XXXX〜 #endif”、”#if〜#else〜#endif”
    • ↑これだけは、原文からは入ってるよーに見えるけど、ちと怪しい。。。要調査(2013/5/15)


逆に、「#pragma XXXX」は入っていないっぽいです。。。(あんま、デバッガには関係ないと思うけど、OpenMPって#pragmaの嵐じゃなかったっけ。。。)

ということで、以下具体的に見て行きますかね。。。


全体的なデータ構造

これ、おもしろいです。(というか、簡単?っぽいです)
他の.debug_xxxxxなセクションには付き物だった、<ヘッダ>はなく、ただひたすら、マクロ命令を表したレコード(原文中では、"macinfo entry")が埋まってるだけみたいです。。。


"macinfo entry"の構造と種類

"macinfo entry"の基本的な構造は、以下みたいです。

<Type Code (1Byte)> <引数1> <引数2>

で、マクロの種類によって、<Type Code>とそれにふっつく<引数x>は変わってきます。ということで、全6種類を以下表で整理してみました。

No. Type Code名 Type Code(1Byte値) 引数1 引数2 概要
1 DW_MACINFO_define 0x01 uLEB128
マクロ定義のソース行番号
NULL終りの文字列
マクロ定義文字列(そのまま)
どんな#defineのマクロがソースのどこに定義されているか、です。
2 DW_MACINFO_undef 0x02 uLEB128
マクロ定義のソース行番号
NULL終りの文字列
マクロ定義文字列(そのまま)
どんな#undefのマクロがソースのどこに定義されているか、です。
3 DW_MACINFO_start_file 0x03 uLEB128
#includeがあるソース側のソース行番号
uLEB128
.debug_line上のファイルテーブルのソースファイルID
#include命令のソース上での開始箇所とどのファイルをインクルードするか、です
4 DW_MACINFO_end_file 0x04 - - #include命令によるインクルードの終了箇所を示すマーク、です
5 DW_MACINFO_vendor_ext 0x05 uLEB128
固定値
NULL終りの文字列 (コンパイラ)ベンダによる勝手?な拡張マクロ。
原文には、「このTypeCodeはコンシュマーは理解できないので全て無視せよ」と明記されていますんで、無視してやりましょー
6 (macinfo 終了コード) 0x00 - - この命令が来たら、macinfoのデータは終りです。

なお、TypeCodeは、それぞれ結構「癖」があるようです。(原文見る限り)
と、いうことで、以下でTypeCode別に、考慮事項をつらつらメモっときます。


DW_MACINFO_define の挙動

これは、例えばソースの3行目に

#define CONST_VAL 3
と書いてあった場合、

  • 引数1(マクロ定義のソース行番号): 3
  • 引数2(マクロ定義文字列): "CONST_VAL 3"

となります。

なお、以下は注意しておかなきゃならんことです。

  • マクロ関数(カッコ内にパラメタへ置き換えるための文字があるマクロ定義)の場合
    • 引数2のマクロ定義文字列には、カッコ内の変数はマクロ定義行での仮変数名がそのまんま出ます。
      例: "#define FUNC(n,m) (n)+(m)"なら、引数2には"FUNC(n,m) (n)+(m)"と入ります。(展開されたりはしません)
    • マクロ名とパラメタリストの左カッコの間にスペースをおいても、引数2のマクロ定義文字列内では、こいつは潰され、くっつけられます。
    • パラメタリスト内の、カンマで区切られていない部分の連続するスペースについても、引数2のマクロ定義文字列内では、無理矢理くっつけられます。
    • パラメタリストの右カッコ、もしくはフツーの定数定義のマクロ定義で、1つめの定義名と2つめの展開後文字列の間のスペースは、必ず1文字にしちゃいます。(2文字以上あると、かってに1文字にカットしちゃいます)
    • 例(恐らく): "#define FUNC (par am , m) (param)+(m)"
      • 引数2のマクロ定義文字列は "FUNC(param,m) (param)+(m)"になる。
      • FUNC と (の間にスペースが2文字 → スペースがなくなっちゃいます。。。
      • 変数param の間にいらないスペースがある → これも、スペースがカットされます。
      • FUNC(param,m)と(param)+(m)の間が、スペース2文字 → スペース1文字になります。
  • コンパイラが勝手に生成する#define や コンパイラのコマンドラインから「-Dxxxxxx」を付与した場合
    • 引数1のマクロ定義の行番号が「0」(行目)に定義されたものとして、出力されます。
    • 最初のDW_MACINFO_start_file命令よりも、必ず先に出力すること、と原文上決められています。


DW_MACINFO_undef の挙動

これは、例えばソースの6行目に

#undef CONST_VAL
と書いてあった場合、

  • 引数1(マクロ定義のソース行番号): 6
  • 引数2(マクロ定義文字列): "CONST_VAL"

となります。

特段、注意事項とか、ありませんです。


DW_MACINFO_start_file のきょどう

この命令は、"#include"がソース上の何行目にあり、その"#include"で取り込まれるファイルは、どのファイルか、を教えてくれるものです。
よって、引数1は、"#include"のあるソース上の行番号です。これは簡単です。
で、問題は「引数2」です。上記 表内では引数2の欄に「.debug_line上のファイルテーブルのソースファイルID」と書きました。これ、何でしょう?ということで.debug_lineセクションの構造と読み方を見てみてくださいです。
ここには、".debug_line"セクションのヘッダ情報をまとめていますが、このヘッダ内の最後の項目に"file_names"なる項目があります。んで、この項目には対象とするCソースで使う、インクルードする.c/.hの一覧が埋まってます。
ということで、この「引数2」に入る数字は、なんとこの".debug_line"セクションのヘッダ内の"file_names"のレコード番号を入れる形で、インクルードするファイルを指定しています。

で、このDW_MACINFO_start_fileには、ちっとだけ注意事項が原文に明記されているので、以下列挙です。

  • 明確なソースのファイル(.c/.h)以外から、インクルードされることもあります。この場合
    • 引数1(#includeのソース上の行番号) : とーぜん#includeはない(ソース上では指定なんかしていない)ですから、「0」(行目)になります。
    • 引数2(.debug_line上のfile_namesレコード番号): 取り込まれちゃうデータの「ファイル」は存在しないですから、これはfile_namesレコード上で「-」になっているレコードの番号が入ります。
    • 原文で、例として上がっている”標準入力からのインクルードファイル流し込み”は一般的にない(というか、できるんかいこれ?)と思いますがね。。。。(C以外ではこんな機能あるんですかね)


DW_MACINFO_end_file の挙動

このめーれいは、"DW_MACINFO_start_file"に相対するもので、#includeの終りを告げるマークです
これは、例えばsample.hなヘッダファイルをincludeする場合、このヘッダファイル内で#defineとかされていること、ありますよね。
sample.h内の#defineもDW_MACINFO_defineで出力されますんで、どこまでの出力がincludeされたヘッダファイル内での出来事なのか、を分かる必要があります。
ので、インクルードファイル内での出来事、終ったよんって教える時、この命令がポンと出て来ます。後で、例は出しますね。

あ、あと、このMACINFOは、ソースの1行目からマクロが登場した順に出力されていきます。これ御見知りおきを。


全体的な注意

最後に、以下2点はちょっと気を掛けておかなきゃならんみたいです。

  • 全てのDW_MACINFO_xxxxは、コンパイラ(と原文にあるが、C言語の場合はどー見てもプリプロセッサ)の処理順序で出力されます。 (まぁ、これはそうでしかないですよね)
  • コンパイラのコマンドラインから突っ込んだマクロは、原則的にコマンドラインに与えられた順番に出ちゃいます。
    • 原文にはこうありますが、そもそもコンパイラは与えられたコンパイルオプションを前から?後ろから?評価する? という議論になりますんで、「事実上、コンパイラ依存」というべきかな。
      (まぁ、まず前からだろーとは思います、が。)
  • コンパイラ自身が勝手に?(気を訊かせて?)追加してくれたマクロは、「ユーザーが明確にコマンドラインから定義したマクロ」として取扱い、ルールにそった形の順番で出力します。
    って、勝手にオマケしてくれたマクロと、コマンドラインからのマクロのどっちがコマンドライン上先に定義されたものとするか、はどーみてもコンパイラの仕様なので、やっぱりこれも「コンパイラ依存」です!


ということで、あんま注意になってないよーな気がしますが、とりあえず書いておきます。


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