モジュール
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