2009-11-05 15 views
11

Jak mogę uzyskać ścieżkę udostępnionej biblioteki z samej biblioteki?ścieżka biblioteki po załadowaniu dynamicznym?

Innymi słowy, załóżmy, że biblioteka X została załadowana przy użyciu dlopen(), w jaki sposób uzyskać dostęp do ścieżki, która została użyta do załadowania biblioteki z samej biblioteki?

Należy zauważyć, że nie mogę pozwolić, aby agent, który załadował bibliotekę, najpierw przekazał mi ten parametr.

AKTUALIZACJA: Oto sposób, który współpracuje z zmiennych statycznych:

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

Czy istnieje opcja ustawienia zmiennej środowiskowej o tej ścieżce? Czy istnieje możliwość napisania pliku tmp (ja wiem ... rozwiązanie shtty :() – bua

+0

@bua: jeśli push przyjdzie do popchnięcia, prawdopodobnie będę potrzebował "trampoliny" w systemie plików ... ale staram się znajdź czystszy sposób: – jldupont

+4

Ku mojemu rozczarowaniu, na Androidzie dli_fname nie zawiera ścieżki do modułu, tylko nazwa pliku –

Odpowiedz

16

dynamiczny linker faktycznie przeszukuje kilka miejsc, aby znaleźć każdy dynamiczny biblioteki. Należą do nich (od człowieka ld.so):

  • Ścieżki podane przez zmienną środowiskową LD_LIBRARY_PATH
  • Ścieżki pieczone na obciążenia binarnym biblioteki pod wpisem
  • Plik cache /etc/ld.so DT_RUNPATH .cache
  • /lib i/usr/lib

Jeśli chcesz uzyskać ścieżkę dla konkretnej udostępnionej biblioteki, polecam funkcję dladdr. Ze strony podręcznika:

Funkcja dladdr() przyjmuje wskaźnik funkcji i próbuje rozpoznać nazwę i plik , gdzie się znajduje. Informacje te są przechowywane w strukturze Dl_info:

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; 

Jeśli nie można odnaleźć symbol dopasowania adr, następnie dli_sname i dli_saddr są ustawione na NULL.

dladdr() zwraca 0 w przypadku błędu i niezerową w przypadku powodzenia.

Po prostu podajesz mu wskaźnik funkcji, który podaje nazwę pliku, który go dostarcza, oraz kilka innych informacji. Tak na przykład, można mieć konstruktora w wywołaniu tej biblioteki na siebie, aby dowiedzieć się pełną ścieżkę do biblioteki:

#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); 
} 

Funkcja ta działa również na OS X z tymi samymi semantyki.

+0

Działa jak urok ... dzięki! – jldupont

+0

AKTUALIZACJA: Wada znaleziona przy twoim rozwiązaniu: inni cecorzy nie są Wywoływane przed twoim 'on_load'. Tak więc, jeśli pewnego rodzaju zmienna C++ jest zadeklarowana jako statyczna, nie można uzyskać do niej dostępu z' on_load'. Może być denerwujące. – jldupont

+2

@jldupont: '__attribute __ ((constructor)) jest dokładnie tym samym mechanizmem, który jest używany do wywoływania konstruktorów zmiennych statycznych w C++, z wyjątkiem tego, że gcc udostępnia je również w C w ten sposób. Więc kolejność nie jest określona w jednostkach tłumaczeniowych. Jednak gcc pozwala na określenie go przez dodanie priorytetu takiego jak '__attribute __ ((constructor (101))). Priorytet konstruktorów można określić, dodając do klasy '__attribute __ ((init_priority (500))), ale nigdzie nie znajduję domyślnego priorytetu. Niższy priorytet oznacza, że ​​konstruktor jest nazywany wcześniej i destruktor później. –

Powiązane problemy