GNU/Linux >> Tutoriales Linux >  >> Linux

Vinculación con una versión de símbolo anterior en un archivo .so

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.


Linux
  1. Vinculación con una versión anterior de libc para proporcionar una mayor cobertura de aplicaciones

  2. Advertencia de libpng:versión de libpng incompatible en la aplicación y la biblioteca

  3. grep una lista grande contra un archivo grande

  4. ¿Cómo puedo vincular a una versión anterior de una biblioteca compartida?

  5. Cómo instalar una versión anterior de gcc en Fedora

Transición de suscripciones de una versión anterior de Plesk a Plesk 12

¿Utiliza una versión anterior de Libreoffice?

Cómo verificar la versión de Ubuntu:métodos rápidos y fáciles

El emulador no puede encontrar la cadena 'Versión de Linux' en el archivo de imagen del kernel

pip install pickle no funciona - no existe tal archivo o directorio

Eliminación elegante de archivos con más de 30 días de antigüedad