为什么 ld -L -l... 不匹配 ld /path/to/library.so 的行为?

Why doesn't `ld -L -l...` match the behavior of `ld /path/to/library.so`?

我有两个问题在下面突出显示。我正在使用 64 位 Linux.

我在另一个 post 上看到 MUSL 被提及为 libc 实现。

我尝试将其与以下 Hello world 汇编程序一起使用,该程序使用两个 libc 函数,write_exit

  .data
hello:
  .ascii "Hello, world\n"

  .text
  .globl _start
_start:
  movl , %edx
  movl $hello, %esi
  movl , %edi
  call write

  movl [=11=], %edi
  call _exit

我用以下代码组装了代码:

# Command 1
$ as -o hello.o hello.s

然后我 运行 ld 生成静态 links MUSL libc.

的可执行文件
# Command 2
$ ld hello.o /usr/lib/x86_64-linux-musl/libc.a 

生成的 a.out 文件按预期工作,执行时输出“Hello, world”。

我还尝试了对前面的 ld 命令的不同调用,使用 -static -lc 而不是直接指定路径,还使用 ​​-L 将路径提供给 MUSL 这样就不会使用 glibc,因为后者已经在 ld 的搜索路径上。

# Command 3
$ ld hello.o -L/usr/lib/x86_64-linux-musl/ -static -lc

按预期工作。

接下来我尝试动态link MUSL libc.

# Command 4
$ ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 hello.o \
     /usr/lib/x86_64-linux-musl/libc.so

这似乎按预期工作。我可以 运行 a.out,并且在 a.out 上调用 ldd 表明 MUSLlibc 是 linked。

最后,我尝试了相对于先前静态 linked 版本的类似修改,使用 -lc-L 而不是指定 .so 文件的路径直接。

# Command 5
$ ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 hello.o \
     -L/usr/lib/x86_64-linux-musl -lc

程序没有运行正常,输出错误:

bash: ./a.out: No such file or directory

当我 运行 带有 --verbose 标志的相同 ld 命令时,输出与将 --verbose 传递给较早的 ld 时相同命令(Command 4 生成了一个有效的可执行文件)。

运行 ldd on a.out 也输出错误:

./a.out: error while loading shared libraries: /usr/lib/x86_64-linux-gnu/libc.so: invalid ELF header

问题 1:为什么在这种情况下使用 -L-lc 调用 ld 与我之前指定的 [=45] 的行为不匹配=] 直接文件?

我注意到,如果我将指定的动态 linker 更改为 /lib/ld-musl-x86_64.so.1,则生成的 a.out 运行s 如预期的那样。

# Command 6
$ ld -dynamic-linker /lib/ld-musl-x86_64.so.1 hello.o \
     -L/usr/lib/x86_64-linux-musl -lc

但是,在生成的 a.out 上调用 ldd 会产生以下错误,之前我没有在 -lc-L 中使用 -L =50=]:

./a.out: error while loading shared libraries: /usr/lib/x86_64-linux-gnu/libc.so: invalid ELF header

问题 2:为什么 ld 在这个二进制文件上失败,但是当我将 .so 文件的路径传递给 ldd 并使用不同的动态 linker?

我遇到的问题是由于将 -L 与链接器一起使用,但没有可用于在运行时加载 libc.so 的路径。

我通过对 Command 4Command 5 生成的程序调用 readelf --dynamic --program-headers 注意到了这一点。

 # Command 4
 0x0000000000000001 (NEEDED) Shared library: [/usr/lib/x86_64-linux-musl/libc.so]
 # Command 5
 0x0000000000000001 (NEEDED) Shared library: [libc.so]

我能够解决由 Command 5 生成的程序的问题,方法是使用环境变量,LD_LIBRARY_PATH=/usr/lib/x86_64-linux-musl,当 运行 程序时,或者通过传递额外的参数到 ld, -rpath /usr/lib/x86_64-linux-musl.