What C library version does my system use?
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?
Nice answers, but no one addresses how to do this on a Mac, where there is no ldd . I’m not sure if otool —version can be regarded as giving the same information.
@dubiousjim Someone could; just not me, because I’m not a Mac user. Around here you might have to ask specifically about that — part of the issue is perhaps people generally don’t use plain C much on OSX? But I’m sure there will be a regular who knows. You could also post a link to this in chat and see what happens, but probably a new, more specific question would be better.
6 Answers 6
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.
> ldd --version ldd (GNU libc) 2.18
On Raspbian (Debian 7 port for ARMv6 Broadcom SoC):
> ldd --version ldd (Debian EGLIBC 2.13-38+rpi2) 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.
@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.
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.
Debian uses /lib/`uname -m`* path. So portable way would be: find /lib/`uname -m`* /usr/lib* -executable -name «*libc.so*» | xargs —version . Thanks for nice explanation.
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:
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 4' $ 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.
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 #include int main(int argc, char *argv[])
(with glibc, includes which defines the relevant GLIBC macros, you need for the function declarations.)
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 , 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.)
Viewing Linux Library / Executable version info
The version info in not explicitly stored in an ELF file. What you have in there is the name of the library, the soname , which includes the major version. The full version is usually stored as a part of the library file name.
If you have library, say libtest.so , then you usually have:
- libtest.so.1.0.1 — The library file itself, containing the full version
- libtest.so.1 — Symlink to libtest.so.1.0.1 , having the same name as soname
- libtest.so — Symlink to libtest.so.1 used for linking.
In the library file libtest.so.1.0.1 , there will be an entry called SONAME in dynamic section, that will say this library is called libtest.so.1 . When you link a program against this library, the linked program will store the soname of the library under NEEDED entry in the dynamic section.
If you want to verify, what exactly is in which ELF file, you can try to run:
where elffile can be either an library of an executable.
If you simply want to get the library version, you can play with:
readelf -d /path/to/library.so |grep SONAME
AFAIK, there’s no such info (at least not by default) in executable files.
Or you can rely on the program itself or your packaging system, as Rahul Patil wrote.
nice info, it’s new to me never used readelf, if you don’t mind , may i ask you where & why use readelf
Readelf (and similar tools) is useful, when you want to look inside an elf file :). I use it mostly when programming to look up symbols in libraries (when something doesn’t work), or when there’s some problem with a library. (man readelf)
You can use ldconfig -v | grep libraryname , also command has option command -V or binaryfile —version
test@ubuntukrb12:~# ls --version ls (GNU coreutils) 8.13 Copyright (C) 2011 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later . This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.
also you can use yum or aptitude based on distro you are using eg.
in RHEL5/CENTOS5/Fedora you can use yum info packagename or if it installed then use rpm —version packagename
[root@ldap1 ~]# yum info bind97 Loaded plugins: downloadonly, fastestmirror, security Loading mirror speeds from cached hostfile * base: mirrors.sin3.sg.voxel.net * epel: mirror.imt-systems.com * extras: mirrors.sin3.sg.voxel.net * updates: mirrors.sin3.sg.voxel.net Installed Packages Name : bind97 Arch : i386 Epoch : 32 Version : 9.7.0 Release : 10.P2.el5_8.4 Size : 6.3 M Repo : installed Summary : The Berkeley Internet Name Domain (BIND) DNS (Domain Name System) server URL : http://www.isc.org/products/BIND/ License : ISC Description: BIND (Berkeley Internet Name Domain) is an implementation of the DNS : (Domain Name System) protocols. BIND includes a DNS server (named), : which resolves host names to IP addresses; a resolver library : (routines for applications to use when interfacing with DNS); and : tools for verifying that the DNS server is operating properly.
In Ubuntu You can use aptitude show pkgname or dpkg —version pkgname
root@ubuntukrb12:~# aptitude show bind9utils Package: bind9utils State: installed Automatically installed: yes Version: 1:9.8.1.dfsg.P1-4ubuntu0.4 Priority: optional Section: net Maintainer: Ubuntu Developers Architecture: amd64 Uncompressed Size: 306 k Depends: libbind9-80, libc6 (>= 2.14), libdns81, libisc83, libisccc80, libisccfg82 Conflicts: bind9utils Replaces: bind9 (