【#も読】オブジェクトファイル(@gorilla0513)のトップ画像

【#も読】オブジェクトファイル(@gorilla0513)

投稿日時:2025/05/12 03:00
ゴリラのアイコン

株式会社テックリード / 代表取締役

ゴリラ

Xアカウントリンク

「あの人も読んでる」略して「も読」。さまざまな寄稿者が最近気になった情報や話題をシェアする企画です。他のテックな人たちがどんな情報を追っているのか、ちょっと覗いてみませんか?


こんにちは。

前回の記事ではリンカーの概要と『リンカ・ローダ実践開発テクニック』という本について紹介しました。リンカーとはなにか、どんな仕事をしているのかについてなんとなくイメージできたかなと思います。

今回はオブジェクトファイルについて少し詳細を話していきます。

オブジェクトファイルとは

前回の記事では次のように説明しました。

オブジェクトファイルはソースファイル単位で独立してコンパイルすることができ、命令やグローバルな変数、定数といったデータを持っています。

オブジェクトファイルにはフォーマットがあって、OSによって異なっています。 それぞれのフォーマットは次の表に示します。

OSフォーマット
Unix/LinuxELF(Executable and Linkable Format)
macOSMach-O(Mach object)
WindowsCOFF(Common Object File Format)

今日のウェブシステム開発ではコンテナが主流で、ELFはなんとなく知っている方もいるのではないと思うので、今回はELFについて少し掘り下げていきます。

ELF(Executable and Linkable Format)について

ELFは名前のとおり、実行・リンク可能なフォーマットとなっています。 ファイルが実行可能なのか、リンク可能なのかを判断するにはreadelfコマンドを使います。

$ readelf -h a.out | grep Type 
  Type:                              EXEC (Executable file)
$ readelf -h a.o | grep Type
  Type:                              REL (Relocatable file)

Relocatable fileは再配置(前回記事参照)情報を持ったリンク可能なファイルです。

ELFは大き分けると次の領域で構成されています。

構成概要
ヘッダーELFファイルのメタデータ、OSのアーキテクチャなどの情報を持つ
プログラムヘッダープログラムを実行する際に必要な情報を持つ
セクションELFファイル内の実際のプログラムデータやコードの情報を持つ
セクションヘッダーELFファイル内の各セクションの位置、サイズ、属性などの情報を持つ

セクションは更にいくつか種類があります。 代表なものとして.data.text.symtabがあります。

.textは命令群(アセンブリ)が配置されていて、objdumpでそれらを確認できます。

$ objdump -d a.out
a.out:     file format elf64-littleaarch64


Disassembly of section .text:

0000000000400100 <_start>:
  400100:       10080080        adr     x0, 410110 <x>
  400104:       b9400000        ldr     w0, [x0]
  400108:       d2800ba8        mov     x8, #0x5d                       // #93
  40010c:       d4000001        svc     #0x0

生データはこんな感じですね。

$ readelf -x .text a.out

Hex dump of section '.text':
  0x00400100 80000810 000040b9 a80b80d2 010000d4 ......@.........

.data.textの命令で使われているデータが配置されます。

$ readelf -x .data a.out

Hex dump of section '.data':
  0x00410110 17000073                            ...s

.symtabはシンボル(変数など)のアドレス値や種類などの情報を持っています。 これらは実行時には不要ですが、デバッグ時に使用します。

$ readelf -s a.out

Symbol table '.symtab' contains 8 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000000000000     0 SECTION LOCAL  DEFAULT    4
     2: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS sub.c
     3: 0000000000410110     0 NOTYPE  LOCAL  DEFAULT    2 $d
     4: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS main.c
     5: 0000000000400100     0 NOTYPE  LOCAL  DEFAULT    1 $x
     6: 0000000000400100     0 NOTYPE  GLOBAL DEFAULT    1 _start
     7: 0000000000410110     4 OBJECT  GLOBAL DEFAULT    2 x

テキストだとあんまり全体像を掴めない方は以下の図を参照してください。大変わかりやすくにまとまっているかなと思います。

corkami「ELF101-64」(CC BY 3.0)

更に細かく知りたい方は『[全部無料]最小限で理解しつつ作るELF parser入門 in Rust』という本がzenn.devで公開されているので、実装しながら理解したい方はぜひこちらをやってみてください。

さいごに

今回はオブジェクトファイルとELFについて少し掘り下げつつ、ELFパーサー実装本について紹介しました。 少し興味を持っていただけたら嬉しいです。

次回は、高速なリンカーmoldについて、少し深堀りしていきます。

ゴリラさんの「も読」過去記事