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

4
我正在开发一个程序,用于分析ELF和PE格式的目标文件(一种学校/研究项目)。目前,我正准备处理可执行文件中的动态导入符号。我希望尽可能多地了解有关符号的信息。
在PE格式中,导入存储在.idata部分中。有几个具有不同信息的表格,但对我来说有趣的是,在哪个库中定义符号并没有问题。总是有共享库的名称,然后是从中导入的符号的名称/序数。
我也想在ELF文件中找到这种信息。所有导入/导出都在.dynsym部分-动态符号表中。那些被导入的符号被标记为未定义,例如:
00000000      DF *UND*  00000000  GLIBC_2.0   fileno

但是没有给出这个符号的源文件信息。所有需要的共享库都在 .dynamic 部分中列出,例如:

Dynamic Section:
  NEEDED               libz.so.1

符号库中唯一有关信息是版本字符串 = 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

好的,所以通常来说,对于每个导入的符号分配库名称是不可能的。但我可能已经通过符号版本控制找到了解决方案。当然,符号版本段不必出现在每个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
    }
    }
}

那么你觉得,这个正确吗?


你最终得出结论了吗?如果是的话,那是什么?我也在问自己完全相同的问题... - langlauf.io

0

我研究了objdump的源代码和一些BFD的知识。我也阅读了ELF规范。基于此,我认为在动态符号表中无法为符号分配库名称,除非它实际上正在被动态链接。但我不能说我对此完全确定,我想在继续之前与比我更有经验的人讨论一下。 - peter matula
啊-好的。我觉得我没有理解你最初的问题。澄清一下-你想根据符号找到所使用的库文件,是吗?在Linux中,这是由程序加载器完成的-它将符号与库缓存进行匹配。请参见http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html。 - Josh
我想知道是否可能为每个导入的符号分配库的名称 - 它被定义的库以及在动态链接期间将从中链接的库,仅基于可执行文件中的数据 - 而不实际加载和搜索共享对象。 - peter matula

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接