Static linking 64-bit glibc libraries into binary - linker

So maybe this is me exposing my naivety in terms of linking and compiling.
I'm trying to compile some Fortran code such that it can run as a stand alone binary. One issue (among several) is that I want to compile on a system with GLIBC 2.14 but run on one with 2.11. Is it possible to statically link in libraries like GLIBC, or is that impossible because of the library's size?
My Makefile uses -static, -static-libgcc, and -static-libgfortran flags and the following compiler flags
-c -cpp -fall-intrinsics -ffpe-trap=invalid,zero -std=f2003
However, when I use ldd on the output, I get
linux-vdso.so.1 => (0x00007fff13b63000)
libgfortran.so.3 => /usr/lib64/libgfortran.so.3 (0x00007febfd7cf000)
libm.so.6 => /lib64/libm.so.6 (0x00007febfd578000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007febfd362000)
libquadmath.so.0 => /usr/lib64/libquadmath.so.0 (0x00007febfd12c000)
libc.so.6 => /lib64/libc.so.6 (0x00007febfcd9c000)
/lib64/ld-linux-x86-64.so.2 (0x00007febfdae7000)
Update
The machine I'm compiling on is running openSUSE 12.2:
Linux 3.4.33-2.24-desktop #1 SMP PREEMPT x86_64 x86_64 x86_64 GNU/Linux
While the machine I'm trying to execute on is openSUSE 11.4:
Linux 2.6.37.6-24-desktop #1 SMP PREEMPT x86_64 x86_64 x86_64 GNU/Linux
Update 2
I've re-written the makefile, and I'm trying to compile with ifort (the intel compiler) because it provides the static-intel flag which reduces some of the dependencies.
My ldd output is now
linux-vdso.so.1 => (0x00007fff381ff000)
libm.so.6 => /lib64/libm.so.6 (0x00007f89b07cf000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f89b05b2000)
libc.so.6 => /lib64/libc.so.6 (0x00007f89b0222000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f89b001e000)
/lib64/ld-linux-x86-64.so.2 (0x00007f89b0a26000)
Using the following compiler flags
FCFLAGS = -cpp -static-intel -static-libgcc
The problem is if I do just -static (or -static-intel -static) then I get
ld: cannot find -lm
ld: cannot find -lpthread
ld: cannot find -lc
ld: cannot find -ldl
ld: cannot find -lc
make: *** [IDP] Error 1
Which I believe is because I don't have static versions of these libraries on my system
UPDATE 3
I also tried the approach of providing the shared objects in a library (as suggested by [this post])(https://stackoverflow.com/a/3214232/615257) but it just segmentation faults.

This is a common problem. All the later distributions from 2011 onwards do not have static versions of the 64-bit libraries. They ship with the 32-bit versions but not with 64. You just have to use the shared lib versions of libm, libc etc.

Related

Getting "cannot open shared object file" even though ldd shows it can find it

I looked for similar post on this topic but none the solutions work for me. I am trying to build a small program using openssl.
/mnt/sda1/openssl$ gcc tstsvr.c -I/mnt/sda1/openssl/include -L/mnt/sda1/openssl -lcrypto -lssl
When I try to run it:
$ sudo ./a.out
./a.out: error while loading shared libraries: libcrypto.so.81.1.1: cannot open shared object file: No such file or directory
But:
$ ldd a.out
linux-vdso.so.1 (0x00007fff23fe6000)
libcrypto.so.81.1.1 => /mnt/sda1/openssl/libcrypto.so.81.1.1 (0x00007f82f1db9000)
libssl.so.81.1.1 => /mnt/sda1/openssl/libssl.so.81.1.1 (0x00007f82f1d1e000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f82f1b1a000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f82f1b14000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f82f1af1000)
/lib64/ld-linux-x86-64.so.2 (0x00007f82f20ad000)
Format looks fine (inside /mnt/sda1/openssl):
$ file a.out
a.out: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=760dc5f7be4f51f598bab38a0b1eab1a42ef8a68, for GNU/Linux 3.2.0, not stripped
$ file libcrypto.so.81.1.1
libcrypto.so.81.1.1: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=404d1e7ed143383801efbb10ed7914f2cd0858d4, not stripped
$ ldd libcrypto.so.81.1.1
linux-vdso.so.1 (0x00007ffc44b5a000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f1083a8c000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f1083a69000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f1083877000)
/lib64/ld-linux-x86-64.so.2 (0x00007f1083d93000)
Just to make sure, I added path to LD_LIBRARY_PATH as well. Even ran sudo ldconfig. Neither made any difference.
What else can I try?
Per sudoers(5):
By default, the env_reset flag is enabled. This causes commands to be executed with a new, minimal environment.
...
Note that the dynamic linker on most operating systems will remove variables that can control dynamic linking from the environment of set-user-ID executables, including sudo. Depending on the operating system this may include RLD*, DYLD, LD_, LDR_*, LIBPATH, SHLIB_PATH, and others. These type of variables are removed from the environment before sudo even begins execution and, as such, it is not possible for sudo to preserve them.
Your easiest option is probably to do:
sudo LD_LIBRARY_PATH=/mnt/sda1/openssl ./a.out

Including a Boost C++ header causes dlopen() to return error: _ZTVN10__cxxabiv117__class_type_infoE

The C HelloWorld.so (shared object) is created by linking in a C++ myatomic library. That C++ library uses a Boost Header:
myatomic.cpp
...
#include <boost/system/error_code.hpp>
...
Loading HelloWorld.so with dlopen() returns error: _ZTVN10__cxxabiv117__class_type_infoE
If that Boost header is commented-out, then dlopen() succeeds?
HelloWorld.yaml
...
Common:
Sources:
- Folder: src
Files:
- HelloWorld.h
- HelloWorld.c
ConanLibs:
- CONAN_PKG::myatomic
Linux:
CompilerOptions:
- -fPIC
LinkerOptions:
- -lstdc++
Does Boost C++ under linux need to built with specific options? Maybe gcc vs g++ issues?
Added -lstdc++ to HelloWorld linker options but to no avail. :(
A co-worker discovered this fix
If we're interacting with C++ materials (in this case Boost C++), we
need to be using g++. The gcc tool, even if supplied with a bunch of
-lstdc++ args - does not fill the shoes of the g++ compiler, in terms of things like 'linker/loader hints'
The reason for the error _ZTVN10__cxxabiv117__class_type_infoE is the HelloWorld.so (C program) was not loading a runtime dependent (C++ shared object) libstdc++.so.6. For example,
$ ldd HelloWorldBAD.so
linux-vdso.so.1 (0x00007ffc8a5c5000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f78cf21f000)
/lib64/ld-linux-x86-64.so.2 (0x00007f78cf431000)
$ ldd HelloWorldGOOD.so
linux-vdso.so.1 (0x00007ffd53bba000)
libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f2540003000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f253fe11000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f253fcc2000)
/lib64/ld-linux-x86-64.so.2 (0x00007f2540205000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f253fca7000)
Edit
It was also found that the ordering of the -lstdc++ option is important. (see also this link)
This command correctly includes the C++ runtime dependencies by placing the -lstdc++ option at the END of the build command
/usr/bin/cc -fPIC -O2 -g -DNDEBUG -shared -Wl,-soname,HelloWorld.so ...Lots of Boost Libraries... -lstdc++
whereas putting the option BEFORE the Boost libraries does not
/usr/bin/cc -fPIC -O2 -g -DNDEBUG -lstdc++ -shared -Wl,-soname,HelloWorld.so ...Lots of Boost Libraries...

How to link so that pthread_getattr_np will be resolved?

I'm using gcc to build a portable shared object. I'm applying the technique outlined in this answer to ensure that my binary will work on systems with older versions of glibc.
For the symbol pthread_getattr_np, I use
extern "C" {
__asm__(".symver pthread_getattr_np,pthread_getattr_np#GLIBC_2.2.5");
int __wrap_pthread_getattr_np(pthread_t thread, pthread_attr_t* attr) {
return pthread_getattr_np(thread, attr);
}
}
along with the option -Wl,--wrap=pthread_getattr_np to link to a specific portable version. However, pthread_getattr_np recently migrated from libpthread to libc for newer version of glibc. Even though the versioned symbol pthread_getattr_np#GLIBC_2.2.5 is the same, it's defined in a different library.
When I try to load my binary on an older system, I get the error
error: unable to load shared object
symbol pthread_getattr_np version GLIBC_2.2.5 not defined in file libc.so.6 with link time reference
If I run
objdump -T /lib/x86_64-linux-gnu/libpthread.so.0 | grep pthread_getattr_np
0000000000009420 g DF .text 000000000000035e GLIBC_2.2.5 pthread_getattr_np
I see that the symbol is defined in libpthread.so; and if I run ldd on my binary, I see that libpthread is a dependency
linux-vdso.so.1 (0x00007ffec17fc000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fa3725cd000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fa3723c9000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fa37202b000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa371c3a000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa3735dd000)
but the symbol won't resolve correctly.
Is there a way to set up the linking for my shared library so that pthread_getattr_np will resolve to either libpthread or libc depending on where it's defined?

version `libssl.so.10' not found

On Ubuntu 18.04 with apt install I installed libssl1.0.0 and libssl1.0-dev.
The following shared objects are available:
/usr/lib/x86_64-linux-gnu/libssl.so
/usr/lib/x86_64-linux-gnu/libssl.so.1.0.0
/usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0
/usr/lib/x86_64-linux-gnu/libcrypto.so
Set the variable LD_LIBRARY_PATH with the previous path:
$ echo $LD_LIBRARY_PATH
/usr/lib/x86_64-linux-gnu
Created the following symbolic links:
ln -s /usr/lib/x86_64-linux-gnu/libssl.so.1.0.0 /usr/lib/x86_64-linux-gnu/libssl.so.10
ln -s /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0 /usr/lib/x86_64-linux-gnu/libcrypto.so.10
Now this is what I have:
$ file /usr/lib/x86_64-linux-gnu/libssl.so.10
/usr/lib/x86_64-linux-gnu/libssl.so.10: symbolic link to /usr/lib/x86_64-linux-gnu/libssl.so.1.0.0
$ ldd /usr/lib/x86_64-linux-gnu/libssl.so.10
linux-vdso.so.1 (0x00007ffeeaddb000)
libcrypto.so.1.0.0 => /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0 (0x00007f28054fc000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f280510b000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f2804f07000)
/lib64/ld-linux-x86-64.so.2 (0x00007f2805ba7000)
$ file /usr/lib/x86_64-linux-gnu/libssl.so.1.0.0
/usr/lib/x86_64-linux-gnu/libssl.so.1.0.0: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=0d054641049b9747c05d030262295dfdfdd3055d, stripped
$ ldd /usr/lib/x86_64-linux-gnu/libssl.so.1.0.0
linux-vdso.so.1 (0x00007ffff3971000)
libcrypto.so.1.0.0 => /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0 (0x00007f446f2b1000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f446eec0000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f446ecbc000)
/lib64/ld-linux-x86-64.so.2 (0x00007f446f95c000)
So, at this point the dependencies for the library I will use are met.
When I try to validate that, I get issues such as version `libssl.so.10' not found.
$ file libpjsua2.so
libpjsua2.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=9481ccc9a0bbfe937ebb1dbc40002af55c2b424c, not stripped
$ ldd libpjsua2.so
./libpjsua2.so: /usr/lib/x86_64-linux-gnu/libssl.so.10: version `libssl.so.10' not found (required by ./libpjsua2.so)
./libpjsua2.so: /usr/lib/x86_64-linux-gnu/libcrypto.so.10: version `OPENSSL_1.0.1_EC' not found (required by ./libpjsua2.so)
./libpjsua2.so: /usr/lib/x86_64-linux-gnu/libcrypto.so.10: version `libcrypto.so.10' not found (required by ./libpjsua2.so)
linux-vdso.so.1 (0x00007ffc83691000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f0d98395000)
libssl.so.10 => /usr/lib/x86_64-linux-gnu/libssl.so.10 (0x00007f0d9812d000)
libcrypto.so.10 => /usr/lib/x86_64-linux-gnu/libcrypto.so.10 (0x00007f0d97cea000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f0d97ae2000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f0d978c3000)
libasound.so.2 => /usr/lib/x86_64-linux-gnu/libasound.so.2 (0x00007f0d975bc000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f0d9721e000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f0d97006000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0d96c15000)
/lib64/ld-linux-x86-64.so.2 (0x00007f0d98d91000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f0d96a11000)
I would like to highlight that appears somehow it's able to resolve some .so:
libssl.so.10 => /usr/lib/x86_64-linux-gnu/libssl.so.10 (0x00007f0d9812d000)
libcrypto.so.10 => /usr/lib/x86_64-linux-gnu/libcrypto.so.10 (0x00007f0d97cea000)
There is a way for me to fix this? So libpjsua2.so is usable.
The shared library libpjsua2.so is designed for the version of OpenSSL shipped by Red Hat, CentOS, or Fedora, while you're trying to use a version built for Ubuntu. This won't work because the SONAME is different, as well as the symbol versioning.
There isn't any way to make this work, so you'll either need to use a shared library compiled for an Ubuntu (or Debian) system or run your program on the system the shared library was compiled for. Note that both Debian and Ubuntu ship a package called libpjsua2, so installing that may meet your needs.
You could theoretically copy the relevant OpenSSL version from the intended operating system, but doing so will likely involve a bunch of other broken shared libraries, and you will probably not be happy with the result.

Link against different glibc

I installed glibc-2.18 into my home directory and want to link an application against it:
$ g++ -pthread -o tsx_test tsx_test.cpp -Wl,--rpath=/home/hl/lib/ \
-Wl,--dynamic-linker=/home/hl/lib/ld-linux-x86-64.so.2
Compiling and linking works fine using g++4.7.3, however, fails when executing it:
$ ./tsx_test
./tsx_test: error while loading shared libraries: libstdc++.so.6: cannot open shared object file: No such file or directory
/usr/lib/x86_64-linux-gnu/libstdc++.so.6 definitely exists, when I compile without "--rpath" the same libstdc++.so.6 is linked and everything works fine.
$ ldd tsx_test
linux-vdso.so.1 => (0x00007fff42bd4000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f42aa3aa000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f42aa194000)
libpthread.so.0 => /home/hl/lib/libpthread.so.0 (0x00007f42a9f75000)
libc.so.6 => /home/hl/lib/libc.so.6 (0x00007f42a9bc8000)
libm.so.6 => /home/hl/lib/libm.so.6 (0x00007f42a98c5000)
/home/hl/lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007f42aa6c9000)
/usr/lib/x86_64-linux-gnu/libstdc++.so.6 definitely exists
... but your libc doesn't look there.
You can set your RPATH like so: -Wl,-rpath=/home/hl/lib:/usr/lib, or you can edit /home/hl/etc/ld.so.conf and tell your libc to look in /usr/lib (after /home/hl/lib).j
Is it a permission problem, can't I mix root owned and user owned libs?
No. You can definitely mix and match root-owned and user-owned libraries.

Resources