方法一:Run otool -L
on it, and it will show its actually version. I choose libSystem.B
as it has different version in the 10.4 and 10.5 SDKs:
$ 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)
方法二:
A second solution is to use NSVersionOfRunTimeLibrary
in a test program, in which you force load the library you want to check. Create a program libversion
from the following C source:
#include <stdio.h>
#include <mach-o/dyld.h>
int main (int argc, char **argv)
{
printf ("%x\n", NSVersionOfRunTimeLibrary (argv[1]));
return 0;
}
Then, you call it like that:
$ DYLD_INSERT_LIBRARIES=/usr/lib/libpam.2.dylib ./a.out libpam.2.dylib
30000
(here, the version number is printed as hexadecimal, but you can adapt to your needs.)
You can check the source code of NSVersionOfRunTimeLibrary here:http://www.opensource.apple.com/source/dyld/dyld-132.13/src/dyldAPIsInLibSystem.cpp
Based on that you can create your own version which replaces if(names_match(install_name, libraryName) == TRUE)
with if(strcmp(_dyld_get_image_name(i), libraryName) == 0)
That will fix the issue that the original expected the library name without full path, the edited version expects the full path, but it'll still search in the loaded dylibs.
#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);
}