J'ai trouvé la solution de travail suivante. Créez d'abord le fichier memcpy.c :
#include <string.h>
/* some systems do not have newest [email protected]@GLIBC_2.14 - stay with old good one */
asm (".symver memcpy, [email protected]_2.2.5");
void *__wrap_memcpy(void *dest, const void *src, size_t n)
{
return memcpy(dest, src, n);
}
Aucun CFLAGS supplémentaire n'est nécessaire pour compiler ce fichier. Ensuite, liez votre programme avec -Wl,--wrap=memcpy .
J'avais un problème similaire. En essayant d'installer des composants oracle sur RHEL 7.1, j'ai ceci :
$ gcc -o /some/oracle/bin/foo .... -L/some/oracle/lib ...
/some/oracle/lib/libfoo.so: undefined reference to `[email protected]_2.14'
Il semble que (ma) glibc de RHEL ne définit que [email protected]_2.2.5 :
$ readelf -Ws /usr/lib/x86_64-redhat-linux6E/lib64/libc_real.so | fgrep [email protected]
367: 000000000001bfe0 16 FUNC GLOBAL DEFAULT 8 [email protected]@GLIBC_2.2.5
1166: 0000000000019250 16 FUNC WEAK DEFAULT 8 [email protected]@GLIBC_2.2.5
J'ai donc réussi à contourner ce problème en créant d'abord un fichier memcpy.c sans encapsulage, comme suit :
#include <string.h>
asm (".symver old_memcpy, [email protected]_2.2.5"); // hook old_memcpy as [email protected]
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);
}
et un fichier memcpy.map qui exporte notre memcpy comme [email protected]_2.14 :
GLIBC_2.14 {
memcpy;
};
J'ai ensuite compilé mon propre memcpy.c dans une bibliothèque partagée comme celle-ci :
$ gcc -shared -fPIC -c memcpy.c
$ gcc -shared -fPIC -Wl,--version-script memcpy.map -o libmemcpy-2.14.so memcpy.o -lc
, déplacé libmemcpy-2.14.so dans /some/oracle/lib (pointé par les arguments -L dans mon lien), et lié à nouveau par
$ gcc -o /some/oracle/bin/foo .... -L/some/oracle/lib ... /some/oracle/lib/libmemcpy-2.14.so -lfoo ...
(qui a été compilé sans erreur) et l'a vérifié par :
$ 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)
Cela a fonctionné pour moi. J'espère qu'il le fera pour vous aussi.
J'ai eu un problème similaire. Une bibliothèque tierce que nous utilisons a besoin de l'ancien [email protected]_2.2.5
. Ma solution est une approche étendue @anight posté.
Je déforme également le memcpy
commande, mais j'ai dû utiliser une approche légèrement différente, car la solution publiée par @anight ne fonctionnait pas pour moi.
memcpy_wrap.c :
#include <stddef.h>
#include <string.h>
asm (".symver wrap_memcpy, [email protected]_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;
};
Créer le wrapper :
gcc -c memcpy_wrap.c -o memcpy_wrap.o
Maintenant, enfin, lors de la liaison du programme, ajoutez
-Wl,--version-script memcpy_wrap.map
memcpy_wrap.o
pour que vous vous retrouviez avec quelque chose comme :
g++ <some flags> -Wl,--version-script memcpy_wrap.map <some .o files> memcpy_wrap.o <some libs>
Liez simplement memcpy de manière statique - extrayez memcpy.o de libc.a ar x /path/to/libc.a memcpy.o
(quelle que soit la version - memcpy est à peu près une fonction autonome) et incluez-la dans votre lien final. Notez que les liens statiques peuvent compliquer les problèmes de licence si votre projet est distribué au public et non open source.
Alternativement, vous pouvez simplement implémenter memcpy vous-même, bien que la version d'assemblage réglée à la main dans la glibc soit probablement plus efficace
Notez que [email protected]_2.2.5 est mappé sur memmove (les anciennes versions de memcpy sont systématiquement copiées dans une direction prévisible, ce qui l'a parfois amené à être mal utilisé alors que memmove aurait dû être utilisé), et c'est la seule raison du changement de version - vous pouvez simplement remplacer memcpy par memmove dans votre code pour ce cas précis.
Ou vous pouvez passer à une liaison statique, ou vous pouvez vous assurer que tous les systèmes de votre réseau ont la même version ou une version supérieure à celle de votre machine de construction.