使用dlopen查找dylib版本

10

有没有一种方法可以通过其路径查找dylib的版本? 我正在寻找接受与dlopen相同参数的内容。 我已经查看了NSVersionOfRunTimeLibrary,但从我阅读文档的方式来看,它似乎获取当前dylib的版本,而不是指定路径中的版本。

谢谢

2个回答

15

运行otool -L命令,它将显示其实际版本。我选择libSystem.B因为在10.4和10.5 SDK中它有不同的版本:

运行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
在这里,文件名中没有版本号。
编辑:第二个解决方案是在测试程序中使用NSVersionOfRunTimeLibrary,在其中强制加载要检查的库。从以下C源代码创建程序libversion:
#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

(这里,版本号以十六进制形式打印,但您可以根据需求进行适应。)


2
更好的答案,我删除了我的。 - EightyEight

5
你可以在这里检查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);
}

你的回答部分正确,但我认为这只是解决方案的一部分。 - Till
关于“这将解决它现在期望完整名称的问题”:我认为这并不是真正的问题,因为adk正在尝试通过其路径(其中包括名称)查询库版本。 - F'x

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接