When GCC links a shared library is the soname stored? - gcc

If you compile and link in a shared library does it store the soname of the library somewhere in the binary so it knows which one to link to? In other words if I link against a version 1.0.0 of liba.so and then I update my library to 2.0.0 and the ABI/API has changed and now my sym link to liba.so is pointing to the 2.0.0 version will the binary still know to look at liba.so.1? In other words does it store the specific soname of the linked library in the binary

Yes, you can use ldd to view the dependency of a binary.
Try ldd /bin/bash yourself
On my machine it prints
linux-vdso.so.1 => (0x00007fff10dff000)
libncurses.so.5 => /lib/libncurses.so.5 (0x00007f2237acb000)
libdl.so.2 => /lib/libdl.so.2 (0x00007f22378c7000)
libc.so.6 => /lib/libc.so.6 (0x00007f2237564000)
/lib64/ld-linux-x86-64.so.2 (0x00007f2237d25000)

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.

How to compile static racket binaries

raco exe makes dynamic executables, and raco distribute doesn't change that:
$ ldd ./tst
linux-vdso.so.1 (0x00007ffc9ed46000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fbeb4c09000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fbeb4a18000)
/lib64/ld-linux-x86-64.so.2 (0x00007fbeb4c67000)
On windows, it looks like one can --embed-dlls, which is kindof what I want, but for all platforms.
I'd like to compile statically for ease of distribution and deployment. Is this possible?

Linking libs into a binary in order to make it static on most of linux environment

I am currently searching for a way to make a binary that I just compiled, a portable binary for most of all linux environment. I was considering Ermine but it's not free (looking for a free solution right now) and tried also with Statifier but didn't work either. Here is the details on the binary I am trying to make static and portable:
sirius#blackb0x:~/MINING/ARIONUM/ariominer/build$ ldd /home/sirius/MINING/ARIONUM/ariominer/build/ariominer
linux-vdso.so.1 => (0x00007fff692fe000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fdfee979000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fdfee775000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fdfee45f000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fdfee159000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fdfedf42000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fdfedb79000)
/lib64/ld-linux-x86-64.so.2 (0x00007fdfeeb97000)
If some could tell me how exactly to link all the libs to the binary so it could run easy on all or almost all linux env (2.6.18 kernels to latest) it would be very appreciated.
Thanks
Rebuild the program and its dependencies from source (while having LIBS set to -static), and make sure to pass --enable-static --disable-shared to their configure scripts.
If that doesn't work, just compile it on a very old machine and provide binaries for glibc and musl.

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.

gcc - A static library with undefined symbols?

I'm trying to build a project using a static library, so that the binary can be used even if the library isn't installed. However, I get lots of errors about undefined symbols when I try to do so.
Looking at the library, I see it has tons of undefined symbols, even though it's a .a static lib:
nm - u /usr/local/lib/libthis.a
....
U EVP_DigestFinal_ex
U EVP_DigestInit_ex
U EVP_DigestUpdate
U EVP_MD_CTX_cleanup
U EVP_MD_CTX_init
Those seem to be from openssl; others seem to be from libbzip2; etc.
Questions:
1. Why does the static (.a) lib have dependencies on shared objects (e.g. libopenssl) that aren't statically compiled?
2. How do I solve this? Trying to manually add -lssl doesn't seem to work. How do I get the binary to compile and not have external dependcies?
Why does the static (.a) lib have dependencies on shared objects (e.g. libopenssl) that aren't statically compiled?
Just about every static library that you can build will have unresolved symbols, e.g.
int my_open_for_read(const char *filename)
{
return open(filename, O_RDONLY); // unresolved reference to open
}
As Marc Glisse pointed out, this a plain unresolved symbol, not a dependency on libc.so.
How do I solve this?
There is no problem to solve here. When you link your binary, you get to decide which libraries to link statically, and which to link dynamically.
Trying to manually add -lssl doesn't seem to work.
This should work:
gcc main.o -lthis -lssl
Possibly you did something like
gcc main.o -lssl -lthis
which is wrong: the order of libraries on the link line matters.
How do I get the binary to compile and not have external dependcies?
Most OSes support using fully-static binaries. Generally this should not be your goal: it makes for less portable binaries, and their use is strongly discouraged.
If you really do want to produce a fully-static binary, link it with -static flag.
Why do you say full static is less portable?
Because they are.
if the user doesn't have the exact same build of the lib, the binary won't be portable with shared libs, but will be portable with static.
This is incorrect: most shared libraries support backward compatibility, e.g. libc.so.6 version 2.22 will happily run executables linked against version 2.3.6 from 10 years ago.
If you do ldd firefox
You need to pay attention to what you are doing:
file -L `which /usr/bin/firefox`
/usr/bin/firefox: POSIX shell script, ASCII text executable
If you look inside the shell script, you'll discover that it invokes /usr/lib/firefox/firefox, and that binary is dynamically linked:
ldd /usr/lib/firefox/firefox
linux-vdso.so.1 => (0x00007ffca278d000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f511731b000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f5117117000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f5116e13000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f5116b0d000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f51168f7000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5116532000)
/lib64/ld-linux-x86-64.so.2 (0x00007f5117757000)

Resources