gold
州的人:
-L DIR, --library-path DIR
Add directory to search path
--rpath-link DIR
Add DIR to link time shared library search path
bfd ld
的人使得它有点像-rpath-link
用于递归包含的sos。
ld.lld
甚至没有将其列为参数。
有人可以为我澄清这种情况吗?
答案 0 :(得分:21)
这是针对GNU ld
的演示,-L
和-rpath-link
之间的差异 -
并且为了衡量,-rpath-link
和-rpath
之间存在差异。
<强> foo.c的强>
#include <stdio.h>
void foo(void)
{
puts(__func__);
}
<强> bar.c 强>
#include <stdio.h>
void bar(void)
{
puts(__func__);
}
<强> foobar.c但是强>
extern void foo(void);
extern void bar(void);
void foobar(void)
{
foo();
bar();
}
<强>的main.c 强>
extern void foobar(void);
int main(void)
{
foobar();
return 0;
}
制作两个共享库,libfoo.so
和libbar.so
:
$ gcc -c -Wall -fPIC foo.c bar.c
$ gcc -shared -o libfoo.so foo.o
$ gcc -shared -o libbar.so bar.o
制作第三个共享库,libfoobar.so
取决于前两个;
$ gcc -c -Wall -fPIC foobar.c
$ gcc -shared -o libfoobar.so foobar.o -lfoo -lbar
/usr/bin/ld: cannot find -lfoo
/usr/bin/ld: cannot find -lbar
collect2: error: ld returned 1 exit status
糟糕。链接器不知道在哪里查找解析-lfoo
或-lbar
。
-L
选项修复了该问题。
$ gcc -shared -o libfoobar.so foobar.o -L. -lfoo -lbar
-Ldir
选项告诉链接器dir
是其中一个目录
搜索解析它的-lname
选项的库。它搜索
-L
目录首先按命令行顺序排列;然后它搜索它
配置的默认目录,按其配置顺序。
现在制作一个取决于libfoobar.so
的程序:
$ gcc -c -Wall main.c
$ gcc -o prog main.o -L. -lfoobar
/usr/bin/ld: warning: libfoo.so, needed by ./libfoobar.so, not found (try using -rpath or -rpath-link)
/usr/bin/ld: warning: libbar.so, needed by ./libfoobar.so, not found (try using -rpath or -rpath-link)
./libfoobar.so: undefined reference to `bar'
./libfoobar.so: undefined reference to `foo'
collect2: error: ld returned 1 exit status
再次哎呀。链接器检测libfoobar.so
请求的动态依赖关系
但不能满足他们。让我们抵制它的建议 - try using -rpath or -rpath-link
-
稍等一下,看看我们可以使用-L
和-l
:
$ gcc -o prog main.o -L. -lfoobar -lfoo -lbar
到目前为止一切顺利。但是:
$ ./prog
./prog: error while loading shared libraries: libfoobar.so: cannot open shared object file: No such file or directory
在运行时,加载程序找不到libfoobar.so
。
然后链接器的建议怎么样?使用-rpath-link
,我们可以:
$ gcc -o prog main.o -L. -lfoobar -Wl,-rpath-link=$(pwd)
并且这种联系也成功了。
-rpath-link=dir
选项告诉链接器何时遇到输入文件
请求动态依赖项 - 例如libfoobar.so
- 它应该搜索目录dir
解决他们。所以我们不需要来指定那些与-lfoo -lbar
的依赖关系,而不是。{
甚至需要知道它们是什么。它们是什么,已经写入的信息
libfoobar.so
的动态部分: -
$ readelf -d libfoobar.so
Dynamic section at offset 0xdf8 contains 26 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libfoo.so]
0x0000000000000001 (NEEDED) Shared library: [libbar.so]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
...
...
我们只需知道一个可以找到它们的目录,无论它们是什么。
但是这会给我们一个可运行的prog
吗?
$ ./prog
./prog: error while loading shared libraries: libfoobar.so: cannot open shared object file: No such file or directory
没有。和以前一样的故事。那是因为-rpath-link=dir
为链接器提供了信息
加载程序需要来解析prog
的某些动态依赖项
在运行时 - 假设它在运行时保持为真 - 但它不会将该信息写入 prog
的动态部分。
它只是让链接成功,而不需要拼出所有的递归动态
与-l
选项的链接的依赖关系。
在运行时,libfoo.so
,libbar.so
- 以及libfoobar.so
-
可能不是他们现在的位置 - $(pwd)
- 但装载者可能能够找到它们
通过其他方式:通过ldconfig
缓存或设置
LD_LIBRARY_PATH
环境变量的变量,例如:
$ export LD_LIBRARY_PATH=.; ./prog
foo
bar
rpath=dir
为链接器提供与rpath-link=dir
相同的信息
和指示链接器将该信息烘焙到动态部分
输出文件。我们试试吧:
$ export LD_LIBRARY_PATH=
$ gcc -o prog main.o -L. -lfoobar -Wl,-rpath=$(pwd)
$ ./prog
foo
bar
一切都好。因为现在,prog
包含$(pwd)
是运行时搜索的信息
正如我们所见,它所依赖的共享库的路径:
$ readelf -d prog
Dynamic section at offset 0xe08 contains 26 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [libfoobar.so]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000000f (RPATH) Library rpath: [/home/imk/develop/so/scrap]
... ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
将在LD_LIBRARY_PATH
中列出的目录(如果已设置)之后,系统默认值之前 - ldconfig
- ed目录加上/lib
和{{ 1}}。
答案 1 :(得分:3)
bfd ld使用--rpath-link
选项添加到用于在执行链接时符号解析时查找DT_NEEDED共享库的搜索路径。在尝试模拟动态链接器在解析符号时所执行的操作(由--rpath
选项或LD_LIBRARY_PATH
环境变量设置)时,它基本上告诉链接器要使用什么作为运行时搜索路径
在解析共享库中的符号时,Gold不会遵循DT_NEEDED条目,因此忽略--rpath-link
选项。这是一个刻意的设计决定;在链接过程中,不需要存在间接依赖关系或在其运行时位置。