-
-#define PACKED_VERSION(major, minor, tiny) ((((major) & 0xffff) << 16) | (((minor) & 0xff) << 8) | ((tiny) & 0xff))
-
-
-static bool getVersionLoadCommandInfo(const mach_header* mh, uint32_t* platform, uint32_t* minOS, uint32_t* sdk)
-{
- 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 false; // not a mach-o file, or wrong endianness
-
- const load_command* const cmdsEnd = (load_command*)((char*)startCmds + mh->sizeofcmds);
- const load_command* cmd = startCmds;
- for(uint32_t i = 0; i < mh->ncmds; ++i) {
- const load_command* nextCmd = (load_command*)((char *)cmd + cmd->cmdsize);
- if ( (cmd->cmdsize < 8) || (nextCmd > cmdsEnd) || (nextCmd < startCmds)) {
- return 0;
- }
- const version_min_command* versCmd;
- const build_version_command* buildVersCmd;
- switch ( cmd->cmd ) {
- case LC_VERSION_MIN_IPHONEOS:
- versCmd = (version_min_command*)cmd;
- *platform = PLATFORM_IOS;
- *minOS = versCmd->version;
- *sdk = versCmd->sdk;
- return true;
- case LC_VERSION_MIN_MACOSX:
- versCmd = (version_min_command*)cmd;
- *platform = PLATFORM_MACOS;
- *minOS = versCmd->version;
- *sdk = versCmd->sdk;
- return true;
- case LC_VERSION_MIN_TVOS:
- versCmd = (version_min_command*)cmd;
- *platform = PLATFORM_TVOS;
- *minOS = versCmd->version;
- *sdk = versCmd->sdk;
- return true;
- case LC_VERSION_MIN_WATCHOS:
- versCmd = (version_min_command*)cmd;
- *platform = PLATFORM_WATCHOS;
- *minOS = versCmd->version;
- *sdk = versCmd->sdk;
- return true;
- case LC_BUILD_VERSION:
- buildVersCmd = (build_version_command*)cmd;
- *platform = buildVersCmd->platform;
- *minOS = buildVersCmd->minos;
- *sdk = buildVersCmd->sdk;
- return true;
- }
- cmd = nextCmd;
- }
- return false;
-}
-
-#if !__WATCH_OS_VERSION_MIN_REQUIRED && !__TV_OS_VERSION_MIN_REQUIRED
-static uint32_t deriveSDKVersFromDylibs(const mach_header* mh)
-{
- 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 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) {
- const load_command* nextCmd = (load_command*)((char *)cmd + cmd->cmdsize);
- // <rdar://problem/14381579&16050962> sanity check size of command
- if ( (cmd->cmdsize < 8) || (nextCmd > cmdsEnd) || (nextCmd < startCmds)) {
- return 0;
- }
- switch ( cmd->cmd ) {
- case LC_LOAD_DYLIB:
- case LC_LOAD_WEAK_DYLIB:
- case LC_LOAD_UPWARD_DYLIB:
- dylibCmd = (dylib_command*)cmd;
- // sanity check dylib command layout
- if ( dylibCmd->dylib.name.offset > cmd->cmdsize )
- return 0;
- 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;
- }
- cmd = nextCmd;
- }
-
- struct DylibToOSMapping {
- uint32_t dylibVersion;
- uint32_t osVersion;
- };
-
- #if __IPHONE_OS_VERSION_MIN_REQUIRED
- static const DylibToOSMapping foundationMapping[] = {
- { PACKED_VERSION(678,24,0), 0x00020000 },
- { PACKED_VERSION(678,26,0), 0x00020100 },
- { PACKED_VERSION(678,29,0), 0x00020200 },
- { PACKED_VERSION(678,47,0), 0x00030000 },
- { PACKED_VERSION(678,51,0), 0x00030100 },
- { PACKED_VERSION(678,60,0), 0x00030200 },
- { PACKED_VERSION(751,32,0), 0x00040000 },
- { PACKED_VERSION(751,37,0), 0x00040100 },
- { PACKED_VERSION(751,49,0), 0x00040200 },
- { PACKED_VERSION(751,58,0), 0x00040300 },
- { PACKED_VERSION(881,0,0), 0x00050000 },
- { PACKED_VERSION(890,1,0), 0x00050100 },
- { PACKED_VERSION(992,0,0), 0x00060000 },
- { PACKED_VERSION(993,0,0), 0x00060100 },
- { PACKED_VERSION(1038,14,0),0x00070000 },
- { PACKED_VERSION(0,0,0), 0x00070000 }
- // We don't need to expand this table because all recent
- // binaries have LC_VERSION_MIN_ load command.
- };
-
- 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), 0x000A0400 },
- { PACKED_VERSION(111,0,0), 0x000A0500 },
- { PACKED_VERSION(123,0,0), 0x000A0600 },
- { PACKED_VERSION(159,0,0), 0x000A0700 },
- { PACKED_VERSION(169,3,0), 0x000A0800 },
- { PACKED_VERSION(1197,0,0), 0x000A0900 },
- { PACKED_VERSION(0,0,0), 0x000A0900 }
- // We don't need to expand this table because all recent
- // binaries have LC_VERSION_MIN_ load command.
- };
-
- 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;
-}
-#endif
-
-
-#if __WATCH_OS_VERSION_MIN_REQUIRED
-static uint32_t watchVersToIOSVers(uint32_t vers)
-{
- return vers + 0x00070000;
-}
-