ということで、.debug_abbrevに登場した「TAGコード」「Attributeコード」「Formコード」の3兄弟ですが、まずは末っ子?の「Formコード」から見て行きます。
というのも、これが分からないと、.debug_infoの解析は、全くできなくなっちゃうからです。
で、DW_FORM_zzzzって何、という話ですが、これ簡単です。
先()に、.debug_infoと.debug_abbrevの関係を見ましたが、そこで.debug_infoで指定されたAbbrevレコード内には、格納されているデバッグ情報の種類として属性(Attributeコード)があり、その属性に対応する実際のデータの格納形式がこの値(Formコード)を表現されている、と例を示しましたが、そのコードです。
って、言葉で書くと全くワケが分からないので、()をおとなしく見てくださいです。
ということで、考えるよりも先に、DW_FORM_zzzz的なFormコードの一覧を以下に列挙です。
番号 | Form名 | 値 | Class | .debug_info内でのデータの持ち方(ごせつめい) | .debug_info内 でのデータサイズ (Byte単位) |
1 | DW_FORM_addr | 0x01 | address | (デバッグ情報が格納されている実行ファイルの)アドレスサイズ分データが.debug_infoに直値として直接埋め込まれています。 この値は、再配置された後のメモリアドレス、です。 何のメモリアドレスかってことは、このFormコードを指定したAttributeコードによりけりです なお、このアドレスサイズ、正確には.debug_infoのCUヘッダに書き込まれている値になります。 | 4Byte(32bit) 8Byte(64bit) |
2 | DW_FORM_block1 | 0x0a | block | こいつは、ある程度の長さを持った「バイト列=バイナリデータ」を.debug_infoに表現したい時に指定されます。 形式は、まずデータの最初の1Byte(unsigned char)に続くデータ列の長さ(0〜255)が格納されます。 んで、その次のバイトから、この長さの分、対象とするデータが直接.debug_infoに埋め込まれています。 この突っ込まれるデータは、本当のバイナリデータから、メモリアドレス、 他のDIEの参照オフセットとか、いろんなものが入るのですが、圧倒的に多いのが「DWARF expression」の数式です。 | 1Byte+(指定された長さ) 最大256Byte |
3 | DW_FORM_block2 | 0x03 | block | (No.2)DW_FORM_block1の最初の長さを2Byte(unsigned short)で表現するタイプです。 データの長さを2Byte(65535Byte)まで取れる以外はNo.2と全く同じです。 | 2Byte+(指定された長さ) |
4 | DW_FORM_block4 | 0x04 | block | (No.2)DW_FORM_block1の最初の長さを4Byte(unsigned int)で表現するタイプです。 データの長さを4Byte(約4GByte)まで取れる以外はNo.2と全く同じです。 (まぁ、実際4GByteを指定することはないけどねきっと) | 4Byte+(指定された長さ) |
5 | DW_FORM_block | 0x09 | block | こいつも、意味としては(No.2)と全く同じです。 が、最初のデータの長さを示す値が、1,2,4Byte固定値ではなく、uLEB128で表現されています。違いはそれだけです。 | 長さuLEB128のサイズ+(指定された長さ) |
6 | DW_FORM_data1 | 0x0b | constant | 1Byteのデータが.debug_infoに直値で埋め込まれています。それだけです。 あ、ただ、この値の解釈は、Attributeの意味に依存していて、符号付き整数、符号なし整数、DIEのオフセット、はたまた浮動小数点、だったりします。 (まぁ、1Byteのdata1の場合は、浮動小数点ってことはないけどねとーぜん、ただ、以下のdata2/4/8はあり得るです) あと、Big/Little Endianの別は、ターゲットマシンに依存します。(つまり、x86/64ならとーぜんリトル、PowerPCならビッグ?です) | 1Byte |
7 | DW_FORM_data2 | 0x05 | constant | (No.6)と意味は同じですが、見てのごとく、2Byteデータ(即値)です。 | 2Byte |
8 | DW_FORM_data4 | 0x06 | constant lineptr loclistptr macptr rangelistptr | これも(No.6)と同じだけど、4Byteですね。 あ、あと、4Byte/8Byte版は、Classがいっぱいあります。これは後述 | 4Byte |
9 | DW_FORM_data8 | 0x07 | constant lineptr loclistptr macptr rangelistptr | んで、いうまでもなく(No.6)の8Byte版ですね。 | 8Byte |
10 | DW_FORM_sdata | 0x0d | constant | これも、data1/2/4/8と同じく「即値」です。 でも、1つだけ。。。これ、sLEB128形式の「即値」で埋め込まれています。よって、サイズの固定/制限はないっす。 あと、気づいてると思いますですが、signedです! | sLEB128 |
11 | DW_FORM_udata | 0x0f | constant | これは(No.10)と同じですが、uLEB128の「即値」です。符号は持っていない、正の整数、ですね。 | uLEB128 |
12 | DW_FORM_string | 0x08 | string | こいつは、名前の通り「文字列」です。 んで、_stringな文字列は、.debug_info内(のDIE内)に、その文字列が直接埋め込まれている、文字列です。 なお、文字列の最後はNULL(0x00)です。 あと、.debug_infoのCompilation unit HeaderにDW_AT_use_UTF8なattributeがあるとき、この値は「UTF8」でエンコードされていますってことなんで、注意。 なお、このattribute君がいなかったら、文字コードは決められていません。(つか、ふつーに考えてASCIIだよね) | (NULL来るまでの長さ) |
13 | DW_FORM_strp | 0x0e | string | こいつは、まずNo.12と同じく、「文字列」です。 ただし、格納場所が違っていて、こいつで指定された文字列は.debug_strセクション内にNULL文字終端で格納されています。 んじゃ、.debug_infoには何がはいっちょるの、ってことですが、これは「.debug_strの先頭から対象とする文字列までのバイト数=offset」が入ってます。 この点が違うっす。 ということで、こんな表の中に紛れてますが、.debug_strはただひたすらNULL終端の文字列がどばーっとつまってるだけ、ということも分かりましたです。 | 4Byte (32bit DWARF) 8Byte (64bit DWARF) |
14 | DW_FORM_flag | 0x0c | flag | これは、一言でいうと「Boolean」ですね。(エイリアンじゃないです、念のため) 0なら、false。(つまり、そのattributeはないってことです) 逆に、0以外の値なら、trueです。 あ、表現自体は、1Byteの整数です。 | 1Byte |
15 | DW_FORM_ref_addr | 0x10 | reference | これは、同じプログラム(実行ファイル)内の、他のCompilation UnitにあるDIEを指し示す時、に使いますです。(これよりも先に、まず下のNo.16見てからみてちょ) 特に、共有オブジェクト(.soなど)内のDIEを指し示す時に使われちゃいます。 で、値は対象とするDIEが含まれた実行ファイルや共有オブジェクトが持つ.debug_infoの先頭からのバイト数(オフセット)になりますです。 データの持ち方は、32bit DWARFなら4Byte, 64bit DWARFなら8byteの即値になるです。 | 4Byte (32bit DWARF) 8Byte (64bit DWARF) |
16 | DW_FORM_ref1 | 0x11 | reference | これは、同じCompilation Unit内(つまり、同じ.cなソース内)の他のDIE(Debbuging Information Entry)を参照する時に使われるです。 例えば、デバッグ情報内で、ある変数の型を指し示すとき、その型を定義しているデバッグ情報のDIEを指し示したいことがあったります。(ある変数のデバッグ情報内に、型のデバッグ情報まで持つのは冗長化して面倒ですよね) こーいうときに、このFORMで、他のDIE(この例なら、変数の型)のDIEを指し示してやる、といった具合ですね。 じゃ、どうやって指し示すのかというと、「.debug_infoのCUヘッダ(Compilation Unitヘッダ)の先頭からのバイト数、すなわちオフセットで指し示しますです。 んで、このFORMが指定されちゃったときは、.debug_info内に1Byte符号無し整数が埋まってて、この値がオフセットになっちゃう、って具合です。 | 1Byte |
17 | DW_FORM_ref2 | 0x12 | reference | (No.16)の2Byte版です。つまり、オフセットがCUヘッダの先頭から255Byteに収まらないとき、使われるってことですね。 | 2Byte |
18 | DW_FORM_ref4 | 0x13 | reference | (No.16)の4Byte版です。以下同文 | 4Byte |
19 | DW_FORM_ref8 | 0x14 | reference | (No.16)の8Byte版ですね。こいつも、以下同文 | 8Byte |
20 | DW_FORM_ref_udata | 0x15 | reference | これも、(No.16)と意味は同じです。 ただ、他のDIEへのオフセット値が、(No.16)などとは違って固定サイズではなく、「uLEB128」形式で.debug_infoに埋まっちゃってます。って違いがあります。 | uLEB128 |
21 | DW_FORM_indirect | 0x16 | (未定義:特殊) | これは特殊用途で、こいつが指定された場合、対応する.debug_infoの場所にはuLEB128の数値が埋まっていて、この数値がDW_FORM_xxxになる、ということらしいです。 んで、原文には明確に書いてないけど、例えばこのuLEB128がDW_FORM_data4なら、このuLEB128の後ろに4Byteが続くってことでしょうかね。 なお、原文にはこいつを設けて、動的にFORMを決められるようにすることで、コンパイラ屋がいちいちAbbrevTableを追加しなくってもえーよーになるよね、ってあります。 (が、良く意味理解できてまへん。ま、例外なんでほっとくかとりあえず。(2013/8/12)) | uLEB128 + 指定された長さ? |
上の表の左から4番目の列に、怪しげな「Class」ってのがあります。んで、これ上では説明してないんですよね。んじゃ、これにゃに、って話です。
で、”Class”ですが、これずばり「DW_FORM_zzzzで指定されたデータの形式で、.debug_infoの中に埋まっているデータの解釈方法」のことです。
例を出すと、例えば、.debug_abbrevの中で、あるTAGがDW_AT_High_pcなAttributeを持っていて、この属性のデータの形式がDW_FORM_data8だったとします。 この時、後のページのDW_AT_yyyyの表に書き込みます(きっと)が、DW_AT_High_pcって属性は「このデバッグ情報エントリ(DIE)が対象とするオブジェクト(変数など)のメモリ上のアドレス範囲のうち、高位のもののアドレスを示す属性」の意味なんで、こいつがもつデータって、いうまでもなく「メモリアドレス」なわけです。 んで、そのメモリアドレスのデータ形式が"DW_FORM_data8"だから、このアドレスは8Byteの固定値(=64bit)ってな訳になるんですね。 次に、この例では、たまたま64bitだったんで、DW_FORM_data8な訳ですが、これもし32bitならどーしちゃいましょ、となると、やっぱりDW_FORM_data4がきちっと指定されちゃいます。
ほんじゃ、ということで、Classの一覧表とその解釈方法を以下に。
Class名 | 解釈方法 | 取り得るDW_FORM_zzzz |
address | マシンのメモリアドレスとして解釈です | DW_FORM_addr |
block | 長さ不定のバイナリデータの塊、として解釈してねって時のもんです。 主に、以下の例ありです。 * 再配置後or再配置可能な複数のアドレス * 他のDIEへの参照 * その他適当なデータの塊 | DW_FORM_block1/2/4 DW_FORM_block |
constant | 「定数」として解釈されます。 ただし、data1/2/4/8系は1/2/4/8バイトの定数、って意味で扱われる訳ですが、その定数の解釈の仕方はさまざまなんです。 「符号付き整数」「符号なし整数」「浮動小数点(4/8の場合)」などの固定値の場合がありますです。 (よーするに、必ず符号なし整数って訳じゃないです、ってこと。あくまでその長さの固定データ、ってことだけです) | DW_FORM_data1/2/4/8 DW_FORM_sdata DW_FORM_udata |
flag | 単なるBooleanとして解釈せよってことです。 0=Flase、0以外=Trueってことです。 | DW_FORM_flag |
lineptr | .debug_lineセクションの先頭から対象とするデータの場所までのオフセット値、って意味です。 .debug_info内のDIEから.debug_lineへリンクさせるときに指定されちゃいますね。 あと、再配置可能なオブジェクトファイル(つまり、.oなファイル)では再配置可能な、実行ファイルや.soな共有オブジェクトでは再配置後の値になるよ、 って原文に書いてますが、?????です。(なんで、lineセクションのオフセットが再配置??) | DW_FORM_data4/8 |
loclistptr | .debug_locセクションの先頭から対象とするデータの場所までのオフセット値、です。 これも、.debug_infoから.debug_locをリンクするときに使われます。 こいつの原文にも、lineptrとおんなじ再配置の下りがあるけど、にゃにこれ?? | DW_FORM_data4/8 |
macptr | .debug_macinfoセクションの先頭から対象データまでのオフセット値です。 またこれも、.debug_infoから.debug_macinfoをリンクするとき用です。 やっぱり、再配置の下りがあるけど、ワカラナイ! | DW_FORM_data4/8 |
rangelistptr | .debug_rangesセクションの先頭から対象のデータまでのオフセット値ですね これも、.debug_infoからのリンク用です。 またしても、再配置の下りありですが、ワカラン! | DW_FORM_data4/8 |
reference | これは、「他のDIEを参照先」として解釈です。参照先のDIEによって、2つのパターンがあるです。 (パターン1)同じCU(Compilation Unit)内の他のDIEを指す場合:.debug_infoの該当するCUヘッダの先頭バイトからのオフセット値として解釈です。 (パターン2) 同じプログラム内の、他のCU内にあるDIEを参照する場合:参照するDIEを含むオブジェクトファイルの.debug_infoの先頭バイトからのオフセット値。 なお、パターン2の場合は必ずDW_FORM_ref_addrが指定されます。それ以外はパターン1 | DW_FORM_ref1/2/4/8 DW_FORM_ref_udata DW_FORM_ref_addr |
string | 見ての通り、「文字列」として解釈です。 文字列は、必ずNULL文字(0x00)で終るルールっす。 あと、CUヘッダのエントリにDW_AT_use_UTF8が指定されてしまった場合は、これらの格納文字列はUTF8になります。 未指定の場合は、未定義です。(事実上、ASCII以外つかうなぁってことですねきっと) | DW_FORM_string DW_FORM_strp |
[PageInfo]
LastUpdate: 2013-08-21 21:24:37, ModifiedBy: koinec
[License]
FreeBSD Documentation License
[Permissions]
view:all, edit:members, delete/config:members