Multiple glibc libraries on a single host
My linux (SLES-8) server currently has glibc-2.2.5-235, but I have a program which won't work on this version and requires glibc-2.3.3.
Is it possible to have multiple glibcs installed on the same host?
This is the error I get when I run my program on the old glibc:
./myapp: /lib/i686/libc.so.6: version `GLIBC_2.3' not found (required by ./myapp)
./myapp: /lib/i686/libpthread.so.0: version `GLIBC_2.3.2' not found (required by ./myapp)
./myapp: /lib/i686/libc.so.6: version `GLIBC_2.3' not found (required by ./libxerces-c.so.27)
./myapp: /lib/ld-linux.so.2: version `GLIBC_2.3' not found (required by ./libstdc++.so.6)
./myapp: /lib/i686/libc.so.6: version `GLIBC_2.3' not found (required by ./libstdc++.so.6)
So I created a new directory called newglibc and copied the following files in:
libpthread.so.0
libm.so.6
libc.so.6
ld-2.3.3.so
ld-linux.so.2 -> ld-2.3.3.so
and
export LD_LIBRARY_PATH=newglibc:$LD_LIBRARY_PATH
But I get an error:
./myapp: /lib/ld-linux.so.2: version `GLIBC_PRIVATE' not found (required by ./newglibc/libpthread.so.0)
./myapp: /lib/ld-linux.so.2: version `GLIBC_2.3' not found (required by libstdc++.so.6)
./myapp: /lib/ld-linux.so.2: version `GLIBC_PRIVATE' not found (required by ./newglibc/libm.so.6)
./myapp: /lib/ld-linux.so.2: version `GLIBC_2.3' not found (required by ./newglibc/libc.so.6)
./myapp: /lib/ld-linux.so.2: version `GLIBC_PRIVATE' not found (required by ./newglibc/libc.so.6)
So it appears that they are still linking to /lib and not picking up from where I put them?
Thanks
Setup 1: compile your own glibc without dedicated GCC and use it
This setup might work and is quick as it does not recompile the whole GCC toolchain, just glibc.
But it is not reliable as it uses host C runtime objects such as
crt1.o
,crti.o
, andcrtn.o
provided by glibc. This is mentioned at: https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_location Those objects do early setup that glibc relies on, so I wouldn't be surprised if things crashed in wonderful and awesomely subtle ways.For a more reliable setup, see Setup 2 below.
Build glibc and install locally:
Setup 1: verify the build
test_glibc.c
Compile and run with
test_glibc.sh
:The program outputs the expected:
Command adapted from https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_location but
--sysroot
made it fail with:so I removed it.
ldd
output confirms that theldd
and libraries that we've just built are actually being used as expected:The
gcc
compilation debug output shows that my host runtime objects were used, which is bad as mentioned previously, but I don't know how to work around it, e.g. it contains:Setup 1: modify glibc
Now let's modify glibc with:
Then recompile and re-install glibc, and recompile and re-run our program:
and we see
hacked
printed a few times as expected.This further confirms that we actually used the glibc that we compiled and not the host one.
Tested on Ubuntu 18.04.
Setup 2: crosstool-NG pristine setup
This is an alternative to setup 1, and it is the most correct setup I've achieved far: everything is correct as far as I can observe, including the C runtime objects such as
crt1.o
,crti.o
, andcrtn.o
.In this setup, we will compile a full dedicated GCC toolchain that uses the glibc that we want.
The only downside to this method is that the build will take longer. But I wouldn't risk a production setup with anything less.
crosstool-NG is a set of scripts that downloads and compiles everything from source for us, including GCC, glibc and binutils.
Yes the GCC build system is so bad that we need a separate project for that.
This setup is only not perfect because crosstool-NG does not support building the executables without extra
-Wl
flags, which feels weird since we've built GCC itself. But everything seems to work, so this is only an inconvenience.Get crosstool-NG and configure it:
The only mandatory option that I can see, is making it match your host kernel version to use the correct kernel headers. Find your host kernel version with:
which shows me:
so in
menuconfig
I do:Operating System
Version of linux
so I select:
which is the first equal or older version. It has to be older since the kernel is backwards compatible.
Now you can build with:
and now wait for about thirty minutes to two hours for compilation.
Setup 2: optional configurations
The
.config
that we generated with./ct-ng x86_64-unknown-linux-gnu
has:To change that, in
menuconfig
do:C-library
Version of glibc
save the
.config
, and continue with the build.Or, if you want to use your own glibc source, e.g. to use glibc from the latest git, proceed like this:
Paths and misc options
Try features marked as EXPERIMENTAL
: set to trueC-library
Source of glibc
Custom location
: say yesCustom location
Custom source location
: point to a directory containing your glibc sourcewhere glibc was cloned as:
Setup 2: test it out
Once you have built he toolchain that you want, test it out with:
Everything seems to work as in Setup 1, except that now the correct runtime objects were used:
Setup 2: failed efficient glibc recompilation attempt
It does not seem possible with crosstool-NG, as explained below.
If you just re-build;
then your changes to the custom glibc source location are taken into account, but it builds everything from scratch, making it unusable for iterative development.
If we do:
it gives a nice overview of the build steps:
therefore, we see that there are glibc steps intertwined with several GCC steps, most notably
libc_start_files
comes beforecc_core_pass_2
, which is likely the most expensive step together withcc_core_pass_1
.In order to build just one step, you must first set the "Save intermediate steps" in
.config
option for the intial build:Paths and misc options
Debug crosstool-NG
Save intermediate steps
and then you can try:
but unfortunately, the
+
required as mentioned at: https://github.com/crosstool-ng/crosstool-ng/issues/1033#issuecomment-424877536and basically still makes the rebuild too slow to be feasible for development, and I don't see how to overcome this without patching crosstool-NG.
Furthermore, starting from the
libc
step didn't seem to copy over the source again fromCustom source location
, further making this method unusable.Bonus: stdlibc++
A bonus if you're also interested in the C++ standard library: How to edit and re-build the GCC libstdc++ C++ standard library source?
"Employed Russian" is among the best answer, and I think all other suggested answer may not work. The reason is simply because when an application is first created, all its the APIs it needs are resolved at compile time. Using "ldd" u can see all the statically linked dependencies:
But at runtime, firefox will also load many other dynamic libraries, eg (for firefox) there are many "glib"-labelled libraries loaded (even though statically linked there are none):
Manytimes, you can see names of one version being soft-linked into another version. Eg:
This therefore means different version of "libraries" exists in one system - which is not a problem as it is the same file, and it will provide compatibilities when applications have multiple versions dependencies.
Therefore, at the system level, all the libraries are almost interdependent on one another, and just changing the libraries loading priority via manipulating LD_PRELOAD or LD_LIBRARY_PATH will not help - even it can load, runtime it may still crash.
http://lightofdawn.org/wiki/wiki.cgi/-wiki/NewAppsOnOldGlibc
Best alternative is chroot (mentioned by ER briefly): but for this you will need to recreate the entire environment in which is the original binary execute - usually starting from /lib, /usr/lib/, /usr/lib/x86 etc. You can either use "Buildroot", or YoctoProject, or just tar from an existing Distro environment. (like Fedora/Suse etc).
Use LD_PRELOAD: put your library somewhere out of the man lib directories and run:
See: the Wikipedia article
It is very possible to have multiple versions of glibc on the same system (we do that every day).
However, you need to know that glibc consists of many pieces (200+ shared libraries) which all must match. One of the pieces is ld-linux.so.2, and it must match libc.so.6, or you'll see the errors you are seeing.
The absolute path to ld-linux.so.2 is hard-coded into the executable at link time, and can not be easily changed after the link is done.
To build an executable that will work with the new glibc, do this:
The
-rpath
linker option will make the runtime loader search for libraries in/path/to/newglibc
(so you wouldn't have to setLD_LIBRARY_PATH
before running it), and the-dynamic-linker
option will "bake" path to correctld-linux.so.2
into the application.If you can't relink the
myapp
application (e.g. because it is a third-party binary), not all is lost, but it gets trickier. One solution is to set a properchroot
environment for it. Another possibility is to use rtldi and a binary editor.Can you consider using Nix http://nixos.org/nix/ ?
If you look closely at the second output you can see that the new location for the libraries is used. Maybe there are still missing libraries that are part of the glibc.
I also think that all the libraries used by your program should be compiled against that version of glibc. If you have access to the source code of the program, a fresh compilation appears to be the best solution.