Вы можете следовать рецепту, описанному в этой статье , просто если вы обращаетесь к символам в нашем собственном адресном пространстве / из библиотеки, загруженной вами через dlopen()
, это намного проще:
- "struct link_map *", которую вы получаете
reinterpret_cast<struct link_map*>(dlopen(...));
- поэтому нет необходимости анализировать "ваш собственный ELF". См. исходный код для __dlopen()
.
- Вам не нужно использовать
ptrace()
для чтения из собственного адресного пространства - просто приведите указатели напрямую.
Я проиллюстрирую 2-й для поиска адреса таблицы символов:
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 делают это ...), просто это больше не делает код легким для чтения. Опять же, я оставляю это в качестве упражнения для читателя.