GNU/Linux >> Tutoriels Linux >  >> Linux

Liaison avec une version de symbole plus ancienne dans un fichier .so

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.


Linux
  1. exécuter une commande sur chaque ligne d'un fichier texte

  2. Les systèmes de fichiers journalisés garantissent-ils contre la corruption après une panne de courant ?

  3. Utiliser une ancienne version de Libreoffice ?

  4. Lien avec une ancienne version de libstdc++

  5. Liaison avec une ancienne version de libc pour fournir une plus grande couverture des applications

Transition des abonnements d'une ancienne version de Plesk vers Plesk 12

Comment vérifier la version d'Ubuntu - Méthodes rapides et faciles

Pas d'accord sur la version du symbole symbol_name après insmod

L'émulateur ne trouve pas la chaîne 'Linux version' dans le fichier image du noyau

pip install pickle ne fonctionne pas - aucun fichier ou répertoire de ce type

cp -L vs cp -H