1 // Platform support for Wasmtime's `no_std` build.
2 //
3 // This header file is what Wasmtime will rely on when it does not otherwise
4 // have support for the native platform. This can happen with `no_std` binaries
5 // for example where the traditional Unix-or-Windows implementation is not
6 // suitable.
7 //
8 // Embedders are expected to implement the symbols defined in this header file.
9 // These symbols can be defined either in C/C++ or in Rust (using
10 // `#[unsafe(no_mangle)]`).
11 //
12 // Note that there are some `#define`s here which can be added before this
13 // header file is included to indicate how Wasmtime was built. This corresponds
14 // to the `wasmtime` crate's Cargo features where if the feature is disabled
15 // then the symbols will not be required.
16 //
17 // * `WASMTIME_SIGNALS_BASED_TRAPS` - corresponds to `signals-based-traps`
18 // * `WASMTIME_CUSTOM_SYNC` - corresponds to `custom-sync-primitives`
19 //
20 // Some more information about this header can additionally be found at
21 // <https://docs.wasmtime.dev/stability-platform-support.html>.
22 
23 
24 #ifndef _WASMTIME_PLATFORM_H
25 #define _WASMTIME_PLATFORM_H
26 
27 /* Generated with cbindgen:0.29.0 */
28 
29 #include <stdarg.h>
30 #include <stdbool.h>
31 #include <stdint.h>
32 #include <stdlib.h>
33 
34 #if defined(WASMTIME_VIRTUAL_MEMORY)
35 /**
36  * Indicates that the memory region should be readable.
37  */
38 #define WASMTIME_PROT_READ (1 << 0)
39 #endif
40 
41 #if defined(WASMTIME_VIRTUAL_MEMORY)
42 /**
43  * Indicates that the memory region should be writable.
44  */
45 #define WASMTIME_PROT_WRITE (1 << 1)
46 #endif
47 
48 #if defined(WASMTIME_VIRTUAL_MEMORY)
49 /**
50  * Indicates that the memory region should be executable.
51  */
52 #define WASMTIME_PROT_EXEC (1 << 2)
53 #endif
54 
55 #if defined(WASMTIME_VIRTUAL_MEMORY)
56 /**
57  * Abstract pointer type used in the `wasmtime_memory_image_*` APIs which
58  * is defined by the embedder.
59  */
60 typedef struct wasmtime_memory_image wasmtime_memory_image;
61 #endif
62 
63 #if defined(WASMTIME_NATIVE_SIGNALS)
64 /**
65  * Handler function for traps in Wasmtime passed to `wasmtime_init_traps`.
66  *
67  * This function is invoked whenever a trap is caught by the system. For
68  * example this would be invoked during a signal handler on Linux. This
69  * function is passed a number of parameters indicating information about the
70  * trap:
71  *
72  * * `ip` - the instruction pointer at the time of the trap.
73  * * `fp` - the frame pointer register's value at the time of the trap.
74  * * `has_faulting_addr` - whether this trap is associated with an access
75  *   violation (e.g. a segfault) meaning memory was accessed when it shouldn't
76  *   be. If this is `true` then the next parameter is filled in.
77  * * `faulting_addr` - if `has_faulting_addr` is true then this is the address
78  *   that was attempted to be accessed. Otherwise this value is not used.
79  *
80  * If this function returns then the trap was not handled by Wasmtime. This
81  * means that it's left up to the embedder how to deal with the trap/signal
82  * depending on its default behavior. This could mean forwarding to a
83  * non-Wasmtime handler, aborting the process, logging then crashing, etc. The
84  * meaning of a trap that's not handled by Wasmtime depends on the context in
85  * which the trap was generated.
86  *
87  * When this function does not return it's because a native exception handler
88  * was resumed to.
89  */
90 typedef void (*wasmtime_trap_handler_t)(uintptr_t ip,
91                                         uintptr_t fp,
92                                         bool has_faulting_addr,
93                                         uintptr_t faulting_addr);
94 #endif
95 
96 #ifdef __cplusplus
97 extern "C" {
98 #endif // __cplusplus
99 
100 #if defined(WASMTIME_VIRTUAL_MEMORY)
101 /**
102  * Creates a new virtual memory mapping of the `size` specified with
103  * protection bits specified in `prot_flags`.
104  *
105  * Memory can be lazily committed.
106  *
107  * Stores the base pointer of the new mapping in `ret` on success.
108  *
109  * Returns 0 on success and an error code on failure.
110  *
111  * Similar to `mmap(0, size, prot_flags, MAP_PRIVATE, 0, -1)` on Linux.
112  */
113 extern int32_t wasmtime_mmap_new(uintptr_t size, uint32_t prot_flags, uint8_t **ret);
114 #endif
115 
116 #if defined(WASMTIME_VIRTUAL_MEMORY)
117 /**
118  * Remaps the virtual memory starting at `addr` going for `size` bytes to
119  * the protections specified with a new blank mapping.
120  *
121  * This will unmap any prior mappings and decommit them. New mappings for
122  * anonymous memory are used to replace these mappings and the new area
123  * should have the protection specified by `prot_flags`.
124  *
125  * Returns 0 on success and an error code on failure.
126  *
127  * Similar to `mmap(addr, size, prot_flags, MAP_PRIVATE | MAP_FIXED, 0, -1)` on Linux.
128  */
129 extern int32_t wasmtime_mmap_remap(uint8_t *addr, uintptr_t size, uint32_t prot_flags);
130 #endif
131 
132 #if defined(WASMTIME_VIRTUAL_MEMORY)
133 /**
134  * Unmaps memory at the specified `ptr` for `size` bytes.
135  *
136  * The memory should be discarded and decommitted and should generate a
137  * segfault if accessed after this function call.
138  *
139  * Returns 0 on success and an error code on failure.
140  *
141  * Similar to `munmap` on Linux.
142  */
143 extern int32_t wasmtime_munmap(uint8_t *ptr, uintptr_t size);
144 #endif
145 
146 #if defined(WASMTIME_VIRTUAL_MEMORY)
147 /**
148  * Configures the protections associated with a region of virtual memory
149  * starting at `ptr` and going to `size`.
150  *
151  * Returns 0 on success and an error code on failure.
152  *
153  * Similar to `mprotect` on Linux.
154  */
155 extern int32_t wasmtime_mprotect(uint8_t *ptr, uintptr_t size, uint32_t prot_flags);
156 #endif
157 
158 #if defined(WASMTIME_VIRTUAL_MEMORY)
159 /**
160  * Returns the page size, in bytes, of the current system.
161  */
162 extern uintptr_t wasmtime_page_size(void);
163 #endif
164 
165 #if defined(WASMTIME_NATIVE_SIGNALS)
166 /**
167  * Initializes trap-handling logic for this platform.
168  *
169  * Wasmtime's implementation of WebAssembly relies on the ability to catch
170  * signals/traps/etc. For example divide-by-zero may raise a machine
171  * exception. Out-of-bounds memory accesses may also raise a machine
172  * exception. This function is used to initialize trap handling.
173  *
174  * The `handler` provided is a function pointer to invoke whenever a trap
175  * is encountered. The `handler` is invoked whenever a trap is caught by
176  * the system.
177  *
178  * Returns 0 on success and an error code on failure.
179  */
180 extern int32_t wasmtime_init_traps(wasmtime_trap_handler_t handler);
181 #endif
182 
183 #if defined(WASMTIME_VIRTUAL_MEMORY)
184 /**
185  * Attempts to create a new in-memory image of the `ptr`/`len` combo which
186  * can be mapped to virtual addresses in the future.
187  *
188  * On success the returned `wasmtime_memory_image` pointer is stored into `ret`.
189  * This value stored can be `NULL` to indicate that an image cannot be
190  * created but no failure occurred. The structure otherwise will later be
191  * deallocated with `wasmtime_memory_image_free` and
192  * `wasmtime_memory_image_map_at` will be used to map the image into new
193  * regions of the address space.
194  *
195  * The `ptr` and `len` arguments are only valid for this function call, if
196  * the image needs to refer to them in the future then it must make a copy.
197  *
198  * Both `ptr` and `len` are guaranteed to be page-aligned.
199  *
200  * Returns 0 on success and an error code on failure. Note that storing
201  * `NULL` into `ret` is not considered a failure, and failure is used to
202  * indicate that something fatal has happened and Wasmtime will propagate
203  * the error upwards.
204  */
205 extern int32_t wasmtime_memory_image_new(const uint8_t *ptr,
206                                          uintptr_t len,
207                                          struct wasmtime_memory_image **ret);
208 #endif
209 
210 #if defined(WASMTIME_VIRTUAL_MEMORY)
211 /**
212  * Maps the `image` provided to the virtual address at `addr` and `len`.
213  *
214  * This semantically should make it such that `addr` and `len` looks the
215  * same as the contents of what the memory image was first created with.
216  * The mappings of `addr` should be private and changes do not reflect back
217  * to `wasmtime_memory_image`.
218  *
219  * In effect this is to create a copy-on-write mapping at `addr`/`len`
220  * pointing back to the memory used by the image originally.
221  *
222  * Note that the memory region will be unmapped with `wasmtime_munmap` in
223  * the future.
224  *
225  * Aborts the process on failure.
226  */
227 extern int32_t wasmtime_memory_image_map_at(struct wasmtime_memory_image *image,
228                                             uint8_t *addr,
229                                             uintptr_t len);
230 #endif
231 
232 #if defined(WASMTIME_VIRTUAL_MEMORY)
233 /**
234  * Deallocates the provided `wasmtime_memory_image`.
235  *
236  * Note that mappings created from this image are not guaranteed to be
237  * deallocated and/or unmapped before this is called.
238  */
239 extern void wasmtime_memory_image_free(struct wasmtime_memory_image *image);
240 #endif
241 
242 /**
243  * Wasmtime requires a single pointer's space of TLS to be used at runtime,
244  * and this function returns the current value of the TLS variable.
245  *
246  * This value should default to `NULL`.
247  */
248 extern uint8_t *wasmtime_tls_get(void);
249 
250 /**
251  * Sets the current TLS value for Wasmtime to the provided value.
252  *
253  * This value should be returned when later calling `wasmtime_tls_get`.
254  */
255 extern void wasmtime_tls_set(uint8_t *ptr);
256 
257 #if defined(WASMTIME_CUSTOM_SYNC)
258 /**
259  * Frees a synchronization lock.
260  *
261  * May be called on a lock that was never used (still has a zero pattern).
262  * The implementor must handle this case gracefully.
263  */
264 extern void wasmtime_sync_lock_free(uintptr_t *lock);
265 #endif
266 
267 #if defined(WASMTIME_CUSTOM_SYNC)
268 /**
269  * Acquires an exclusive lock.
270  *
271  * If the lock is uninitialized (zero pattern), it will be initialized lazily.
272  * This function blocks until the lock is acquired.
273  * Must be paired with [`wasmtime_sync_lock_release`].
274  */
275 extern void wasmtime_sync_lock_acquire(uintptr_t *lock);
276 #endif
277 
278 #if defined(WASMTIME_CUSTOM_SYNC)
279 /**
280  * Releases an exclusive lock previously acquired with [`wasmtime_sync_lock_acquire`].
281  */
282 extern void wasmtime_sync_lock_release(uintptr_t *lock);
283 #endif
284 
285 #if defined(WASMTIME_CUSTOM_SYNC)
286 /**
287  * Acquires a read lock on an RwLock.
288  *
289  * If the lock is uninitialized (zero pattern), it will be initialized lazily.
290  * Multiple readers can hold the lock simultaneously.
291  * Must be paired with [`wasmtime_sync_rwlock_read_release`].
292  */
293 extern void wasmtime_sync_rwlock_read(uintptr_t *lock);
294 #endif
295 
296 #if defined(WASMTIME_CUSTOM_SYNC)
297 /**
298  * Releases a read lock previously acquired with [`wasmtime_sync_rwlock_read`].
299  */
300 extern void wasmtime_sync_rwlock_read_release(uintptr_t *lock);
301 #endif
302 
303 #if defined(WASMTIME_CUSTOM_SYNC)
304 /**
305  * Acquires a write lock on an RwLock.
306  *
307  * If the lock is uninitialized (zero pattern), it will be initialized lazily.
308  * Only one writer can hold the lock, and no readers can be present.
309  * Must be paired with [`wasmtime_sync_rwlock_write_release`].
310  */
311 extern void wasmtime_sync_rwlock_write(uintptr_t *lock);
312 #endif
313 
314 #if defined(WASMTIME_CUSTOM_SYNC)
315 /**
316  * Releases a write lock previously acquired with [`wasmtime_sync_rwlock_write`].
317  */
318 extern void wasmtime_sync_rwlock_write_release(uintptr_t *lock);
319 #endif
320 
321 #if defined(WASMTIME_CUSTOM_SYNC)
322 /**
323  * Frees an RwLock.
324  *
325  * May be called on a lock that was never used (still has a zero pattern).
326  * The implementor must handle this case gracefully.
327  */
328 extern void wasmtime_sync_rwlock_free(uintptr_t *lock);
329 #endif
330 
331 #ifdef __cplusplus
332 }  // extern "C"
333 #endif  // __cplusplus
334 
335 #endif  /* _WASMTIME_PLATFORM_H */
336