动态加载时的库路径?

jld*_*ont 13 linux shared-libraries dlopen

如何从库本身获取共享库的路径?

换句话说,假设库X是使用加载的dlopen(),我怎样才能访问用于从库本身加载所述库的路径?

请注意,我不能让首先加载库的代理程序提交给我这个参数.

更新:这是使用静态变量的方式:

std::string wdir;

namespace {
    class dynamic_library_load_unload_handler {
         public:
              dynamic_library_load_unload_handler(){
                    Dl_info dl_info;
                    dladdr((void *) NP_Initialize, &dl_info);

                    std::string path(dl_info.dli_fname);
                    wdir = path.substr( 0, path.find_last_of( '/' ) +1 );
              }
              ~dynamic_library_load_unload_handler(){
                    // Code to execute when the library is unloaded
              }
    } dynamic_library_load_unload_handler_hook;
}
Run Code Online (Sandbox Code Playgroud)

Jay*_*rod 18

动态链接器实际上搜索多个位置以查找每个动态库.这些包括(来自man ld.so):

  • 环境变量给出的路径 LD_LIBRARY_PATH
  • 烘焙到二进制文件中的路径加载DT_RUNPATH条目下的库
  • 缓存文件/etc/ld.so.cache
  • / lib和/ usr/lib

如果您想获取特定共享库的路径,我会推荐该dladdr功能.从手册页:

函数dladdr()接受函数指针并尝试解析它所在的名称和文件.信息存储在 Dl_info结构中:

typedef struct {
    const char *dli_fname;  /* Pathname of shared object that
                               contains address */
    void       *dli_fbase;  /* Address at which shared object
                               is loaded */
    const char *dli_sname;  /* Name of nearest symbol with address
                               lower than addr */
    void       *dli_saddr;  /* Exact address of symbol named
                               in dli_sname */
} Dl_info;
Run Code Online (Sandbox Code Playgroud)

如果没有符号匹配的地址可以找到,然后dli_snamedli_saddr被设置为NULL.

dladdr() 错误时返回0,成功时返回非零.

所以你只需给它一个函数指针,它会给你提供它的文件的名称和一堆其他信息.因此,例如,您可以在库中使用构造函数调用此函数来查找库的完整路径:

#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>

__attribute__((constructor))
void on_load(void) {
    Dl_info dl_info;
    dladdr((void *)on_load, &dl_info);
    fprintf(stderr, "module %s loaded\n", dl_info.dli_fname);
}
Run Code Online (Sandbox Code Playgroud)

此函数也适用于OS X,具有相同的语义.

  • @jldupont:`__attribute __((构造函数))`与C++中用于调用静态变量构造函数的机制完全相同,除了gcc使它在C中也可用.因此,不会在翻译单元中指定顺序.但是,gcc允许您通过添加优先级来指定它,例如`__attribute __((constructor(101)))`.可以通过向类添加`__attribute __((init_priority(500)))来指定构造函数的优先级,但我无法在任何地方找到默认优先级.较低的优先级意味着较早的构造函数和稍后的析构函数. (2认同)