Created
February 2, 2025 01:12
-
-
Save EthanArbuckle/372f97a92b681aaf58b69d47f30d9e6d to your computer and use it in GitHub Desktop.
Make Music.app run in iOS Simulator
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
// | |
// sim_dylib_loader.m | |
// objsee | |
// | |
// Created by Ethan Arbuckle on 1/31/25. | |
// | |
#include <Foundation/Foundation.h> | |
#include <objc/runtime.h> | |
#include <dlfcn.h> | |
#define WHILE_IGNORING_SIGNALS(code) ({ \ | |
int __result = 0; \ | |
struct sigaction __old_sa_segv, __old_sa_bus; \ | |
if (!g_sig_ignoring) { \ | |
g_sig_ignoring = 1; \ | |
install_signal_handlers(&__old_sa_segv, &__old_sa_bus); \ | |
if ((__result = sigsetjmp(g_sig_ignore_jmpbuf, 1)) == 0) { \ | |
code; \ | |
} \ | |
restore_signal_handlers(&__old_sa_segv, &__old_sa_bus); \ | |
g_sig_ignoring = 0; \ | |
} \ | |
__result; \ | |
}) | |
static __thread sigjmp_buf g_sig_ignore_jmpbuf; | |
static __thread volatile sig_atomic_t g_sig_ignoring = 0; | |
static void _sig_ignoring_handler(int signo) { | |
if (g_sig_ignoring) { | |
siglongjmp(g_sig_ignore_jmpbuf, signo); | |
} | |
} | |
static inline void install_signal_handlers(struct sigaction * _Nonnull old_sa_segv, struct sigaction * _Nonnull old_sa_bus) { | |
struct sigaction sa; | |
memset(&sa, 0, sizeof(sa)); | |
sa.sa_handler = _sig_ignoring_handler; | |
sa.sa_flags = 0; | |
sigemptyset(&sa.sa_mask); | |
sigaction(SIGSEGV, &sa, old_sa_segv); | |
sigaction(SIGBUS, &sa, old_sa_bus); | |
} | |
static inline void restore_signal_handlers(const struct sigaction * _Nonnull old_sa_segv, const struct sigaction * _Nonnull old_sa_bus) { | |
sigaction(SIGSEGV, old_sa_segv, NULL); | |
sigaction(SIGBUS, old_sa_bus, NULL); | |
} | |
__attribute__((constructor)) static void launch_apple_music(void) { | |
NSString *processName = [[NSProcessInfo processInfo] processName]; | |
if (![processName isEqualToString:@"Music"]) { | |
return; | |
} | |
// Codesigning limitations make it such that Music possesses no entitlements when installed under Simulator. | |
// Missing entitlements cause several issues that are worked around here with method swizzling | |
dlopen("/System/Library/Frameworks/CloudKit.framework/CloudKit", RTLD_NOW); | |
// CloudKit raises an exception about missing container ID. Fix by hardcoding a container ID in `-[CKContainerID initWithContainerIdentifier:environment:]` | |
SEL initWithContainerIdentifier = sel_registerName("initWithContainerIdentifier:environment:"); | |
Method initWithContainerIdentifier_method = class_getInstanceMethod(objc_getClass("CKContainerID"), initWithContainerIdentifier); | |
IMP orig_initWithContainerIdentifier_imp = method_getImplementation(initWithContainerIdentifier_method); | |
IMP newImp = imp_implementationWithBlock(^(__unsafe_unretained id self, NSString *containerID, id environment) { | |
return ((id (*)(id, SEL, id, id))orig_initWithContainerIdentifier_imp)(self, initWithContainerIdentifier, @"fake", environment); | |
}); | |
method_setImplementation(initWithContainerIdentifier_method, newImp); | |
// Mock in-process entitlement checks | |
SEL hasBoolEntitlement = sel_registerName("hasBoolEntitlement:shouldLogForMissingEntitlement:"); | |
Method hasBoolEntitlementMethod = class_getClassMethod(objc_getClass("NSObject"), hasBoolEntitlement); | |
IMP newHasBoolEntitlement = imp_implementationWithBlock(^BOOL(Class self, NSString *entitlement, BOOL shouldLog) { | |
return YES; | |
}); | |
method_setImplementation(hasBoolEntitlementMethod, newHasBoolEntitlement); | |
// Crashes are expected, so kick off UIApplicationMain in a signal-ignoring context. | |
// On success, run the runloop to keep the bootstrapped app alive. | |
// On failure, the launch will be attempted again by the app's usual entry point | |
WHILE_IGNORING_SIGNALS({ | |
void *_UIApplicationMain = dlsym(dlopen(NULL, 0), "UIApplicationMain"); | |
if (_UIApplicationMain) { | |
((void (*)(int, char **, id, id))_UIApplicationMain)(0, NULL, nil, @"_TtC5Music19ApplicationDelegate"); | |
CFRunLoopRun(); | |
} | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment