Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

How can I tell for sure what userland C library my system uses? Possible reasons to need this information include:

  • There's a gigantic source package I am considering downloading which I'm sure will do proper checks and lists a mininum library version, but I'd rather save myself a potential hassle by checking first if it will work.

  • I am concerned about ABI compatibility with some third party binaries I want to try and install outside the system's package management system.

  • I have a source package who's documentation mentions the need for a minimum version of my system's library, but the build process does not perform any checks.

  • I am building a cross-compiler targeting a specific system and do not want to risk forward compatibility problems.

share|improve this question
    
Why not try it and see. I don't know if the version tells you everything; what about patches? Or are distrubutions careful about altering the ABI? Isn't the issue whether the exported symbols are resolved, or something like that? –  Faheem Mitha Mar 19 at 15:07

6 Answers 6

up vote 15 down vote accepted

GNU/Linux systems usually use either glibc (Fedora/Redhat family, Arch) or its close cousin, eglibc (Debian/Ubuntu family); since eglibc is now being merged back into glibc (see EGLIBC 2.19 Branch Created under "News"), in the near future they will all be glibc again.

The easiest way to check the exact version is to ask ldd, which ships with the C library.

On Fedora 20:

> ldd --version
ldd (GNU libc) 2.18

That's glibc 2.18.

On Raspbian (Debian 7 port for ARMv6 Broadcom SoC):

> ldd --version
ldd (Debian EGLIBC 2.13-38+rpi2) 2.13

That's eglibc 2.13.

If for whatever reason you have mixed and matched some parts or otherwise aren't sure about ldd, you can query the C library directly.

> whereis libc.so
libc: /usr/lib64/libc.a /usr/lib64/libc.so /usr/share/man/man7/libc.7.gz

None of those is executable but they provide a clue about where to find one.

> $(find /usr/lib64/ -executable -name "*libc.so*") --version
GNU C Library (GNU libc) stable release version 2.18, by Roland McGrath et al.

However, it is not necessarily so easy, because the C library does not have to reside somewhere whereis can find it.

> whereis libc.so
libc: /usr/share/man/man7/libc.7.gz

Unfortunately, the man page does not provide a version number. ldd still comes in handy, since any working, dynamically linked executable on the system (e.g., almost everything in /usr/bin) will link to the C library.

> ldd /usr/bin/touch
    /usr/lib/arm-linux-gnueabihf/libcofi_rpi.so (0xb6eed000)
    librt.so.1 => /lib/arm-linux-gnueabihf/librt.so.1 (0xb6ed0000)
    libc.so.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0xb6da1000)
    /lib/ld-linux-armhf.so.3 (0xb6efb000)
    libpthread.so.0 => /lib/arm-linux-gnueabihf/libpthread.so.0 (0xb6d82000)

libc.so.6 is on the third line.

> /lib/arm-linux-gnueabihf/libc.so.6 --version
GNU C Library (Debian EGLIBC 2.13-38+rpi2) stable release version 2.13, by Roland McGrath et al.
share|improve this answer
    
What makes a GNU/Linux system "normal"? What about distributions using musl? –  Elliott Frisch Mar 19 at 14:33
1  
@ElliottFrisch It was intended to apply to GNU/Linux, as in, "normal GNU/Linux" (adjective, noun), since there could be (are, I'm sure) systems which do not use (e)glibc but do use the rest of the GNU stack (bash, binutils, etc.). I would consider those "unusual" GNU/Linux systems. But I've removed the "normal " and changed it to "GNU/Linux systems usually use...". Note I intentionally left the question open WRT OS specifics (there is no linux or GNU or glibc tag), so if you want to add an answer regarding any system appropriate to U&L, please do. –  goldilocks Mar 19 at 14:56
1  
After I found it like you showed and I queried the version, it also printed available extensions! (in my case stubs, crypt, libidn, native threads and bind) and referred to ABI: libc ABIs: UNIQUE IFUNC. –  Amphiteót Mar 19 at 15:21

A system isn't actually limited to one C library. Most, though, primarily use only one, which will also be the one the default compiler uses. And since you're downloading source code to compile, that's the one you're concerned with.

Start with a trivial program:

#include <stdio.h>
int main() {
    printf("Hello, world\n");
    return 0;
}

compile it using the compiler you're going to use for the source code, then use ldd to find out where the C library is:

$ ldd ./libc-test 
        linux-vdso.so.1 (0x00007fff2e5fe000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f8c8ad98000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f8c8b171000)

You now have the path to the C library. You could look this up in your package manager to find the package (e.g., dpkg -S /lib/x86_64-linux-gnu/libc.so.6 or rpm -q -f /lib/x86_64-linux-gnu/libc.so.6).

At least in the case of eglibc/glibc, you can run it:

$ /lib/x86_64-linux-gnu/libc.so.6  
GNU C Library (Debian EGLIBC 2.18-4) stable release version 2.18, by Roland McGrath et al.
Copyright (C) 2013 Free Software Foundation, Inc.
⋮

Finally, you could see if you can get clues from objdump -p /lib/x86_64-linux-gnu/libc.so.6, by looking in the version definitions section:

Version definitions:
1 0x01 0x0865f4e6 libc.so.6
2 0x00 0x09691a75 GLIBC_2.2.5
3 0x00 0x09691a76 GLIBC_2.2.6
⋮
21 0x00 0x06969197 GLIBC_2.17
        GLIBC_2.16 
22 0x00 0x06969198 GLIBC_2.18
        GLIBC_2.17 
23 0x00 0x0963cf85 GLIBC_PRIVATE
        GLIBC_2.18 

Note how the GLIBC_2.18 symbol has the most recent version number among the symbols listed, and the library version is indeed 2.18. It's eglibc, though (it aims to be binary-compatible with glibc 2.18, so it uses the same symbol versions).

You could also attempt to use strings to find out something about it. You'll want to specify a longer minimal length (-n), or use grep to search for something:

$ strings  /lib/x86_64-linux-gnu/libc.so.6 | grep 'version [0-9]'
$ strings  /lib/x86_64-linux-gnu/libc.so.6 | grep -iC1 'copyright'

both work for this eglibc.

NOTE: The Debian package utility dpkg-shlibdeps uses objdump under the hood, along with stored symbol information in Debian library packages to determine the minimum versions of dependencies required by binary Debian packages at build time. Basically, it looks at the symbols exported by the binary Debian package, and then finds the minimum versions of the libraries that contain those symbols.

share|improve this answer

GNU libc (what most Linux distributions use in one form or the other) goes to great lengths to keep strict backwards compatibility. So you should run into trouble only if you try to run a too-new binary on an old version (or a "enterprise" distribution, they normally freeze versions, particularly foundation ones like the C library, backporting fixes while keeping rigurous binary compatibility). I believe you are much more liable to run into problems with other libraries (C++ had a few API/ABI changes in recent memory, some other libraries just don't care for backward compatibility).

Sadly, the only way to find out for sure is to try.

share|improve this answer
    
+1 In fact they have a chart regarding backward compatibility and I would assume the only reason it isn't all 100% is because of code that exploits esoteric GNU extensions. However, there's no such chart I'm aware of regarding forward compatibility, which as you note is more the real concern. –  goldilocks Mar 19 at 15:01

(This is essentially the same as goldilocks' answer but with some more explanation of what is going on under the hood.)

The core shared library for GNU libc, libc.so.6 (on Linux; Hurd has a different SONAME), has the unusual property (for shared libraries) that you can invoke it as an executable. If you do, it prints out the sort of thing GNU utilities usually print when run with --version, like this:

$ /lib/x86_64-linux-gnu/libc.so.6 
GNU C Library (Debian EGLIBC 2.18-4) stable release version 2.18, by Roland McGrath et al.
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 4.8.2.
Compiled on a Linux 3.12.6 system on 2014-03-02.
Available extensions:
    crypt add-on version 2.1 by Michael Glad and others
    GNU Libidn by Simon Josefsson
    Native POSIX Threads Library by Ulrich Drepper et al
    BIND-8.2.3-T5B
libc ABIs: UNIQUE IFUNC
For bug reporting instructions, please see:
<http://www.debian.org/Bugs/>.

But of course the directory where libc.so.6 lives is not in $PATH, so you have to know where to look for it. It might be in /lib, /lib64, /usr/lib, or something even wackier (as in this case). Conveniently, ldd will tell you:

$ ldd /bin/sh | grep libc
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5660b93000)

For that to work, of course, you have to know the full pathname of a dynamically-linked binary executable. The sh executable is guaranteed to be in /bin (because so many #! scripts expect it to be), and can't itself be a #! script. It could be statically linked, but I haven't encountered a system that did that in many years.

I don't know what you do if you're running with uClibc or musl or something more exotic.

share|improve this answer
1  
Well, you don't have to know the full path to /bin/sh or whatever. You can always $ ldd $(which sh) | grep libc. :D –  Matt Nordhoff Mar 20 at 14:06

The obvious answer, though not the most comprehensive, is to check your package manager, e.g

rpm -qi glibc
dpkg -l libc6

(Sadly, glibc doesn't have a pkconfig .pc file, so pkgconfig --modversion glibc is a non-runner.) See also @Gnouc's excellent getconf suggestion.

The simplest case, with gcc+glibc, and the one I mostly use first is to just execute libc.so, as outlined in some of the other answers here. There's no need to pass any arguments, it outputs its version by default. This works back as far as glibc-2.1 (glibc-2.0 seg-faults, though way back then you could check the (now retired) glibcbug script to confirm the version). This method also works with recent (>0.9.15) versions of musl-libc (which just went 1.0 today, March 20th). It does not work with uClibc, it segfaults.

One simple way to tell exactly what your gcc is going to do is compile:

#include <stdio.h>
int main(int argc, char *argv[]) {
    printf("%s %s\n",gnu_get_libc_version(),gnu_get_libc_release());
    printf("glibc v%i %i.%i\n",__GNU_LIBRARY__,__GLIBC__,__GLIBC_MINOR__);
}

This catches more complex cases (multiple libc's, and/or multiple compilers), assuming you're using the right compiler (and flags) of course. (I suspect it won't distinguish between eglibc and glibc proper though.)

If you are certain you are using glibc (or eglibc) then ld will also confirm the version (sorry, this is not correct).

If __GNU_LIBRARY__ is not defined you will get errors, then it's time for plan B.

gcc -dumpmachine may help, e.g. for uclibc it has a -uclibc suffix, as may gcc -dumpspecs | grep dynamic-linker. This also may imply the ABI.

gcc -print-file-name=libc.so will tell you what file the compiler will use for "-lc", this is almost certainly a linker-script within your gcc installation, which you can read it as plain text. That will show the exact path to libc.so. This will also work if you're passing flags like -m32 or -m64.

In the event you're using uclibc (as used by OpenWRT and more), it defines __UCLIBC_MAJOR__, __UCLIBC_MINOR__ and __UCLIBC_SUBLEVEL__ as well as __UCLIBC__ in <features.h>, so it's easily detected using a minor variation on the above C code snippet. In the interest of compatibility, uClibc may also define the GNU/GLIBC macros as used above, it currently pretends to be glibc-2.2. It does not currently implement the gnu_get_libc_X() functions, but it does implement getconf which may also mislead (I suspect it returns an empty answer for getconf GNU_LIBC_VERSION, my build env is sulking today so I cannot confirm.)

In the unlikely event you're using dietlibc, running diet -v will display the version.

(FWIW, over several years with software using autoconf I've had more problems with unchecked-for gcc and g++ requirements than with checked-for glibc features.)

share|improve this answer

Another way to get it:

getconf GNU_LIBC_VERSION
share|improve this answer
    
Nice one, this should work reliably since glibc-2.3.3. –  mr.spuratic Mar 21 at 15:02

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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