Newly built gcc not being used even after setting $PATH - linux

My server has GCC4 and I need newer version, so I built GCC7.3.0 and added the path to the $PATH variable. After this, gcc -v and g++ -v points to the correct version:
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/users/home/m/GCC-7.3.0/bin/../libexec/gcc/x86_64-pc-linux-gnu/7.3.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /home/m/gccbuild/../srcdir/configure --prefix=/home/m/GCC-7.3.0 --enable-languages=c,c++,fortran,go --disable-multilib
Thread model: posix
gcc version 7.3.0 (GCC)
However, I tried compiling a simple hello.cc program and ldd a.out gives:
linux-vdso.so.1 => (0x00007ffe609bb000)
libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007fa0bff67000)
libm.so.6 => /lib64/libm.so.6 (0x00007fa0bfc65000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007fa0bfa4f000)
libc.so.6 => /lib64/libc.so.6 (0x00007fa0bf681000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa0c026e000)
From here, was expecting something like:
libstdc++.so.6 => /users/home/m/GCC-7.3.0/lib64/libstdc++.so.6 (0x0000123456789000)
libgcc_s.so.1 => /users/home/m/GCC-7.3.0/lib64/libgcc_s.so.1 (0x0000123456ABC000)
Also, cat /proc/version gives:
Linux version 3.10.0-1127.el7.x86_64 (mockbuild#kbuilder.bsys.centos.org) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC) ) #1 SMP Tue Mar 31 23:36:51 UTC 2020
EDIT:
Output to grep configure config.status within gcc build directory:
# Generated by configure.
# Compiler output produced by configure, useful for debugging
# configure, is in config.log if it exists.
configured by /home/s18002/gccbuild/../srcdir/configure, generated by GNU Autoconf 2.64,
ac_configure_extra_args=
ac_configure_extra_args="$ac_configure_extra_args --silent"
set X '/bin/sh' '/home/s18002/gccbuild/../srcdir/configure' '--prefix=/home/m/GCC-7.3.0' '--disable-multilib' '--enable-languages=c,c++,fortran,go,lto' $ac_configure_extra_args --no-create --no-recursion
"L) $$r/$(TARGET_SUBDIR)/libstdc++-v3/scripts/testsuite_flags --build-includes; else echo -funconfigured-libstdc++-v3 ; fi` -L$$r/$(TARGET_SUBDIR)/li"\
S["extra_host_zlib_configure_flags"]=""
S["extra_host_libiberty_configure_flags"]="--enable-shared"
S["extra_linker_plugin_configure_flags"]=""
S["extra_isl_gmp_configure_flags"]="--with-gmp- builddir=$$r/$(HOST_SUBDIR)/gmp"
S["extra_mpc_mpfr_configure_flags"]="--with-mpfr-include=$$s/mpfr/src --with-mpfr-lib=$$r/$(HOST_SUBDIR)/mpfr/src/.libs"
S["extra_mpc_gmp_configure_flags"]="--with-gmp-include=$$r/$(HOST_SUBDIR)/gmp --with-gmp-lib=$$r/$(HOST_SUBDIR)/gmp/.libs"
S["extra_mpfr_configure_flags"]="--with-gmp-include=$$r/$(HOST_SUBDIR)/gmp --with-gmp-lib=$$r/$(HOST_SUBDIR)/gmp/.libs"
S["extra_liboffloadmic_configure_flags"]=""
S["TOPLEVEL_CONFIGURE_ARGUMENTS"]="/home/s18002/gccbuild/../srcdir/configure --prefix=/home/s18002/GCC-7.3.0 --enable-languages=c,c++,fortran,go --disable-multilib"
# Let's still pretend it is `configure' which instantiates (i.e., don't
configure_input='Generated from '`
`' by configure.'
configure_input="$ac_file. $configure_input"
case $configure_input in #(
ac_sed_conf_input=`$as_echo "$configure_input" |
*) ac_sed_conf_input=$configure_input;;
s|#configure_input#|$ac_sed_conf_input|;t t
The package I was trying to install got installed, which means it is using gcc7. How can I make sure GCC7 is used locally for all my purposes?

Make sure you are compiling with g++ and not gcc:
$ gcc test.c
$ ldd a.out
linux-vdso.so.1 => (0x00007ffcbdd71000)
libc.so.6 => /lib64/libc.so.6 (0x00007f3b23c32000)
/lib64/ld-linux-x86-64.so.2 (0x00007f3b24000000)
$ g++ test.c
$ ldd a.out
linux-vdso.so.1 => (0x00007ffedc577000)
libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f745ed73000)
libm.so.6 => /lib64/libm.so.6 (0x00007f745ea71000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f745e85b000)
libc.so.6 => /lib64/libc.so.6 (0x00007f745e48d000)
/lib64/ld-linux-x86-64.so.2 (0x00007f745f07a000)

Related

Circular reference between libc.so.6 and liblsp.so?

▶ldd /lib/x86_64-linux-gnu/libc.so.6
linux-vdso.so.1 (0x00007fff2b856000)
/lib/$LIB/liblsp.so => /lib/lib/x86_64-linux-gnu/liblsp.so (0x00007f472effc000)
/lib64/ld-linux-x86-64.so.2 (0x00007f472f3f5000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f472efd5000)
▶ldd /lib/lib/x86_64-linux-gnu/liblsp.so
linux-vdso.so.1 (0x00007ffe305ee000)
/lib/$LIB/liblsp.so => /lib/lib/x86_64-linux-gnu/liblsp.so (0x00007f28eea81000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f28eea5a000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f28ee868000)
/lib64/ld-linux-x86-64.so.2 (0x00007f28eee8d000)
We can find a circular reference between libc.so.6 and liblsp.so. How does it works?
How does it works?
libc.so.6 doesn't really depend on liblsp.so. You can verify this with readelf -d /lib/x86_64-linux-gnu/libc.so.6 | grep NEEDED.
The reason ldd shows it is that it's listed in your /etc/ld.so.preload.
As Nate Eldredge commented, this "cycle" doesn't matter -- the loader needs to load dependent libraries which aren't already loaded. If a library is already loaded, the loader simply increments its reference count.

How do I diagnose why a shared library is not found?

I am trying to run an app which is linked against libboost_system.so
$ ./app
app: error while loading shared libraries: libboost_system.so.1.63.0: cannot open shared object file: \
No such file or directory
If I run ldd on the app, it shows it can't find the library:
$ ldd ./app
linux-vdso.so.1 (0x00007ffdedb94000)
libboost_system.so.1.63.0 => not found
libpcap.so.1 => /lib64/libpcap.so.1 (0x00007f19a1a7b000)
librt.so.1 => /lib64/librt.so.1 (0x00007f19a1a70000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f19a1a69000)
libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f19a1879000)
libm.so.6 => /lib64/libm.so.6 (0x00007f19a1733000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f19a1716000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f19a16f4000)
libc.so.6 => /lib64/libc.so.6 (0x00007f19a152a000)
/lib64/ld-linux-x86-64.so.2 (0x00007f19a1ae5000)
The library is present on my system:
$ locate libboost_system.so.1.63.0
/usr/local/lib/libboost_system.so.1.63.0
$ ls -la /usr/local/lib/libboost_system*
-rw-r--r--. 1 root root 47014 Jul 2 16:57 /usr/local/lib/libboost_system.a
lrwxrwxrwx. 1 root root 25 Jul 2 16:57 /usr/local/lib/libboost_system.so -> libboost_system.so.1.63.0
-rwxr-xr-x. 1 root root 19816 Jul 2 16:57 /usr/local/lib/libboost_system.so.1.63.0
ld is configured with /usr/local/lib:
$ ld --verbose | grep SEARCH_DIR | sed 's/; /\n/g'
SEARCH_DIR("=/usr/x86_64-redhat-linux/lib64")
SEARCH_DIR("=/usr/lib64")
SEARCH_DIR("=/usr/local/lib64")
SEARCH_DIR("=/lib64")
SEARCH_DIR("=/usr/x86_64-redhat-linux/lib")
SEARCH_DIR("=/usr/local/lib") <----- here
SEARCH_DIR("=/lib")
SEARCH_DIR("=/usr/lib")
I've also run ldconfig to refresh the cache, but that doesn't help.
I tried searching for RPATH or RUNPATH with readelf, neither are specified:
$ readelf -d ./app | grep -i path
< no results >
If I explicitly set LD_LIBARY_PATH then the library is found:
$ LD_LIBRARY_PATH=/usr/local/lib ldd ./app
linux-vdso.so.1 (0x00007fffa9a5d000)
libboost_system.so.1.63.0 => /usr/local/lib/libboost_system.so.1.63.0 (0x00007f5fff664000)
libpcap.so.1 => /lib64/libpcap.so.1 (0x00007f5fff5fc000)
librt.so.1 => /lib64/librt.so.1 (0x00007f5fff5f1000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f5fff5ea000)
libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f5fff3fa000)
libm.so.6 => /lib64/libm.so.6 (0x00007f5fff2b4000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f5fff297000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f5fff275000)
libc.so.6 => /lib64/libc.so.6 (0x00007f5fff0ab000)
/lib64/ld-linux-x86-64.so.2 (0x00007f5fff66b000)
Why can't ld find libboost_system.so.1.63.0 without specifying LD_LIBRARY_PATH?
You are looking at the "wrong" linker. ld is the static linker and isn't what's used by at runtime to locate the shared libraries.
The dynamic linker, ld.so, is what locates shared libraries.
The dynamic linker does look at the LD_LIBRARY_PATH and that's why it works if you set it.
If you want to update the search locations for dynamic linker (and not want to set LD_LIBRARY_PATH), you can create a file in /etc/ld.so.conf.d/ and update /etc/ld.so.cache with ldconfig.
The diagnostic is activated by LD_DEBUG (cf. man ld.so):
LD_DEBUG=libs ./a.out
It shows the search paths that the loader tried: ($LD_LIBRARY_PATH, R[UN]PATH from the app or library's ELF, ld.so.cache).
Its output is a little long to copy here, but would look like this:
265: find library=libboost_system.so.1.63.0 [0]; searching
265: search path= [...] (LD_LIBRARY_PATH)
[trying many files...]
265: search path= [...] (RUNPATH from file ./app)
[still trying many files...]
265: search cache=/etc/ld.so.cache
[still trying many files...]
In your case, you'd probably have seen that /usr/local/lib was not in the cache. Depending on the distribution, it may look by default in /usr/local/lib/x86_64-linux-gnu or /usr/local/lib64 or none at all.

Linking: Why does linker not honour symlink to library?

I have the following C program:
#include <stdio.h>
#include <zlib.h>
int main()
{
z_stream strm;
int integer = 0;
scanf("heloworld %d", &integer);
printf("ok\n");
if (integer == 10)
{
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
deflateInit(&strm, 0);
}
return 0;
}
This is a basic helloworld program which uses zlib.
If I search for the libz library, I can find it under /usr/lib/x86_64-linux-gnu/libz.so:
$ ls -lah libz.so
lrwxrwxrwx 1 root root 40 May 20 14:55 libz.so -> /usr/lib/x86_64-linux-gnu/libz.so.1.2.11
and it is pointing to the real version of libz rather than the soname.
I compile it with the following command and check the dependencies:
$ gcc a.c -lz
$ ldd a.out
linux-vdso.so.1 (0x00007ffec44b6000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f6674055000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f6673e63000)
/lib64/ld-linux-x86-64.so.2 (0x00007f667408c000)
How is it pointing to libz.so.1 instead of libz.so.1.2.11 (realname) since the symlink of libz.so.1 is pointing there? I am assuming that the linker is using the symlink however this is not the case.
Further to this, if I perform the following command:
$ objdump -p libz.so.1.2.11 | grep SONAME
SONAME libz.so.1
My question is, is it using the symlink name or the SONAME from the file the symlink provides?
If the linker put libz.so.1.2.11 in your executable, then it would break when you updated the library. Instead it puts the major version known to ldconfig in the executable, which is in turn a link to the current installed version.
See ldconfig http://man7.org/linux/man-pages/man8/ldconfig.8.html
I have discovered that under /lib/x86_64-linux-gnu there are two symlinks for libz.so which are:
libz.so
libz.so.1
When I compile, the linker uses the libz.so as a symlink to point to another .so file.
The .so file which libz.so is pointing to contains an SONAME entry which can be viewed as so:
$ objdump -p ./libz.so | grep SONAME
SONAME libz.so.1
Further I can see that the symlink points to libz.so.1.2.11
$ ls -alh libz.so
lrwxrwxrwx 1 root root 36 May 21 00:51 libz.so -> /lib/x86_64-linux-gnu/libz.so.1.2.11
If I edit the .dynstr section of that library like so:
$ sudo objcopy --dump-section .dynstr=/tmp/dyn.dump ./libz.so.1.2.11
# Find the bytes for libz.so.1 and change them to libz.so.2
$ hexedit /tmp/dyn.dump
$ sudo objcopy --update-section .dynstr=/tmp/dyn.dump ./libz.so.1.2.11
and then recompile my binary I notice:
$ ldd a.out
linux-vdso.so.1 (0x00007ffe54bbe000)
libz.so.2 => not found
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f58bb5c7000)
/lib64/ld-linux-x86-64.so.2 (0x00007f58bb7f0000)
Once I create a symlink of libz.so.2 under /lib/x86_64-linux-gnu/libz.so.2 to point to libz.so.1.2.11 I get the following output:
$ ldd a.out
linux-vdso.so.1 (0x00007ffe54bbe000)
libz.so.2 => /lib/x86_64-linux-gnu/libz.so.2 (0x00007f58bb7b9000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f58bb5c7000)
/lib64/ld-linux-x86-64.so.2 (0x00007f58bb7f0000)
Therefore to answer my question it is not the symlink which adds an entry in the runtime dependencies of the executable but the SONAME entry in the shared object.

Why won't my compiled c++ binary execute?

So I have just compiled my code and when I try to execute the binary I am getting
-bash: ./a.out: No such file or directory
When I do ldd a.out I see everything is there that I need
ldd a.out
linux-vdso.so.1 (0x00007ffd337fb000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f1200930000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f1200728000)
libncurses.so.5 => /lib/x86_64-linux-gnu/libncurses.so.5 (0x00007f1200505000)
libtinfo.so.5 => /lib/x86_64-linux-gnu/libtinfo.so.5 (0x00007f12002db000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f12000d7000)
libcap.so.2 => /lib/x86_64-linux-gnu/libcap.so.2 (0x00007f11ffed1000)
libnsl.so.1 => /lib/x86_64-linux-gnu/libnsl.so.1 (0x00007f11ffcb7000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f11ff919000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f11ff6fa000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f11ff309000)
/usr/lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007f1200b4d000)
Also doing an ls -la shows the file as such
lrwxrwxrwx 1 user user 33 Jul 18 21:26 a.out
Does anyone have any reason why this isn't working?
I am using Ubuntu 18.04.2 LTS.
When I do ldd a.out I see everything is there that I need
No, there isn't.
ldd has been changed to run a known ELF interpreter / dynamic linker instead of the one from the binary's header. You can check that by yourself -- ldd is a shell script on your system.
ldd a.out
...
/usr/lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2
And here it's the proof. Do you have a /usr/lib/ld-linux-x86-64.so.2 on your system?
A simpler testcase:
$ echo 'int main(){}' | cc -xc -
$ ./a.out
$ perl -pe 's/ld-linux/ld-LOOOL/' -i ./a.out
$ ./a.out
bash: ./a.out: No such file or directory
$ ldd ./a.out
linux-vdso.so.1 (0x00007ffd707e9000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe936d52000)
/lib64/ld-LOOOL-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007fe9372f3000)
As a quick-fix, you can pass the path to an existing interpreter when compiling your program
cc -Wl,-dynamic-linker,/lib64/ld-linux-x86-64.so.2 ...

"No such file or directory" error when running a dynamically-linked ARM executable

I am cross-compiling for an ARM embedded Linux platform running Ubuntu 15.04. Previous, statically-linked, versions of this program have run just fine. Recently I needed to link in libproprietary (lib name changed for this question), which is only available as an .so.
libproprietary.so works; I am able to run a different program that depends on it.
$ uname -a
Linux <hostname> 3.10.92-71 #1 SMP PREEMPT Fri Dec 18 00:38:54 BRST 2015 armv7l armv7l armv7l GNU/Linux
The problem:
$ ./myprogram
-bash: ./myprogram: No such file or directory
What I've tried:
$ ldd ./myprogram
libproprietary.so.2 => /usr/lib/libproprietary.so.2 (0xb6bbc000)
librt.so.1 => /lib/arm-linux-gnueabihf/librt.so.1 (0xb6ba6000)
libpthread.so.0 => /lib/arm-linux-gnueabihf/libpthread.so.0 (0xb6b92000)
libusb-1.0.so.0 => /lib/arm-linux-gnueabihf/libusb-1.0.so.0 (0xb6b72000)
libstdc++.so.6 => /usr/lib/arm-linux-gnueabihf/libstdc++.so.6 (0xb6ab8000)
libm.so.6 => /lib/arm-linux-gnueabihf/libm.so.6 (0xb6a43000)
libc.so.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0xb6955000)
/usr/lib/ld.so.1 => /lib/ld-linux-armhf.so.3 (0xb6f28000)
libgcc_s.so.1 => /lib/arm-linux-gnueabihf/libgcc_s.so.1 (0xb692c000)
libudev.so.1 => /lib/arm-linux-gnueabihf/libudev.so.1 (0xb690f000)
$ file ./myprogram
./myprogram: ELF 32-bit LSB executable, ARM, EABI5 version 1 (GNU/Linux), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=881d76b2ce20f32aef95796b4fee9f01e492a7d2, not stripped
$ file /bin/ls
/bin/ls: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=a687c2baf9963c62c6abd209863d360dd0863686, stripped
$ readelf -l myprogram| grep interpreter
[Requesting program interpreter: /usr/lib/ld.so.1]
$ strace ./myprogram
execve("./myprogram", ["./myprogram"...], [/* 21 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 +++
$ ls -l myprogram
-rwxrwxr-x [details snipped]
$ file /usr/lib/libproprietary.so.<version>
/usr/lib/libproprietary.so.<version>: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, BuildID[sha1]=d9b4ba3b9ec03779792984bc8a89ceede5737455, stripped
It appears that the interpreter, /usr/lib/ld.so.1, does not exist. I'm going to guess that it should be similar to what /bin/ls is using:
$ readelf -l /bin/ls | grep interpreter
[Requesting program interpreter: /lib/ld-linux-armhf.so.3]
I don't know how to fix this in my link step however.
ccache arm-linux-gnueabihf-g++ -o myprogram -static -Wl,--whole-archive -lpthread -Wl,--no-whole-archive -Wl,-no-undefined -pthread -Wl,-Bdynamic -lproprietary -Wl,-rpath-link=result/debug/lib -Wl,-rpath=\$ORIGIN/../../../../result/debug/lib variant-dir/debug/core-.o -Lresult/debug/lib -Wl,-Bstatic -l<other libs>
I did try moving -Wl,-Bdynamic -lproprietary after the core-.o word, but that didn't change anything.
It appears that the interpreter, /usr/lib/ld.so.1, does not exist. I'm going to guess that it should be similar to what /bin/ls is using:
Correct. You could change the interpreter by adding -Wl,--dynamic-linker=/lib/ld-linux-armhf.so.3 flag at link time.
However,
Your toolchain may be targeting a different version of libc from the one you actually have installed (in which case the program will likely crash).
If it is targeting correct libc, then your toolchain is mis-configured.

Resources