GNU/Linux >> Znalost Linux >  >> Linux

Propojení se starší verzí symbolu v souboru .so

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 [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);
}

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 `[email protected]_2.14'

Zdá se, že glibc (mého) RHEL definuje pouze [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

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, [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);
}

a soubor memcpy.map, který exportuje naše memcpy jako [email protected]_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ý [email protected]_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, [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;
};

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.map
  • memcpy_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 [email protected]_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í.


Linux
  1. spuštění příkazu proti každému řádku v textovém souboru

  2. Propojení se starou verzí knihovny libc pro zajištění většího pokrytí aplikací

  3. Upozornění libpng:Nekompatibilní verze libpng v aplikaci a knihovně

  1. grep velký seznam proti velkému souboru

  2. přemístění R_X86_64_32S proti propojování Chyba

  3. Jak mohu propojit starší verzi sdílené knihovny

  1. Propojení se starší verzí libstdc++

  2. Jak nainstalovat starší verzi gcc na Fedoru

  3. Otevíráte geodatabázi souborů v QGIS pro Ubuntu?