我正致力于分析ELF和PE格式(学校/研究项目类型)的目标文件的程序。现在我即将处理可执行文件中的动态导入符号。我想尽可能多地找到关于符号的信息。
在PE格式中,导入存储在.idata
部分中。有几个表有不同的信息,但对我来说有趣的是,找出符号定义的库是没有问题的。总是存在共享库的名称,然后是从中导入的符号的名称/序号。
我想在ELF文件中找到这种信息。所有导入/导出都在.dynsym
部分 - 动态符号表中。导入的那些符号标记为未定义,例如:
00000000 DF *UND* 00000000 GLIBC_2.0 fileno
但是没有信息,这个符号的源文件是什么。所有需要的共享库都列在.dynamic
部分中,例如:
Dynamic Section:
NEEDED libz.so.1
仅符号中有关库的信息是Version String = GLIBC_2.0
。我正在考虑通过这个获取真正的库名,但是当我查看objdump -p
的输出时,我发现GLIBC_2.0
可以与多个库连接:
Version References:
required from libm.so.6:
0x0d696910 0x00 13 GLIBC_2.0
required from libgcc_s.so.1:
0x0b792650 0x00 12 GLIBC_2.0
如果我正确理解ELF动态链接过程,则不可能在ELF可执行文件中找到此信息。从哪里导入的符号在将所有符号表加载到内存后由链接器确定。 但我想在继续之前确定这一点,所以我的问题是:有什么办法可以从ELF可执行文件中找出符号共享库的名称?
感谢您的任何建议。
答案 0 :(得分:0)
几个月前,我正在研究非常类似的东西 - 我能够通过抓取nm和readelf来源回答我的所有问题。 (见http://ftp.gnu.org/gnu/binutils/) 我发现这也很有用 - > http://www.skyfree.org/linux/references/ELF_Format.pdf
答案 1 :(得分:0)
好的,所以通常不可能为每个导入的符号分配库名。但我可能通过符号版本控制找到了解决方案。当然,sybol版本部分不必存在于每个ELF文件中。
struct elf_obj_tdata *pElf = bfdFile->tdata.elf_obj_data;
for (long i = 0; i < dynNumSyms; i++)
{
asymbol *dynSym = dynSymTab[i];
// If there is version information in file.
if (pElf->dynversym_section != 0
&& (pElf->dynverdef_section != 0
|| pElf->dynverref_section != 0))
{
unsigned int vernum;
const char *version_string;
const char *fileName;
vernum = ((elf_symbol_type *) dynSym)->version & VERSYM_VERSION;
if (vernum == 0) // local sym
version_string = "";
else if (vernum == 1) // global sym, defined in this object
version_string = "Base";
else if (vernum <= pElf->cverdefs)
version_string = pElf->verdef[vernum - 1].vd_nodename;
else
{
Elf_Internal_Verneed *t;
version_string = "";
fileName = "";
// Iterate through all Verneed entries - all libraries
for (t = pElf->verref; t != NULL; t = t->vn_nextref)
{
Elf_Internal_Vernaux *a;
// Iterate through all Vernaux entries
for (a = t->vn_auxptr; a != NULL; a = a->vna_nextptr)
{
// Find associated entry
if (a->vna_other == vernum)
{
version_string = a->vna_nodename;
fileName = t->vn_filename;
break;
}
}
}
// here we have got:
// name of symbol = dynSym->name
// version string = version_string
// name of library = fileName
}
}
}
那么你怎么看?这是正确的吗?