先端ソフトウェア工学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{}で囲みリンケージリークを防ぐ おわり