技術情報

実行ファイルはどう作られるか (3)

オブジェクトファイルのセクション

オブジェクトファイルは複数のセクションを持ち、それぞれが異なる役割を持っています。例えば、主要なセクションについては次表のとおりです:

.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セクションに存在することを示しています。このように、オブジェクトファイル中にはシンボルをバイナリに変換するための情報を格納されていることが分かります。

次回以降

次回は、実行ファイルのリンクの際にどのようにしてシンボルの実態データへの置き換えがなされるかを解説します。

D.S S.O
データサイエンティストのS.Oです。