1 /*
2  * Copyright 2018 WebAssembly Community Group participants
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef WASM_RT_H_
18 #define WASM_RT_H_
19 
20 #include <stdbool.h>
21 #include <stdint.h>
22 #include <stddef.h>
23 #include <setjmp.h>
24 
25 #if defined(_WIN32)
26   #define WASM2C_FUNC_EXPORT __declspec(dllexport)
27 #else
28   #define WASM2C_FUNC_EXPORT
29 #endif
30 
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34 
35 /** Maximum stack depth before trapping. This can be configured by defining
36  * this symbol before including wasm-rt when building the generated c files,
37  * for example:
38  *
39  * ```
40  *   cc -c -DWASM_RT_MAX_CALL_STACK_DEPTH=100 my_module.c -o my_module.o
41  * ```
42  * */
43 #ifndef WASM_RT_MAX_CALL_STACK_DEPTH
44 #define WASM_RT_MAX_CALL_STACK_DEPTH 500
45 #endif
46 
47 /** Check if we should use guard page model.
48  * This is enabled by default unless WASM_USE_EXPLICIT_BOUNDS_CHECKS is defined.
49  */
50 #if defined(WASM_USE_GUARD_PAGES) && defined(WASM_USE_EXPLICIT_BOUNDS_CHECKS)
51 #  error "Cannot define both WASM_USE_GUARD_PAGES and WASM_USE_EXPLICIT_BOUNDS_CHECKS"
52 #elif !defined(WASM_USE_GUARD_PAGES) && !defined(WASM_USE_EXPLICIT_BOUNDS_CHECKS)
53 // default to guard pages
54 #  define WASM_USE_GUARD_PAGES
55 #endif
56 
57 /** Define WASM_USE_INCREMENTAL_MOVEABLE_MEMORY_ALLOC if you want the runtime to incrementally allocate heap/linear memory
58  * Note that this memory may be moved when it needs to expand
59  */
60 
61 #if defined(_MSC_VER)
62 #define WASM_RT_NO_RETURN __declspec(noreturn)
63 #else
64 #define WASM_RT_NO_RETURN __attribute__((noreturn))
65 #endif
66 
67 /** Reason a trap occurred. Provide this to `wasm_rt_trap`.
68  * If you update this enum also update the error message in wasm_rt_trap.
69  */
70 typedef enum {
71   WASM_RT_TRAP_NONE,                          /** No error. */
72   WASM_RT_TRAP_OOB,                           /** Out-of-bounds access in linear memory. */
73   WASM_RT_TRAP_INT_OVERFLOW,                  /** Integer overflow on divide or truncation. */
74   WASM_RT_TRAP_DIV_BY_ZERO,                   /** Integer divide by zero. */
75   WASM_RT_TRAP_INVALID_CONVERSION,            /** Conversion from NaN to integer. */
76   WASM_RT_TRAP_UNREACHABLE,                   /** Unreachable instruction executed. */
77   WASM_RT_TRAP_CALL_INDIRECT_TABLE_EXPANSION, /** Invalid call_indirect, as func table cannot grow/grow further. */
78   WASM_RT_TRAP_CALL_INDIRECT_OOB_INDEX,       /** Invalid call_indirect, due to index larger than func table. */
79   WASM_RT_TRAP_CALL_INDIRECT_NULL_PTR,        /** Invalid call_indirect, as function being invoked is null. */
80   WASM_RT_TRAP_CALL_INDIRECT_TYPE_MISMATCH,   /** Invalid call_indirect, as function being invoked has an unexpected type. */
81   WASM_RT_TRAP_CALL_INDIRECT_UNKNOWN_ERR,     /** Invalid call_indirect, for other reason. */
82   WASM_RT_TRAP_EXHAUSTION,                    /** Call stack exhausted. */
83   WASM_RT_TRAP_SHADOW_MEM,                    /** Trap due to shadow memory mismatch */
84   WASM_RT_TRAP_WASI,                          /** Trap due to WASI error */
85 } wasm_rt_trap_t;
86 
87 /** Value types. Used to define function signatures. */
88 typedef enum {
89   WASM_RT_I32,
90   WASM_RT_I64,
91   WASM_RT_F32,
92   WASM_RT_F64,
93 } wasm_rt_type_t;
94 
95 /** A function type for all `anyfunc` functions in a Table. All functions are
96  * stored in this canonical form, but must be cast to their proper signature to
97  * call. */
98 typedef void (*wasm_rt_anyfunc_t)(void);
99 
100 /**
101  * The class of the indirect function being invoked
102  */
103 typedef enum {
104   WASM_RT_INTERNAL_FUNCTION,
105   WASM_RT_EXTERNAL_FUNCTION
106 } wasm_rt_elem_target_class_t;
107 
108 /** A single element of a Table. */
109 typedef struct {
110   wasm_rt_elem_target_class_t func_class;
111   /** The index as returned from `wasm_rt_register_func_type`. */
112   uint32_t func_type;
113   /** The function. The embedder must know the actual C signature of the
114    * function and cast to it before calling. */
115   wasm_rt_anyfunc_t func;
116 } wasm_rt_elem_t;
117 
118 typedef uint8_t wasm2c_shadow_memory_cell_t;
119 
120 typedef struct {
121   wasm2c_shadow_memory_cell_t* data;
122   size_t data_size;
123   void* allocation_sizes_map;
124   uint32_t heap_base;
125 } wasm2c_shadow_memory_t;
126 
127 /** A Memory object. */
128 typedef struct {
129   /** The linear memory data, with a byte length of `size`. */
130 #if defined(WASM_USE_GUARD_PAGES) || !defined(WASM_USE_INCREMENTAL_MOVEABLE_MEMORY_ALLOC)
131   uint8_t* const data;
132 #else
133   uint8_t* data;
134 #endif
135   /** The current and maximum page count for this Memory object. If there is no
136    * maximum, `max_pages` is 0xffffffffu (i.e. UINT32_MAX). */
137   uint32_t pages, max_pages;
138   /** The current size of the linear memory, in bytes. */
139   uint32_t size;
140 
141   /** 32-bit platforms use masking for sandboxing. This sets the mask, which is
142    * computed based on the heap size */
143 #if UINTPTR_MAX == 0xffffffff
144   const uint32_t mem_mask;
145 #endif
146 
147 #if defined(WASM_CHECK_SHADOW_MEMORY)
148   wasm2c_shadow_memory_t shadow_memory;
149 #endif
150 } wasm_rt_memory_t;
151 
152 /** A Table object. */
153 typedef struct {
154   /** The table element data, with an element count of `size`. */
155   wasm_rt_elem_t* data;
156   /** The maximum element count of this Table object. If there is no maximum,
157    * `max_size` is 0xffffffffu (i.e. UINT32_MAX). */
158   uint32_t max_size;
159   /** The current element count of the table. */
160   uint32_t size;
161 } wasm_rt_table_t;
162 
163 typedef struct wasm_func_type_t {
164   wasm_rt_type_t* params;
165   wasm_rt_type_t* results;
166   uint32_t param_count;
167   uint32_t result_count;
168 } wasm_func_type_t;
169 
170 #define WASM2C_WASI_MAX_SETJMP_STACK 32
171 #define WASM2C_WASI_MAX_FDS 32
172 typedef struct wasm_sandbox_wasi_data {
173   wasm_rt_memory_t* heap_memory;
174 
175   uint32_t tempRet0;
176 
177   uint32_t next_setjmp_index;
178   jmp_buf setjmp_stack[WASM2C_WASI_MAX_SETJMP_STACK];
179 
180   uint32_t main_argc;
181   char** main_argv;
182 
183   int wasm_fd_to_native[WASM2C_WASI_MAX_FDS];
184   uint32_t next_wasm_fd;
185 
186   void* clock_data;
187 
188 } wasm_sandbox_wasi_data;
189 
190 typedef void (*wasm_rt_sys_init_t)(void);
191 typedef void* (*create_wasm2c_sandbox_t)(uint32_t max_wasm_pages);
192 typedef void (*destroy_wasm2c_sandbox_t)(void* sbx_ptr);
193 typedef void* (*lookup_wasm2c_nonfunc_export_t)(void* sbx_ptr, const char* name);
194 typedef uint32_t (*lookup_wasm2c_func_index_t)(void* sbx_ptr, uint32_t param_count, uint32_t result_count, wasm_rt_type_t* types);
195 typedef uint32_t (*add_wasm2c_callback_t)(void* sbx_ptr, uint32_t func_type_idx, void* func_ptr, wasm_rt_elem_target_class_t func_class);
196 typedef void (*remove_wasm2c_callback_t)(void* sbx_ptr, uint32_t callback_idx);
197 
198 typedef struct wasm2c_sandbox_funcs_t {
199   wasm_rt_sys_init_t wasm_rt_sys_init;
200   create_wasm2c_sandbox_t create_wasm2c_sandbox;
201   destroy_wasm2c_sandbox_t destroy_wasm2c_sandbox;
202   lookup_wasm2c_nonfunc_export_t lookup_wasm2c_nonfunc_export;
203   lookup_wasm2c_func_index_t lookup_wasm2c_func_index;
204   add_wasm2c_callback_t add_wasm2c_callback;
205   remove_wasm2c_callback_t remove_wasm2c_callback;
206 } wasm2c_sandbox_funcs_t;
207 
208 /** Stop execution immediately and jump back to the call to `wasm_rt_try`.
209  *  The result of `wasm_rt_try` will be the provided trap reason.
210  *
211  *  This is typically called by the generated code, and not the embedder. */
212 WASM_RT_NO_RETURN extern void wasm_rt_trap(wasm_rt_trap_t);
213 
214 /** An indirect callback function failed.
215  *  Deduce the reason for the failure and then call trap.
216  *
217  *  This is typically called by the generated code, and not the embedder. */
218 WASM_RT_NO_RETURN extern void wasm_rt_callback_error_trap(wasm_rt_table_t* table, uint32_t func_index, uint32_t expected_func_type);
219 
220 /** Register a function type with the given signature. The returned function
221  * index is guaranteed to be the same for all calls with the same signature.
222  * The following varargs must all be of type `wasm_rt_type_t`, first the
223  * params` and then the `results`.
224  *
225  *  ```
226  *    // Register (func (param i32 f32) (result i64)).
227  *    wasm_rt_register_func_type(2, 1, WASM_RT_I32, WASM_RT_F32, WASM_RT_I64);
228  *    => returns 1
229  *
230  *    // Register (func (result i64)).
231  *    wasm_rt_register_func_type(0, 1, WASM_RT_I32);
232  *    => returns 2
233  *
234  *    // Register (func (param i32 f32) (result i64)) again.
235  *    wasm_rt_register_func_type(2, 1, WASM_RT_I32, WASM_RT_F32, WASM_RT_I64);
236  *    => returns 1
237  *  ``` */
238 extern uint32_t wasm_rt_register_func_type(wasm_func_type_t** p_func_type_structs,
239                                            uint32_t* p_func_type_count,
240                                            uint32_t params,
241                                            uint32_t results,
242                                            wasm_rt_type_t* types);
243 
244 extern void wasm_rt_cleanup_func_types(wasm_func_type_t** p_func_type_structs,
245                                uint32_t* p_func_type_count);
246 
247 /**
248  * Return the default value of the maximum size allowed for wasm memory.
249  */
250 extern uint64_t wasm_rt_get_default_max_linear_memory_size();
251 
252 /** Initialize a Memory object with an initial page size of `initial_pages` and
253  * a maximum page size of `max_pages`.
254  *
255  *  ```
256  *    wasm_rt_memory_t my_memory;
257  *    // 1 initial page (65536 bytes), and a maximum of 2 pages.
258  *    wasm_rt_allocate_memory(&my_memory, 1, 2);
259  *  ``` */
260 extern bool wasm_rt_allocate_memory(wasm_rt_memory_t*,
261                                     uint32_t initial_pages,
262                                     uint32_t max_pages);
263 
264 extern void wasm_rt_deallocate_memory(wasm_rt_memory_t*);
265 
266 /** Grow a Memory object by `pages`, and return the previous page count. If
267  * this new page count is greater than the maximum page count, the grow fails
268  * and 0xffffffffu (UINT32_MAX) is returned instead.
269  *
270  *  ```
271  *    wasm_rt_memory_t my_memory;
272  *    ...
273  *    // Grow memory by 10 pages.
274  *    uint32_t old_page_size = wasm_rt_grow_memory(&my_memory, 10);
275  *    if (old_page_size == UINT32_MAX) {
276  *      // Failed to grow memory.
277  *    }
278  *  ``` */
279 extern uint32_t wasm_rt_grow_memory(wasm_rt_memory_t*, uint32_t pages);
280 
281 /** Initialize a Table object with an element count of `elements` and a maximum
282  * page size of `max_elements`.
283  *
284  *  ```
285  *    wasm_rt_table_t my_table;
286  *    // 5 elemnets and a maximum of 10 elements.
287  *    wasm_rt_allocate_table(&my_table, 5, 10);
288  *  ``` */
289 extern void wasm_rt_allocate_table(wasm_rt_table_t*,
290                                    uint32_t elements,
291                                    uint32_t max_elements);
292 
293 extern void wasm_rt_deallocate_table(wasm_rt_table_t*);
294 
295 extern void wasm_rt_expand_table(wasm_rt_table_t*);
296 
297 // One time init function for wasm runtime. Should be called once for the current process
298 extern void wasm_rt_sys_init();
299 
300 // Initialize wasi for the given sandbox. Called prior to sandbox execution.
301 extern void wasm_rt_init_wasi(wasm_sandbox_wasi_data*);
302 
303 extern void wasm_rt_cleanup_wasi(wasm_sandbox_wasi_data*);
304 
305 // Helper function that host can use to ensure wasm2c code is loaded correctly when using dynamic libraries
306 extern void wasm2c_ensure_linked();
307 
308 // Runtime functions for shadow memory
309 
310 // Create the shadow memory
311 extern void wasm2c_shadow_memory_create(wasm_rt_memory_t* mem);
312 // Expand the shadow memory to match wasm memory
313 extern void wasm2c_shadow_memory_expand(wasm_rt_memory_t* mem);
314 // Cleanup
315 extern void wasm2c_shadow_memory_destroy(wasm_rt_memory_t* mem);
316 // Perform checks for the load operation that completed
317 WASM2C_FUNC_EXPORT extern void wasm2c_shadow_memory_load(wasm_rt_memory_t* mem, const char* func_name, uint32_t ptr, uint32_t ptr_size);
318 // Perform checks for the store operation that completed
319 WASM2C_FUNC_EXPORT extern void wasm2c_shadow_memory_store(wasm_rt_memory_t* mem, const char* func_name, uint32_t ptr, uint32_t ptr_size);
320 // Mark an area as allocated, if it is currently unused. If already used, this is a noop.
321 extern void wasm2c_shadow_memory_reserve(wasm_rt_memory_t* mem, uint32_t ptr, uint32_t ptr_size);
322 // Perform checks for the malloc operation that completed
323 extern void wasm2c_shadow_memory_dlmalloc(wasm_rt_memory_t* mem, uint32_t ptr, uint32_t ptr_size);
324 // Perform checks for the free operation that will be run
325 extern void wasm2c_shadow_memory_dlfree(wasm_rt_memory_t* mem, uint32_t ptr);
326 // Pass on information about the boundary between wasm globals and heap
327 // Shadow asan will check that all malloc metadata structures below this boundary are only accessed by malloc related functions
328 extern void wasm2c_shadow_memory_mark_globals_heap_boundary(wasm_rt_memory_t* mem, uint32_t ptr);
329 // Print a list of all allocations currently active
330 WASM2C_FUNC_EXPORT extern void wasm2c_shadow_memory_print_allocations(wasm_rt_memory_t* mem);
331 // Print the size of allocations currently active
332 WASM2C_FUNC_EXPORT uint64_t wasm2c_shadow_memory_print_total_allocations(wasm_rt_memory_t* mem);
333 
334 #ifdef __cplusplus
335 }
336 #endif
337 
338 #endif /* WASM_RT_H_ */
339