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