Linking Against an Old Version of Libc to Provide Greater Application Coverage

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



Leave a reply



Submit