【问题标题】:Returning a shared library symbol table返回共享库符号表
【发布时间】:2011-02-11 06:21:27
【问题描述】:

例如:

void* sdl_library = dlopen("libSDL.so", RTLD_LAZY);
void* initializer = dlsym(sdl_library,"SDL_Init");

假设没有错误,初始化器将指向共享库 libSDK.so 中的函数 SD_Init。

但是,这需要知道符号“SDL_Init”的存在。

是否可以查询库的所有符号?例如,在这种情况下,它将返回 SDL_Init、函数指针以及 libSDL.so 导出的任何其他符号。

【问题讨论】:

    标签: c dll plugins shared-libraries dlopen


    【解决方案1】:

    没有 libc 函数可以做到这一点。但是,您可以自己编写一个(虽然代码有些复杂)。

    在 Linux 上,dlopen() 实际上返回 link_map 结构的地址,该结构有一个名为 l_addr 的成员指向加载的共享对象的基地址(假设您的系统没有随机化共享库位置,并且您的库尚未预先链接)。

    在 Linux 上,找到基地址(Elf*_Ehdr 的地址)的可靠方法是在 dlopen() 库之后使用 dl_iterate_phdr()

    有了 ELF 标头,您应该能够遍历导出符号列表(动态符号表),首先找到 PT_DYNAMIC 类型的 Elf*_Phdr,然后找到 DT_SYMTABDT_STRTAB条目,并迭代动态符号表中的所有符号。使用/usr/include/elf.h指导您。

    此外,您可以使用libelf,但我无法为您提供指导,因为我之前没有这方面的经验。

    最后请注意,这个练习有点徒劳:你会得到一个已定义函数的列表,但你不知道如何调用它们(它们期望什么参数),那么有什么意义呢?

    【讨论】:

      【解决方案2】:

      我认为没有为此发布的 API。您可以使用 binutils 中的 nm 工具或检查其源代码: http://sourceware.org/cgi-bin/cvsweb.cgi/src/binutils/?cvsroot=src

      http://sourceware.org/cgi-bin/cvsweb.cgi/src/binutils/nm.c?rev=1.63&content-type=text/x-cvsweb-markup&cvsroot=src

      (显然是小精灵)

      【讨论】:

        【解决方案3】:

        Boost.DLL 通过library_info::symbols 函数提供此功能。改编自Querying libraries for symbols上的教程:

        // Class `library_info` can extract information from a library
        boost::dll::library_info inf(libpath);
        
        // Getting exported symbols
        std::vector<std::string> exports = inf.symbols();
        
        // Printing symbols
        for (std::size_t j = 0; j < exports.size(); ++j) {
            std::cout << exports[j] << std::endl;
        }
        

        请注意,这只适用于nm 列出没有 --dynamic 标志的符号,即.symtab 部分中的符号。似乎某些库不会在该部分中导出任何符号。我已经打开了feature request 以支持在这种情况下退回到.dynsym 部分。

        【讨论】:

          【解决方案4】:
          void *dlsym(void *restrict handle, const char *restrict name);
          

          返回值

          如果 handle 没有引用有效的 dlopen() 打开的对象,或者如果 在其中找不到命名符号 任何相关的对象 handledlsym() 应返回 NULL。 更详细的诊断信息 应通过 dlerror() 获得。

          (来源:http://www.opengroup.org/onlinepubs/009695399/functions/dlsym.html

          换句话说,如果找不到符号,dlsym() 将返回 NULL。不确定这是否是您要查找的内容,但这是我能找到的最简单的方法。

          【讨论】:

          • 在我看来,OP 正在寻找从库中获取导出符号的列表。如果不对 ELF 结构中的部分进行一些解析,我认为这是不可能的。
          【解决方案5】:

          【讨论】:

          • 问题似乎是在寻找一种查询共享库符号表的编程方法。 nm 是一个命令行实用程序,其文本输出格式因平台而异。
          猜你喜欢
          • 1970-01-01
          • 2011-02-28
          • 1970-01-01
          • 2017-08-02
          • 2018-04-14
          • 2016-09-26
          • 2016-10-16
          • 2021-07-27
          • 2014-11-03
          相关资源
          最近更新 更多