使用 -static-libgcc -static-libstdc++ 编译仍然会导致对 libc.so 的动态依赖

2021-12-18 00:00:00 gcc c c++ static-linking glibc

我正在尝试制作一个尽可能可移植的可执行文件.删除一些依赖项后,我在另一个系统上运行二进制文件时遇到了以下问题:

I'm trying to make an executable that's as portable as possible. After removing a few dependencies, I came across the following when running the binary on another system:

/lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.15' not found (required by foob)
/lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.15' not found (required by foob)
/lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.14' not found (required by foob)

我希望我的二进制文件不要求用户升级他们的 libc 版本,所以我也想删除这个依赖项.

I'd prefer my binary not to require the user to upgrade their version of libc, so I'd like to remove this dependency as well.

生成上述二进制文件的链接器标志已经包含 -static-libgcc -static-libstdc++.为什么二进制文件仍然需要共享的 libc.so.6?

The linker flags that produced the above binary already included -static-libgcc -static-libstdc++. How come the binary still requires on the shared libc.so.6?

我也尝试添加 -static 标志,但是当我尝试运行 那个 二进制文件时,结果很奇怪:

I tried adding the -static flag as well, however when I try to run that binary the result is very strange:

$ ls -l foob
-rwxr-xr-x 1 claudiu claudiu 13278191 Oct 10 13:03 foob
$ ./foob
bash: ./foob: No such file or directory

怎么办?

$ file foob
foob: ELF 64-bit LSB  executable, x86-64, version 1 (GNU/Linux), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=5adee9a598b9261a29f1c7b0ffdadcfc72197cd7, not stripped
$ strace -f ./foob
execve("./foob", ["./foob"], [/* 64 vars */]) = -1 ENOENT (No such file or directory)
write(2, "strace: exec: No such file or di"..., 40strace: exec: No such file or directory
) = 40
exit_group(1)                           = ?
+++ exited with 1 +++

有趣的是,如果我ldd没有-static的版本,它比版本少两个条目使用 -static,即:

Interestingly, if I ldd the version without -static, it has two less entries than the version with -static, namely:

libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f4f420c1000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f4f41636000)

推荐答案

GNU libc 并非设计为静态链接.重要功能,例如gethostbynameiconv 在静态二进制文件中会出现故障或根本无法工作.可以说更糟糕的是,在某些情况下,静态二进制文件会尝试动态打开和使用 libc.so.6,即使静态链接的全部目的是避免这种依赖关系.

GNU libc is not designed to be statically linked. Important functions, e.g. gethostbyname and iconv, will malfunction or not work at all in a static binary. Arguably even worse, under some conditions a static binary will attempt to dynamically open and use libc.so.6, even though the whole point of static linkage is to avoid such dependencies.

您应该针对 uClibc 或 musl libc 代替.

You should compile your program against uClibc or musl libc instead.

(至少 15 年来一直如此.)

(This has been true for at least 15 years.)

相关文章