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). Si
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.
For nim-lang, I elaborated on a solution I found using the C compiler --include=
flag as follows:
Create a file symver.h with:
__asm__(".symver fcntl,fcntl@GLIBC_2.4");
Build your program with nim c ---passC:--include=symver.h
As for me I'm cross compiling too. I compile with nim c --cpu:arm --os:linux --passC:--include=symver.h ...
and I can get symbol versions using arm-linux-gnueabihf-objdump -T ../arm-libc.so.6 | grep fcntl
I had to remove ~/.cache/nim
at some point. And it seems to work.
I had a similar problem. Trying to install some oracle components on RHEL 7.1, I got this:
$ gcc -o /some/oracle/bin/foo .... -L/some/oracle/lib ...
/some/oracle/lib/libfoo.so: undefined reference to `memcpy@GLIBC_2.14'
It seems that (my) RHEL's glibc only defines memcpy@GLIBC_2.2.5:
$ readelf -Ws /usr/lib/x86_64-redhat-linux6E/lib64/libc_real.so | fgrep memcpy@
367: 000000000001bfe0 16 FUNC GLOBAL DEFAULT 8 memcpy@@GLIBC_2.2.5
1166: 0000000000019250 16 FUNC WEAK DEFAULT 8 wmemcpy@@GLIBC_2.2.5
So, I managed to get around this, by first creating a memcpy.c file without wrapping, as follows:
#include <string.h>
asm (".symver old_memcpy, memcpy@GLIBC_2.2.5"); // hook old_memcpy as memcpy@2.2.5
void *old_memcpy(void *, const void *, size_t );
void *memcpy(void *dest, const void *src, size_t n) // then export memcpy
{
return old_memcpy(dest, src, n);
}
and a memcpy.map file that exports our memcpy as memcpy@GLIBC_2.14:
GLIBC_2.14 {
memcpy;
};
I then compiled my own memcpy.c into a shared lib like this:
$ gcc -shared -fPIC -c memcpy.c
$ gcc -shared -fPIC -Wl,--version-script memcpy.map -o libmemcpy-2.14.so memcpy.o -lc
, moved libmemcpy-2.14.so into /some/oracle/lib (pointed to by -L arguments in my linking), and linked again by
$ gcc -o /some/oracle/bin/foo .... -L/some/oracle/lib ... /some/oracle/lib/libmemcpy-2.14.so -lfoo ...
(which compiled without errors) and verified it by:
$ ldd /some/oracle/bin/foo
linux-vdso.so.1 => (0x00007fff9f3fe000)
/some/oracle/lib/libmemcpy-2.14.so (0x00007f963a63e000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007f963a428000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f963a20c000)
librt.so.1 => /lib64/librt.so.1 (0x00007f963a003000)
libc.so.6 => /lib64/libc.so.6 (0x00007f9639c42000)
/lib64/ld-linux-x86-64.so.2 (0x00007f963aa5b000)
This worked for me. I hope it does it for you, too.
It may caused by old ld (gnu link) version. For following simple problem:
#include <string.h>
#include <stdio.h>
int main(int argc,char **argv)
{
char buf[5];
memset(buf,0,sizeof(buf));
printf("ok\n");
return 0;
}
When I use ld 2.19.1, memset is relocated to: memset@@GLIBC_2.0, and cause crash. After upgraded to 2.25, it is: memset@plt, and crash solved.
I think you can get away with making a simple C file containing the symver statement and perhaps a dummy function calling memcpy. Then you just have to ensure that the resulting object file is the first file given to linker.
I had a similar issue. A third party library we use needs the old memcpy@GLIBC_2.2.5
. My solution is an extended approach @anight posted.
I also warp the memcpy
command, but i had to use a slightly different approach, since the solution @anight posted did not work for me.
memcpy_wrap.c:
#include <stddef.h>
#include <string.h>
asm (".symver wrap_memcpy, memcpy@GLIBC_2.2.5");
void *wrap_memcpy(void *dest, const void *src, size_t n) {
return memcpy(dest, src, n);
}
memcpy_wrap.map:
GLIBC_2.2.5 {
memcpy;
};
Build the wrapper:
gcc -c memcpy_wrap.c -o memcpy_wrap.o
Now finally when linking the program add
-Wl,--version-script memcpy_wrap.map
memcpy_wrap.o
so that you will end up with something like:
g++ <some flags> -Wl,--version-script memcpy_wrap.map <some .o files> memcpy_wrap.o <some libs>