Ich versuche, mehr über die Bibliotheksversionierung unter Linux zu erfahren und zu erfahren, wie alles funktioniert. Hier ist der Kontext:
- Ich habe zwei Versionen einer dynamischen Bibliothek, die denselben Satz von Schnittstellen verfügbar machen, sagen wir libsome1.so
und libsome2.so
.
- Eine Anwendung ist mit verknüpft libsome1.so
.
- Diese Anwendung libdl.so
lädt beispielsweise dynamisch ein anderes Modul libmagic.so
.
- Jetzt libmagic.so
ist dagegen verlinkt libsome2.so
. Ohne Verwendung von Linker-Skripten zum Ausblenden von Symbolen libmagic.so
werden zur Laufzeit alle Aufrufe von Interfaces in libsome2.so
aufgelöst libsome1.so
. Dies kann bestätigt werden, indem der von zurückgegebene Wert mit libVersion()
dem Wert des Makros verglichen wird LIB_VERSION
.
- Also versuche ich als nächstes, libmagic.so
ein Linker-Skript zu kompilieren und zu verknüpfen, das alle Symbole mit Ausnahme von 3 verbirgt, die darin definiert libmagic.so
sind und von diesem exportiert werden. Das funktioniert ... oder zumindest libVersion()
und LIB_VERSION
Werte stimmen überein (und es wird Version 2 und nicht 1 gemeldet).
- Als jedoch einige Datenstrukturen auf die Festplatte serialisiert wurden, bemerkte ich eine Beschädigung. Wenn ich im Verzeichnis der Anwendung libsome1.so
einen Softlink lösche und an seiner Stelle einen solchen erstelle libsome2.so
, funktioniert alles wie erwartet, und die gleiche Beschädigung tritt nicht auf.
Ich kann nicht anders, als zu glauben, dass dies auf einen Konflikt in der Symbolauflösung des Laufzeit-Linkers zurückzuführen ist. Ich habe viele Dinge ausprobiert, wie den Versuch, eine Verknüpfung zu libsome2.so
erstellen, damit alle Symbole gleich sind symbol@@VER_2
(worüber ich immer noch verwirrt bin, weil der Befehl nm -CD libsome2.so
immer noch Symbole als symbol
und nicht auflistet symbol@@VER_2
) ... Nichts scheint zu funktionieren !!! Hilfe!!!!!!
quelle
RTLD_LOCAL
undRTLD_DEEPBIND
dlopen Flags in Ihrer App. Ich habe jetzt keine Zeit, dies zu testen, aber es sollte basierend auf der Manpage funktionieren.Antworten:
Dies beantwortet Ihre Frage nicht genau, aber ...
Zuallererst ist ELF die Spezifikation, die von Linux für ausführbare Dateien (Programme), gemeinsam genutzte Bibliotheken und auch Objektdateien verwendet wird, die die Zwischendateien sind, die beim Kompilieren von Software gefunden werden. Objektdateien enden mit .o, gemeinsam genutzte Bibliotheken enden mit .so, gefolgt von null oder mehr durch Punkte getrennten Ziffern, und ausführbare Dateien haben normalerweise keine Erweiterung.
Es gibt normalerweise drei Formulare, um eine gemeinsam genutzte Bibliothek zu benennen. Das erste Formular endet einfach mit .so. Beispielsweise wird eine Bibliothek mit dem Namen readline in einer Datei mit dem Namen libreadline.so gespeichert und befindet sich normalerweise unter / lib, / usr / lib oder / usr / local / lib. Diese Datei befindet sich beim Kompilieren von Software mit einer Option wie -lreadline. -l weist den Compiler an, eine Verknüpfung mit der folgenden Bibliothek herzustellen. Da sich Bibliotheken von Zeit zu Zeit ändern, kann dies veralten, sodass Bibliotheken einen so genannten SONAME einbetten. Der SONAME für readline könnte für die Hauptversion von libreadline wie libreadline.so.2 aussehen. Möglicherweise sind auch viele kleinere Versionen von readline kompatibel und erfordern keine Neukompilierung der Software. Eine kleinere Version von readline könnte libreadline.so.2.14 heißen. Normalerweise libreadline. In diesem Fall ist dies nur ein symbolischer Link zur neuesten Hauptversion von readline, libreadline.so.2. libreadline.so.2 ist auch ein symbolischer Link zu libreadline.so.2.14, bei dem es sich tatsächlich um die verwendete Datei handelt.
Der SONAME einer Bibliothek ist in die Bibliotheksdatei selbst eingebettet. Irgendwo in der Datei libreadline.so.2.14 befindet sich der String libreadline.so.2. Wenn ein Programm kompiliert und mit readline verknüpft wird, sucht es nach der Datei libreadline.so und liest den darin eingebetteten SONAME. Später, wenn das Programm tatsächlich ausgeführt wird, wird libreadline.so.2 geladen, nicht nur libreadline.so, da dies der SONAME war, der beim ersten Verknüpfen gelesen wurde. Auf diese Weise können auf einem System mehrere inkompatible Versionen von readline installiert werden, und jedes Programm lädt die entsprechende Hauptversion, mit der es verknüpft wurde. Wenn ich beispielsweise readline auf 2.17 aktualisiere, kann ich libreadline.so.2.17 einfach neben der vorhandenen Bibliothek installieren und den symbolischen Link libreadline.so.2 von libreadline.so.2.13 nach libreadline.so.2.17 verschieben.
quelle