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