install the glibc into a separate directory, but the so is still linked into the sys so - glibc

I make and install the glibc into a separate directory using the following commands:
[root#yf-sdc-cf06 glibc]# pwd
/home/work/glibc
[root#yf-sdc-cf06 glibc]# /home/work/glibc-2.12.2/configure --prefix=/home/work/glibc
[root#yf-sdc-cf06 glibc]# make
[root#yf-sdc-cf06 glibc]# make install
But
[root#yf-sdc-cf06 glibc]# ldd lib/libc.so.6
/home/work/glibc/lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007fe7f6aba000)
linux-vdso.so.1 => (0x00007fff6a7d4000)
why is the lib/libc.so.6 linked into /lib64/ld-linux-x86-64.so.2 (the system's so) instead of the ld-linux-x86-64.so.2 that is generated by the install?
Any ideas? Thank you!

The ldd searches the library path to find the right candidate of ld-linux-x86-64.so.2, please try to do the following things:
vim /etc/ld.so.conf
add your lib into this file
ldconfig
You might see the new libc is using your ld-linux-x86-64.so.2
BTW:
Please make your question more readable for human.

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.

Why does the program which is compiled against the installed glibc not run normally?

Thanks in advance.
my development environment:
$ cat /proc/version
Linux version 5.4.0-66-generic (buildd#lgw01-amd64-016) (gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)) #74~18.04.2-Ubuntu SMP Fri Feb 5 11:17:31 UTC 2021
$ ld --version
GNU ld (GNU Binutils for Ubuntu) 2.30
Copyright (C) 2018 Free Software Foundation, Inc.
$ getconf GNU_LIBC_VERSION
glibc 2.27
$ #my glibc source version is 2.32.9000-development
$ cat ./version.h
/* This file just defines the current version number of libc. */
#define RELEASE "development"
#define VERSION "2.32.9000"
For some reasons, I need to modify and test glibc. I follow the steps of this website(https://sourceware.org/glibc/wiki/Testing/Builds#Compile_against_glibc_in_an_installed_location) to modify glibc and write test programs.
compile glibc.(confgure and make)
install glibc.(make install to a directory)
...other steps in the website above.
I successfully modified some pthread functions and passed the test (the test program I wrote can compiled against the install glibc and ran successfully). ldd the program.
$ ldd ./exec/1-1.out
linux-vdso.so.1 (0x00007ffcbf367000)
libpthread.so.0 => /home/cjl-target/gnu/install/lib64/libpthread.so.0 (0x00007fcadcea9000)
libc.so.6 => /home/cjl-target/gnu/install/lib64/libc.so.6 (0x00007fcadcaed000)
/home/cjl-target/gnu/install/lib64/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007fcadd2ca000)
As shown above, the shared libraries that the program depends on all point to the glibc installation path.
But when I compiled message-queue's test program(test mq_unlink) and ran it, failed as bellow:
./exec/1-1.out: symbol lookup error: /lib/x86_64-linux-gnu/libpthread.so.0: undefined symbol: __libc_vfork, version GLIBC_PRIVATE
check the library that is depended by the program:
$ ldd ./exec/1-1.out
linux-vdso.so.1 (0x00007ffce3f72000)
librt.so.1 => /home/cjl-target/gnu/install/lib64/librt.so.1 (0x00007f0a389a2000)
libc.so.6 => /home/cjl-target/gnu/install/lib64/libc.so.6 (0x00007f0a385e6000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f0a383c7000)
/home/cjl-target/gnu/install/lib64/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007f0a38dac000)
As shown above, the shared libraries libpthread.so.0 points to the system library. Why?
my compile script is(from the website above):
# dobuild.sh
SYSROOT=/home/xxx/xxx/xxx #the glibc's installation path
(set -x; \
gcc \
-L${SYSROOT}/usr/lib64 \
-I${SYSROOT}/usr/include \
--sysroot=${SYSROOT} \
-Wl,-rpath=${SYSROOT}/lib64 \
-Wl,--dynamic-linker=${SYSROOT}/lib64/ld-linux-x86-64.so.2 \
-Wall $*
)
when I compile the pthread's test program:./dobuild 1-1.c -pthread -Wall
when I compile the mq's test program:./dobuild 1-1.c -lrt -Wall
In addition, it is confusing that when invoke the pthread_create in the mq_unlink's test program, compiling it ./dobuild 1-1.c -lrt -pthread, the ldd result shows that all dependent libraries point to the installed glibc.
I've tried multiple variations of this, but none of them seem to work. Any ideas?
First, you should stop using ldd -- in the presence of multiple GLIBCs on a host, ldd is more likely to mislead than to illuminate.
If you want to see which libraries are really loaded, do this instead:
LD_TRACE_LOADED_OBJECTS=1 ./exec/1-1.out
Second, you should almost never use $* in shell scripts. Use "$#" instead (note: quotes are important). See this answer.
Third, the behavior you are observing is easily explained. To understand it, you need to know the difference between DT_RPATH and DT_RUNPATH, described here.
You can verify that your binaries are currently using RUNPATH, like so:
readelf -d 1-1.out | grep 'R.*PATH'
And you can verify that everything starts working as you expect by adding -Wl,--disable-new-dtags to the link command (which would cause the binary to use RPATH instead).
To summarize:
RUNPATH affects the search for the binary itself, but not for any libraries the binary depends on.
RPATH affects the search path for the binary and all libraries it depends on.
with RUNPATH, expected libpthread.so.0 is found only when the binary depends on it directly, but not when the dependency on libpthread is indirect (via librt).
with RPATH, expected libpthread.so.0 is found regardless of whether the dependency is direct or indirect.
Update:
If I want to use DT_RUNPATH, how to set the library runpath for librt?
You would need to link librt.so with -rpath=${SYSROOT}/lib64.
You could edit the rt/Makefile, or build with:
make LDFLAGS-rt.so='-Wl,--enable-new-dtags,-z,nodelete,-rpath=${SYSROOT}/lib64'
You would need to do the same for any other library that may bring transitive dependency on other parts of GLIBC. I don't know of a general way to do this, but setitng LDFLAGS-lib.so='-Wl,-rpath=${SYSROOT}/lib64' and rebuilding everything might do the trick.

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.

Error while loading shared libraries: /usr/local/lib64/libssl.so.1.1

I’m trying to compile openssl-1.1.0e on Centos 7 (7.3.1611)
but after i successfully compiled everything without any warning, i get an error when i’m trying any openssl command
[mdm#dev openssl-1.1.0e]$ openssl version
openssl: error while loading shared libraries: libssl.so.1.1: cannot open shared object file: No such file or directory
Is it a bug or my mistake?
Here below some info about my system/configuration
Configure:
[mdm#dev openssl-1.1.0e]$ ./Configure linux-x86_64 --prefix=/usr/local --openssldir=/usr/local
Make/Make test:
...
All tests successful.
Files=91, Tests=486, 44 wallclock secs ( 0.47 usr 0.08 sys + 27.72 cusr 13.41 csys = 41.68 CPU)
Result: PASS
...
Make install:
...
install libcrypto.a -> /usr/local/lib64/libcrypto.a
install libssl.a -> /usr/local/lib64/libssl.a
install libcrypto.so.1.1 -> /usr/local/lib64/libcrypto.so.1.1
link /usr/local/lib64/libcrypto.so -> /usr/local/lib64/libcrypto.so.1.1
install libssl.so.1.1 -> /usr/local/lib64/libssl.so.1.1
link /usr/local/lib64/libssl.so -> /usr/local/lib64/libssl.so.1.1
...
But if i check with ldd two libraries are not found despite Make install did its job...
[mdm#dev openssl-1.1.0e]$ ldd /usr/local/bin/openssl
linux-vdso.so.1 => (0x00007fffcfe75000)
/lib/$LIB/liblsp.so => /lib/lib64/liblsp.so (0x00007fa5cd77a000)
libssl.so.1.1 => not found
libcrypto.so.1.1 => not found
libdl.so.2 => /lib64/libdl.so.2 (0x00007fa5cd55d000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fa5cd341000)
libc.so.6 => /lib64/libc.so.6 (0x00007fa5ccf7f000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa5cd981000)
I have already installed by distro a version of openssl:
[mdm#dev]$ openssl version
OpenSSL 1.0.1e-fips 11 Feb 2013
[mdm#dev]$ which openssl
/usr/bin/openssl
yum info openssl:
...
Installed Packages
Name : openssl
Arch : x86_64
Epoch : 1
Version : 1.0.1e
Release : 60.el7_3.1
Size : 1.5 M
Repo : installed
From repo : updates
...
Appreciate any help or suggestion!
Sometime when you want climb the mountain you looking just the top without checking if something can help you on the base...
In my case I solved just exporting LD_LIBRARY_PATH before compile it again.
export LD_LIBRARY_PATH=/usr/local/lib:/usr/local/lib64
and after
sudo ldconfig
that should keep saved the path also after rebooting machine (and also for next times)
thanks to levitte, RenatoXSR
for OpenSSL 1.1.0g, CentOS 7.2.1511, you can try this
sudo bash -c "echo '/usr/local/lib64' >> /etc/ld.so.conf"
sudo ldconfig
this link explains the cause of problem
The use of RPATH is inconsistent. On some systems, ld.so considers RPATH before even looking at LD_LIBRARY_PATH, which makes it hard to override, for example when testing a new OpenSSL build (!). We did so in pre-1.1.0 versions by hacking LD_PRELOAD, but there are some sanitizers that do not agree with that, which makes life hard as well, for example when testing a new OpenSSL build (!)
this link gave an solution example
I know this is late but in my case I did not have the libssl.so.1.1 on my server.
There was a recommendation here to install openssl11-libs but not openssl11 as installing it could create problems.
Confirm you dont have libssl.so.1.1 on your server probably by trying locate libssl.so.1.1.
Simply do sudo yum install -y openssl11-libs if you don't have the libssl.so.1.1 library on your server.
It worked for me.
Try this:
ldd libssl.so -> libcrypto.so.1.1 => not found
sudo ln -s /usr/local/lib64/libcrypto.so.1.1 /usr/lib64/libcrypto.so.1.1
libcrypto.so.1.1 => /lib64/libcrypto.so.1.1 (0x00007f17d46c7000)
Configure:
[mdm#dev openssl-1.1.0e]$ ./Configure linux-x86_64 --prefix=/usr/local --openssldir=/usr/local
In this case, you should configure OpenSSL with:
./Configure linux-x86_64 enable-ec_nistp_64_gcc_128 -Wl,-rpath=/usr/local/lib64 \
--prefix=/usr/local --openssldir=/usr/local
OpenSSL does not add RPATHs by default (except on some of the BSDs). You need to manually specify it in your configure command. Once you manually specify it, things will "just work" for you without the need for LD_LIBRARY_PATH tricks.
The enable-ec_nistp_64_gcc_128 is applicable to x86_64. It makes Diffie-Hellman run 2x to 4x faster. The option has some restrictions, so be careful when using it (but you are safe on x86_64).
Also see Compilation and Installation on the OpenSSL wiki. There is a discussion of RPATHs, and a discussion of enable-ec_nistp_64_gcc_128.
In this case, you should configure OpenSSL with:
./Configure linux-x86_64 enable-ec_nistp_64_gcc_128
-Wl,-rpath=/usr/local/lib64 \ --prefix=/usr/local --openssldir=/usr/local OpenSSL does not add RPATHs by default (except on some of the BSDs). You need to manually specify it in your
configure command. Once you manually specify it, things will "just
work" for you without the need for LD_LIBRARY_PATH tricks.
i have followed your advice but still same error if i don't specify LD_LIBRARY_PATH it doesn't work anyway...
[mdm#dev openssl-1.1.0e]$ export LD_LIBRARY_PATH=/usr/local/lib:/usr/local/lib64
[mdm#dev openssl-1.1.0e]$ ldd /usr/local/bin/openssl
linux-vdso.so.1 => (0x00007ffc87aef000)
/lib/$LIB/liblsp.so => /lib/lib64/liblsp.so (0x00007f57511fa000)
libssl.so.1.1 => /usr/local/lib/libssl.so.1.1 (0x00007f5750f8c000)
libcrypto.so.1.1 => /usr/local/lib/libcrypto.so.1.1 (0x00007f5750ae8000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f57508cb000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f57506ae000)
libc.so.6 => /lib64/libc.so.6 (0x00007f57502ed000)
/lib64/ld-linux-x86-64.so.2 (0x00007f5751401000)
[mdm#dev openssl-1.1.0e]$ openssl version
OpenSSL 1.1.0e 16 Feb 2017
It looks like i have to use LD_LIBRARY_PATH anyway
I wonder if that is normal or is just misbehavior in my machine for some reasons that my knowledge can't figure it out...
jk2K solved my issue
For OpenSSL 1.1.0g, CentOS 7.2.1511, you can try this:
sudo bash -c "echo '/usr/local/lib64' >> /etc/ld.so.conf"
sudo ldconfig
For CentOS 7+, Add the following to /etc/environment:
LD_LIBRARY_PATH=/usr/local/lib:/usr/local/lib64
I suggest you to use a semi-official OpenSSL 1.1 package openssl11 from the EPEL repo instead of compiling it from scratch with:
# if you don't have EPEL repo yet...
yum install -y epel-release
# ...and then:
yum install -y openssl11
this might do the trick
sudo apt-get install libssl1.1
We ran into same problems after upgrading openssl from 1.0.2g to 1.1.0g.
The required libraries were present and also the soft link was present.
sudo ldconfig
worked for us. It rebuilt ldconfig cache.

Resources