如何强制运行时链接程序使用可执行目录中的共享库?

时间:2019-07-06 20:45:58

标签: linux ubuntu shared-libraries dynamic-linking

我有一个要在另一台计算机上运行的二进制文件,但是我收到此错误消息:

./program.run: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.29' not found (required by /home/ubuntu/lamodal/server/linux/./libxml2.so.2)

我正在使用选项-Wl,-rpath='$ORIGIN'使用g ++ 8.3.0编译程序,并且在将程序二进制文件放入的目录中,我还放置了所需的所有共享库。为了发现我需要放置在目录中的库,在我用来运行ldd ./program的程序的机器上找到了库列表,然后将其复制到我想要的机器目录中运行我的程序。

但是,在目标计算机(即要在其上运行程序的计算机)中,当我运行ldd ./program时,我得到以下输出:

./program.run: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.29' not found (required by /home/ubuntu/lamodal/server/linux/./libxml2.so.2)
        linux-vdso.so.1 (0x00007fff8a1d8000)
        libwebsockets.so.13 => /home/ubuntu/lamodal/server/linux/./libwebsockets.so.13 (0x00007f5b220d8000)
        libxml2.so.2 => /home/ubuntu/lamodal/server/linux/./libxml2.so.2 (0x00007f5b21ebd000)
        libssl.so.1.1 => /home/ubuntu/lamodal/server/linux/./libssl.so.1.1 (0x00007f5b21e29000)
        libcrypto.so.1.1 => /home/ubuntu/lamodal/server/linux/./libcrypto.so.1.1 (0x00007f5b21b40000)
        libdl.so.2 => /home/ubuntu/lamodal/server/linux/./libdl.so.2 (0x00007f5b220d2000)
        libstdc++.so.6 => /home/ubuntu/lamodal/server/linux/./libstdc++.so.6 (0x00007f5b2195e000)
        libgcc_s.so.1 => /home/ubuntu/lamodal/server/linux/./libgcc_s.so.1 (0x00007f5b220b6000)
        libpthread.so.0 => /home/ubuntu/lamodal/server/linux/./libpthread.so.0 (0x00007f5b22095000)
        libc.so.6 => /home/ubuntu/lamodal/server/linux/./libc.so.6 (0x00007f5b21773000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f5b213d5000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f5b22020000)

如您所见,大多数链接的库都位于$ ORIGIN目录中,即/home/ubuntu/lamodal/server/linux/,但libm.so.6/lib64/ld-linux-x86-64.so.2除外。这两个库都在目录中,但是链接器似乎更喜欢其他目录中的库。

有关机器的一些其他信息:

开发机器:

  • Ubuntu 19.04 x86_64

  • ldd --version的输出:ldd (Ubuntu GLIBC 2.29-0ubuntu2) 2.29

目标机器:

  • Ubuntu 18.04.2 LTS x86_64

  • ldd --version的输出:ldd (Ubuntu GLIBC 2.27-3ubuntu1) 2.27

是否有一种方法可以强制运行时链接程序先查看$ ORIGIN,然后再查看其他地方?

修改 我尝试了Employed Russian to this question提供的答案,我的构建命令现在看起来像这样:

g++ -Wl,-rpath='$ORIGIN' \
    -Wl,--dynamic-linker='$ORIGIN/ld-linux-x86-64.so.2' \
    ...
    -o ./path/to/program.run

然后,我已将开发机器(位于ld-linux-x86-64.so.2中的/lib64复制到目标机器上的可执行目录。 ldd ./program.run的输出保持不变。但是现在,当我尝试运行./program.run时,我得到了No such file or directory错误,根据某些原因是因为找不到运行时链接程序。然后,我尝试将构建脚本修改为使用完整路径,而不是使用$ORIGIN,但这并不能解决任何问题。

1 个答案:

答案 0 :(得分:-1)

也许这会起作用:

$> LD_PRELOAD=/path/to/my/shared_files ./program.run

这在很大程度上取决于。您正在做的事情-以及您做事的方式-都是棘手的,很容易造成损坏。但这可能有效。 LD_PRELOAD表示从给定路径而不是标准系统路径加载库。