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

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

问题描述

我刚刚举了一个使用ld的-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.

运行时文件结构为:

  • 项目/
    • lib/
      • dir/
        • sub/
          • bar.so
  • project/
    • lib/
      • dir/
        • sub/
          • bar.so
  • main.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:警告:lib.dir/foo.so所需的bar.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.

推荐答案

好,我有一些工作要做.但是我真的不明白为什么会起作用.对我来说,这感觉就像是一个小虫.

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

我运行strace -f -o /var/tmp/strace.out -- g++ ...进行main.run编译.静态链接器实际上正在尝试打开其文字名称看起来像"$ 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天全站免登陆