Поиск версии dylib с помощью dlopen - PullRequest
10 голосов
/ 14 февраля 2010

Есть ли способ найти версию dylib по его пути? Я ищу что-то, что принимает те же аргументы, что и dlopen. Я посмотрел на NSVersionOfRunTimeLibrary, но из моего прочтения документации похоже, что он получает версию текущего dylib, а не ту, которая указана в пути.

Спасибо

Ответы [ 2 ]

14 голосов
/ 04 марта 2010

Запустите otool -L на нем, и он покажет свою актуальную версию. Я выбираю libSystem.B, так как она имеет разные версии в 10.4 и 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)

(посмотрите, как у первого версия 88.3.11, а у второго 111.1.4). Этот пример также показывает, что не все библиотеки являются символическими ссылками на файлы с номером версии в них:

$ 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

Здесь файлы не имеют номера версии в названии.

EDIT: Вторым решением является использование NSVersionOfRunTimeLibrary в тестовой программе, в которой вы принудительно загружаете библиотеку, которую хотите проверить. Создайте программу libversion из следующего источника C:

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

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

Затем вы называете это так:

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

(здесь номер версии печатается в шестнадцатеричном формате, но вы можете адаптироваться к вашим потребностям.)

5 голосов
/ 05 марта 2010

Вы можете проверить исходный код NSVersionOfRunTimeLibrary здесь: http://www.opensource.apple.com/source/dyld/dyld-132.13/src/dyldAPIsInLibSystem.cpp

Исходя из этого, вы можете создать свою собственную версию, которая заменяет if(names_match(install_name, libraryName) == TRUE) на if(strcmp(_dyld_get_image_name(i), libraryName) == 0) Это решит проблему, когда оригинал ожидал имя библиотеки без полного пути, отредактированная версия ожидает полный путь, но все равно будет искать в загруженных библиотеках.

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