Bibliotheken mit inkompatiblen Abhängigkeiten verknüpfen

9

Ich arbeite an einem C ++ - Projekt, das zwei Bibliotheken von Drittanbietern benötigt ( libfoo.so und libbar.so ). Mein Betriebssystem ist Linux.

libfoo.so ist dynamisch mit libpng14.so.14 (1.4.8) (EDIT 1)

verknüpft

libbar.so scheint statisch mit einer unbekannten Version von libpng libpng 1.2.8 (EDIT 1)

verbunden zu sein

Ich sage "scheint zu sein", weil:

  • ldd libbar.so zeigt nichts über png
  • nm -D libbar.so | grep png_read_png sagt "004f41b0 T png_read_png"
  • less libbar.so | grep png_read_png sagt "4577: 004f41b0 738 FUNC GLOBAL DEFAULT 10 png_read_png"

Wenn ich mein Programm starte, bricht es ab:

%Vor%

Dies ist gdb backtrace:

%Vor%

Wie Sie sehen, wird eine Ausnahme in Foo :: Image :: load geworfen, die zu libfoo.so

gehört

Wenn ich den Teil meines Codes deaktiviere, der libbar.so verwendet und das Verknüpfen mit ihm löscht, löst Foo :: Image :: load keine Ausnahme aus und funktioniert einwandfrei .

Also ich denke, es kann aufgrund einer Mehrdeutigkeit in der Symboltabelle sein. Wie kann ich es beheben?

BEARBEITEN 1

png_access_version_number ()

  • Mit libbar.so verknüpft, png_access_version_number() return 10208 : Version 1.2.8
  • Ohne libbar.so verknüpft, png_access_version_number() return 10408 : Version 1.4.8
Alessandro Pezzato 16.12.2011, 14:07
quelle

1 Antwort

4

Da Sie keine der Bibliotheken neu erstellen können, und da die Bibliotheken aufgrund von in Konflikt stehenden Symbolen nicht im selben "Dynamic Linker Namespace" residieren können, besteht die einzige Möglichkeit darin, isolieren sie.

Sie können dies erreichen, indem Sie dlopen("lib*.so", RTLD_LOCAL) (für eine oder beide Bibliotheken) verwenden, anstatt direkt mit ihnen zu verknüpfen.

Dies könnte praktikabel sein, wenn Sie nur ein paar Symbole aus z. libfoo.so - Sie können einfach dlsym verwenden, anstatt die Funktionen direkt aufzurufen.

Wenn Sie zu viele Abhängigkeiten von beiden Bibliotheken haben, könnte Ihre andere Lösung darin bestehen, eine "Interposer" -Bibliothek zu erstellen. Nehmen wir an, Sie möchten libbar.so einfügen und Sie benötigen bar1() , bar2() , ... bar1000() .

Schreiben Sie (oder erzeugen Sie mit einem einfachen Perl-Skript) eine Quelldatei, die wie folgt aussieht:

%Vor%

Kompilieren und verlinken Sie diese Quelle jetzt in libbar_interposer.so und verknüpfen Sie Ihre Anwendung damit (dies funktioniert nicht für C++ wegen Namensmangel, nur für plain- C ). Voila, keine Quelle ändert sich in der Anwendung, und Sie haben noch libbar.so isoliert, so dass ihre Symbole für den Rest der Anwendung nicht sichtbar sind, und insbesondere keinen Konflikt mit Symbolen in libpng .

    
Employed Russian 18.12.2011, 04:24
quelle