30

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)

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.

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?

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

What to do?

EDIT:

$ 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 +++

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)
Marc.2377
  • 7,807
  • 7
  • 51
  • 95
Claudiu
  • 224,032
  • 165
  • 485
  • 680
  • can you show strace -f -v for that static binary? What about "file foob" ? You may want to include the specific source and target (linux?) distributions + architectures you're using. – ggiroux Oct 10 '14 at 17:18
  • As suggested, run `file foob`. Make sure it's a 64-bit executable. –  Oct 10 '14 at 17:22
  • 1
    I just compiled a simplish program with *only* the -static flag: "gcc -o ts --std=c99 --static test.c". Works fine. – Hack Saw Oct 10 '14 at 17:28
  • run `strace -f ./foob` so we can see what the "No such file or directory" is about. – nos Oct 10 '14 at 17:49
  • possible duplicate of [Linux static linking is dead?](http://stackoverflow.com/questions/3430400/linux-static-linking-is-dead) - static linking is well known to not be completely workable on a typical modern desktop linux – Chris Stratton Oct 10 '14 at 18:04
  • 1
    @ChrisStratton, I have never had a problem with `-static` on multiple linux systems. I may have had to install some static libraries but that was it. – Z boson Oct 10 '14 at 18:54
  • What's your OS and version ? Ubuntu 14.04? Redhat? What kind of libc are you using and what's it's version? I'm using Ubuntu 14.04 and Eglibc 2.19 and static linking works fine for me. – Z boson Oct 10 '14 at 18:56
  • @Zboson: I'm using Ubuntu. The libc version is "Ubuntu EGLIBC 2.19-0ubuntu6" – Claudiu Oct 10 '14 at 18:59
  • @Claudiu, have you tried a simple hello world? See my updated answer. – Z boson Oct 10 '14 at 19:10
  • objdump -T on your result, and then grepping for the "UND" will let you see what specific functionality is still being pulled from dynamic libraries - likely that which is simply no longer supported with a static alternative. – Chris Stratton Oct 10 '14 at 19:27

2 Answers2

37

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.

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

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

zwol
  • 135,547
  • 38
  • 252
  • 361
  • Hi @zwol, can you help me understand why it's best to link against uClibc or musl libc instead? If one's goal is to statically link against libc to accomplish customizing libc (e.g., memory allocation behavior) for the shared library *but not the target application*, would one still follow this advice? See http://stackoverflow.com/questions/35072500/malloc-function-interposition-in-the-standard-c-and-c-libraries. – sholsapp Jan 28 '16 at 23:14
  • @sholsapp That depends on which C library functions are used by the shared library in question. I can't give you any more specific answer without knowing a great deal more about what your shared library does, what it needs out of the C library, and why you want to do this rather peculiar thing in the first place. – zwol Jan 29 '16 at 15:49
  • I just tried the following command whose warning message confirmed that: gcc-4.8 --static ... netcat.c warning: Using 'gethostbyaddr' in statically link applications requires at runtime the shared libraries from the glibc version used for linking – zhaorufei Apr 12 '17 at 03:14
1

First be aware that static linking of libc might not improve portability of your program, as libc might depend on other parts of your system e.g. kernel version.

If you want to try complete static linking just using -static should the trick. Provided that there are static versions of all used libraries installed.

You can check if your program has only linked static libraries by using:

ldd binary_name

EDIT:

Another way that provides useful information for debugging this problem would be to add --verbose to your linker flags.

crash
  • 71
  • 3
  • Well that last error is really strange. -static does exactly what he wants to do. And -static-libgcc -static-libstdc++ can be left out, but that shouldn't change anything. – crash Oct 10 '14 at 17:37
  • Static linking is well known to not be completely workable on a typical modern desktop linux. – Chris Stratton Oct 10 '14 at 18:05
  • 4
    @ChrisStratton: Only if you use glibc! – Janus Troelsen Mar 22 '15 at 18:13
  • Sure, but that is what the poster *is* using. And what *else* would you use on a modern desktop linux? – Chris Stratton Mar 23 '15 at 00:44
  • 1
    Musl these days for example, Chris Stratton. Voidlinux uses it. It's quite interesting - I don't think it is competitive feature-wise, but more competition is a good thing IMO. Also note that "partial" static linking is fine; I keep a static version of busybox around, but you can statically compile make, sed, grep, coreutils, etc... and these work. Some folks even managed with GCC; I haven't yet. It can be useful if you manage to break a library somehow (and there are ways how one can do this accidentally). – shevy May 30 '20 at 21:00