- const load_command* startCmds = NULL;
- if ( mh->magic == MH_MAGIC_64 )
- startCmds = (load_command*)((char *)mh + sizeof(mach_header_64));
- else if ( mh->magic == MH_MAGIC )
- startCmds = (load_command*)((char *)mh + sizeof(mach_header));
- else
- return 0; // not a mach-o file, or wrong endianness
-
- const load_command* const cmdsEnd = (load_command*)((char*)startCmds + mh->sizeofcmds);
- const version_min_command* versCmd;
- const dylib_command* dylibCmd;
- const load_command* cmd = startCmds;
- const char* dylibName;
-#if __IPHONE_OS_VERSION_MIN_REQUIRED
- uint32_t foundationVers = 0;
-#else
- uint32_t libSystemVers = 0;
-#endif
- for(uint32_t i = 0; i < mh->ncmds; ++i) {
- switch ( cmd->cmd ) {
-#if __IPHONE_OS_VERSION_MIN_REQUIRED
- case LC_VERSION_MIN_IPHONEOS:
-#else
- case LC_VERSION_MIN_MACOSX:
-#endif
- versCmd = (version_min_command*)cmd;
-#ifdef DICE_KIND_DATA
- if ( versCmd->sdk != 0 )
- return versCmd->sdk; // found explicit SDK version
-#else
- if ( versCmd->reserved != 0 )
- return versCmd->reserved; // found explicit SDK version
-#endif
- break;
- case LC_LOAD_DYLIB:
- case LC_LOAD_WEAK_DYLIB:
- case LC_LOAD_UPWARD_DYLIB:
- dylibCmd = (dylib_command*)cmd;
- dylibName = (char*)dylibCmd + dylibCmd->dylib.name.offset;
-#if __IPHONE_OS_VERSION_MIN_REQUIRED
- if ( strcmp(dylibName, "/System/Library/Frameworks/Foundation.framework/Foundation") == 0 )
- foundationVers = dylibCmd->dylib.current_version;
-#else
- if ( strcmp(dylibName, "/usr/lib/libSystem.B.dylib") == 0 )
- libSystemVers = dylibCmd->dylib.current_version;
-#endif
- break;
- }
- // <rdar://problem/14381579> sanity check size of command
- if ( (cmd->cmdsize < 8) || (cmd->cmdsize > mh->sizeofcmds) )
- return 0;
- cmd = (load_command*)((char *)cmd + cmd->cmdsize);
- // <rdar://problem/14381579> bounds check
- if ( (cmd > cmdsEnd) || (cmd < startCmds) )
- return 0;
- }
-
- struct DylibToOSMapping {
- uint32_t dylibVersion;
- uint32_t osVersion;
- };
-
-#if __IPHONE_OS_VERSION_MIN_REQUIRED
- static const DylibToOSMapping foundationMapping[] = {
- { PACKED_VERSION(678,24,0), DYLD_IOS_VERSION_2_0 },
- { PACKED_VERSION(678,26,0), DYLD_IOS_VERSION_2_1 },
- { PACKED_VERSION(678,29,0), DYLD_IOS_VERSION_2_2 },
- { PACKED_VERSION(678,47,0), DYLD_IOS_VERSION_3_0 },
- { PACKED_VERSION(678,51,0), DYLD_IOS_VERSION_3_1 },
- { PACKED_VERSION(678,60,0), DYLD_IOS_VERSION_3_2 },
- { PACKED_VERSION(751,32,0), DYLD_IOS_VERSION_4_0 },
- { PACKED_VERSION(751,37,0), DYLD_IOS_VERSION_4_1 },
- { PACKED_VERSION(751,49,0), DYLD_IOS_VERSION_4_2 },
- { PACKED_VERSION(751,58,0), DYLD_IOS_VERSION_4_3 },
- { PACKED_VERSION(881,0,0), DYLD_IOS_VERSION_5_0 },
- { PACKED_VERSION(890,1,0), DYLD_IOS_VERSION_5_1 },
- { PACKED_VERSION(992,0,0), DYLD_IOS_VERSION_6_0 },
- { PACKED_VERSION(993,0,0), DYLD_IOS_VERSION_6_1 },
- { PACKED_VERSION(1038,14,0),DYLD_IOS_VERSION_7_0 }, // check final
- { PACKED_VERSION(0,0,0), DYLD_IOS_VERSION_7_0 }
- };
-
- if ( foundationVers != 0 ) {
- uint32_t lastOsVersion = 0;
- for (const DylibToOSMapping* p=foundationMapping; ; ++p) {
- if ( p->dylibVersion == 0 )
- return p->osVersion;
- if ( foundationVers < p->dylibVersion )
- return lastOsVersion;
- lastOsVersion = p->osVersion;
- }
- }
-
-#else
- // Note: versions are for the GM release. The last entry should
- // always be zero. At the start of the next major version,
- // a new last entry needs to be added and the previous zero
- // updated to the GM dylib version.
- static const DylibToOSMapping libSystemMapping[] = {
- { PACKED_VERSION(88,1,3), DYLD_MACOSX_VERSION_10_4 },
- { PACKED_VERSION(111,0,0), DYLD_MACOSX_VERSION_10_5 },
- { PACKED_VERSION(123,0,0), DYLD_MACOSX_VERSION_10_6 },
- { PACKED_VERSION(159,0,0), DYLD_MACOSX_VERSION_10_7 },
- { PACKED_VERSION(169,3,0), DYLD_MACOSX_VERSION_10_8 },
- { PACKED_VERSION(1197,0,0), DYLD_MACOSX_VERSION_10_9 },
- { PACKED_VERSION(0,0,0), DYLD_MACOSX_VERSION_10_9 }
- };
-
- if ( libSystemVers != 0 ) {
- uint32_t lastOsVersion = 0;
- for (const DylibToOSMapping* p=libSystemMapping; ; ++p) {
- if ( p->dylibVersion == 0 )
- return p->osVersion;
- if ( libSystemVers < p->dylibVersion )
- return lastOsVersion;
- lastOsVersion = p->osVersion;
- }
- }
-#endif
-
- return 0;