-
-
Save dlevi309/b06e14607e4f7a9d2296145d0734bb32 to your computer and use it in GitHub Desktop.
Exchange Mach-O platform types with min version
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// main.m | |
// platform_swap @LOLgrep | |
// | |
#import <Foundation/Foundation.h> | |
#import <mach-o/loader.h> | |
#define PLATFORM_VISIONOS 11 | |
#define PLATFORM_VISIONOSSIMULATOR 12 | |
struct version { | |
int fix : 8; | |
int min : 8; | |
int max : 16; | |
}; | |
int main(int argc, const char * argv[]) { | |
if (argc != 6) { | |
printf("platform_swap platform_num major minor bugfix (i.e. convert MacOS M1 binary to iOS 10.3.1 -> platform_swap /tmp/afile 2 10 3 1\nSee PLATFORM_* in <mach-o/loader.h>\n"); | |
exit(1); | |
} | |
long platform = strtol(argv[2], NULL, 12); | |
if ( platform < 1 || platform > 12 ) { | |
printf("Invalid platform number %ld\n", platform); | |
exit(1); | |
} | |
long major = strtol(argv[3], NULL, 12); | |
long minor = strtol(argv[4], NULL, 12); | |
long bugfix = strtol(argv[5], NULL, 12); | |
NSString *file = [NSString stringWithUTF8String:argv[1]]; | |
NSURL *fileURL = [NSURL fileURLWithPath:file]; | |
if (!fileURL) { | |
printf("Can't find file %s\n", argv[1]); | |
exit(1); | |
} | |
NSMutableData *data = [NSMutableData dataWithContentsOfFile:file]; | |
char *ptr = (void*)[data bytes]; | |
int32_t *magic = (int32_t*)ptr; | |
if (*magic != MH_MAGIC_64) { | |
printf("Invalid header file\n"); | |
exit(1); | |
} | |
struct mach_header_64 *header = (void*)ptr; | |
struct load_command *cur = (void*)((uintptr_t)ptr + (uintptr_t)sizeof(struct mach_header_64)); | |
for (int i = 0; i < header->ncmds; i++) { | |
if (cur->cmd == LC_BUILD_VERSION) { | |
struct build_version_command*build = (void*)cur; | |
NSRange platform_range = NSMakeRange((uintptr_t)&build->platform - (uintptr_t)ptr, sizeof(build->platform)); | |
int32_t new_platform = (int)platform; | |
[data replaceBytesInRange:platform_range withBytes:&new_platform]; | |
NSRange version_range = NSMakeRange((uintptr_t)&build->minos - (uintptr_t)ptr, sizeof(build->minos)); | |
struct version new_version = {(int)bugfix, (int)minor, (int)major}; | |
[data replaceBytesInRange:version_range withBytes:&new_version]; | |
char *platform_name = NULL; | |
switch (platform) { | |
case PLATFORM_MACOS: | |
platform_name = "macos"; | |
break; | |
case PLATFORM_IOS: | |
platform_name = "ios"; | |
break; | |
case PLATFORM_TVOS: | |
platform_name = "tvos"; | |
break; | |
case PLATFORM_WATCHOS: | |
platform_name = "watchos"; | |
break; | |
case PLATFORM_BRIDGEOS: | |
platform_name = "bridgeos"; | |
break; | |
case PLATFORM_MACCATALYST: | |
platform_name = "maccatalyst"; | |
break; | |
case PLATFORM_IOSSIMULATOR: | |
platform_name = "iossimulator"; | |
break; | |
case PLATFORM_TVOSSIMULATOR: | |
platform_name = "tvossimulator"; | |
break; | |
case PLATFORM_WATCHOSSIMULATOR: | |
platform_name = "watchossimulator"; | |
break; | |
case PLATFORM_DRIVERKIT: | |
platform_name = "driverkit"; | |
break; | |
case PLATFORM_VISIONOS: | |
platform_name = "visionos"; | |
break; | |
case PLATFORM_VISIONOSSIMULATOR: | |
platform_name = "visionossimulator"; | |
break; | |
default: | |
break; | |
} | |
NSString *resolvedString = [NSString stringWithFormat:@"%@_%s", file, platform_name]; | |
[data writeToFile:resolvedString atomically:YES]; | |
printf("written to \"%s\"\n", resolvedString.UTF8String); | |
exit(0); | |
} | |
cur = (void*)(cur->cmdsize + (uintptr_t)cur); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment