gdb uses wrong library, but sysroot declared - debugging

I run a cross debug session with GDB. GDB is configured with option --with-sysroot, how described in the docs. My Application uses shared libraries like the following.
Code:
libpthread.so.0 => /lib/libpthread.so.0 (0x40026000)
libm.so.6 => /lib/libm.so.6 (0x40046000)
libdl.so.2 => /lib/libdl.so.2 (0x400b9000)
librt.so.1 => /lib/librt.so.1 (0x400c4000)
libts-0.0.so.0 => /usr/lib/libts-0.0.so.0 (0x400d3000)
libfreetype.so.6 => /usr/lib/libfreetype.so.6 (0x4015f000)
libz.so.1 => /usr/lib/libz.so.1 (0x401d3000)
libjpeg.so.8 => /usr/lib/libjpeg.so.8 (0x401ee000)
The libraries pthread, libdl, ... are found in my toolchain, declared by set sysroot, --with-sysroot and set solib-absolute-path
The libraries libts, libz, ... are available in my additional path for shared libraries, declared in session with set solib-search-path
For the libraries libfreetype, libjpeg the following error occurs:
102,416 &"warning: `/usr/lib/libfreetype.so.6': Shared library architecture unknown is not compatible with target architecture arm.\n"
102,416 =library-loaded,id="/usr/lib/libfreetype.so.6",target-name="/usr/liblibfreetype.so.6",host-name="/usr/lib/libfreetype.so.6",symbols-loaded="0",thread-group="i1"
The reason GDB still takes libraries of host rootfs, once not found in the toolchain, and available in host rootfs. It doesn't care about my additional path declared with set solib-search-path
I configured GDB with --with-sysroot, declared additional set sysroot, set solib-search-path, set solib-absolute-path (nevermind alias of set sysroot).
In the docu, --prefix configures GDB to take the sysroot autmatically, but why this is higher prior than --with-sysroot?
Is GDB using the order sysroot, host-sysroot, solib-search-path?
What i missed to tell GDB, not to use the host rootfs?

There is a gdb bug tracking the very same issue http://sourceware.org/bugzilla/show_bug.cgi?id=13989
It is not fixed until version gdb-7.4. So, I think this behavior is expected with previous versions.

Related

Use shared library that uses glibc on AlpineLinux

I'm working on an AlpineLinux (installed on my computer, not into a docker) and I'm trying to use a shared library which depends on glibc.
As Glibc isn't integrated into this distribution, I saw that an alternative, gcompat, was developed to provide a compatiblity with programs that were built for Glibc.
The library I want to use is the IDS Imaging's driver (for their camera).
When loading dynamically the .so with CDLL (from a python script), it fails.
After this fail, I ran ldd libueye_api.so to check if all dependencies were found and I got :
/lib/ld-musl-x86_64.so.1 (0x7fb685c50000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x7fb684d93000)
librt.so.1 => /lib/ld-musl-x86_64.so.1 (0x7fb685c50000)
libdl.so.2 => /lib/ld-musl-x86_64.so.1 (0x7fb685c50000)
libpthread.so.0 => /lib/ld-musl-x86_64.so.1 (0x7fb685c50000)
libgomp.so.1 => /usr/lib/libgomp.so.1 (0x7fb684d51000)
libm.so.6 => /lib/ld-musl-x86_64.so.1 (0x7fb685c50000)
libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x7fb684d38000)
libc.so.6 => /lib/ld-musl-x86_64.so.1 (0x7fb685c50000)
ld-linux-x86-64.so.2 => /lib/ld-linux-x86-64.so.2 (0x7fb684d32000)
Error relocating libueye_api.so: __pthread_register_cancel: symbol not found
Error relocating libueye_api.so: __pthread_unregister_cancel: symbol not found
In this log I see that musl and gcompat were successfully found but __pthread_register_cancel and __pthread_unregister_cancel were not found...
Someone has an idea to solve this issue ?
AlpineLinux uses MUSL instead of GLIBC. MUSL is lighter and doesn't drag a legacy with it. This is a problem when applications depend on the legacy, like when they want to use pthread.
AlpineLinux has a wiki that describes 4 alternatives for running applications that require GLIBC.
https://wiki.alpinelinux.org/wiki/Running_glibc_programs
One of the options is to use the gcompat package from a community contribution. The APK package, description and other details are on the pkgs pages
https://pkgs.alpinelinux.org/packages?name=gcompat&branch=edge&repo=community&arch=x86_64
In the APKBUILD file it shows where the source code come from and the pthread in the compat lib does not have __pthread_register_cancel. In your stacktrace I don't see any reference to /lib/libgcompat.so.0, so maybe the library still needs to be found, by running ldconfig, but I think gcompat does not contain all pthread methods. It just isn't in the code
https://git.adelielinux.org/adelie/gcompat/-/blob/current/libgcompat/pthread.c
I vaguely remember that I once installed GLIBC packages in AlpineLinux, but that may just have been one of my crazy dreams, I can't find such package in the repositories
What I do find is an APK and Docker image by Sasha Gerrand, who created a full GLIBC 2.34 library for AlpineLinux. If you install the APK package or use the Docker image, you should have a full glibc running on AlpineLinux.
https://github.com/sgerrand/alpine-pkg-glibc
Personally I would try to avoid running applications that are so library dependent, but I understand it sometimes isn't a choice to switch to something more flexible.

Asan : Issue with asan library loading

In our build system we have recently integrated ASAN tool (adding -fsanitize=address) to CFLAGS & also while linking , creating library .so files.
Note:- We are using GCC 6.3 compiler.
We are able to successfully build our code. But while running it fails with following issue:
==52215==ASan runtime does not come first in initial library list; you should either link runtime to your application or manually preload it with LD_PRELOAD.
Here is my gcc command:-
/local/common/pkgs/gcc/v6.3.0/bin/gcc -m32 -shared -o /local/testing/build/new_tool/asan_build/syn/verilog/libspd.so -Wl,-rpath=\$ORIGIN/lib -Wl,-rpath=\$ORIGIN/../lib -W1,-rpath=/local/common/gcc/v6.3.0/lib -fsanitize=address -L/local/testing/build/new_tool/asan_build/modules /local/testing/build/new_tool/asan_build/modules/silvpi.o /local/testing/build/new_tool/asan_build/modules/sypsv.o /local/testing/build/new_tool/asan_build/modules/cdnsv_tfs.o /local/testing/build/new_tool/asan_build/modules/libcore.o /local/testing/build/new_tool/asan_build/modules/vpi_user.o /local/testing/build/new_tool/asan_build/modules/libdenbase.a /local/testing/build/new_tool/asan_build/modules/libbdd.a -L/local/testing/build/new_tool/asan_build/syn/lib -L/local/testing/build/new_tool/asan_build/modules -L/home/local/outer/Linux/lib /local/testing/build/new_tool/asan_build/modules/vhpimodelfunc.o /local/testing/build/new_tool/asan_build/modules/vipcommonlib.a -lm -lc -ldenbase -lbdd -ldenbase -lviputil -llocalCommonMT_sh
I am able to build library libspd.so successfully. But when we try to run it fails with above error i mentioned.
i can see the dependent library list of libspd.so
ldd /local/testing/build/new_tool/asan_build/syn/verilog/libspd.so
linux-gate.so.1 => (0x00279000)
libasan.so.3 => /local/pkgs/gcc/v6.3.0/lib/libasan.so.3 (0xf7175000)
libm.so.6 => /lib/libm.so.6 (0x0014e000)
libc.so.6 => /lib/libc.so.6 (0xf6f83000)
libcdsCommonMT_sh.so => /local/testing/build/new_tool/asan_build/verilog/../lib/liblocalCommonMT_sh.so (0x00178000)
libdl.so.2 => /lib/libdl.so.2 (0x00197000)
We are trying to run our application with 'xrun' where it runs simulation on top of my build which was build with asan.
As error says : you should either link runtime to your application i was trying to add my complete asan library path to LD_LIBRARY_PATH, Still facing the same issue.
Not sure whats going wrong here. How can i resolve this issue?
Any idea? Thanks and regards!
You have several ways to work around this:
build main executable with -fsanitize=address
get rid of /etc/ld.so.preload on your test machine
disable the check (need recent GCC) with export ASAN_OPTIONS=verify_asan_link_order=0; but you have to be sure that libraries from /etc/ld.so.preload do not intercept symbols important for Asan e.g. malloc, free, etc., otherwise things will start breaking

Go build with another glibc

I have installed another version of GLIBC and want to compile Golang code against this new GLIBC.
I have tried the following command for dynamic compilation:
go build --ldflags '-linkmode external -L /path/to/another_glibc/
But when I run ldd "go_executable", it still shows linked to default glibc.
Output:
linux-vdso.so.1 => (0x00007fff29da7000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f128a93c000)
/lib64/ld-linux-x86-64.so.2 (0x00007f128ad06000)
Expected Output:
linux-vdso.so.1 => (0x00007fff45fa7000)
libc.so.6 => /another_glibc/lib/libc.so.6 (0x00007f5cd2067000)
/another_glibc/ld-2.29.so => /lib64/ld-linux-x86-64.so.2 (0x00007f5cd2420000)
What is missing here?
This is not an answer to the question, just a warning:
If you, like me, came here because you were compiling to deploy on another machine and got "version `GLIBC_2.32' not found" (or similar), but you were not intentionally using CGo, stop here.
Go on Linux dynamically links C libraries to have faster and smaller builds, but it is able to supplement them for example when cross-compiling.
You can do export CGO_ENABLED=0 to disable CGo and get rid of the dependencies.
Before doing go build
Set
CGO_LDFLAGS
Dynamic:
export CGO_LDFLAGS="-Xlinker -rpath=/path/to/another_glibc/lib"
Static:
export CGO_LDFLAGS="-Xlinker -rpath=/path/to/another_glibc/lib -static"
CGO_LDFLAGS lets you set GCC-like ld flags for Go.
bitbyter's answer is not correct for the dynamic case because it requires that the system dynamic linker is compatible with the non-system glibc, which is unlikely. You can set the dynamic linker like this:
export CGO_LDFLAGS="-Xlinker -rpath=/path/to/another_glibc/lib64"
CGO_LDFLAGS="$CGO_LDFLAGS -Xlinker --dynamic-linker="/path/to/another_glibc/lib64/ld-linux-x86-64.so.2"
The dynamic linker name is specific to the architecture, so you have to research its name.

Static linking against openmp

I am building a shared object on Ubuntu 16.04 which uses libgomp. My goal is to make this final object as portable as possible, by static linking anything not normally in a base distribution (using docker ubuntu or alpine images as a reference baseline). I've been able to do this with my other dependencies pretty easily, but I'm hung up on libgomp.
I can link just fine with the -fopenmp option, and get a dynamic link:
# ldd *.so
linux-vdso.so.1 => (0x00007fff01df4000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f9ba59db000)
libgomp.so.1 => /usr/lib/x86_64-linux-gnu/libgomp.so.1 (0x00007f9ba57b9000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f9ba55a3000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f9ba5386000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f9ba4fbc000)
/lib64/ld-linux-x86-64.so.2 (0x00007f9ba6516000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f9ba4db8000)
But if I naively add -static before -fopenmp I get:
relocation R_X86_64_32 against `__TMC_END__' can not be used when making a shared object; recompile with -fPIC
Fair enough; with my other dependencies I've just built from source to enable PIC and any other options I needed. When I try to do the same with libgomp, though, I'm not having any luck. I checked out gcc 5.5 from http://gcc.gnu.org/svn/gcc, and tried building from the gcc/libgomp folder. There is a configure script already generated, but running it returns:
./config.status: line 1486: ./../../config-ml.in: No such file or directory
OK, apparently this has something to do with multilibrary support, which I don't believe I need. Running ./configure --help shows that there is an --enable-multilib option with no obvious default, but setting --enable-multilib=no or --disable-multilib still returns the same error. I've also tried running autoreconf -fiv to regenerate the configure script, but I get this error:
configure.ac:5: error: Please use exactly Autoconf 2.64 instead of 2.69.
If I explicitly install and use autoreconf2.64, I get this one:
configure.ac:65: error: Autoconf version 2.65 or higher is required
What am I missing?
What I was missing was the fact that libgomp is not buildable separate from the rest of gcc. It was just a matter of going up a level and running the whole build with -fPIC enabled:
export CFLAGS="-O3 -fPIC"
export CXXFLAGS="-O3 -fPIC"
./configure --disable-multilib --enable-languages=c,c++
make
make install
That gave me a copy of libgomp.a in /usr/local/lib64 ready for linking in to my shared object.
Follow up:
While this worked, at least in a test environment, after the comments above from Jim Cownie we decided to just disable OpenMP support from our library for now.

Why does setting LD_LIBRARY_PATH change the shared library dependencies?

I have a simple hello_world.cpp program. I compiled it using g++4.4.7 on a CentOS 6.6 system. When I look at ldd a.out:
linux-vdso.so.1 => (0x00007fffbd79e000)
libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00002ab6f6819000)
libm.so.6 => /lib64/libm.so.6 (0x00002ab6f6b1f000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00002ab6f6da4000)
libc.so.6 => /lib64/libc.so.6 (0x00002ab6f6fba000)
/lib64/ld-linux-x86-64.so.2 (0x00002ab6f65f7000)
When I load a module for gcc-4.9.2, LD_LIBRARY_PATH is set to /path/to/gcc-4.9.2/lib64 and running ldd a.out yields :
linux-vdso.so.1 => (0x00007ffff9393000)
libstdc++.so.6 => /path/to/gcc-4.9.2/lib64/libstdc++.so.6 (0x00002b2b7c104000)
libm.so.6 => /lib64/libm.so.6 (0x00002b2b7c435000)
libgcc_s.so.1 => /path/to/gcc-4.9.2/lib64/libgcc_s.so.1 (0x00002b2b7c6b9000)
libc.so.6 => /lib64/libc.so.6 (0x00002b2b7c8cf000)
/lib64/ld-linux-x86-64.so.2 (0x00002b2b7bee2000)
QUESTION : Why is the 4.9.2 version of the gcc libraries used when LD_LIBRARY_PATH is set, even though I compiled with with 4.4.7?
This seems to pose a problem of knowing which version of a library is being used. A user may compile a program with one compiler version, load a different compiler versions (via module) and then run the executable which uses a different library version than expected.
I don't know whether you're aware that the use of Environment Modules
is not a necessary or normal part of using GCC, or even using multiple versions of GCC.
Setting LD_LIBRARY_PATH to override the system dynamic linker's default directory search order
is a practice that has been long and loudly censured, for reasons that include the
one expressed in the last paragraph of your post. See e.g. Gurus say that LD_LIBRARY_PATH is bad
Doing so within environment modules in a system tailored for the use of multiple versions of tools or toolchains
can be regarded as a regulated application of a hazardous practice. In that context, however, the
setting of LD_LIBRARY_PATH in your gcc-4.9.2 environment module is doing exactly what
such a setting is supposed to do: overriding the
dynamic linker's default directory search order. See the documentation: 3.3.1.
In principle it is possible that a program compiled and linked with an older or
later version of GCC would behave unexpectedly if you choose to run it in the
environment of the gcc-4.9.2 module. Environment modules are a niche convenience,
and they come with this risk. Although if you built the program in the native
environment, or specifically in a module-enabled environment for gcc 4.4.7, then
the risk attendant on running it in your gcc-4.9.2 environment is presumably one
that you don't have to take.

Resources