おしながき

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_frameセクションの構造:DW_CFA命令編

ということで、次にCIEのinitial_instruction, FDEのinstructionsの中の命令を列挙。

DW_CFA命令のバイナリ文法

まず、DW_CFA命令は、以下のバイナリ文法。

<1Byte目:命令> <引数1> <引数2>
  • <1Byte目:命令>
    • どの命令も必ずあります。当然、命令によって値が変わります。
    • この命令1Byteは、「上位2ビット」「下位6ビット」で分けられています。そして、命令によっては、下位6ビットにはレジスタ番号などが埋まっていたりします。
      • どの命令の下位6ビットは、レジスタ番号なのか、などは下記を参照。
      • この工夫(下記6ビットになんか埋め込む)は、デバッグ情報のデータサイズ軽減のための工夫らしい。
  • <引数1><引数2>
    • 命令によって、引数1、引数2どっちもないもの、引数1だけあるもの、どっちもあるもの、があります。
    • 命令別の引数ありなしは、以下表に。

DW_CFA命令の詳細

DW_CFA命令は、大きく以下の種類があるそうです。

  1. 行作成系命令 : CFIルール表の行 を作成(追加)する命令群です。行の作り方によっていくつか命令があります。
  2. CFA宣言系命令 : これは、CFIルール表内での、今の行のCFA(Call Frame Address)はどやつですよ、を名指しするための命令っぽいです。これも名指しのやり方でいくつか命令があります。
  3. レジスタルール命令 : これは、通常CIEのinitial_instruction内で、各レジスタの初期値を設定するための命令です。
  4. 行状態操作命令 : 全レジスタの退避、退避したレジスタの戻し命令です。
  5. パディング命令: 文字通り、パディングです。バウンダリの都合とから、すき間ができたら突っ込む無意味命令です。

以下、この種類別に詳細を列挙です。

DW_CFA命令一覧#1 : 行作成命令

No. 命令名称 1Byte明
上位2bit
1Byte目
下位6bit
引数1 引数2 意味/説明
1-1 DW_CFA_set_loc 00 0x01 address
(8byte=64bit)
- ルール表に、引数1で指定されたコードアドレスの行を作成します。
ルール表のaddress以外の項目、CFA,Reg Xは全て現在の行の値を引き継ぎます(=値は変えない)
1-2 DW_CFA_advance_loc 01 delta - - 現在の行のaddressに delta × CIE:code_alignment_factor を足した値を新しいアドレスとした行を作成。
他の値(CFA/Reg X)は全部現在の行のものが引き継がれます
1-3 DW_CFA_advance_loc1 00 0x02 1Byte delta
unsinged char
- この命令は(1-2 DW_CFA_advance_loc)と同じ動き。が、deltaの制限が6bitから8bitに拡張されたもの
1-4 DW_CFA_advance_loc2 00 0x03 2Byte delta
unsinged short
- この命令は(1-2 DW_CFA_advance_loc)と同じ動き。が、deltaの制限が6bitから16bitに拡張されたもの
1-5 DW_CFA_advance_loc4 00 0x04 4Byte delta
unsinged int
- この命令は(1-2 DW_CFA_advance_loc)と同じ動き。が、deltaの制限が6bitから32bitに拡張されたもの

DW_CFA命令一覧#2: CFA宣言系命令

No. 命令名称 1Byte明
上位2bit
1Byte目
下位6bit
引数1 引数2 意味/説明
2-1 DW_CFA_def_cfa 00 0x0c uLEB128
Reg.
uLEB128
non-fact. Offset
CFIルール表の現在の行のCFAを「[Reg.]+offsetのアドレス」であると設定する。
引数1のReg.はレジスタ番号が格納される
引数2のnon-fact. は、引数のoffsetをそのままオフセット値として使う、という意味です。
2-2 DW_CFA_def_cfa_sf 00 0x12 uLEB128
Reg.
sLEB128
factored Offset
この命令は(2-1 DW_CFA_def_cfa)と同じ動き。
ただし、引数2のオフセットの指定で、まず負数(マイナス)のオフセット指定が可能。
さらに、factoredがついているので、引数1のレジスタ番号で指定されるレジスタに足し込まれる実際のオフセット値は Offset(引数2)× CIE:data_alignment_factorの値となる
↑このfactoredはこの後、以下で一杯出て来るので注意!
なお、DWARF3からの命令
2-3 DW_CFA_def_cfa_register 00 0x0d uLEB128
Reg.
- 現在の行のCFA列の値(ルール)に使われているレジスタ(番号)を、引数1で指定されたレジスタに書き換える。
現在のCFAが「 Reg2 + 4 」だとして、引数1が Reg3 なら、この命令によって「 Reg3 + 4 」になる。(と思われる)
なお、この命令ちょっと英訳自信ないです。。。原文に" to use the provided register (but to keep the old offset). "なる部分があるのですが、この"but to keep"の部分が、「しかし、オフセットは維持する」なので「維持しない」なのかいまいち自信なしです。。。
2-4 DW_CFA_def_cfa_offset 00 0x0e uLEB128
non-fact. offset
- 現在の行のCFA列の値(ルール)のオフセットを引数1で指定された値に上書きする。
なお、レジスタ番号はそのまま(に、読める。2-3と同じbut toがあるので)
例: 現在が「 reg2+4 」で、引数のoffsetが8なら、この命令の後のCFAは「 reg2 + 8 」になると思われる。
なお、non-fact. の意味は2-2を参照してね
2-5 DW_CFA_def_cfa_offset_sf 00 0x013 sLEB128
factored offset
- これは(2-4 DW_CFA_def_cfa_offset)と同じ挙動。
ただし、引数1のオフセットはfactoredで、さらに負数指定も可能。
なお、DWARF3からの命令
2-6 DW_CFA_def_cfa_expression 00 0x0f BLOCK - まず、引数1の"BLOCK"は、最初に「データサイズを示すuLEB128」があり、その後このデータサイズ分のバイナリデータが続く、と言う意味。よって数バイト以上はあるはず
で、この命令は現在の行のCFA列の値を「引数1に格納されたバイナリデータで構成される、DWARFオペレータ形式の計算式によって計算された値」に上書きするもの。
DWARFオペレータ形式、とは、なんかDWARFが決めたバイナリで表現された、簡易の計算用言語っぽいです。この詳細はそのうち調べましょっかね。
あ、なおこの命令もDWARF3から命令です。(見ている限り、FreeBSD 6,7,8,9系のgccはみんなDWARF2系らしいので、とりあえず無視していい?

DW_CFA命令一覧#3 : レジスタルール命令

No. 命令名称 1Byte明
上位2bit
1Byte目
下位6bit
引数1 引数2 意味/説明
3-1 DW_CFA_undefined 00 0x07 uLEB128
Reg.
- 指定されたレジスタ番号の値(ルール)を「未定義」にします。
「未定義」って何や?→よーは、このレジスタ番号は今時点では使いませんってことらしいです。
ちなみに、未定義ならそもそも命令しなくってもいいじゃんって思っちゃいますが、この命令はどうもCIEのinitial_instructionsで、最初のレジスタの値の定義をする時、列は定義しておきたいけど今はこのレジスタ使わねーって時に命令されちゃうみたいです。
3-2 DW_CFA_same_value 00 0x08 uLEB128
Reg.
- 指定されたレジスタ番号の値(ルール)を「同じ値」にします。
これは、ようするに、「そのレジスタの前の値を変えません」ってことらしいです。
これも、CIEのinitial_instructionsで使われるみたいです。
3-3 DW_CFA_offset 10 Reg. uLEB128
factored Offset
- まず、この命令の下位6ビットは、レジスタ番号となります。それ注意
で、この命令は、下位6ビットで指定されたレジスタ番号のレジスタの値を、現在のCFA+Nのアドレスに保存(コピー)します。
Nは、引数1のfactored Offset × CIE:data_alignment_factorです。
3-4 DW_CFA_offset_extended 00 0x05 uLEB128
Reg
uLEB128
factored offset
この命令は(3-3 DW_CFA_offset)と同じ。
ただし、レジスタ番号を引数1のuLEB128に置き換えることで6ビット制限が撤廃されています。よーは、65個以上のレジスタが使えますモデルです。
3-5 DW_CFA_offset_extended_sf 00 0x11 uLEB128
Reg
sLEB128
factored offset
この命令は(3-4 DW_CFA_offset_extended)と同じ。
ただし、引数2のオフセット値に負数(マイナス)が指定できます。
なお、これはDWARF3からの命令です
3-6 DW_CFA_val_offset 00 0x14 uLEB128
Reg
uLEB128
factored offset
引数1で指定したレジスタの値に、CFA+(引数2 * CIE:data_alignment_factor) で計算されるアドレス内の値を書き込みます。
なお、これもDWARF3からの新参者
3-7 DW_CFA_val_offset_sf 00 0x15 uLEB128
Reg
sLEB128
factored offset
この命令は(3-6 DW_CFA_val_offset)と同じ。
ただし、前出同等、ケツに_sfが付いているので、引数2のoffsetにマイナスが許されているのですね。
なお、当然?こいつもDWARF3の新参
3-8 DW_CFA_register 00 0x09 uLEB128
Reg1
uLEB128
Reg2
引数1のレジスタ1に、引数2のレジスタ2の値をつっこみます。 それだけ。。。
3-9 DW_CFA_expression 00 0x10 uLEB128
Reg
BLOCK まず、引数2のBLOCKは、(2-6 DW_CFA_def_cfa_expression)の説明を参照。
こいつは、引数1のレジスタの値を、引数2にDWARFオペレータ形式で書かれた命令に沿って計算されたアドレスに保存(コピー)します。
で、おもろいのは、引数2のDWARFオペレータを計算する前に、CFIルール表のCFAの値をDWARFの仮想的なスタックにpushします。
(DWARFオペレータをまだ調べてないけど、おそらくDWARFオペレータ内からこの値をpopして使えるっぽいよね)
ちなみに、これもDWARF3新参選手
3-10 DW_CFA_val_expression 00 0x16 uLEB128
Reg
BLOCK 引数のBLOCKは前出と同じ。
引数1のレジスタ値に、引数2のDWARFオペレータ形式で計算された値をつっこむ命令。
こいつも、DWARFオペレータ計算前に、DWARFの仮想スタックにCFAの値をpushしちゃいます。
あ、無論?DWARF3からの新参選手
3-11 DW_CFA_restore 11 Reg - - Regで指定されたレジスタ番号の値を、CIEのinitial_instructionsにある初期値で上書きします。ようるすに、初期値に戻すだけ
3-12 DW_CFA_restore_extended 00 0x06 uLEB128
Reg
- これは(3-11 DW_CFA_restore)と同じだけど、前出同様、引数1のレジスタ番号の6ビット制限をuLEB128にして撤廃したもん

DW_CFA命令一覧#4 : 行状態操作命令

No. 命令名称 1Byte明
上位2bit
1Byte目
下位6bit
引数1 引数2 意味/説明
4-1 DW_CFA_remember_state 00 0x0a - - 全てのレジスタの値(ルール)を「仮想的なスタック」へpushします。
解析プログラム上では、この命令が来たらCFIルール表上の全レジスタの値をどっかに保存しておく必要があるってことです
4-2 DW_CFA_restore_state 00 0x0b - - CFIルール表の現在の行へ、「仮想的なスタック」上にpushしたレジスタの値(ルール)を上書きで戻します。(=popします)
解析プログラム上でも、同様に過去remember_state命令で逃した値を戻す処理が必要

DW_CFA命令一覧#5 : パディング命令

No. 命令名称 1Byte明
上位2bit
1Byte目
下位6bit
引数1 引数2 意味/説明
5-1 DW_CFA_nop 00 0x00 - - CIE、FDEの余り領域を埋めるための何もしない命令です。
よって解析時には無視でOK
目次に戻る:DWARFファイルフォーマット