ELFフォーマットについてのメモ書き

勉強用のメモ書き いずれ分かりやすく書くので適当に羅列していきます

随時更新する予定

 

 

LinuxにおいてのELFフォーマットの定義は /usr/include/elf.h を参照することで確認できる。32bitアーキテクチャと64bitアーキテクチャで定義が分かれているので注意。

・elf.h内のデータ型の定義は同ファイル内の typedef を見ることで確認できる。詳しく知りたい場合は /usr/include/stdint.h を読むことになるが、大体コメントアウトの内容で察することが出来る。

30 │ /* Type for a 16-bit quantity. */
31 │ typedef uint16_t Elf32_Half;
32 │ typedef uint16_t Elf64_Half;
33 │
34 │ /* Types for signed and unsigned 32-bit quantities. */
35 │ typedef uint32_t Elf32_Word;
36 │ typedef int32_t Elf32_Sword;
37 │ typedef uint32_t Elf64_Word;
38 │ typedef int32_t Elf64_Sword;
39 │
40 │ /* Types for signed and unsigned 64-bit quantities. */
41 │ typedef uint64_t Elf32_Xword;
42 │ typedef int64_t Elf32_Sxword;
43 │ typedef uint64_t Elf64_Xword;
44 │ typedef int64_t Elf64_Sxword;
45 │
46 │ /* Type of addresses. */
47 │ typedef uint32_t Elf32_Addr;
48 │ typedef uint64_t Elf64_Addr;
49 │
50 │ /* Type of file offsets. */
51 │ typedef uint32_t Elf32_Off;
52 │ typedef uint64_t Elf64_Off;
53 │
54 │ /* Type for section indices, which are 16-bit quantities. */
55 │ typedef uint16_t Elf32_Section;
56 │ typedef uint16_t Elf64_Section;
57 │
58 │ /* Type for version symbol information. */
59 │ typedef Elf32_Half Elf32_Versym;
60 │ typedef Elf64_Half Elf64_Versym;

 

・ELFフォーマットは大体ELFヘッダ、プログラムヘッダテーブル、セクション(セグメント)、セクションヘッダテーブルで構成されている。詳しくは以下のリンク。ただし、サイトに載っているのはLinuxではなくOpenBSDでのELFフォーマットなので、変数のビット数や順番などが微妙に違うため、自分のelf.hと照らし合わせて間違えないようにする。

http://caspar.hazymoon.jp/OpenBSD/annex/elf.html

・ELF 64において、ELFヘッダは先頭から0x40バイトまでである。6バイト目にバイトオーダーの指定があり、1だとリトルエンディアン、2だとビッグエンディアンである。これによってバイナリの読み方が変わってくるので、自力でバイナリを読む人は注意。

・ELF 64において、プログラムヘッダは一つ0x38バイトである。ELFヘッダのe_phentsizeを見ることでも確認できる。

・ELF 64において、セクションヘッダは一つ0x40バイトである。ELFヘッダのe_shentsizeを見ることでも確認できる。

・セクションヘッダは一つのセクションとそれぞれ対応している。
$readelf -S hogehoge でセクションヘッダの内容を見ることが出来る。バイナリを直接読みたい人はELFヘッダの e_shoff (セクションヘッダテーブルのオフセット)から e_shentsize(セクションヘッダ1個のサイズ) * e_shnum(セクションヘッダの個数) バイトを参照すればよい。

f:id:nexem:20200304024133p:plain

 

・readelfでセクションヘッダを見ると名前が出てくるが、これはセクションヘッダに直書きされているわけではなく、.shstrtab セクションに書かれている。ELFヘッダのe_shstrndxに、.shstrtabセクションへのインデックスが書かれている(注:オフセットではない)。 readelfコマンドには、インデックス指定でセクションをダンプできるオプションがあるので、それを使うとセクションの名前が羅列されているのが確認できる。例えば、e_shstrndx が 0x1c だった場合、$ readelf -x0x1c hogehoge という感じで。

f:id:nexem:20200304024203p:plain

 

セクションの各役割

 

.interp
その実行ファイルを動作させる動的リンカ(もしくはそれへのシンボリックリンク)が示されている。

f:id:nexem:20200306030243p:plain


.note.ABI-tag
最低限互換性のあるLinuxカーネルのバージョンが記述されている?(要調査

f:id:nexem:20200306030447p:plain

 

参考リンク

ELF Formatについて

http://caspar.hazymoon.jp/OpenBSD/annex/elf.html

【ELF形式】セクションヘッダとセクションの関係

https://yz2cm.hatenadiary.org/entry/20131012/1381604147