あなたがdlopen()
経由でロードされるライブラリから私たち自身のアドレス空間/内のシンボルにアクセスしている場合は、ちょうどそのin this articleを概説レシピに従うことができますがはるかに簡単です:
- 「構造体link_map *」君
reinterpret_cast<struct link_map*>(dlopen(...));
で取得する - あなた自身のELFを解析する必要はありません。 sourcecode for __dlopen()
を参照してください。
ptrace()
を使用して自分のアドレス空間から読み込む必要はありません。ポインタを直接キャストするだけです。
私は、シンボルテーブルのアドレスを見つけるための第二を説明します:
struct link_map *map = reinterpret_cast<struct link_map*>(dlopen(...));
int nchains = 0;
Elf32_Dyn *dyn = static_cast<Elf32_Dyn*>(map->l_ld);
Elf32_Sym *symtab = NULL;
char *strtab = NULL;
while (dyn->d_tag) {
switch (dyn->d_tag) {
case DT_HASH:
nchains = *static_cast<int*>(dyn->d_un.d_ptr + map->l_addr + 4);
break;
case DT_SYM:
symtab = static_cast<Elf32_Sym*>(dyn->d_un.d_ptr);
break;
case DT_STR:
strtab = static_cast<char*>(dyn->d_un.d_ptr);
break;
default:
break;
}
dyn++;
}
これは私がにリンクされている記事のresolv_tables()
機能のインメモリと同等です。 find_sym_in_tables()
を独自のアドレス空間を介してパターン検索に変換することは、読者の練習として残されています。
これはLinux固有のものです(dlopen()
はstruct link_map*
を返します)。他のシステムでは、この条件が満たされている限り(ELFを使用している限り)、この手法は有効です。
編集:これは32ビットELF用です。 64ビットを使用している場合は、データ型が変更されます(Elf64_Sym
/Elf64_Dyn
と64ビット整数のテーブルサイズが考えられます)。私はこれを抽象化することができると確信しています(glibcのソースはそうです...)、コードを読みやすくすることはできません。再び、私はそれを読者に運動として残す。