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

发布于 2024-11-19 23:06:19 字数 974 浏览 3 评论 0原文

我正在开发一个程序,该程序将分析 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 可执行文件中找到符号共享库的名称吗?

感谢您的任何建议。

i'm working on program that will analyze object files in ELF and PE formats (kind of school/research project). Right now i'm about to process dynamic import symbols in executable files. I would like to find as much info about symbol as possible.

In PE format, imports are stored in .idata section. There are several tables with different information but what is interesting for me is, that there is no problem to find out in which library is symbol defined. There is always name of shared library and then names/ordinals of symbols imported from it.

I would like to find out this kind of information in ELF files as well. All imports/exports are in .dynsym section - dynamic symbol table. Those symbols which are imported are marked as undefined, for example:

00000000      DF *UND*  00000000  GLIBC_2.0   fileno

But there are no information, what is source file of this symbol. All needed shared libraries are listed in .dynamic section, for example:

Dynamic Section:
  NEEDED               libz.so.1

Only information about library in symbol is Version String = GLIBC_2.0. I was thinking about getting to real library name through this, but when i look at output of objdump -p i found out that GLIBC_2.0 can be connected with more than one library:

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

If i understand ELF dynamic linking process correctly, it should not be possible to find out this information in ELF executable file. Where exactly is the symbol imported from is determined by linker after it loads all symbol tables to memory.
But i would like to be sure about this before i move on, so my question is: Is there any way how can I find out name of symbols shared library from ELF executable file?

Thank you for any advice.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

神妖 2024-11-26 23:06:19

几个月前,我正在研究非常类似的东西 - 我能够通过获取 nm 和 readelf 的源代码来回答我所有的问题。 (参见 http://ftp.gnu.org/gnu/binutils/
我发现这也很有用 -> http://www.skyfree.org/linux/references/ELF_Format.pdf

A few months ago I was working on pretty similar stuff - I was able to answer all my questions by grabbing the source to nm and readelf. ( See http://ftp.gnu.org/gnu/binutils/ )
I found this useful as well -> http://www.skyfree.org/linux/references/ELF_Format.pdf

滥情稳全场 2024-11-26 23:06:19

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

那么您认为这是否正确?

Ok, so it is probably generaly impossible to assign library name to each imported symbol. But i may have found the solution through Symbol Versioning. Of course sybol version sections do not have to be present in each ELF file.

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

So what do you think, is this correct?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文