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