aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcomex2015-07-16 13:54:46 -0400
committercomex2015-07-16 13:54:46 -0400
commit67f060e2c68da1f3918aaa745030fc24ffaedfc7 (patch)
tree3dfce62c60e049295a1e563d1feb8c8d9500d301
parentPSH thread safety fix/minor cleanup (diff)
downloadsubstitute-67f060e2c68da1f3918aaa745030fc24ffaedfc7.tar.gz
save/load state
-rw-r--r--darwin-bootstrap/substituted.m84
1 files changed, 82 insertions, 2 deletions
diff --git a/darwin-bootstrap/substituted.m b/darwin-bootstrap/substituted.m
index f30ab9f..560d1ac 100644
--- a/darwin-bootstrap/substituted.m
+++ b/darwin-bootstrap/substituted.m
@@ -1,7 +1,10 @@
-#import <Foundation/Foundation.h>
-#import <CoreFoundation/CoreFoundation.h>
#include "darwin/xxpc.h"
#include "substitute.h"
+#import <Foundation/Foundation.h>
+#import <CoreFoundation/CoreFoundation.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <mach/vm_param.h>
void *vproc_swap_complex(void *vp, int key, xxpc_object_t inval,
__strong xxpc_object_t *outval);
@@ -21,6 +24,81 @@ static enum {
static NSSet *g_springboard_loaded_dylibs;
static NSSet *g_springboard_last_loaded_dylibs;
+static bool load_state() {
+ int fd = shm_open("com.ex.substituted.state", O_RDONLY);
+ if (fd == -1)
+ return false;
+ struct stat st;
+ if (fstat(fd, &st)) {
+ NSLog(@"fstat error");
+ return false;
+ }
+ size_t size = (size_t) st.st_size;
+ /* note: can't have concurrent modification */
+ void *buf = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (buf == MAP_FAILED) {
+ NSLog(@"mmap error");
+ return false;
+ }
+ NSData *nsd = [NSData dataWithBytesNoCopy:buf length:size];
+ NSError *err = nil;
+ id result = [NSPropertyListSerialization propertyListWithData:nsd
+ options:NSPropertyListImmutable
+ format:NULL error:&err];
+ if (err)
+ NSLog(@"propertyListWithData: %@", err);
+ if (!result)
+ return false;
+ if (![result isKindOfClass:[NSSet class]]) {
+ NSLog(@"loaded data is not NSSet - newer version?");
+ return false;
+ }
+ for (id str in result) {
+ if (![str isKindOfClass:[NSString class]]) {
+ NSLog(@"loaded data member is not NSString");
+ return false;
+ }
+ }
+ g_springboard_last_loaded_dylibs = result;
+ munmap(buf, size);
+ close(fd);
+ return true;
+}
+
+static bool save_state() {
+ NSError *err = nil;
+ NSData *data = [NSPropertyListSerialization
+ dataWithPropertyList:g_springboard_last_loaded_dylibs
+ format:NSPropertyListBinaryFormat_v1_0 options:0
+ error:&err];
+ if (err)
+ NSLog(@"dataWithPropertyList: %@", err);
+ if (!data)
+ return false;
+ int fd = shm_open("com.ex.substituted.state", O_RDWR | O_CREAT | O_TRUNC,
+ 0644);
+ if (fd == -1) {
+ NSLog(@"shm_open error (write)");
+ return false;
+ }
+ size_t size = ([data length] + PAGE_MASK) & ~PAGE_MASK;
+ if (ftruncate(fd, size)) {
+ NSLog(@"ftruncate error (%zu)", size);
+ return false;
+ }
+
+ void *buf = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (buf == MAP_FAILED) {
+ NSLog(@"mmap error (write)");
+ return false;
+ }
+
+ memcpy(buf, [data bytes], [data length]);
+ munmap(buf, size);
+ close(fd);
+ return true;
+}
+
extern kern_return_t bootstrap_look_up3(mach_port_t bp,
const char *service_name, mach_port_t *sp, pid_t target_pid,
const uuid_t instance_id, uint64_t flags);
@@ -279,6 +357,7 @@ enum convert_filters_ret {
if (_is_springboard) {
g_springboard_last_loaded_dylibs = g_springboard_loaded_dylibs;
g_springboard_loaded_dylibs = _loaded_dylibs = [NSMutableSet set];
+ save_state();
[self updateSpringBoardNeedsSafeThen:^{
[self handleMessageHelloRest:request];
@@ -418,6 +497,7 @@ bad:
int main() {
NSLog(@"hello from substituted");
install_deadlock_warning();
+ load_state();
xxpc_connection_t listener = xxpc_connection_create_mach_service(
"com.ex.substituted", dispatch_get_main_queue(),
XXPC_CONNECTION_MACH_SERVICE_LISTENER);