Našel jsem následující funkční řešení. Nejprve vytvořte soubor memcpy.c:
#include <string.h>
/* some systems do not have newest example@unixlinux.online@GLIBC_2.14 - stay with old good one */
asm (".symver memcpy, example@unixlinux.online_2.2.5");
void *__wrap_memcpy(void *dest, const void *src, size_t n)
{
return memcpy(dest, src, n);
}
Ke kompilaci tohoto souboru nejsou potřeba žádné další CFLAGS. Poté propojte svůj program s -Wl,--wrap=memcpy .
Měl jsem podobný problém. Při pokusu o instalaci některých komponent oracle na RHEL 7.1 jsem dostal toto:
$ gcc -o /some/oracle/bin/foo .... -L/some/oracle/lib ...
/some/oracle/lib/libfoo.so: undefined reference to `example@unixlinux.online_2.14'
Zdá se, že glibc (mého) RHEL definuje pouze example@unixlinux.online_2.2.5:
$ readelf -Ws /usr/lib/x86_64-redhat-linux6E/lib64/libc_real.so | fgrep example@unixlinux.online
367: 000000000001bfe0 16 FUNC GLOBAL DEFAULT 8 example@unixlinux.online@GLIBC_2.2.5
1166: 0000000000019250 16 FUNC WEAK DEFAULT 8 example@unixlinux.online@GLIBC_2.2.5
Takže se mi to podařilo obejít tím, že jsem nejprve vytvořil soubor memcpy.c bez zalamování, a to následovně:
#include <string.h>
asm (".symver old_memcpy, example@unixlinux.online_2.2.5"); // hook old_memcpy as example@unixlinux.online
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);
}
a soubor memcpy.map, který exportuje naše memcpy jako example@unixlinux.online_2.14:
GLIBC_2.14 {
memcpy;
};
Potom jsem zkompiloval svůj vlastní memcpy.c do sdílené knihovny takto:
$ gcc -shared -fPIC -c memcpy.c
$ gcc -shared -fPIC -Wl,--version-script memcpy.map -o libmemcpy-2.14.so memcpy.o -lc
, přesunul libmemcpy-2.14.so do /some/oracle/lib (na který odkazují argumenty -L v mém propojení) a znovu propojil pomocí
$ gcc -o /some/oracle/bin/foo .... -L/some/oracle/lib ... /some/oracle/lib/libmemcpy-2.14.so -lfoo ...
(který se zkompiloval bez chyb) a ověřil ho:
$ 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)
Tohle mi fungovalo. Doufám, že to udělá i vám.
Měl jsem podobný problém. Knihovna třetí strany, kterou používáme, potřebuje starý example@unixlinux.online_2.2.5 . Mým řešením je rozšířený přístup @anight posted.
Také jsem pokřivil memcpy příkaz, ale musel jsem použít trochu jiný přístup, protože řešení zveřejněné @anight pro mě nefungovalo.
memcpy_wrap.c:
#include <stddef.h>
#include <string.h>
asm (".symver wrap_memcpy, example@unixlinux.online_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;
};
Sestavení obálky:
gcc -c memcpy_wrap.c -o memcpy_wrap.o
Nyní konečně při propojování programu přidejte
-Wl,--version-script memcpy_wrap.mapmemcpy_wrap.o
takže skončíte s něčím jako:
g++ <some flags> -Wl,--version-script memcpy_wrap.map <some .o files> memcpy_wrap.o <some libs>
Stačí staticky propojit memcpy – vytáhněte memcpy.o z libc.a ar x /path/to/libc.a memcpy.o (bez ohledu na verzi - memcpy je do značné míry samostatná funkce) a zahrňte ji do svého konečného odkazu. Všimněte si, že statické propojení může komplikovat licenční problémy, pokud je váš projekt distribuován veřejnosti a není open source.
Případně můžete jednoduše implementovat memcpy sami, ačkoli ručně vyladěná verze sestavení v glibc bude pravděpodobně efektivnější
Všimněte si, že example@unixlinux.online_2.2.5 je mapován na memmove (staré verze memcpy se důsledně kopírují předvídatelným směrem, což vedlo k tomu, že někdy bylo zneužito, když mělo být použito memmove), a to je jediný důvod, proč verze - pro tento konkrétní případ můžete ve svém kódu jednoduše nahradit memcpy za memmove.
Nebo můžete přejít na statické propojení nebo můžete zajistit, aby všechny systémy ve vaší síti měly stejnou nebo lepší verzi než váš počítač pro sestavení.