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 example@unixlinux.online@GLIBC_2.14 - stay with old good one */
asm (".symver memcpy, example@unixlinux.online_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 `example@unixlinux.online_2.14'

Zdá se, že glibc (mého) RHEL definuje pouze example@unixlinux.online_2.2.5:

$ readelf -Ws /usr/lib/x86_64-redhat-linux6E/lib64/libc_real.so | fgrep example@unixlinux.online
   367: 000000000001bfe0    16 FUNC    GLOBAL DEFAULT    8 example@unixlinux.online@GLIBC_2.2.5
  1166: 0000000000019250    16 FUNC    WEAK   DEFAULT    8 example@unixlinux.online@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, example@unixlinux.online_2.2.5");       // hook old_memcpy as example@unixlinux.online
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 example@unixlinux.online_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ý example@unixlinux.online_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, example@unixlinux.online_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 example@unixlinux.online_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?