2010-02-14 23 views
10

C'è un modo per trovare la versione di un dylib usando il suo percorso? Sto cercando qualcosa che accetti gli stessi argomenti di dlopen. Ho esaminato NSVersionOfRunTimeLibrary, ma dalla mia lettura della documentazione sembra che abbia la versione del dylib corrente, non quella specificata nel percorso.Trovare la versione di dylib usando dlopen

Grazie

risposta

14

Run otool -L su di esso, e mostrerà la sua realtà di versione. Ho scelto libSystem.B come ha versione diversa nei 10.4 e 10.5 SDK:

$ otool -L /Developer/SDKs/MacOSX10.4u.sdk/usr/lib/libSystem.B.dylib 
/Developer/SDKs/MacOSX10.4u.sdk/usr/lib/libSystem.B.dylib: 
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 88.3.11) 
    /usr/lib/system/libmathCommon.A.dylib (compatibility version 1.0.0, current version 220.0.0) 
$ otool -L /Developer/SDKs/MacOSX10.5.sdk/usr/lib/libSystem.B.dylib 
/Developer/SDKs/MacOSX10.5.sdk/usr/lib/libSystem.B.dylib: 
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 111.1.4) 
    /usr/lib/system/libmathCommon.A.dylib (compatibility version 1.0.0, current version 292.4.0) 

(vedere come il primo ha 88.3.11 versione, mentre la seconda ha 111.1.4). Questo esempio dimostra anche che non tutte le librerie sono collegamenti simbolici ai file con il numero di versione in loro:

$ ll /Developer/SDKs/MacOSX10.*.sdk/usr/lib/libSystem.B.dylib 
-rwxr-xr-x 1 root wheel 749K May 15 2009 /Developer/SDKs/MacOSX10.4u.sdk/usr/lib/libSystem.B.dylib 
-rwxr-xr-x 1 root wheel 670K May 15 2009 /Developer/SDKs/MacOSX10.5.sdk/usr/lib/libSystem.B.dylib 
-rwxr-xr-x 1 root wheel 901K Sep 25 00:21 /Developer/SDKs/MacOSX10.6.sdk/usr/lib/libSystem.B.dylib 

Qui, i file non hanno il numero di versione nel loro nome.

MODIFICA: una seconda soluzione è utilizzare NSVersionOfRunTimeLibrary in un programma di test, in cui si forza il carico della libreria che si desidera controllare. Creare un programma libversion della fonte seguente C:

#include <stdio.h> 
#include <mach-o/dyld.h> 

int main (int argc, char **argv) 
{ 
    printf ("%x\n", NSVersionOfRunTimeLibrary (argv[1])); 
    return 0; 
} 

Poi, si chiamano così:

$ DYLD_INSERT_LIBRARIES=/usr/lib/libpam.2.dylib ./a.out libpam.2.dylib 
30000 

(qui, il numero di versione viene stampato come esadecimale, ma è possibile adattare alle proprie esigenze .)

+2

Risposta molto migliore, cancellata la mia. – EightyEight

4

È possibile controllare il codice sorgente di NSVersionOfRunTimeLibrary qui: http://www.opensource.apple.com/source/dyld/dyld-132.13/src/dyldAPIsInLibSystem.cpp

Basato su tha t è possibile creare la propria versione che sostituisce if(names_match(install_name, libraryName) == TRUE) con if(strcmp(_dyld_get_image_name(i), libraryName) == 0) Questo risolverà il problema che l'originale si aspettava il nome della libreria senza percorso completo, la versione modificata si aspetta il percorso completo, ma continuerà a cercare nei dylibs caricati.

#include <mach-o/dyld.h> 
int32_t 
library_version(const char* libraryName) 
{ 
    unsigned long i, j, n; 
    struct load_command *load_commands, *lc; 
    struct dylib_command *dl; 
    const struct mach_header *mh; 

    n = _dyld_image_count(); 
    for(i = 0; i < n; i++){ 
     mh = _dyld_get_image_header(i); 
     if(mh->filetype != MH_DYLIB) 
     continue; 
     load_commands = (struct load_command *) 
#if __LP64__ 
       ((char *)mh + sizeof(struct mach_header_64)); 
#else 
       ((char *)mh + sizeof(struct mach_header)); 
#endif 
     lc = load_commands; 
     for(j = 0; j < mh->ncmds; j++){ 
     if(lc->cmd == LC_ID_DYLIB){ 
      dl = (struct dylib_command *)lc; 
      if(strcmp(_dyld_get_image_name(i), libraryName) == 0) 
      return(dl->dylib.current_version); 
     } 
     lc = (struct load_command *)((char *)lc + lc->cmdsize); 
     } 
    } 
    return(-1); 
} 
+0

La risposta è parziale, ma penso che questo dovrebbe essere parte della soluzione. – Till

+0

Per quanto riguarda "Questo risolverà il problema che ora si aspetta il nome completo": non penso che sia davvero un problema, dato che adk sta cercando di interrogare una versione della libreria dal suo percorso (che include il nome). –

Problemi correlati