Encontré la siguiente solución de trabajo. Primero crea el archivo 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);
}
No se necesitan CFLAGS adicionales para compilar este archivo. Luego vincule su programa con -Wl,--wrap=memcpy .
Tuve un problema similar. Al intentar instalar algunos componentes de Oracle en RHEL 7.1, obtuve esto:
$ gcc -o /some/oracle/bin/foo .... -L/some/oracle/lib ...
/some/oracle/lib/libfoo.so: undefined reference to `[email protected]_2.14'
Parece que (mi) glibc de RHEL solo define [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
Por lo tanto, me las arreglé para solucionar esto, creando primero un archivo memcpy.c sin envolver, de la siguiente manera:
#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);
}
y un archivo memcpy.map que exporta nuestro memcpy como [email protected]_2.14:
GLIBC_2.14 {
memcpy;
};
Luego compilé mi propio memcpy.c en una librería compartida como esta:
$ gcc -shared -fPIC -c memcpy.c
$ gcc -shared -fPIC -Wl,--version-script memcpy.map -o libmemcpy-2.14.so memcpy.o -lc
, moví libmemcpy-2.14.so a /some/oracle/lib (señalado por argumentos -L en mi vinculación) y vinculado de nuevo por
$ gcc -o /some/oracle/bin/foo .... -L/some/oracle/lib ... /some/oracle/lib/libmemcpy-2.14.so -lfoo ...
(que compiló sin errores) y lo verificó por:
$ 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)
Esto funcionó para mí. Espero que también lo haga por ti.
Tuve un problema similar. Una biblioteca de terceros que usamos necesita el antiguo [email protected]_2.2.5
. Mi solución es un enfoque extendido publicado por @anight.
También deformo el memcpy
comando, pero tuve que usar un enfoque ligeramente diferente, ya que la solución que publicó @anight no funcionó para mí.
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.mapa:
GLIBC_2.2.5 {
memcpy;
};
Crear el envoltorio:
gcc -c memcpy_wrap.c -o memcpy_wrap.o
Ahora, finalmente, al vincular el programa, agregue
-Wl,--version-script memcpy_wrap.map
memcpy_wrap.o
para que termines con algo como:
g++ <some flags> -Wl,--version-script memcpy_wrap.map <some .o files> memcpy_wrap.o <some libs>
Simplemente vincule memcpy estáticamente:extraiga memcpy.o de libc.a ar x /path/to/libc.a memcpy.o
(cualquiera que sea la versión, memcpy es prácticamente una función independiente) e inclúyalo en su enlace final. Tenga en cuenta que la vinculación estática puede complicar los problemas de licencia si su proyecto se distribuye al público y no es de código abierto.
Alternativamente, podría simplemente implementar memcpy usted mismo, aunque es probable que la versión ensamblada ajustada a mano en glibc sea más eficiente
Tenga en cuenta que [email protected]_2.2.5 está asignado a memmove (las versiones antiguas de memcpy se copiaban constantemente en una dirección predecible, lo que provocaba que a veces se usara incorrectamente cuando se debería haber usado memmove), y esta es la única razón por la que la versión aumenta - podría simplemente reemplazar memcpy con memmove en su código para este caso específico.
O podría ir a la vinculación estática, o podría asegurarse de que todos los sistemas en su red tengan la misma o mejor versión que su máquina de compilación.