25

我有一个程序,它依赖于一个共享库,它希望在目录结构的深处找到。我想把那个共享库移到一个更好的地方。在 OS X 上,这可以通过 install_name_tool 完成。我找不到 Linux 的等价物。

作为参考,readelf -d myprogram吐出以下释义输出:

Dynamic section at offset 0x1e9ed4 contains 30 entries:
  Tag        Type                         Name/Value
 0x00000001 (NEEDED)                     Shared library: [this/is/terrible/library.so]
 0x00000001 (NEEDED)                     Shared library: [libGL.so.1]
 0x00000001 (NEEDED)                     Shared library: [libGLU.so.1]
 0x00000001 (NEEDED)                     Shared library: [libstdc++.so.6]
(continues in an uninteresting fashion)

(并应要求,ldd myprogram:)

    linux-gate.so.1 =>  (0x0056a000)
    this/is/terrible/library.so => not found
    libGL.so.1 => /usr/lib/mesa/libGL.so.1 (0x0017d000)
    libGLU.so.1 => /usr/lib/libGLU.so.1 (0x00a9c000)
    libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00710000)
   (etc, etc)

我想将“this/is/terrible/library.so”勘误为“shared/library.so”。请注意,如果程序留在其“构建”位置,相对路径 this/is/terrible/library.so 实际存在的位置,则 ldd 能够找到它,正如您所期望的那样。

我知道 RPATH 并且它不是我想要的,我不需要全局更改搜索路径。

4

4 回答 4

28

我们可以使用patchelf

patchelf --replace-needed liboriginal.so.1 libreplacement.so.1 my-program

我们也可以移除一个依赖:

patchelf --remove-needed libfoo.so.1 my-program

添加依赖项:

patchelf --add-needed libfoo.so.1 my-program

或者更改搜索库的路径(rpath):

patchelf --set-rpath /path/to/lib:/other/path my-program
于 2017-06-13T19:33:43.273 回答
11

发布一个试探性的、可怕的、骇人听闻的解决方案。

库依赖项存储在称为 .depends 块的 ELF 块中。该块的格式是标识符/字符串指针对的大型数组,其中字符串指针指向位于二进制文件某处的标准 C 空终止字符串。

你知道这是怎么回事,对吧?

是的,只要您需要的新路径不大于旧路径,您就可以直接进入二进制文件并进行简单的字符串替换。确保不要添加或删除字节,否则会破坏整个二进制文件。如果你想更安全一点,你实际上可以遍历 ELF 结构以确保你有正确的位置 - 现在我只是检查以确保源字符串只显示一次。

ELF 确实包含一个校验和,但显然没有真正验证它的加载程序,所以它是“安全的”——尽管很乱——可以忽略。

“真正的解决方案”将是一个允许对 ELF 结构进行低级通用操作的实用程序。据我所知,除了少数特殊情况(主要是 RPATH)之外,不存在这样的实用程序。我不假装知道编写这样的实用程序有多么困难。

我绝对希望有一个更好的解决方案,但是,到目前为止,这似乎有效。

于 2010-05-03T17:52:06.247 回答
6

HT - 这可能会有所帮助。

HT 是可执行文件的文件编辑器/查看器/分析器。目标是结合调试器的低级功能和 IDE 的可用性。我们计划实现所有(十六进制)编辑功能并支持最重要的文件格式。

我找不到与 ZorbaTHut 的解决方案有太大不同的东西,但也许可以使用不同长度的名称并保持二进制有效。

gelf - 这也很有用。

GElf 是一个通用的、独立于 ELF 类的 API,用于操作 ELF 目标文件。GElf 为处理 32 位和 64 位 ELF 格式的目标文件提供了一个单一的通用接口。

于 2010-05-03T19:26:40.543 回答
-3

您可以使用 LD_LIBRARY_PATH 更改共享库的搜索路径。如果您的程序依赖于您的示例所示的特定相对路径,您仍然需要具有该目录结构。换句话说,您可以将 lib 移动/home/user/dev/project/this/is/terrible/library.so/usr/local/lib/this/is/terrible/library.so但不能移动到/usr/local/lib/library.so

如果您可以重建您的程序,那么您可以更改它用于库的相对路径。

在http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html有更多关于 Linux 中共享库的信息

于 2010-05-03T17:36:21.147 回答