2009-11-05 16 views
11

Wie kann ich den Pfad der gemeinsam genutzten Bibliothek innerhalb der Bibliothek selbst abrufen?Bibliothekspfad, wenn dynamisch geladen?

Mit anderen Worten, nehmen wir an, dass Bibliothek X geladen wird mit dlopen(), wie bekomme ich Zugriff auf den Pfad, der verwendet wurde, um die besagte Bibliothek aus der Bibliothek selbst zu laden?

Beachten Sie, dass ich nicht den Agenten, der die Bibliothek an erster Stelle geladen haben kann mir diesen Parameter übergeben.

AKTUALISIERT: Hier Art und Weise, die mit statischen Variablen arbeitet:

std::string wdir; 

namespace { 
    class dynamic_library_load_unload_handler { 
     public: 
       dynamic_library_load_unload_handler(){ 
        Dl_info dl_info; 
        dladdr((void *) NP_Initialize, &dl_info); 

        std::string path(dl_info.dli_fname); 
        wdir = path.substr(0, path.find_last_of('/') +1); 
       } 
       ~dynamic_library_load_unload_handler(){ 
        // Code to execute when the library is unloaded 
       } 
    } dynamic_library_load_unload_handler_hook; 
} 
+0

Gibt es eine Option, um einige Umgebungsvariablen mit diesem Pfad zu setzen? Gibt es die Möglichkeit, einige tmp-Datei zu schreiben (ich weiß ... shtty Lösung :() – bua

+0

@bua: Wenn Push kommt, werde ich wahrscheinlich auf dem Dateisystem "Trampolin" brauchen ... aber ich versuche es finden Sie einen saubereren Weg. – jldupont

+4

Zu meiner Enttäuschung, auf Android dli_fname enthält nicht den Modul Pfad, nur Dateiname. –

Antwort

16

Der dynamische Linker mehrere Stellen tatsächlich durchsucht jede dynamische Bibliothek zu finden. Diese umfassen (vom Menschen ld.so):

  • Paths gegeben durch die Umgebungsvariable LD_LIBRARY_PATH
  • Paths eingebrannt in die binäre Last die Bibliothek unter dem Eintrag DT_RUNPATH
  • Die Cache-Datei /etc/ld.so .cache
  • /lib und/usr/lib

Wenn Sie den Pfad für eine bestimmte gemeinsam benutzte Bibliothek erhalten möchten, würde ich die dladdr Funktion empfehlen. Aus der Manpage:

Die Funktion dladdr() nimmt einen Funktionszeiger und versucht Name und Datei zu lösen, wo es sich befindet. Die Informationen werden in der Dl_info Struktur gespeichert:

typedef struct { 
    const char *dli_fname; /* Pathname of shared object that 
           contains address */ 
    void  *dli_fbase; /* Address at which shared object 
           is loaded */ 
    const char *dli_sname; /* Name of nearest symbol with address 
           lower than addr */ 
    void  *dli_saddr; /* Exact address of symbol named 
           in dli_sname */ 
} Dl_info; 

Wenn kein Symbol Adr, gefunden werden kann, dann dli_sname und dli_saddr werden auf NULL.

dladdr() gibt 0 bei Fehler und nicht Null bei Erfolg zurück.

So geben Sie es einfach einen Funktionszeiger, und es gibt Ihnen den Namen der Datei, die es liefert und eine Reihe anderer Informationen. So zum Beispiel könnten Sie einen Konstruktor in einem Bibliotheksaufruf haben diese auf sich selbst den vollständigen Pfad der Bibliothek, um herauszufinden:

#define _GNU_SOURCE 
#include <dlfcn.h> 
#include <stdio.h> 

__attribute__((constructor)) 
void on_load(void) { 
    Dl_info dl_info; 
    dladdr((void *)on_load, &dl_info); 
    fprintf(stderr, "module %s loaded\n", dl_info.dli_fname); 
} 

Diese Funktion auf OS X mit der gleichen Semantik auch funktioniert.

+0

Funktioniert wie ein Charme ... danke! – jldupont

+0

AKTUALISIERT: der Nachteil, den ich mit Ihrer Lösung gefunden: andere ctors sind nicht Wenn also eine C++ - Variable irgendeiner Art als statisch deklariert wird, kann nicht von 'on_load' aus zugegriffen werden. – jldupont

+2

@jldupont: Das '__attribute __ ((Konstruktor))' ist genau der gleiche Mechanismus, der zum Aufruf von Konstruktoren von statischen Variablen in C++ verwendet wird, außer dass gcc es auch auf diese Weise in C verfügbar macht. Daher wird die Reihenfolge nicht über Übersetzungseinheiten hinweg angegeben. Gcc erlaubt es jedoch, sie durch Hinzufügen einer Priorität wie '__attribut __ ((constructor (101)))' anzugeben. Die Priorität der Konstruktoren kann angegeben werden, indem '__attribute __ ((init_priority (500)))' zur Klasse hinzugefügt wird, aber ich kann nirgends die Standardpriorität finden. Niedrigere Priorität bedeutet, dass Konstruktor früher und Destruktor später aufgerufen wird. –

Verwandte Themen