Linux, GNU GCC, ld, Versions-Skripte und das ELF-Binärformat - Wie funktioniert es?

8

Ich versuche, mehr über die Bibliotheksversionierung in Linux zu lernen und wie alles funktioniert. Hier ist der Kontext:

- Ich habe zwei Versionen einer dynamischen Bibliothek, die den gleichen Satz von Schnittstellen offen legen, sagen wir libsome1.so und libsome2.so .

- Eine Anwendung ist mit libsome1.so verknüpft.

- Diese Anwendung verwendet libdl.so , um ein anderes Modul dynamisch zu laden, zB libmagic.so .

- Jetzt ist libmagic.so mit libsome2.so verknüpft. Ohne Verwendung von Linker-Skripts zum Ausblenden von Symbolen in libmagic.so werden zur Laufzeit alle Aufrufe von Schnittstellen in libsome2.so in libsome1.so aufgelöst. Dies kann bestätigt werden, indem der von libVersion() zurückgegebene Wert mit dem Wert des Makros LIB_VERSION verglichen wird.

- Also versuche ich als nächstes, libmagic.so mit einem Linker-Skript zu kompilieren und zu verlinken, das alle Symbole außer 3, die in libmagic.so definiert sind, ausblendet und von ihr exportiert wird. Das funktioniert ... Oder mindestens libVersion() und LIB_VERSION Werte stimmen überein (und es meldet Version 2 nicht 1).

- Wenn jedoch einige Datenstrukturen auf die Festplatte serialisiert werden, habe ich etwas Korruption festgestellt. Im Verzeichnis der Anwendung, wenn ich libsome1.so lösche und an seiner Stelle eine weiche Verknüpfung anstelle, die auf libsome2.so zeigt, funktioniert alles wie erwartet und die gleiche Beschädigung tritt nicht auf.

Ich kann nicht anders, als zu denken, dass dies aufgrund eines Konflikts in der Laufzeitauflösung der Symbole verursacht werden kann. Ich habe viele Dinge ausprobiert, wie zum Beispiel libsome2.so zu verlinken, so dass alle Symbole zu symbol@@VER_2 gehören (worüber ich immer noch verwirrt bin, weil der Befehl nm -CD libsome2.so immer noch Symbole als symbol und nicht symbol@@VER_2 auflistet) ... scheint nichts zu funktionieren !!! Hilfe !!!!!!

Edit: Ich hätte es früher erwähnen sollen, aber die fragliche App ist Firefox, und libsome1.so ist libsqlite3.so , die damit geliefert wird. Ich habe nicht die Möglichkeit, sie neu zu kompilieren. Auch das Verwenden von Versionsskripten zum Ausblenden von Symbolen scheint derzeit die einzige Lösung zu sein. Was passiert also wirklich, wenn Symbole versteckt sind? Werden sie "lokal" für die SO? Hat rtld keine Kenntnis von ihrer Existenz? Was passiert, wenn sich eine exportierte Funktion auf ein verstecktes Symbol bezieht?

    
themoondothshine 11.01.2011, 17:14
quelle

1 Antwort

4

Versuchen Sie, sowohl libsome1.so als auch libsome2.so zu kompilieren, um die Symbolversionierung mit jeweils einer eigenen Version hinzuzufügen (verwenden Sie die --version-script -Option zu ld ). Verknüpfen Sie dann die Anwendung und libmagic.so mit den neuen Bibliotheken. Dann sollten libsome1.so und libsome2.so vollständig getrennt sein.

Probleme können immer noch auftreten, wenn es nicht versionierte Verweise auf Symbole gibt. Solche Verweise können von versionierten Definitionen erfüllt werden (so dass es möglich ist, einer Bibliothek eine Symbolversionierung hinzuzufügen, ohne die Binärkompatibilität zu beeinträchtigen). Wenn mehrere Symbole mit demselben Namen vorhanden sind, kann es manchmal schwierig sein vorherzusagen, welcher verwendet wird.

In Bezug auf Werkzeuge zeigt nm -D keine Informationen zur Symbolversionierung an. Probieren Sie stattdessen objdump -T oder readelf -s .

    
jilles 14.01.2011 16:50
quelle

Tags und Links