オブジェクトファイルのセクション
オブジェクトファイルは複数のセクションを持ち、それぞれが異なる役割を持っています。例えば、主要なセクションについては次表のとおりです:
.text | 実行命令 |
---|---|
.symtab | 変数名や関数名など、ソースコード中で定義したシンボルに関する情報 |
.data | 初期化済みデータ |
.rodate | 読み込み専用データ |
.rela.text | シンボルの置き換え情報 |
実行ファイルはバイナリ形式であるため、ソースコード上で定義された変数や関数等のシンボルはすべてメモリ上のデータに置き換えなければなりません。この時、.textセクション中に格納された命令列にいついて、「どの部分をどのシンボルのデータで置き換えるか?また、各シンボルはどのデータをさすのか?」という問題が発生します。これを解決するために、リンクの際には、.symtab内の情報を用いてシンボルが「どのデータを指すのか?」という部分を解決、さらに.rela.textを用いて、「どの部分をどのシンボルのデータで置き換えるか?」を解決しています。
コンパイルされたオブジェクトファイルを見てみよう
次のコマンドを実行し、hoge.txtを開いてみましょう:
objdump -S -t exec_file_sample.o >> hoge.txt
hoge.txt内に.textセクションが存在し、内容は次のようになります:
Disassembly of section .text:
0000000000000000 <main>:
0: f3 0f 1e fa endbr64
4: 55 push %rbp
5: 48 89 e5 mov %rsp,%rbp
8: 48 83 ec 10 sub $0x10,%rsp
c: c7 45 fc 02 00 00 00 movl $0x2,-0x4(%rbp)
13: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # 19 <main+0x19>
19: 8b 55 fc mov -0x4(%rbp),%edx
1c: 89 d6 mov %edx,%esi
1e: 89 c7 mov %eax,%edi
20: e8 00 00 00 00 callq 25 <main+0x25>
25: 89 c6 mov %eax,%esi
27: 48 8d 3d 00 00 00 00 lea 0x0(%rip),%rdi # 2e <main+0x2e>
2e: b8 00 00 00 00 mov $0x0,%eax
33: e8 00 00 00 00 callq 38 <main+0x38>
38: b8 00 00 00 00 mov $0x0,%eax
3d: c9 leaveq
3e: c3 retq
このセクションではコンピュータが実行可能なバイナリ形式の命令が格納されています。また、右にはそのアセンブラ表記が書かれています。アセンブラはCPUへの命令を記述するものです。さらに、hoge.txtには.symtabセクションが存在し、次のようになります:
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 exec_file_sample.c
0000000000000000 l d .text 0000000000000000 .text
0000000000000000 l d .data 0000000000000000 .data
0000000000000000 l d .bss 0000000000000000 .bss
0000000000000000 l d .rodata 0000000000000000 .rodata
0000000000000000 l d .note.GNU-stack 0000000000000000 .note.GNU-stack
0000000000000000 l d .note.gnu.property 0000000000000000 .note.gnu.property
0000000000000000 l d .eh_frame 0000000000000000 .eh_frame
0000000000000000 l d .comment 0000000000000000 .comment
0000000000000000 g O .bss 0000000000000004 hoge
0000000000000000 g F .text 000000000000003f main
0000000000000000 *UND* 0000000000000000 _GLOBAL_OFFSET_TABLE_
0000000000000000 *UND* 0000000000000000 add_num
0000000000000000 *UND* 0000000000000000 printf
ここでは、実際にソースコード中で定義した変数名・関数名等のシンボルに関する情報が格納されています。ここで、4列目の表記が.dataとなっているシンボルは、データの実態が.dataセクションに存在することを示しています。このように、オブジェクトファイル中にはシンボルをバイナリに変換するための情報を格納されていることが分かります。
次回以降
次回は、実行ファイルのリンクの際にどのようにしてシンボルの実態データへの置き換えがなされるかを解説します。