aboutsummaryrefslogtreecommitdiff
path: root/lib/darwin/inject-asm-raw.c
diff options
context:
space:
mode:
authorcomex2015-01-21 00:27:31 -0500
committercomex2015-01-21 00:27:31 -0500
commit21681b72291e3057577608aacf16a7841517135a (patch)
tree9a864fd2f9a7dc0e68a9d4e42aa191a8c50ae087 /lib/darwin/inject-asm-raw.c
parent... (diff)
downloadsubstitute-21681b72291e3057577608aacf16a7841517135a.tar.gz
woo, inject seems to work on all platforms
Diffstat (limited to 'lib/darwin/inject-asm-raw.c')
-rw-r--r--lib/darwin/inject-asm-raw.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/lib/darwin/inject-asm-raw.c b/lib/darwin/inject-asm-raw.c
new file mode 100644
index 0000000..bb92828
--- /dev/null
+++ b/lib/darwin/inject-asm-raw.c
@@ -0,0 +1,87 @@
+#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 _) {
+ 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("syscall" : "=r"(out) : "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 _) {
+ REG(s, r12); REG(a, r0); REG(b, r1); REG(c, r2); REG(d, r3);
+ OREG(out, r0);
+ asm volatile("svc #0x80" : "=r"(out) : "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 _) {
+ REG(s, x16); REG(a, x0); REG(b, x1); REG(c, x2); REG(d, x3);
+ OREG(out, x0);
+ asm volatile("svc #0x80" : "=r"(out) : "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;
+}