(2013/5/19 不明点を訂正のうえ、作成終り。一応これで大丈夫かなarangesは)
このセクションには、プログラムコードのどの範囲が、.debug_info内のcompilation unit、すなわち「(C言語の).cファイル」のどれに対応するか、の「早見表」が格納されています。
なので、デバッガちゃんはこいつを読んでメモリ展開なんかしておいて、その状態でプログラムコードアドレスを与えられたら、どのソースファイルの情報を調べればいいか、がすぐに分かるのですね。
ということで、早速構造見て行きます。っていっても、こいつは簡単そーです。(原文がA4 1ページしかない。lineやframeに比べて大違い)
.debug_arangesセクションでは、compilation unit、つまり.cソースの単位に、以下のレコード構造を持っているみたいです。
この構成が.cソース数分、繰り返しています。また、最後は0番地のアドレスと、長さ0のレコードで終ります。
それでは、以下で詳細に見て行きますかね。
arangesヘッダは、以下の構造みたいです。
No. | 項目名 | サイズ | 説明 |
1 | unit_length | 4byteor 12Byte unsigned 整数 | このcompilation unitのarangesレコードの長さです。 なお、このunit_lengthの長さは含みません なお、他と同様、0xffffffffじゃなかったら、この値は4Byteで以下のNo.3も4Byte 逆に0xffffffffなら続く8Byteが長さで、No.3も8Byte |
2 | version | 2Byte unsigned short | .debug_arangesセクションのバージョン これ、DWARF自体のバージョンとは違うので、注意 |
3 | debug_info_offset | 4Byte or 8Byte unit_lengthの長さ次第でいずれか | このarangesレコードが対象とするcompilation unitの情報が書かれている、.debug_infoセクション内でのオフセット、つまりセクションの頭からの位置です。 |
4 | address_size | 1Byte unsigned char | これは、<開始アドレス>のサイズをByte数で表現したものです。64bitなら、8ですね。 なお、セグメント方式のアドレス表現をするアーキでは、この値はセグメント内での開始アドレスまでのオフセットを表現するために必要なサイズとなります。 32bit(x86)は影響ありそうですね。(つか、Dr.deamon64はこれが面倒+もう32bitは本人使ってないんで、割り切って64bitだからとりあえず無視でOK?) |
5 | segment_size | 1Byte unsigned char | セグメント方式アドレッシングのアーキの場合、セグメントサイズのByte表記が入ります。リニア(フラット)アドレッシングの場合は、0です。 |
6 | Boundary Padding | (参照→) | 次に続く、<開始アドレス>は、32bitアーキなら4Byte、64bitアーキなら8Byte単位のセクション内のオフセットからはじまる必要があるっぽいです。なので、ヘッダのNo.5終了後のセクション内のオフセット値(アドレス)が、4ないし8で割り切れない時は、割り切れるオフセットになるまで分のサイズを0x00でパディングする必要があります。これ「要注意」 (ちなみに、DWARF3の原文には、このパディングの記述がありません。。。) |
arangesヘッダの後には、<開始アドレス><長さ>の組が、連続します。
連続する、と書いたのは、例えば1つのCソースをコンパイルした結果、 0x004005b0 - 0x004005c4 と 0x004006b0 - 0x004006c8 のの2つの範囲に分断されてコードが配置された、というケースが考えられます。
この場合、 0x004005b0 0x14 0x004006b0 0x18 と連続させて表現するためです。
さて、表現形式です。これは、上の例の様に、バイナリ列で、<開始アドレス><長さ>が連続するだけです。。。
よって、上の例が説明になっちゃってます。 ただし、以下に注意するみたいです。
なお、開始アドレス=0番地、長さ=0 の<開始アドレス><長さ>の組が登場したら、1つのarangesヘッダが終了です。
.debug_arangesセクションの長さがまだある場合は、もう1つ以上arangesレコードがありますきっと。逆に、その部分で.debug_arangesセクションが終ったら、それでサイナラです。
ということで、実機でやってみました。
まず、イケニエにしたソースです。ちょー適当な例ですが、.cソースが2つあればそれで十分、なので、これで勘弁してくださいです。
/* .debug_aranges sample source - test1.c */ int g1; extern int g2; // by test2.c extern int func1(int a, int b); // by test2.c int func2(int d) { return d + g2 + g1; } int main(int argc, char *argv[]) { int a, b, r; g1 = 1; g2 = 2; a = 3; b = 4; r = func1(a,b); r = func2(r); return r; }
んで、次に2つめのソースです。
/* .debug_aranges sample source - test2.c */ int g2; int func1(int a, int b) { return a+b-g2; }
ちなみに、使った環境は、以下です。
prompt # uname -a FreeBSD xxxx.koinec.jp 9.1-RELEASE FreeBSD 9.1-RELEASE #0: amd64 prompt # gcc -v Using built-in specs. Target: amd64-undermydesk-freebsd Configured with: FreeBSD/amd64 system compiler Thread model: posix gcc version 4.2.1 20070831 patched [FreeBSD]
さて、この環境で、上記ソースをビルドして、そこから.debug_arangesセクションをバイナリで抜きだして解析してみました。その結果が以下です。
なお、#の行はつっこんだコメントですので、よろしく。
# Hex.Dump of .debug_aranges Section ---- 00000000 2c 00 00 00 : unit_length = 0x0000002c = 44 Byte ですね。 00000004 02 00 : version = 0x0002 = 2 # これはDWARFのversionは異なるので注意。 00000006 00 00 00 00 : debug_info_offset = 0x00000000 # .debug_infoセクションの頭0x00000000バイト目から始まるCUの範囲ですよってことです。 0000000a 08 : address_size = 0x08 # 64bitコンパイルですから、0x08になっていて、これもOKです。 0000000b 00 : segment_size = 0x00 # FreeBSDのINTEL64のアドレス空間はリニア(フラット)ですから、0x00でOKです。 # (やってないけど、これdosなら値もつかな?) 0000000c 00 00 00 00 : Boundary Padding(4Byte) # 64bit(8Byte)アーキなので、アドレス表現はセクション内の8Byte単位のオフセットから # 始める必要があるみたいですが、0x0000000cなので、4Byte足りません。 # → よって、4Byteを0x00でパディング!! (原文の漏れじゃ。。。) 00000010 60 05 40 00 00 00 00 00 : <開始アドレス>=0x0000000000400560 # .symtabセクションを見ると、func2関数のアドレスと一致しています。 # よって、test2.cのアドレスの開始範囲と見れますので、大丈夫そーですね。 00000018 6f 00 00 00 00 00 00 00 : <長さ>=0x000000000000006f = 111 Byte # 開始アドレス 0x0000000000400560 - 終了アドレス0x00000000004005cf です。 # .symtabセクションでは、test1.c内のfunc1関数の開始が0x004005d0になってますから # これもあってそうですね。 00000020 00 00 00 00 00 00 00 00 : <開始アドレス>= 0x0000000000000000 00000028 00 00 00 00 00 00 00 00 : <長さ> = 0x0000000000000000 # ということで、<開始アドレス><長さ>ともに、0のレコードが登場しました。 # ので、このCソース分は、終りましたです。 # で、次のCソース分(test1.c)です。 # が、もう以下ざっと見た瞬間に、上のtest2とおんなじ構造であることが # 明らかなので、もういいですね。。。ということで、割愛。 00000030 2c 00 00 00 00000034 02 00 00000036 47 01 00 00 0000003a 08 0000003b 00 0000003c 00 00 00 00 00000040 d0 05 40 00 00 00 00 00 00000048 20 00 00 00 00 00 00 00 00000050 00 00 00 00 00 00 00 00 00000058 00 00 00 00 00 00 00 00
最後に、念のため上記のわたくしの解析が正しいかどうか、あやしかったりするんで、答え、としてreadelf君の解析結果を載せます。
これ見る限り、上記あってるっぽいですね。
The section .debug_aranges contains: Length: 44 Version: 2 Offset into .debug_info: 0 Pointer Size: 8 Segment Size: 0 Address Length 0x0000000000400560 0x6f 0x0000000000000000 0x0 Length: 44 Version: 2 Offset into .debug_info: 147 ←ちなみに、これ10進へ変換忘れ or 0xの付け忘れっぽいですね。。。 Pointer Size: 8 Segment Size: 0 Address Length 0x00000000004005d0 0x20 0x0000000000000000 0x0
というこで、.debug_arangesはこれでおわりです。これは、簡単でした。
が、ヘッダのケツにパディングが必要だったのは、「んなもん規約に書いてなきゃ分かるかい!!」というのが感想ですな。
[PageInfo]
LastUpdate: 2013-05-28 22:13:55, ModifiedBy: koinec
[License]
FreeBSD Documentation License
[Permissions]
view:all, edit:members, delete/config:members