ELF格式的导入符号的源共享库的名称

时间:2011-07-12 17:29:15

标签: import symbols elf portable-executable

我正致力于分析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可执行文件中找出符号共享库的名称?

感谢您的任何建议。

2 个答案:

答案 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
    }
    }
}

那么你怎么看?这是正确的吗?