2010-02-14 14 views
10

¿Hay alguna manera de encontrar la versión de un dylib usando su ruta? Estoy buscando algo que acepte los mismos argumentos que dlopen. He examinado NSVersionOfRunTimeLibrary, pero a partir de mi lectura de la documentación, parece que obtiene la versión del archivo dylib actual, no la especificada en la ruta.Encontrar la versión de dylib usando dlopen

Gracias

Respuesta

14

Run otool -L en él, y se mostrará su versión de realidad. Elegir libSystem.B ya que tiene versión diferente en los 10.4 y 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) 

(ver cómo el primero de ellos cuenta con la versión 88.3.11, mientras que el segundo tiene 111.1.4). Este ejemplo muestra también que no todas las bibliotecas son enlaces simbólicos a los archivos con el número de versión en ellos:

$ 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 

Aquí, los archivos no tienen el número de versión en su nombre.

EDIT: una segunda solución es usar NSVersionOfRunTimeLibrary en un programa de prueba, en el que fuerza la carga de la biblioteca que desea verificar. Crear un programa de libversion de la siguiente fuente C:

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

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

A continuación, se llaman así:

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

(aquí, el número de versión se imprime como hexadecimal, pero se puede adaptar a sus necesidades .)

+2

Mucho mejor respuesta, eliminado el mío. – EightyEight

4

puede comprobar el código fuente de NSVersionOfRunTimeLibrary aquí: http://www.opensource.apple.com/source/dyld/dyld-132.13/src/dyldAPIsInLibSystem.cpp

Basado en tha t Puede crear su propia versión que reemplace if(names_match(install_name, libraryName) == TRUE) con if(strcmp(_dyld_get_image_name(i), libraryName) == 0) Eso solucionará el problema de que el original esperaba el nombre de la biblioteca sin la ruta completa, la versión editada espera la ruta completa, pero seguirá buscando en los archivos dylibs cargados.

#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

Estás respondiendo parcialmente, pero aún así debería ser parte de la solución, creo. – Till

+0

Con respecto a "Eso solucionará el problema de que ahora espera el nombre completo": no creo que sea realmente un problema, ya que adk intenta consultar una versión de la biblioteca por su ruta (que incluye el nombre). –

Cuestiones relacionadas