Document

advertisement
先端ソフトウェア工学II
リンク、ロード、オブジェクト等の詳細

参考書


Linkers&Loaders, John R.Levine,オーム社
Binary Hacks, オライリージャパン
プログラムの翻訳と起動

コンパイル:高級言語(Cを例として扱う)を
アセンブリコードに変換


アセンブル:アセンブリコードをマシンコード
に変換し、オブジェクトファイルを生成



hoge.c -> hoge.s
hoge.s -> hoge.o
リンク:複数のオブジェクトファイルをつなぎ
合わせる
ロード:実行ファイルをメモリに読み込み起
動する
リンクとロード
ロード



プログラムのロード:プログラムを実行可能
なように2次記憶(ディスク等)からメインメ
モリにコピーすること。
再配置(relocation):プログラムに割り付け
られたアドレス情報に基づき、プログラム
のコードやデータを調整する処理。
シンボルの解決:シンボルとはあるプログ
ラムから他のプログラムを呼び出す際に利
用する参照で、これをアドレス情報を利用
して解決する処理。
リンク
具体例&Cの復習

以下のコードを考える
call_lib.c:
my_lib.c:
other_lib.c:
extern void my_func(void);
extern void other_func(void);
int main(void){
my_func();
other_func();
return 0;
}
#include <stdio.h>
void my_func(void){
printf(“my_func\n”);
}
#include <stdio.h>
void other_func(void){
printf(“other_func\n”);
}
コンパイル&実行
%gcc –c my_libc.c
%gcc –c other_libc.c
%gcc –c call_lib.c
%ls
call_lib.o my_lib.o other_lib.o
%gcc –o call_lib call_lib.o my_lib.o other_lib.o
%./call_lib
my_func
other_func
静的ライブラリの作成
%gcc –c my_libc.c
%gcc –c other_libc.c
%ls
my_lib.o other_lib.o
%ar rcus libmy_lib.a my_lib.o other_lib.o
#以下はリンク&実行
%gcc –o static_call call_lib.c –L. –lmy_lib
%./static_call
my_func
other_func
nmによるシンボルの確認

nm:オブジェクトファイルに含まれるシンボ
ルを表示するツール
%nm –version
GNU nm (GNU Binutils for Debian) 2.19.91.20091003
Copyright 2009 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) any later version.
This program has absolutely no warranty.
nmによるシンボルの確認
%nm my_lib.o
00000000 T my_func
U puts
%nm other_lib.o
00000000 T other_func
U puts
%nm libmy_lib.a
my_lib.o:
00000000 T my_func
U puts
other_lib.o:
00000000 T other_func
U puts
nmによるシンボルの確認
%nm static_call
0804950c d _DYNAMIC
080495e0 d _GLOBAL_OFFSET_TABLE_
080484dc R _IO_stdin_used
w _Jv_RegisterClasses
080494fc d __CTOR_END__
080494f8 d __CTOR_LIST__
08049504 D __DTOR_END__
08049500 d __DTOR_LIST__
080484f4 r __FRAME_END__
08049508 d __JCR_END__
08049508 d __JCR_LIST__
08049600 A __bss_start
080495f8 D __data_start
08048490 t __do_global_ctors_aux
08048340 t __do_global_dtors_aux
080495fc D __dso_handle
w __gmon_start__
0804848a T __i686.get_pc_thunk.bx
080494f8 d __init_array_end
080494f8 d __init_array_start
08048420 T __libc_csu_fini
08048430 T __libc_csu_init
U __libc_start_main@@GLIBC_2.0
08049600 A _edata
08049608 A _end
080484bc T _fini
080484d8 R _fp_hw
08048298 T _init
08048310 T _start
08049600 b completed.5723
080495f8 W data_start
08049604 b dtor_idx.5725
080483a0 t frame_dummy
080483c4 T main
080483f0 T my_func
08048404 T other_func
U puts@@GLIBC_2.0
nmによるシンボルの確認

stripしてみる(シンボル情報を削る)
%strip static_call
%nm static_call
nm: static_call: no symbols
#動的シンボルを表示
%nm –D static_call
080484dc R _IO_stdin_used
w __gmon_start__
U __libc_start_main
U puts
nmの使い方

シンボルクラス





A:シンボルの値が絶対値。
B:シンボルは未初期化データ領域(BSS)にあ
る。
C:シンボルは初期化済みデータセクションに
ある。
G:シンボルは小さなオブジェクトで使われる初
期化済みデータセクションにある。
I:シンボルは別のシンボルへの間接参照。
a.outのGNU拡張。
nmの使い方

シンボルクラス





N:デバッグ用シンボル。
R:読み込み専用データセクションにある。
S:小さなオブジェクトに使われる未初期化デー
タセクションにある。
T:テキストセクションにある。
U:未定義シンボル。別のオブジェクトファイル
または共有ライブラリにシンボルの実体があ
る。
nmの使い方

シンボルクラス




V:weakオブジェクト。
W:シンボルはweakオブジェクトシンボルと決
まっていないweakシンボル。
-:a.outオブジェクトファイル内のstabsシンボ
ル。(デバッグ情報等)
?:未知のシンボルクラス。
nmの使い方

セクション毎に分類

テキストセクション



データセクション





T:グローバル
t:ローカル
D:グローバル
G:グローバル(小さなオブジェクト)
d:グローバル
g:グローバル(小さなオブジェクト)
読み込み専用データ

R:グローバル
nmの使い方

BSS(未初期化データ)





weakオブジェクト



B:グローバル
S:グローバル(小さなオブジェクト用)
b:ローカル
s:ローカル(小さなオブジェクト用)
V:グローバル
v:ローカル
weakシンボル


W:グローバル
w:ローカル
nmの使い方

コモン


デバッグ用




C:グローバル
N:グローバル
n:ローカル
-:stabs
絶対値


A:グローバル
a:ローカル
nmの使い方

未定義


間接参照



U:グローバル
I:グローバル
i:ローカル
未知のクラス

?
共有ライブラリの作成
%gcc –c –fPIC my_libc.c
%gcc –c –fPIC other_libc.c
%ls
my_lib.o other_lib.o
%gcc –shared –o libmy_lib.so my_lib.o other_lib.o
#本当はgcc –shared –Wl,-soname,libmy_lib.so.0
#のように soname を指定するほうが良い。
#以下はリンク&実行
%gcc –o dynamic_call call_lib.c –L. –lmy_lib
%./static_call
my_func
other_func
fileコマンドによる確認

fileコマンド:ファイルの種類を判別
%file my_lib.o
my_lib.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
%file other_lib.o
other_lib.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
%file libmy_lib.so
libmy_lib.so: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV),
dynamically linked, not stripped
%file dynamic_call
Dynamic_call: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV),
dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped
nmによるシンボルの確認
%nm my_lib.o
U _GLOBAL_OFFSET_TABLE_
00000000 T __i686.get_pc_thunk.bx
00000000 T my_func
U puts
%nm other_lib.o
U _GLOBAL_OFFSET_TABLE_
00000000 T __i686.get_pc_thunk.bx
00000000 T other_func
U puts
nmによるシンボルの確認
%nm libmy_lib.so
00001550 a _DYNAMIC
00001624 a _GLOBAL_OFFSET_TABLE_
w _Jv_RegisterClasses
00001540 d __CTOR_END__
0000153c d __CTOR_LIST__
00001548 d __DTOR_END__
00001544 d __DTOR_LIST__
00000538 r __FRAME_END__
0000154c d __JCR_END__
0000154c d __JCR_LIST__
00001640 A __bss_start
w __cxa_finalize@@GLIBC_2.1.3
000004d0 t __do_global_ctors_aux
000003c0 t __do_global_dtors_aux
0000163c d __dso_handle
w __gmon_start__
00000477 t __i686.get_pc_thunk.bx
00001640 A _edata
00001648 A _end
00000508 T _fini
0000034c T _init
00001640 b completed.5723
00001644 b dtor_idx.5725
00000440 t frame_dummy
0000047c T my_func
000004a4 T other_func
U puts@@GLIBC_2.0
lddによる依存関係の調査

ldd:共有ライブラリの依存関係を調べるた
めのコマンド
%ldd libmy_lib.so
linux-gate.so.1 => (0xb8006000)
libc.so.6 => /lib/i686/cmov/libc.so.6 (0xb7e8d000)
/lib/ld-linux.so.2 (0xb8007000)
nmによるシンボルの確認
%nm dynamic_call
080495e8 d _DYNAMIC
080496c4 d _GLOBAL_OFFSET_TABLE_
080485cc R _IO_stdin_used
w _Jv_RegisterClasses
080495d8 d __CTOR_END__
080495d4 d __CTOR_LIST__
080495e0 D __DTOR_END__
080495dc d __DTOR_LIST__
080485d0 r __FRAME_END__
080495e4 d __JCR_END__
080495e4 d __JCR_LIST__
080496e8 A __bss_start
080496e0 D __data_start
08048580 t __do_global_ctors_aux
08048460 t __do_global_dtors_aux
080496e4 D __dso_handle
w __gmon_start__
0804857a T __i686.get_pc_thunk.bx
080495d4 d __init_array_end
080495d4 d __init_array_start
08048510 T __libc_csu_fini
08048520 T __libc_csu_init
U __libc_start_main@@GLIBC_2.0
080496e8 A _edata
080496f0 A _end
080485ac T _fini
080485c8 R _fp_hw
080483ac T _init
08048430 T _start
080496e8 b completed.5723
080496e0 W data_start
080496ec b dtor_idx.5725
080484c0 t frame_dummy
080484e4 T main
U my_func
U other_func
lddによる依存関係の調査
%ldd dynamic_call
linux-gate.so.1 => (0xb8063000)
libmy_lib.so => ./libmy_lib.so (0xb805f000)
libc.so.6 => /lib/i686/cmov/libc.so.6 (0xb7eea000)
/lib/ld-linux.so.2 (0xb8064000)
メモリまわりの話
メモリアドレスetc

メモリアドレス


メモリに割り当てられた0からメ
モリアドレス幅で決定される最大
値までの値。通常、バイトアドレ
スとなる。
メモリ
3
0
31
28
エンディアン


ビッグエンディアン:上位アドレス
が下位バイトを示す。
リトルエンディアン:下位アドレス
が下位バイトを示す。
0
1
2
3
63 3
2
1
0 60
ページングと仮想メモリ
仮想アドレス空間
ページ
:数KB
物理メモリ
ページテーブル
2次記憶(ディスク等)
ページングと仮想メモリ
仮想アドレス空間
ページ
:数KB
物理メモリ
ページテーブル
2次記憶(ディスク等)
ページングと仮想メモリ
仮想アドレス空間
ページ
:数KB
物理メモリ
ページテーブル
2次記憶(ディスク等)
ページングと仮想メモリ
仮想アドレス空間
ページ
:数KB
物理メモリ
ページテーブル
2次記憶(ディスク等)
ページングと仮想メモリ
仮想アドレス空間
ページ
:数KB
物理メモリ
ページテーブル
2次記憶(ディスク等)
ページングと仮想メモリ
仮想アドレス空間
ページ
:数KB
物理メモリ
ページテーブル
2次記憶(ディスク等)
ページングと仮想メモリ
仮想アドレス空間
ページ
:数KB
ページフォルト
ページテーブル
物理メモリ
2次記憶(ディスク等)
ページングと仮想メモリ
仮想アドレス空間
ページ
:数KB
物理メモリ
ページテーブル
2次記憶(ディスク等)
ページングと仮想メモリ
仮想アドレス空間
ページ
:数KB
物理メモリ
ページテーブル
2次記憶(ディスク等)
ページングと仮想メモリ
仮想アドレス空間
ページ
:数KB
ページイン
ページテーブル
物理メモリ
2次記憶(ディスク等)
ページングと仮想メモリ
仮想アドレス空間
ページ
:数KB
物理メモリ
ページテーブル
2次記憶(ディスク等)
ページングと仮想メモリ
仮想アドレス空間
ページ
:数KB
物理メモリ
ページテーブル
2次記憶(ディスク等)
ページングと仮想メモリ
仮想アドレス空間
ページ
:数KB
物理メモリ
ページテーブル
2次記憶(ディスク等)
ページングと仮想メモリ
仮想アドレス空間
ページ
:数KB
物理メモリ
ページテーブル
2次記憶(ディスク等)
ページングと仮想メモリ
仮想アドレス空間
ページ
:数KB
物理メモリ
ページテーブル
2次記憶(ディスク等)
ページングと仮想メモリ
仮想アドレス空間
ページ
:数KB
ページアウト
ページテーブル
物理メモリ
2次記憶(ディスク等)
ページングと仮想メモリ
仮想アドレス空間
ページ
:数KB
ページアウト
ページテーブル
物理メモリ
2次記憶(ディスク等)
ページングと仮想メモリ
仮想アドレス空間
ページ
:数KB
物理メモリ
ページテーブル
2次記憶(ディスク等)
ページングと仮想メモリ
仮想アドレス空間
ページ
:数KB
ページイン
ページテーブル
物理メモリ
2次記憶(ディスク等)
ページングと仮想メモリ
読み出し専用属性による高速化
仮想アドレス空間
ページ
:数KB
物理メモリ
ページテーブル
2次記憶(ディスク等)
ページングと仮想メモリ
仮想アドレス空間
ページ
:数KB
物理メモリ
ページテーブル
2次記憶(ディスク等)
ページングと仮想メモリ
仮想アドレス空間
ページ
:数KB
ページイン
ページテーブル
物理メモリ
2次記憶(ディスク等)
ページングと仮想メモリのまとめ

利点


仮想メモリによる大規模アドレス空間の提供
欠点

ページフォールト時に非常に遅延の大きい
ディスクアクセスを要求
リンカが頑張ってコンパクトにまとめる
プログラムのアドレス空間

PDP-11versionのUNIX




アドレス空間:0番地からの64KB
読み出し専用コード:0番地からの領域にロー
ド
データ:コードの後の8KB境界から
スタック:64K-1番地から下位方向に伸ばす
プログラムのアドレス空間

VAX UNIX


PDP-11と同様
最初の2バイトが必ず0


文字列ポインタをnullにすると0が読まれる:nullポ
インタによるバグの温床
UNIXシステム


各アプリケーション毎に独立したアドレス空間
OSはアプリケーションと独立したアドレス空間
プログラムのアドレス空間

x86 MS-DOS



ハードウェア保護を使わない
システムとアプリケーションが同じアドレス空
間
システムは未使用メモリの最も大きなかたまり
上にプログラムをロードして実行
ハードウェア保護:仮想メモリを実現する機構のこと。
MMU(Memory Management Unit)という
プログラムのアドレス空間

MS Windows



各プログラムは標準の開始アドレスにロード
実行可能なプログラムは再配置情報を保有
標準アドレスが利用不可能な場合は適切な場
所にロードする
共有ライブラリとプログラム

ページテーブルセットの割り当て

各プログラムに独立


頑健だが性能に難あり
ライブラリの共有


再配置されないコードおよび読み出し専用
コード:RO(Read Only)としてマップする
書き込み可能データ:COW(Copy On Write)
でマップする
共有ライブラリとプログラム2次記憶(ディスク等)
仮想アドレス空間0
仮想アドレス空間1
仮想アドレス空間2
仮想アドレス空間3
物理メモリ
共有ライブラリとプログラム2次記憶(ディスク等)
仮想アドレス空間0
仮想アドレス空間1
仮想アドレス空間2
仮想アドレス空間3
物理メモリ
共有ライブラリとプログラム2次記憶(ディスク等)
仮想アドレス空間0
仮想アドレス空間1
仮想アドレス空間2
仮想アドレス空間3
物理メモリ
共有ライブラリとプログラム2次記憶(ディスク等)
仮想アドレス空間0
仮想アドレス空間1
仮想アドレス空間2
仮想アドレス空間3
物理メモリ
共有ライブラリとプログラム2次記憶(ディスク等)
仮想アドレス空間0
仮想アドレス空間1
仮想アドレス空間2
仮想アドレス空間3
物理メモリ
共有ライブラリとプログラム2次記憶(ディスク等)
仮想アドレス空間0
仮想アドレス空間1
仮想アドレス空間2
仮想アドレス空間3
物理メモリ
共有ライブラリとプログラム2次記憶(ディスク等)
仮想アドレス空間0
仮想アドレス空間1
仮想アドレス空間2
仮想アドレス空間3
物理メモリ
共有ライブラリとプログラム2次記憶(ディスク等)
仮想アドレス空間0
仮想アドレス空間1
仮想アドレス空間2
仮想アドレス空間3
物理メモリ
物理的コピーの共有に必要なリ
ンカのサポート




ROとしてマップされるファイルに実行コード
の全てを埋め込む
COWとしてマップされる領域にデータをま
とめる
各セクションがアドレス空間と物理的配置
においてページ境界となるようにする
複数の異なるプログラムが共有ライブラリ
を各アドレス空間にマップできるようにする
位置独立コード



共有ライブラリを異なるアドレス空間内で
共有する仕掛け
PIC(Position Independent Code)という
メモリ内のどこにロードされても動作する
コード
昔のCPUを使ってみる
The Computer History Simulation Project

http://simh.trailing-edge.com
オブジェクトファイル
オブジェクトファイルとは

一般に以下の5種類の情報を含むファイル





ヘッダ情報:コードサイズ、ソースファイル名等
ファイルに関する全体的な情報
オブジェクトコード:バイナリ命令とデータ
再配置情報:リンカがオブジェクトコードのアド
レスを変更した時に調整が必要なオブジェクト
コード内の位置リスト
シンボル:参照情報
デバッグ情報:デバッガが利用する情報
オブジェクト形式の設計

オブジェクトの機能



リンク可能
実行可能
ロード可能
MS-DOS.COMファイル


バイナリコード以外の情報を一切持たない
実行方法



オフセット0x100から始まる未使用メモリに
ロード
SPレジスタがセグメントの終端を差すように
セット
プログラムの先頭にジャンプ
UNIX a.out ファイル


最も単純なa.outファイル
a.out ヘッダ








a_magic:マジックナンバ
a_text:テキストセグメントサイズ
a_data:初期化データのサイズ
a_bss:未初期化データのサイズ
a_syms:シンボルテーブルのサイズ
a_entry:エントリポイント
a_trsize:テキスト再配置情報のサイズ
a_drsize:データ再配置情報のサイズ
a.outヘッダ
テキストセク
ション
データセクショ
ン
その他のセク
ション
UNIX a.out ファイル

OSのロードおよび起動手順






a.outヘッダの読み出し
共有可能なコードセグメントの調査
データとbssを合わせて格納可能なデータセグメントを
作成してプロセスにマップし、ファイルからロード。bss
は0で初期化
スタックを作成してマップ
引数をスタックに積む
レジスタを設定し、エントリポイントにジャンプ
bssに配置される変数
•初期値を持たない大域変数
•初期値が0の大域変数
•初期値を持たない静的局所変数
•初期値が0の静的局所変数
UNIX a.out ファイル
プロセス
a.outファイル
a.outヘッダ
テキストセク
ション
データセクショ
ン
テキストサイズ
テキストセグメ
ント
データサイズ
データ
ヘッダから得た
bssサイズ
bss
ヒープ
スタック
ページング対応 a.out ファイル

仮想メモリへの対応による効率化



テキストセグメントおよびデータセグメント毎に仮想メモ
リを割り当てる
仮想メモリ用の新しいディスク領域はプログラムが書き
込みを行ったページに対してのみ割り当てられる
仮想メモリシステムはファイル全体ではなく、プログラ
ムが実際に使っているページのみをロードする
ページング対応 a.out ファイル
ページングa.outファイル(ZMAGIC)
ヘッダページ
テキストペー
ジ
データページ
読み出し専用として
マップ
書き込み時コピー
としてマップ
プロセス
アドレス0
テキストセグメ
ント
データ
bss
ヒープ
•a.outヘッダは32バイトにも関わらず4K
バイトのディスク容量を消費
•テキストとデータの隙間も平均2Kバイト
消費
スタック
ページ境界
に整列
ページング対応コンパクト形式




a.outヘッダをテキストセグメントの一部とみなす
テキストセグメント、データセグメントをページ単位
に切り上げる
データセグメントの最後のページはbssデータ用に
0で埋める
bssが埋め合わせより多い場合はヘッダで指定し
て領域確保
ページング対応コンパクト形式
ページングa.outファイル(QMAGIC)
テキストペー
ジ
データページ
読み出し専用として
マップ
プロセス
テキストセグメ アドレス0
ント
データ
書き込み時コピー
としてマップ
bss
ヒープ
スタック
ページ境界
に整列
MS-DOS EXEファイル

同じ論理アドレスにロード可能なようにアド
レス空間を割りつける


a.outが適しているが、多くのシステムにとって
都合が良い方式であるわけではない
常に同じアドレスにプログラムをロードでき
ない場合

再配置エントリ(フィックスアップ)を実行可能
ファイルに格納する
MS-DOS EXEファイルヘッダ
char signature[2]=“MZ”; //マジックナンバ
short lastsize; //最後のブロックの使用バイト数
short nblocks; //512バイトブロックの個数
short nreloc; //再配置エントリの個数
short hdrsize;//16バイトパラグラフ単位のファイルヘッダのサイズ
short minalloc; //割り当てる追加メモリの最小量
short maxalloc; //割り当てる追加メモリの最大量
void far *sp;//初期スタックポインタ
short checksum;//ファイルの合計値の1の補数
void far *ip;//初期命令ポインタ
short relocpos;//再配置フィックスアップテーブルの位置
short noverlay;//オーバレイ番号(プログラムの場合は0)
char extra[];//オーバレイなどのための追加項目
void far *relocs[];//relocpos から始まる再配置エントリ
MS-DOS EXEファイル起動手順




ヘッダを読み出しマジックナンバをチェック
必要なメモリ量をチェック(minallocおよび
maxallocフィールド)
PSP(プログラム先頭にある制御領域)を作
成
PSPの直後にプログラムをロード。nblocks
フィールドとlastsizeフィールドでコードの長
さを決定。
MS-DOS EXEファイル起動手順


relocposからnreloc個のフィックスアップを
読み出す。アドレスを計算し、再配置。
スタックポインタをspに設定してから、再配
置したipにジャンプしてプログラムを起動。
シンボルと再配置

ここまでで説明したオブジェクト形式


より一般的なオブジェクトファイル


ロード可能:メモリにロードしてそのまま実行で
きる
ロード可能ではなく、コンパイラやアセンブラか
らリンカに渡される中間ファイル。リンク可能
ファイル。
オブジェクトファイルの具体例


再配置可能なa.out
ELF
再配置可能なa.out
a.outヘッダ
テキストセクション
データセクション
テキスト再配置情報
データ再配置情報
シンボルテーブル
文字列テーブル
UNIX a.out ファイル


最も単純なa.outファイル
a.out ヘッダ








a_magic:マジックナンバ
a_text:テキストセグメントサイズ
a_data:初期化データのサイズ
a_bss:未初期化データのサイズ
a_syms:シンボルテーブルのサイズ
a_entry:エントリポイント
a_trsize:テキスト再配置情報のサイズ
a_drsize:データ再配置情報のサイズ
a.outヘッダ
テキストセク
ション
データセクショ
ン
その他のセク
ション
リンカが使う
再配置可能なa.out

再配置エントリ

コード内の修正が必要な箇所をマーク


コードのセクションを別のベースアドレスに再配置
する場合
未定義シンボルへの参照をマーク

シンボルの定義が最終的に決定したときに修正す
べき箇所を保存
再配置可能なa.out

シンボルと文字列




シンボルは右に示す12バ
イト
シンボル名の文字列は文
字列テーブルに置く
タイプの最下位ビットが1な
らば外部シンボル(他のモ
ジュールから見えるシンボ
ル)
タイプのほかのビットはシ
ンボルタイプを表現
4バイトの名前オフセット
1バイ
トのタ
イプ
1バイ
トの
予備
2倍とのデ
バッガ用情
報
4バイトの値
再配置可能なa.out

シンボルタイプ



テキストデータ、bss:このモジュール内で定
義されるシンボル。値はシンボルに対応する
モジュール内の再配置可能アドレス。
abs:再配置されない絶対値シンボル。
未定義:このモジュールで定義されないシン
ボル。外部参照ビットはオンになる。
再配置可能なa.out

まとめ



形式が単純でページング機構を持つ比較的
単純なシステムには適している
動的リンクのサポートが困難
C++をサポートしない

初期化子(initializer)と終了子(finalizer)が必要
だから
ELF(Executable and Linkable Format)

ELFファイルの種類

再配置可能


実行可能


コンパイラやアセンブラが作成。リンカによる処理
が必要。
再配置がすべて完了。共有ライブラリ以外の全て
のシンボルが解決済み。
共有オブジェクト

リンカ用のシンボル情報および実行時にそのまま
使われるコードの両方を格納する。
ELFファイル形式
実行可能セグメント
リンク可能セクション
ELFヘッダ
プログラムヘッ
ダテーブル
セクションを記述する
セクションヘッダ
テーブル
セグメントを記述する
ELFヘッダ


ELFファイルの先頭に必ず存在し、ELFファ
イルであることを表す。
readelf –h で見れる。
ELFヘッダの出力例
%readelf -h /bin/ls
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class:
ELF32
Data:
2's complement, little endian
Version:
1 (current)
OS/ABI:
UNIX - System V
ABI Version:
0
Type:
EXEC (Executable file)
Machine:
Intel 80386
Version:
0x1
Entry point address:
0x8049b40
Start of program headers:
52 (bytes into file)
Start of section headers:
90064 (bytes into file)
Flags:
0x0
Size of this header:
52 (bytes)
Size of program headers:
32 (bytes)
Number of program headers:
8
Size of section headers:
40 (bytes)
Number of section headers:
28
Section header string table index: 27
ELFヘッダの構造(32ビット)
/* The ELF file header. This appears at the start of every ELF file. */
#define EI_NIDENT (16)
typedef struct
{
unsigned char e_ident[EI_NIDENT];
/* Magic number and other info */
Elf32_Half e_type;
/* Object file type */
Elf32_Half e_machine;
/* Architecture */
Elf32_Word e_version;
/* Object file version */
Elf32_Addr e_entry;
/* Entry point virtual address */
Elf32_Off
e_phoff;
/* Program header table file offset */
Elf32_Off
e_shoff;
/* Section header table file offset */
Elf32_Word e_flags;
/* Processor-specific flags */
Elf32_Half e_ehsize;
/* ELF header size in bytes */
Elf32_Half e_phentsize;
/* Program header table entry size */
Elf32_Half e_phnum;
/* Program header table entry count */
Elf32_Half e_shentsize;
/* Section header table entry size */
Elf32_Half e_shnum;
/* Section header table entry count */
Elf32_Half e_shstrndx;
/* Section header string table index */
} Elf32_Ehdr;
ELFヘッダの構造(64ビット)
typedef struct
{
unsigned char e_ident[EI_NIDENT];
/* Magic number and other info */
Elf64_Half e_type;
/* Object file type */
Elf64_Half e_machine;
/* Architecture */
Elf64_Word e_version;
/* Object file version */
Elf64_Addr e_entry;
/* Entry point virtual address */
Elf64_Off
e_phoff;
/* Program header table file offset */
Elf64_Off
e_shoff;
/* Section header table file offset */
Elf64_Word e_flags;
/* Processor-specific flags */
Elf64_Half e_ehsize;
/* ELF header size in bytes */
Elf64_Half e_phentsize;
/* Program header table entry size */
Elf64_Half e_phnum;
/* Program header table entry count */
Elf64_Half e_shentsize;
/* Section header table entry size */
Elf64_Half e_shnum;
/* Section header table entry count */
Elf64_Half e_shstrndx;
/* Section header string table index */
} Elf64_Ehdr;
ELFヘッダ解説

E_idnet:マジックナンバー、ビット数、エン
ディアン、ELFバージョン、OS、ABI
(Application Binary Interface)の情報を
ELFバージョン
保持
OS ABI
“ELF”
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
リトルエン
ディアン
ELF32
ELFを意味するマジック
詳細
/* Fields in the e_ident array. The EI_* macros are indices into the
array. The macros under each EI_* macro are the values the byte
may have. */
#define EI_MAG0
#define ELFMAG0
0
0x7f
/* File identification byte 0 index */
/* Magic number byte 0 */
#define EI_MAG1
#define ELFMAG1
1
'E'
/* File identification byte 1 index */
/* Magic number byte 1 */
#define EI_MAG2
#define ELFMAG2
2
'L'
/* File identification byte 2 index */
/* Magic number byte 2 */
#define EI_MAG3
#define ELFMAG3
3
'F'
/* File identification byte 3 index */
/* Magic number byte 3 */
詳細
/* Conglomeration of the identification bytes, for easy testing as a word. */
#define ELFMAG
"\177ELF"
#define SELFMAG
4
#define
#define
#define
#define
#define
EI_CLASS
4
ELFCLASSNONE 0
ELFCLASS32
1
ELFCLASS64
2
ELFCLASSNUM
3
/* File class byte index */
/* Invalid class */
/* 32-bit objects */
/* 64-bit objects */
#define
#define
#define
#define
#define
EI_DATA
5
ELFDATANONE
ELFDATA2LSB
ELFDATA2MSB
ELFDATANUM
/* Data encoding byte index */
/* Invalid data encoding */
/* 2's complement, little endian */
/* 2's complement, big endian */
#define EI_VERSION
0
1
2
3
6
/* File version byte index */
/* Value must be EV_CURRENT */
詳細
#define EI_OSABI
7
/* OS ABI identification */
#define ELFOSABI_NONE
0
/* UNIX System V ABI */
#define ELFOSABI_SYSV
0
/* Alias. */
#define ELFOSABI_HPUX
1
/* HP-UX */
#define ELFOSABI_NETBSD
2
/* NetBSD. */
#define ELFOSABI_LINUX
3
/* Linux. */
#define ELFOSABI_SOLARIS
6
/* Sun Solaris. */
#define ELFOSABI_AIX
7
/* IBM AIX. */
#define ELFOSABI_IRIX
8
/* SGI Irix. */
#define ELFOSABI_FREEBSD
9
/* FreeBSD. */
#define ELFOSABI_TRU64
10
/* Compaq TRU64 UNIX. */
#define ELFOSABI_MODESTO
11
/* Novell Modesto. */
#define ELFOSABI_OPENBSD
12
/* OpenBSD. */
#define ELFOSABI_ARM
97
/* ARM */
#define ELFOSABI_STANDALONE
255
/* Standalone (embedded) application */
#define EI_ABIVERSION 8
#define EI_PAD
9
/* ABI version */
/* Byte index of padding bytes */
ELFヘッダ解説

e_type:オブジェクトファイルのタイプを指
定
/* Legal values for e_type (object file type). */
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
ET_NONE
ET_REL
ET_EXEC
ET_DYN
ET_CORE
ET_NUM
ET_LOOS
ET_HIOS
ET_LOPROC
ET_HIPROC
1
2
3
4
5
0xfe00
0xfeff
0xff00
0xffff
0
/*
/*
/*
/*
/*
/*
/*
/*
/*
/* No file type */
Relocatable file */
Executable file */
Shared object file */
Core file */
Number of defined types */
OS-specific range start */
OS-specific range end */
Processor-specific range start */
Processor-specific range end */
ELFヘッダ解説

e_machine:アーキテクチャタイプ
* Legal values for e_machine (architecture). */
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
EM_NONE
EM_M32
EM_SPARC
EM_386
EM_68K
EM_88K
EM_860
EM_MIPS
EM_S370
EM_MIPS_RS3_LE
#define
#define
#define
#define
#define
#define
#define
EM_PARISC
EM_VPP500
EM_SPARC32PLUS
EM_960
EM_PPC
EM_PPC64
EM_S390
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
EM_V800
EM_FR20
EM_RH32
EM_RCE
EM_ARM
EM_FAKE_ALPHA
EM_SH
EM_SPARCV9
EM_TRICORE
EM_ARC
EM_H8_300
2
10
15
17
18
21
41
42
43
44
46
0
1
3
4
5
7
8
9
19
20
22
36
37
38
39
40
45
/* No machine */
/* AT&T WE 32100 */
/* SUN SPARC */
/* Intel 80386 */
/* Motorola m68k family */
/* Motorola m88k family */
/* Intel 80860 */
/* MIPS R3000 big-endian */
/* IBM System/370 */
/* MIPS R3000 little-endian */
/* HPPA */
/* Fujitsu VPP500 */
/* Sun's "v8plus" */
/* Intel 80960 */
/* PowerPC */
/* PowerPC 64-bit */
/* IBM S390 */
/*
/*
/*
/*
/*
/* NEC V800 series */
/* Fujitsu FR20 */
/* TRW RH-32 */
/* Motorola RCE */
/* ARM */
Digital Alpha */
Hitachi SH */
SPARC v9 64-bit */
Siemens Tricore */
/* Argonaut RISC Core */
Hitachi H8/300 */
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
EM_H8_300H
EM_H8S
EM_H8_500
EM_IA_64 50
EM_MIPS_X
EM_COLDFIRE
EM_68HC12
EM_MMA
EM_PCP
EM_NCPU
EM_NDR1
EM_STARCORE
EM_ME16
EM_ST100 60
EM_TINYJ 61
EM_X86_6462
EM_PDSP
47
48
49
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
EM_FX66
EM_ST9PLUS
EM_ST7
EM_68HC16
EM_68HC11
EM_68HC08
EM_68HC05
EM_SVX
EM_ST19
EM_VAX
EM_CRIS
EM_JAVELIN
EM_FIREPATH
EM_ZSP
EM_MMIX
EM_HUANY 81
EM_PRISM 82
EM_AVR
EM_FR30
EM_D10V
EM_D30V
EM_V850
EM_M32R
EM_MN10300
EM_MN10200
EM_PJ
EM_OPENRISC
EM_ARC_A5
EM_XTENSA
EM_NUM
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
51
52
53
54
55
56
57
58
59
63
83
84
85
86
87
88
89
90
91
92
93
94
95
/* Intel Merced */
/* Stanford MIPS-X */
/* Motorola Coldfire */
/* Motorola M68HC12 */
/* Fujitsu MMA Multimedia Accelerator*/
/* Siemens PCP */
/* Sony nCPU embeeded RISC */
/* Denso NDR1 microprocessor */
/* Motorola Start*Core processor */
/* Toyota ME16 processor */
/* STMicroelectronic ST100 processor */
/* Advanced Logic Corp. Tinyj emb.fam*/
/* AMD x86-64 architecture */
/* Sony DSP Processor */
/* Siemens FX66 microcontroller */
/* STMicroelectronics ST9+ 8/16 mc */
/* STmicroelectronics ST7 8 bit mc */
/* Motorola MC68HC16 microcontroller */
/* Motorola MC68HC11 microcontroller */
/* Motorola MC68HC08 microcontroller */
/* Motorola MC68HC05 microcontroller */
/* Silicon Graphics SVx */
/* STMicroelectronics ST19 8 bit mc */
/* Digital VAX */
/* Axis Communications 32-bit embedded processor */
/* Infineon Technologies 32-bit embedded processor */
/* Element 14 64-bit DSP Processor */
/* LSI Logic 16-bit DSP Processor */
/* Donald Knuth's educational 64-bit processor */
/* Harvard University machine-independent object files */
/* SiTera Prism */
/* Atmel AVR 8-bit microcontroller */
/* Fujitsu FR30 */
/* Mitsubishi D10V */
/* Mitsubishi D30V */
/* NEC v850 */
/* Mitsubishi M32R */
/* Matsushita MN10300 */
/* Matsushita MN10200 */
/* picoJava */
/* OpenRISC 32-bit embedded processor */
/* ARC Cores Tangent-A5 */
/* Tensilica Xtensa Architecture */
/* If it is necessary to assign new unofficial EM_* values, please
pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the
chances of collision with official or non-GNU unofficial values. */
#define EM_ALPHA 0x9026
/* Hitachi H8/300H */
/* Hitachi H8S */
/* Hitachi H8/500 */
ELFヘッダ解説






e_version:ELFバージョンを示す
e_entry:実行開始仮想アドレス
e_ehsize:ELFヘッダのサイズ
e_phoff,e_phentsize,e_phnum:プログラ
ムヘッダテーブル情報(位置、サイズ、数)
e_shoff,e_shentsize,e_shnum:セクション
ヘッダテーブル情報(位置、サイズ、数)
e_shstrndx:セクション名の文字列テーブ
ルを持つセクションヘッダインデックス
プログラムヘッダ
%readelf -l /bin/ls
Elf file type is EXEC (Executable file)
Entry point 0x8049b40
There are 8 program headers, starting at offset 52
Program Headers:
Type
Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR
0x000034 0x08048034 0x08048034 0x00100 0x00100 R E 0x4
INTERP
0x000134 0x08048134 0x08048134 0x00013 0x00013 R 0x1
[Requesting program interpreter: /lib/ld-linux.so.2]
LOAD
0x000000 0x08048000 0x08048000 0x15b20 0x15b20 R E 0x1000
LOAD
0x015b20 0x0805eb20 0x0805eb20 0x003cc 0x01020 RW 0x1000
DYNAMIC
0x015b34 0x0805eb34 0x0805eb34 0x000e8 0x000e8 RW 0x4
NOTE
0x000148 0x08048148 0x08048148 0x00044 0x00044 R 0x4
GNU_EH_FRAME 0x015a64 0x0805da64 0x0805da64 0x0002c 0x0002c R 0x4
GNU_STACK
0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4
Section to Segment mapping:
Segment Sections...
00
01
.interp
02
.interp .note.ABI-tag .note.gnu.build-id .hash .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn
.rel.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
03
.ctors .dtors .jcr .dynamic .got .got.plt .data .bss
04
.dynamic
05
.note.ABI-tag .note.gnu.build-id
06
.eh_frame_hdr
07
プログラムヘッダ
/* Program segment header. */
typedef struct
{
Elf32_Word
Elf32_Off
Elf32_Addr
Elf32_Addr
Elf32_Word
Elf32_Word
Elf32_Word
Elf32_Word
} Elf32_Phdr;
p_type;
p_offset;
p_vaddr;
p_paddr;
p_filesz;
p_memsz;
p_flags;
p_align;
/*
/*
/*
/*
/*
/* Segment type */
Segment file offset */
Segment virtual address */
/* Segment physical address */
Segment size in file */
/* Segment size in memory */
Segment flags */
Segment alignment */
セグメントタイプ






PT_LOAD:ロードされるプログラムセグメント
PT_DYNAMIC:動的リンク情報
PT_INTERP:プログラムインタープリタ
PT_NOTE:補助的な情報
PT_PHDR:プログラムヘッダテーブル自体
PT_TLS:スレッドローカルストレージ
セグメントタイプ
/* Legal values for p_type (segment type). */
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
PT_NULL 0/* Program header table entry unused */
PT_LOAD
1/* Loadable program segment */
PT_DYNAMIC
2/* Dynamic linking information */
PT_INTERP 3/* Program interpreter */
PT_NOTE
4/* Auxiliary information */
PT_SHLIB 5/* Reserved */
PT_PHDR
6/* Entry for header table itself */
PT_TLS
7/* Thread-local storage segment */
PT_NUM
8/* Number of defined types */
PT_LOOS
0x60000000
/* Start of OS-specific */
PT_GNU_EH_FRAME 0x6474e550
/* GCC .eh_frame_hdr segment */
PT_GNU_STACK
0x6474e551
/* Indicates stack executability */
PT_GNU_RELRO
0x6474e552
/* Read-only after relocation */
PT_LOSUNW
0x6ffffffa
PT_SUNWBSS
0x6ffffffa /* Sun Specific segment */
PT_SUNWSTACK
0x6ffffffb /* Stack segment */
PT_HISUNW
0x6fffffff
PT_HIOS
0x6fffffff /* End of OS-specific */
PT_LOPROC
0x70000000
/* Start of processor-specific */
PT_HIPROC0x7fffffff /* End of processor-specific */
セクションヘッダ
%readelf -l /bin/ls
There are 28 section headers, starting at offset 0x15fd0:
Section Headers:
[Nr] Name
Type
Addr
Off Size ES Flg Lk Inf Al
[ 0]
NULL
00000000 000000 000000 00
0 0 0
[ 1] .interp
PROGBITS
08048134 000134 000013 00 A 0 0 1
[ 2] .note.ABI-tag
NOTE
08048148 000148 000020 00 A 0 0 4
[ 3] .note.gnu.build-i NOTE
08048168 000168 000024 00 A 0 0 4
[ 4] .hash
HASH
0804818c 00018c 000338 04 A 6 0 4
[ 5] .gnu.hash
GNU_HASH
080484c4 0004c4 00005c 04 A 6 0 4
[ 6] .dynsym
DYNSYM
08048520 000520 0006b0 10 A 7 1 4
[ 7] .dynstr
STRTAB
08048bd0 000bd0 00048c 00 A 0 0 1
[ 8] .gnu.version
VERSYM
0804905c 00105c 0000d6 02 A 6 0 2
[ 9] .gnu.version_r VERNEED
08049134 001134 0000b0 00 A 7 3 4
[10] .rel.dyn
REL
080491e4 0011e4 000028 08 A 6 0 4
[11] .rel.plt
REL
0804920c 00120c 0002f8 08 A 6 13 4
[12] .init
PROGBITS
08049504 001504 000030 00 AX 0 0 4
[13] .plt
PROGBITS
08049534 001534 000600 04 AX 0 0 4
[14] .text
PROGBITS
08049b40 001b40 00ffcc 00 AX 0 0 16
[15] .fini
PROGBITS
08059b0c 011b0c 00001c 00 AX 0 0 4
[16] .rodata
PROGBITS
08059b40 011b40 003f23 00 A 0 0 32
[17] .eh_frame_hdr
PROGBITS
0805da64 015a64 00002c 00 A 0 0 4
[18] .eh_frame
PROGBITS
0805da90 015a90 000090 00 A 0 0 4
[19] .ctors
PROGBITS
0805eb20 015b20 000008 00 WA 0 0 4
[20] .dtors
PROGBITS
0805eb28 015b28 000008 00 WA 0 0 4
[21] .jcr
PROGBITS
0805eb30 015b30 000004 00 WA 0 0 4
[22] .dynamic
DYNAMIC
0805eb34 015b34 0000e8 08 WA 7 0 4
[23] .got
PROGBITS
0805ec1c 015c1c 000008 04 WA 0 0 4
[24] .got.plt
PROGBITS
0805ec24 015c24 000188 04 WA 0 0 4
[25] .data
PROGBITS
0805edc0 015dc0 00012c 00 WA 0 0 32
[26] .bss
NOBITS
0805ef00 015eec 000c40 00 WA 0 0 32
[27] .shstrtab
STRTAB
00000000 015eec 0000e3 00
0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
セクションヘッダ
/* Section header. */
typedef struct
{
Elf32_Word
Elf32_Word
Elf32_Word
Elf32_Addr
Elf32_Off
Elf32_Word
Elf32_Word
Elf32_Word
Elf32_Word
Elf32_Word
} Elf32_Shdr;
sh_name;
sh_type;
sh_flags;
sh_addr;
sh_offset;
sh_size;
sh_link;
sh_info;
sh_addralign;
sh_entsize;
/*
/*
/*
/*
/*
/*
/* Section name (string tbl index) */
Section type */
Section flags */
Section virtual addr at execution */
/* Section file offset */
Section size in bytes */
Link to another section */
Additional section information */
/* Section alignment */
/* Entry size if section holds table */
セクションタイプ






SHT_PROGBITS:プログラムデータ
SHT_SYMTAB:シンボルテーブル
SHT_STRTAB:ストリングテーブル
SHT_RELA:リロケーションエントリ
SHT_HASH:シンボルハッシュテーブル
SHT_DYNAMIC:動的リンク情報
セクションタイプ
/* Legal values for sh_type (section type). */
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
SHT_NULL
0
SHT_PROGBITS
1
SHT_SYMTAB
2
SHT_STRTAB
3
SHT_RELA
4
SHT_HASH
5
SHT_DYNAMIC
6
SHT_NOTE
7
SHT_NOBITS
8
SHT_REL
SHT_SHLIB
10
SHT_DYNSYM
11
SHT_INIT_ARRAY
14
SHT_FINI_ARRAY
15
SHT_PREINIT_ARRAY 16
SHT_GROUP
17
SHT_SYMTAB_SHNDX 18
SHT_NUM
SHT_LOOS
0x60000000
SHT_GNU_ATTRIBUTES 0x6ffffff5
SHT_GNU_HASH
0x6ffffff6
SHT_GNU_LIBLIST
0x6ffffff7
SHT_CHECKSUM
0x6ffffff8
SHT_LOSUNW
0x6ffffffa
SHT_SUNW_move
0x6ffffffa
SHT_SUNW_COMDAT 0x6ffffffb
SHT_SUNW_syminfo 0x6ffffffc
SHT_GNU_verdef
0x6ffffffd
SHT_GNU_verneed
0x6ffffffe
SHT_GNU_versym
0x6fffffff
SHT_HISUNW
0x6fffffff
SHT_HIOS
0x6fffffff
SHT_LOPROC
0x70000000
SHT_HIPROC
0x7fffffff
SHT_LOUSER
0x80000000
SHT_HIUSER
0x8fffffff
/*
/*
/*
/*
/*
/*
/*
/*
/*
Section header table entry unused */
Program data */
Symbol table */
String table */
Relocation entries with addends */
Symbol hash table */
Dynamic linking information */
Notes */
Program space with no data (bss) */
9
/* Relocation entries, no addends */
/* Reserved */
/* Dynamic linker symbol table */
/* Array of constructors */
/* Array of destructors */
/* Array of pre-constructors */
/* Section group */
/* Extended section indeces */
19
/* Number of defined types. */
/* Start OS-specific. */
/* Object attributes. */
/* GNU-style hash table. */
/* Prelink library list */
/* Checksum for DSO content. */
/* Sun-specific low bound. */
/*
/*
/*
/*
/*
/*
/*
/*
/*
Version definition section. */
Version needs section. */
Version symbol table. */
Sun-specific high bound. */
End OS-specific type */
Start of processor-specific */
End of processor-specific */
Start of application-specific */
End of application-specific */
シンボルテーブル
/* Symbol table entry. */
typedef struct
{
Elf32_Word
Elf32_Addr
Elf32_Word
unsigned char
unsigned char
Elf32_Section
} Elf32_Sym;
st_name;
st_value;
st_size;
st_info;
st_other;
st_shndx;
typedef struct
{
Elf64_Word
st_name;
unsigned char
st_info;
unsigned char st_other;
Elf64_Section
st_shndx;
Elf64_Addr
st_value;
Elf64_Xword
st_size;
} Elf64_Sym;
/*
/*
/*
/*
/*
/*
Symbol
Symbol
Symbol
Symbol
Symbol
Section
name (string tbl index) */
value */
size */
type and binding */
visibility */
index */
/*
/*
/*
/*
/*
/*
Symbol
Symbol
Symbol
Section
Symbol
Symbol
name (string tbl index) */
type and binding */
visibility */
index */
value */
size */
シンボルタイプ
/* Legal values for ST_TYPE subfield of st_info (symbol type). */
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
STT_NOTYPE
STT_OBJECT
STT_FUNC 2
STT_SECTION
STT_FILE 4
STT_COMMON
STT_TLS
STT_NUM
STT_LOOS 10
STT_HIOS 12
STT_LOPROC
STT_HIPROC
0
1
3
5
6
7
13
15
/*
/*
/*
/*
/* Symbol type is unspecified */
/* Symbol is a data object */
Symbol is a code object */
/* Symbol associated with a section */
Symbol's name is file name */
/* Symbol is a common data object */
/* Symbol is thread-local data object*/
/* Number of defined types. */
Start of OS-specific */
End of OS-specific */
/* Start of processor-specific */
/* End of processor-specific */
再配置情報

SHT_RELA
/* Relocation table entry with addend (in section of type SHT_RELA). */
typedef struct
{
Elf32_Addr
Elf32_Word
Elf32_Sword
} Elf32_Rela;
typedef struct
{
Elf64_Addr
Elf64_Xword
Elf64_Sxword
} Elf64_Rela;
r_offset;
r_info;
r_addend;
/* Address */
/* Relocation type and symbol index */
/* Addend */
r_offset;
r_info;
r_addend;
/* Address */
/* Relocation type and symbol index */
/* Addend */
再配置情報

SHT_REL
/* Relocation table entry without addend (in section of type SHT_REL). */
typedef struct
{
Elf32_Addr
Elf32_Word
} Elf32_Rel;
r_offset;
r_info;
/* Address */
/* Relocation type and symbol index */
/* I have seen two different definitions of the Elf64_Rel and
Elf64_Rela structures, so we'll leave them out until Novell (or
whoever) gets their act together. */
/* The following, at least, is used on Sparc v9, MIPS, and Alpha. */
typedef struct
{
Elf64_Addr
Elf64_Xword
} Elf64_Rel;
r_offset;
r_info;
/* Address */
/* Relocation type and symbol index */
objdump

とりあえずダンプしてみる


セクションヘッダだけダンプ


objdump –h /bin/ls
特定のセクションだけダンプ


objdump –s /bin/ls とか
objdump –s –j .interp /bin/ls
逆アセンブル

objdump –d /bin/ls
プログラミングにおける注意
CとC++のプログラムをリンク

C/C++とシンボル名


gcc –c func.c
g++ -c func.c
func.o を nm で比較する
C++には関数の所属する名前空間の情報や
関数の引数の型情報がシンボルに含まれる
C++からCの関数を呼び出す

ビルドして動かす




gcc –c func.c
gcc –c call.cpp
gcc –o hoge func.o call.o
extern “C” の影響

ありとなしを nm で比較
extern “C”の注意点

引数の型がチェックされない
extern “C” void func(int);
Int main(){
func(0);
return 0;
}
リンクに成功してしまう
C++であれば”リンク成功->間違った型で関数は呼ばれない”と
考えたいが、extern “C” を使っている部分はそうではなく、C相当
にまで安全性が低下する。
一般的な利用方法

以下のようなヘッダを用意する。
#ifdef __cplusplus
extern “C”{
#endif
void func(const char *);
#ifdef __cplusplus
}
#end if
CからC++の関数を呼ぶ



g++ -c func.cpp
gcc –c call.c
g++ -o call_c call.o func.o
•C++の関数は例外をCの関数側に漏らし
てはならない
•関数ポインタを扱うCの関数に注意
リンク時のシンボル衝突

同名シンボルの衝突

a.c、b.cに同名の関数が定義されている場合
gcc
gcc
gcc
gcc
–c a.c
–c b.c
–c main.c
–o main a.o b.o main.o
リンカエラー
リンク時のシンボル衝突

ライブラリを作ってリンクする場合
gcc –c a.c
gcc –c b.c
ar cr libhoge.a a.o b.o
gcc –c main.c
gcc –o main libhoge.a
先に見つかった方が使われる
(順序を入れ替えると逆になる)
リンク時のシンボル衝突

共有ライブラリを作ってリンクする場合
gcc
gcc
gcc
gcc
–fPIC –shared –o a.so a.c
–fPIC –shared –o b.so b.c
–fPIC –shared –o main.so main.c
–o main_shared ./a.so ./b.so ./main.so
先に見つかった方が使われる
(順序を入れ替えると逆になる)
リンク時のシンボル衝突

共有ライブラリを作ってリンクする場合
gcc
gcc
gcc
gcc
–fPIC –shared –o liba.so a.c
–fPIC –shared –o libb.so b.c
–c main.c
–o main_shared –L. –la -lb
先に見つかった方が使われる
(-la –lb の順序に依存)
LD_PRELOADで制御可能
weakシンボル

ELFではweak参照のほかにweak定義とい
うもう1つのweakシンボルを追加している。
Weak定義は、通常の定義が存在しない場
合に大域シンボルを定義する。通常の定
義が存在される場合はweak定義は無視さ
れる。
weakシンボル

ふつうにコンパイル


g++ main.cpp
同名の実装が他にある



g++ -c a.cpp
g++ -c main.cpp
g++ -o main main.o a.o
実行される関数が異なる
原因はweakシンボル(nmで確認)
weak定義

g++がインライン関数をweak定義とみな
す
回避するにはmain.cppのclass定義を
namespace{}で囲みリンケージリークを防ぐ
おわり
Download