共享库如何知道它所在的位置?

How can a shared library know where it resides?

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

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

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

我知道,我可以使用 /proc/self/maps 或类似的东西来获取加载的文件,但这只有效,只要库知道它自己的名字。

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

Is there any practical, reliable way for the shared library to determine where it resides?

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

I know, I could use /proc/self/maps or something like that, to get the loaded files, but this works only, as long the library knows its own name.

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

无需处理页面映射或 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);
}

从技术上讲,这不可移植;实际上,它甚至可以在 on-Linux 系统(例如 macOS)上运行。您可能需要手动为 realpath 分配存储空间以避免出现非标准行为(在 Linux 和 macOS 上,realpath 本身就是 malloc 的存储空间,并且需要freed 由来电者提供)。

此 returns 路径 共享库本身 。如果要获取目录,可以使用dirname之类的(注意:可重入)或者自己修改字符串。