6 Stimmen

GCC / Linux: Hinzufügen einer statischen Bibliothek zu einem .so?

Ich habe ein Programm, das ein Plugin-System implementiert, indem es eine Funktion aus plugin_name.so dynamisch lädt (wie üblich).

Aber andererseits habe ich eine statische "Helfer"-Bibliothek (nennen wir sie helper.a), deren Funktionen sowohl vom Hauptprogramm als auch von der Hauptfunktion im Plugin verwendet werden. Sie müssen in keiner Weise zusammenarbeiten, es handelt sich nur um Hilfsfunktionen für Textmanipulation und ähnliches.

Dieses Programm kann nach dem Start nicht neu geladen oder neu gestartet werden, deshalb erwarte ich, dass die neue "Helfer"-Funktionalität aus dem Plugin stammt, nicht aus dem Hauptprogramm.

Also lautet meine Frage.. ist es möglich, den "Plugin-Funktionscode" in der .so dazu zu zwingen (statisch gegen?) eine andere (vielleicht neuere) Version von "helper" als das Hauptprogramm zu verwenden?

Wie könnte dies erreicht werden? eventuell durch statisches Linken oder durch das Hinzufügen von helper.a zu plugin_name.so?

6voto

Employed Russian Punkte 180738

Die Antwort von Nick Meyer ist auf Windows und AIX korrekt, aber auf allen anderen UNIX-Plattformen standardmäßig unwahrscheinlich korrekt.

Auf den meisten UNIX-Plattformen unterhält der Laufzeitlader einen einzigen Namensraum für alle Symbole. Wenn Sie also foo_helper in a.out definieren und auch in plugin.so, und dann foo_helper aus einem von ihnen aufrufen, wird für beide Aufrufe standardmäßig die erste Definition verwendet, die dem Laufzeitlader sichtbar ist (normalerweise die von a.out).

Darüber hinaus wird das Bild durch die Tatsache kompliziert, dass foo_helper möglicherweise nicht aus a.out exportiert wird (und dem Laufzeitlader somit unsichtbar ist), es sei denn, Sie verwenden das Flag -rdynamic oder ein anderes gemeinsam genutztes Bibliothek bezieht sich darauf. Mit anderen Worten, die Dinge können so erscheinen, wie Nick sie beschrieben hat, doch wenn Sie eine gemeinsam genutzte Bibliothek zur Verknüpfungszeile von a.out hinzufügen, funktionieren sie nicht mehr auf diese Weise.

Auf ELF-Plattformen (wie Linux) haben Sie eine große Kontrolle über die Sichtbarkeit und Bindung von Symbolen. Siehe Beschreibung von -fvisibility=hidden und -rdynamic in der Man-Page von GCC sowie -Bsymbolic in der Linker-Man-Page.

Die meisten anderen UNIX-Plattformen haben ebenfalls Möglichkeiten, die Symbolbindungen zu steuern, aber dies ist zwangsläufig plattformspezifisch.

1voto

Nick Meyer Punkte 37405

Wenn Ihr Hauptprogramm und die dynamische Bibliothek beide statisch an helper.a verknüpft sind, müssen Sie sich keine Gedanken darüber machen, verschiedene Versionen von helper.a zu mischen (solange Sie keine Dinge wie Zeiger, die in helper.a allokiert wurden, zwischen den .exe und .so-Grenzen übergeben).

Der für helper.a erforderliche Code wird in das tatsächliche Binärprogramm eingefügt, wenn Sie es verknüpfen. Wenn Sie also aus der .exe in helper.a aufrufen, führen Sie Code aus dem Code-Segment Ihres ausführbaren Bildes aus, und wenn Sie aus der .so in helper.a aufrufen, führen Sie Code aus dem Teil des Adressraums aus, in dem die .so geladen wurde. Selbst wenn Sie dieselbe Funktion innerhalb von helper.a aufrufen, rufen Sie je nachdem, ob der Aufruf aus der .exe oder der .so erfolgt, zwei verschiedene 'Instanzen' dieser Funktion auf.

0voto

user951501 Punkte 21

Ich denke, diese Frage ist die gleiche wie deine. Wie erzwinge ich, dass Symbole aus einer statischen Bibliothek in einem shared-Library-Build enthalten sind?

Die Option --whole-archive des Linkers sollte dies tun. Sie würden sie verwenden wie z.B.

gcc -o libmyshared.so foo.o -lanothersharedlib -Wl,--whole-archive -lmystaticlib

und es funktioniert für mich.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X