Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linking against older symbol version in a .so file

Tags:

c

linux

gcc

linker

ld

Using gcc and ld on x86_64 linux I need to link against a newer version of a library (glibc 2.14) but the executable needs to run on a system with an older version (2.5). Since the only incompatible symbol is memcpy (needing memcpy@GLIBC_2.2.5 but the library providing memcpy@GLIBC_2.14), I would like to tell the linker that instead of taking the default version for memcpy, it should take an old version I specify.

I found a quite arkward way to do it: simply specify a copy of the old .so file at the linker command line. This works fine, but I don't like the idea of having multiple .so files (I could only make it work by specifying all old libraries I link to that also have references to memcpy) checked into the svn and needed by my build system.

So I am searching for a way to tell the linker to take the old versioned symbol.

Alternatives that don't work (well) for me are:

  • Using asm .symver (as seen on Web Archive of Trevor Pounds' Blog) since this would require me to make sure the symver is before all the code that is using memcpy, which would be very hard (complex codebase with 3rd party code)
  • Maintaining a build environment with the old libraries; simply because I want to develop on my desktop system and it would be a pita to sync stuff around in our network.

When thinking about all the jobs a linker does, it doesn't seem like a hard thing to imlpement, after all it has some code to figure out the default version of a symbol too.

Any other ideas that are on the same complexity level as a simple linker command line (like creating a simple linker script etc.) are welcome too, as long as they are not weird hacks like editing the resulting binary...

edit: To conserve this for the future readers, additionally to the below ideas I found the option --wrap to the linker, which might be useful sometimes too.

like image 445
PlasmaHH Avatar asked Jan 11 '12 16:01

PlasmaHH


People also ask

Is glibc backward compatible?

In general, binaries that were compiled for an older glibc version will run fine on a system with a newer glibc, as glibc is backward-compatible and handles automatically changes to its application binary interface (ABI).

What is glibc version?

The current stable version of glibc is 2.36, released on August 1st, 2022. The current development version of glibc is 2.37, releasing on or around February 1st, 2023.

Does GCC use glibc?

glibc is the "normal" C library implementation you would find on a linux machine by default. libgcc is the support library which is needed by gcc for some special machines.


2 Answers

I found the following working solution. First create file memcpy.c:

#include <string.h>  /* some systems do not have newest memcpy@@GLIBC_2.14 - stay with old good one */ asm (".symver memcpy, memcpy@GLIBC_2.2.5");  void *__wrap_memcpy(void *dest, const void *src, size_t n) {     return memcpy(dest, src, n); } 

No additional CFLAGS needed to compile this file. Then link your program with -Wl,--wrap=memcpy.

like image 187
anight Avatar answered Oct 10 '22 01:10

anight


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.

like image 32
Random832 Avatar answered Oct 10 '22 01:10

Random832