ELFフォーマット

Executable and Linkable Format。Linux の実行ファイル・オブジェクトファイル・共有ライブラリの形式。

二面性

ELFの最大の特徴は、プログラムの「リンク」と「実行」に応じた二重構造を持つこと。

  • セクション(section) から見る視点: リンク時に使う。.text(プログラム)、.rodata.data(書き換え可能な global/static 変数)、.bss。section headers が記述する。
  • セグメント(segment) から見る視点: 実行(ロード)時に使う。複数のセクションをまとめたもので、program headers がメタ情報を持つ。readelf の “Section to Segment mapping” で対応がわかる。

ヘッダ構造

全体は ELF header → program headers → 各 section → section headers の順に並ぶ。

  • アーキテクチャでフォーマットが変わる。i386(x86)はオフセットが u32x64u64。先頭16バイトで判別可能。詳細は cpu-architecture-isa
  • program header の p_filesz(ファイル上サイズ)と p_memsz(メモリ上サイズ)は異なり、.bss(static配列など)の分だけ後者が膨らむ。
  • type: PT_GNU_STACK(スタックの実行可否をシステムに伝える。アセンブラを混ぜると executable flag が付く)、PT_GNU_RELRO(dataセグメントの一部、cpu-side-channel-attacks や pwn で頻出)。

VMAとLMA

  • VMA (Virtual Memory Address): プログラム実行時に参照されるアドレス。リンカスクリプト記述の基準。
  • LMA (Load Memory Address): プログラムをロードするときに参照されるアドレス。組み込みでは RAM 上のアドレスを指す。
  • 通常は両者一致するが、kernel program では異なる。リンカスクリプト(ld の Linker Script)では . が現在のVMAを示し、AT(<lma>) でLMAを指定する。

関連ツール

  • readelf / objdump: ELF の解析・逆アセンブル。
  • gdb: -g 付きでデバッグ情報を付与、gcc -static でstaticリンク。
  • スタックフレーム: 関数呼び出しの局所変数・戻りアドレス領域。

関連: _moc-systems / linux / operating-system-kernel