我编写了一些代码来搜索共享库的ELF标头中的符号。如果我解析存储在我的磁盘上的共享对象文件,代码将起作用。在运行时读取加载共享对象的ELF标题
现在,我想使用此代码来解析加载的共享库的ELF头。作为一个例子,libdl库被映射到当前进程中:
b7735000-b7738000 r-xp 00000000 08:01 315560 /lib/i386-linux-gnu/libdl.so.2
b7738000-b7739000 r--p 00002000 08:01 315560 /lib/i386-linux-gnu/libdl.so.2
b7739000-b773a000 rw-p 00003000 08:01 315560 /lib/i386-linux-gnu/libdl.so.2
地址的(第一个)映射包含ELF头。我试图读取此标题并提取.dynsym部分中的dlopen符号。但是,标题与磁盘上'plain'.so文件的标题略有不同。例如,.shstrtab版本的偏移量为0.因此,无法获取节的名称。
我想问为什么ELF标题在加载库期间发生变化,以及在哪里可以找到“缺失”部分。加载库之后甚至可以解析ELF头文件? 有没有人知道任何文章解释共享库/它的ELF头被映射到进程时的布局?
目前我使用以下函数遍历ELF头。如果libdl_start指向内存映射libdl.so.2文件,代码工作正常。但是,如果它指向由链接器映射的区域,则get_dynstr_section未找到dynstr部分。
int get_libdl_functions()
{
Elf32_Ehdr *ehdr = libdl_start;
Elf32_Shdr *shdr, *shdrs_start = (Elf32_Shdr *)(((char *)ehdr) + ehdr->e_shoff);
Elf32_Sym *symbol, *symbols_start;
char *strtab = get_dynstr_section();
int sec_it = 0, sym_it = 0;
rt_info->dlopen = NULL;
rt_info->dlsym = NULL;
if(strtab == NULL)
return -1;
for(sec_it = 0; sec_it < ehdr->e_shnum; ++sec_it) {
// Iterate over all sections to find .dynsym
shdr = shdrs_start + sec_it;
if(shdr->sh_type == SHT_DYNSYM)
{
// Ok we found the right section
symbols_start = (Elf32_Sym *)(((char *)ehdr) + shdr->sh_offset);
for(sym_it = 0; sym_it < shdr->sh_size/sizeof(Elf32_Sym); ++sym_it) {
symbol = symbols_start + sym_it;
if(ELF32_ST_TYPE(symbol->st_info) != STT_FUNC)
continue;
if(strncmp(strtab + symbol->st_name, DL_OPEN_NAME, sizeof DL_OPEN_NAME) && !rt_info->dlopen) {
//printf("Offset of dlopen: 0x%x\n", symbol->st_value);
dlopen = ((char *)ehdr) + symbol->st_value;
} else if(strncmp(strtab + symbol->st_name, DL_SYM_NAME, sizeof DL_SYM_NAME) && !rt_info->dlsym) {
//printf("Offset of dlsym: 0x%x\n", symbol->st_value);
dlsym = ((char *)ehdr) + symbol->st_value;
}
if(dlopen != 0 && dlsym != 0)
return 0;
}
}
}
return -1;
}
void *get_dynstr_section()
{
Elf32_Ehdr *ehdr = libdl_start;
Elf32_Shdr *shdr, *shdrs_start = (Elf32_Shdr *)(((char *)ehdr) + ehdr->e_shoff);
char *strtab = ((char *)ehdr) + ((shdrs_start + ehdr->e_shstrndx))->sh_offset;
int sec_it = 0;
for(sec_it = 0; sec_it < ehdr->e_shnum; ++sec_it) {
// Iterate over all sections to find .dynstr section
shdr = shdrs_start + sec_it;
if(shdr->sh_type == SHT_STRTAB && strncmp(strtab + shdr->sh_name, DYNSTR_NAME, sizeof DYNSTR_NAME))
return ((char *)ehdr) + shdr->sh_offset;
}
return NULL;
}
我添加了我用来将ELF标题迭代到原始问题的代码。 – PraMiD
@PraMiD据我所知,你的问题是“'get_dynstr_section'找不到dynstr部分”。但是你没有显示它的代码。你如何期待任何人来帮助你?您应该尝试构建一个https://stackoverflow.com/help/mcve。 –
问题中包含'get_dynstr_section'的代码。在'get_libdl_functions'之后# – PraMiD