はじめに
動的リンクについて簡単にまとめてみました
動的リンクとは
- 動的リンクとは、プログラムの実行に必要なライブラリやモジュールなどを、実行時にリンク(連結)して起動すること。
- 例えばprintfなどを使ったC言語のプログラムを実行するときは、LinuxのGlibc(標準Cライブラリ)などの共有ライブラリが実行時に動的にリンクされる
実行ファイルの中身を見てみた
readelf -a a.out
ELF ヘッダ:
マジック: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
クラス: ELF32
データ: 2 の補数、リトルエンディアン
(中略)
セクションヘッダ:
[番] 名前 タイプ アドレス Off サイズ ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .interp PROGBITS 08048154 000154 000013 00 A 0 0 1
[ 2] .note.ABI-tag NOTE 08048168 000168 000020 00 A 0 0 4
[ 3] .note.gnu.build-i NOTE 08048188 000188 000024 00 A 0 0 4
[ 4] .gnu.hash GNU_HASH 080481ac 0001ac 000020 04 A 5 0 4
[ 5] .dynsym DYNSYM 080481cc 0001cc 000040 10 A 6 1 4
(中略)
プログラムヘッダ:
タイプ オフセット 仮想Addr 物理Addr FileSiz MemSiz Flg Align
PHDR 0x000034 0x08048034 0x08048034 0x00120 0x00120 R E 0x4
INTERP 0x000154 0x08048154 0x08048154 0x00013 0x00013 R 0x1
[要求されるプログラムインタプリタ: /lib/ld-linux.so.2]
LOAD 0x000000 0x08048000 0x08048000 0x00590 0x00590 R E 0x1000
LOAD 0x000f08 0x08049f08 0x08049f08 0x00110 0x00114 RW 0x1000
DYNAMIC 0x000f14 0x08049f14 0x08049f14 0x000e8 0x000e8 RW 0x4
オフセット 0xf14 にある動的セクションは 24 個のエントリから構成されています:
タグ タイプ 名前/値
0x00000001 (NEEDED) 共有ライブラリ: [libc.so.6]
0x0000000c (INIT) 0x8048294
0x0000000d (FINI) 0x8048494
0x00000019 (INIT_ARRAY) 0x8049f08
0x0000001b (INIT_ARRAYSZ) 4 (バイト)
(中略)
再配置セクション '.rel.plt' (オフセット 0x284) は 2 個のエントリから構成されています:
オフセット 情報 型 シンボル値 シンボル名
0804a00c 00000107 R_386_JUMP_SLOT 00000000 __gmon_start__
0804a010 00000207 R_386_JUMP_SLOT 00000000 __libc_start_main
interpセクション
- 動的リンカが指定されている(/lib/ld-linux.so.2)。通称ld.so。リンク時に共有ライブラリなどがある場合、リンカによって書き込まれる。
動的リンクの流れ
- execveされてカーネルがメモリに実行ファイルをロード。カーネルがINTREPセクションを発見するとそのパスに書かれている動的リンカをメモリにロードする。上だと(/lib/ld-linux.so.2)。
- そしてカーネルは処理をこの動的リンカに受け渡して動的リンカが起動
- 動的リンカはカーネルから渡された情報(実行ファイルなど)を元に実行ファイルのDYNAMICセクションを探してDYNAMICセクションのTYPEがNEEDEDの共有ライブラリ(上記のlibc.so.6)をメモリに読み込む。
- 共有ライブラリを検索する場所は環境変数、デフォルト検索パスなど(コマンドラインでコンパイルした時に-Lを指定したパス)
- そして共有ライブラリのDYNAMICセクションにも共有ライブラリがリンクされていたら再帰的にメモリにロードしてすべての共有ライブラリをメモリに配置する
実行ファイルと共有ライブラリ
- 対象:実行ファイル(ELF)
- **カーネル(ローダー)**がメモリに配置する。
- 対象:実行ファイルで使用される共有ライブラリ
- **動的リンカ(ダイナミックリンカローダ)**がメモリに配置する