diff options
author | comex | 2015-01-25 21:56:22 -0500 |
---|---|---|
committer | comex | 2015-01-25 22:01:25 -0500 |
commit | 1b5ec6c220f3ea457077a17f4cf6003502a06bb0 (patch) | |
tree | 19f8594402414d15b94c237d0f99e6efb6ac415e /lib | |
parent | this is dumb (diff) | |
download | substitute-1b5ec6c220f3ea457077a17f4cf6003502a06bb0.tar.gz |
right, fix cleanup. (compared to the old system, this avoids busywaiting, and properly frees the thread resources)
Diffstat (limited to 'lib')
-rw-r--r-- | lib/darwin/inject-asm-raw.c | 36 | ||||
-rw-r--r-- | lib/darwin/inject.c | 19 |
2 files changed, 49 insertions, 6 deletions
diff --git a/lib/darwin/inject-asm-raw.c b/lib/darwin/inject-asm-raw.c index 9b272e7..ca316f1 100644 --- a/lib/darwin/inject-asm-raw.c +++ b/lib/darwin/inject-asm-raw.c @@ -6,8 +6,14 @@ #define _PAGE_SIZE 0x1000 #endif +/* This is somewhat more complicated than it has to be because it does not use + * pthread_join, which depends on pthread_self, which would need to be + * initialized manually; the format of this has changed in the past, and could + * again. */ + struct baton { int (*pthread_create)(int *, void *, void *(*)(void *), void *); + int (*pthread_detach)(int); void *(*dlopen)(const char *, int); void *(*dlsym)(void *, const char *); int (*munmap)(void *, long); @@ -22,8 +28,9 @@ static int bsd_thread_func(void *); __attribute__((fastcall)) #endif void entry(struct baton *baton) { - int pt; + int pt = 0; baton->pthread_create(&pt, 0, (void *) bsd_thread_func, baton); + baton->pthread_detach(pt); manual_syscall(361 /* bsdthread_terminate */, 0, 0, 0, baton->sem_port); ((void (*)()) 0xbad)(); } @@ -39,6 +46,33 @@ static int bsd_thread_func(void *arg) { } manual_syscall(-36 /* semaphore_wait_trap */, baton->sem_port, 0, 0, 0); +#ifndef __i386__ + /* since we're munmapping our own code, this must be optimized into a jump + * (taill call elimination) */ unsigned long ptr = (unsigned long) baton & ~(_PAGE_SIZE - 1); return baton->munmap((void *) ptr, 0x2000); +#else + /* i386 can't normally eliminate tail calls in caller-cleanup calling + * conventions, unless the number of arguments is the same, so use a nasty + * hack */ + extern int jump_to_munmap(void *); + return jump_to_munmap(baton); +#endif } +#ifdef __i386__ +/* yuck */ +asm("jmp _entry;" + ".globl _jump_to_munmap;" + "_jump_to_munmap:" + "push %ebp;" + "mov %esp, %ebp;" + "sub $0x400, %ebp;" + "mov 8(%esp), %edx;" /* baton */ + "mov 16(%edx), %eax;" /* munmap */ + "and $~0xfff, %edx;" + "mov %edx, 8(%ebp);" + "movl $0x2000, 12(%ebp);" + "add $3, %eax;" /* !? */ + "jmp *%eax;" +); +#endif diff --git a/lib/darwin/inject.c b/lib/darwin/inject.c index 4e715d5..a74b057 100644 --- a/lib/darwin/inject.c +++ b/lib/darwin/inject.c @@ -390,7 +390,7 @@ got_symbol:; static int do_baton(const char *filename, size_t filelen, bool is64, mach_vm_address_t target_stackpage_end, mach_vm_address_t *target_stack_top_p, - uint64_t sym_addrs[static 4], + uint64_t sym_addrs[static 5], const struct shuttle *shuttle, size_t nshuttle, struct shuttle **target_shuttle_p, semaphore_t *sem_port_p, @@ -398,7 +398,7 @@ static int do_baton(const char *filename, size_t filelen, bool is64, char **error) { int ret; - size_t baton_len = 7 * (is64 ? 8 : 4); + size_t baton_len = 8 * (is64 ? 8 : 4); size_t shuttles_len = nshuttle * sizeof(struct shuttle); size_t filelen_rounded = (filelen + 7) & ~7; size_t total_len = baton_len + shuttles_len + filelen_rounded; @@ -480,6 +480,7 @@ static int do_baton(const char *filename, size_t filelen, bool is64, sym_addrs[1], sym_addrs[2], sym_addrs[3], + sym_addrs[4], target_stack_top + baton_len + shuttles_len, sem_port, nshuttle @@ -544,10 +545,12 @@ int substitute_dlopen_in_pid(int pid, const char *filename, int options, if ((ret = find_foreign_images(task, images, 3, error)) > 0) goto fail; - uint64_t pthread_create_addr, dlopen_addr, dlsym_addr, munmap_addr; + uint64_t pthread_create_addr, pthread_detach_addr; + uint64_t dlopen_addr, dlsym_addr, munmap_addr; cpu_type_t cputype; if (ret == FFI_SHORT_CIRCUIT) { pthread_create_addr = (uint64_t) pthread_create; + pthread_detach_addr = (uint64_t) pthread_detach; dlopen_addr = (uint64_t) dlopen; dlsym_addr = (uint64_t) dlsym; munmap_addr = (uint64_t) munmap; @@ -570,7 +573,7 @@ int substitute_dlopen_in_pid(int pid, const char *filename, int options, } syms[2]; } libs[3] = { {images[0].address, 2, {{"_dlopen", 0}, {"_dlsym", 0}}}, - {images[1].address, 1, {{"_pthread_create", 0}}}, + {images[1].address, 2, {{"_pthread_create", 0}, {"_pthread_detach", 0}}}, {images[2].address, 1, {{"_munmap", 0}}}, }; @@ -602,6 +605,8 @@ int substitute_dlopen_in_pid(int pid, const char *filename, int options, dlopen_addr = libs[0].syms[0].symaddr; dlsym_addr = libs[0].syms[1].symaddr; pthread_create_addr = libs[1].syms[0].symaddr; + pthread_detach_addr = libs[1].syms[1].symaddr; + munmap_addr = libs[2].syms[0].symaddr; } UNUSED @@ -632,7 +637,11 @@ int substitute_dlopen_in_pid(int pid, const char *filename, int options, goto fail; } - uint64_t sym_addrs[] = {pthread_create_addr, dlopen_addr, dlsym_addr, munmap_addr}; + uint64_t sym_addrs[] = {pthread_create_addr, + pthread_detach_addr, + dlopen_addr, + dlsym_addr, + munmap_addr}; mach_vm_address_t target_stack_top; if ((ret = do_baton(filename, filelen, cputype & CPU_ARCH_ABI64, target_code_page, &target_stack_top, |