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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
#ifdef __arm64__
#define _PAGE_SIZE 0x4000
#else
#define _PAGE_SIZE 0x1000
#endif
#define REG(var, reg) register long _##var asm(#reg) = var
#define OREG(var, reg) register long var asm(#reg)
__attribute__((always_inline))
#if defined(__x86_64__)
static int syscall(long s, long a, long b, long c, long d, long e) {
if (s < 0)
s = -s | 1 << 24;
else
s |= 2 << 24;
REG(s, rax); REG(a, rdi); REG(b, rsi); REG(c, rdx); REG(d, rcx);
OREG(out, rax);
asm volatile("push %1; syscall; pop %1"
: "=r"(out)
: "r"(e), "r"(_s), "r"(_a), "r"(_b), "r"(_c), "r"(_d));
return out;
}
#elif defined(__i386__)
static int syscall(long s, long a, long b, long c, long d, long e) {
REG(s, eax);
OREG(out, eax);
OREG(sp, ecx);
asm volatile("mov %%esp, %0" : "=r"(sp));
asm volatile("push %0" :: "r"(e));
asm volatile("push %0" :: "r"(d));
asm volatile("push %0" :: "r"(c));
asm volatile("push %0" :: "r"(b));
asm volatile("push %0" :: "r"(a));
asm volatile("call 1f; 1: pop %%edx; add $(2f-1b), %%edx;"
"sysenter; 2:"
: "=r"(out) : "r"(_s) : "edx");
return out;
}
#elif defined(__arm__)
static int syscall(long s, long a, long b, long c, long d, long e) {
REG(s, r12); REG(a, r0); REG(b, r1); REG(c, r2); REG(d, r3);
OREG(out, r0);
asm volatile("push {%1}; svc #0x80; pop {%1}"
: "=r"(out)
: "r"(e), "r"(_s), "r"(_a), "r"(_b), "r"(_c), "r"(_d));
return out;
}
#elif defined(__arm64__)
static int syscall(long s, long a, long b, long c, long d, long e) {
REG(s, x16); REG(a, x0); REG(b, x1); REG(c, x2); REG(d, x3);
OREG(out, x0);
asm volatile("str %1, [sp, #-0x10]!\n svc #0x80\n ldr %1, [sp], #0x10"
: "=r"(out)
: "r"(e), "r"(_s), "r"(_a), "r"(_b), "r"(_c), "r"(_d));
return out;
}
#else
#error ?
#endif
struct baton {
int (*pthread_create)(int *, void *, void *(*)(void *), void *);
void (*dlopen)(const char *, int);
const char *path;
long done;
};
struct baton2 {
void (*dlopen)(const char *, int);
const char *path;
int port;
};
static void *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)
syscall(-62 /*clock_sleep_trap */, 0, 1, 0, 8000 /*ns*/, -1);
syscall(361 /*bsdthread_terminate*/, ptr, 0x2000, 0, 0, 0);
((void (*)()) 0xbad)();
}
static void *bsd_thread_func(void *arg) {
struct baton *baton = arg;
baton->dlopen(baton->path, 0);
baton->done = 1;
return 0;
}
|