【问题标题】:How can a shared library know where it resides?共享库如何知道它所在的位置?
【发布时间】:2017-01-10 07:45:23
【问题描述】:

我正在为 linux 机器开发一个共享库,它是相对于使用 rpath 的主可执行文件动态加载的。 现在,库本身尝试相对于其位置动态加载其他库,但没有 rpath(我使用 scandir 搜索某个文件夹中的共享库 - 我还不知道它们的名称)。

仅当工作目录设置为共享库位置时才有效,否则我会按预期查看不同的目录。

共享库是否有任何实用、可靠的方法来确定其所在位置?

我知道,我可以使用 /proc/self/maps 或类似的东西来获取加载的文件,但这仅适用于库知道自己的名称。

另一个想法是使用 dlinfo(),但要使用它,共享库需要知道自己的句柄。

【问题讨论】:

    标签: linux shared-libraries dynamic-loading


    【解决方案1】:

    共享库有什么实用可靠的方法吗 确定它的位置?

    我会使用dlinfo/proc/self/mapsproc 可能并不总是被挂载,尤其是在容器中)。

    我知道,我可以使用 /proc/self/maps 或类似的东西, 获取加载的文件,但这仅适用于库 知道自己的名字。

    并非如此,您可以将指针指向库中的某些代码(最好指向某些内部标签,以避免与 PLT/GOT 混淆)并将结果与​​从/proc/self/maps(或dlinfo)获得的内存范围进行比较。

    【讨论】:

    • 库如何获得自己的句柄以使用 dlinfo()? dlopen() 的文档说,如果我使用 NULL 作为文件名,我将获得主程序的句柄。这可能不是共享库,对吧?
    • "库如何获取自己的句柄以使用 dlinfo()" - 您可以通过 l->l_next 返回的 dlinfo(dlopen(0, RTLD_LAZY), RTLD_DI_LINKMAP, &l) (句柄等于指向链接映射的指针)。您将通过检查它的地址范围是否包含本地函数指针来识别有趣的库。
    • 实际上,我想知道您是否需要dlinfo - 您可以简单地从dlopen(0) 返回的link_map 进行迭代...
    【解决方案2】:

    无需处理页面映射或dlinfo。您可以在共享库中定义的任何符号上使用dladdr

    #define _GNU_SOURCE
    #include <dlfcn.h>
    #include <stdlib.h>
    
    static char *lib_path(void) {
        Dl_info info;
        if (! dladdr((void *) lib_path, & info)) return NULL;
        return realpath(info.dli_fname, NULL);
    }
    

    从技术上讲,这不是便携式的;实际上,它甚至可以在 macOS 等 Linux 系统上运行。您可能需要手动为 realpath 分配存储空间以避免出现非标准行为(在 Linux 和 macOS 上,realpath 本身为 mallocs 存储空间,并且需要由调用者为 freed)。

    这将返回到共享库本身的路径。如果要获取目录,可以使用dirname 之类的东西(小心:可重入)或自己修改字符串。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-04-06
      • 1970-01-01
      • 2021-02-10
      • 2012-06-13
      • 2021-10-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多