├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── build_emscripten.sh ├── indentlinux.sh ├── src ├── valgrind │ └── valgrind.h ├── wasmjit │ ├── ast.c │ ├── ast.h │ ├── ast_dump.c │ ├── ast_dump.h │ ├── compile.c │ ├── compile.h │ ├── dynamic_emscripten_runtime.c │ ├── dynamic_emscripten_runtime.h │ ├── dynamic_runtime.c │ ├── elf_relocatable.c │ ├── elf_relocatable.h │ ├── emscripten_runtime.c │ ├── emscripten_runtime.h │ ├── emscripten_runtime_def.h │ ├── emscripten_runtime_sys.h │ ├── emscripten_runtime_sys_def.h │ ├── emscripten_runtime_sys_errno_def.h │ ├── emscripten_runtime_sys_linux_kernel.c │ ├── emscripten_runtime_sys_posix.c │ ├── emscripten_runtime_sys_so_def.h │ ├── high_level.c │ ├── high_level.h │ ├── instantiate.c │ ├── instantiate.h │ ├── ktls.h │ ├── kwasmjit.h │ ├── kwasmjit_linux.c │ ├── main.c │ ├── parse.c │ ├── parse.h │ ├── runtime.c │ ├── runtime.h │ ├── static_emscripten_runtime.c │ ├── static_runtime.c │ ├── static_runtime.h │ ├── sys.h │ ├── tls.h │ ├── util.c │ ├── util.h │ ├── vector.c │ ├── vector.h │ └── x86_64_jmp.S └── wasmjit_examples │ └── selfpipe.c └── wasmjit.png /.gitignore: -------------------------------------------------------------------------------- 1 | *~ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Rian Hunter 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # *** THIS IS NOT A LONG TERM SOLUTION *** 2 | 3 | LCFLAGS ?= -Isrc -g -Wall -Wextra -Werror 4 | 5 | all: wasmjit 6 | 7 | clean: 8 | rm -f src/wasmjit/vector.o src/wasmjit/ast.o src/wasmjit/ast_dump.o src/wasmjit/main.o src/wasmjit/parse.o src/wasmjit/compile.o wasmjit src/wasmjit/runtime.o src/wasmjit/util.o src/wasmjit/elf_relocatable.o src/wasmjit/dynamic_emscripten_runtime.o src/wasmjit/emscripten_runtime_sys_posix.o src/wasmjit/instantiate.o src/wasmjit/emscripten_runtime.o src/wasmjit/high_level.o src/wasmjit/dynamic_runtime.o 9 | 10 | wasmjit: src/wasmjit/main.o src/wasmjit/vector.o src/wasmjit/ast.o src/wasmjit/parse.o src/wasmjit/ast_dump.o src/wasmjit/compile.o src/wasmjit/runtime.o src/wasmjit/util.o src/wasmjit/elf_relocatable.o src/wasmjit/dynamic_emscripten_runtime.o src/wasmjit/emscripten_runtime_sys_posix.o src/wasmjit/instantiate.o src/wasmjit/emscripten_runtime.o src/wasmjit/high_level.o src/wasmjit/dynamic_runtime.o 11 | $(CC) -o $@ $^ $(LCFLAGS) -pthread 12 | 13 | %.o: %.c 14 | $(CC) -c -o $@ $< $(LCFLAGS) 15 | 16 | UNAME ?= $(shell uname -r) 17 | EXTRA_CFLAGS := -I$(src)/src -msse -DIEC559_FLOAT_ENCODING 18 | 19 | obj-m += kwasmjit.o 20 | kwasmjit-objs := src/wasmjit/kwasmjit_linux.o src/wasmjit/parse.o src/wasmjit/ast.o src/wasmjit/instantiate.o src/wasmjit/runtime.o src/wasmjit/compile.o src/wasmjit/vector.o src/wasmjit/util.o src/wasmjit/emscripten_runtime.o src/wasmjit/dynamic_emscripten_runtime.o src/wasmjit/emscripten_runtime_sys_linux_kernel.o src/wasmjit/high_level.o src/wasmjit/x86_64_jmp.o src/wasmjit/dynamic_runtime.o 21 | 22 | .PHONY: kwasmjit.ko 23 | kwasmjit.ko: 24 | make -C /lib/modules/$(UNAME)/build M=$(PWD) modules 25 | 26 | modclean: 27 | make -C /lib/modules/$(UNAME)/build M=$(PWD) clean 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Wasmjit 2 | 3 | Wasmjit is a small embeddable WebAssembly runtime. Its core is written in 4 | C90 and is easily portable to most environments. 5 | 6 | Its primary target is a Linux kernel module that can host 7 | Emscripten-generated WebAssembly modules. In this configuration it 8 | runs WebAssembly modules in kernel-space (ring 0) and provides access 9 | to system calls as normal function calls. This configuration avoids 10 | user-kernel transition overhead, as well as scheduling overheads from 11 | swapping page tables. This results in a significant performance 12 | increase for syscall-bound programs like web servers or FUSE file 13 | systems. The performance increase is more pronounced in a 14 | post-Spectre/Meltdown world due to PTI overhead. Check it out: 15 | 16 | ![example wasmjit run](https://raw.githubusercontent.com/rianhunter/wasmjit/master/wasmjit.png) 17 | 18 | It also includes a host environment for running in user-space on POSIX 19 | systems. This is useful for running WebAssembly modules without having 20 | to run an entire browser. 21 | 22 | Wasmjit is licensed under a permissive MIT license. 23 | 24 | # Getting Started 25 | 26 | Wasmjit currently runs on x86_64 POSIX systems, like Linux, macOS, and 27 | the BSDs. It can also optionally use a Linux kernel module that can 28 | significantly speed up execution. To get started with Wasmjit you need 29 | a few tools: 30 | 31 | * A standard POSIX C development environment that includes `cc` and 32 | `make`. 33 | * [Emscripten SDK](https://kripken.github.io/emscripten-site/docs/getting_started/downloads.html) 34 | * (Optional) Your Linux distro's kernel headers. On Debian, install 35 | the `linux-headers-amd64` package, on Fedora, install `kernel-devel`. 36 | 37 | ## (Optional) Installing the Kernel Module 38 | 39 | $ make modclean 40 | $ make kwasmjit.ko 41 | $ sudo insmod ./kwasmjit.ko 42 | $ sudo chmod 777 /dev/wasm # See caveat below 43 | 44 | ## Building the Executable 45 | 46 | $ make clean 47 | $ make -j wasmjit 48 | 49 | ## Building and running the Example 50 | 51 | $ source path_to_emsdk/emsdk_env.sh # bring emcc into $PATH 52 | $ emcc -o selfpipe.js src/wasmjit_examples/selfpipe.c 53 | 54 | You can now run the example: 55 | 56 | $ time ./wasmjit selfpipe.wasm 57 | 58 | If you installed the Linux kernel module, this should run much quicker than 59 | a native binary: 60 | 61 | $ cc -o selfpipe src/wasmjit_examples/selfpipe.c 62 | $ time ./selfpipe 63 | 64 | # Status 65 | 66 | Wasmjit can run a subset of Emscripten-generated WebAssembly 67 | on Linux, macOS, and within the Linux kernel as a kernel module. It 68 | currently only supports x86_64. Here are the current developments goals 69 | in order of priority: 70 | 71 | * Implement enough Emscripten host-bindings to run 72 | [`nginx.wasm`](https://www.dropbox.com/sh/lmz3nnz92jx9szh/AAA-YOEHxwM_nki8jX0uFRuqa?dl=0) 73 | * Implement an interpreter 74 | * Implement Rust-runtime for Rust-generated wasm files 75 | * Implement Go-runtime for Go-generated wasm files 76 | * Optimize x86_64 JIT 77 | * Implement arm64 JIT 78 | * Implement macOS kernel module 79 | 80 | PRs are welcome :) 81 | 82 | # Linux Kernel Mode Caveats 83 | 84 | The code and data section allocations are done using `vmalloc()`. This 85 | prevents those pages from ever being swapped to disk. Thus, 86 | indiscriminately allowing access to the `/dev/wasm` device may make a 87 | system vulnerable to denial-of-service attacks. In the future a 88 | system-wide limit on the amount of memory used by the `/dev/wasm` 89 | device will be provided to mitigate that risk. 90 | 91 | # Contact 92 | 93 | Rian Hunter [@cejetvole](https://twitter.com/cejetvole) 94 | -------------------------------------------------------------------------------- /build_emscripten.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -eu 4 | 5 | make clean 6 | 7 | make wasmjit 8 | 9 | ./wasmjit -p "$1" > src/wasmjit/static_emscripten_runtime_helper.c 10 | 11 | ./wasmjit -o "$1" > "$1.o" 12 | 13 | SUPPORT="static_runtime emscripten_runtime emscripten_runtime_sys_posix runtime vector static_emscripten_runtime static_emscripten_runtime_helper" 14 | SUPPORT_FILES="" 15 | for FILE in $SUPPORT 16 | do 17 | rm -f src/wasmjit/${FILE}.o 18 | make src/wasmjit/${FILE}.o 19 | SUPPORT_FILES="$SUPPORT_FILES src/wasmjit/${FILE}.o" 20 | done 21 | 22 | 23 | cc -o "$1.exe" "$1.o" $SUPPORT_FILES 24 | -------------------------------------------------------------------------------- /indentlinux.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Documented here 4 | # https://www.kernel.org/doc/Documentation/process/coding-style.rst 5 | 6 | INDENT=indent 7 | 8 | if which gindent > /dev/null 9 | then 10 | INDENT=gindent 11 | fi 12 | 13 | $INDENT -nbad -bap -nbc -bbo -hnl -br -brs -c33 -cd33 -ncdb -ce -ci4 \ 14 | -cli0 -d0 -di1 -nfc1 -i8 -ip0 -l80 -lp -npcs -nprs -npsl -sai \ 15 | -saf -saw -ncs -nsc -sob -nfca -cp33 -ss -ts8 -il1 "$@" 16 | -------------------------------------------------------------------------------- /src/wasmjit/ast.c: -------------------------------------------------------------------------------- 1 | /* -*-mode:c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ 2 | 3 | /* 4 | Copyright (c) 2018 Rian Hunter 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #include 26 | 27 | #include 28 | 29 | void init_instruction(struct Instr *instr) 30 | { 31 | memset(instr, 0, sizeof(*instr)); 32 | } 33 | 34 | void free_instruction(struct Instr *instr) 35 | { 36 | switch (instr->opcode) { 37 | case OPCODE_BLOCK: 38 | case OPCODE_LOOP: { 39 | struct BlockLoopExtra *block = 40 | instr->opcode == OPCODE_BLOCK 41 | ? &instr->data.block : &instr->data.loop; 42 | if (block->instructions) { 43 | free_instructions(block->instructions, 44 | block->n_instructions); 45 | } 46 | break; 47 | }; 48 | case OPCODE_IF: { 49 | if (instr->data.if_.instructions_then) { 50 | free_instructions(instr->data.if_.instructions_then, 51 | instr->data.if_.n_instructions_then); 52 | } 53 | if (instr->data.if_.instructions_else) { 54 | free_instructions(instr->data.if_.instructions_else, 55 | instr->data.if_.n_instructions_else); 56 | } 57 | break; 58 | } 59 | case OPCODE_BR_TABLE: { 60 | if (instr->data.br_table.labelidxs) { 61 | free(instr->data.br_table.labelidxs); 62 | } 63 | break; 64 | } 65 | } 66 | } 67 | 68 | void free_instructions(struct Instr *instructions, size_t n_instructions) 69 | { 70 | size_t i; 71 | for (i = 0; i < n_instructions; ++i) { 72 | free_instruction(&instructions[i]); 73 | } 74 | free(instructions); 75 | } 76 | 77 | void wasmjit_init_module(struct Module *module) 78 | { 79 | memset(module, 0, sizeof(*module)); 80 | } 81 | 82 | void wasmjit_free_module(struct Module *module) 83 | { 84 | if (module->type_section.types) { 85 | free(module->type_section.types); 86 | } 87 | 88 | if (module->import_section.imports) { 89 | uint32_t i; 90 | for (i = 0; i < module->import_section.n_imports; ++i) { 91 | free(module->import_section.imports[i].name); 92 | free(module->import_section.imports[i].module); 93 | } 94 | free(module->import_section.imports); 95 | } 96 | 97 | if (module->function_section.typeidxs) { 98 | free(module->function_section.typeidxs); 99 | } 100 | 101 | if (module->table_section.tables) { 102 | free(module->table_section.tables); 103 | } 104 | 105 | if (module->memory_section.memories) { 106 | free(module->memory_section.memories); 107 | } 108 | 109 | if (module->global_section.globals) { 110 | uint32_t i; 111 | for (i = 0; i < module->global_section.n_globals; ++i) { 112 | free_instructions(module->global_section.globals[i].instructions, 113 | module->global_section.globals[i].n_instructions); 114 | } 115 | free(module->global_section.globals); 116 | } 117 | 118 | if (module->export_section.exports) { 119 | uint32_t i; 120 | for (i = 0; i < module->export_section.n_exports; ++i) { 121 | if (module->export_section.exports[i].name) { 122 | free(module->export_section.exports[i].name); 123 | } 124 | } 125 | free(module->export_section.exports); 126 | } 127 | 128 | 129 | if (module->element_section.elements) { 130 | uint32_t i; 131 | for (i = 0; i < module->element_section.n_elements; ++i) { 132 | struct ElementSectionElement *element = 133 | &module->element_section.elements[i]; 134 | 135 | if (element->instructions) { 136 | free_instructions(element->instructions, 137 | element->n_instructions); 138 | } 139 | 140 | if (element->funcidxs) { 141 | free(element->funcidxs); 142 | } 143 | } 144 | free(module->element_section.elements); 145 | } 146 | 147 | if (module->code_section.codes) { 148 | uint32_t i; 149 | for (i = 0; i < module->code_section.n_codes; ++i) { 150 | struct CodeSectionCode *code = &module->code_section.codes[i]; 151 | 152 | if (code->locals) { 153 | free(code->locals); 154 | } 155 | 156 | if (code->instructions) { 157 | free_instructions(code->instructions, 158 | code->n_instructions); 159 | } 160 | } 161 | free(module->code_section.codes); 162 | } 163 | 164 | if (module->data_section.datas) { 165 | uint32_t i; 166 | for (i = 0; i < module->data_section.n_datas; ++i) { 167 | struct DataSectionData *data = &module->data_section.datas[i]; 168 | 169 | if (data->instructions) { 170 | free_instructions(data->instructions, 171 | data->n_instructions); 172 | } 173 | 174 | if (data->buf) { 175 | free(data->buf); 176 | } 177 | } 178 | free(module->data_section.datas); 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /src/wasmjit/ast.h: -------------------------------------------------------------------------------- 1 | /* -*-mode:c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ 2 | 3 | /* 4 | Copyright (c) 2018 Rian Hunter 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #ifndef __WASMJIT__WASMBIN_H__ 26 | #define __WASMJIT__WASMBIN_H__ 27 | 28 | #include 29 | 30 | enum { 31 | /* Control Instructions */ 32 | OPCODE_UNREACHABLE = 0x00, 33 | OPCODE_NOP = 0x01, 34 | OPCODE_BLOCK = 0x02, 35 | OPCODE_LOOP = 0x03, 36 | OPCODE_IF = 0x04, 37 | OPCODE_BR = 0x0C, 38 | OPCODE_BR_IF = 0x0D, 39 | OPCODE_BR_TABLE = 0x0E, 40 | OPCODE_RETURN = 0x0F, 41 | OPCODE_CALL = 0x10, 42 | OPCODE_CALL_INDIRECT = 0x11, 43 | 44 | /* Parametric Instructions */ 45 | OPCODE_DROP = 0x1A, 46 | OPCODE_SELECT = 0x1B, 47 | 48 | /* Variable Instructions */ 49 | OPCODE_GET_LOCAL = 0x20, 50 | OPCODE_SET_LOCAL = 0x21, 51 | OPCODE_TEE_LOCAL = 0x22, 52 | OPCODE_GET_GLOBAL = 0x23, 53 | OPCODE_SET_GLOBAL = 0x24, 54 | 55 | /* Memory Instructions */ 56 | OPCODE_I32_LOAD = 0x28, 57 | OPCODE_I64_LOAD = 0x29, 58 | OPCODE_F32_LOAD = 0x2A, 59 | OPCODE_F64_LOAD = 0x2B, 60 | OPCODE_I32_LOAD8_S = 0x2C, 61 | OPCODE_I32_LOAD8_U = 0x2D, 62 | OPCODE_I32_LOAD16_S = 0x2E, 63 | OPCODE_I32_LOAD16_U = 0x2F, 64 | OPCODE_I64_LOAD8_S = 0x30, 65 | OPCODE_I64_LOAD8_U = 0x31, 66 | OPCODE_I64_LOAD16_S = 0x32, 67 | OPCODE_I64_LOAD16_U = 0x33, 68 | OPCODE_I64_LOAD32_S = 0x34, 69 | OPCODE_I64_LOAD32_U = 0x35, 70 | OPCODE_I32_STORE = 0x36, 71 | OPCODE_I64_STORE = 0x37, 72 | OPCODE_F32_STORE = 0x38, 73 | OPCODE_F64_STORE = 0x39, 74 | OPCODE_I32_STORE8 = 0x3A, 75 | OPCODE_I32_STORE16 = 0x3B, 76 | OPCODE_I64_STORE8 = 0x3C, 77 | OPCODE_I64_STORE16 = 0x3D, 78 | OPCODE_I64_STORE32 = 0x3E, 79 | OPCODE_MEMORY_SIZE = 0x3F, 80 | OPCODE_MEMORY_GROW = 0x40, 81 | 82 | /* Numeric Instructions */ 83 | OPCODE_I32_CONST = 0x41, 84 | OPCODE_I64_CONST = 0x42, 85 | OPCODE_F32_CONST = 0x43, 86 | OPCODE_F64_CONST = 0x44, 87 | 88 | OPCODE_I32_EQZ = 0x45, 89 | OPCODE_I32_EQ = 0x46, 90 | OPCODE_I32_NE = 0x47, 91 | OPCODE_I32_LT_S = 0x48, 92 | OPCODE_I32_LT_U = 0x49, 93 | OPCODE_I32_GT_S = 0x4A, 94 | OPCODE_I32_GT_U = 0x4B, 95 | OPCODE_I32_LE_S = 0x4C, 96 | OPCODE_I32_LE_U = 0x4D, 97 | OPCODE_I32_GE_S = 0x4E, 98 | OPCODE_I32_GE_U = 0x4F, 99 | 100 | OPCODE_I64_EQZ = 0x50, 101 | OPCODE_I64_EQ = 0x51, 102 | OPCODE_I64_NE = 0x52, 103 | OPCODE_I64_LT_S = 0x53, 104 | OPCODE_I64_LT_U = 0x54, 105 | OPCODE_I64_GT_S = 0x55, 106 | OPCODE_I64_GT_U = 0x56, 107 | OPCODE_I64_LE_S = 0x57, 108 | OPCODE_I64_LE_U = 0x58, 109 | OPCODE_I64_GE_S = 0x59, 110 | OPCODE_I64_GE_U = 0x5A, 111 | 112 | OPCODE_F32_EQ = 0x5B, 113 | OPCODE_F32_NE = 0x5C, 114 | OPCODE_F32_LT = 0x5D, 115 | OPCODE_F32_GT = 0x5E, 116 | OPCODE_F32_LE = 0x5F, 117 | OPCODE_F32_GE = 0x60, 118 | 119 | OPCODE_F64_EQ = 0x61, 120 | OPCODE_F64_NE = 0x62, 121 | OPCODE_F64_LT = 0x63, 122 | OPCODE_F64_GT = 0x64, 123 | OPCODE_F64_LE = 0x65, 124 | OPCODE_F64_GE = 0x66, 125 | 126 | OPCODE_I32_CLZ = 0x67, 127 | OPCODE_I32_CTZ = 0x68, 128 | OPCODE_I32_POPCNT = 0x69, 129 | OPCODE_I32_ADD = 0x6A, 130 | OPCODE_I32_SUB = 0x6B, 131 | OPCODE_I32_MUL = 0x6C, 132 | OPCODE_I32_DIV_S = 0x6D, 133 | OPCODE_I32_DIV_U = 0x6E, 134 | OPCODE_I32_REM_S = 0x6F, 135 | OPCODE_I32_REM_U = 0x70, 136 | OPCODE_I32_AND = 0x71, 137 | OPCODE_I32_OR = 0x72, 138 | OPCODE_I32_XOR = 0x73, 139 | OPCODE_I32_SHL = 0x74, 140 | OPCODE_I32_SHR_S = 0x75, 141 | OPCODE_I32_SHR_U = 0x76, 142 | OPCODE_I32_ROTL = 0x77, 143 | OPCODE_I32_ROTR = 0x78, 144 | 145 | OPCODE_I64_CLZ = 0x79, 146 | OPCODE_I64_CTZ = 0x7A, 147 | OPCODE_I64_POPCNT = 0x7B, 148 | OPCODE_I64_ADD = 0x7C, 149 | OPCODE_I64_SUB = 0x7D, 150 | OPCODE_I64_MUL = 0x7E, 151 | OPCODE_I64_DIV_S = 0x7F, 152 | OPCODE_I64_DIV_U = 0x80, 153 | OPCODE_I64_REM_S = 0x81, 154 | OPCODE_I64_REM_U = 0x82, 155 | OPCODE_I64_AND = 0x83, 156 | OPCODE_I64_OR = 0x84, 157 | OPCODE_I64_XOR = 0x85, 158 | OPCODE_I64_SHL = 0x86, 159 | OPCODE_I64_SHR_S = 0x87, 160 | OPCODE_I64_SHR_U = 0x88, 161 | OPCODE_I64_ROTL = 0x89, 162 | OPCODE_I64_ROTR = 0x8A, 163 | 164 | OPCODE_F32_ABS = 0x8B, 165 | OPCODE_F32_NEG = 0x8C, 166 | OPCODE_F32_CEIL = 0x8D, 167 | OPCODE_F32_FLOOR = 0x8E, 168 | OPCODE_F32_TRUNC = 0x8F, 169 | OPCODE_F32_NEAREST = 0x90, 170 | OPCODE_F32_SQRT = 0x91, 171 | OPCODE_F32_ADD = 0x92, 172 | OPCODE_F32_SUB = 0x93, 173 | OPCODE_F32_MUL = 0x94, 174 | OPCODE_F32_DIV = 0x95, 175 | OPCODE_F32_MIN = 0x96, 176 | OPCODE_F32_MAX = 0x97, 177 | OPCODE_F32_COPYSIGN = 0x98, 178 | 179 | OPCODE_F64_ABS = 0x99, 180 | OPCODE_F64_NEG = 0x9A, 181 | OPCODE_F64_CEIL = 0x9B, 182 | OPCODE_F64_FLOOR = 0x9C, 183 | OPCODE_F64_TRUNC = 0x9D, 184 | OPCODE_F64_NEAREST = 0x9E, 185 | OPCODE_F64_SQRT = 0x9F, 186 | OPCODE_F64_ADD = 0xA0, 187 | OPCODE_F64_SUB = 0xA1, 188 | OPCODE_F64_MUL = 0xA2, 189 | OPCODE_F64_DIV = 0xA3, 190 | OPCODE_F64_MIN = 0xA4, 191 | OPCODE_F64_MAX = 0xA5, 192 | OPCODE_F64_COPYSIGN = 0xA6, 193 | 194 | OPCODE_I32_WRAP_I64 = 0xA7, 195 | OPCODE_I32_TRUNC_S_F32 = 0xA8, 196 | OPCODE_I32_TRUNC_U_F32 = 0xA9, 197 | OPCODE_I32_TRUNC_S_F64 = 0xAA, 198 | OPCODE_I32_TRUNC_U_F64 = 0xAB, 199 | OPCODE_I64_EXTEND_S_I32 = 0xAC, 200 | OPCODE_I64_EXTEND_U_I32 = 0xAD, 201 | OPCODE_I64_TRUNC_S_F32 = 0xAE, 202 | OPCODE_I64_TRUNC_U_F32 = 0xAF, 203 | OPCODE_I64_TRUNC_S_F64 = 0xB0, 204 | OPCODE_I64_TRUNC_U_F64 = 0xB1, 205 | OPCODE_F32_CONVERT_S_I32 = 0xB2, 206 | OPCODE_F32_CONVERT_U_I32 = 0xB3, 207 | OPCODE_F32_CONVERT_U_I64 = 0xB4, 208 | OPCODE_F32_CONVERT_S_I64 = 0xB5, 209 | OPCODE_F32_DEMOTE_F64 = 0xB6, 210 | OPCODE_F64_CONVERT_S_I32 = 0xB7, 211 | OPCODE_F64_CONVERT_U_I32 = 0xB8, 212 | OPCODE_F64_CONVERT_U_I64 = 0xB9, 213 | OPCODE_F64_CONVERT_S_I64 = 0xBA, 214 | OPCODE_F64_PROMOTE_F32 = 0xBB, 215 | OPCODE_I32_REINTERPRET_F32 = 0xBC, 216 | OPCODE_I64_REINTERPRET_F64 = 0xBD, 217 | OPCODE_F32_REINTERPRET_I32 = 0xBE, 218 | OPCODE_F64_REINTERPRET_I64 = 0xBF, 219 | }; 220 | 221 | enum { 222 | VALTYPE_NULL = 0x40, 223 | VALTYPE_I32 = 0x7f, 224 | VALTYPE_I64 = 0x7e, 225 | VALTYPE_F32 = 0x7d, 226 | VALTYPE_F64 = 0x7c, 227 | }; 228 | 229 | typedef uint8_t wasmjit_valtype_t; 230 | typedef uint8_t wasmjit_desc_t; 231 | 232 | __attribute__ ((unused)) 233 | static const char *wasmjit_valtype_repr(wasmjit_valtype_t valtype) 234 | { 235 | switch (valtype) { 236 | case VALTYPE_I32: 237 | return "I32"; 238 | case VALTYPE_I64: 239 | return "I64"; 240 | case VALTYPE_F32: 241 | return "F32"; 242 | case VALTYPE_F64: 243 | return "F64"; 244 | default: 245 | assert(0); 246 | return NULL; 247 | } 248 | } 249 | 250 | enum { 251 | IMPORT_DESC_TYPE_FUNC, 252 | IMPORT_DESC_TYPE_TABLE, 253 | IMPORT_DESC_TYPE_MEM, 254 | IMPORT_DESC_TYPE_GLOBAL, 255 | IMPORT_DESC_TYPE_LAST, 256 | }; 257 | 258 | 259 | __attribute__ ((unused)) 260 | static const char *wasmjit_desc_repr(wasmjit_desc_t desc) 261 | { 262 | switch (desc) { 263 | case IMPORT_DESC_TYPE_FUNC: 264 | return "func"; 265 | case IMPORT_DESC_TYPE_TABLE: 266 | return "table"; 267 | case IMPORT_DESC_TYPE_MEM: 268 | return "mem"; 269 | case IMPORT_DESC_TYPE_GLOBAL: 270 | return "global"; 271 | default: 272 | assert(0); 273 | return NULL; 274 | } 275 | } 276 | 277 | enum { 278 | ELEMTYPE_ANYFUNC = 0x70, 279 | }; 280 | 281 | struct GlobalType { 282 | uint8_t valtype; 283 | uint8_t mut; 284 | }; 285 | 286 | struct Limits { 287 | uint32_t min, max; 288 | }; 289 | 290 | #define FUNC_TYPE_N_OUTPUTS(ft) ((ft)->output_type == VALTYPE_NULL ? 0 : 1) 291 | #define FUNC_TYPE_OUTPUT_IDX(ft, idx) ((ft)->output_type) 292 | #define FUNC_TYPE_OUTPUT_TYPES(ft) (&((ft)->output_type)) 293 | 294 | #define FUNC_TYPE_MAX_INPUTS 254 295 | #define FUNC_TYPE_MAX_OUTPUTS 1 296 | 297 | struct FuncType { 298 | uint8_t n_inputs; 299 | wasmjit_valtype_t input_types[FUNC_TYPE_MAX_INPUTS]; 300 | wasmjit_valtype_t output_type; 301 | }; 302 | 303 | struct TableType { 304 | unsigned elemtype; 305 | struct Limits limits; 306 | }; 307 | 308 | struct MemoryType { 309 | struct Limits limits; 310 | }; 311 | 312 | struct Instr { 313 | uint8_t opcode; 314 | union { 315 | struct BlockLoopExtra { 316 | uint8_t blocktype; 317 | size_t n_instructions; 318 | struct Instr *instructions; 319 | } block, loop; 320 | struct IfExtra { 321 | uint8_t blocktype; 322 | size_t n_instructions_then; 323 | struct Instr *instructions_then; 324 | size_t n_instructions_else; 325 | struct Instr *instructions_else; 326 | } if_; 327 | struct BrIfExtra { 328 | uint32_t labelidx; 329 | } br, br_if; 330 | struct { 331 | uint32_t n_labelidxs; 332 | uint32_t *labelidxs; 333 | uint32_t labelidx; 334 | } br_table; 335 | struct { 336 | uint32_t funcidx; 337 | } call; 338 | struct { 339 | uint32_t typeidx; 340 | } call_indirect; 341 | struct LocalExtra { 342 | uint32_t localidx; 343 | } get_local, set_local, tee_local; 344 | struct GlobalExtra { 345 | uint32_t globalidx; 346 | } get_global, set_global; 347 | struct LoadStoreExtra { 348 | uint32_t align; 349 | uint32_t offset; 350 | } i32_load, i64_load, f32_load, f64_load, 351 | i32_load8_s, i32_load8_u, i32_load16_s, i32_load16_u, 352 | i64_load8_s, i64_load8_u, i64_load16_s, i64_load16_u, 353 | i64_load32_s, i64_load32_u, 354 | i32_store, i64_store, f32_store, f64_store, 355 | i32_store8, i32_store16, i64_store8, i64_store16, 356 | i64_store32; 357 | struct { 358 | uint32_t value; 359 | } i32_const; 360 | struct { 361 | uint64_t value; 362 | } i64_const; 363 | struct { 364 | float value; 365 | } f32_const; 366 | struct { 367 | double value; 368 | } f64_const; 369 | } data; 370 | }; 371 | 372 | void init_instruction(struct Instr *instr); 373 | void free_instruction(struct Instr *instr); 374 | void free_instructions(struct Instr *instructions, size_t n_instructions); 375 | 376 | #define TypeSectionType FuncType 377 | 378 | struct TypeSection { 379 | uint32_t n_types; 380 | struct TypeSectionType *types; 381 | }; 382 | 383 | struct ImportSection { 384 | uint32_t n_imports; 385 | struct ImportSectionImport { 386 | char *module; 387 | char *name; 388 | unsigned desc_type; 389 | union { 390 | uint32_t functypeidx; 391 | struct TableType tabletype; 392 | struct MemoryType memtype; 393 | struct GlobalType globaltype; 394 | } desc; 395 | } *imports; 396 | }; 397 | 398 | struct FunctionSection { 399 | uint32_t n_typeidxs; 400 | uint32_t *typeidxs; 401 | }; 402 | 403 | #define TableSectionTable TableType 404 | 405 | struct TableSection { 406 | uint32_t n_tables; 407 | struct TableType *tables; 408 | }; 409 | 410 | struct MemorySection { 411 | uint32_t n_memories; 412 | struct MemorySectionMemory { 413 | struct MemoryType memtype; 414 | } *memories; 415 | }; 416 | 417 | struct GlobalSection { 418 | uint32_t n_globals; 419 | struct GlobalSectionGlobal { 420 | struct GlobalType type; 421 | size_t n_instructions; 422 | struct Instr *instructions; 423 | } *globals; 424 | }; 425 | 426 | struct ExportSection { 427 | uint32_t n_exports; 428 | struct ExportSectionExport { 429 | char *name; 430 | uint8_t idx_type; 431 | uint32_t idx; 432 | } *exports; 433 | }; 434 | 435 | struct StartSection { 436 | int has_start; 437 | uint32_t funcidx; 438 | }; 439 | 440 | struct ElementSection { 441 | uint32_t n_elements; 442 | struct ElementSectionElement { 443 | uint32_t tableidx; 444 | size_t n_instructions; 445 | struct Instr *instructions; 446 | uint32_t n_funcidxs; 447 | uint32_t *funcidxs; 448 | } *elements; 449 | }; 450 | 451 | struct CodeSection { 452 | uint32_t n_codes; 453 | struct CodeSectionCode { 454 | uint32_t size; 455 | uint32_t n_locals; 456 | struct CodeSectionCodeLocal { 457 | uint32_t count; 458 | wasmjit_valtype_t valtype; 459 | } *locals; 460 | size_t n_instructions; 461 | struct Instr *instructions; 462 | } *codes; 463 | }; 464 | 465 | struct DataSection { 466 | uint32_t n_datas; 467 | struct DataSectionData { 468 | uint32_t memidx; 469 | size_t n_instructions; 470 | struct Instr *instructions; 471 | uint32_t buf_size; 472 | char *buf; 473 | } *datas; 474 | }; 475 | 476 | struct Module { 477 | struct TypeSection type_section; 478 | struct ImportSection import_section; 479 | struct FunctionSection function_section; 480 | struct TableSection table_section; 481 | struct MemorySection memory_section; 482 | struct GlobalSection global_section; 483 | struct ExportSection export_section; 484 | struct StartSection start_section; 485 | struct ElementSection element_section; 486 | struct CodeSection code_section; 487 | struct DataSection data_section; 488 | }; 489 | 490 | void wasmjit_init_module(struct Module *module); 491 | void wasmjit_free_module(struct Module *modules); 492 | 493 | #endif 494 | -------------------------------------------------------------------------------- /src/wasmjit/ast_dump.c: -------------------------------------------------------------------------------- 1 | /* -*-mode:c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ 2 | 3 | /* 4 | Copyright (c) 2018 Rian Hunter 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #include 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | void dump_type_section(struct TypeSection *type_section) 33 | { 34 | size_t i, j; 35 | for (i = 0; i < type_section->n_types; ++i) { 36 | struct TypeSectionType *type = &type_section->types[i]; 37 | 38 | printf("("); 39 | for (j = 0; j < type->n_inputs; ++j) { 40 | printf("%d,", type->input_types[j]); 41 | } 42 | printf(") -> ("); 43 | for (j = 0; j < FUNC_TYPE_N_OUTPUTS(type); ++j) { 44 | printf("%d,", FUNC_TYPE_OUTPUT_TYPES(type)[j]); 45 | } 46 | printf(")\n"); 47 | } 48 | } 49 | 50 | void dump_global_section(struct GlobalSection *global_section) 51 | { 52 | uint32_t i; 53 | 54 | for (i = 0; i < global_section->n_globals; ++i) { 55 | struct GlobalSectionGlobal *global = 56 | &global_section->globals[i]; 57 | printf("Global Section %" PRIu32 " type: %" PRIu8 58 | " can mute: %" PRIu8 "\n", i, 59 | global->type.valtype, global->type.mut); 60 | } 61 | } 62 | 63 | void dump_instructions(const struct Instr *instructions, 64 | size_t n_instructions, int indent); 65 | 66 | void dump_instruction(const struct Instr *instruction, int indent) 67 | { 68 | int sps = indent * 2; 69 | const char *name; 70 | switch (instruction->opcode) { 71 | case OPCODE_UNREACHABLE: 72 | printf("%*sunreachable\n", sps, ""); 73 | break; 74 | case OPCODE_BLOCK: 75 | printf("%*sblock 0x%02" PRIx8 "\n", sps, "", 76 | instruction->data.block.blocktype); 77 | dump_instructions(instruction->data.block.instructions, 78 | instruction->data.block.n_instructions, 79 | indent + 1); 80 | break; 81 | case OPCODE_LOOP: 82 | printf("%*sloop 0x%02" PRIx8 "\n", sps, "", 83 | instruction->data.loop.blocktype); 84 | dump_instructions(instruction->data.loop.instructions, 85 | instruction->data.loop.n_instructions, 86 | indent + 1); 87 | break; 88 | case OPCODE_IF: 89 | printf("%*sif 0x%02" PRIx8 "\n", sps, "", 90 | instruction->data.if_.blocktype); 91 | dump_instructions(instruction->data.if_.instructions_then, 92 | instruction->data.if_.n_instructions_then, 93 | indent + 1); 94 | if (instruction->data.if_.n_instructions_else) { 95 | printf("%*selse\n", sps, ""); 96 | dump_instructions(instruction->data.if_.instructions_else, 97 | instruction->data.if_.n_instructions_else, 98 | indent + 1); 99 | } 100 | break; 101 | case OPCODE_BR: 102 | printf("%*sbr 0x%" PRIx32 "\n", sps, "", 103 | instruction->data.br.labelidx); 104 | break; 105 | case OPCODE_BR_IF: 106 | printf("%*sbr_if 0x%" PRIx32 "\n", sps, "", 107 | instruction->data.br_if.labelidx); 108 | break; 109 | case OPCODE_RETURN: 110 | printf("%*sreturn\n", sps, ""); 111 | break; 112 | case OPCODE_CALL: 113 | printf("%*scall 0x%" PRIx32 "\n", sps, "", 114 | instruction->data.call.funcidx); 115 | break; 116 | case OPCODE_DROP: 117 | printf("%*sdrop\n", sps, ""); 118 | break; 119 | case OPCODE_GET_LOCAL: 120 | printf("%*sget_local 0x%" PRIx32 "\n", sps, "", 121 | instruction->data.get_local.localidx); 122 | break; 123 | case OPCODE_SET_LOCAL: 124 | printf("%*sset_local 0x%" PRIx32 "\n", sps, "", 125 | instruction->data.set_local.localidx); 126 | break; 127 | case OPCODE_TEE_LOCAL: 128 | printf("%*stee_local 0x%" PRIx32 "\n", sps, "", 129 | instruction->data.tee_local.localidx); 130 | break; 131 | case OPCODE_GET_GLOBAL: 132 | printf("%*sget_global 0x%" PRIx32 "\n", sps, "", 133 | instruction->data.get_global.globalidx); 134 | break; 135 | case OPCODE_SET_GLOBAL: 136 | printf("%*sset_global 0x%" PRIx32 "\n", sps, "", 137 | instruction->data.set_global.globalidx); 138 | break; 139 | case OPCODE_I32_LOAD: 140 | name = "i32.load"; 141 | printf("%*s%s align: 0x%" PRIx32 " offset: 0x%" PRIx32 142 | "\n", sps, "", name, 143 | instruction->data.i32_load.align, 144 | instruction->data.i32_load.offset); 145 | break; 146 | case OPCODE_I32_CONST: 147 | printf("%*si32.const 0x%" PRIx32 "\n", sps, "", 148 | instruction->data.i32_const.value); 149 | break; 150 | case OPCODE_I32_LT_S: 151 | printf("%*si32.lt_s\n", sps, ""); 152 | break; 153 | case OPCODE_I32_GE_S: 154 | printf("%*si32.ge_s\n", sps, ""); 155 | break; 156 | case OPCODE_I32_ADD: 157 | printf("%*si32.add\n", sps, ""); 158 | break; 159 | case OPCODE_I32_MUL: 160 | printf("%*si32.mul\n", sps, ""); 161 | break; 162 | case OPCODE_I32_AND: 163 | printf("%*si32.and\n", sps, ""); 164 | break; 165 | default: 166 | printf("%*sBAD 0x%02" PRIx8 "\n", sps, "", instruction->opcode); 167 | break; 168 | } 169 | } 170 | 171 | void dump_instructions(const struct Instr *instructions, 172 | size_t n_instructions, int indent) 173 | { 174 | uint32_t i; 175 | 176 | for (i = 0; i < n_instructions; ++i) { 177 | dump_instruction(&instructions[i], indent); 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /src/wasmjit/ast_dump.h: -------------------------------------------------------------------------------- 1 | /* -*-mode:c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ 2 | 3 | /* 4 | Copyright (c) 2018 Rian Hunter 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #ifndef __WASMJIT__WASMBIN_DUMP_H__ 26 | #define __WASMJIT__WASMBIN_DUMP_H__ 27 | 28 | #include 29 | 30 | void dump_instruction(const struct Instr *instructions, 31 | int indent); 32 | 33 | void dump_instructions(const struct Instr *instructions, size_t n_instructions, 34 | int indent); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /src/wasmjit/compile.h: -------------------------------------------------------------------------------- 1 | /* -*-mode:c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ 2 | 3 | /* 4 | Copyright (c) 2018 Rian Hunter 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #ifndef __WASMJIT__COMPILE_H__ 26 | #define __WASMJIT__COMPILE_H__ 27 | 28 | #include 29 | 30 | #include 31 | 32 | struct ModuleTypes { 33 | struct FuncType *functypes; 34 | struct TableType *tabletypes; 35 | struct MemoryType *memorytypes; 36 | struct GlobalType *globaltypes; 37 | }; 38 | 39 | struct MemoryReferences { 40 | size_t n_elts; 41 | struct MemoryReferenceElt { 42 | enum { 43 | MEMREF_TYPE, 44 | MEMREF_FUNC, 45 | MEMREF_TABLE, 46 | MEMREF_MEM, 47 | MEMREF_GLOBAL, 48 | MEMREF_RESOLVE_INDIRECT_CALL, 49 | MEMREF_TRAP, 50 | MEMREF_STACK_TOP, 51 | } type; 52 | size_t code_offset; 53 | size_t idx; 54 | } *elts; 55 | }; 56 | 57 | char *wasmjit_compile_function(const struct FuncType *func_types, 58 | const struct ModuleTypes *module_types, 59 | const struct FuncType *type, 60 | const struct CodeSectionCode *code, 61 | struct MemoryReferences *memrefs, 62 | size_t *out_size, 63 | size_t *stack_usage); 64 | 65 | char *wasmjit_compile_hostfunc(struct FuncType *type, 66 | void *hostfunc, 67 | void *funcinst_ptr, 68 | size_t *out_size); 69 | 70 | char *wasmjit_compile_invoker(struct FuncType *type, 71 | void *compiled_code, 72 | size_t *out_size); 73 | 74 | char *wasmjit_compile_invoker_offset(struct FuncType *type, 75 | size_t *compiled_code_offset, 76 | size_t *out_size); 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /src/wasmjit/dynamic_emscripten_runtime.c: -------------------------------------------------------------------------------- 1 | /* -*-mode:c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ 2 | 3 | /* 4 | Copyright (c) 2018 Rian Hunter 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include 31 | 32 | static struct FuncInst *alloc_func(struct ModuleInst *module, void *_fptr, 33 | wasmjit_valtype_t _output, size_t n_inputs, 34 | wasmjit_valtype_t *inputs) 35 | { 36 | void *tmp_unmapped = NULL; 37 | struct FuncInst *tmp_func = NULL; 38 | 39 | tmp_func = calloc(1, sizeof(struct FuncInst)); 40 | if (!tmp_func) 41 | goto error; 42 | tmp_func->module_inst = module; 43 | tmp_func->type.n_inputs = n_inputs; 44 | memcpy(tmp_func->type.input_types, inputs, n_inputs); 45 | tmp_func->type.output_type = _output; 46 | tmp_unmapped = 47 | wasmjit_compile_hostfunc(&tmp_func->type, _fptr, 48 | tmp_func, 49 | &tmp_func->compiled_code_size); 50 | if (!tmp_unmapped) 51 | goto error; 52 | tmp_func->compiled_code = 53 | wasmjit_map_code_segment(tmp_func->compiled_code_size); 54 | if (!tmp_func->compiled_code) 55 | goto error; 56 | memcpy(tmp_func->compiled_code, tmp_unmapped, 57 | tmp_func->compiled_code_size); 58 | if (!wasmjit_mark_code_segment_executable(tmp_func->compiled_code, 59 | tmp_func->compiled_code_size)) 60 | goto error; 61 | tmp_unmapped = 62 | wasmjit_compile_invoker(&tmp_func->type, 63 | tmp_func->compiled_code, 64 | &tmp_func->invoker_size); 65 | if (!tmp_unmapped) 66 | goto error; 67 | tmp_func->invoker = 68 | wasmjit_map_code_segment(tmp_func->invoker_size); 69 | memcpy(tmp_func->invoker, tmp_unmapped, 70 | tmp_func->invoker_size); 71 | if (!wasmjit_mark_code_segment_executable(tmp_func->invoker, 72 | tmp_func->invoker_size)) 73 | goto error; 74 | 75 | if (0) { 76 | error: 77 | if (tmp_func) 78 | wasmjit_free_func_inst(tmp_func); 79 | tmp_func = NULL; 80 | } 81 | 82 | if (tmp_unmapped) 83 | free(tmp_unmapped); 84 | 85 | return tmp_func; 86 | } 87 | 88 | struct NamedModule *wasmjit_instantiate_emscripten_runtime(uint32_t static_bump, 89 | int has_table, 90 | size_t tablemin, 91 | size_t tablemax, 92 | size_t *amt) 93 | { 94 | struct { 95 | size_t n_elts; 96 | struct NamedModule *elts; 97 | } modules = {0, NULL}; 98 | struct FuncInst *tmp_func = NULL; 99 | struct FuncInst *start_func = NULL; 100 | struct FuncInst **tmp_table_buf = NULL; 101 | struct TableInst *tmp_table = NULL; 102 | char *tmp_mem_buf = NULL; 103 | struct MemInst *tmp_mem = NULL; 104 | struct GlobalInst *tmp_global = NULL; 105 | struct ModuleInst *module = NULL; 106 | struct NamedModule *ret; 107 | struct WasmJITEmscriptenMemoryGlobals globals; 108 | 109 | wasmjit_emscripten_derive_memory_globals(static_bump, &globals); 110 | 111 | /* TODO: add exports */ 112 | 113 | #define LVECTOR_GROW(sstack, n_elts) \ 114 | do { \ 115 | if (!VECTOR_GROW((sstack), (n_elts))) \ 116 | goto error; \ 117 | } \ 118 | while (0) 119 | 120 | #define START_MODULE() \ 121 | { \ 122 | if (start_func) { \ 123 | wasmjit_free_func_inst(start_func); \ 124 | start_func = NULL; \ 125 | } \ 126 | module = calloc(1, sizeof(struct ModuleInst)); \ 127 | if (!module) \ 128 | goto error; \ 129 | } 130 | 131 | #define STR(x) #x 132 | #define XSTR(x) STR(x) 133 | 134 | #define END_MODULE() \ 135 | { \ 136 | if (!strcmp(XSTR(CURRENT_MODULE), "env")) { \ 137 | module->private_data = calloc(1, sizeof(struct EmscriptenContext)); \ 138 | if (!module->private_data) \ 139 | goto error; \ 140 | module->free_private_data = &free; \ 141 | } \ 142 | if (start_func) { \ 143 | wasmjit_invoke_function(start_func, NULL, NULL); \ 144 | } \ 145 | LVECTOR_GROW(&modules, 1); \ 146 | modules.elts[modules.n_elts - 1].name = strdup(XSTR(CURRENT_MODULE)); \ 147 | modules.elts[modules.n_elts - 1].module = module; \ 148 | module = NULL; \ 149 | } 150 | 151 | #define START_TABLE_DEFS() 152 | #define END_TABLE_DEFS() 153 | #define START_MEMORY_DEFS() 154 | #define END_MEMORY_DEFS() 155 | #define START_GLOBAL_DEFS() 156 | #define END_GLOBAL_DEFS() 157 | #define START_FUNCTION_DEFS() 158 | #define END_FUNCTION_DEFS() 159 | 160 | #define DEFINE_WASM_FUNCTION(_name, _fptr, _output, n, ...) \ 161 | { \ 162 | wasmjit_valtype_t inputs[] = { __VA_ARGS__ }; \ 163 | tmp_func = alloc_func(module, _fptr, _output, n, inputs); \ 164 | if (!tmp_func) \ 165 | goto error; \ 166 | LVECTOR_GROW(&module->funcs, 1); \ 167 | module->funcs.elts[module->funcs.n_elts - 1] = tmp_func; \ 168 | tmp_func = NULL; \ 169 | \ 170 | LVECTOR_GROW(&module->exports, 1); \ 171 | module->exports.elts[module->exports.n_elts - 1].name = strdup(#_name); \ 172 | module->exports.elts[module->exports.n_elts - 1].type = IMPORT_DESC_TYPE_FUNC; \ 173 | module->exports.elts[module->exports.n_elts - 1].value.func = module->funcs.elts[module->funcs.n_elts - 1]; \ 174 | } 175 | 176 | #define DEFINE_WASM_START_FUNCTION(fptr) \ 177 | do { \ 178 | start_func = alloc_func(module, fptr, VALTYPE_NULL, 0, NULL); \ 179 | if (!start_func) \ 180 | goto error; \ 181 | } while (0); 182 | 183 | #define DEFINE_EXTERNAL_WASM_TABLE(name) \ 184 | if (has_ ## name) { \ 185 | DEFINE_WASM_TABLE(name, ELEMTYPE_ANYFUNC, \ 186 | name ## min, name ## max) \ 187 | } 188 | 189 | #define DEFINE_WASM_TABLE(_name, _elemtype, _min, _max) \ 190 | { \ 191 | tmp_table_buf = calloc(_min, sizeof(tmp_table_buf[0])); \ 192 | if ((_min) && !tmp_table_buf) \ 193 | goto error; \ 194 | tmp_table = calloc(1, sizeof(struct TableInst)); \ 195 | if (!tmp_table) \ 196 | goto error; \ 197 | tmp_table->data = tmp_table_buf; \ 198 | tmp_table_buf = NULL; \ 199 | tmp_table->elemtype = (_elemtype); \ 200 | tmp_table->length = (_min); \ 201 | tmp_table->max = (_max); \ 202 | LVECTOR_GROW(&module->tables, 1); \ 203 | module->tables.elts[module->tables.n_elts - 1] = tmp_table; \ 204 | tmp_table = NULL; \ 205 | \ 206 | LVECTOR_GROW(&module->exports, 1); \ 207 | module->exports.elts[module->exports.n_elts - 1].name = strdup(#_name); \ 208 | module->exports.elts[module->exports.n_elts - 1].type = IMPORT_DESC_TYPE_TABLE; \ 209 | module->exports.elts[module->exports.n_elts - 1].value.table = module->tables.elts[module->tables.n_elts - 1]; \ 210 | } 211 | 212 | #define DEFINE_WASM_MEMORY(_name, _min, _max) \ 213 | { \ 214 | tmp_mem_buf = calloc((_min) * WASM_PAGE_SIZE, 1); \ 215 | if ((_min) && !tmp_mem_buf) \ 216 | goto error; \ 217 | tmp_mem = calloc(1, sizeof(struct MemInst)); \ 218 | tmp_mem->data = tmp_mem_buf; \ 219 | tmp_mem_buf = NULL; \ 220 | tmp_mem->size = (_min) * WASM_PAGE_SIZE; \ 221 | tmp_mem->max = (_max) * WASM_PAGE_SIZE; \ 222 | LVECTOR_GROW(&module->mems, 1); \ 223 | module->mems.elts[module->mems.n_elts - 1] = tmp_mem; \ 224 | tmp_mem = NULL; \ 225 | \ 226 | LVECTOR_GROW(&module->exports, 1); \ 227 | module->exports.elts[module->exports.n_elts - 1].name = strdup(#_name); \ 228 | module->exports.elts[module->exports.n_elts - 1].type = IMPORT_DESC_TYPE_MEM; \ 229 | module->exports.elts[module->exports.n_elts - 1].value.mem = module->mems.elts[module->mems.n_elts - 1]; \ 230 | } 231 | 232 | #define DEFINE_EXTERNAL_WASM_GLOBAL(_name) \ 233 | DEFINE_WASM_GLOBAL(_name, globals. _name, VALTYPE_I32, i32, 0) \ 234 | 235 | #define DEFINE_WASM_GLOBAL(_name, _init, _type, _member, _mut) \ 236 | { \ 237 | tmp_global = calloc(1, sizeof(struct GlobalInst)); \ 238 | if (!tmp_global) \ 239 | goto error; \ 240 | tmp_global->value.type = (_type); \ 241 | tmp_global->value.data._member = (_init); \ 242 | tmp_global->mut = (_mut); \ 243 | LVECTOR_GROW(&module->globals, 1); \ 244 | module->globals.elts[module->globals.n_elts - 1] = tmp_global; \ 245 | tmp_global = NULL; \ 246 | \ 247 | LVECTOR_GROW(&module->exports, 1); \ 248 | module->exports.elts[module->exports.n_elts - 1].name = strdup(#_name); \ 249 | module->exports.elts[module->exports.n_elts - 1].type = IMPORT_DESC_TYPE_GLOBAL; \ 250 | module->exports.elts[module->exports.n_elts - 1].value.global = module->globals.elts[module->globals.n_elts - 1]; \ 251 | } 252 | 253 | #include 254 | 255 | if (0) { 256 | error: 257 | ret = NULL; 258 | 259 | if (modules.elts) { 260 | size_t i; 261 | for (i = 0; i < modules.n_elts; i++) { 262 | struct NamedModule *nm = &modules.elts[i]; 263 | free(nm->name); 264 | wasmjit_free_module_inst(nm->module); 265 | } 266 | free(modules.elts); 267 | } 268 | } 269 | else { 270 | ret = modules.elts; 271 | if (amt) { 272 | *amt = modules.n_elts; 273 | } 274 | } 275 | 276 | if (module) { 277 | wasmjit_free_module_inst(module); 278 | } 279 | if (tmp_func) { 280 | wasmjit_free_func_inst(tmp_func); 281 | } 282 | if (start_func) { 283 | wasmjit_free_func_inst(start_func); 284 | } 285 | if (tmp_table_buf) 286 | free(tmp_table_buf); 287 | if (tmp_table) { 288 | free(tmp_table->data); 289 | free(tmp_table); 290 | } 291 | if (tmp_mem_buf) 292 | free(tmp_mem_buf); 293 | if (tmp_mem) { 294 | free(tmp_mem->data); 295 | free(tmp_mem); 296 | } 297 | if (tmp_global) 298 | free(tmp_global); 299 | 300 | return ret; 301 | } 302 | -------------------------------------------------------------------------------- /src/wasmjit/dynamic_emscripten_runtime.h: -------------------------------------------------------------------------------- 1 | /* -*-mode:c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ 2 | 3 | /* 4 | Copyright (c) 2018 Rian Hunter 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #ifndef __WASMJIT__DYNAMIC_EMSCRIPTEN_RUNTIME_H__ 26 | #define __WASMJIT__DYNAMIC_EMSCRIPTEN_RUNTIME_H__ 27 | 28 | #include 29 | 30 | struct NamedModule *wasmjit_instantiate_emscripten_runtime(uint32_t static_bump, 31 | int has_table, 32 | size_t tablemin, 33 | size_t tablemax, 34 | size_t *amt); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /src/wasmjit/dynamic_runtime.c: -------------------------------------------------------------------------------- 1 | /* -*-mode:c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ 2 | 3 | /* 4 | Copyright (c) 2018 Rian Hunter 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #include 26 | 27 | #include 28 | 29 | /* platform specific */ 30 | 31 | #ifdef __KERNEL__ 32 | 33 | #include 34 | 35 | #include 36 | #include 37 | 38 | void *wasmjit_map_code_segment(size_t code_size) 39 | { 40 | return __vmalloc(code_size, GFP_KERNEL, PAGE_KERNEL_EXEC); 41 | } 42 | 43 | int wasmjit_mark_code_segment_executable(void *code, size_t code_size) 44 | { 45 | /* TODO: mess with pte a la mprotect_fixup */ 46 | (void)code; 47 | (void)code_size; 48 | return 1; 49 | } 50 | 51 | int wasmjit_unmap_code_segment(void *code, size_t code_size) 52 | { 53 | (void)code_size; 54 | vfree(code); 55 | return 1; 56 | } 57 | 58 | jmp_buf *wasmjit_get_jmp_buf(void) 59 | { 60 | return wasmjit_get_ktls()->jmp_buf; 61 | } 62 | 63 | int wasmjit_set_jmp_buf(jmp_buf *jmpbuf) 64 | { 65 | wasmjit_get_ktls()->jmp_buf = jmpbuf; 66 | return 1; 67 | } 68 | 69 | void *wasmjit_stack_top(void) 70 | { 71 | return wasmjit_get_ktls()->stack_top; 72 | } 73 | 74 | int wasmjit_set_stack_top(void *stack_top) 75 | { 76 | wasmjit_get_ktls()->stack_top = stack_top; 77 | return 1; 78 | } 79 | 80 | #else 81 | 82 | #include 83 | 84 | #include 85 | 86 | void *wasmjit_map_code_segment(size_t code_size) 87 | { 88 | void *newcode; 89 | newcode = mmap(NULL, code_size, PROT_READ | PROT_WRITE, 90 | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 91 | if (newcode == MAP_FAILED) 92 | return NULL; 93 | return newcode; 94 | } 95 | 96 | int wasmjit_mark_code_segment_executable(void *code, size_t code_size) 97 | { 98 | return !mprotect(code, code_size, PROT_READ | PROT_EXEC); 99 | } 100 | 101 | 102 | int wasmjit_unmap_code_segment(void *code, size_t code_size) 103 | { 104 | return !munmap(code, code_size); 105 | } 106 | 107 | wasmjit_tls_key_t jmp_buf_key; 108 | 109 | __attribute__((constructor)) 110 | static void _init_jmp_buf(void) 111 | { 112 | wasmjit_init_tls_key(&jmp_buf_key, NULL); 113 | } 114 | 115 | jmp_buf *wasmjit_get_jmp_buf(void) 116 | { 117 | jmp_buf *toret; 118 | int ret; 119 | ret = wasmjit_get_tls_key(jmp_buf_key, &toret); 120 | if (!ret) return NULL; 121 | return toret; 122 | } 123 | 124 | int wasmjit_set_jmp_buf(jmp_buf *jmpbuf) 125 | { 126 | return wasmjit_set_tls_key(jmp_buf_key, jmpbuf); 127 | } 128 | 129 | wasmjit_tls_key_t stack_top_key; 130 | 131 | __attribute__((constructor)) 132 | static void _init_stack_top(void) 133 | { 134 | wasmjit_init_tls_key(&stack_top_key, NULL); 135 | } 136 | 137 | void *wasmjit_stack_top(void) 138 | { 139 | jmp_buf *toret; 140 | int ret; 141 | ret = wasmjit_get_tls_key(stack_top_key, &toret); 142 | if (!ret) return NULL; 143 | return toret; 144 | } 145 | 146 | int wasmjit_set_stack_top(void *stack_top) 147 | { 148 | return wasmjit_set_tls_key(stack_top_key, stack_top); 149 | } 150 | 151 | #endif 152 | 153 | __attribute__((noreturn)) 154 | void wasmjit_trap(int reason) 155 | { 156 | assert(reason); 157 | longjmp(*wasmjit_get_jmp_buf(), reason); 158 | } 159 | 160 | int wasmjit_invoke_function(struct FuncInst *funcinst, 161 | union ValueUnion *values, 162 | union ValueUnion *out) 163 | { 164 | union ValueUnion lout; 165 | int ret; 166 | jmp_buf jmpbuf; 167 | 168 | if (wasmjit_get_jmp_buf()) { 169 | lout = wasmjit_invoke_function_raw(funcinst, values); 170 | if (out) 171 | *out = lout; 172 | ret = 0; 173 | } else { 174 | wasmjit_set_jmp_buf(&jmpbuf); 175 | if (!(ret = setjmp(jmpbuf))) { 176 | lout = wasmjit_invoke_function_raw(funcinst, values); 177 | if (out) 178 | *out = lout; 179 | ret = 0; 180 | } 181 | wasmjit_set_jmp_buf(NULL); 182 | } 183 | 184 | return ret; 185 | } 186 | -------------------------------------------------------------------------------- /src/wasmjit/elf_relocatable.h: -------------------------------------------------------------------------------- 1 | /* -*-mode:c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ 2 | 3 | /* 4 | Copyright (c) 2018 Rian Hunter 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #ifndef __WASMJIT__ELF_RELOCATABLE_H__ 26 | #define __WASMJIT__ELF_RELOCATABLE_H__ 27 | 28 | #include 29 | 30 | void *wasmjit_output_elf_relocatable(const char *module_name, 31 | const struct Module *module, 32 | size_t *outsize); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /src/wasmjit/emscripten_runtime.h: -------------------------------------------------------------------------------- 1 | /* -*-mode:c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ 2 | 3 | /* 4 | Copyright (c) 2018 Rian Hunter 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #ifndef __WASMJIT__EMSCRIPTEN_RUNTIME_H__ 26 | #define __WASMJIT__EMSCRIPTEN_RUNTIME_H__ 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | enum { 33 | WASMJIT_EMSCRIPTEN_TOTAL_MEMORY = 16777216, 34 | }; 35 | 36 | struct EmscriptenContext { 37 | struct FuncInst *errno_location_inst; 38 | char **environ; 39 | int buildEnvironmentCalled; 40 | struct FuncInst *malloc_inst; 41 | struct FuncInst *free_inst; 42 | }; 43 | 44 | #define CTYPE_VALTYPE_I32 uint32_t 45 | #define CTYPE_VALTYPE_NULL void 46 | #define CTYPE(val) CTYPE_ ## val 47 | 48 | #define __PARAM(to, n, t) CTYPE(t) 49 | 50 | #define COMMA_0 51 | #define COMMA_1 , 52 | #define COMMA_2 , 53 | #define COMMA_3 , 54 | #define COMMA_IF_NOT_EMPTY(_n) CAT(COMMA_, _n) 55 | 56 | #define DEFINE_WASM_FUNCTION(_name, _fptr, _output, _n, ...) \ 57 | CTYPE(_output) wasmjit_emscripten_ ## _name(__KMAP(_n, __PARAM, ##__VA_ARGS__) COMMA_IF_NOT_EMPTY(_n) struct FuncInst *); 58 | 59 | #define DEFINE_WASM_START_FUNCTION(_name) \ 60 | void _name(struct FuncInst *); 61 | 62 | #define START_MODULE() 63 | #define END_MODULE() 64 | #define START_FUNCTION_DEFS() 65 | #define END_FUNCTION_DEFS() 66 | #define START_TABLE_DEFS() 67 | #define END_TABLE_DEFS() 68 | #define START_MEMORY_DEFS() 69 | #define END_MEMORY_DEFS() 70 | #define START_GLOBAL_DEFS() 71 | #define END_GLOBAL_DEFS() 72 | #define DEFINE_WASM_GLOBAL(...) 73 | #define DEFINE_WASM_TABLE(...) 74 | #define DEFINE_WASM_MEMORY(...) 75 | #define DEFINE_EXTERNAL_WASM_GLOBAL(...) 76 | #define DEFINE_EXTERNAL_WASM_TABLE(...) 77 | 78 | #include 79 | 80 | #undef COMMA_0 81 | #undef COMMA_1 82 | #undef COMMA_2 83 | #undef COMMA_3 84 | #undef COMMA_IF_NOT_EMPTY 85 | #undef START_MODULE 86 | #undef END_MODULE 87 | #undef DEFINE_WASM_GLOBAL 88 | #undef DEFINE_WASM_FUNCTION 89 | #undef DEFINE_WASM_TABLE 90 | #undef DEFINE_WASM_MEMORY 91 | #undef START_TABLE_DEFS 92 | #undef END_TABLE_DEFS 93 | #undef START_MEMORY_DEFS 94 | #undef END_MEMORY_DEFS 95 | #undef START_GLOBAL_DEFS 96 | #undef END_GLOBAL_DEFS 97 | #undef START_FUNCTION_DEFS 98 | #undef END_FUNCTION_DEFS 99 | #undef DEFINE_WASM_START_FUNCTION 100 | #undef DEFINE_EXTERNAL_WASM_TABLE 101 | #undef DEFINE_EXTERNAL_WASM_GLOBAL 102 | 103 | #undef __PARAM 104 | #undef CTYPE 105 | #undef CTYPE_VALTYPE_I32 106 | #undef CTYPE_VALTYPE_NULL 107 | 108 | struct EmscriptenContext *wasmjit_emscripten_get_context(struct ModuleInst *); 109 | void wasmjit_emscripten_cleanup(struct ModuleInst *); 110 | 111 | void wasmjit_emscripten_internal_abort(const char *msg) __attribute__((noreturn)); 112 | struct MemInst *wasmjit_emscripten_get_mem_inst(struct FuncInst *funcinst); 113 | 114 | 115 | int wasmjit_emscripten_init(struct EmscriptenContext *ctx, 116 | struct FuncInst *errno_location_inst, 117 | struct FuncInst *malloc_inst, 118 | struct FuncInst *free_inst, 119 | char *envp[]); 120 | 121 | #define WASMJIT_TRAP_OFFSET 0x100 122 | #define WASMJIT_IS_TRAP_ERROR(ret) ((ret) >= WASMJIT_TRAP_OFFSET) 123 | #define WASMJIT_DECODE_TRAP_ERROR(ret) ((ret) - WASMJIT_TRAP_OFFSET) 124 | #define WASMJIT_ENCODE_TRAP_ERROR(ret) ((ret) + WASMJIT_TRAP_OFFSET) 125 | 126 | int wasmjit_emscripten_build_environment(struct FuncInst *environ_constructor); 127 | 128 | int wasmjit_emscripten_invoke_main(struct MemInst *meminst, 129 | struct FuncInst *stack_alloc_inst, 130 | struct FuncInst *main_inst, 131 | int argc, 132 | char *argv[]); 133 | 134 | struct WasmJITEmscriptenMemoryGlobals { 135 | uint32_t memoryBase; 136 | uint32_t tempDoublePtr; 137 | uint32_t DYNAMICTOP_PTR; 138 | uint32_t STACKTOP; 139 | uint32_t STACK_MAX; 140 | }; 141 | 142 | void wasmjit_emscripten_derive_memory_globals(uint32_t static_bump, 143 | struct WasmJITEmscriptenMemoryGlobals *out); 144 | 145 | #endif 146 | -------------------------------------------------------------------------------- /src/wasmjit/emscripten_runtime_def.h: -------------------------------------------------------------------------------- 1 | /* -*-mode:c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ 2 | 3 | /* 4 | Copyright (c) 2018 Rian Hunter 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #define DEFINE_WASM_I32_GLOBAL(_name, _init, _mut) \ 26 | DEFINE_WASM_GLOBAL(_name, _init, VALTYPE_I32, i32, _mut) 27 | #define DEFINE_WASM_F64_GLOBAL(_name, _init, _mut) \ 28 | DEFINE_WASM_GLOBAL(_name, _init, VALTYPE_F64, f64, _mut) 29 | 30 | #define CURRENT_MODULE global 31 | 32 | START_MODULE() 33 | 34 | START_TABLE_DEFS() 35 | END_TABLE_DEFS() 36 | 37 | START_MEMORY_DEFS() 38 | END_MEMORY_DEFS() 39 | 40 | START_GLOBAL_DEFS() 41 | DEFINE_WASM_F64_GLOBAL(NaN, NAN, 0) 42 | DEFINE_WASM_F64_GLOBAL(Infinity, INFINITY, 0) 43 | END_GLOBAL_DEFS() 44 | 45 | START_FUNCTION_DEFS() 46 | END_FUNCTION_DEFS() 47 | 48 | END_MODULE() 49 | 50 | #undef CURRENT_MODULE 51 | 52 | #define CURRENT_MODULE env 53 | 54 | START_MODULE() 55 | 56 | START_TABLE_DEFS() 57 | DEFINE_EXTERNAL_WASM_TABLE(table) 58 | END_TABLE_DEFS() 59 | 60 | START_MEMORY_DEFS() 61 | DEFINE_WASM_MEMORY(memory, 256, 256) 62 | END_MEMORY_DEFS() 63 | 64 | START_GLOBAL_DEFS() 65 | DEFINE_EXTERNAL_WASM_GLOBAL(memoryBase) 66 | DEFINE_EXTERNAL_WASM_GLOBAL(tempDoublePtr) 67 | DEFINE_EXTERNAL_WASM_GLOBAL(DYNAMICTOP_PTR) 68 | DEFINE_EXTERNAL_WASM_GLOBAL(STACKTOP) 69 | DEFINE_EXTERNAL_WASM_GLOBAL(STACK_MAX) 70 | DEFINE_WASM_I32_GLOBAL(tableBase, 0, 0) 71 | DEFINE_WASM_I32_GLOBAL(ABORT, 0, 0) 72 | END_GLOBAL_DEFS() 73 | 74 | #define DEFINE_EMSCRIPTEN_FUNCTION(_name, _output, _n, ...) \ 75 | DEFINE_WASM_FUNCTION(_name, &(wasmjit_emscripten_ ## _name), _output, _n, ##__VA_ARGS__) 76 | 77 | START_FUNCTION_DEFS() 78 | DEFINE_EMSCRIPTEN_FUNCTION(enlargeMemory, VALTYPE_I32, 0) 79 | DEFINE_EMSCRIPTEN_FUNCTION(getTotalMemory, VALTYPE_I32, 0) 80 | DEFINE_EMSCRIPTEN_FUNCTION(abortOnCannotGrowMemory, VALTYPE_I32, 0) 81 | DEFINE_EMSCRIPTEN_FUNCTION(abortStackOverflow, VALTYPE_NULL, 1, VALTYPE_I32) 82 | DEFINE_EMSCRIPTEN_FUNCTION(nullFunc_ii, VALTYPE_NULL, 1, VALTYPE_I32) 83 | DEFINE_EMSCRIPTEN_FUNCTION(nullFunc_iiii, VALTYPE_NULL, 1, VALTYPE_I32) 84 | DEFINE_EMSCRIPTEN_FUNCTION(___lock, VALTYPE_NULL, 1, VALTYPE_I32) 85 | DEFINE_EMSCRIPTEN_FUNCTION(___setErrNo, VALTYPE_NULL, 1, VALTYPE_I32) 86 | DEFINE_EMSCRIPTEN_FUNCTION(___syscall3, VALTYPE_I32, 2, VALTYPE_I32, VALTYPE_I32) 87 | DEFINE_EMSCRIPTEN_FUNCTION(___syscall42, VALTYPE_I32, 2, VALTYPE_I32, VALTYPE_I32) 88 | DEFINE_EMSCRIPTEN_FUNCTION(___syscall140, VALTYPE_I32, 2, VALTYPE_I32, VALTYPE_I32) 89 | DEFINE_EMSCRIPTEN_FUNCTION(___syscall146, VALTYPE_I32, 2, VALTYPE_I32, VALTYPE_I32) 90 | DEFINE_EMSCRIPTEN_FUNCTION(___syscall4, VALTYPE_I32, 2, VALTYPE_I32, VALTYPE_I32) 91 | DEFINE_EMSCRIPTEN_FUNCTION(___syscall54, VALTYPE_I32, 2, VALTYPE_I32, VALTYPE_I32) 92 | DEFINE_EMSCRIPTEN_FUNCTION(___syscall6, VALTYPE_I32, 2, VALTYPE_I32, VALTYPE_I32) 93 | DEFINE_EMSCRIPTEN_FUNCTION(___unlock, VALTYPE_NULL, 1, VALTYPE_I32) 94 | DEFINE_EMSCRIPTEN_FUNCTION(_emscripten_memcpy_big, VALTYPE_I32, 3, VALTYPE_I32, VALTYPE_I32, VALTYPE_I32) 95 | DEFINE_EMSCRIPTEN_FUNCTION(abort, VALTYPE_NULL, 1, VALTYPE_I32) 96 | DEFINE_EMSCRIPTEN_FUNCTION(___buildEnvironment, VALTYPE_NULL, 1, VALTYPE_I32) 97 | DEFINE_EMSCRIPTEN_FUNCTION(___syscall10, VALTYPE_I32, 2, VALTYPE_I32, VALTYPE_I32) 98 | DEFINE_EMSCRIPTEN_FUNCTION(___syscall102, VALTYPE_I32, 2, VALTYPE_I32, VALTYPE_I32) 99 | DEFINE_EMSCRIPTEN_FUNCTION(___syscall221, VALTYPE_I32, 2, VALTYPE_I32, VALTYPE_I32) 100 | DEFINE_EMSCRIPTEN_FUNCTION(___syscall12, VALTYPE_I32, 2, VALTYPE_I32, VALTYPE_I32) 101 | DEFINE_EMSCRIPTEN_FUNCTION(___syscall122, VALTYPE_I32, 2, VALTYPE_I32, VALTYPE_I32) 102 | END_FUNCTION_DEFS() 103 | 104 | DEFINE_WASM_START_FUNCTION(wasmjit_emscripten_start_func) 105 | 106 | END_MODULE() 107 | 108 | #undef DEFINE_EMSCRIPTEN_FUNCTION 109 | 110 | #undef CURRENT_MODULE 111 | 112 | #undef DEFINE_WASM_F64_GLOBAL 113 | #undef DEFINE_WASM_I32_GLOBAL 114 | -------------------------------------------------------------------------------- /src/wasmjit/emscripten_runtime_sys.h: -------------------------------------------------------------------------------- 1 | /* -*-mode:c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ 2 | 3 | /* 4 | Copyright (c) 2018 Rian Hunter 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #ifndef __WASMJIT__EMSCRIPTEN_RUNTIME_SYS_H__ 26 | #define __WASMJIT__EMSCRIPTEN_RUNTIME_SYS_H__ 27 | 28 | #ifdef __KERNEL__ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | typedef int socklen_t; 37 | typedef struct user_msghdr user_msghdr_t; 38 | 39 | #define SYS_CMSG_NXTHDR(msg, cmsg) __CMSG_NXTHDR((msg)->msg_control, (msg)->msg_controllen, (cmsg)) 40 | 41 | #else 42 | 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | 52 | #ifndef PATH_MAX 53 | #define PATH_MAX 4096 54 | #endif 55 | 56 | typedef struct msghdr user_msghdr_t; 57 | 58 | #define SYS_CMSG_NXTHDR(msg, cmsg) CMSG_NXTHDR((msg), (cmsg)) 59 | 60 | #endif 61 | 62 | #include 63 | 64 | /* declare all sys calls */ 65 | 66 | #define __KDECL(to,n,t) t _##n 67 | 68 | #ifdef __KERNEL__ 69 | 70 | #define KWSCx(_n, _name, ...) extern long (*sys_ ## _name)(__KMAP(_n, __KDECL, __VA_ARGS__)); 71 | 72 | #else 73 | 74 | #define KWSCx(_n, _name, ...) long sys_ ## _name(__KMAP(_n, __KDECL, __VA_ARGS__)); 75 | 76 | #endif 77 | 78 | #define KWSC1(name, ...) KWSCx(1, name, __VA_ARGS__) 79 | #define KWSC2(name, ...) KWSCx(2, name, __VA_ARGS__) 80 | #define KWSC3(name, ...) KWSCx(3, name, __VA_ARGS__) 81 | #define KWSC5(name, ...) KWSCx(5, name, __VA_ARGS__) 82 | #define KWSC6(name, ...) KWSCx(6, name, __VA_ARGS__) 83 | 84 | #include 85 | 86 | #undef KWSC1 87 | #undef KWSC2 88 | #undef KWSC3 89 | #undef KWSC5 90 | #undef KWSC6 91 | #undef KWSCx 92 | #undef __KDECL 93 | 94 | #endif 95 | -------------------------------------------------------------------------------- /src/wasmjit/emscripten_runtime_sys_def.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018 Rian Hunter 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | 23 | KWSC3(lseek, unsigned int, off_t, unsigned int) 24 | KWSC3(writev, unsigned long, const struct iovec *, unsigned long) 25 | KWSC3(write, unsigned int, void *, size_t) 26 | KWSC1(close, unsigned int) 27 | KWSC1(unlink, const char *) 28 | KWSC3(socket, int, int, int) 29 | KWSC3(bind, int, const struct sockaddr *, socklen_t) 30 | KWSC3(connect, int, const struct sockaddr *, socklen_t) 31 | KWSC2(listen, int, int) 32 | KWSC3(accept, int, struct sockaddr *, socklen_t *) 33 | KWSC3(getsockname, int, struct sockaddr *, socklen_t *) 34 | KWSC3(getpeername, int, struct sockaddr *, socklen_t *) 35 | KWSC6(sendto, int, const void *, size_t, int, const struct sockaddr *, socklen_t) 36 | KWSC6(recvfrom, int, void *, size_t, int, struct sockaddr *, socklen_t *) 37 | KWSC5(setsockopt, int, int, int, const void *, socklen_t) 38 | KWSC5(getsockopt, int, int, int, void *, socklen_t *) 39 | KWSC3(sendmsg, int, const user_msghdr_t *, int) 40 | KWSC3(recvmsg, int, user_msghdr_t *, int) 41 | KWSC1(chdir, const char *) 42 | KWSC3(read, int, void *, size_t) 43 | KWSC1(pipe, int *) 44 | -------------------------------------------------------------------------------- /src/wasmjit/emscripten_runtime_sys_errno_def.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018 Rian Hunter 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | 23 | #ifdef EPERM 24 | ERRNO(EPERM, 1) 25 | #endif 26 | #ifdef ENOENT 27 | ERRNO(ENOENT, 2) 28 | #endif 29 | #ifdef ESRCH 30 | ERRNO(ESRCH, 3) 31 | #endif 32 | #ifdef EINTR 33 | ERRNO(EINTR, 4) 34 | #endif 35 | #ifdef EIO 36 | ERRNO(EIO, 5) 37 | #endif 38 | #ifdef ENXIO 39 | ERRNO(ENXIO, 6) 40 | #endif 41 | #ifdef E2BIG 42 | ERRNO(E2BIG, 7) 43 | #endif 44 | #ifdef ENOEXEC 45 | ERRNO(ENOEXEC, 8) 46 | #endif 47 | #ifdef EBADF 48 | ERRNO(EBADF, 9) 49 | #endif 50 | #ifdef ECHILD 51 | ERRNO(ECHILD, 10) 52 | #endif 53 | #ifdef EAGAIN 54 | ERRNO(EAGAIN, 11) 55 | #endif 56 | #ifdef ENOMEM 57 | ERRNO(ENOMEM, 12) 58 | #endif 59 | #ifdef EACCES 60 | ERRNO(EACCES, 13) 61 | #endif 62 | #ifdef EFAULT 63 | ERRNO(EFAULT, 14) 64 | #endif 65 | #ifdef ENOTBLK 66 | ERRNO(ENOTBLK, 15) 67 | #endif 68 | #ifdef EBUSY 69 | ERRNO(EBUSY, 16) 70 | #endif 71 | #ifdef EEXIST 72 | ERRNO(EEXIST, 17) 73 | #endif 74 | #ifdef EXDEV 75 | ERRNO(EXDEV, 18) 76 | #endif 77 | #ifdef ENODEV 78 | ERRNO(ENODEV, 19) 79 | #endif 80 | #ifdef ENOTDIR 81 | ERRNO(ENOTDIR, 20) 82 | #endif 83 | #ifdef EISDIR 84 | ERRNO(EISDIR, 21) 85 | #endif 86 | #ifdef EINVAL 87 | ERRNO(EINVAL, 22) 88 | #endif 89 | #ifdef ENFILE 90 | ERRNO(ENFILE, 23) 91 | #endif 92 | #ifdef EMFILE 93 | ERRNO(EMFILE, 24) 94 | #endif 95 | #ifdef ENOTTY 96 | ERRNO(ENOTTY, 25) 97 | #endif 98 | #ifdef ETXTBSY 99 | ERRNO(ETXTBSY, 26) 100 | #endif 101 | #ifdef EFBIG 102 | ERRNO(EFBIG, 27) 103 | #endif 104 | #ifdef ENOSPC 105 | ERRNO(ENOSPC, 28) 106 | #endif 107 | #ifdef ESPIPE 108 | ERRNO(ESPIPE, 29) 109 | #endif 110 | #ifdef EROFS 111 | ERRNO(EROFS, 30) 112 | #endif 113 | #ifdef EMLINK 114 | ERRNO(EMLINK, 31) 115 | #endif 116 | #ifdef EPIPE 117 | ERRNO(EPIPE, 32) 118 | #endif 119 | #ifdef EDOM 120 | ERRNO(EDOM, 33) 121 | #endif 122 | #ifdef ERANGE 123 | ERRNO(ERANGE, 34) 124 | #endif 125 | #ifdef EDEADLK 126 | ERRNO(EDEADLK, 35) 127 | #endif 128 | #ifdef ENAMETOOLONG 129 | ERRNO(ENAMETOOLONG, 36) 130 | #endif 131 | #ifdef ENOLCK 132 | ERRNO(ENOLCK, 37) 133 | #endif 134 | #ifdef ENOSYS 135 | ERRNO(ENOSYS, 38) 136 | #endif 137 | #ifdef ENOTEMPTY 138 | ERRNO(ENOTEMPTY, 39) 139 | #endif 140 | #ifdef ELOOP 141 | ERRNO(ELOOP, 40) 142 | #endif 143 | #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN 144 | ERRNO(EWOULDBLOCK, 11) 145 | #endif 146 | #ifdef ENOMSG 147 | ERRNO(ENOMSG, 42) 148 | #endif 149 | #ifdef EIDRM 150 | ERRNO(EIDRM, 43) 151 | #endif 152 | #ifdef ECHRNG 153 | ERRNO(ECHRNG, 44) 154 | #endif 155 | #ifdef EL2NSYNC 156 | ERRNO(EL2NSYNC, 45) 157 | #endif 158 | #ifdef EL3HLT 159 | ERRNO(EL3HLT, 46) 160 | #endif 161 | #ifdef EL3RST 162 | ERRNO(EL3RST, 47) 163 | #endif 164 | #ifdef ELNRNG 165 | ERRNO(ELNRNG, 48) 166 | #endif 167 | #ifdef EUNATCH 168 | ERRNO(EUNATCH, 49) 169 | #endif 170 | #ifdef ENOCSI 171 | ERRNO(ENOCSI, 50) 172 | #endif 173 | #ifdef EL2HLT 174 | ERRNO(EL2HLT, 51) 175 | #endif 176 | #ifdef EBADE 177 | ERRNO(EBADE, 52) 178 | #endif 179 | #ifdef EBADR 180 | ERRNO(EBADR, 53) 181 | #endif 182 | #ifdef EXFULL 183 | ERRNO(EXFULL, 54) 184 | #endif 185 | #ifdef ENOANO 186 | ERRNO(ENOANO, 55) 187 | #endif 188 | #ifdef EBADRQC 189 | ERRNO(EBADRQC, 56) 190 | #endif 191 | #ifdef EBADSLT 192 | ERRNO(EBADSLT, 57) 193 | #endif 194 | #if defined(EDEADLOCK) && EDEADLOCK != EDEADLK 195 | ERRNO(EDEADLOCK, 35) 196 | #endif 197 | #ifdef EBFONT 198 | ERRNO(EBFONT, 59) 199 | #endif 200 | #ifdef ENOSTR 201 | ERRNO(ENOSTR, 60) 202 | #endif 203 | #ifdef ENODATA 204 | ERRNO(ENODATA, 61) 205 | #endif 206 | #ifdef ETIME 207 | ERRNO(ETIME, 62) 208 | #endif 209 | #ifdef ENOSR 210 | ERRNO(ENOSR, 63) 211 | #endif 212 | #ifdef ENONET 213 | ERRNO(ENONET, 64) 214 | #endif 215 | #ifdef ENOPKG 216 | ERRNO(ENOPKG, 65) 217 | #endif 218 | #ifdef EREMOTE 219 | ERRNO(EREMOTE, 66) 220 | #endif 221 | #ifdef ENOLINK 222 | ERRNO(ENOLINK, 67) 223 | #endif 224 | #ifdef EADV 225 | ERRNO(EADV, 68) 226 | #endif 227 | #ifdef ESRMNT 228 | ERRNO(ESRMNT, 69) 229 | #endif 230 | #ifdef ECOMM 231 | ERRNO(ECOMM, 70) 232 | #endif 233 | #ifdef EPROTO 234 | ERRNO(EPROTO, 71) 235 | #endif 236 | #ifdef EMULTIHOP 237 | ERRNO(EMULTIHOP, 72) 238 | #endif 239 | #ifdef EDOTDOT 240 | ERRNO(EDOTDOT, 73) 241 | #endif 242 | #ifdef EBADMSG 243 | ERRNO(EBADMSG, 74) 244 | #endif 245 | #ifdef EOVERFLOW 246 | ERRNO(EOVERFLOW, 75) 247 | #endif 248 | #ifdef ENOTUNIQ 249 | ERRNO(ENOTUNIQ, 76) 250 | #endif 251 | #ifdef EBADFD 252 | ERRNO(EBADFD, 77) 253 | #endif 254 | #ifdef EREMCHG 255 | ERRNO(EREMCHG, 78) 256 | #endif 257 | #ifdef ELIBACC 258 | ERRNO(ELIBACC, 79) 259 | #endif 260 | #ifdef ELIBBAD 261 | ERRNO(ELIBBAD, 80) 262 | #endif 263 | #ifdef ELIBSCN 264 | ERRNO(ELIBSCN, 81) 265 | #endif 266 | #ifdef ELIBMAX 267 | ERRNO(ELIBMAX, 82) 268 | #endif 269 | #ifdef ELIBEXEC 270 | ERRNO(ELIBEXEC, 83) 271 | #endif 272 | #ifdef EILSEQ 273 | ERRNO(EILSEQ, 84) 274 | #endif 275 | #ifdef ERESTART 276 | ERRNO(ERESTART, 85) 277 | #endif 278 | #ifdef ESTRPIPE 279 | ERRNO(ESTRPIPE, 86) 280 | #endif 281 | #ifdef EUSERS 282 | ERRNO(EUSERS, 87) 283 | #endif 284 | #ifdef ENOTSOCK 285 | ERRNO(ENOTSOCK, 88) 286 | #endif 287 | #ifdef EDESTADDRREQ 288 | ERRNO(EDESTADDRREQ, 89) 289 | #endif 290 | #ifdef EMSGSIZE 291 | ERRNO(EMSGSIZE, 90) 292 | #endif 293 | #ifdef EPROTOTYPE 294 | ERRNO(EPROTOTYPE, 91) 295 | #endif 296 | #ifdef ENOPROTOOPT 297 | ERRNO(ENOPROTOOPT, 92) 298 | #endif 299 | #ifdef EPROTONOSUPPORT 300 | ERRNO(EPROTONOSUPPORT, 93) 301 | #endif 302 | #ifdef ESOCKTNOSUPPORT 303 | ERRNO(ESOCKTNOSUPPORT, 94) 304 | #endif 305 | #ifdef EOPNOTSUPP 306 | ERRNO(EOPNOTSUPP, 95) 307 | #endif 308 | #ifdef EPFNOSUPPORT 309 | ERRNO(EPFNOSUPPORT, 96) 310 | #endif 311 | #ifdef EAFNOSUPPORT 312 | ERRNO(EAFNOSUPPORT, 97) 313 | #endif 314 | #ifdef EADDRINUSE 315 | ERRNO(EADDRINUSE, 98) 316 | #endif 317 | #ifdef EADDRNOTAVAIL 318 | ERRNO(EADDRNOTAVAIL, 99) 319 | #endif 320 | #ifdef ENETDOWN 321 | ERRNO(ENETDOWN, 100) 322 | #endif 323 | #ifdef ENETUNREACH 324 | ERRNO(ENETUNREACH, 101) 325 | #endif 326 | #ifdef ENETRESET 327 | ERRNO(ENETRESET, 102) 328 | #endif 329 | #ifdef ECONNABORTED 330 | ERRNO(ECONNABORTED, 103) 331 | #endif 332 | #ifdef ECONNRESET 333 | ERRNO(ECONNRESET, 104) 334 | #endif 335 | #ifdef ENOBUFS 336 | ERRNO(ENOBUFS, 105) 337 | #endif 338 | #ifdef EISCONN 339 | ERRNO(EISCONN, 106) 340 | #endif 341 | #ifdef ENOTCONN 342 | ERRNO(ENOTCONN, 107) 343 | #endif 344 | #ifdef ESHUTDOWN 345 | ERRNO(ESHUTDOWN, 108) 346 | #endif 347 | #ifdef ETOOMANYREFS 348 | ERRNO(ETOOMANYREFS, 109) 349 | #endif 350 | #ifdef ETIMEDOUT 351 | ERRNO(ETIMEDOUT, 110) 352 | #endif 353 | #ifdef ECONNREFUSED 354 | ERRNO(ECONNREFUSED, 111) 355 | #endif 356 | #ifdef EHOSTDOWN 357 | ERRNO(EHOSTDOWN, 112) 358 | #endif 359 | #ifdef EHOSTUNREACH 360 | ERRNO(EHOSTUNREACH, 113) 361 | #endif 362 | #ifdef EALREADY 363 | ERRNO(EALREADY, 114) 364 | #endif 365 | #ifdef EINPROGRESS 366 | ERRNO(EINPROGRESS, 115) 367 | #endif 368 | #ifdef ESTALE 369 | ERRNO(ESTALE, 116) 370 | #endif 371 | #ifdef EUCLEAN 372 | ERRNO(EUCLEAN, 117) 373 | #endif 374 | #ifdef ENOTNAM 375 | ERRNO(ENOTNAM, 118) 376 | #endif 377 | #ifdef ENAVAIL 378 | ERRNO(ENAVAIL, 119) 379 | #endif 380 | #ifdef EISNAM 381 | ERRNO(EISNAM, 120) 382 | #endif 383 | #ifdef EREMOTEIO 384 | ERRNO(EREMOTEIO, 121) 385 | #endif 386 | #ifdef EDQUOT 387 | ERRNO(EDQUOT, 122) 388 | #endif 389 | #ifdef ENOMEDIUM 390 | ERRNO(ENOMEDIUM, 123) 391 | #endif 392 | #ifdef EMEDIUMTYPE 393 | ERRNO(EMEDIUMTYPE, 124) 394 | #endif 395 | #ifdef ECANCELED 396 | ERRNO(ECANCELED, 125) 397 | #endif 398 | #ifdef ENOKEY 399 | ERRNO(ENOKEY, 126) 400 | #endif 401 | #ifdef EKEYEXPIRED 402 | ERRNO(EKEYEXPIRED, 127) 403 | #endif 404 | #ifdef EKEYREVOKED 405 | ERRNO(EKEYREVOKED, 128) 406 | #endif 407 | #ifdef EKEYREJECTED 408 | ERRNO(EKEYREJECTED, 129) 409 | #endif 410 | #ifdef EOWNERDEAD 411 | ERRNO(EOWNERDEAD, 130) 412 | #endif 413 | #ifdef ENOTRECOVERABLE 414 | ERRNO(ENOTRECOVERABLE, 131) 415 | #endif 416 | -------------------------------------------------------------------------------- /src/wasmjit/emscripten_runtime_sys_linux_kernel.c: -------------------------------------------------------------------------------- 1 | /* -*-mode:c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ 2 | 3 | /* 4 | Copyright (c) 2018 Rian Hunter 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #include 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #define __KT(to,n,t) t 34 | #define __KA(to,n,t) _##n 35 | #define __KDECL(to,n,t) t _##n 36 | #define __KINIT(to,n,t) . t = (unsigned long) _##n 37 | #define __KSET(to,n,t) vals-> t = (unsigned long) _##n 38 | 39 | #define KWSC1(name, ...) KWSCx(1, name, __VA_ARGS__) 40 | #define KWSC2(name, ...) KWSCx(2, name, __VA_ARGS__) 41 | #define KWSC3(name, ...) KWSCx(3, name, __VA_ARGS__) 42 | #define KWSC5(name, ...) KWSCx(5, name, __VA_ARGS__) 43 | #define KWSC6(name, ...) KWSCx(6, name, __VA_ARGS__) 44 | 45 | #define KWSCx(x, name, ...) long (*sys_ ## name)(__KMAP(x, __KT, __VA_ARGS__)); 46 | 47 | #include 48 | 49 | #undef KWSCx 50 | 51 | #ifdef __x86_64__ 52 | 53 | #define KWSCx(x, name, ...) long (*name)(struct pt_regs *); 54 | 55 | static struct { 56 | #include 57 | } sctable_regs; 58 | 59 | #undef KWSCx 60 | #define KWSCx(x, name, ...) \ 61 | long sys_ ## name ## _regs(__KMAP(x, __KDECL, __VA_ARGS__)) \ 62 | { \ 63 | struct pt_regs *vals = &wasmjit_get_ktls()->regs; \ 64 | __KMAP(x, __KSET, di, si, dx, cx, r8, r9); \ 65 | return sctable_regs. name (vals); \ 66 | } 67 | 68 | #include 69 | 70 | #undef KWSCx 71 | 72 | #define SCPREFIX "__x64_sys_" 73 | 74 | #endif 75 | 76 | __attribute__((noreturn)) 77 | void wasmjit_emscripten_internal_abort(const char *msg) 78 | { 79 | printk(KERN_NOTICE "kwasmjit abort PID %d: %s", current->pid, msg); 80 | wasmjit_trap(WASMJIT_TRAP_ABORT); 81 | } 82 | 83 | struct MemInst *wasmjit_emscripten_get_mem_inst(struct FuncInst *funcinst) 84 | { 85 | return wasmjit_get_ktls()->mem_inst; 86 | } 87 | 88 | int wasmjit_emscripten_linux_kernel_init(void) { 89 | #ifdef SCPREFIX 90 | 91 | #define KWSCx(x, n, ...) \ 92 | do { \ 93 | sys_ ## n = (void *)kallsyms_lookup_name("sys_" #n); \ 94 | if (!sys_ ## n) { \ 95 | sctable_regs. n = (void *)kallsyms_lookup_name(SCPREFIX #n); \ 96 | if (!sctable_regs. n) \ 97 | return 0; \ 98 | sys_ ## n = &sys_ ## n ## _regs; \ 99 | } \ 100 | } \ 101 | while (0); 102 | 103 | #else 104 | 105 | #define KWSCx(x, n, ...) \ 106 | do { \ 107 | sctable. n = (void *)kallsyms_lookup_name("sys_" #n); \ 108 | if (!sctable. n) \ 109 | return 0; \ 110 | } \ 111 | while (0); 112 | 113 | #endif 114 | 115 | #include 116 | 117 | return 1; 118 | } 119 | -------------------------------------------------------------------------------- /src/wasmjit/emscripten_runtime_sys_posix.c: -------------------------------------------------------------------------------- 1 | /* -*-mode:c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ 2 | 3 | /* 4 | Copyright (c) 2018 Rian Hunter 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #include 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #include 32 | 33 | #include 34 | #include 35 | 36 | #define __KDECL(to,n,t) t _##n 37 | #define __KA(to,n,t) _##n 38 | 39 | #define KWSCx(x, name, ...) \ 40 | long sys_ ## name(__KMAP(x, __KDECL, __VA_ARGS__)) \ 41 | { \ 42 | long ret; \ 43 | ret = name(__KMAP(x, __KA, __VA_ARGS__)); \ 44 | if (ret == -1) { \ 45 | ret = -errno; \ 46 | } \ 47 | return ret; \ 48 | } 49 | 50 | #define KWSC1(name, ...) KWSCx(1, name, __VA_ARGS__) 51 | #define KWSC2(name, ...) KWSCx(2, name, __VA_ARGS__) 52 | #define KWSC3(name, ...) KWSCx(3, name, __VA_ARGS__) 53 | #define KWSC5(name, ...) KWSCx(5, name, __VA_ARGS__) 54 | #define KWSC6(name, ...) KWSCx(6, name, __VA_ARGS__) 55 | 56 | #include 57 | 58 | struct MemInst *wasmjit_emscripten_get_mem_inst(struct FuncInst *funcinst) { 59 | return funcinst->module_inst->mems.elts[0]; 60 | } 61 | 62 | __attribute__((noreturn)) 63 | void wasmjit_emscripten_internal_abort(const char *msg) 64 | { 65 | fprintf(stderr, "%s\n", msg); 66 | wasmjit_trap(WASMJIT_TRAP_ABORT); 67 | } 68 | -------------------------------------------------------------------------------- /src/wasmjit/emscripten_runtime_sys_so_def.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018 Rian Hunter 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | 23 | #ifdef SO_DEBUG 24 | SO(DEBUG, 1, INT) 25 | #endif 26 | #ifdef SO_REUSEADDR 27 | SO(REUSEADDR, 2, INT) 28 | #endif 29 | #ifdef SO_TYPE 30 | SO(TYPE, 3, INT) 31 | #endif 32 | #ifdef SO_ERROR 33 | SO(ERROR, 4, INT) 34 | #endif 35 | #ifdef SO_DONTROUTE 36 | SO(DONTROUTE, 5, INT) 37 | #endif 38 | #ifdef SO_BROADCAST 39 | SO(BROADCAST, 6, INT) 40 | #endif 41 | #ifdef SO_SNDBUF 42 | SO(SNDBUF, 7, INT) 43 | #endif 44 | #ifdef SO_RCVBUF 45 | SO(RCVBUF, 8, INT) 46 | #endif 47 | #ifdef SO_SNDBUFFORCE 48 | SO(SNDBUFFORCE, 32, INT) 49 | #endif 50 | #ifdef SO_RCVBUFFORCE 51 | SO(RCVBUFFORCE, 33, INT) 52 | #endif 53 | #ifdef SO_KEEPALIVE 54 | SO(KEEPALIVE, 9, INT) 55 | #endif 56 | #ifdef SO_OOBINLINE 57 | SO(OOBINLINE, 10, INT) 58 | #endif 59 | #ifdef SO_NO_CHECK 60 | SO(NO_CHECK, 11, INT) 61 | #endif 62 | #ifdef SO_PRIORITY 63 | SO(PRIORITY, 12, INT) 64 | #endif 65 | #ifdef SO_LINGER 66 | SO(LINGER, 13, LINGER) 67 | #endif 68 | #ifdef SO_BSDCOMPAT 69 | SO(BSDCOMPAT, 14, INT) 70 | #endif 71 | #ifdef SO_REUSEPORT 72 | SO(REUSEPORT, 15, INT) 73 | #endif 74 | #ifdef SO_PASSCRED 75 | SO(PASSCRED, 16, INT) 76 | #endif 77 | #ifdef SO_PEERCRED 78 | SO(PEERCRED, 17, UCRED) 79 | #endif 80 | #ifdef SO_RCVLOWAT 81 | SO(RCVLOWAT, 18, INT) 82 | #endif 83 | #ifdef SO_SNDLOWAT 84 | SO(SNDLOWAT, 19, INT) 85 | #endif 86 | #ifdef SO_RCVTIMEO 87 | SO(RCVTIMEO, 20, TIMEVAL) 88 | #endif 89 | #ifdef SO_SNDTIMEO 90 | SO(SNDTIMEO, 21, TIMEVAL) 91 | #endif 92 | #ifdef SO_SECURITY_AUTHENTICATION 93 | SO(SECURITY_AUTHENTICATION, 22, INT) 94 | #endif 95 | #ifdef SO_SECURITY_ENCRYPTION_TRANSPORT 96 | SO(SECURITY_ENCRYPTION_TRANSPORT, 23, INT) 97 | #endif 98 | #ifdef SO_SECURITY_ENCRYPTION_NETWORK 99 | SO(SECURITY_ENCRYPTION_NETWORK, 24, INT) 100 | #endif 101 | #ifdef SO_BINDTODEVICE 102 | SO(BINDTODEVICE, 25, STRING) 103 | #endif 104 | #ifdef SO_ATTACH_FILTER 105 | SO(ATTACH_FILTER, 26, INT) 106 | #endif 107 | #ifdef SO_DETACH_FILTER 108 | SO(DETACH_FILTER, 27, INT) 109 | #endif 110 | #if defined(SO_GET_FILTER) && SO_GET_FILTER != SO_ATTACH_FILTER 111 | SO(GET_FILTER, 26, INT) 112 | #endif 113 | #ifdef SO_PEERNAME 114 | SO(PEERNAME, 28, INT) 115 | #endif 116 | #ifdef SO_TIMESTAMP 117 | SO(TIMESTAMP, 29, INT) 118 | #endif 119 | #ifdef SO_ACCEPTCONN 120 | SO(ACCEPTCONN, 30, INT) 121 | #endif 122 | #ifdef SO_PEERSEC 123 | SO(PEERSEC, 31, INT) 124 | #endif 125 | #ifdef SO_PASSSEC 126 | SO(PASSSEC, 34, INT) 127 | #endif 128 | #ifdef SO_TIMESTAMPNS 129 | SO(TIMESTAMPNS, 35, INT) 130 | #endif 131 | #ifdef SO_MARK 132 | SO(MARK, 36, INT) 133 | #endif 134 | #ifdef SO_TIMESTAMPING 135 | SO(TIMESTAMPING, 37, INT) 136 | #endif 137 | #ifdef SO_PROTOCOL 138 | SO(PROTOCOL, 38, INT) 139 | #endif 140 | #ifdef SO_DOMAIN 141 | SO(DOMAIN, 39, INT) 142 | #endif 143 | #ifdef SO_RXQ_OVFL 144 | SO(RXQ_OVFL, 40, INT) 145 | #endif 146 | #ifdef SO_WIFI_STATUS 147 | SO(WIFI_STATUS, 41, INT) 148 | #endif 149 | #ifdef SO_PEEK_OFF 150 | SO(PEEK_OFF, 42, INT) 151 | #endif 152 | #ifdef SO_NOFCS 153 | SO(NOFCS, 43, INT) 154 | #endif 155 | #ifdef SO_LOCK_FILTER 156 | SO(LOCK_FILTER, 44, INT) 157 | #endif 158 | #ifdef SO_SELECT_ERR_QUEUE 159 | SO(SELECT_ERR_QUEUE, 45, INT) 160 | #endif 161 | #ifdef SO_BUSY_POLL 162 | SO(BUSY_POLL, 46, INT) 163 | #endif 164 | #ifdef SO_MAX_PACING_RATE 165 | SO(MAX_PACING_RATE, 47, INT) 166 | #endif 167 | #ifdef SO_BPF_EXTENSIONS 168 | SO(BPF_EXTENSIONS, 48, INT) 169 | #endif 170 | #ifdef SO_INCOMING_CPU 171 | SO(INCOMING_CPU, 49, INT) 172 | #endif 173 | #ifdef SO_ATTACH_BPF 174 | SO(ATTACH_BPF, 50, INT) 175 | #endif 176 | #if defined(SO_DETACH_BPF) && SO_DETACH_BPF != SO_DETACH_FILTER 177 | SO(DETACH_BPF, 27, INT) 178 | #endif 179 | #ifdef SO_ATTACH_REUSEPORT_CBPF 180 | SO(ATTACH_REUSEPORT_CBPF, 51, INT) 181 | #endif 182 | #ifdef SO_ATTACH_REUSEPORT_EBPF 183 | SO(ATTACH_REUSEPORT_EBPF, 52, INT) 184 | #endif 185 | #ifdef SO_CNX_ADVICE 186 | SO(CNX_ADVICE, 53, INT) 187 | #endif 188 | #ifdef SO_MEMINFO 189 | SO(MEMINFO, 55, INT) 190 | #endif 191 | #ifdef SO_INCOMING_NAPI_ID 192 | SO(INCOMING_NAPI_ID, 56, INT) 193 | #endif 194 | #ifdef SO_COOKIE 195 | SO(COOKIE, 57, INT) 196 | #endif 197 | #ifdef SO_PEERGROUPS 198 | SO(PEERGROUPS, 59, INT) 199 | #endif 200 | #ifdef SO_ZEROCOPY 201 | SO(ZEROCOPY, 60, INT) 202 | #endif 203 | -------------------------------------------------------------------------------- /src/wasmjit/high_level.c: -------------------------------------------------------------------------------- 1 | /* -*-mode:c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ 2 | 3 | /* 4 | Copyright (c) 2018 Rian Hunter 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #include 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #ifdef WASMJIT_CAN_USE_DEVICE 35 | #include 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #endif 43 | 44 | static int add_named_module(struct WasmJITHigh *self, 45 | const char *module_name, 46 | struct ModuleInst *module) 47 | { 48 | int ret; 49 | char *new_module_name = NULL; 50 | struct NamedModule *new_named_modules = NULL; 51 | self->n_modules += 1; 52 | 53 | new_module_name = strdup(module_name); 54 | if (!new_module_name) 55 | goto error; 56 | 57 | new_named_modules = realloc(self->modules, 58 | self->n_modules * sizeof(self->modules[0])); 59 | if (!new_named_modules) { 60 | goto error; 61 | } 62 | 63 | new_named_modules[self->n_modules - 1].name = new_module_name; 64 | new_named_modules[self->n_modules - 1].module = module; 65 | self->modules = new_named_modules; 66 | new_module_name = NULL; 67 | new_named_modules = NULL; 68 | 69 | if (0) { 70 | error: 71 | ret = 0; 72 | } 73 | else { 74 | ret = 1; 75 | } 76 | 77 | if (new_named_modules) 78 | free(new_named_modules); 79 | 80 | if (new_module_name) 81 | free(new_module_name); 82 | 83 | return ret; 84 | } 85 | 86 | int wasmjit_high_init(struct WasmJITHigh *self) 87 | { 88 | #ifdef WASMJIT_CAN_USE_DEVICE 89 | { 90 | int fd; 91 | fd = open("/dev/wasm", O_RDWR | O_CLOEXEC); 92 | if (fd >= 0) { 93 | self->fd = fd; 94 | return 0; 95 | } 96 | } 97 | self->fd = -1; 98 | #endif 99 | 100 | self->n_modules = 0; 101 | self->modules = NULL; 102 | self->emscripten_asm_module = NULL; 103 | self->emscripten_env_module = NULL; 104 | memset(self->error_buffer, 0, sizeof(self->error_buffer)); 105 | return 0; 106 | } 107 | 108 | static int wasmjit_high_instantiate_buf(struct WasmJITHigh *self, 109 | const char *buf, size_t size, 110 | const char *module_name, uint32_t flags) 111 | { 112 | int ret; 113 | struct ParseState pstate; 114 | struct Module module; 115 | struct ModuleInst *module_inst = NULL; 116 | 117 | #ifdef WASMJIT_CAN_USE_DEVICE 118 | /* should not be using this if we are backending to kernel */ 119 | assert(self->fd < 0); 120 | #endif 121 | 122 | (void)flags; 123 | 124 | wasmjit_init_module(&module); 125 | 126 | if (!init_pstate(&pstate, buf, size)) { 127 | goto error; 128 | } 129 | 130 | if (!read_module(&pstate, &module, NULL, 0)) { 131 | goto error; 132 | } 133 | 134 | /* TODO: validate module */ 135 | 136 | module_inst = wasmjit_instantiate(&module, self->n_modules, self->modules, 137 | self->error_buffer, sizeof(self->error_buffer)); 138 | if (!module_inst) { 139 | goto error; 140 | } 141 | 142 | if (!add_named_module(self, module_name, module_inst)) { 143 | goto error; 144 | } 145 | module_inst = NULL; 146 | 147 | if (0) { 148 | error: 149 | ret = -1; 150 | } else { 151 | ret = 0; 152 | } 153 | 154 | wasmjit_free_module(&module); 155 | 156 | if (module_inst) { 157 | wasmjit_free_module_inst(module_inst); 158 | } 159 | 160 | return ret; 161 | } 162 | 163 | int wasmjit_high_instantiate(struct WasmJITHigh *self, const char *filename, const char *module_name, uint32_t flags) 164 | { 165 | int ret; 166 | size_t size; 167 | char *buf; 168 | 169 | #ifdef WASMJIT_CAN_USE_DEVICE 170 | if (self->fd >= 0) { 171 | struct kwasmjit_instantiate_args arg; 172 | arg.version = 0; 173 | arg.file_name = filename; 174 | arg.module_name = module_name; 175 | arg.flags = flags; 176 | 177 | return ioctl(self->fd, KWASMJIT_INSTANTIATE, &arg); 178 | } 179 | #endif 180 | 181 | self->error_buffer[0] = '\0'; 182 | 183 | /* TODO: do incremental reading */ 184 | 185 | buf = wasmjit_load_file(filename, &size); 186 | if (!buf) 187 | goto error; 188 | 189 | ret = wasmjit_high_instantiate_buf(self, buf, size, module_name, flags); 190 | 191 | if (0) { 192 | error: 193 | ret = -1; 194 | } 195 | 196 | if (buf) 197 | wasmjit_unload_file(buf, size); 198 | 199 | return ret; 200 | } 201 | 202 | int wasmjit_high_instantiate_emscripten_runtime(struct WasmJITHigh *self, 203 | uint32_t static_bump, 204 | size_t tablemin, 205 | size_t tablemax, 206 | uint32_t flags) 207 | { 208 | int ret, has_table; 209 | size_t n_modules, i; 210 | struct NamedModule *modules = NULL; 211 | 212 | #ifdef WASMJIT_CAN_USE_DEVICE 213 | if (self->fd >= 0) { 214 | struct kwasmjit_instantiate_emscripten_runtime_args arg; 215 | 216 | arg.version = 0; 217 | arg.static_bump = static_bump; 218 | arg.tablemin = tablemin; 219 | arg.tablemax = tablemax; 220 | arg.flags = flags; 221 | 222 | if (ioctl(self->fd, KWASMJIT_INSTANTIATE_EMSCRIPTEN_RUNTIME, &arg) < 0) 223 | goto error; 224 | 225 | goto success; 226 | } 227 | #endif 228 | 229 | self->error_buffer[0] = '\0'; 230 | 231 | has_table = !(flags & WASMJIT_HIGH_INSTANTIATE_EMSCRIPTEN_RUNTIME_FLAGS_NO_TABLE); 232 | 233 | modules = wasmjit_instantiate_emscripten_runtime(static_bump, 234 | has_table, 235 | tablemin, 236 | tablemax, 237 | &n_modules); 238 | if (!modules) { 239 | goto error; 240 | } 241 | 242 | for (i = 0; i < n_modules; ++i) { 243 | if (!add_named_module(self, modules[i].name, modules[i].module)) { 244 | goto error; 245 | } 246 | 247 | /* TODO: delegate to emscripten_runtime how to find 248 | emscripten cleanup module */ 249 | if (!strcmp(modules[i].name, "env")) { 250 | self->emscripten_env_module = modules[i].module; 251 | } 252 | 253 | modules[i].module = NULL; 254 | } 255 | 256 | #ifdef WASMJIT_CAN_USE_DEVICE 257 | success: 258 | #endif 259 | ret = 0; 260 | 261 | if (0) { 262 | error: 263 | ret = -1; 264 | } 265 | 266 | if (modules) { 267 | for (i = 0; i < n_modules; ++i) { 268 | free(modules[i].name); 269 | if (modules[i].module) 270 | wasmjit_free_module_inst(modules[i].module); 271 | } 272 | free(modules); 273 | } 274 | 275 | return ret; 276 | } 277 | 278 | int wasmjit_high_emscripten_invoke_main(struct WasmJITHigh *self, 279 | const char *module_name, 280 | int argc, char **argv, char **envp, 281 | uint32_t flags) 282 | { 283 | size_t i; 284 | struct ModuleInst *env_module_inst; 285 | struct FuncInst *main_inst, 286 | *stack_alloc_inst, 287 | *environ_constructor; 288 | struct MemInst *meminst; 289 | struct ModuleInst *module_inst; 290 | int ret; 291 | 292 | #ifdef WASMJIT_CAN_USE_DEVICE 293 | if (self->fd >= 0) { 294 | struct kwasmjit_emscripten_invoke_main_args arg; 295 | 296 | arg.version = 0; 297 | arg.module_name = module_name; 298 | arg.argc = argc; 299 | arg.argv = argv; 300 | arg.envp = envp; 301 | arg.flags = flags; 302 | 303 | return ioctl(self->fd, KWASMJIT_EMSCRIPTEN_INVOKE_MAIN, &arg); 304 | } 305 | #endif 306 | 307 | self->error_buffer[0] = '\0'; 308 | 309 | module_inst = NULL; 310 | for (i = 0; i < self->n_modules; ++i) { 311 | if (!strcmp(self->modules[i].name, module_name)) { 312 | module_inst = self->modules[i].module; 313 | } 314 | } 315 | 316 | if (!module_inst) 317 | return -1; 318 | 319 | env_module_inst = NULL; 320 | for (i = 0; i < self->n_modules; ++i) { 321 | if (!strcmp(self->modules[i].name, "env")) { 322 | env_module_inst = self->modules[i].module; 323 | break; 324 | } 325 | } 326 | 327 | if (!env_module_inst) 328 | return -1; 329 | 330 | main_inst = wasmjit_get_export(module_inst, "_main", 331 | IMPORT_DESC_TYPE_FUNC).func; 332 | if (!main_inst) 333 | return -1; 334 | 335 | stack_alloc_inst = wasmjit_get_export(module_inst, "stackAlloc", 336 | IMPORT_DESC_TYPE_FUNC).func; 337 | if (!stack_alloc_inst) 338 | return -1; 339 | 340 | meminst = wasmjit_get_export(env_module_inst, "memory", 341 | IMPORT_DESC_TYPE_MEM).mem; 342 | if (!meminst) 343 | return -1; 344 | 345 | if (self->emscripten_env_module) { 346 | assert(self->emscripten_env_module == env_module_inst); 347 | if (!self->emscripten_asm_module) { 348 | struct FuncInst 349 | *errno_location_inst, 350 | *malloc_inst, 351 | *free_inst; 352 | 353 | errno_location_inst = wasmjit_get_export(module_inst, "___errno_location", 354 | IMPORT_DESC_TYPE_FUNC).func; 355 | 356 | malloc_inst = wasmjit_get_export(module_inst, 357 | "_malloc", 358 | IMPORT_DESC_TYPE_FUNC).func; 359 | if (!malloc_inst) 360 | return -1; 361 | 362 | 363 | free_inst = wasmjit_get_export(module_inst, 364 | "_free", 365 | IMPORT_DESC_TYPE_FUNC).func; 366 | 367 | if (wasmjit_emscripten_init(wasmjit_emscripten_get_context(env_module_inst), 368 | errno_location_inst, 369 | malloc_inst, 370 | free_inst, 371 | envp)) 372 | return -1; 373 | 374 | self->emscripten_asm_module = module_inst; 375 | } 376 | 377 | if (self->emscripten_asm_module != module_inst) { 378 | ret = -1; 379 | goto error; 380 | } 381 | } 382 | 383 | environ_constructor = wasmjit_get_export(module_inst, 384 | "___emscripten_environ_constructor", 385 | IMPORT_DESC_TYPE_FUNC).func; 386 | ret = wasmjit_emscripten_build_environment(environ_constructor); 387 | if (ret) { 388 | ret = -1; 389 | goto error; 390 | } 391 | 392 | ret = wasmjit_emscripten_invoke_main(meminst, 393 | stack_alloc_inst, 394 | main_inst, 395 | argc, argv); 396 | error: 397 | return ret; 398 | } 399 | 400 | void wasmjit_high_close(struct WasmJITHigh *self) 401 | { 402 | size_t i; 403 | 404 | #ifdef WASMJIT_CAN_USE_DEVICE 405 | if (self->fd >= 0) { 406 | (void)close(self->fd); 407 | return; 408 | } 409 | #endif 410 | 411 | if (self->emscripten_env_module) 412 | wasmjit_emscripten_cleanup(self->emscripten_env_module); 413 | 414 | self->error_buffer[0] = '\0'; 415 | 416 | for (i = 0; i < self->n_modules; ++i) { 417 | free(self->modules[i].name); 418 | wasmjit_free_module_inst(self->modules[i].module); 419 | } 420 | if (self->modules) 421 | free(self->modules); 422 | 423 | } 424 | 425 | int wasmjit_high_error_message(struct WasmJITHigh *self, 426 | char *buf, size_t buf_size) 427 | { 428 | #ifdef WASMJIT_CAN_USE_DEVICE 429 | if (self->fd >= 0) { 430 | struct kwasmjit_error_message_args arg; 431 | 432 | arg.version = 0; 433 | arg.buffer = buf; 434 | arg.size = buf_size; 435 | 436 | return ioctl(self->fd, KWASMJIT_ERROR_MESSAGE, &arg); 437 | } 438 | #endif 439 | 440 | strncpy(buf, self->error_buffer, buf_size); 441 | if (buf_size > 0) 442 | buf[buf_size - 1] = '\0'; 443 | 444 | return 0; 445 | } 446 | -------------------------------------------------------------------------------- /src/wasmjit/high_level.h: -------------------------------------------------------------------------------- 1 | /* -*-mode:c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ 2 | 3 | /* 4 | Copyright (c) 2018 Rian Hunter 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #ifndef __WASMJIT__HIGH_LEVEL_H 26 | #define __WASMJIT__HIGH_LEVEL_H 27 | 28 | #include 29 | 30 | /* this interface mimics the kernel interface and thus lacks power 31 | since we can't pass in abitrary objects for import, like host functions */ 32 | 33 | #if (defined(__linux__) || defined(__APPLE__) || defined(__unix__)) && !defined(__KERNEL__) 34 | #define WASMJIT_CAN_USE_DEVICE 35 | #endif 36 | 37 | struct WasmJITHigh { 38 | #ifdef WASMJIT_CAN_USE_DEVICE 39 | int fd; 40 | #endif 41 | size_t n_modules; 42 | struct NamedModule *modules; 43 | char error_buffer[256]; 44 | struct ModuleInst *emscripten_asm_module; 45 | struct ModuleInst *emscripten_env_module; 46 | }; 47 | 48 | #define WASMJIT_HIGH_INSTANTIATE_EMSCRIPTEN_RUNTIME_FLAGS_NO_TABLE 1 49 | 50 | int wasmjit_high_init(struct WasmJITHigh *self); 51 | int wasmjit_high_instantiate(struct WasmJITHigh *self, 52 | const char *filename, 53 | const char *module_name, 54 | uint32_t flags); 55 | int wasmjit_high_instantiate_emscripten_runtime(struct WasmJITHigh *self, 56 | uint32_t static_bump, 57 | size_t tablemin, 58 | size_t tablemax, 59 | uint32_t flags); 60 | int wasmjit_high_emscripten_invoke_main(struct WasmJITHigh *self, 61 | const char *module_name, 62 | int argc, char **argv, char **envp, 63 | uint32_t flags); 64 | void wasmjit_high_close(struct WasmJITHigh *self); 65 | int wasmjit_high_error_message(struct WasmJITHigh *self, char *buf, size_t buf_size); 66 | 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /src/wasmjit/instantiate.h: -------------------------------------------------------------------------------- 1 | /* -*-mode:c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ 2 | 3 | /* 4 | Copyright (c) 2018 Rian Hunter 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #ifndef __WASMJIT__INSTANTIATE_H__ 26 | #define __WASMJIT__INSTANTIATE_H__ 27 | 28 | #include 29 | #include 30 | 31 | struct ModuleInst *wasmjit_instantiate(const struct Module *module, 32 | size_t n_imports, 33 | const struct NamedModule *imports, 34 | char *why, size_t why_size); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /src/wasmjit/ktls.h: -------------------------------------------------------------------------------- 1 | /* -*-mode:c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ 2 | 3 | /* 4 | Copyright (c) 2018 Rian Hunter 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #ifndef __KWASMJIT__KTLS_H 26 | #define __KWASMJIT__KTLS_H 27 | 28 | #ifndef __KERNEL__ 29 | #error Only for kernel 30 | #endif 31 | 32 | #include 33 | 34 | struct KernelThreadLocal { 35 | jmp_buf *jmp_buf; 36 | void *stack_top; 37 | struct pt_regs regs; 38 | struct MemInst *mem_inst; 39 | }; 40 | 41 | static inline char *ptrptr(void) { 42 | /* NB: use space below entry of kernel stack for our thread local info 43 | if task_pt_regs(current) does not point to the bottom of the stack, 44 | this will fail very badly. wasmjit_high_emscripten_invoke_main always 45 | restores the original value before returning, so while we in the system 46 | call it should be safe to reappropriate this space. 47 | */ 48 | return (char *)task_pt_regs(current) - sizeof(struct ThreadLocal *); 49 | } 50 | 51 | static inline struct KernelThreadLocal *wasmjit_get_ktls(void) 52 | { 53 | struct KernelThreadLocal *toret; 54 | memcpy(&toret, ptrptr(), sizeof(toret)); 55 | return toret; 56 | } 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /src/wasmjit/kwasmjit.h: -------------------------------------------------------------------------------- 1 | /* -*-mode:c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ 2 | 3 | /* 4 | Copyright (c) 2018 Rian Hunter 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #ifndef __KWASMJIT__KWASMJIT_H 26 | #define __KWASMJIT__KWASMJIT_H 27 | 28 | #ifdef __KERNEL__ 29 | #include 30 | #else 31 | #include 32 | #endif 33 | 34 | #if defined(__linux__) 35 | #include 36 | #elif defined(__APPLE__) 37 | #include 38 | #else 39 | #error System not supported 40 | #endif 41 | 42 | #define KWASMJIT_MAGIC 0xCC 43 | 44 | struct kwasmjit_instantiate_args { 45 | uint32_t version; 46 | const char *file_name; 47 | const char *module_name; 48 | uint32_t flags; 49 | }; 50 | 51 | #define KWASMJIT_INSTANTIATE_EMSCRIPTEN_RUNTIME_FLAGS_NO_TABLE 1 52 | 53 | struct kwasmjit_instantiate_emscripten_runtime_args { 54 | uint32_t version; 55 | uint32_t static_bump; 56 | size_t tablemin, tablemax; 57 | uint32_t flags; 58 | }; 59 | 60 | struct kwasmjit_emscripten_invoke_main_args { 61 | uint32_t version; 62 | const char *module_name; 63 | int argc; 64 | char **argv; 65 | char **envp; 66 | uint32_t flags; 67 | }; 68 | 69 | struct kwasmjit_error_message_args { 70 | uint32_t version; 71 | char *buffer; 72 | size_t size; 73 | }; 74 | 75 | #define KWASMJIT_INSTANTIATE _IOW(KWASMJIT_MAGIC, 0, struct kwasmjit_instantiate_args) 76 | #define KWASMJIT_INSTANTIATE_EMSCRIPTEN_RUNTIME _IOW(KWASMJIT_MAGIC, 1, struct kwasmjit_instantiate_emscripten_runtime_args) 77 | #define KWASMJIT_EMSCRIPTEN_INVOKE_MAIN _IOW(KWASMJIT_MAGIC, 2, struct kwasmjit_emscripten_invoke_main_args) 78 | #define KWASMJIT_ERROR_MESSAGE _IOW(KWASMJIT_MAGIC, 3, struct kwasmjit_error_message_args) 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /src/wasmjit/kwasmjit_linux.c: -------------------------------------------------------------------------------- 1 | /* -*-mode:c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ 2 | 3 | /* 4 | Copyright (c) 2018 Rian Hunter 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #include 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | 45 | MODULE_LICENSE("GPL"); 46 | MODULE_AUTHOR("Rian Hunter"); 47 | MODULE_DESCRIPTION("Executes WASM files natively."); 48 | MODULE_VERSION("0.01"); 49 | 50 | static void set_current_stack(void) 51 | { 52 | void *addr = end_of_stack(current); 53 | /* account for STACK_END_MAGIC */ 54 | #ifdef CONFIG_STACK_GROWSUP 55 | addr = (unsigned long *)addr - 1; 56 | #else 57 | addr = (unsigned long *)addr + 1; 58 | #endif 59 | wasmjit_set_stack_top(addr); 60 | } 61 | 62 | static void *kvmemdup_user(const void __user *src, size_t len, gfp_t flags) 63 | { 64 | void *p; 65 | 66 | p = kvmalloc(len, flags); 67 | if (!p) 68 | return ERR_PTR(-ENOMEM); 69 | 70 | if (copy_from_user(p, src, len)) { 71 | kvfree(p); 72 | return ERR_PTR(-EFAULT); 73 | } 74 | 75 | return p; 76 | } 77 | 78 | static char *kvstrndup_user(const char __user *s, long n, gfp_t flags) 79 | { 80 | char *p; 81 | long length; 82 | 83 | length = strnlen_user(s, n); 84 | 85 | if (!length) 86 | return ERR_PTR(-EFAULT); 87 | 88 | if (length > n) 89 | return ERR_PTR(-EINVAL); 90 | 91 | p = kvmemdup_user(s, length, flags); 92 | 93 | if (IS_ERR(p)) 94 | return p; 95 | 96 | p[length - 1] = '\0'; 97 | 98 | return p; 99 | } 100 | 101 | struct kwasmjit_private { 102 | struct WasmJITHigh high; 103 | }; 104 | 105 | static int kwasmjit_instantiate(struct kwasmjit_private *self, 106 | struct kwasmjit_instantiate_args *arg) 107 | { 108 | int retval; 109 | char *module_name = NULL; 110 | char *file_name = NULL; 111 | 112 | /* 113 | I know it's bad to read files from the kernel 114 | but our intent is to have an interface similar to execve() 115 | which does read files. 116 | */ 117 | 118 | file_name = kvstrndup_user(arg->file_name, 1024, GFP_KERNEL); 119 | if (IS_ERR(file_name)) { 120 | retval = PTR_ERR(file_name); 121 | file_name = NULL; 122 | goto error; 123 | } 124 | 125 | module_name = kvstrndup_user(arg->module_name, 1024, GFP_KERNEL); 126 | if (IS_ERR(module_name)) { 127 | retval = PTR_ERR(module_name); 128 | module_name = NULL; 129 | goto error; 130 | } 131 | 132 | set_current_stack(); 133 | if (wasmjit_high_instantiate(&self->high, file_name, module_name, arg->flags)) { 134 | retval = -EINVAL; 135 | goto error; 136 | } 137 | 138 | retval = 0; 139 | 140 | error: 141 | if (module_name) 142 | kvfree(module_name); 143 | 144 | if (file_name) 145 | kvfree(file_name); 146 | 147 | return retval; 148 | } 149 | 150 | static int kwasmjit_instantiate_emscripten_runtime(struct kwasmjit_private *self, 151 | struct kwasmjit_instantiate_emscripten_runtime_args *args) 152 | { 153 | int retval; 154 | 155 | set_current_stack(); 156 | if (wasmjit_high_instantiate_emscripten_runtime(&self->high, 157 | args->static_bump, 158 | args->tablemin, 159 | args->tablemax, args->flags)) { 160 | retval = -EINVAL; 161 | goto error; 162 | } 163 | 164 | retval = 0; 165 | 166 | error: 167 | return retval; 168 | } 169 | 170 | static void wasmjit_set_ktls(struct KernelThreadLocal *ktls) 171 | { 172 | memcpy(ptrptr(), &ktls, sizeof(ktls)); 173 | } 174 | 175 | #define PAGE_ORDER_UP(x) ((order_base_2(x) + (PAGE_SHIFT - 1)) / PAGE_SHIFT) 176 | 177 | static void *alloc_stack(size_t requested_size, size_t *resulting_size) 178 | { 179 | #if !defined(CONFIG_THREAD_INFO_IN_TASK) 180 | /* NB: if thread info is stored on the stack, we cannot change the size 181 | of the stack, otherwise the accessor functions won't work */ 182 | return NULL; 183 | #elif defined(CONFIG_VMAP_STACK) && defined(__x86_64__) 184 | /* NB: arm64's version of CONFIG_VMAP_STACK uses alignment to check 185 | for corrupted stack, but this doesn't work if stack is larger than 186 | THREAD_SIZE, which is the point here. 187 | */ 188 | size_t stack_pages; 189 | stack_pages = (requested_size >> PAGE_SHIFT) + ((requested_size & PAGE_MASK) ? 1 : 0); 190 | *resulting_size = stack_pages << PAGE_SHIFT; 191 | return __vmalloc(*resulting_size, THREADINFO_GFP, PAGE_KERNEL); 192 | #elif !defined(CONFIG_VMAP_STACK) 193 | int node = NUMA_NO_NODE; 194 | size_t size_order = PAGE_ORDER_UP(requested_size); 195 | *resulting_size = size_order << (PAGE_SHIFT * size_order); 196 | struct page *page = alloc_pages_node(node, THREADINFO_GFP, size_order); 197 | return page ? page_address(page) : NULL; 198 | #else 199 | return NULL; 200 | #endif 201 | } 202 | 203 | static void free_stack(void *ptr, size_t size) 204 | { 205 | BUG_ON(!ptr); 206 | #ifdef CONFIG_VMAP_STACK 207 | vfree(ptr); 208 | #else 209 | __free_pages(virt_to_page(ptr), PAGE_ORDER_UP(size)); 210 | #endif 211 | } 212 | 213 | #define MAX_STACK (8 * 1024 * 1024) 214 | 215 | struct InvokeMainArgs { 216 | struct WasmJITHigh *high; 217 | const char *module_name; 218 | int argc; 219 | char **argv; 220 | char **envp; 221 | uint32_t flags; 222 | }; 223 | 224 | static int handler(void *ctx) 225 | { 226 | struct InvokeMainArgs *arg = ctx; 227 | return wasmjit_high_emscripten_invoke_main(arg->high, 228 | arg->module_name, 229 | arg->argc, 230 | arg->argv, 231 | arg->envp, 232 | arg->flags); 233 | } 234 | 235 | int invoke_on_stack(void *stack, void *fptr, void *ctx); 236 | 237 | static int invoke_main_on_stack(void *stack, 238 | struct WasmJITHigh *high, 239 | const char *module_name, 240 | int argc, char **argv, char **envp, 241 | int flags) 242 | { 243 | struct InvokeMainArgs args = { 244 | .high = high, 245 | .module_name = module_name, 246 | .argc = argc, 247 | .argv = argv, 248 | .envp = envp, 249 | .flags = flags, 250 | }; 251 | #if defined(CONFIG_VMAP_STACK) && defined(__x86_64__) 252 | /* fault in vmalloc area to pgd before jumping off */ 253 | READ_ONCE(*((char *)stack - PAGE_SIZE)); 254 | #endif 255 | return invoke_on_stack(stack, &handler, &args); 256 | } 257 | 258 | static int kwasmjit_emscripten_invoke_main(struct kwasmjit_private *self, 259 | struct kwasmjit_emscripten_invoke_main_args *arg) 260 | { 261 | int retval, i; 262 | char **argv = NULL, *module_name = NULL, **envp = NULL; 263 | 264 | argv = kvzalloc(arg->argc * sizeof(char *), GFP_KERNEL); 265 | if (IS_ERR(argv)) { 266 | retval = PTR_ERR(argv); 267 | argv = NULL; 268 | goto error; 269 | } 270 | 271 | for (i = 0; i < arg->argc; ++i) { 272 | char __user *argp; 273 | get_user(argp, arg->argv + i); 274 | argv[i] = kvstrndup_user(argp, MAX_ARG_STRLEN, GFP_KERNEL); 275 | if (IS_ERR(argv[i])) { 276 | retval = PTR_ERR(argv[i]); 277 | argv[i] = NULL; 278 | goto error; 279 | } 280 | } 281 | 282 | for (i = 0; ; ++i) { 283 | char __user *env; 284 | get_user(env, arg->envp + i); 285 | if (!env) break; 286 | } 287 | 288 | envp = kvzalloc((i + 1) * sizeof(char *), GFP_KERNEL); 289 | if (IS_ERR(envp)) { 290 | retval = PTR_ERR(envp); 291 | envp = NULL; 292 | goto error; 293 | } 294 | 295 | for (i = 0; ; ++i) { 296 | char __user *env; 297 | get_user(env, arg->envp + i); 298 | if (!env) break; 299 | envp[i] = kvstrndup_user(env, MAX_ARG_STRLEN, GFP_KERNEL); 300 | if (IS_ERR(envp[i])) { 301 | retval = PTR_ERR(envp[i]); 302 | envp[i] = NULL; 303 | goto error; 304 | } 305 | } 306 | 307 | module_name = kvstrndup_user(arg->module_name, 1024, GFP_USER); 308 | if (IS_ERR(module_name)) { 309 | retval = PTR_ERR(module_name); 310 | module_name = NULL; 311 | goto error; 312 | } 313 | 314 | { 315 | mm_segment_t old_fs = get_fs(); 316 | size_t real_size; 317 | void *stack; 318 | struct mm_struct *saved_mm; 319 | 320 | /* set base address once so it's a quick load in the runtime */ 321 | { 322 | size_t i; 323 | for (i = 0; i < self->high.n_modules; ++i) { 324 | if (!strcmp("env", self->high.modules[i].name)) { 325 | struct ModuleInst *inst = self->high.modules[i].module; 326 | wasmjit_get_ktls()->mem_inst = inst->mems.elts[0]; 327 | break; 328 | } 329 | } 330 | if (i == self->high.n_modules) { 331 | retval = -EINVAL; 332 | goto error; 333 | } 334 | } 335 | 336 | stack = alloc_stack(MMAX(rlimit(RLIMIT_STACK), MAX_STACK), &real_size); 337 | if (stack) { 338 | #ifdef CONFIG_STACK_GROWSUP 339 | wasmjit_set_stack_top(stack + real_size); 340 | #else 341 | wasmjit_set_stack_top(stack); 342 | #endif 343 | } else { 344 | set_current_stack(); 345 | } 346 | 347 | /* 348 | we only handle kernel validated memory now 349 | so remove address limit 350 | */ 351 | set_fs(get_ds()); 352 | 353 | /* 354 | signal to kernel that we don't need our user mappings 355 | this makes context switching much faster 356 | */ 357 | saved_mm = current->mm; 358 | mmgrab(saved_mm); 359 | unuse_mm(saved_mm); 360 | 361 | if (stack) { 362 | void *stack2 = stack; 363 | #ifndef CONFIG_STACK_GROWSUP 364 | stack2 = (char *)stack + real_size; 365 | #endif 366 | retval = invoke_main_on_stack(stack2, 367 | &self->high, 368 | module_name, 369 | arg->argc, argv, envp, arg->flags); 370 | } else { 371 | retval = wasmjit_high_emscripten_invoke_main(&self->high, 372 | module_name, 373 | arg->argc, argv, envp, arg->flags); 374 | } 375 | 376 | /* 377 | re-acquire our user mappings before returning to user space 378 | */ 379 | use_mm(saved_mm); 380 | mmdrop(saved_mm); 381 | 382 | set_fs(old_fs); 383 | 384 | if (stack) { 385 | free_stack(stack, real_size); 386 | } 387 | } 388 | 389 | if (retval < 0) { 390 | retval = -EINVAL; 391 | } 392 | 393 | /* TODO: copy back mutations to argv? */ 394 | 395 | error: 396 | if (module_name) 397 | kvfree(module_name); 398 | 399 | if (argv) { 400 | for (i = 0; i < arg->argc; ++i) { 401 | if (argv[i]) 402 | kvfree(argv[i]); 403 | } 404 | kvfree(argv); 405 | } 406 | 407 | if (envp) { 408 | for (i = 0; envp[i]; ++i) { 409 | kvfree(envp[i]); 410 | } 411 | kvfree(envp); 412 | } 413 | 414 | 415 | return retval; 416 | } 417 | 418 | static int kwasmjit_error_message(struct kwasmjit_private *self, 419 | struct kwasmjit_error_message_args *arg) 420 | { 421 | size_t src_len = strlen(self->high.error_buffer); 422 | size_t to_copy = MMIN(src_len, arg->size - 1); 423 | if (copy_to_user(arg->buffer, self->high.error_buffer, to_copy)) 424 | return -EFAULT; 425 | if (put_user(0, &arg->buffer[to_copy])) 426 | return -EFAULT; 427 | return 0; 428 | } 429 | 430 | static int kwasmjit_open(struct inode *inode, struct file *filp) 431 | { 432 | /* allocate kwasmjit_private */ 433 | filp->private_data = kvzalloc(sizeof(struct kwasmjit_private), 434 | GFP_KERNEL); 435 | if (!filp->private_data) 436 | return -ENOMEM; 437 | 438 | if (wasmjit_high_init(&((struct kwasmjit_private *)filp->private_data)->high)) { 439 | kvfree(filp->private_data); 440 | return -EINVAL; 441 | } 442 | 443 | return 0; 444 | } 445 | 446 | static void preemptible_kernel_fpu_begin(struct fpu *dest_fpu) 447 | { 448 | preempt_disable(); 449 | __kernel_fpu_begin(); 450 | memcpy(dest_fpu, ¤t->thread.fpu, fpu_kernel_xstate_size); 451 | fpu__initialize(¤t->thread.fpu); 452 | preempt_enable(); 453 | } 454 | 455 | static void preemptible_kernel_fpu_end(struct fpu *src_fpu) 456 | { 457 | preempt_disable(); 458 | memcpy(¤t->thread.fpu, src_fpu, fpu_kernel_xstate_size); 459 | __kernel_fpu_end(); 460 | preempt_enable(); 461 | } 462 | 463 | static long kwasmjit_unlocked_ioctl(struct file *filp, 464 | unsigned int cmd, 465 | unsigned long arg) 466 | { 467 | struct fpu *fpu_preserve; 468 | long retval; 469 | void *parg = (void *) arg; 470 | struct kwasmjit_private *self = filp->private_data; 471 | int fpu_set = 0; 472 | struct KernelThreadLocal *preserve, ktls; 473 | 474 | preserve = wasmjit_get_ktls(); 475 | 476 | memset(&ktls, 0, sizeof(ktls)); 477 | wasmjit_set_ktls(&ktls); 478 | 479 | fpu_preserve = kvmalloc(fpu_kernel_xstate_size, GFP_KERNEL); 480 | if (!fpu_preserve) { 481 | retval = -ENOMEM; 482 | goto error; 483 | } 484 | 485 | preemptible_kernel_fpu_begin(fpu_preserve); 486 | fpu_set = 1; 487 | 488 | switch (cmd) { 489 | case KWASMJIT_INSTANTIATE: { 490 | struct kwasmjit_instantiate_args arg; 491 | uint32_t version; 492 | 493 | get_user(version, (uint32_t *) parg); 494 | if (version > 0) { 495 | retval = -EINVAL; 496 | goto error; 497 | } 498 | 499 | if (copy_from_user(&arg, parg, sizeof(arg))) { 500 | retval = -EFAULT; 501 | goto error; 502 | } 503 | 504 | retval = kwasmjit_instantiate(self, &arg); 505 | break; 506 | } 507 | case KWASMJIT_INSTANTIATE_EMSCRIPTEN_RUNTIME: { 508 | struct kwasmjit_instantiate_emscripten_runtime_args arg; 509 | uint32_t version; 510 | 511 | get_user(version, (uint32_t *) parg); 512 | if (version > 0) { 513 | retval = -EINVAL; 514 | goto error; 515 | } 516 | 517 | if (copy_from_user(&arg, parg, sizeof(arg))) { 518 | retval = -EFAULT; 519 | goto error; 520 | } 521 | 522 | retval = kwasmjit_instantiate_emscripten_runtime(self, &arg); 523 | break; 524 | } 525 | case KWASMJIT_EMSCRIPTEN_INVOKE_MAIN: { 526 | struct kwasmjit_emscripten_invoke_main_args arg; 527 | uint32_t version; 528 | 529 | get_user(version, (uint32_t *) parg); 530 | if (version > 0) { 531 | retval = -EINVAL; 532 | goto error; 533 | } 534 | 535 | if (copy_from_user(&arg, parg, sizeof(arg))) { 536 | retval = -EFAULT; 537 | goto error; 538 | } 539 | 540 | retval = kwasmjit_emscripten_invoke_main(self, &arg); 541 | break; 542 | } 543 | case KWASMJIT_ERROR_MESSAGE: { 544 | struct kwasmjit_error_message_args arg; 545 | uint32_t version; 546 | 547 | get_user(version, (uint32_t *) parg); 548 | if (version > 0) { 549 | retval = -EINVAL; 550 | goto error; 551 | } 552 | 553 | if (copy_from_user(&arg, parg, sizeof(arg))) { 554 | retval = -EFAULT; 555 | goto error; 556 | } 557 | 558 | retval = kwasmjit_error_message(self, &arg); 559 | break; 560 | } 561 | default: 562 | retval = -EINVAL; 563 | break; 564 | } 565 | 566 | error: 567 | if (fpu_set) 568 | preemptible_kernel_fpu_end(fpu_preserve); 569 | 570 | if (fpu_preserve) 571 | kvfree(fpu_preserve); 572 | 573 | wasmjit_set_ktls(preserve); 574 | 575 | return retval; 576 | } 577 | 578 | static int kwasmjit_release(struct inode *inode, 579 | struct file *filp) 580 | { 581 | struct kwasmjit_private *self = filp->private_data; 582 | wasmjit_high_close(&self->high); 583 | kvfree(self); 584 | return 0; 585 | } 586 | 587 | struct file_operations kwasmjit_ops = { 588 | .owner = THIS_MODULE, 589 | .open = kwasmjit_open, 590 | .unlocked_ioctl = kwasmjit_unlocked_ioctl, 591 | .release = kwasmjit_release, 592 | }; 593 | 594 | #define CLASS_NAME "wasm" 595 | #define DEVICE_NAME "wasm" 596 | static dev_t device_number = -1; 597 | static struct class *device_class = NULL; 598 | static struct device *device_handle = NULL; 599 | 600 | static void kwasmjit_cleanup_module(void) 601 | { 602 | if (device_handle) 603 | device_destroy(device_class, MKDEV(device_number, 0)); 604 | 605 | if (device_class) 606 | class_unregister(device_class); 607 | 608 | if (device_number >= 0) 609 | unregister_chrdev(device_number, DEVICE_NAME); 610 | } 611 | 612 | int wasmjit_emscripten_linux_kernel_init(void); 613 | 614 | static int __init kwasmjit_init(void) 615 | { 616 | if (!wasmjit_emscripten_linux_kernel_init()) 617 | goto error; 618 | 619 | device_number = register_chrdev(0, DEVICE_NAME, &kwasmjit_ops); 620 | if (device_number < 0) { 621 | goto error; 622 | } 623 | 624 | device_class = class_create(THIS_MODULE, CLASS_NAME); 625 | if (IS_ERR(device_class)) { 626 | device_class = NULL; 627 | goto error; 628 | } 629 | 630 | device_handle = device_create(device_class, NULL, MKDEV(device_number, 0), 631 | NULL, DEVICE_NAME); 632 | if (IS_ERR(device_handle)) { 633 | device_handle = NULL; 634 | goto error; 635 | } 636 | 637 | if (0) { 638 | error: 639 | kwasmjit_cleanup_module(); 640 | printk(KERN_DEBUG "kwasmjit failed to load.\n"); 641 | } else { 642 | printk(KERN_DEBUG "kwasmjit loaded.\n"); 643 | } 644 | 645 | return 0; 646 | } 647 | 648 | static void __exit kwasmjit_exit(void) 649 | { 650 | kwasmjit_cleanup_module(); 651 | printk(KERN_DEBUG "kwasmjit unloaded.\n"); 652 | } 653 | 654 | module_init(kwasmjit_init); 655 | module_exit(kwasmjit_exit); 656 | -------------------------------------------------------------------------------- /src/wasmjit/main.c: -------------------------------------------------------------------------------- 1 | /* -*-mode:c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ 2 | 3 | /* 4 | Copyright (c) 2018 Rian Hunter 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | 45 | #include 46 | #include 47 | #include 48 | 49 | #include 50 | 51 | #ifdef __linux__ 52 | 53 | #include 54 | 55 | #include 56 | #include 57 | 58 | static void *get_stack_top(void) 59 | { 60 | struct rlimit rlim; 61 | uintptr_t stack_bottom; 62 | FILE *stream; 63 | void *stack_top; 64 | char *pathname = NULL; 65 | 66 | if (RUNNING_ON_VALGRIND) 67 | return NULL; 68 | 69 | stream = fopen("/proc/self/maps", "r"); 70 | if (!stream) 71 | goto error; 72 | 73 | while (1) { 74 | uintptr_t start_address, end_address; 75 | char perms[4]; 76 | uint64_t offset; 77 | uint8_t dev_major, dev_minor; 78 | uint64_t inode; 79 | int ret; 80 | 81 | free(pathname); 82 | 83 | ret = fscanf(stream, 84 | "%" SCNxPTR "-%" SCNxPTR "%*[ ]%4c%*[ ]%" SCNx64 85 | "%*[ ]%" SCNx8 ":%" SCNx8 "%*[ ]%" SCNu64 86 | "%*[ ]%m[^\n]%*[\n]", 87 | &start_address, &end_address, perms, &offset, 88 | &dev_major, &dev_minor, &inode, &pathname); 89 | if (ret == 7) { 90 | /* read newline if there was no pathname */ 91 | int c; 92 | c = fgetc(stream); 93 | if (c != '\n') 94 | goto error; 95 | pathname = NULL; 96 | } else if (ret != 8) { 97 | goto error; 98 | } 99 | 100 | if (pathname && !strcmp(pathname, "[stack]")) { 101 | stack_bottom = end_address; 102 | break; 103 | } 104 | } 105 | 106 | if (getrlimit(RLIMIT_STACK, &rlim)) { 107 | goto error; 108 | } 109 | 110 | stack_top = (void *)(stack_bottom - rlim.rlim_cur); 111 | 112 | if (0) { 113 | error: 114 | stack_top = NULL; 115 | } 116 | 117 | free(pathname); 118 | 119 | if (stream) 120 | fclose(stream); 121 | 122 | return stack_top; 123 | } 124 | 125 | #else 126 | 127 | static void *get_stack_top(void) 128 | { 129 | return NULL; 130 | } 131 | 132 | #endif 133 | 134 | static int parse_module(const char *filename, struct Module *module) 135 | { 136 | char *buf = NULL; 137 | int ret, result; 138 | size_t size; 139 | struct ParseState pstate; 140 | 141 | buf = wasmjit_load_file(filename, &size); 142 | if (!buf) 143 | goto error; 144 | 145 | ret = init_pstate(&pstate, buf, size); 146 | if (!ret) 147 | goto error; 148 | 149 | ret = read_module(&pstate, module, NULL, 0); 150 | if (!ret) 151 | goto error; 152 | 153 | result = 0; 154 | 155 | if (0) { 156 | error: 157 | result = -1; 158 | } 159 | 160 | if (buf) 161 | wasmjit_unload_file(buf, size); 162 | return result; 163 | } 164 | 165 | static int dump_wasm_module(const char *filename) 166 | { 167 | uint32_t i; 168 | struct Module module; 169 | int res = -1; 170 | 171 | wasmjit_init_module(&module); 172 | 173 | if (parse_module(filename, &module)) 174 | goto error; 175 | 176 | /* the most basic validation */ 177 | if (module.code_section.n_codes != module.function_section.n_typeidxs) { 178 | fprintf(stderr, 179 | "# Functions != # Codes %" PRIu32 " != %" PRIu32 "\n", 180 | module.function_section.n_typeidxs, 181 | module.code_section.n_codes); 182 | goto error; 183 | } 184 | 185 | for (i = 0; i < module.code_section.n_codes; ++i) { 186 | uint32_t j; 187 | struct TypeSectionType *type; 188 | struct CodeSectionCode *code = 189 | &module.code_section.codes[i]; 190 | 191 | type = 192 | &module.type_section.types[module.function_section. 193 | typeidxs[i]]; 194 | 195 | printf("Code #%" PRIu32 "\n", i); 196 | 197 | printf("Locals (%" PRIu32 "):\n", code->n_locals); 198 | for (j = 0; j < code->n_locals; ++j) { 199 | printf(" %s (%" PRIu32 ")\n", 200 | wasmjit_valtype_repr(code->locals[j]. 201 | valtype), 202 | code->locals[j].count); 203 | } 204 | 205 | printf("Signature: ["); 206 | for (j = 0; j < type->n_inputs; ++j) { 207 | printf("%s,", 208 | wasmjit_valtype_repr(type-> 209 | input_types[j])); 210 | } 211 | printf("] -> ["); 212 | for (j = 0; j < FUNC_TYPE_N_OUTPUTS(type); ++j) { 213 | printf("%s,", 214 | wasmjit_valtype_repr(FUNC_TYPE_OUTPUT_IDX(type, j))); 215 | } 216 | printf("]\n"); 217 | 218 | printf("Instructions:\n"); 219 | dump_instructions(module.code_section.codes[i]. 220 | instructions, 221 | module.code_section.codes[i]. 222 | n_instructions, 1); 223 | printf("\n"); 224 | } 225 | 226 | res = 0; 227 | 228 | error: 229 | wasmjit_free_module(&module); 230 | 231 | return res; 232 | } 233 | 234 | static int get_static_bump(const char *filename, uint32_t *static_bump) 235 | { 236 | char *js_path = NULL, *filebuf = NULL, *filebuf2 = NULL; 237 | size_t fnlen, filesize; 238 | regex_t re; 239 | regmatch_t pmatch[4]; 240 | int ret, compiled = 0; 241 | long result; 242 | 243 | fnlen = strlen(filename); 244 | if (fnlen < 4) 245 | goto error; 246 | 247 | js_path = malloc(fnlen + 1); 248 | memcpy(js_path, filename, fnlen - 4); 249 | strcpy(&js_path[fnlen - 4], "js"); 250 | 251 | filebuf = wasmjit_load_file(js_path, &filesize); 252 | if (!filebuf) 253 | goto error; 254 | 255 | /* we need to null terminal the file... */ 256 | filebuf2 = malloc(filesize + 1); 257 | if (!filebuf2) 258 | goto error; 259 | 260 | memcpy(filebuf2, filebuf, filesize); 261 | filebuf2[filesize] = '\0'; 262 | 263 | ret = regcomp(&re, "(^|;|\n) *var +STATIC_BUMP *= *([0-9]+) *(;|$|\n)", REG_EXTENDED); 264 | if (ret) 265 | goto error; 266 | 267 | compiled = 1; 268 | 269 | ret = regexec(&re, filebuf2, 4, pmatch, 0); 270 | if (ret) 271 | goto error; 272 | 273 | result = strtol(filebuf2 + pmatch[2].rm_so, NULL, 10); 274 | if ((result == LONG_MIN || result == LONG_MAX) && errno == ERANGE) 275 | goto error; 276 | 277 | if (result < 0 || result > UINT32_MAX) 278 | goto error; 279 | 280 | *static_bump = result; 281 | 282 | ret = 0; 283 | 284 | if (0) { 285 | error: 286 | ret = -1; 287 | } 288 | 289 | if (compiled) 290 | regfree(&re); 291 | free(filebuf2); 292 | if (filebuf) 293 | wasmjit_unload_file(filebuf, filesize); 294 | free(js_path); 295 | 296 | return ret; 297 | } 298 | 299 | static int get_emscripten_runtime_parameters(const char *filename, 300 | uint32_t *static_bump, 301 | int *has_table, 302 | size_t *tablemin, size_t *tablemax) 303 | { 304 | size_t i; 305 | int ret; 306 | struct Module module; 307 | 308 | wasmjit_init_module(&module); 309 | 310 | if (parse_module(filename, &module)) 311 | goto error; 312 | 313 | /* find correct tablemin and tablemax */ 314 | for (i = 0; i < module.import_section.n_imports; ++i) { 315 | struct ImportSectionImport *import; 316 | import = &module.import_section.imports[i]; 317 | if (strcmp(import->module, "env") || 318 | strcmp(import->name, "table") || 319 | import->desc_type != IMPORT_DESC_TYPE_TABLE) 320 | continue; 321 | 322 | *tablemin = import->desc.tabletype.limits.min; 323 | *tablemax = import->desc.tabletype.limits.max; 324 | break; 325 | } 326 | 327 | *has_table = i != module.import_section.n_imports; 328 | 329 | ret = get_static_bump(filename, static_bump); 330 | if (ret) { 331 | fprintf(stderr, "Couldn't get static bump!\n"); 332 | goto error; 333 | } 334 | 335 | if (0) { 336 | error: 337 | ret = -1; 338 | } 339 | 340 | wasmjit_free_module(&module); 341 | 342 | return ret; 343 | } 344 | 345 | static int run_emscripten_file(const char *filename, 346 | uint32_t static_bump, 347 | int has_table, 348 | size_t tablemin, size_t tablemax, 349 | int argc, char **argv, char **envp) 350 | { 351 | struct WasmJITHigh high; 352 | int ret; 353 | void *stack_top; 354 | int high_init = 0; 355 | const char *msg; 356 | uint32_t flags = 0; 357 | 358 | stack_top = get_stack_top(); 359 | if (!stack_top) { 360 | fprintf(stderr, "warning: running without a stack limit\n"); 361 | } 362 | 363 | wasmjit_set_stack_top(stack_top); 364 | 365 | if (wasmjit_high_init(&high)) { 366 | msg = "failed to initialize"; 367 | goto error; 368 | } 369 | high_init = 1; 370 | 371 | if (!has_table) 372 | flags |= WASMJIT_HIGH_INSTANTIATE_EMSCRIPTEN_RUNTIME_FLAGS_NO_TABLE; 373 | 374 | if (wasmjit_high_instantiate_emscripten_runtime(&high, 375 | static_bump, 376 | tablemin, tablemax, flags)) { 377 | msg = "failed to instantiate emscripten runtime"; 378 | goto error; 379 | } 380 | 381 | if (wasmjit_high_instantiate(&high, filename, "asm", 0)) { 382 | msg = "failed to instantiate module"; 383 | goto error; 384 | } 385 | 386 | ret = wasmjit_high_emscripten_invoke_main(&high, "asm", 387 | argc, argv, envp, 0); 388 | 389 | if (WASMJIT_IS_TRAP_ERROR(ret)) { 390 | fprintf(stderr, "TRAP: %s\n", 391 | wasmjit_trap_reason_to_string(WASMJIT_DECODE_TRAP_ERROR(ret))); 392 | } else if (ret < 0) { 393 | msg = "failed to invoke main"; 394 | goto error; 395 | } 396 | 397 | if (0) { 398 | char error_buffer[256]; 399 | 400 | error: 401 | ret = wasmjit_high_error_message(&high, 402 | error_buffer, 403 | sizeof(error_buffer)); 404 | if (!ret) { 405 | fprintf(stderr, "%s: %s\n", 406 | msg, error_buffer); 407 | ret = -1; 408 | } 409 | } 410 | 411 | if (high_init) 412 | wasmjit_high_close(&high); 413 | 414 | return ret; 415 | } 416 | 417 | extern char **environ; 418 | int main(int argc, char *argv[]) 419 | { 420 | int ret; 421 | char *filename; 422 | int dump_module, create_relocatable, create_relocatable_helper, opt; 423 | int has_table; 424 | size_t tablemin = 0, tablemax = 0; 425 | uint32_t static_bump = 0; 426 | 427 | dump_module = 0; 428 | create_relocatable = 0; 429 | create_relocatable_helper = 0; 430 | while ((opt = getopt(argc, argv, "dop")) != -1) { 431 | switch (opt) { 432 | case 'o': 433 | create_relocatable = 1; 434 | break; 435 | case 'p': 436 | create_relocatable_helper = 1; 437 | break; 438 | case 'd': 439 | dump_module = 1; 440 | break; 441 | default: 442 | return -1; 443 | } 444 | } 445 | 446 | if (optind >= argc) { 447 | fprintf(stderr, "Need an input file\n"); 448 | return -1; 449 | } 450 | 451 | filename = argv[optind]; 452 | 453 | if (dump_module) 454 | return dump_wasm_module(filename); 455 | 456 | if (create_relocatable) { 457 | struct Module module; 458 | 459 | wasmjit_init_module(&module); 460 | 461 | if (!parse_module(filename, &module)) { 462 | void *a_out; 463 | size_t size; 464 | a_out = wasmjit_output_elf_relocatable("asm", &module, &size); 465 | ret = write(1, a_out, size); 466 | free(a_out); 467 | ret = ret >= 0 ? 0 : -1; 468 | } else { 469 | ret = -1; 470 | } 471 | 472 | wasmjit_free_module(&module); 473 | 474 | return ret; 475 | } 476 | 477 | ret = get_emscripten_runtime_parameters(filename, &static_bump, &has_table, &tablemin, &tablemax); 478 | if (ret) 479 | return -1; 480 | 481 | if (create_relocatable_helper) { 482 | struct WasmJITEmscriptenMemoryGlobals globals; 483 | 484 | wasmjit_emscripten_derive_memory_globals(static_bump, &globals); 485 | 486 | printf("#include \n"); 487 | printf("#define CURRENT_MODULE env\n"); 488 | 489 | if (has_table) { 490 | printf("DEFINE_WASM_TABLE(table, ELEMTYPE_ANYFUNC, %zu, %zu)\n", 491 | tablemin, tablemax); 492 | } 493 | 494 | printf("DEFINE_WASM_GLOBAL(memoryBase, %" PRIu32 ", VALTYPE_I32, i32, 0)\n", 495 | globals.memoryBase); 496 | printf("DEFINE_WASM_GLOBAL(tempDoublePtr, %" PRIu32 ", VALTYPE_I32, i32, 0)\n", 497 | globals.tempDoublePtr); 498 | printf("DEFINE_WASM_GLOBAL(DYNAMICTOP_PTR, %" PRIu32 ", VALTYPE_I32, i32, 0)\n", 499 | globals.DYNAMICTOP_PTR); 500 | printf("DEFINE_WASM_GLOBAL(STACKTOP, %" PRIu32 ", VALTYPE_I32, i32, 0)\n", 501 | globals.STACKTOP); 502 | printf("DEFINE_WASM_GLOBAL(STACK_MAX, %" PRIu32 ", VALTYPE_I32, i32, 0)\n", 503 | globals.STACK_MAX); 504 | 505 | return 0; 506 | } 507 | 508 | return run_emscripten_file(filename, 509 | static_bump, has_table, tablemin, tablemax, 510 | argc - optind, &argv[optind], environ); 511 | } 512 | -------------------------------------------------------------------------------- /src/wasmjit/parse.h: -------------------------------------------------------------------------------- 1 | /* -*-mode:c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ 2 | 3 | /* 4 | Copyright (c) 2018 Rian Hunter 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #ifndef __WASMJIT__PARSE_H__ 26 | #define __WASMJIT__PARSE_H__ 27 | 28 | #include 29 | 30 | #include 31 | 32 | struct ParseState { 33 | int eof; 34 | const char *input; 35 | size_t amt_left; 36 | }; 37 | 38 | int read_module(struct ParseState *pstate, struct Module *module, 39 | char *why, size_t why_size); 40 | 41 | int init_pstate(struct ParseState *pstate, const char *buf, size_t size); 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /src/wasmjit/runtime.c: -------------------------------------------------------------------------------- 1 | /* -*-mode:c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ 2 | 3 | /* 4 | Copyright (c) 2018 Rian Hunter 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #include 26 | 27 | #include 28 | #include 29 | 30 | #include 31 | 32 | DEFINE_VECTOR_GROW(func_types, struct FuncTypeVector); 33 | 34 | 35 | /* end platform specific */ 36 | 37 | union ExportPtr wasmjit_get_export(const struct ModuleInst *module_inst, 38 | const char *name, 39 | wasmjit_desc_t type) { 40 | size_t i; 41 | union ExportPtr ret; 42 | 43 | for (i = 0; i < module_inst->exports.n_elts; ++i) { 44 | if (strcmp(module_inst->exports.elts[i].name, name)) 45 | continue; 46 | 47 | if (module_inst->exports.elts[i].type != type) 48 | break; 49 | 50 | return module_inst->exports.elts[i].value; 51 | } 52 | 53 | switch (type) { 54 | case IMPORT_DESC_TYPE_FUNC: 55 | ret.func = NULL; 56 | break; 57 | case IMPORT_DESC_TYPE_TABLE: 58 | ret.table = NULL; 59 | break; 60 | case IMPORT_DESC_TYPE_MEM: 61 | ret.mem = NULL; 62 | break; 63 | case IMPORT_DESC_TYPE_GLOBAL: 64 | ret.global = NULL; 65 | break; 66 | } 67 | 68 | return ret; 69 | } 70 | 71 | void wasmjit_free_func_inst(struct FuncInst *funcinst) 72 | { 73 | if (funcinst->invoker) 74 | wasmjit_unmap_code_segment(funcinst->invoker, 75 | funcinst->invoker_size); 76 | if (funcinst->compiled_code) 77 | wasmjit_unmap_code_segment(funcinst->compiled_code, 78 | funcinst->compiled_code_size); 79 | free(funcinst); 80 | } 81 | 82 | void wasmjit_free_module_inst(struct ModuleInst *module) 83 | { 84 | size_t i; 85 | if (module->free_private_data) 86 | module->free_private_data(module->private_data); 87 | free(module->types.elts); 88 | for (i = module->n_imported_funcs; i < module->funcs.n_elts; ++i) { 89 | wasmjit_free_func_inst(module->funcs.elts[i]); 90 | } 91 | free(module->funcs.elts); 92 | for (i = module->n_imported_tables; i < module->tables.n_elts; ++i) { 93 | free(module->tables.elts[i]->data); 94 | free(module->tables.elts[i]); 95 | } 96 | free(module->tables.elts); 97 | for (i = module->n_imported_mems; i < module->mems.n_elts; ++i) { 98 | free(module->mems.elts[i]->data); 99 | free(module->mems.elts[i]); 100 | } 101 | free(module->mems.elts); 102 | for (i = module->n_imported_globals; i < module->globals.n_elts; ++i) { 103 | free(module->globals.elts[i]); 104 | } 105 | free(module->globals.elts); 106 | for (i = 0; i < module->exports.n_elts; ++i) { 107 | if (module->exports.elts[i].name) 108 | free(module->exports.elts[i].name); 109 | } 110 | free(module->exports.elts); 111 | free(module); 112 | } 113 | 114 | int wasmjit_typecheck_func(const struct FuncType *type, 115 | const struct FuncInst *funcinst) 116 | { 117 | return wasmjit_typelist_equal(type->n_inputs, type->input_types, 118 | funcinst->type.n_inputs, 119 | funcinst->type.input_types) && 120 | wasmjit_typelist_equal(FUNC_TYPE_N_OUTPUTS(type), 121 | FUNC_TYPE_OUTPUT_TYPES(type), 122 | FUNC_TYPE_N_OUTPUTS(&funcinst->type), 123 | FUNC_TYPE_OUTPUT_TYPES(&funcinst->type)); 124 | } 125 | 126 | int wasmjit_typecheck_table(const struct TableType *type, 127 | const struct TableInst *tableinst) 128 | { 129 | return (tableinst->elemtype == type->elemtype && 130 | tableinst->length >= type->limits.min && 131 | (!type->limits.max || 132 | (type->limits.max && tableinst->max && 133 | tableinst->max <= type->limits.max))); 134 | } 135 | 136 | int wasmjit_typecheck_memory(const struct MemoryType *type, 137 | const struct MemInst *meminst) 138 | { 139 | size_t msize = meminst->size / WASM_PAGE_SIZE; 140 | size_t mmax = meminst->max / WASM_PAGE_SIZE; 141 | return (msize >= type->limits.min && 142 | (!type->limits.max || 143 | (type->limits.max && mmax && 144 | mmax <= type->limits.max))); 145 | } 146 | 147 | int wasmjit_typecheck_global(const struct GlobalType *globaltype, 148 | const struct GlobalInst *globalinst) 149 | { 150 | return globalinst->value.type == globaltype->valtype && 151 | globalinst->mut == globaltype->mut; 152 | } 153 | 154 | void _wasmjit_create_func_type(struct FuncType *ft, 155 | size_t n_inputs, 156 | wasmjit_valtype_t *input_types, 157 | size_t n_outputs, 158 | wasmjit_valtype_t *output_types) 159 | { 160 | assert(n_outputs <= 1); 161 | assert(n_inputs <= sizeof(ft->input_types) / sizeof(ft->input_types[0])); 162 | memset(ft, 0, sizeof(*ft)); 163 | 164 | ft->n_inputs = n_inputs; 165 | memcpy(ft->input_types, input_types, sizeof(input_types[0]) * n_inputs); 166 | 167 | if (n_outputs) { 168 | ft->output_type = output_types[0]; 169 | } else { 170 | ft->output_type = VALTYPE_NULL; 171 | } 172 | } 173 | 174 | struct FuncInst *wasmjit_resolve_indirect_call(const struct TableInst *tableinst, 175 | const struct FuncType *expected_type, 176 | uint32_t idx) 177 | { 178 | struct FuncInst *funcinst; 179 | 180 | if (idx >= tableinst->length) 181 | wasmjit_trap(WASMJIT_TRAP_TABLE_OVERFLOW); 182 | 183 | funcinst = tableinst->data[idx]; 184 | if (!funcinst) 185 | wasmjit_trap(WASMJIT_TRAP_UNINITIALIZED_TABLE_ENTRY); 186 | 187 | if (!wasmjit_typecheck_func(expected_type, funcinst)) 188 | wasmjit_trap(WASMJIT_TRAP_MISMATCHED_TYPE); 189 | 190 | return funcinst; 191 | } 192 | 193 | union ValueUnion wasmjit_invoke_function_raw(struct FuncInst *funcinst, 194 | union ValueUnion *values) 195 | { 196 | #ifndef __x86_64__ 197 | #error Only works on x86_64 198 | #endif 199 | return funcinst->invoker(values); 200 | } 201 | -------------------------------------------------------------------------------- /src/wasmjit/runtime.h: -------------------------------------------------------------------------------- 1 | /* -*-mode:c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ 2 | 3 | /* 4 | Copyright (c) 2018 Rian Hunter 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #ifndef __WASMJIT__RUNTIME_H__ 26 | #define __WASMJIT__RUNTIME_H__ 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | struct Value { 33 | wasmjit_valtype_t type; 34 | union ValueUnion { 35 | uint32_t i32; 36 | uint64_t i64; 37 | float f32; 38 | double f64; 39 | struct {} null; 40 | } data; 41 | }; 42 | 43 | struct FuncInst { 44 | struct ModuleInst *module_inst; 45 | /* 46 | the function signature of compiled_code 47 | pointers mirrors that of the WASM input 48 | types. 49 | */ 50 | void *compiled_code; 51 | size_t compiled_code_size; 52 | union ValueUnion (*invoker)(union ValueUnion *); 53 | size_t invoker_size; 54 | size_t stack_usage; 55 | struct FuncType type; 56 | }; 57 | 58 | struct TableInst { 59 | struct FuncInst **data; 60 | unsigned elemtype; 61 | size_t length; 62 | size_t max; 63 | }; 64 | 65 | struct MemInst { 66 | char *data; 67 | size_t size; 68 | size_t max; /* max of 0 means no max */ 69 | }; 70 | 71 | struct GlobalInst { 72 | struct Value value; 73 | unsigned mut; 74 | }; 75 | 76 | struct Export { 77 | char *name; 78 | wasmjit_desc_t type; 79 | union ExportPtr { 80 | struct FuncInst *func; 81 | struct TableInst *table; 82 | struct MemInst *mem; 83 | struct GlobalInst *global; 84 | } value; 85 | }; 86 | 87 | struct ModuleInst { 88 | struct FuncTypeVector { 89 | size_t n_elts; 90 | struct FuncType *elts; 91 | } types; 92 | DEFINE_ANON_VECTOR(struct FuncInst *) funcs; 93 | DEFINE_ANON_VECTOR(struct TableInst *) tables; 94 | DEFINE_ANON_VECTOR(struct MemInst *) mems; 95 | DEFINE_ANON_VECTOR(struct GlobalInst *) globals; 96 | DEFINE_ANON_VECTOR(struct Export) exports; 97 | size_t n_imported_funcs, n_imported_tables, 98 | n_imported_mems, n_imported_globals; 99 | void *private_data; 100 | void (*free_private_data)(void *); 101 | }; 102 | 103 | DECLARE_VECTOR_GROW(func_types, struct FuncTypeVector); 104 | 105 | struct NamedModule { 106 | char *name; 107 | struct ModuleInst *module; 108 | }; 109 | 110 | #define IS_HOST(funcinst) ((funcinst)->host_function) 111 | 112 | #define WASM_PAGE_SIZE ((size_t) (64 * 1024)) 113 | 114 | void _wasmjit_create_func_type(struct FuncType *ft, 115 | size_t n_inputs, 116 | wasmjit_valtype_t *input_types, 117 | size_t n_outputs, wasmjit_valtype_t *output_types); 118 | 119 | int wasmjit_typecheck_func(const struct FuncType *expected_type, 120 | const struct FuncInst *func); 121 | 122 | int wasmjit_typecheck_table(const struct TableType *expected_type, 123 | const struct TableInst *table); 124 | 125 | int wasmjit_typecheck_memory(const struct MemoryType *expected_type, 126 | const struct MemInst *mem); 127 | 128 | int wasmjit_typecheck_global(const struct GlobalType *expected_type, 129 | const struct GlobalInst *mem); 130 | 131 | __attribute__ ((unused)) 132 | static int wasmjit_typelist_equal(size_t nelts, const wasmjit_valtype_t *elts, 133 | size_t onelts, const wasmjit_valtype_t *oelts) 134 | { 135 | size_t i; 136 | if (nelts != onelts) return 0; 137 | for (i = 0; i < nelts; ++i) { 138 | if (elts[i] != oelts[i]) return 0; 139 | } 140 | return 1; 141 | } 142 | 143 | enum { 144 | WASMJIT_TRAP_UNREACHABLE = 1, 145 | WASMJIT_TRAP_TABLE_OVERFLOW, 146 | WASMJIT_TRAP_UNINITIALIZED_TABLE_ENTRY, 147 | WASMJIT_TRAP_MISMATCHED_TYPE, 148 | WASMJIT_TRAP_MEMORY_OVERFLOW, 149 | WASMJIT_TRAP_ABORT, 150 | WASMJIT_TRAP_STACK_OVERFLOW, 151 | WASMJIT_TRAP_INTEGER_OVERFLOW, 152 | }; 153 | 154 | __attribute__ ((unused)) 155 | static const char *wasmjit_trap_reason_to_string(int reason) { 156 | const char *msg; 157 | switch (reason) { 158 | case WASMJIT_TRAP_UNREACHABLE: 159 | msg = "unreachable instruction hit"; 160 | break; 161 | case WASMJIT_TRAP_TABLE_OVERFLOW: 162 | msg = "table overflow"; 163 | break; 164 | case WASMJIT_TRAP_UNINITIALIZED_TABLE_ENTRY: 165 | msg = "uninitialized table entry"; 166 | break; 167 | case WASMJIT_TRAP_MISMATCHED_TYPE: 168 | msg = "mismatched type"; 169 | break; 170 | case WASMJIT_TRAP_MEMORY_OVERFLOW: 171 | msg = "memory overflow"; 172 | break; 173 | case WASMJIT_TRAP_STACK_OVERFLOW: 174 | msg = "stack overflow"; 175 | break; 176 | default: 177 | assert(0); 178 | __builtin_unreachable(); 179 | } 180 | return msg; 181 | } 182 | 183 | struct FuncInst *wasmjit_resolve_indirect_call(const struct TableInst *tableinst, 184 | const struct FuncType *expected_type, 185 | uint32_t idx); 186 | void wasmjit_trap(int reason) __attribute__((noreturn)); 187 | void *wasmjit_stack_top(void); 188 | 189 | void wasmjit_free_func_inst(struct FuncInst *funcinst); 190 | void wasmjit_free_module_inst(struct ModuleInst *module); 191 | 192 | void *wasmjit_map_code_segment(size_t code_size); 193 | int wasmjit_mark_code_segment_executable(void *code, size_t code_size); 194 | int wasmjit_unmap_code_segment(void *code, size_t code_size); 195 | 196 | int wasmjit_set_stack_top(void *stack_top); 197 | int wasmjit_set_jmp_buf(jmp_buf *jmpbuf); 198 | jmp_buf *wasmjit_get_jmp_buf(void); 199 | 200 | union ExportPtr wasmjit_get_export(const struct ModuleInst *, const char *name, wasmjit_desc_t type); 201 | 202 | union ValueUnion wasmjit_invoke_function_raw(struct FuncInst *funcinst, 203 | union ValueUnion *values); 204 | 205 | int wasmjit_invoke_function(struct FuncInst *funcinst, 206 | union ValueUnion *values, 207 | union ValueUnion *out); 208 | 209 | #endif 210 | -------------------------------------------------------------------------------- /src/wasmjit/static_emscripten_runtime.c: -------------------------------------------------------------------------------- 1 | /* -*-mode:c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ 2 | 3 | /* 4 | Copyright (c) 2018 Rian Hunter 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | #include 30 | 31 | #include 32 | 33 | #define START_MODULE() \ 34 | struct StaticModuleInst WASM_MODULE_SYMBOL(CURRENT_MODULE); 35 | 36 | #define DEFINE_WASM_START_FUNCTION(fptr) \ 37 | DEFINE_WASM_FUNCTION_ADVANCED(static, __start_func__, wasmjit_emscripten_start_func, VALTYPE_NULL, 0) 38 | 39 | #define END_MODULE() 40 | #define START_TABLE_DEFS() 41 | #define END_TABLE_DEFS() 42 | #define START_MEMORY_DEFS() 43 | #define END_MEMORY_DEFS() 44 | #define START_GLOBAL_DEFS() 45 | #define END_GLOBAL_DEFS() 46 | #define START_FUNCTION_DEFS() 47 | #define END_FUNCTION_DEFS() 48 | #define DEFINE_EXTERNAL_WASM_TABLE(name) \ 49 | extern struct TableInst WASM_TABLE_SYMBOL(CURRENT_MODULE, name); 50 | #define DEFINE_EXTERNAL_WASM_GLOBAL(name) \ 51 | extern struct GlobalInst WASM_GLOBAL_SYMBOL(CURRENT_MODULE, name); 52 | 53 | #include 54 | 55 | #undef START_MODULE 56 | #undef END_MODULE 57 | #undef DEFINE_WASM_GLOBAL 58 | #undef DEFINE_WASM_FUNCTION 59 | #undef DEFINE_WASM_TABLE 60 | #undef DEFINE_WASM_MEMORY 61 | #undef START_TABLE_DEFS 62 | #undef END_TABLE_DEFS 63 | #undef START_MEMORY_DEFS 64 | #undef END_MEMORY_DEFS 65 | #undef START_GLOBAL_DEFS 66 | #undef END_GLOBAL_DEFS 67 | #undef START_FUNCTION_DEFS 68 | #undef END_FUNCTION_DEFS 69 | #undef DEFINE_WASM_START_FUNCTION 70 | #undef DEFINE_EXTERNAL_WASM_TABLE 71 | #undef DEFINE_EXTERNAL_WASM_GLOBAL 72 | 73 | #define DEFINE_WASM_START_FUNCTION(...) 74 | #define START_MODULE() 75 | 76 | #define START_TABLE_DEFS(n) \ 77 | static struct TableInst *CAT(CURRENT_MODULE, _tables)[] = { 78 | #define DEFINE_WASM_TABLE(_name, ...) \ 79 | &WASM_TABLE_SYMBOL(CURRENT_MODULE, _name), 80 | #define DEFINE_EXTERNAL_WASM_TABLE(_name) \ 81 | &WASM_TABLE_SYMBOL(CURRENT_MODULE, _name), 82 | #define END_TABLE_DEFS() \ 83 | }; 84 | 85 | #define START_MEMORY_DEFS(n) \ 86 | static struct MemInst *CAT(CURRENT_MODULE, _mems)[] = { 87 | #define DEFINE_WASM_MEMORY(_name, ...) \ 88 | &WASM_MEMORY_SYMBOL(CURRENT_MODULE, _name), 89 | #define END_MEMORY_DEFS() \ 90 | }; 91 | 92 | #define START_GLOBAL_DEFS(n) \ 93 | static struct GlobalInst *CAT(CURRENT_MODULE, _globals)[] = { 94 | #define DEFINE_WASM_GLOBAL(_name, ...) \ 95 | &WASM_GLOBAL_SYMBOL(CURRENT_MODULE, _name), 96 | #define DEFINE_EXTERNAL_WASM_GLOBAL(_name) \ 97 | &WASM_GLOBAL_SYMBOL(CURRENT_MODULE, _name), 98 | #define END_GLOBAL_DEFS() \ 99 | }; 100 | 101 | #define START_FUNCTION_DEFS(n) \ 102 | static struct FuncInst *CAT(CURRENT_MODULE, _funcs)[] = { 103 | #define DEFINE_WASM_FUNCTION(_name, ...) \ 104 | &WASM_FUNC_SYMBOL(CURRENT_MODULE, _name), 105 | #define END_FUNCTION_DEFS() \ 106 | }; 107 | 108 | struct EmscriptenContext g_emscripten_ctx; 109 | 110 | #define END_MODULE() 111 | 112 | #include 113 | 114 | #undef START_MODULE 115 | #undef END_MODULE 116 | #undef DEFINE_WASM_GLOBAL 117 | #undef DEFINE_WASM_FUNCTION 118 | #undef DEFINE_WASM_TABLE 119 | #undef DEFINE_WASM_MEMORY 120 | #undef START_TABLE_DEFS 121 | #undef END_TABLE_DEFS 122 | #undef START_MEMORY_DEFS 123 | #undef END_MEMORY_DEFS 124 | #undef START_GLOBAL_DEFS 125 | #undef END_GLOBAL_DEFS 126 | #undef START_FUNCTION_DEFS 127 | #undef END_FUNCTION_DEFS 128 | #undef DEFINE_WASM_START_FUNCTION 129 | #undef DEFINE_EXTERNAL_WASM_TABLE 130 | #undef DEFINE_EXTERNAL_WASM_GLOBAL 131 | 132 | /* create exports */ 133 | 134 | #define DEFINE_WASM_START_FUNCTION(...) 135 | #define START_FUNCTION_DEFS(...) 136 | #define END_FUNCTION_DEFS(...) 137 | #define START_TABLE_DEFS(...) 138 | #define END_TABLE_DEFS(...) 139 | #define START_MEMORY_DEFS(...) 140 | #define END_MEMORY_DEFS(...) 141 | #define START_GLOBAL_DEFS(...) 142 | #define END_GLOBAL_DEFS(...) 143 | 144 | #define START_MODULE() \ 145 | static struct Export CAT(CURRENT_MODULE, _exports)[] = { 146 | #define DEFINE_WASM_FUNCTION(_name, ...) \ 147 | { \ 148 | .name = #_name, \ 149 | .type = IMPORT_DESC_TYPE_FUNC, \ 150 | .value = { \ 151 | .func = &WASM_FUNC_SYMBOL(CURRENT_MODULE, _name), \ 152 | } \ 153 | }, 154 | #define DEFINE_WASM_TABLE(_name, ...) \ 155 | { \ 156 | .name = #_name, \ 157 | .type = IMPORT_DESC_TYPE_TABLE, \ 158 | .value = { \ 159 | .table = &WASM_TABLE_SYMBOL(CURRENT_MODULE, _name), \ 160 | } \ 161 | }, 162 | #define DEFINE_EXTERNAL_WASM_TABLE(_name) DEFINE_WASM_TABLE(_name) 163 | #define DEFINE_WASM_MEMORY(_name, ...) \ 164 | { \ 165 | .name = #_name, \ 166 | .type = IMPORT_DESC_TYPE_MEM, \ 167 | .value = { \ 168 | .mem = &WASM_MEMORY_SYMBOL(CURRENT_MODULE, _name), \ 169 | } \ 170 | }, 171 | #define DEFINE_WASM_GLOBAL(_name, ...) \ 172 | { \ 173 | .name = #_name, \ 174 | .type = IMPORT_DESC_TYPE_GLOBAL, \ 175 | .value = { \ 176 | .global = &WASM_GLOBAL_SYMBOL(CURRENT_MODULE, _name), \ 177 | } \ 178 | }, 179 | #define DEFINE_EXTERNAL_WASM_GLOBAL(_name) DEFINE_WASM_GLOBAL(_name) 180 | #define END_MODULE() \ 181 | }; 182 | 183 | #include 184 | 185 | #undef START_MODULE 186 | #undef END_MODULE 187 | #undef DEFINE_WASM_GLOBAL 188 | #undef DEFINE_WASM_FUNCTION 189 | #undef DEFINE_WASM_TABLE 190 | #undef DEFINE_WASM_MEMORY 191 | #undef START_TABLE_DEFS 192 | #undef END_TABLE_DEFS 193 | #undef START_MEMORY_DEFS 194 | #undef END_MEMORY_DEFS 195 | #undef START_GLOBAL_DEFS 196 | #undef END_GLOBAL_DEFS 197 | #undef START_FUNCTION_DEFS 198 | #undef END_FUNCTION_DEFS 199 | #undef DEFINE_WASM_START_FUNCTION 200 | #undef DEFINE_EXTERNAL_WASM_TABLE 201 | #undef DEFINE_EXTERNAL_WASM_GLOBAL 202 | 203 | /* create module */ 204 | 205 | #define START_FUNCTION_DEFS() 206 | #define END_FUNCTION_DEFS() 207 | #define START_TABLE_DEFS() 208 | #define END_TABLE_DEFS() 209 | #define START_MEMORY_DEFS() 210 | #define END_MEMORY_DEFS() 211 | #define START_GLOBAL_DEFS() 212 | #define END_GLOBAL_DEFS() 213 | #define DEFINE_WASM_GLOBAL(...) 214 | #define DEFINE_WASM_FUNCTION(...) 215 | #define DEFINE_WASM_TABLE(...) 216 | #define DEFINE_WASM_MEMORY(...) 217 | #define DEFINE_EXTERNAL_WASM_GLOBAL(...) 218 | #define DEFINE_EXTERNAL_WASM_TABLE(...) 219 | 220 | #define START_MODULE() \ 221 | struct StaticModuleInst WASM_MODULE_SYMBOL(CURRENT_MODULE) = { \ 222 | .module = { \ 223 | .funcs = { \ 224 | .n_elts = ARRAY_LEN(CAT(CURRENT_MODULE, _funcs)), \ 225 | .elts = CAT(CURRENT_MODULE, _funcs), \ 226 | }, \ 227 | .tables = { \ 228 | .n_elts = ARRAY_LEN(CAT(CURRENT_MODULE, _tables)), \ 229 | .elts = CAT(CURRENT_MODULE, _tables), \ 230 | }, \ 231 | .mems = { \ 232 | .n_elts = ARRAY_LEN(CAT(CURRENT_MODULE, _mems)), \ 233 | .elts = CAT(CURRENT_MODULE, _mems), \ 234 | }, \ 235 | .globals = { \ 236 | .n_elts = ARRAY_LEN(CAT(CURRENT_MODULE, _globals)), \ 237 | .elts = CAT(CURRENT_MODULE, _globals), \ 238 | }, \ 239 | .exports = { \ 240 | .n_elts = ARRAY_LEN(CAT(CURRENT_MODULE, _exports)),\ 241 | .elts = CAT(CURRENT_MODULE, _exports), \ 242 | }, \ 243 | .private_data = &g_emscripten_ctx, \ 244 | }, 245 | 246 | #define DEFINE_WASM_START_FUNCTION(...) \ 247 | .start_func = &WASM_FUNC_SYMBOL(CURRENT_MODULE, __start_func__), \ 248 | 249 | #define END_MODULE() }; 250 | 251 | #include 252 | 253 | extern struct FuncInst WASM_FUNC_SYMBOL(asm, _main); 254 | extern struct FuncInst WASM_FUNC_SYMBOL(asm, stackAlloc); 255 | extern struct FuncInst WASM_FUNC_SYMBOL(asm, ___errno_location) __attribute__((weak)); 256 | extern struct FuncInst WASM_FUNC_SYMBOL(asm, ___emscripten_environ_constructor) __attribute__((weak)); 257 | extern struct FuncInst WASM_FUNC_SYMBOL(asm, _malloc); 258 | extern struct FuncInst WASM_FUNC_SYMBOL(asm, _free); 259 | 260 | __attribute__((constructor)) 261 | static void init_module(void) 262 | { 263 | wasmjit_init_static_module(&WASM_MODULE_SYMBOL(env)); 264 | } 265 | 266 | extern char **environ; 267 | int main(int argc, char *argv[]) { 268 | int ret; 269 | ret = wasmjit_emscripten_init(&g_emscripten_ctx, 270 | &WASM_FUNC_SYMBOL(asm, ___errno_location), 271 | &WASM_FUNC_SYMBOL(asm, _malloc), 272 | &WASM_FUNC_SYMBOL(asm, _free), 273 | environ); 274 | if (ret) 275 | return -1; 276 | ret = wasmjit_emscripten_build_environment(&WASM_FUNC_SYMBOL(asm, ___emscripten_environ_constructor)); 277 | if (ret) 278 | return -1; 279 | return wasmjit_emscripten_invoke_main(&WASM_MEMORY_SYMBOL(env, memory), 280 | &WASM_FUNC_SYMBOL(asm, stackAlloc), 281 | &WASM_FUNC_SYMBOL(asm, _main), 282 | argc, argv); 283 | } 284 | -------------------------------------------------------------------------------- /src/wasmjit/static_runtime.c: -------------------------------------------------------------------------------- 1 | /* -*-mode:c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ 2 | 3 | /* 4 | Copyright (c) 2018 Rian Hunter 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #include 26 | 27 | #include 28 | 29 | #include 30 | #include 31 | 32 | int wasmjit_unmap_code_segment(void *code, size_t code_size) 33 | { 34 | (void)code; 35 | (void)code_size; 36 | return 1; 37 | } 38 | 39 | __attribute__((noreturn)) 40 | void wasmjit_trap(int reason) 41 | { 42 | fprintf(stderr, "TRAP: %s\n", 43 | wasmjit_trap_reason_to_string(reason)); 44 | exit(-1); 45 | } 46 | 47 | void wasmjit_init_static_module(struct StaticModuleInst *smi) 48 | { 49 | size_t i; 50 | 51 | if (smi->initted) return; 52 | 53 | /* type-check all imports */ 54 | 55 | for (i = 0; i < smi->func_types.n_elts; ++i) { 56 | struct FuncInst *ref = smi->module.funcs.elts[i]; 57 | struct FuncType *expected_type = &smi->func_types.elts[i]; 58 | if (!wasmjit_typecheck_func(expected_type, ref)) 59 | wasmjit_trap(WASMJIT_TRAP_MISMATCHED_TYPE); 60 | } 61 | 62 | for (i = 0; i < smi->table_types.n_elts; ++i) { 63 | struct TableInst *ref = smi->module.tables.elts[i]; 64 | struct TableType *expected_type = &smi->table_types.elts[i]; 65 | if (!wasmjit_typecheck_table(expected_type, ref)) 66 | wasmjit_trap(WASMJIT_TRAP_MISMATCHED_TYPE); 67 | } 68 | 69 | for (i = 0; i < smi->mem_types.n_elts; ++i) { 70 | struct MemInst *ref = smi->module.mems.elts[i]; 71 | struct MemoryType *expected_type = &smi->mem_types.elts[i]; 72 | if (!wasmjit_typecheck_memory(expected_type, ref)) 73 | wasmjit_trap(WASMJIT_TRAP_MISMATCHED_TYPE); 74 | } 75 | 76 | for (i = 0; i < smi->global_types.n_elts; ++i) { 77 | struct GlobalInst *ref = smi->module.globals.elts[i]; 78 | struct GlobalType *expected_type = &smi->global_types.elts[i]; 79 | if (!wasmjit_typecheck_global(expected_type, ref)) 80 | wasmjit_trap(WASMJIT_TRAP_MISMATCHED_TYPE); 81 | } 82 | 83 | /* init non-imported globals */ 84 | for (i = 0; i < smi->global_inits.n_elts; ++i) { 85 | // smi->global_types.n_elts 86 | struct GlobalInst *my_global = smi->module.globals.elts[smi->global_types.n_elts + i]; 87 | struct GlobalInit *gitr = &smi->global_inits.elts[i]; 88 | 89 | if (gitr->init_type == GLOBAL_GLOBAL_INIT) { 90 | /* TODO: check types */ 91 | wasmjit_init_static_module(gitr->init.parent.module); 92 | my_global->value = gitr->init.parent.global->value; 93 | } else { 94 | my_global->value = gitr->init.constant; 95 | } 96 | } 97 | 98 | for (i = 0; i < smi->elements.n_elts; ++i) { 99 | struct ElementInst *element = &smi->elements.elts[i]; 100 | struct TableInst *table = smi->module.tables.elts[element->tableidx]; 101 | size_t j; 102 | struct Value offset; 103 | 104 | if (element->offset_source_type == GLOBAL_CONST_INIT) { 105 | offset = element->offset.constant; 106 | } else { 107 | offset = element->offset.global->value; 108 | } 109 | 110 | if (offset.type != VALTYPE_I32) 111 | wasmjit_trap(WASMJIT_TRAP_MISMATCHED_TYPE); 112 | 113 | if (element->n_funcidxs + offset.data.i32 > table->length) 114 | wasmjit_trap(WASMJIT_TRAP_TABLE_OVERFLOW); 115 | 116 | for (j = 0; j < element->n_funcidxs; ++j) { 117 | table->data[offset.data.i32 + j] = smi->module.funcs.elts[element->funcidxs[j]]; 118 | } 119 | } 120 | 121 | for (i = 0; i < smi->datas.n_elts; ++i) { 122 | struct DataInst *data = &smi->datas.elts[i]; 123 | struct MemInst *mem = smi->module.mems.elts[data->memidx]; 124 | struct Value offset; 125 | 126 | if (data->offset_source_type == GLOBAL_CONST_INIT) { 127 | offset = data->offset.constant; 128 | } else { 129 | offset = data->offset.global->value; 130 | } 131 | 132 | if (offset.type != VALTYPE_I32) 133 | wasmjit_trap(WASMJIT_TRAP_MISMATCHED_TYPE); 134 | 135 | if (data->buf_size + offset.data.i32 > mem->size) 136 | wasmjit_trap(WASMJIT_TRAP_MEMORY_OVERFLOW); 137 | 138 | memcpy(mem->data + offset.data.i32, 139 | data->buf, 140 | data->buf_size); 141 | } 142 | 143 | if (smi->start_func) { 144 | struct FuncType expected_type; 145 | void (*start)(void); 146 | _wasmjit_create_func_type(&expected_type, 0, NULL, 0, NULL); 147 | if (!wasmjit_typecheck_func(&expected_type, smi->start_func)) 148 | wasmjit_trap(WASMJIT_TRAP_MISMATCHED_TYPE); 149 | start = smi->start_func->compiled_code; 150 | start(); 151 | } 152 | 153 | smi->initted = 1; 154 | } 155 | 156 | int wasmjit_invoke_function(struct FuncInst *funcinst, 157 | union ValueUnion *values, 158 | union ValueUnion *out) 159 | { 160 | union ValueUnion lout; 161 | lout = wasmjit_invoke_function_raw(funcinst, values); 162 | if (out) 163 | *out = lout; 164 | return 0; 165 | } 166 | -------------------------------------------------------------------------------- /src/wasmjit/static_runtime.h: -------------------------------------------------------------------------------- 1 | /* -*-mode:c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ 2 | 3 | /* 4 | Copyright (c) 2018 Rian Hunter 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #ifndef __WASMJIT__STATIC_RUNTIME_H__ 26 | #define __WASMJIT__STATIC_RUNTIME_H__ 27 | 28 | #include 29 | #include 30 | 31 | #include 32 | 33 | enum { 34 | GLOBAL_CONST_INIT, 35 | GLOBAL_GLOBAL_INIT, 36 | }; 37 | 38 | struct StaticModuleInst; 39 | 40 | struct GlobalInit { 41 | unsigned init_type; 42 | union GlobalInitUnion { 43 | struct Value constant; 44 | struct MGStruct { 45 | struct StaticModuleInst *module; 46 | struct GlobalInst *global; 47 | } parent; 48 | } init; 49 | }; 50 | 51 | struct ElementInst { 52 | size_t tableidx; 53 | unsigned offset_source_type; 54 | union ElementInstUnion { 55 | struct Value constant; 56 | struct GlobalInst *global; 57 | } offset; 58 | size_t n_funcidxs; 59 | uint32_t *funcidxs; 60 | }; 61 | 62 | struct DataInst { 63 | size_t memidx; 64 | unsigned offset_source_type; 65 | union DataInstUnion { 66 | struct Value constant; 67 | struct GlobalInst *global; 68 | } offset; 69 | size_t buf_size; 70 | char *buf; 71 | }; 72 | 73 | struct StaticModuleInst { 74 | struct ModuleInst module; 75 | 76 | DEFINE_ANON_VECTOR(struct FuncType) func_types; 77 | DEFINE_ANON_VECTOR(struct TableType) table_types; 78 | DEFINE_ANON_VECTOR(struct MemoryType) mem_types; 79 | DEFINE_ANON_VECTOR(struct GlobalType) global_types; 80 | 81 | DEFINE_ANON_VECTOR(struct GlobalInit) global_inits; 82 | DEFINE_ANON_VECTOR(struct DataInst) datas; 83 | DEFINE_ANON_VECTOR(struct ElementInst) elements; 84 | 85 | int initted; 86 | 87 | struct FuncInst *start_func; 88 | }; 89 | 90 | void wasmjit_init_static_module(struct StaticModuleInst *smi); 91 | 92 | 93 | #define WASM_SYMBOL(_module, _name, _type) _module ## __ ## _name ## __ ## _type 94 | 95 | #define WASM_FUNC_SYMBOL(_module, _name) WASM_SYMBOL(_module, _name, func) 96 | #define WASM_TABLE_SYMBOL(_module, _name) WASM_SYMBOL(_module, _name, table) 97 | #define WASM_MEMORY_SYMBOL(_module, _name) WASM_SYMBOL(_module, _name, mem) 98 | #define WASM_GLOBAL_SYMBOL(_module, _name) WASM_SYMBOL(_module, _name, global) 99 | #define WASM_MODULE_SYMBOL(___module) CAT(___module, _module) 100 | 101 | #define _DEFINE_WASM_GLOBAL(_module, _name, _init, _type, _member, _mut) \ 102 | struct GlobalInst WASM_SYMBOL(_module, _name, global) = { \ 103 | .value = { \ 104 | .type = (_type), \ 105 | .data = { \ 106 | ._member = (_init), \ 107 | }, \ 108 | }, \ 109 | .mut = (_mut), \ 110 | }; 111 | 112 | #define DEFINE_WASM_GLOBAL(...) _DEFINE_WASM_GLOBAL(CURRENT_MODULE, __VA_ARGS__) 113 | 114 | /* All these crazy macros are here because we have to statically generate a function 115 | with a compiled code signature from a function with host function signature */ 116 | 117 | #define CTYPE_VALTYPE_I32 uint32_t 118 | #define CTYPE_VALTYPE_NULL void 119 | #define CTYPE(val) CTYPE_ ## val 120 | 121 | #define VALUE_MEMBER_VALTYPE_I32 i32 122 | #define VALUE_MEMBER(val) VALUE_MEMBER_ ## val 123 | 124 | #define ITER __KMAP 125 | 126 | #define CT(to, n, t) CTYPE(t) CAT(arg, n) 127 | #define EXPAND_PARAMS(_n, ...) ITER(_n, CT, ##__VA_ARGS__) 128 | 129 | #define ARG(to, n, t) CAT(arg, n) 130 | #define EXPAND_ARGS(_n, ...) ITER(_n, ARG, ##__VA_ARGS__) 131 | 132 | #define VALUE(to, n, t) args[to - n]. VALUE_MEMBER(t) 133 | #define EXPAND_VALUES(_n, ...) ITER(_n, VALUE, ##__VA_ARGS__) 134 | 135 | #define COMMA_0 136 | #define COMMA_1 , 137 | #define COMMA_2 , 138 | #define COMMA_3 , 139 | #define COMMA_IF_NOT_EMPTY(_n) CAT(COMMA_, _n) 140 | 141 | #define _DEFINE_INVOKER_VALTYPE_NULL(_module, _name, _fptr, _unused, _n, ...) \ 142 | union ValueUnion CAT(CAT(CAT(_module, __), _name), __emscripten__hostfunc__invoker)(union ValueUnion *args) \ 143 | { \ 144 | union ValueUnion rout; \ 145 | (void)args; \ 146 | (*_fptr)(EXPAND_VALUES(_n, ##__VA_ARGS__) COMMA_IF_NOT_EMPTY(_n) &WASM_FUNC_SYMBOL(_module, _name)); \ 147 | memset(&rout.null, 0, sizeof(rout.null)); \ 148 | return rout; \ 149 | } \ 150 | 151 | #define _DEFINE_INVOKER_VALTYPE_NON_NULL(_module, _name, _fptr, _output, _n, ...) \ 152 | union ValueUnion CAT(CAT(CAT(_module, __), _name), __emscripten__hostfunc__invoker)(union ValueUnion *args) \ 153 | { \ 154 | CTYPE(_output) out; \ 155 | union ValueUnion rout; \ 156 | (void)args; \ 157 | out = (*_fptr)(EXPAND_VALUES(_n, ##__VA_ARGS__) COMMA_IF_NOT_EMPTY(_n) &WASM_FUNC_SYMBOL(_module, _name)); \ 158 | rout. VALUE_MEMBER(_output) = out; \ 159 | return rout; \ 160 | } \ 161 | 162 | #define _DEFINE_INVOKER_VALTYPE_I32 _DEFINE_INVOKER_VALTYPE_NON_NULL 163 | 164 | #define _DEFINE_INVOKER(_module, _name, _fptr, _output, _n, ...) \ 165 | _DEFINE_INVOKER_ ## _output(_module, _name, _fptr, _output, _n, ##__VA_ARGS__) 166 | 167 | #define _DEFINE_WASM_FUNCTION(qualifier, _module, _name, _fptr, _output, _n, ...) \ 168 | qualifier struct FuncInst WASM_FUNC_SYMBOL(_module, _name); \ 169 | \ 170 | _DEFINE_INVOKER(_module, _name, _fptr, _output, _n, ##__VA_ARGS__) \ 171 | \ 172 | CTYPE(_output) CAT(CAT(CAT(_module, __), _name), __emscripten__hostfunc__)(EXPAND_PARAMS(_n, ##__VA_ARGS__)) \ 173 | { \ 174 | return (*_fptr)(EXPAND_ARGS(_n, ##__VA_ARGS__) COMMA_IF_NOT_EMPTY(_n) &WASM_FUNC_SYMBOL(_module, _name)); \ 175 | } \ 176 | \ 177 | qualifier struct FuncInst WASM_FUNC_SYMBOL(_module, _name) = { \ 178 | .module_inst = &WASM_MODULE_SYMBOL(_module).module, \ 179 | .compiled_code = CAT(CAT(CAT(_module, __), _name), __emscripten__hostfunc__), \ 180 | .invoker = CAT(CAT(CAT(_module, __), _name), __emscripten__hostfunc__invoker), \ 181 | .type = { \ 182 | .n_inputs = _n, \ 183 | .input_types = { __VA_ARGS__ }, \ 184 | .output_type = _output, \ 185 | } \ 186 | }; 187 | 188 | #define DEFINE_WASM_FUNCTION_ADVANCED(qualifier, ...) _DEFINE_WASM_FUNCTION(qualifier, CURRENT_MODULE, __VA_ARGS__) 189 | #define DEFINE_WASM_FUNCTION(...) _DEFINE_WASM_FUNCTION(, CURRENT_MODULE, __VA_ARGS__) 190 | 191 | #define _DEFINE_WASM_TABLE(_module, _name, _elemtype, _length_, _max) \ 192 | struct FuncInst *WASM_SYMBOL(_module, _name, buffer) [(_max)]; \ 193 | struct TableInst WASM_TABLE_SYMBOL(_module, _name) = { \ 194 | .data = WASM_SYMBOL(_module, _name, buffer), \ 195 | .elemtype = ELEMTYPE_ANYFUNC, \ 196 | .length = (_max), \ 197 | .max = (_max), \ 198 | }; 199 | 200 | #define DEFINE_WASM_TABLE(...) _DEFINE_WASM_TABLE(CURRENT_MODULE, __VA_ARGS__) 201 | 202 | #define _DEFINE_WASM_MEMORY(_module, _name, _min, _max) \ 203 | char WASM_SYMBOL(_module, _name, buffer)[(_min) * WASM_PAGE_SIZE]; \ 204 | struct MemInst WASM_MEMORY_SYMBOL(_module, _name) = {\ 205 | .data = WASM_SYMBOL(_module, _name, buffer), \ 206 | .size = (_min) * WASM_PAGE_SIZE, \ 207 | .max = (_min) * WASM_PAGE_SIZE, \ 208 | }; 209 | 210 | #define DEFINE_WASM_MEMORY(...) _DEFINE_WASM_MEMORY(CURRENT_MODULE, __VA_ARGS__) 211 | 212 | #endif 213 | -------------------------------------------------------------------------------- /src/wasmjit/sys.h: -------------------------------------------------------------------------------- 1 | /* -*-mode:c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ 2 | 3 | /* 4 | Copyright (c) 2018 Rian Hunter 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #ifndef __WASMJIT__SYS_H__ 26 | #define __WASMJIT__SYS_H__ 27 | 28 | #ifdef __KERNEL__ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #ifdef NDEBUG 36 | #define assert(x) 37 | #else 38 | #define assert(x) BUG_ON(!(x)) 39 | #endif 40 | 41 | #define OFF (sizeof(size_t) * 2) 42 | 43 | __attribute__((unused)) 44 | static void *malloc(size_t size) 45 | { 46 | char *ret; 47 | size_t cap = 1; 48 | 49 | if (!size) 50 | return NULL; 51 | 52 | while ((size + OFF) > cap) { 53 | cap <<= 1; 54 | } 55 | 56 | ret = kvmalloc(cap, GFP_KERNEL); 57 | if (!ret) 58 | return NULL; 59 | memcpy(ret, &cap, sizeof(cap)); 60 | memcpy(ret + sizeof(cap), &size, sizeof(size)); 61 | return &ret[OFF]; 62 | } 63 | 64 | __attribute__((unused)) 65 | static void free(void *ptr) 66 | { 67 | if (ptr) 68 | kvfree(&((char *)ptr)[-OFF]); 69 | } 70 | 71 | __attribute__((unused)) 72 | static void *calloc(size_t nmemb, size_t elt_size) 73 | { 74 | char *ret; 75 | size_t size, cap; 76 | if (__builtin_umull_overflow(nmemb, elt_size, &size)) { 77 | return NULL; 78 | } 79 | 80 | if (!size) 81 | return NULL; 82 | 83 | cap = 1; 84 | while ((size + OFF) > cap) { 85 | cap <<= 1; 86 | } 87 | 88 | ret = kvzalloc(cap, GFP_KERNEL); 89 | if (!ret) 90 | return NULL; 91 | 92 | memcpy(ret, &cap, sizeof(cap)); 93 | memcpy(ret + sizeof(cap), &size, sizeof(size)); 94 | 95 | return &ret[OFF]; 96 | } 97 | 98 | __attribute__((unused)) 99 | static void *realloc(void *previous, size_t size) 100 | { 101 | char *cptr = previous, *new; 102 | 103 | if (!size) { 104 | free(previous); 105 | return NULL; 106 | } 107 | 108 | if (cptr) { 109 | size_t prev_cap; 110 | memcpy(&prev_cap, &cptr[-OFF], sizeof(prev_cap)); 111 | 112 | if ((size + OFF) < prev_cap) { 113 | /* NB: we don't support shrinking */ 114 | memcpy(&cptr[-OFF + sizeof(prev_cap)], &size, sizeof(size)); 115 | return cptr; 116 | } 117 | } 118 | 119 | new = malloc(size); 120 | if (!new) 121 | return NULL; 122 | 123 | if (cptr) { 124 | size_t prev_size; 125 | memcpy(&prev_size, &cptr[-OFF + sizeof(size_t)], sizeof(prev_size)); 126 | memcpy(new, cptr, prev_size); 127 | free(cptr); 128 | } 129 | 130 | return new; 131 | } 132 | 133 | __attribute__((unused)) 134 | static char *strdup(const char *s) 135 | { 136 | size_t l = strlen(s); 137 | char *n = malloc(l + 1); 138 | if (!n) 139 | return NULL; 140 | memcpy(n, s, l + 1); 141 | return n; 142 | } 143 | 144 | #define PRIx32 "x" 145 | #define PRIu32 "u" 146 | #define INT32_MAX 2147483647 147 | #define INT32_MIN (-2147483648) 148 | 149 | #if defined __GNUC__ && defined __GNUC_MINOR__ 150 | # define __GNUC_PREREQ(maj, min) \ 151 | ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) 152 | #else 153 | # define __GNUC_PREREQ(maj, min) 0 154 | #endif 155 | 156 | # if __GNUC_PREREQ (3, 3) 157 | # define INFINITY (__builtin_inff ()) 158 | # else 159 | # define INFINITY HUGE_VALF 160 | # endif 161 | 162 | #if __GNUC_PREREQ (3, 3) 163 | # define NAN (__builtin_nanf ("")) 164 | # else 165 | /* This will raise an "invalid" exception outside static initializers, 166 | but is the best that can be done in ISO C while remaining a 167 | constant expression. */ 168 | # define NAN (0.0f / 0.0f) 169 | # endif 170 | 171 | typedef int64_t intmax_t; 172 | 173 | 174 | #ifdef __x86_64__ 175 | typedef unsigned long __jmp_buf[8]; 176 | #else 177 | #error Only works on x86_64 178 | #endif 179 | 180 | typedef struct __jmp_buf_tag { 181 | __jmp_buf __jb; 182 | unsigned long __fl; 183 | unsigned long __ss[128/sizeof(long)]; 184 | } jmp_buf[1]; 185 | 186 | int setjmp(jmp_buf); 187 | void longjmp(jmp_buf, int) __attribute__((noreturn)); 188 | 189 | #else 190 | 191 | #include 192 | #include 193 | #include 194 | #include 195 | #include 196 | #include 197 | #include 198 | #include 199 | #include 200 | #include 201 | #include 202 | 203 | #endif 204 | 205 | #endif 206 | -------------------------------------------------------------------------------- /src/wasmjit/tls.h: -------------------------------------------------------------------------------- 1 | /* -*-mode:c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ 2 | 3 | /* 4 | Copyright (c) 2018 Rian Hunter 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #ifndef __WASMJIT__TLS_H__ 26 | #define __WASMJIT__TLS_H__ 27 | 28 | #include 29 | #include 30 | 31 | typedef pthread_key_t wasmjit_tls_key_t; 32 | 33 | __attribute__((unused)) 34 | static int wasmjit_init_tls_key(wasmjit_tls_key_t *pkey, void (*destr)(void *)) 35 | { 36 | return !pthread_key_create(pkey, destr); 37 | } 38 | 39 | __attribute__((unused)) 40 | static int wasmjit_get_tls_key(wasmjit_tls_key_t key, void *newval) 41 | { 42 | errno = 0; 43 | *(void **)newval = pthread_getspecific(key); 44 | return (*(void **)newval || !errno); 45 | } 46 | 47 | __attribute__((unused)) 48 | static int wasmjit_set_tls_key(wasmjit_tls_key_t key, void *val) 49 | { 50 | return !pthread_setspecific(key, val); 51 | } 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /src/wasmjit/util.c: -------------------------------------------------------------------------------- 1 | /* -*-mode:c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ 2 | 3 | /* 4 | Copyright (c) 2018 Rian Hunter 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #include 26 | 27 | #include 28 | 29 | #include 30 | 31 | DEFINE_VECTOR_GROW(buffer, struct SizedBuffer); 32 | 33 | int output_buf(struct SizedBuffer *sstack, const void *buf, 34 | size_t n_elts) 35 | { 36 | if (!buffer_grow(sstack, n_elts)) 37 | return 0; 38 | memcpy(sstack->elts + sstack->n_elts - n_elts, buf, 39 | n_elts * sizeof(sstack->elts[0])); 40 | return 1; 41 | } 42 | 43 | #ifndef __KERNEL__ 44 | 45 | #include 46 | #include 47 | #include 48 | 49 | #include 50 | #include 51 | 52 | char *wasmjit_load_file(const char *filename, size_t *size) 53 | { 54 | FILE *f = NULL; 55 | char *input = NULL; 56 | int fd = -1, ret; 57 | struct stat st; 58 | size_t rets; 59 | 60 | fd = open(filename, O_RDONLY); 61 | if (fd < 0) { 62 | goto error_exit; 63 | } 64 | 65 | ret = fstat(fd, &st); 66 | if (ret < 0) { 67 | goto error_exit; 68 | } 69 | 70 | f = fdopen(fd, "r"); 71 | if (!f) { 72 | goto error_exit; 73 | } 74 | fd = -1; 75 | 76 | *size = st.st_size; 77 | input = malloc(st.st_size); 78 | if (!input) { 79 | goto error_exit; 80 | } 81 | 82 | rets = fread(input, sizeof(char), st.st_size, f); 83 | if (rets != (size_t) st.st_size) { 84 | goto error_exit; 85 | } 86 | 87 | goto success_exit; 88 | 89 | error_exit: 90 | if (input) { 91 | free(input); 92 | } 93 | 94 | success_exit: 95 | if (f) { 96 | fclose(f); 97 | } 98 | 99 | if (fd >= 0) { 100 | close(fd); 101 | } 102 | 103 | return input; 104 | } 105 | 106 | void wasmjit_unload_file(char *buf, size_t size) 107 | { 108 | free(buf); 109 | (void) size; 110 | } 111 | 112 | #else 113 | 114 | #include 115 | 116 | char *wasmjit_load_file(const char *file_name, size_t *size) 117 | { 118 | void *buf; 119 | loff_t offsize; 120 | int ret; 121 | ret = kernel_read_file_from_path(file_name, &buf, &offsize, 122 | INT_MAX, READING_UNKNOWN); 123 | if (ret < 0) 124 | return NULL; 125 | 126 | *size = offsize; 127 | return buf; 128 | } 129 | 130 | void wasmjit_unload_file(char *buf, size_t size) 131 | { 132 | vfree(buf); 133 | (void) size; 134 | } 135 | 136 | #endif 137 | -------------------------------------------------------------------------------- /src/wasmjit/util.h: -------------------------------------------------------------------------------- 1 | /* -*-mode:c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ 2 | 3 | /* 4 | Copyright (c) 2018 Rian Hunter 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #ifndef __WASMJIT__UTIL_H__ 26 | #define __WASMJIT__UTIL_H__ 27 | 28 | #include 29 | 30 | #include 31 | 32 | __attribute__ ((unused)) 33 | static uint16_t uint16_t_swap_bytes(uint16_t data) 34 | { 35 | #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 36 | return data; 37 | #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 38 | uint16_t bottom = (data >> 0) & 0xFF; 39 | uint16_t top = (data >> 8) & 0xFF; 40 | return (bottom << 8) | top; 41 | #else 42 | #error Unsupported Architecture 43 | #endif 44 | } 45 | 46 | __attribute__ ((unused)) 47 | static uint32_t uint32_t_swap_bytes(uint32_t data) 48 | { 49 | #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 50 | return data; 51 | #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 52 | uint32_t bottom = uint16_t_swap_bytes(data & 0xffff); 53 | uint32_t top = uint16_t_swap_bytes((data >> 16) & 0xffff); 54 | return (bottom << 8) | top; 55 | #else 56 | #error Unsupported Architecture 57 | #endif 58 | } 59 | 60 | __attribute__ ((unused)) 61 | static uint64_t uint64_t_swap_bytes(uint64_t data) 62 | { 63 | #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 64 | return data; 65 | #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 66 | uint64_t bottom = uint32_t_swap_bytes(data & 0xffffffff); 67 | uint64_t top = uint32_t_swap_bytes((data >> 32) & 0xffffffff); 68 | return (bottom << 32) | top; 69 | #else 70 | #error Unsupported Architecture 71 | #endif 72 | } 73 | 74 | __attribute__ ((unused)) 75 | static void encode_le_uint64_t(uint64_t val, char *buf) 76 | { 77 | uint64_t le_val = uint64_t_swap_bytes(val); 78 | memcpy(buf, &le_val, sizeof(le_val)); 79 | } 80 | 81 | __attribute__ ((unused, malloc)) 82 | static void *wasmjit_alloc_vector(size_t n_elts, size_t elt_size, size_t *alloced) { 83 | size_t size; 84 | if (__builtin_umull_overflow(n_elts, elt_size, &size)) { 85 | return NULL; 86 | } 87 | 88 | if (alloced) 89 | *alloced = size; 90 | 91 | return malloc(size); 92 | } 93 | 94 | __attribute__ ((unused, malloc)) 95 | static void *wasmjit_copy_buf(void *buf, size_t n_elts, size_t elt_size) 96 | { 97 | void *newbuf; 98 | size_t size; 99 | newbuf = wasmjit_alloc_vector(n_elts, elt_size, &size); 100 | if (!newbuf) 101 | return NULL; 102 | 103 | memcpy(newbuf, buf, size); 104 | return newbuf; 105 | } 106 | 107 | struct SizedBuffer { 108 | size_t n_elts; 109 | char *elts; 110 | }; 111 | 112 | DECLARE_VECTOR_GROW(buffer, struct SizedBuffer); 113 | 114 | int output_buf(struct SizedBuffer *sstack, const void *buf, 115 | size_t n_elts); 116 | 117 | #define ARRAY_LEN(arr) (sizeof(arr) / sizeof(arr[0])) 118 | #define NUMVALS(...) (sizeof((int[]){__VA_ARGS__})/sizeof(int)) 119 | 120 | #define CATAGAIN(a, b) a ## b 121 | #define CAT(a, b) CATAGAIN(a, b) 122 | 123 | #if defined(__STDC_IEC_559__) || (defined(__x86_64__) && defined(__clang__)) 124 | #define IEC559_FLOAT_ENCODING 125 | #endif 126 | 127 | char *wasmjit_load_file(const char *filename, size_t *size); 128 | void wasmjit_unload_file(char *buf, size_t size); 129 | 130 | #define __KMAP0(to,m,...) 131 | #define __KMAP1(to,m,t,...) m(to,1,t) 132 | #define __KMAP2(to,m,t,...) m(to,2,t), __KMAP1(to,m,__VA_ARGS__) 133 | #define __KMAP3(to,m,t,...) m(to,3,t), __KMAP2(to,m,__VA_ARGS__) 134 | #define __KMAP4(to,m,t,...) m(to,4,t), __KMAP3(to,m,__VA_ARGS__) 135 | #define __KMAP5(to,m,t,...) m(to,5,t), __KMAP4(to,m,__VA_ARGS__) 136 | #define __KMAP6(to,m,t,...) m(to,6,t), __KMAP5(to,m,__VA_ARGS__) 137 | #define __KMAP(n,...) __KMAP##n(n, __VA_ARGS__) 138 | 139 | #define MMIN(x, y) (((x) < (y)) ? (x) : (y)) 140 | #define MMAX(x, y) (((x) > (y)) ? (x) : (y)) 141 | 142 | #endif 143 | -------------------------------------------------------------------------------- /src/wasmjit/vector.c: -------------------------------------------------------------------------------- 1 | /* -*-mode:c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ 2 | 3 | /* 4 | Copyright (c) 2018 Rian Hunter 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #include 26 | 27 | int wasmjit_vector_set_size(void *elts_, size_t *n_elts, size_t new_n_elts, 28 | size_t elt_size) 29 | { 30 | void **elts = (void **)elts_; 31 | void *newstackelts; 32 | size_t total_elt_size; 33 | 34 | if (__builtin_umull_overflow(new_n_elts, elt_size, &total_elt_size)) { 35 | goto error; 36 | } 37 | 38 | newstackelts = realloc(*elts, total_elt_size); 39 | if (!newstackelts && total_elt_size) 40 | goto error; 41 | 42 | *elts = newstackelts; 43 | *n_elts = new_n_elts; 44 | 45 | return 1; 46 | 47 | error: 48 | free(*elts); 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /src/wasmjit/vector.h: -------------------------------------------------------------------------------- 1 | /* -*-mode:c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ 2 | 3 | /* 4 | Copyright (c) 2018 Rian Hunter 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | */ 24 | 25 | #ifndef __WASMJIT__VECTOR_H__ 26 | #define __WASMJIT__VECTOR_H__ 27 | 28 | #include 29 | 30 | int wasmjit_vector_set_size(void *, size_t *, size_t, size_t); 31 | 32 | #define DEFINE_ANON_VECTOR(type) \ 33 | struct { \ 34 | size_t n_elts; \ 35 | type *elts; \ 36 | } 37 | 38 | #define VECTOR_GROW(sstack, _n_elts) \ 39 | wasmjit_vector_set_size(&(sstack)->elts, \ 40 | &(sstack)->n_elts, \ 41 | ((sstack)->n_elts + (_n_elts)), \ 42 | sizeof((sstack)->elts[0])) 43 | 44 | 45 | 46 | #define DECLARE_VECTOR_GROW(name, _type) \ 47 | int name ## _grow(_type *sstack, size_t n_elts) 48 | 49 | 50 | #define DEFINE_VECTOR_GROW(name, _type) \ 51 | int name ## _grow(_type *sstack, size_t n_elts) { \ 52 | return wasmjit_vector_set_size(&sstack->elts, \ 53 | &sstack->n_elts, \ 54 | (sstack->n_elts + n_elts), \ 55 | sizeof(sstack->elts[0])); \ 56 | } 57 | 58 | #define DEFINE_VECTOR_TRUNCATE(name, _type) \ 59 | int name ## _truncate(_type *sstack, size_t amt) { \ 60 | return wasmjit_vector_set_size(&sstack->elts, \ 61 | &sstack->n_elts, \ 62 | amt, \ 63 | sizeof(sstack->elts[0])); \ 64 | } 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /src/wasmjit/x86_64_jmp.S: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018 Rian Hunter 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | */ 22 | 23 | #include 24 | #include 25 | 26 | .global invoke_on_stack 27 | .type invoke_on_stack,@function 28 | invoke_on_stack: 29 | push %rbp 30 | mov %rsp, %rbp 31 | mov %rdi, %rsp 32 | mov %rdx, %rdi 33 | CALL_NOSPEC %rsi 34 | mov %rbp, %rsp 35 | pop %rbp 36 | ret 37 | 38 | /* The following code is Copyright 2011-2012 Nicholas J. Kain, licensed under standard MIT license */ 39 | 40 | .global setjmp 41 | .type setjmp,@function 42 | setjmp: 43 | mov %rbx,(%rdi) /* rdi is jmp_buf, move registers onto it */ 44 | mov %rbp,8(%rdi) 45 | mov %r12,16(%rdi) 46 | mov %r13,24(%rdi) 47 | mov %r14,32(%rdi) 48 | mov %r15,40(%rdi) 49 | lea 8(%rsp),%rdx /* this is our rsp WITHOUT current ret addr */ 50 | mov %rdx,48(%rdi) 51 | mov (%rsp),%rdx /* save return addr ptr for new rip */ 52 | mov %rdx,56(%rdi) 53 | xor %rax,%rax /* always return 0 */ 54 | ret 55 | 56 | .global longjmp 57 | .type longjmp,@function 58 | longjmp: 59 | mov %rsi,%rax /* val will be longjmp return */ 60 | test %rax,%rax 61 | jnz 1f 62 | inc %rax /* if val==0, val=1 per longjmp semantics */ 63 | 1: 64 | mov (%rdi),%rbx /* rdi is the jmp_buf, restore regs from it */ 65 | mov 8(%rdi),%rbp 66 | mov 16(%rdi),%r12 67 | mov 24(%rdi),%r13 68 | mov 32(%rdi),%r14 69 | mov 40(%rdi),%r15 70 | mov 48(%rdi),%rdx /* this ends up being the stack pointer */ 71 | mov %rdx,%rsp 72 | mov 56(%rdi),%rdx /* this is the instruction pointer */ 73 | JMP_NOSPEC %rdx /* goto saved address without altering rsp */ 74 | -------------------------------------------------------------------------------- /src/wasmjit_examples/selfpipe.c: -------------------------------------------------------------------------------- 1 | /* -*-mode:c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ 2 | 3 | /* 4 | System-call heavy microbenchmark to show off speed of wasmjit. 5 | */ 6 | 7 | /* 8 | Copyright (c) 2018 Rian Hunter 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all 18 | copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | */ 28 | 29 | #include 30 | 31 | #include 32 | 33 | char buf[4096]; 34 | 35 | int main(int argc, char *argv[]) 36 | { 37 | int pipes[2], ret; 38 | size_t i; 39 | 40 | ret = pipe(pipes); 41 | if (ret) { 42 | perror("pipe"); 43 | return -1; 44 | } 45 | 46 | for (i = 0; i < 16ULL * 1024ULL * 1024ULL * 1024 / 4096; ++i) { 47 | ret = write(pipes[1], buf, sizeof(buf)); 48 | if (ret < 0) { 49 | perror("write"); 50 | return -1; 51 | } 52 | 53 | ret = read(pipes[0], buf, sizeof(buf)); 54 | if (ret < 0) { 55 | perror("read"); 56 | } 57 | } 58 | 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /wasmjit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenny-ngo/wasmjit/fa148c4c4b453cb387f8868bb2997e60dc49d954/wasmjit.png --------------------------------------------------------------------------------