I see this line in my binary:

0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

Shouldn't I rather get rid of it? Actually more confusingly, why is it there in the first place, I feel like gcc by default compiling things that only run on the host machine is a bit crazy. Isnt it super dangerous to just depend on some random libc that may or may not be on the machine that I'll eventually copy paste this binary to? I dont get it. On Windows I think I'd get some kind of "missing runtime" error that is versioned to the exact runtime that I compiled it with, so if I compiled on XP with a certain compiler then any host machine has to have that runtime installed too. But on Linux I've never heard of such a case, or is there a directory of 50 different libc.so somewhere and the right one gets linked when my application is trying to start up? Because I sort of have a feeling that .dll hell exists for real on Linux and this isn't actually the case.

  • You can read this for some intro link – Tryna Learn Somethin Mar 12 at 13:15
  • that answers nothing about versioning and so on, I'm not asking some basic question ala 'what is the libc'. I'm asking exactly why there is such hard coupling and whether this can result in silent runtime problems as I suspect it can if I run the executable on a machine that has an incompatible libc – Blub Mar 12 at 13:21
  • If you use some function from libc in your code. The fucntion parameters etc will be the same accross different version of libc. The only thing that is different is implementation of those function inside of libc which generally shouldn't be of interest to you – Tryna Learn Somethin Mar 12 at 13:22

At least with the GNU C library, linking carries version information for every single symbol (function etc.) that’s used. You can see this with objdump -T; for example, on /bin/ls, I get

0000000000000000      DF *UND*  0000000000000000  GLIBC_2.3   __ctype_toupper_loc
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 __uflow
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 getenv
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 sigprocmask
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.3.4 __snprintf_chk
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 raise
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 free
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 abort


The C library developers go to great lengths to ensure that the C library remains backwards compatible. The above output means that ls needs __ctype_toupper_loc from version 2.3 or later of the C library, etc. Any C library which provides all the required symbols will be able to run a given binary; and any given version of the GNU C library provides implementations of all the symbols which have ever been provided by an older version of the C library (going back to 1997).

Another way of handling things, used by most libraries on Linux-based systems (in fact, ELF-based systems and others), is the soname. Each library defines not only its name, but a version number, which is changed whenever breaking changes are introduced (in some cases, more often). Multiple versions of libraries, with different sonames, can be installed in parallel; for example

-rw-r--r--  1 root root  2500416 Dec 16 21:07 libcrypto.so.1.0.2
-rw-r--r--  1 root root  2711616 Nov 28 23:43 libcrypto.so.1.1

(This is also used by the C library, as evidenced by the dependency name, libc.so.6 — but the last GNU C library soname bump occurred many years ago.)

To address the question in your title, it is possible to statically link the C library, but it’s rarely necessary or useful (and can be confusing since some parts of the C library are dynamically linked even when the C library is statically linked). It can be useful to link other libraries statically. Other languages use different approaches, and for example Go programs are statically linked.

  • "some parts of the C library are dynamically linked even when the C library is statically linked" what do you mean by that, who is making that decision / doing that to my process? If I statically link in musl, you are saying I could still have competing symbols in memory from the host's libc? – Blub Mar 12 at 15:29
  • With the GNU C library, this happens in particular with libnss — if you statically link a program which uses DNS-related functions implemented by libnss, in most systems the program will need the dynamic libnss libraries at runtime. The people making that decision are the library developers. You won’t get bits of glibc mixing in with musl (well, it might be possible, but you’d have to be trying hard and doing it on purpose — or linking to other libraries linked with the other C library). – Stephen Kitt Mar 12 at 15:48
  • oh ok, you just mean that people will dlopen and dlsym stuff from libc sometimes – Blub Mar 12 at 16:35
  • Yes, including the C library which can be surprising when you build with gcc -static ;-). – Stephen Kitt Mar 12 at 16:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.