是否可以为可执行文件配置动态加载程序

是否可以为可执行文件配置动态加载程序

我正在寻找一种方法来允许可执行文件找到其共享库,但为了避免与可能使用同一共享库的不同版本的任何包发生冲突,我更喜欢将这些库保留在“私有路径”中(而不是/usr/lib)。

可能的方法似乎是:

  • 在可执行文件中嵌入 rpath
  • 启动可执行文件时设置 LD_LIBRARY_PATH
  • 在 ld.so.conf.d 文件中的 ldconfig 配置中添加库路径

rpath 将目标结构链接到构建,ld.so.conf.d 配置系统路径,LD_LIBRARY_PATH 需要调用者进程知道它。

所以我想知道是否可以使用仅应用于可执行文件的 ld.so.conf.d (或类似的加载器配置)?

答案1

不容易。ld.so.conf文件的格式非常简单:它们只是路径列表。

您可以通过使用不同的方式构建可执行文件来完成某些操作口译员;正常的值类似于/lib64/ld-linux-x86-64.so.21,它实际上负责执行动态链接。因此,您的自定义动态链接器可以查看不同的ld.so.conf,或者执行任何操作。但这听起来比 rpath 差得多!

一个更简单的解决方案是包装器。将二进制文件安装为program.real,或者更好的是,安装在/usr/local/lib/某处(即不在$PATH)。然后输入一个简单的 shell 脚本/usr/local/bin/program

#!/bin/sh
export LD_LIBRARY_PATH=/path/to/libs
exec /usr/local/lib/program/program.real

现在,您的库位置与构建无关,但调用程序不需要了解它。




1:快速查找系统上通常存在的内容的方法:readelf /bin/bash -p .interp。尝试一些不同的可执行文件;您会发现至少 32 位和 64 位程序使用不同的程序。

答案2

可以使用相对 rpath 使用$ORIGIN.

将可执行文件链接到-Wl,-rpath,'$ORIGIN/../lib'允许可执行文件找到其安装的库:

  • 可执行文件在<base>/bin/
  • 共享库位于<base>/lib/

像这样继续操作,仅允许为这些可执行文件配置此链接,并且该<base>目录可以位于任何位置。

答案3

filename的参数可以dlopen是绝对路径(以“ /”开头)。

因此,将“私有路径”存储在配置文件中,并从中构建库的全名。或者,如果您知道私有库将与可执行文件位于同一目录中,请在可执行文件的路径上执行简单的字符串操作以找到它......

#include <dlfcn.h>
#include <unistd.h>
#include <string.h>

static int (*foo)();

/* ... */
char buf[BUFSIZ];
char *lastslash;
void *handle;

realpath(argv[0],buf);
lastslash = strrchr(buf,'/');
strcpy(lastslash,"foo." VERSION_BUILD ".so");
dlopen(buf,RTLD_LOCAL | RTLD_LAZY);
*(void **)(&foo) = dlsym(handle, "foo");

/* ... */
printf("%d\n",foo());

相关内容