Linking against an old version of libc to provide greater application coverage
Work out which symbols in your executable are creating the dependency on the undesired version of glibc.
$ objdump -p myprog
...
Version References:
required from libc.so.6:
0x09691972 0x00 05 GLIBC_2.3
0x09691a75 0x00 03 GLIBC_2.2.5
$ objdump -T myprog | fgrep GLIBC_2.3
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.3 realpath
Look within the depended-upon library to see if there are any symbols in older versions that you can link against:
$ objdump -T /lib/libc.so.6 | grep -w realpath
0000000000105d90 g DF .text 0000000000000021 (GLIBC_2.2.5) realpath
000000000003e7b0 g DF .text 00000000000004bf GLIBC_2.3 realpath
We're in luck!
Request the version from GLIBC_2.2.5
in your code:
#include <limits.h>
#include <stdlib.h>
__asm__(".symver realpath,realpath@GLIBC_2.2.5");
int main () {
realpath ("foo", "bar");
}
Observe that GLIBC_2.3 is no longer needed:
$ objdump -p myprog
...
Version References:
required from libc.so.6:
0x09691a75 0x00 02 GLIBC_2.2.5
$ objdump -T myprog | grep realpath
0000000000000000 DF *UND* 0000000000000000 GLIBC_2.2.5 realpath
For further information, see http://web.archive.org/web/20160107032111/http://www.trevorpounds.com/blog/?p=103.
Linking against older symbol version in a .so file
Just link memcpy statically - pull memcpy.o out of libc.a ar x /path/to/libc.a memcpy.o
(whatever version - memcpy is pretty much a standalone function) and include it in your final link. Note that static linking may complicate licensing issues if your project is distributed to the public and not open-source.
Alternatively, you could simply implement memcpy yourself, though the hand-tuned assembly version in glibc is likely to be more efficient
Note that memcpy@GLIBC_2.2.5 is mapped to memmove (old versions of memcpy consistently copied in a predictable direction, which led to it sometimes being misused when memmove should have been used), and this is the only reason for the version bump - you could simply replace memcpy with memmove in your code for this specific case.
Or you could go to static linking, or you could ensure that all systems on your network have the same or better version than your build machine.
Build and bind against older libc version
If your project does not depend on any native libraries, then probably the easiest way would be to use the x86_64-unknown-linux-musl
target.
This target statically links against MUSL Libc rather than dynamically linking against the system's libc. As a result it produces completely static binaries which should run on a wide range of systems.
To install this target:
rustup target add x86_64-unknown-linux-musl
To build your project using this target:
cargo build --target x86_64-unknown-linux-musl
See the edition guide for more details.
If you are using any non-rust libraries it becomes more difficult, because they may be dynamically linked and may in turn depend on the system libc. In that case you would either need to statically link the external libraries (assuming that is even possible, and that the libraries you are using will work with MUSL libc), or make different builds for each platform you want to target.
If you end up having to make different builds for each platform, a docker container would be the easiest way to achieve that.
Tell which version of symbols are available for linking against (in libc)?
It seems to me that you have mixed up your libraries and binaries a bit...
/lib/libc.so.6
on most Linux distributions is a 32-bit shared object and should contain the *@GLIBC_2.0
symbols. If you are on an x86_64 platform, though, I would expect GCC to produce an 64-bit binary by default. 64-bit binaries are generally linked against /lib64/libc.so.6
, which would not contain compatibility symbols for an old glibc version like 2.0 - the x86_64 architecture did not even exist back then...
Try compiling your *@GLIBC_2.0
program with the -m32
GCC flag to force linking against the 32-bit C library.
Related Topics
./Configure: /Bin/Sh^M: Bad Interpreter
Retaining File Permissions With Git
Is There Any API For Determining the Physical Address from Virtual Address in Linux
How to Compile a 32-Bit Binary on a 64-Bit Linux Machine With Gcc/Cmake
Setting Up Ftp on Amazon Cloud Server
Difference Between ${} and $() in Bash
Why Are the Backslash and Semicolon Required With the Find Command'S -Exec Option
Shell/Bash Shortcut For Bulk Renaming of Files in a Folder
Linux/Unix Command to Determine If Process Is Running
Read Values into a Shell Variable from a Pipe
How to Parse a CSV File in Bash
How Are the Fs/Gs Registers Used in Linux Amd64
How to Set Environment Variable For Everyone Under My Linux System
How to Run a Program With a Different Working Directory from Current, from Linux Shell
How to Loop Over Directories in Linux
How to Get Unique Values from an Array in Bash
Exit Code of Variable Assignment to Command Substitution in Bash