aboutsummaryrefslogtreecommitdiff
path: root/lib/darwin/inject-asm-raw.c
blob: 9b272e79c7bbffecd09f576367d427ed637658c8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include "darwin/manual-syscall.h"

#ifdef __arm64__
#define _PAGE_SIZE 0x4000
#else
#define _PAGE_SIZE 0x1000
#endif

struct baton {
    int (*pthread_create)(int *, void *, void *(*)(void *), void *);
    void *(*dlopen)(const char *, int);
    void *(*dlsym)(void *, const char *);
    int (*munmap)(void *, long);
    const char *path;
    /* bsd_thread_func uses this to wait for entry to go away */
    long sem_port;
    long nshuttle;
    char shuttle[0];
};
static int bsd_thread_func(void *);
#if defined(__i386__)
__attribute__((fastcall))
#endif
void entry(struct baton *baton) {
    int pt;
    baton->pthread_create(&pt, 0, (void *) bsd_thread_func, baton);
    manual_syscall(361 /* bsdthread_terminate */, 0, 0, 0, baton->sem_port);
    ((void (*)()) 0xbad)();
}
static int bsd_thread_func(void *arg) {
    struct baton *baton = arg;
    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);
}