ld:在共享库中使用 -rpath,$ORIGIN(递归) [英] ld: Using -rpath,$ORIGIN inside a shared library (recursive)

查看:16
本文介绍了ld:在共享库中使用 -rpath,$ORIGIN(递归)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚做了一个基本示例,将 ld 的 -rpath 选项与 $ORIGIN here(有关工作版本,请参阅第二个响应).我正在尝试创建一个示例,其中 main.run 链接到 foo.so,而 foo.so 又链接到 bar.so,全部使用rpath$ORIGIN.

I just made a basic example of using ld's -rpath option with $ORIGIN here (see 2nd response for a working version). I'm trying to create an example where main.run links to foo.so, which in turn links to bar.so, all using rpath and $ORIGIN.

运行时文件结构为:

  • 项目/
    • 库/
      • 目录/
        • 子/
          • bar.so
          • ma​​in.run(构建失败)
          • main.run (failing to build)

          我正在构建 foo.so 使用:

          I'm building foo.so using:

          g++ -c -o obj/foo.o src/foo.cpp -fPIC
          g++ -shared -o lib/dir/foo.so obj/foo.o -Wl,-soname,foo.so -Wl,-rpath,'$ORIGIN/sub' -Llib/dir/sub -l:bar.so
          

          构建良好.ldd lib/dir/foo.so 甚至可以找到bar.so.

          Which builds fine. ldd lib/dir/foo.so can even find bar.so.

          但是,当我尝试将 main.run 链接到 foo.so 时,foo.so 找不到 bar.so.

          However, when I try to link main.run to foo.so, foo.so can't find bar.so.

          我正在构建 main.so 使用:

          I'm building main.so using:

          g++ -c -o obj/main.o src/main.cpp
          g++ -o run/main.run obj/main.o -Wl,-rpath,'$ORIGIN/../lib/dir' -Llib/dir -l:foo.so
          

          如果使用不递归链接的另一个版本的 foo.so,这会正常工作.(在 make.sh 中取消注释行,在下面的项目中进行测试).

          This works fine if another version of foo.so is used that doesn't recursively link. (Uncomment lines in make.sh, in project below, to test).

          但是,使用普通 foo.so 我在构建 main.run 时遇到此错误:

          However, using the normal foo.so I'm getting this error when building main.run:

          /usr/bin/ld: 警告:bar.so,lib/dir/foo.so 需要,未找到(尝试使用 -rpath 或 -rpath-link)

          /usr/bin/ld: warning: bar.so, needed by lib/dir/foo.so, not found (try using -rpath or -rpath-link)

          所以我的问题是:

          1. foo.so 中的 $ORIGIN 是否解析为 project/lib/dir(foo.so 所在的位置)或 project/run(main.run(链接它的可执行文件)在哪里)?
            ldd 似乎表明它是 project/lib/dir,这似乎是最好的方法(尽管我尝试同时假设两者).
          2. 如何让这些链接(同时保持可重定位性) - 最好不使用 -rpath-link.
          1. Does $ORIGIN within foo.so resolve to project/lib/dir (where foo.so is) or project/run (where main.run (the executable linking it) is)?
            ldd would seem to indicate that it's project/lib/dir, which would seem to be the best way (although I tried assuming both).
          2. How do I get these to link (while preserving relocatability) - preferably without using -rpath-link.

          您可以在此处下载项目.这就像我能做到的一样简单.4 个短资源和一个脚本.
          解压后,只需在 project/ 中运行 ./make.sh.

          You can download the project here. It's as simple as I can make it. 4 short sources and a script.
          After extracting, just run ./make.sh from within project/.

          注意:我使用的是 -l:.这不应该改变任何东西,除了库被命名为 foo.so 而不是 libfoo.so,并且与 -l:foo.so 而不是 -lfoo.

          Note: I'm using -l:. This shouldn't change anything except that the libraries are named like foo.so instead of libfoo.so, and lunk with -l:foo.so instead of -lfoo.

          推荐答案

          好吧,我有一些工作.但我真的不明白为什么它会起作用.这对我来说就像 ld 中的一个错误.

          Well, I have something working. But I do not really understand why it works. This feels like a bug in ld to me.

          我为 main.run 编译运行了 strace -f -o/var/tmp/strace.out -- g++ ....静态链接器实际上是在尝试打开文字名称类似于$ORIGIN/lib/dir/sub/bar.so"的文件,以及其他 20-30 个文件.(换句话说,它正在寻找一个名为 $ORIGIN 的实际目录.说真的.)

          I ran strace -f -o /var/tmp/strace.out -- g++ ... for the main.run compilation. The static linker is actually trying to open files whose literal name looks like "$ORIGIN/lib/dir/sub/bar.so", among 20-30 other things. (In other words, it is looking for an actual directory named $ORIGIN. Seriously.)

          它似乎还在 -rpath-link 路径中搜索名称lib/dir/sub/bar.so",而不仅仅是bar.so".我不知道为什么.

          It also appears to be searching the -rpath-link path for the name "lib/dir/sub/bar.so", not just "bar.so". I have no clue why.

          无论如何,这是对我有用的 main.run 链接:

          Anyway, this is the link for main.run that is working for me:

          g++ -o run/main.run obj/main.o -Wl,-rpath,'$ORIGIN/../lib/dir' -Wl,-rpath-link,. -Llib/dir -l:foo.so
          

          它与你的相同,但插入了 -Wl,-rpath-link,..

          It is identical to yours but with -Wl,-rpath-link,. inserted.

          [附录]

          好的,我想我明白发生了什么.首先,静态链接器 (GNU ld) 根本不支持它链接的库中的 $ORIGIN.

          OK I think I see what is going on. First, the static linker (GNU ld) simply does not honor $ORIGIN in the libraries it links against.

          其次,使用 -lbar-l:bar.so 时的行为非常不同.

          Second, the behavior when you use -lbar versus -l:bar.so is very different.

          foo.so 上运行 readelf -a.在您的构建中,它显示了对lib/dir/sub/bar.so"的依赖.这就是为什么将 rpath-link 设置为."的原因.修复 main.run 的构建;它会导致静态链接器搜索."对于它找到的lib/dir/sub/bar.so".

          Run readelf -a on foo.so. In your build, it shows a dependency on "lib/dir/sub/bar.so". This is why setting the rpath-link to "." fixes the build of main.run; it causes the static linker to search "." for "lib/dir/sub/bar.so", which it finds.

          如果将 bar.so 重命名为 libbar.so,并将 foo.so 链接为使用 -lbar 而不是 -l:bar.so,同样的 readelf 会显示foo.so 现在依赖于libbar.so"(没有路径组件).使用 foo.so,您可以使用 -Wl,-rpath-link,lib/dir/sub 使 main.run 链接正常工作,正如您所期望的那样,如果您知道静态链接器只是简单的不尊重 $ORIGIN.

          If you rename bar.so to libbar.so, and link foo.so to use -lbar instead of -l:bar.so, the same readelf shows that foo.so now depends on "libbar.so" (with no path component). With that foo.so, you can get the main.run link to work using -Wl,-rpath-link,lib/dir/sub, as you would expect if you knew that the static linker simply does not honor $ORIGIN.

          顺便说一句,我在 GNU ld 手册的任何地方都没有看到 -l:bar.so 语法.出于好奇,你是怎么想到的?

          By the way, I do not see the -l:bar.so syntax documented anywhere in the GNU ld manual. Out of curiosity, how did you come up with it?

          假设它是一个受支持的功能,这看起来有点像一个错误(-l:bar.so 创建对 lib/dir/sub/bar.so 的依赖,而不仅仅是 bar.so).您可以通过将 rpath-link 设置为 '.' 来处理此错误.对于 main.run,或者您可以以通常的方式重命名 (libxxx.so).

          Assuming it is a supported feature, this looks a bit like a bug (-l:bar.so creating a dependency on lib/dir/sub/bar.so instead of just bar.so). You can either deal with this bug by setting rpath-link to '.' for main.run, or you can rename stuff in the usual way (libxxx.so).

          这篇关于ld:在共享库中使用 -rpath,$ORIGIN(递归)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆