ということで、次にCIEのinitial_instruction, FDEのinstructionsの中の命令を列挙。
まず、DW_CFA命令は、以下のバイナリ文法。
DW_CFA命令は、大きく以下の種類があるそうです。
以下、この種類別に詳細を列挙です。
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に拡張されたもの |
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系らしいので、とりあえず無視していい? |
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にして撤廃したもん |
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命令で逃した値を戻す処理が必要 |
No. | 命令名称 | 1Byte明 上位2bit | 1Byte目 下位6bit | 引数1 | 引数2 | 意味/説明 |
5-1 | DW_CFA_nop | 00 | 0x00 | - | - | CIE、FDEの余り領域を埋めるための何もしない命令です。 よって解析時には無視でOK |
[PageInfo]
LastUpdate: 2013-05-28 22:12:13, ModifiedBy: koinec
[License]
FreeBSD Documentation License
[Permissions]
view:all, edit:members, delete/config:members