【ELF形式】セクションヘッダとセクションの関係
今回、セクションヘッダが30個あるという情報を、ELF形式ファイルの先頭から48(0x30)バイト目の位置にある2バイトの情報(e_shnum)から取得しましたが、これはつまり、セクション実体が30個あるということでもあります。
セクションヘッダとは、それに対応するセクションに関するメタ情報(セクションの位置やサイズ)を持つデータです。セクションヘッダとセクションは1対1に対応しています。
セクション0 | <==== | セクションヘッダ0 |
セクション1 | <==== | セクションヘッダ1 |
セクション2 | <==== | セクションヘッダ1 |
… | … | … |
セクション28 | <==== | セクションヘッダ28 |
セクション29 | <==== | セクションヘッダ29 |
上の例では、セクションとセクションヘッダのメモリ上の順番が同じように書いてありますが、セクションヘッダは、ELF形式ファイルの先頭からのオフセットアドレスでセクションを管理しているため、必ずしもセクションヘッダの順番とセクションの順番が一致している必要はありません。
また、セクションヘッダは情報としてセクション名を持ちますが、セクション名の文字列はセクションヘッダにベタに書かれているわけではなく、セクション名を格納する専用セクション(.shstrtab)におけるオフセットアドレスで管理しています。
説明が難しいので、実際の.shstrtabセクションの内容を確認してみます。ELFヘッダより、.shstrtabは「27番目のセクション」であることが分かっていますので、readelfコマンドでセクション番号27を指定(-x27)してダンプしてみます
※セクション番号はゼロベースであることに注意。
※以下ダンプの内容は「セクション」の内容であって「セクションヘッダ」の内容ではないことに注意。この点、しばしば混乱を招く。
$ readelf -x27 sample セクション '.shstrtab' の 十六進数ダンプ: 0x00000000 002e7379 6d746162 002e7374 72746162 ..symtab..strtab 0x00000010 002e7368 73747274 6162002e 696e7465 ..shstrtab..inte 0x00000020 7270002e 6e6f7465 2e414249 2d746167 rp..note.ABI-tag 0x00000030 002e6e6f 74652e67 6e752e62 75696c64 ..note.gnu.build 0x00000040 2d696400 2e676e75 2e686173 68002e64 -id..gnu.hash..d 0x00000050 796e7379 6d002e64 796e7374 72002e67 ynsym..dynstr..g 0x00000060 6e752e76 65727369 6f6e002e 676e752e nu.version..gnu. 0x00000070 76657273 696f6e5f 72002e72 656c2e64 version_r..rel.d 0x00000080 796e002e 72656c2e 706c7400 2e696e69 yn..rel.plt..ini 0x00000090 74002e74 65787400 2e66696e 69002e72 t..text..fini..r 0x000000a0 6f646174 61002e65 685f6672 616d655f odata..eh_frame_ 0x000000b0 68647200 2e65685f 6672616d 65002e69 hdr..eh_frame..i 0x000000c0 6e69745f 61727261 79002e66 696e695f nit_array..fini_ 0x000000d0 61727261 79002e6a 6372002e 64796e61 array..jcr..dyna 0x000000e0 6d696300 2e676f74 002e676f 742e706c mic..got..got.pl 0x000000f0 74002e64 61746100 2e627373 002e636f t..data..bss..co 0x00000100 6d6d656e 7400 mment.
というように、実際のセクション名の文字列は、.shstrtabセクション内に
\0 | セクション名 | \0 | セクション名 | \0 | セクション名 | \0 | … | セクション名 | \0 |
というナルターミネートされた状態で格納されています。
現時点で、「27番目のセクションヘッダが管理するのは.shstrtabセクションである」ということが分かっているので、27番目のセクションヘッダに、上の「.shstrtab」の位置情報が本当に格納されているか?確認してみます。
27番目のセクションヘッダのオフセットアドレスは「0x1584」でした。このアドレスをダンプしてみます。
$ od -x -A x -j0x1584 -N0x28 sample 001584 0011 0000 0003 0000 0000 0000 0000 0000 001594 1046 0000 0106 0000 0000 0000 0000 0000 0015a4 0001 0000 0000 0000 0015ac
セクション名の格納位置情報は、セクションヘッダにおける先頭2バイトとなります。上の場合、「0x0011」がそれに当たります。ここから、以下のことが言えます。
「27番目のセクションヘッダは、セクション名の文字列を、.shstrtabの先頭から0x0011(17)バイト目に持っている」
以下を見ると、確かに.shstrtabセクションの先頭17バイト目から「.shstrtab」という文字がセットされています。
0x00000000 002e7379 6d746162 002e7374 72746162 ..symtab..strtab 0x00000010 002e7368 73747274 6162002e 696e7465 ..shstrtab..inte
この調子で、他のセクションヘッダからもセクション名の位置情報を取得します。
$ od -x -A x -j0x0000114c -N0x28 sample 00114c 0000 0000 0000 0000 0000 0000 0000 0000 * 00116c 0000 0000 0000 0000 001174 $ od -x -A x -j0x1174 -N0x28 sample 001174 001b 0000 0001 0000 0002 0000 8154 0804 001184 0154 0000 0013 0000 0000 0000 0000 0000 001194 0001 0000 0000 0000 00119c $ od -x -A x -j0x119c -N0x28 sample 00119c 0023 0000 0007 0000 0002 0000 8168 0804 0011ac 0168 0000 0020 0000 0000 0000 0000 0000 0011bc 0004 0000 0000 0000 0011c4 $ od -x -A x -j0x11c4 -N0x28 sample 0011c4 0031 0000 0007 0000 0002 0000 8188 0804 0011d4 0188 0000 0024 0000 0000 0000 0000 0000 0011e4 0004 0000 0000 0000 0011ec $ od -x -A x -j0x11ec -N0x28 sample 0011ec 0044 0000 fff6 6fff 0002 0000 81ac 0804 0011fc 01ac 0000 0020 0000 0005 0000 0000 0000 00120c 0004 0000 0004 0000 001214 $ od -x -A x -j0x1214 -N0x28 sample 001214 004e 0000 000b 0000 0002 0000 81cc 0804 001224 01cc 0000 0040 0000 0006 0000 0001 0000 001234 0004 0000 0010 0000 00123c $ od -x -A x -j0x123c -N0x28 sample 00123c 0056 0000 0003 0000 0002 0000 820c 0804 00124c 020c 0000 0045 0000 0000 0000 0000 0000 00125c 0001 0000 0000 0000 001264 $ od -x -A x -j0x1264 -N0x28 sample 001264 005e 0000 ffff 6fff 0002 0000 8252 0804 001274 0252 0000 0008 0000 0005 0000 0000 0000 001284 0002 0000 0002 0000 00128c $ od -x -A x -j0x128c -N0x28 sample 00128c 006b 0000 fffe 6fff 0002 0000 825c 0804 00129c 025c 0000 0020 0000 0006 0000 0001 0000 0012ac 0004 0000 0000 0000 0012b4 $ od -x -A x -j0x12b4 -N0x28 sample 0012b4 007a 0000 0009 0000 0002 0000 827c 0804 0012c4 027c 0000 0008 0000 0005 0000 0000 0000 0012d4 0004 0000 0008 0000 0012dc $ od -x -A x -j0x12dc -N0x28 sample 0012dc 0083 0000 0009 0000 0002 0000 8284 0804 0012ec 0284 0000 0010 0000 0005 0000 000c 0000 0012fc 0004 0000 0008 0000 001304 $ od -x -A x -j0x1304 -N0x28 sample 001304 008c 0000 0001 0000 0006 0000 8294 0804 001314 0294 0000 0023 0000 0000 0000 0000 0000 001324 0004 0000 0000 0000 00132c $ od -x -A x -j0x132c -N0x28 sample 00132c 0087 0000 0001 0000 0006 0000 82c0 0804 00133c 02c0 0000 0030 0000 0000 0000 0000 0000 00134c 0010 0000 0004 0000 001354 $ od -x -A x -j0x1354 -N0x28 sample 001354 0092 0000 0001 0000 0006 0000 82f0 0804 001364 02f0 0000 0184 0000 0000 0000 0000 0000 001374 0010 0000 0000 0000 00137c $ od -x -A x -j0x137c -N0x28 sample 00137c 0098 0000 0001 0000 0006 0000 8474 0804 00138c 0474 0000 0014 0000 0000 0000 0000 0000 00139c 0004 0000 0000 0000 0013a4 $ od -x -A x -j0x13a4 -N0x28 sample 0013a4 009e 0000 0001 0000 0002 0000 8488 0804 0013b4 0488 0000 0008 0000 0000 0000 0000 0000 0013c4 0004 0000 0000 0000 0013cc $ od -x -A x -j0x13cc -N0x28 sample 0013cc 00a6 0000 0001 0000 0002 0000 8490 0804 0013dc 0490 0000 002c 0000 0000 0000 0000 0000 0013ec 0004 0000 0000 0000 0013f4 $ od -x -A x -j0x13f4 -N0x28 sample 0013f4 00b4 0000 0001 0000 0002 0000 84bc 0804 001404 04bc 0000 00b0 0000 0000 0000 0000 0000 001414 0004 0000 0000 0000 00141c $ od -x -A x -j0x141c -N0x28 sample 00141c 00be 0000 000e 0000 0003 0000 9f08 0804 00142c 0f08 0000 0004 0000 0000 0000 0000 0000 00143c 0004 0000 0000 0000 001444 $ od -x -A x -j0x1444 -N0x28 sample 001444 00ca 0000 000f 0000 0003 0000 9f0c 0804 001454 0f0c 0000 0004 0000 0000 0000 0000 0000 001464 0004 0000 0000 0000 00146c $ od -x -A x -j0x146c -N0x28 sample 00146c 00d6 0000 0001 0000 0003 0000 9f10 0804 00147c 0f10 0000 0004 0000 0000 0000 0000 0000 00148c 0004 0000 0000 0000 001494 $ od -x -A x -j0x1494 -N0x28 sample 001494 00db 0000 0006 0000 0003 0000 9f14 0804 0014a4 0f14 0000 00e8 0000 0006 0000 0000 0000 0014b4 0004 0000 0008 0000 0014bc $ od -x -A x -j0x14bc -N0x28 sample 0014bc 00e4 0000 0001 0000 0003 0000 9ffc 0804 0014cc 0ffc 0000 0004 0000 0000 0000 0000 0000 0014dc 0004 0000 0004 0000 0014e4 $ od -x -A x -j0x14e4 -N0x28 sample 0014e4 00e9 0000 0001 0000 0003 0000 a000 0804 0014f4 1000 0000 0014 0000 0000 0000 0000 0000 001504 0004 0000 0004 0000 00150c $ od -x -A x -j0x150c -N0x28 sample 00150c 00f2 0000 0001 0000 0003 0000 a014 0804 00151c 1014 0000 0008 0000 0000 0000 0000 0000 00152c 0004 0000 0000 0000 001534 $ od -x -A x -j0x1534 -N0x28 sample 001534 00f8 0000 0008 0000 0003 0000 a01c 0804 001544 101c 0000 0004 0000 0000 0000 0000 0000 001554 0004 0000 0000 0000 00155c $ od -x -A x -j0x155c -N0x28 sample 00155c 00fd 0000 0001 0000 0030 0000 0000 0000 00156c 101c 0000 002a 0000 0000 0000 0000 0000 00157c 0001 0000 0001 0000 001584 $ od -x -A x -j0x1584 -N0x28 sample 001584 0011 0000 0003 0000 0000 0000 0000 0000 001594 1046 0000 0106 0000 0000 0000 0000 0000 0015a4 0001 0000 0000 0000 0015ac $ od -x -A x -j0x15ac -N0x28 sample 0015ac 0001 0000 0002 0000 0000 0000 0000 0000 0015bc 15fc 0000 0420 0000 001d 0000 002d 0000 0015cc 0004 0000 0010 0000 0015d4 $ od -x -A x -j0x15d4 -N0x28 sample 0015d4 0009 0000 0003 0000 0000 0000 0000 0000 0015e4 1a1c 0000 0241 0000 0000 0000 0000 0000 0015f4 0001 0000 0000 0000 0015fc
表にまとめると、こうなります。
セクション番号 | .shstrtab上のセクション名の位置 | セクション番号 | .shstrtab上のセクション名の位置 |
---|---|---|---|
0 | 0x0000 | 15 | 0x009e |
1 | 0x001b | 16 | 0x00a6 |
2 | 0x0023 | 17 | 0x00b4 |
3 | 0x0031 | 18 | 0x00be |
4 | 0x0044 | 19 | 0x00ca |
5 | 0x004e | 20 | 0x00d6 |
6 | 0x0056 | 21 | 0x00db |
7 | 0x005e | 22 | 0x00e4 |
8 | 0x006b | 23 | 0x00e9 |
9 | 0x007a | 24 | 0x00f2 |
10 | 0x0083 | 25 | 0x00f8 |
11 | 0x008c | 26 | 0x00fd |
12 | 0x0087 | 27 | 0x0011 |
13 | 0x0092 | 28 | 0x0001 |
14 | 0x0098 | 29 | 0x0009 |
つぎに、.shstrtabの内容と位置情報の表を突き合わせて、セクション名を抽出してみます。
$ readelf -x27 sample セクション '.shstrtab' の 十六進数ダンプ: 0x00000000 002e7379 6d746162 002e7374 72746162 ..symtab..strtab 0x00000010 002e7368 73747274 6162002e 696e7465 ..shstrtab..inte 0x00000020 7270002e 6e6f7465 2e414249 2d746167 rp..note.ABI-tag 0x00000030 002e6e6f 74652e67 6e752e62 75696c64 ..note.gnu.build 0x00000040 2d696400 2e676e75 2e686173 68002e64 -id..gnu.hash..d 0x00000050 796e7379 6d002e64 796e7374 72002e67 ynsym..dynstr..g 0x00000060 6e752e76 65727369 6f6e002e 676e752e nu.version..gnu. 0x00000070 76657273 696f6e5f 72002e72 656c2e64 version_r..rel.d 0x00000080 796e002e 72656c2e 706c7400 2e696e69 yn..rel.plt..ini 0x00000090 74002e74 65787400 2e66696e 69002e72 t..text..fini..r 0x000000a0 6f646174 61002e65 685f6672 616d655f odata..eh_frame_ 0x000000b0 68647200 2e65685f 6672616d 65002e69 hdr..eh_frame..i 0x000000c0 6e69745f 61727261 79002e66 696e695f nit_array..fini_ 0x000000d0 61727261 79002e6a 6372002e 64796e61 array..jcr..dyna 0x000000e0 6d696300 2e676f74 002e676f 742e706c mic..got..got.pl 0x000000f0 74002e64 61746100 2e627373 002e636f t..data..bss..co 0x00000100 6d6d656e 7400 mment.
セクション番号 | .shstrtab上のセクション名の位置 | その位置にある文字列 |
---|---|---|
0 | 0x0000 | "\0" |
1 | 0x001b | ".interp" |
2 | 0x0023 | ".note.ABI-tag" |
3 | 0x0031 | ".note.gnu.build-id" |
4 | 0x0044 | ".gnu.hash" |
5 | 0x004e | ".dynsym" |
6 | 0x0056 | ".dynstr" |
7 | 0x005e | ".gnu.version" |
8 | 0x006b | ".gnu.version_r" |
9 | 0x007a | ".rel.dyn" |
10 | 0x0083 | ".rel.plt" |
11 | 0x008c | ".init" |
12 | 0x0087 | ".plt" |
13 | 0x0092 | ".text" |
14 | 0x0098 | ".fini" |
15 | 0x009e | ".rodata" |
16 | 0x00a6 | ".eh_frame_hdr" |
17 | 0x00b4 | ".eh_frame" |
18 | 0x00be | ".init_array" |
19 | 0x00ca | ".fini_array" |
20 | 0x00d6 | ".jcr" |
21 | 0x00db | ".dynamic" |
22 | 0x00e4 | ".got" |
23 | 0x00e9 | ".got.plt" |
24 | 0x00f2 | ".data" |
25 | 0x00f8 | ".bss" |
26 | 0x00fd | ".comment" |
27 | 0x0011 | ".shstrtab" |
28 | 0x0001 | ".symtab" |
29 | 0x0009 | ".strtab" |
と、綺麗に抽出できました。正直ホッとした…(^^;
この表を作成していて細かいことに気づいたのですが、
10 | 0x0083 | ".rel.plt" |
12 | 0x0087 | ".plt" |
セクション名".plt"は".rel.plt"と別に格納されているのではなく、".rel.plt"の4バイト目を開始位置として抽出しています。バイト数を節約する工夫でしょうか。
最後に、前回作成したELF形式のレイアウトに、今回取得したセクション名を穴埋めしておきます。
オフセット | 内容 | サイズ | 管理セクション名 |
---|---|---|---|
0x0000114c | セクションヘッダ0 | 28h(40d)バイト | "\0" |
0x00001174 | セクションヘッダ1 | 28h(40d)バイト | ".interp" |
0x0000119c | セクションヘッダ2 | 28h(40d)バイト | ".note.ABI-tag" |
0x000011c4 | セクションヘッダ3 | 28h(40d)バイト | ".note.gnu.build-id" |
0x000011ec | セクションヘッダ4 | 28h(40d)バイト | ".gnu.hash" |
0x00001214 | セクションヘッダ5 | 28h(40d)バイト | ".dynsym" |
0x0000123c | セクションヘッダ6 | 28h(40d)バイト | ".dynstr" |
0x00001264 | セクションヘッダ7 | 28h(40d)バイト | ".gnu.version" |
0x0000128c | セクションヘッダ8 | 28h(40d)バイト | ".gnu.version_r" |
0x000012b4 | セクションヘッダ9 | 28h(40d)バイト | ".rel.dyn" |
0x000012dc | セクションヘッダ10 | 28h(40d)バイト | ".rel.plt" |
0x00001304 | セクションヘッダ11 | 28h(40d)バイト | ".init" |
0x0000132c | セクションヘッダ12 | 28h(40d)バイト | ".plt" |
0x00001354 | セクションヘッダ13 | 28h(40d)バイト | ".text" |
0x0000137c | セクションヘッダ14 | 28h(40d)バイト | ".fini" |
0x000013a4 | セクションヘッダ15 | 28h(40d)バイト | ".rodata" |
0x000013cc | セクションヘッダ16 | 28h(40d)バイト | ".eh_frame_hdr" |
0x000013f4 | セクションヘッダ17 | 28h(40d)バイト | ".eh_frame" |
0x0000141c | セクションヘッダ18 | 28h(40d)バイト | ".init_array" |
0x00001444 | セクションヘッダ19 | 28h(40d)バイト | ".fini_array" |
0x0000146c | セクションヘッダ20 | 28h(40d)バイト | ".jcr" |
0x00001494 | セクションヘッダ21 | 28h(40d)バイト | ".dynamic" |
0x000014bc | セクションヘッダ22 | 28h(40d)バイト | ".got" |
0x000014e4 | セクションヘッダ23 | 28h(40d)バイト | ".got.plt" |
0x0000150c | セクションヘッダ24 | 28h(40d)バイト | ".data" |
0x00001534 | セクションヘッダ25 | 28h(40d)バイト | ".bss" |
0x0000155c | セクションヘッダ26 | 28h(40d)バイト | ".comment" |
0x00001584 | セクションヘッダ27 | 28h(40d)バイト | ".shstrtab" |
0x000015ac | セクションヘッダ28 | 28h(40d)バイト | ".symtab" |
0x000015d4 | セクションヘッダ29 | 28h(40d)バイト | ".strtab" |