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 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
#include <assert.h>
#include <errno.h>
#include <setjmp.h>
#include <signal.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/ucontext.h>
#include <unistd.h>
#include "wasmtime-platform.h"
static int wasmtime_to_mmap_prot_flags(uint32_t prot_flags) {
int flags = 0;
if (prot_flags & WASMTIME_PROT_READ)
flags |= PROT_READ;
if (prot_flags & WASMTIME_PROT_WRITE)
flags |= PROT_WRITE;
if (prot_flags & WASMTIME_PROT_EXEC)
flags |= PROT_EXEC;
return flags;
}
int wasmtime_mmap_new(uintptr_t size, uint32_t prot_flags, uint8_t **ret) {
void *rc = mmap(NULL, size, wasmtime_to_mmap_prot_flags(prot_flags),
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (rc == MAP_FAILED)
return errno;
*ret = rc;
return 0;
}
int wasmtime_mmap_remap(uint8_t *addr, uintptr_t size, uint32_t prot_flags) {
void *rc = mmap(addr, size, wasmtime_to_mmap_prot_flags(prot_flags),
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (rc == MAP_FAILED)
return errno;
return 0;
}
int wasmtime_munmap(uint8_t *ptr, uintptr_t size) {
int rc = munmap(ptr, size);
if (rc != 0)
return errno;
return 0;
}
int wasmtime_mprotect(uint8_t *ptr, uintptr_t size, uint32_t prot_flags) {
int rc = mprotect(ptr, size, wasmtime_to_mmap_prot_flags(prot_flags));
if (rc != 0)
return errno;
return 0;
}
uintptr_t wasmtime_page_size(void) { return sysconf(_SC_PAGESIZE); }
int32_t wasmtime_setjmp(const uint8_t **jmp_buf_out,
void (*callback)(uint8_t *, uint8_t *),
uint8_t *payload, uint8_t *callee) {
jmp_buf buf;
if (setjmp(buf) != 0)
return 0;
*jmp_buf_out = (uint8_t *)&buf;
callback(payload, callee);
return 1;
}
void wasmtime_longjmp(const uint8_t *jmp_buf_ptr) {
longjmp(*(jmp_buf *)jmp_buf_ptr, 1);
}
static wasmtime_trap_handler_t g_handler = NULL;
static void handle_signal(int signo, siginfo_t *info, void *context) {
assert(g_handler != NULL);
uintptr_t ip, fp;
#if defined(__aarch64__)
ucontext_t *cx = context;
ip = cx->uc_mcontext.pc;
fp = cx->uc_mcontext.regs[29];
#elif defined(__x86_64__)
ucontext_t *cx = context;
ip = cx->uc_mcontext.gregs[REG_RIP];
fp = cx->uc_mcontext.gregs[REG_RBP];
#else
#error "Unsupported platform"
#endif
bool has_faulting_addr = signo == SIGSEGV;
uintptr_t faulting_addr = 0;
if (has_faulting_addr)
faulting_addr = (uintptr_t)info->si_addr;
g_handler(ip, fp, has_faulting_addr, faulting_addr);
// If wasmtime didn't handle this trap then reset the handler to the default
// behavior which will probably abort the process.
signal(signo, SIG_DFL);
}
int wasmtime_init_traps(wasmtime_trap_handler_t handler) {
int rc;
g_handler = handler;
struct sigaction action;
memset(&action, 0, sizeof(action));
action.sa_sigaction = handle_signal;
action.sa_flags = SA_SIGINFO | SA_NODEFER;
sigemptyset(&action.sa_mask);
rc = sigaction(SIGILL, &action, NULL);
if (rc != 0)
return errno;
rc = sigaction(SIGSEGV, &action, NULL);
if (rc != 0)
return errno;
rc = sigaction(SIGFPE, &action, NULL);
if (rc != 0)
return errno;
return 0;
}
int wasmtime_memory_image_new(const uint8_t *ptr, uintptr_t len,
struct wasmtime_memory_image **ret) {
*ret = NULL;
return 0;
}
int wasmtime_memory_image_map_at(struct wasmtime_memory_image *image,
uint8_t *addr, uintptr_t len) {
abort();
}
void wasmtime_memory_image_free(struct wasmtime_memory_image *image) {
abort();
}
// Pretend that this platform doesn't have threads where storing in a static is
// ok.
static uint8_t *WASMTIME_TLS = NULL;
uint8_t *wasmtime_tls_get() { return WASMTIME_TLS; }
void wasmtime_tls_set(uint8_t *val) { WASMTIME_TLS = val; }
|