aboutsummaryrefslogtreecommitdiff
path: root/lib/darwin/inject-asm-raw.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/darwin/inject-asm-raw.c')
-rw-r--r--lib/darwin/inject-asm-raw.c41
1 files changed, 23 insertions, 18 deletions
diff --git a/lib/darwin/inject-asm-raw.c b/lib/darwin/inject-asm-raw.c
index 3b0f1ce..9b272e7 100644
--- a/lib/darwin/inject-asm-raw.c
+++ b/lib/darwin/inject-asm-raw.c
@@ -8,32 +8,37 @@
struct baton {
int (*pthread_create)(int *, void *, void *(*)(void *), void *);
- void (*dlopen)(const char *, int);
+ void *(*dlopen)(const char *, int);
+ void *(*dlsym)(void *, const char *);
+ int (*munmap)(void *, long);
const char *path;
- long done;
+ /* bsd_thread_func uses this to wait for entry to go away */
+ long sem_port;
+ long nshuttle;
+ char shuttle[0];
};
-struct baton2 {
- void (*dlopen)(const char *, int);
- const char *path;
- int port;
-};
-static void *bsd_thread_func(void *);
+static int bsd_thread_func(void *);
#if defined(__i386__)
__attribute__((fastcall))
#endif
-/* xxx need to change this to have host allocate two pages - way easier */
void entry(struct baton *baton) {
int pt;
- baton->pthread_create(&pt, 0, bsd_thread_func, baton);
- unsigned long ptr = (unsigned long) baton & ~(_PAGE_SIZE - 1);
- while (!baton->done)
- manual_syscall(-62 /*clock_sleep_trap */, 0, 1, 0, 8000 /*ns*/, -1);
- manual_syscall(361 /*bsdthread_terminate*/, ptr, 0x2000, 0, 0, 0);
+ baton->pthread_create(&pt, 0, (void *) bsd_thread_func, baton);
+ manual_syscall(361 /* bsdthread_terminate */, 0, 0, 0, baton->sem_port);
((void (*)()) 0xbad)();
}
-static void *bsd_thread_func(void *arg) {
+static int bsd_thread_func(void *arg) {
struct baton *baton = arg;
- baton->dlopen(baton->path, 0);
- baton->done = 1;
- return 0;
+ void *r = baton->dlopen(baton->path, 0);
+ if (r) {
+ __attribute__((section("__TEXT,__text")))
+ static char name[] = "substitute_init";
+ void (*init)(void *, unsigned long) = baton->dlsym(r, name);
+ if (init)
+ init(baton->shuttle, baton->nshuttle);
+
+ }
+ manual_syscall(-36 /* semaphore_wait_trap */, baton->sem_port, 0, 0, 0);
+ unsigned long ptr = (unsigned long) baton & ~(_PAGE_SIZE - 1);
+ return baton->munmap((void *) ptr, 0x2000);
}