Check glibc version for a particular gcc compiler - c

I have two gcc compilers installed on my system, one is gcc 4.1.2 (default) and the other is gcc 4.4.4. How can I check the libc version used by gcc 4.4.4, because /lib/libc.so.6 shows the glibc used by gcc 4.1.2, since it is the default compiler.

even easier
use ldd --version
This should return the glibc version being used i.e.
$ ldd --version
ldd (GNU libc) 2.17
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
...
which is the same result as running my libc library
$ /lib/libc.so.6
GNU C Library (GNU libc) stable release version 2.17, by Roland McGrath et al.
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
...

Write a test program (name it for example glibc-version.c):
#include <stdio.h>
#include <stdlib.h>
#include <gnu/libc-version.h>
int main(int argc, char *argv[]) {
printf("GNU libc version: %s\n", gnu_get_libc_version());
exit(EXIT_SUCCESS);
}
and compile it with the gcc-4.4 compiler:
gcc-4.4 glibc-version.c -o glibc-version
When you execute ./glibc-version the used glibc version is shown.

Use -print-file-name gcc option:
$ gcc -print-file-name=libc.so
/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc.so
That gives the path. Let's examine the file:
$ file $(gcc -print-file-name=libc.so)
/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libc.so: ASCII text
$ cat $(gcc -print-file-name=libc.so)
/* GNU ld script
Use the shared library, but some functions are only in
the static library, so try that secondarily. */
OUTPUT_FORMAT(elf64-x86-64)
GROUP ( /lib/x86_64-linux-gnu/libc.so.6 /usr/lib/x86_64-linux-gnu/libc_nonshared.a AS_NEEDED ( /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 ) )
The file is a linker script, which links the libraries in GROUP list.
On ELF platforms /lib/x86_64-linux-gnu/libc.so.6 is a position-independent executable with a dynamic symbol table (like that of a shared library):
$ file /lib/x86_64-linux-gnu/libc.so.6
/lib/x86_64-linux-gnu/libc.so.6: symbolic link to libc-2.31.so
$ file $(readlink -f /lib/x86_64-linux-gnu/libc.so.6)
/usr/lib/x86_64-linux-gnu/libc-2.31.so: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=1878e6b475720c7c51969e69ab2d276fae6d1dee, for GNU/Linux 3.2.0, stripped
$ /lib/x86_64-linux-gnu/libc.so.6
GNU C Library (Ubuntu GLIBC 2.31-0ubuntu9.9) stable release version 2.31.
Copyright (C) 2020 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 9.4.0.
libc ABIs: UNIQUE IFUNC ABSOLUTE
For bug reporting instructions, please see:
<https://bugs.launchpad.net/ubuntu/+source/glibc/+bugs>.

gnu_get_libc_version identifies the runtime version of the GNU C Library.
If what you care about is the compile-time version (that is, the version that provided the headers in /usr/include), you should look at the macros __GLIBC__ and __GLIBC_MINOR__. These expand to positive integers, and will be defined as a side-effect of including any header file provided by the GNU C Library; this means you can include a standard header, and then use #ifdef __GLIBC__ to decide whether you can include a nonstandard header like gnu/libc-version.h.
Expanding the test program from the accepted answer:
#include <stdio.h>
#ifdef __GLIBC__
#include <gnu/libc-version.h>
#endif
int
main(void)
{
#ifdef __GLIBC__
printf("GNU libc compile-time version: %u.%u\n", __GLIBC__, __GLIBC_MINOR__);
printf("GNU libc runtime version: %s\n", gnu_get_libc_version());
return 0;
#else
puts("Not the GNU C Library");
return 1;
#endif
}
When I compile and run this program on the computer I'm typing this answer on (which is a Mac) it prints
Not the GNU C Library
but when compiled and run on a nearby Linux box it prints
GNU libc compile-time version: 2.24
GNU libc runtime version: 2.24
Under normal circumstances, the "runtime" version could be bigger than the "compile-time" version, but never smaller. The major version number is unlikely ever to change again (the last time it changed was the "libc6 transition" in 1997).
If you would prefer a shell 'one-liner' to dump these macros, use:
echo '#include <errno.h>' | gcc -xc - -E -dM |
grep -E '^#define __GLIBC(|_MINOR)__ ' | sort
The grep pattern is chosen to match only the two macros that are relevant, because there are dozens of internal macros named __GLIBC_somethingorother that you don't want to have to read through.

I doubt if you have more than one glibc installed in your system.But ldd -v <path/to/gcc-4.x> should give you the glibc used.

The easiest way is to use ldd which comes with glibc
Just run this command ldd --version :
dina#dina-X450LA:~$ ldd --version
ldd (Ubuntu GLIBC 2.23-0ubuntu9) 2.23
Copyright (C) 2016 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.
Written by Roland McGrath and Ulrich Drepper.
Their is two additional ways to find out the glibc version:
Check the version of the installed glibc rpm package : this by runing this command
rpm -q glibc
Check the version of the used libc.so file. This way is a little bit more difficult. You can check it in this link: Linux: Check the glibc version

You can use strings command to check GLIBC version of compiler. Highest version is applicable.
ubuntu1604:extra$ strings ./arm-unknown-linux-gnueabi/bin/arm-unknown-linux-gnueabi-gcc | grep GLIBC
GLIBC_2.3
GLIBC_2.8
GLIBC_2.14
GLIBC_2.4
GLIBC_2.11
GLIBC_2.2.5
GLIBC_2.3.4

Also, check the higher versioning symbol of the libc:
readelf -V /lib64/libc.so.6

Related

Why does one of my finaries fail with version `GLIBC_2.27' not found

I am cross-compiling by binaries identically by CMake clauses like
add_executable(mybinary1 mybinary1.c util_temp.c)
target_link_libraries(mybinary1 m)
add_executable(mybinary2 mybinary2.c util_temp.c)
target_link_libraries(mybinary2 m)
Unfortunately, one of them fails when running on target platform:
/mybinary2: /lib/arm-linux-gnueabihf/libm.so.6: version `GLIBC_2.27' not found (required by ./mybinary2)
First binary runs well.
ldd shows
# ldd mybinary2
./mybinary2: /lib/arm-linux-gnueabihf/libm.so.6: version `GLIBC_2.27' not found (required by ./mybinary2)
linux-vdso.so.1 (0x7ed1d000)
/usr/lib/arm-linux-gnueabihf/libarmmem.so (0x76fa2000)
libm.so.6 => /lib/arm-linux-gnueabihf/libm.so.6 (0x76f27000)
libc.so.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0x76de6000)
/lib/ld-linux-armhf.so.3 (0x76fcc000)
# ldd mybinary1
linux-vdso.so.1 (0x7ee09000)
/usr/lib/arm-linux-gnueabihf/libarmmem.so (0x76ece000)
libm.so.6 => /lib/arm-linux-gnueabihf/libm.so.6 (0x76e53000)
libc.so.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0x76d12000)
/lib/ld-linux-armhf.so.3 (0x76efb000)
What does it mean and how to solve it? Can I compile against specific version of a library? Why does it refer GLIBS indirectly, via libm?
If I do
target_link_libraries(mybinary2 m -static)
it starts to work but binary becomes x20 larger.
I also tried
__asm__(".symver realpath,realpath#GLIBC_2.19");
int main(int argc, char *argv[])
in mybinary2.c with no effect.
target_link_libraries(mybinary2 m -static-libgcc -static-libstdc++)
in CMakeLists.txt with no effect.
target_link_libraries(mybinary2 m libc.so.6:2.19)
with error message
[build] /usr/lib/gcc-cross/arm-linux-gnueabihf/7/../../../../arm-linux-gnueabihf/bin/ld: cannot find -llibc.so.6:2.19
Is latter syntax correct? How to see, which version (and of what) is on my system?
I tried commands like
ld -llibc
but neither work.
On my target computer (it is Raspberry Pi with old version of OS):
# ldd --version
ldd (Debian GLIBC 2.19-18+deb8u10) 2.19
Copyright (C) 2014 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.
Written by Roland McGrath and Ulrich Drepper.
I don't know how to use cross ldd on source computer.
Based on what your target computer outputs via ldd --version and based on the error (which also explains why a static link works):
You have a GLIBC version mismatch, i.e. you compile it using GLIBC 2.27 but on the target computer you have GLIBC 2.19. You either need to crosscompile with a lower version than you are currently using or upgrade glibc on the target computer.
EDIT: To clarify which errors and general info I mean:
1)
# ldd mybinary2
./mybinary2: /lib/arm-linux-gnueabihf/libm.so.6: version `GLIBC_2.27' not found (required by ./mybinary2)
# ldd --version
ldd (Debian GLIBC 2.19-18+deb8u10) 2.19
EDIT2: Did a quick search and assuming you are crosscompiling on debian you could use the following command to get available package versions:
apt-cache policy myPackage
Where myPackage will most likely be libc6-dev-armhf-cross for your current needs.
EDIT3: As Andrew Henle pointed out. The easiest solution is to directly compile your project on the target device (or a compilation environment that is identical to the one on the target). Consider the above only if the target device is limiting you in doing so.

How to make GCC not to generate endbr64?

My gcc version is 9.3.0
gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
Copyright (C) 2019 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
According to gcc 9.3 manual
-mmanual-endbr
Insert ENDBR instruction at function entry only via the cf_check function
attribute. This is useful when used with the option ‘-fcf-protection=branch’
to control ENDBR insertion at the function entry.
From my understand, if I compile something using following command:
gcc -fcf-protection=branch -mmanual-endbr sth.c -o sth
The main function hasn't cf_check attribute, so there should isn't endbr64 at entry of main.
But it turns out still has endbr64 at entry.
So, how to make GCC not to generate endbr64?
Thanks.

Compiling for rx600 with gcc

I have a project that compiles for an RX600 with renasas' gcc compiler (from now on rx-elf-gcc). But I was wondering, shouldn't I be able to compile it with standard gcc? And if, how?
I'm making a docker container for the project, and I would prefere if I did not have to install renesas' compiler, installing it and supplying the activation code, etc.
I have found this piece of documentation, that got me started
https://gcc.gnu.org/onlinedocs/gcc-7.3.0/gcc/RX-Options.html
I then expected to be able to do something like:
$ gcc -mcpu=rx600 -mlittle-endian-data dummy.c
But it gives the error:
gcc: warning: ‘-mcpu=’ is deprecated; use ‘-mtune=’ or ‘-march=’ instead
gcc: error: unrecognized command line option ‘-mlittle-endian-data’
I have tried using -mtune instead, but it seems rx is not a valid option
$ gcc -mtune=rx600 dummy.c
cc1: error: bad value (‘rx600’) for ‘-mtune=’ switch
cc1: note: valid arguments to ‘-mtune=’ switch are: nocona core2 nehalem corei7 westmere sandybridge corei7-avx ivybridge core-avx-i haswell core-avx2 broadwell skylake skylake-avx512 bonnell atom silvermont slm knl intel x86-64 eden-x2 nano nano-1000 nano-2000 nano-3000 nano-x2 eden-x4 nano-x4 k8 k8-sse3 opteron opteron-sse3 athlon64 athlon64-sse3 athlon-fx amdfam10 barcelona bdver1 bdver2 bdver3 bdver4 znver1 btver1 btver2 generic
So, can I add a new hardware model to my installation? Or will these models just simply redirect my to rx-elf-gcc?
As a side note:
$ gcc --version
gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0
Copyright (C) 2017 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.
$ rx-elf-gcc --version
rx-elf-gcc (GCC_Build_20180315) 4.8.4.201801-GNURX
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.
And the following works:
$ rx-elf-gcc -mcpu=rx600 -mlittle-endian-data -c dummy.c

Creating a shared library with main() [duplicate]

This question already has answers here:
How to make a linux shared object (library) runnable on its own?
(2 answers)
Closed 5 years ago.
In glibc (and also EGLIBC I believe), the libc.so library has a main() method:
$ /lib/i386-linux-gnu/libc.so.6
GNU C Library (Debian GLIBC 2.19-18+deb8u1) stable release version 2.19, by Roland McGrath et al.
Copyright (C) 2014 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.4.
Compiled on a Linux 3.16.7 system on 2015-08-30.
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/>.
Now I want to do the same with the following minimalistic example (i. e. I want my own SO to also have a main()):
#include <stdio.h>
int main(int argc, char *argv[]) {
printf("Hello, World!\n");
return 0;
}
Linking as a regular executable:
$ gcc -g -O0 -Wall -c test.c
$ gcc -o test test.o
$ ./test
Hello, World!
Now linking as a shared object:
$ gcc -g -O0 -Wall -c test.c
$ gcc -shared -o libtest.so test.o
$ ./libtest.so
Segmentation fault
nm shows that main symbol is present (000004f5 T main)
When debugging, gdb doesn't show any meaningful backtrace.
Adding -fpic or -fPIC to the gcc command line doesn't help.
What am I doing wrong?
the libc.so library has a main() method
No, the implementation of C library of gcc has an entry point not a main symbol.
You can find an example of how to do this here.

OS X: CMake ignores CMAKE_C_COMPILER

I am trying to build Trilinos on my OS X 10.11.6 laptop and keep encountering the following problem: CMake uses Apple's Clang instead of GCC
...
Probing the environment ...
-- USE_XSDK_DEFAULTS='FALSE'
-- CMAKE_BUILD_TYPE='RELEASE'
-- BUILD_SHARED_LIBS='FALSE'
-- CMAKE_C_COMPILER_ID='AppleClang'
-- CMAKE_C_COMPILER_VERSION='7.3.0.7030031'
-- CMAKE_CXX_COMPILER_ID='AppleClang'
-- CMAKE_CXX_COMPILER_VERSION='7.3.0.7030031'
...
Despite the fact that I passed gcc/g++ address as an argument in call:
cmake -D CMAKE_C_COMPILER=/usr/bin/gcc -D CMAKE_CXX_COMPILER=/usr/bin/g++ ..
I installed GCC and G++ separately:
$ gcc --version
gcc (GCC) 4.9.2 20141029 (prerelease)
Copyright (C) 2014 Free Software Foundation, Inc.
UPD If anybody's interested, I've given up and moved development to ubuntu. If you find a way to do this, please comment below
When compiler is set explicitely, CMake doesn't try to guess its identification (variables *_COMPILER_ID and *_COMPILER_VERSION.
If you want (and usually you do want) this identification to correctly reflect your compiler, you need to set these variables explicitely too.
For setup several variables describing building environment you may use toolchain files.

Resources