モジュール
Rev.1を表示中。最新版はこちら。
モジュールのロード
sys_init_module()
load_module()
フォーマット(ELFか?等)をチェック
module_alloc() - 単なるvmalloc()
セクションヘッダテーブル内の全エントリに対して以下を実行
SHF_ALLOCが設定されているセクションを移動
simplify_symbols()
シンボルテーブル内の全エントリに対して以下を実行
st_shndx: SHN_UNDEFならresolve_symbol()
/* Now do relocations. */
セクションヘッダテーブルを全てチェック。
セクションのタイプが
SHT_REL ならapply_relocate()
SHT_RELAならapply_relocate_add()
mod->init() - モジュールの初期化ルーチン呼び出し
resolve_symbol() - シンボルのアドレス解決
__find_symbol() - シンボルの検索
カーネル内のシンボルテーブルから検索
__start___ksymtab
__start___ksymtab_gpl
組み込み済のモジュール内のシンボルテーブルから検索
mod->syms[i]
mod->gpl_syms[i]
apply_relocate() - 再配置(アドレスの書き換えを行う)
再配置テーブル内の全エントリに対して以下を実行
rel[i].r_offsetが指しているアドレスにシンボルテーブル
から引っ張って来たアドレスを設定する。
*location += sym->st_value;
(シンボルのアドレス解決(sym->st_value)の設定は
simplify_symbols()で行われる。)
----------------------------------------------------
ELFファイルメモ
+--------------------------+
| ELFヘッダ |
| e_type | ET_REL,ET_EXEC,ET_DYN,ET_CORE
| |
| e_phoff |プログラムヘッダテーブルのファイルオフセット
| e_shoff |セクションヘッダテーブルのファイルオフセット
| |
| e_shstrndx |セクション名文字列テーブルに関連付けられたエントリ
| |のセクションヘッダテーブルインデックスを保持する。
+--------------------------+
+--------------------------+
| プログラムヘッダテーブル | セグメントを表す
| | セグメント には 1 つ以上の セクション が含まれる
| |
| p_vaddr | セグメント開始の仮想アドレス
| |
| |
+--------------------------+
| |
:
+--------------------------+
| セクションヘッダテーブル | ファイル内の各セクションの情報を保存
| |
| sh_name | セクション名(セクションヘッダ文字列テーブル
| | セクションのインデクス)
| sh_type | SHT_SYMTAB, SHT_REL, SHT_STRTA...
+--------------------------+
| |
:
+--------------------------+
| シンボルテーブル | シンボル情報が列挙される
| |
| | 00000000 l df *ABS* 00000000 ifload.c
| | 00000000 l d .text 00000000
| | 00000000 l d .data 00000000
| | 00000000 l d .bss 00000000
| | 00000000 l d .rodata.str1.4 00000000
| | 00000348 l F .text 00000197 get_iflist
| | 000004e0 l F .text 00000134 update_stats
| | 00000000 *UND* 00000000 stderr
| | 00000000 *UND* 00000000 fwrite
| | :
+--------------------------+ *UND*が未解決シンボル
+--------------------------+
| 文字列テーブル |
+--------------------------+
| 再配置テーブル | 再配置必要な箇所が列挙される
| |
| | OFFSET TYPE VALUE
| | 00000008 R_386_32 stderr
| | 00000011 R_386_32 .rodata.str1.1
| | 00000016 R_386_PC32 fwrite
| | 0000001c R_386_32 stderr
| | :
+--------------------------+
OFFSET 再配置動作が適用される位置(解決後のアドレスが書き込まれる場所)
<--逆アセンブルしてみるとここのアドレスにはダミーのアドレス値
が入っている。以下参照
TYPE R_386_32,R_386_PC32
VALUE 参照先シンボル(実際にはシンボルテーブル内でのインデックス値)
00000000 <usage>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 ec 08 sub $0x8,%esp
6: ff 35 00 00 00 00 pushl 0x0 #0x08 stderr
c: 6a 07 push $0x7
e: 6a 01 push $0x1
10: 68 00 00 00 00 push $0x0 #0x11 .rodata.str1.1
15: e8 fc ff ff ff call 16 <usage+0x16> #0x16 fwrite
1a: ff 35 00 00 00 00 pushl 0x0 #0x1c stderr
20: 6a 0e push $0xe
22: 6a 01 push $0x1
