Leider ist die maßgebliche Dokumentation der Quellcode. Die meisten Linux-Distributionen verwenden glibc oder seinen Fork, eglibc. Im Quellcode für beide, die Datei, die dokumentieren dlopen sollte() lautet wie folgt:
manual/libdl.texi
@c FIXME these are undocumented:
@c dladdr
@c dladdr1
@c dlclose
@c dlerror
@c dlinfo
@c dlmopen
@c dlopen
@c dlsym
@c dlvsym
Welche technische Spezifikation wird von der ELF specification und der POSIX-Standard gezogen werden kann, . Die ELF-Spezifikation macht ein schwaches Symbol sinnvoll. POSIX ist das eigentliche specification for dlopen() selbst.
Dies ist, was ich finde, der relevanteste Teil der ELF-Spezifikation zu sein.
Wenn der Linkeditor Archivbibliotheken durchsucht, extrahiert er das Archiv Mitglieder, die Definitionen nicht definierter globaler Symbole enthalten. Die Memberdefinition kann entweder ein globales oder ein schwaches Symbol sein.
Die ELF-Spezifikation bezieht sich nicht auf dynamisches Laden, so dass der Rest dieses Absatzes meine eigene Interpretation ist. Der Grund, warum ich das oben genannte relevant finde, ist, dass das Auflösen von Symbolen bei einem einzigen "wenn" auftritt. In dem von Ihnen angegebenen Beispiel versucht das dynamische Ladeprogramm a
, b.so
dynamisch zu laden, nicht definierte Symbole aufzulösen. Dies kann am Ende mit globalen oder schwachen Symbolen enden. Wenn das Programm dann dynamisch c.so
lädt, versucht der dynamische Lader erneut, nicht definierte Symbole aufzulösen. In dem von Ihnen beschriebenen Szenario wurden Symbole in b.so
mit schwachen Symbolen aufgelöst. Sobald diese aufgelöst sind, sind diese Symbole nicht länger undefiniert. Es spielt keine Rolle, ob globale oder schwache Symbole verwendet wurden, um sie zu definieren. Sie sind bereits nicht mehr definiert, wenn c.so
geladen ist.
Die ELF-Spezifikation gibt keine genaue Definition, was ein Link-Editor ist oder wann der Link-Editor Objektdateien kombinieren muss. Vermutlich ist dies kein Problem, da das Dokument dynamisch verknüpft ist.
POSIX beschreibt einige der dlopen() - Funktionalität, aber lässt viel bis zur Implementierung, einschließlich der Substanz Ihrer Frage. POSIX bezieht sich nicht auf das ELF-Format oder schwache Symbole im Allgemeinen. Für Systeme, die dlopen() implementieren, braucht es keine Vorstellung von schwachen Symbolen zu geben.
http://pubs.opengroup.org/onlinepubs/9699919799/functions/dlopen.html
POSIX-Konformität ist Teil eines anderen Standard, der Linux Standard Base. Linux-Distributionen können diesen Standards folgen oder auch nicht und können oder werden möglicherweise nicht in Schwierigkeiten geraten, zertifiziert zu werden. Zum Beispiel verstehe ich, dass eine formelle Unix-Zertifizierung durch Open Group ziemlich teuer ist - daher die Fülle von "Unix-ähnlichen" Systemen.
Ein interessanter Punkt über die Einhaltung der Standards von dlopen() ist auf der Wikipedia article for dynamic loading gemacht. dlopen(), wie von POSIX gefordert, gibt void * zurück, aber C, wie von ISO gefordert, sagt, dass void * ein Zeiger auf ein Objekt ist und ein solcher Zeiger nicht notwendigerweise mit einem Funktionszeiger kompatibel ist.
Es bleibt die Tatsache, dass jede Umwandlung zwischen Funktion und Objekt Zeiger als (von Natur aus nicht-portable) Umsetzung Erweiterung betrachtet werden muss, und dass kein „richtiger“ Weg für eine direkte Umwandlung vorhanden ist, da in In dieser Hinsicht widersprechen sich die POSIX- und ISO-Standards .
Die Standards, die existieren, widersprechen und welche Standards Dokumente dort sind möglicherweise nicht besonders sinnvoll. Hier schreibt Ulrich Drepper über seine Verachtung für die Open Group und ihre "Spezifikationen".
http://udrepper.livejournal.com/8511.html
ähnliche Stimmung wird von rodrigo in der Post verbunden ausgedrückt.
Der Grund, warum ich diese Änderung vorgenommen habe, ist wirklich nicht mehr konformen (es ist schön, aber kein Grund, da niemand über das alte Verhalten beschwert) zu sein.
Nach hinein suchen, glaube ich, die richtige Antwort auf die Frage, wie Sie es, dass es gefragt haben, ist für dlopen()
in dieser Hinsicht keine richtige oder falsche Verhalten. Sobald eine Suche ein Symbol aufgelöst hat, ist es nicht länger undefiniert und bei nachfolgenden Suchen versucht der dynamische Lader nicht, das bereits definierte Symbol aufzulösen.
Schließlich, wie Sie in den Kommentaren angeben, ist das, was Sie im ursprünglichen Beitrag beschreiben, nicht korrekt. Dynamisch geladene, gemeinsam genutzte Bibliotheken können verwendet werden, um undefinierte Symbole in zuvor dynamisch geladenen, gemeinsam genutzten Bibliotheken aufzulösen. Tatsächlich ist dies nicht auf nicht definierte Symbole in dynamisch geladenem Code beschränkt. Hier ist ein Beispiel, in dem die ausführbare Datei selbst ein nicht definiertes Symbol enthält, das durch dynamisches Laden aufgelöst wird.
main.c
#include <dlfcn.h>
void say_hi(void);
int main(void) {
void* symbols_b = dlopen("./dyload.so", RTLD_NOW | RTLD_GLOBAL);
/* uh-oh, forgot to define this function */
/* better remember to define it in dyload.so */
say_hi();
return 0;
}
dyload.c
#include <stdio.h>
void say_hi(void) {
puts("dyload.so: hi");
}
Kompilieren und ausführen.
gcc-4.8 main -fpic -ldl -Wl,--unresolved-symbols=ignore-all -o main
gcc-4.8 dyload.c -shared -fpic -o dyload.so
$ ./main
dyload.so: hi
Beachten Sie, dass die Hauptdatei selbst als PIC kompiliert wurde.
Haben Sie sich [dieses PDF] (http://refspecs.linuxbase.org/elf/elf.pdf) angesehen? Viele interessante Daten, aber nicht sicher, ob es enthält, wonach Sie suchen. – rodrigo
@rodrigo: Nicht sicher, ob dies oder etwas ähnliches war, aber bisher beschrieben alle ELF-Dokumente, die ich gefunden habe, nur die dynamische Verknüpfung vor der Ausführung einer Binärdatei, nicht die Verknüpfung in dynamisch geladenen Objekten. Es ist ein langes Dokument, und ich hätte vielleicht an den falschen Stellen nachgesehen, aber bisher scheint es nicht das zu sein, wonach ich suche. – MvG
Und was ist das [Drepper Beitrag] (http://www.sourceware.org/ml/libc-hacker/2000-06/msg00029.html) und seine mehr oder weniger [verwandten Dokument] (http: // www. akkadia.org/drepper/dsohowto.pdf) (siehe Abschnitt 1.5.2)? Wie ich es interpretiere, werden schwache Symbole nur für statische Verknüpfungen verwendet. So würde 'dlopen()' keinen Unterschied zwischen schwachen und starken Symbolen machen. – rodrigo