File: wasmtime-platform.c

package info (click to toggle)
rust-wasmtime 26.0.1%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 48,492 kB
  • sloc: ansic: 4,003; sh: 561; javascript: 542; cpp: 254; asm: 175; ml: 96; makefile: 55
file content (143 lines) | stat: -rw-r--r-- 3,806 bytes parent folder | download
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; }