1 #include <assert.h> 2 #include <errno.h> 3 #include <setjmp.h> 4 #include <signal.h> 5 #include <string.h> 6 #include <sys/mman.h> 7 #include <sys/ucontext.h> 8 #include <unistd.h> 9 10 #include "wasmtime-platform.h" 11 12 #ifdef WASMTIME_VIRTUAL_MEMORY 13 14 static int wasmtime_to_mmap_prot_flags(uint32_t prot_flags) { 15 int flags = 0; 16 if (prot_flags & WASMTIME_PROT_READ) 17 flags |= PROT_READ; 18 if (prot_flags & WASMTIME_PROT_WRITE) 19 flags |= PROT_WRITE; 20 if (prot_flags & WASMTIME_PROT_EXEC) 21 flags |= PROT_EXEC; 22 return flags; 23 } 24 25 int wasmtime_mmap_new(uintptr_t size, uint32_t prot_flags, uint8_t **ret) { 26 void *rc = mmap(NULL, size, wasmtime_to_mmap_prot_flags(prot_flags), 27 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 28 if (rc == MAP_FAILED) 29 return errno; 30 *ret = rc; 31 return 0; 32 } 33 34 int wasmtime_mmap_remap(uint8_t *addr, uintptr_t size, uint32_t prot_flags) { 35 void *rc = mmap(addr, size, wasmtime_to_mmap_prot_flags(prot_flags), 36 MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 37 if (rc == MAP_FAILED) 38 return errno; 39 return 0; 40 } 41 42 int wasmtime_munmap(uint8_t *ptr, uintptr_t size) { 43 int rc = munmap(ptr, size); 44 if (rc != 0) 45 return errno; 46 return 0; 47 } 48 49 int wasmtime_mprotect(uint8_t *ptr, uintptr_t size, uint32_t prot_flags) { 50 int rc = mprotect(ptr, size, wasmtime_to_mmap_prot_flags(prot_flags)); 51 if (rc != 0) 52 return errno; 53 return 0; 54 } 55 56 uintptr_t wasmtime_page_size(void) { return sysconf(_SC_PAGESIZE); } 57 58 #endif // WASMTIME_VIRTUAL_MEMORY 59 60 bool wasmtime_setjmp(const uint8_t **jmp_buf_out, 61 bool (*callback)(uint8_t *, uint8_t *), uint8_t *payload, 62 uint8_t *callee) { 63 jmp_buf buf; 64 if (setjmp(buf) != 0) 65 return false; 66 *jmp_buf_out = (uint8_t *)&buf; 67 return callback(payload, callee); 68 } 69 70 void wasmtime_longjmp(const uint8_t *jmp_buf_ptr) { 71 longjmp(*(jmp_buf *)jmp_buf_ptr, 1); 72 } 73 74 #ifdef WASMTIME_NATIVE_SIGNALS 75 76 static wasmtime_trap_handler_t g_handler = NULL; 77 78 static void handle_signal(int signo, siginfo_t *info, void *context) { 79 assert(g_handler != NULL); 80 uintptr_t ip, fp; 81 #if defined(__aarch64__) 82 ucontext_t *cx = context; 83 ip = cx->uc_mcontext.pc; 84 fp = cx->uc_mcontext.regs[29]; 85 #elif defined(__x86_64__) 86 ucontext_t *cx = context; 87 ip = cx->uc_mcontext.gregs[REG_RIP]; 88 fp = cx->uc_mcontext.gregs[REG_RBP]; 89 #else 90 #error "Unsupported platform" 91 #endif 92 93 bool has_faulting_addr = signo == SIGSEGV; 94 uintptr_t faulting_addr = 0; 95 if (has_faulting_addr) 96 faulting_addr = (uintptr_t)info->si_addr; 97 g_handler(ip, fp, has_faulting_addr, faulting_addr); 98 99 // If wasmtime didn't handle this trap then reset the handler to the default 100 // behavior which will probably abort the process. 101 signal(signo, SIG_DFL); 102 } 103 104 int wasmtime_init_traps(wasmtime_trap_handler_t handler) { 105 int rc; 106 g_handler = handler; 107 108 struct sigaction action; 109 memset(&action, 0, sizeof(action)); 110 111 action.sa_sigaction = handle_signal; 112 action.sa_flags = SA_SIGINFO | SA_NODEFER; 113 sigemptyset(&action.sa_mask); 114 115 rc = sigaction(SIGILL, &action, NULL); 116 if (rc != 0) 117 return errno; 118 rc = sigaction(SIGSEGV, &action, NULL); 119 if (rc != 0) 120 return errno; 121 rc = sigaction(SIGFPE, &action, NULL); 122 if (rc != 0) 123 return errno; 124 return 0; 125 } 126 127 #endif // WASMTIME_NATIVE_SIGNALS 128 129 #ifdef WASMTIME_VIRTUAL_MEMORY 130 131 int wasmtime_memory_image_new(const uint8_t *ptr, uintptr_t len, 132 struct wasmtime_memory_image **ret) { 133 *ret = NULL; 134 return 0; 135 } 136 137 int wasmtime_memory_image_map_at(struct wasmtime_memory_image *image, 138 uint8_t *addr, uintptr_t len) { 139 abort(); 140 } 141 142 void wasmtime_memory_image_free(struct wasmtime_memory_image *image) { 143 abort(); 144 } 145 146 #endif // WASMTIME_VIRTUAL_MEMORY 147 148 // Pretend that this platform doesn't have threads where storing in a static is 149 // ok. 150 static uint8_t *WASMTIME_TLS = NULL; 151 152 uint8_t *wasmtime_tls_get() { return WASMTIME_TLS; } 153 154 void wasmtime_tls_set(uint8_t *val) { WASMTIME_TLS = val; } 155