├── BasicCABI.md ├── BasicModuleABI.md ├── BuildId.md ├── CodeMetadata.md ├── Coredump.md ├── Debugging.md ├── DynamicLinking.md ├── EHScheme.md ├── ItaniumLikeC++ABI.md ├── LICENSE ├── Lime.md ├── Linking.md ├── ProducersSection.md ├── README.md ├── SetjmpLongjmp.md ├── Signatures.md └── SwiftABI.md /BasicCABI.md: -------------------------------------------------------------------------------- 1 | This document describes the "Basic" C ABI for WebAssembly. As mentioned in 2 | [README](README.md), it's not the only possible C ABI. It is the ABI that the 3 | clang/LLVM WebAssembly backend is currently using, and any other C or C++ 4 | compiler wishing to be ABI-compatible with it. 5 | 6 | # Versioning and Machine interface 7 | 8 | The current version of this ABI is *1*. 9 | 10 | This ABI is designed to work with Release 1.0 of the WebAssembly [Specification](https://webassembly.github.io/spec/core/index.html). It does not require any 11 | [features](https://github.com/WebAssembly/proposals) 12 | that have not yet been implemented and standardized. Future versions will depend on 13 | features such as threads and/or multi-value. 14 | 15 | ## Data Representation 16 | 17 | **Scalar Types** 18 | 19 | The ABI for the currently-specifed version of WebAssembly (also known as "wasm32") uses an "ILP32" data model, 20 | where `int`, `long`, and pointer types are 32 bits. It is expected that the proposed extension to allow memories 21 | larger than 4GB ("wasm64") will use an "LP64" data model, where `int` is 32 bits while `pointer` and `long` are 22 | 64 bits. 23 | 24 | The following table shows the memory sizes and alignments of C and C++ scalar types, and their 25 | correspondence to types used in the WebAssembly specification: 26 | 27 | 28 | General type | C Type | `sizeof` | Alignment (bytes) | Wasm Value Type 29 | -|-|-|-|- 30 | Integer | `_Bool`/`bool` | 1 | 1 | i32 31 | Integer | `char`, `signed char` | 1 | 1 | i32 32 | Integer | `unsigned char` | 1 | 1 | i32 33 | Integer | `short` / `signed short` | 2 | 2 | i32 34 | Integer | `unsigned short` | 2 | 2 | i32 35 | Integer | `int` / `signed int` / `enum` | 4 | 4 | i32 36 | Integer | `unsigned int` | 4 | 4 | i32 37 | Integer | `long` / `signed long` | 4 | 4 | i32 38 | Integer | `unsigned long` | 4 | 4 | i32 39 | Integer | `long long` / `signed long long` | 8 | 8 | i64 40 | Integer | `unsigned long long` | 8 | 8 | i64 41 | Integer | `__int128_t` | 16 | 16 | (none) 42 | Integer | `__uint128_t` | 16 | 16 | (none) 43 | Pointer | *`any-type *`* / *`any-type (*)()`* | 4 | 4 | i32 44 | Floating point | `float` | 4 | 4 | f32 45 | Floating point | `double` | 8 | 8 | f64 46 | Floating point | `long double` | 16 | 16 | (none) 47 | Floating point | `long double` (Emscripten) | 16 | 8 | (none) 48 | 49 | * `long double` values correspond to 128-bit IEEE-754 quad-precision binary128 values. 50 | Operations on these values are currently implemented as calls to 51 | compiler-rt library functions. 52 | * A null pointer (for all types) has the value zero 53 | * The `size_t` type is defined as `unsigned long`. 54 | * An `enum` is `i32` if all the members of the `enum` can be represented 55 | by an `int`. 56 | An `enum` is `i32` if all the members of the `enum` can be represented 57 | by an `unsigned int`. 58 | Otherwise, if a compiler supports such an `enum`, it would use `i64` 59 | for the `enum`. 60 | * Emscripten uses 8 byte alignment for `long double`. 61 | * `__int128_t` and `__uint128_t` are passed as two `i64`s in little-endian 62 | order, and are otherwise represented in the ABI as a struct containing two 63 | `i64` fields, in little-endian order. 64 | * `_Complex` types are represented in the ABI as a struct containing two 65 | corresponding floating-point fields, real and imaginary. 66 | * `_BitInt(N)` types are supported up to width 128 and are represented as the 67 | smallest same-signedness Integer type with at least as many bits. 68 | 69 | **Aggregates and Unions** 70 | 71 | Structures and unions assume the alignment of their most strictly aligned component. 72 | Each member is assigned to the lowest available offset with the appropriate 73 | alignment. The size of any object is always a multiple of the object‘s alignment. 74 | An array uses the same alignment as its elements, except that a local or global 75 | array variable of length at least 16 bytes or a C99 variable-length array variable 76 | always has alignment of at least 16 bytes. 77 | Structure and union objects can require padding to meet size and alignment 78 | constraints. The contents of any padding is undefined. 79 | 80 | **Bit-fields** 81 | 82 | C struct and union definitions may include bit-fields that define integral values of 83 | a specified size. 84 | The ABI does not permit bit-fields having the type __m64, __m128 or __m256. 85 | (Programs using bit-fields of these types are not portable.) 86 | Bit-fields that are neither signed nor unsigned always have non-negative values. 87 | Although they may have type char, short, int, or long (which can have negative values), 88 | these bit-fields have the same range as a bit-field of the same size 89 | with the corresponding unsigned type. Bit-fields obey the same size and alignment 90 | rules as other structure and union members. 91 | Also: 92 | 93 | * bit-fields are allocated from right to left 94 | * bit-fields must be contained in a storage unit appropriate for its declared 95 | type 96 | * bit-fields may share a storage unit with other struct / union members 97 | * Unnamed bit-fields’ types do not affect the alignment of a structure or union. 98 | 99 | Bitfield type | Witdh *w* | Range 100 | -|-|- 101 | `signed char` | 1 to 8 | -2(w-1) to 2(w-1)-1 102 | `char`, `unsigned char` | 1 to 8 | 0 to 2w-1 103 | `signed short` | 1 to 16 | -2(w-1) to 2(w-1)-1 104 | `short`, `unsigned short` | 1 to 16 | 0 to 2w-1 105 | `signed int` | 1 to 32 | -2(w-1) to 2(w-1)-1 106 | `int`, `unsigned int` | 1 to 32 | 0 to 2w-1 107 | `signed long long` | 1 to 64 | -2(w-1) to 2(w-1)-1 108 | `long long`, `unsigned long long` | 1 to 64 | 0 to 2w-1 109 | 110 | **SIMD Vector types** 111 | 112 | The ABI for vector types is not stable and may change as new optimization opportunities are 113 | found. 114 | 115 | # Function Calling Sequence 116 | This section describes the standard function calling sequence, including stack frame 117 | layout, Wasm argument and local value usage, and so on. These requirements apply 118 | only to global functions (those reachable from other compilation units) . Local functions 119 | may use different conventions; however this may reduce the ability of external tools 120 | to understand them. 121 | 122 | 123 | ## Locals and the stack frame 124 | WebAssembly does not have registers in the style of hardware architectures. Instead it has an 125 | unlimited number of function arguments and local variables, which have wasm value types. These 126 | local values are generally used as registers would be in a traditional architecture, but there 127 | are some important differences. Because arguments are modeled explicitly and locals are local 128 | to a function, there is no need for a concept of callee- or caller-saved locals. 129 | 130 | 131 | ### The linear stack 132 | WebAssembly is a [Harvard](https://en.wikipedia.org/wiki/Harvard_architecture) architecture; 133 | this means that code and data are not in the same memory space. No code or code addresses are 134 | visible in the wasm linear memory space, the only "address" that a function has is its index 135 | in the wasm function index space. Additionally the wasm implementation's runtime call stack 136 | (including the return address and function arguments) is not visible in the linear memory either. 137 | This means that address-taken local C variables need to be on a separate stack in the linear memory 138 | (herafter called the "linear stack"). It also means that some functions may not need a frame in the 139 | linear stack at all. 140 | 141 | Instead of registers visible to all functions, WebAssembly has a table of global variables. One of these 142 | acts as the stack pointer [TODO: describe how stack pointer is designated here, or in object file section] 143 | [TODO: discuss mutable global requirement]. 144 | 145 | Each function may have a frame on the linear stack. This stack grows downward 146 | [TODO: describe how start position is determined]. 147 | The stack pointer global (`SP`) points to the bottom of the stack frame and always has 16-byte alignment. 148 | If there are dynamically-sized objects on the stack, a frame pointer (a local variable, `FP`) is used, 149 | and it points to the bottom of the static-size objects (those whose sizes are known at compile time). 150 | If objects in the current frame require alignment greater than 16, then a base pointer (another local, `BP`) 151 | is used, which points to the bottom of the previous frame. 152 | The stack also has a "red zone" which extends 128 bytes below the stack pointer. If a function 153 | does not need a frame or base pointer, it may write data into the red zone which is not needed 154 | across function calls. So a leaf function which needs less than 128 bytes of stack space 155 | need not update the stack pointer in its prolog or epilog at all. 156 | 157 | The frame organization is illustrated as follows (with higher memory addresses at the top): 158 | 159 | Position | Contents | Frame 160 | ---------------------------- | -------------------------------| ----------- 161 | `BP` | unspecified | Previous 162 | ... | unspecified (aligment padding) | Current 163 | `FP` + *s*
...
`FP` | static-size objects | Current 164 | `SP` + *d*
...
`SP` | dynamic-size objects | Current 165 | ...
`SP`-128 | small static-size objects | Current (red zone) 166 | 167 | Note: in other ABIs the frame pointer typically points to a saved frame pointer (and return address) 168 | at the top of the current frame. In this ABI the frame pointer points to the bottom of the current frame instead. 169 | This is because the constant offset 170 | field of Wasm load and store instructions are unsigned; addresses of the form `FP` + *n* can be folded 171 | into a single insruction, e.g. `i32.load offset=n`. This is also why the stack grows downward (so `SP` + *n* 172 | can also be folded). One consequence of of the lack of return addresses and frame pointer chains is that there 173 | is no way to traverse the linear stack. There is also no currently-specified way to determine which wasm local 174 | is used as the frame pointer or base pointer. This functionality is not needed for backtracing or unwinding (since the 175 | wasm VM must do this in any case); however it may still be desirable to allow this functionality for debugging 176 | or in-field crash reporting. Future ABIs may designate a convention for determining frame size and local usage. 177 | 178 | ### Function arguments and return values 179 | 180 | Types can be passed directly via WebAssembly function parameters or indirectly 181 | via a pointer parameter that points to the value in memory. The callee is 182 | allowed to modify the contents of that memory, so the caller is responsible for 183 | making a copy of any indirectly passed data that the callee should not modify. 184 | Similarly, types can either be returned directly from WebAssembly functions or 185 | returned indirectly via a pointer parameter prepended to the parameter list. 186 | 187 | Type | Parameter | Result | 188 | -----------------------------|---------------|----------| 189 | scalar[1] | direct | direct | 190 | empty struct or union | ignored | ignored | 191 | singleton struct or union[2] | direct | direct | 192 | other struct or union[3] | indirect | indirect | 193 | array | indirect | N/A | 194 | 195 | [1] `long long double` and `__int128` are passed directly as two `i64` values. 196 | Signed 8 and 16-bit scalars are sign-extended, and unsigned 8 and 16-bit 197 | scalars are zero-extended before passing or returning. 198 | 199 | [2] Any struct or union that recursively (including through nested structs, 200 | unions, and arrays) contains just a single scalar value and is not specified to 201 | have greater than natural alignment. 202 | 203 | [3] This calling convention was defined before 204 | [multivalue](https://github.com/WebAssembly/multi-value) was standardized. A new 205 | default calling convention that changes this behavior and takes advantage of 206 | multivalue may be introduced in the future. 207 | 208 | Varargs are placed in a buffer by the caller and the last parameter to the 209 | function is a pointer to that buffer. The callee is allowed to modify the 210 | contents of the buffer, so the caller is responsible for making a copy of any 211 | varargs data that the callee should not modify. Arguments are arranged in order 212 | in the buffer, with each argument placed at the lowest appropriately aligned 213 | address after the previous argument. 214 | 215 | ## Program startup 216 | 217 | ### User entrypoint 218 | 219 | The *user entrypoint* is the function which runs the bulk of the program. 220 | It is called `main` in C, C++, and other languages. Note that this may 221 | not be the first function in the program to be called, as programs may 222 | also have global constructors which run before it. 223 | 224 | At the wasm C ABI level, the following symbol names are used: 225 | 226 | C ABI Symbol name | C and C++ signature | 227 | ---------------------------- | -----------------------------------| 228 | `main` | `int main(void)` or `int main()` | 229 | `__main_argc_argv` | `int main(int argc, char *argv[])` | 230 | 231 | These symbol names only apply at the ABI level; C and C++ source should 232 | continue to use the standard `main` name, and compilers will handle the 233 | details of conforming to the ABI. 234 | 235 | Also note that C symbol names are distinct from WebAssembly export 236 | names, which are outside the scope of the C ABI. Toolchains which export 237 | the user entrypoint may chose to export it as the name `main`, even when 238 | the C ABI symbol name is `__main_argc_argv`. 239 | 240 | A symbol name other than `main` is needed because the usual trick of 241 | having implementations pass arguments to `main` even when they aren't 242 | needed doesn't work in wasm, which requires caller and callee signatures 243 | to exactly match. 244 | 245 | For the same reason, the wasm C ABI doesn't support an `envp` parameter. 246 | Fortunately, `envp` is not required by C, POSIX, or any other relevant 247 | standards, and is generally considered obsolete in favor of `getenv`. 248 | 249 | ### Program entrypoint 250 | 251 | The *program entrypoint* is the first function in the program to be called. 252 | It is commonly called `_start` on other platforms, though this is a 253 | low-level detail that most code doesn't interact with. 254 | 255 | The program entrypoint is out of scope for the wasm C ABI. It may depend 256 | on what environment the program will be run in. 257 | -------------------------------------------------------------------------------- /BasicModuleABI.md: -------------------------------------------------------------------------------- 1 | Basic Module ABI 2 | ================ 3 | 4 | There are many different ways to use Wasm modules, and many different 5 | conventions, language-specific ABIs, and toolchain-specific ABIs. This 6 | document describes ABI features intended to be common across all ABIs. 7 | 8 | ## The `_initialize` function 9 | 10 | If a module exports a function named `_initialize` with no arguments and no 11 | return values, and does not export a function named `_start`, the toolchain 12 | that produced my assume that on any instance of the module, this `_initialize` 13 | function is called before any other exports are accessed. 14 | 15 | This is intended to support language features such as C++ static constructors, 16 | as well as "top-level scripts" in many scripting languages, which can't use 17 | the [wasm start function] because they may call imports that need to access 18 | the module's exports. In use cases that don't need this, the wasm start 19 | function should be used. 20 | 21 | [wasm start section]: https://webassembly.github.io/spec/core/syntax/modules.html#syntax-start 22 | -------------------------------------------------------------------------------- /BuildId.md: -------------------------------------------------------------------------------- 1 | # Build ID 2 | 3 | A Build ID (or debug info ID) is a value that uniquely identifies a build. It 4 | is intended to capture the "meaning" or inputs of the build, and is usually 5 | associated with debug info. So for example, programs compiled from different 6 | sources would have different build IDs, even if their generated code happened to 7 | be the same. A common use case is when a build is created with debug info, and 8 | then the debug info is stripped before distribution and archived by the 9 | developer. If both the distributed and archived version retain the build ID, 10 | then they can be matched, and the distributed version can be debugged or 11 | symbolized. 12 | 13 | Because the build ID is usually intended to identify debug info, tools that 14 | transform Wasm binaries will need to decide whether they will preserve, drop, or 15 | recompute the build ID. Generally speaking, if a transformation would invalidate 16 | debug info (for example, by rewriting the code section and changing the code 17 | offsets), then the tool should drop or recompute the build ID. If a tool updates 18 | or regenerates debug info along with its transformation, it should also 19 | generally update the build ID, since the debug info no longer 20 | matches. Conversely, adding custom sections to a binary would generally not 21 | require updating the build ID. 22 | 23 | ## Build ID Section 24 | The Build ID section is a [custom section](https://webassembly.github.io/spec/core/binary/modules.html#custom-section) 25 | and thus has no semantic effects and can be stripped at any time. It is named 26 | `build_id` and has no restriction on where in the binary it can appear. It 27 | consists of only 2 fields: 28 | 29 | | Field | Type | Description | 30 | | ----------- | ----------- | ----------- | 31 | | length | `varuint32` | number of bytes that follow | 32 | | id | `bytes` | sequence of bytes | 33 | 34 | Unlike most "string" fields in wasm binaries, the `id` field is arbitrary binary 35 | data and is not required to be valid UTF-8. 36 | 37 | ## Implementation Notes 38 | The exact size and method of generating the build ID is unspecified, other than 39 | that it should be unique. LLVM lld supports several different methods, including 40 | a hash (which includes at least all the code, data, and debug info sections of 41 | the output), a random (v4) UUID, and user-specified values. The default is to 42 | hash the output and create from it a name-based (v5) UUID, which is 43 | deterministic for a given set of inputs. 44 | -------------------------------------------------------------------------------- /CodeMetadata.md: -------------------------------------------------------------------------------- 1 | # Code Metadata Framework 2 | 3 | This document describe a convention for encoding a number of WebAssembly features (here generically called "code metadata") that don't affect the module semantics. 4 | The goal of this convention is to make it easier for tools that work on WebAssembly modules to handle and preserve such metadata. 5 | 6 | Note: This is a work in progress 7 | 8 | ## Code Metadata 9 | 10 | Each type of Code Metadata is identified by a name: `metadata.code.`. 11 | 12 | An instance of Code Metadata is defined by its type, a position in the code section, 13 | and a payload. 14 | 15 | The payload is a byte string, whose meaning depends on the type. 16 | 17 | Removing Code Metadata from a module does not change its semantics. 18 | 19 | A tool that transforms the module must drop any Code Metadata that it does not know, or knows it can’t preserve. 20 | 21 | ## Binary Representation 22 | 23 | Each type of Code Metadata is encoded in a custom section named `metadata.code.`. 24 | 25 | Such sections have the following binary format: 26 | 27 | ``` 28 | codemetadatasec(A) ::= section_0(codemetadatacontent(A)) 29 | 30 | codemetadatacontent(A) ::= n:name (if n = 'metadata.code.A') 31 | vec(codemetadatafunc(A)) 32 | 33 | codemetadatafunc(A) ::= idx: funcidx 34 | vec(codemetadatainstance(A)) 35 | 36 | codemetadatainstance(A) ::= funcpos: u32 37 | size: u32 (if size = ||A||) 38 | data: A 39 | ``` 40 | 41 | Where `funcpos` is the byte offset of the annotation starting from the beginning of the function body, and `data` is a further payload, whose content depends on the section type `A`. 42 | 43 | `codemetadatafunc` entries must appear in order of increasing `idx`, and duplicate `idx` values are not allowed. 44 | `codemetadatainstance` entries must appear in order of increasing `funcpos`, and duplicate `funcpos` values are not allowed. 45 | 46 | ## Text Representation 47 | 48 | Code Metadata are represented in the .wat format using [custom annotations](https://github.com/WebAssembly/annotations), as follows: 49 | 50 | ``` 51 | (@metadata.code. data:str) 52 | ``` 53 | The `data` fields correspond to the field with the same name in the binary representation. 54 | The code position is implicit and it is derived by the position of the annotation: 55 | 56 | Custom annotations can appear anywhere , but **Code Metadata annotations** are allowed only in function definitions (in which case the code position is the offset of the start of the function body in the code section), or before an instruction (in which case the code position is the byte offset of the instruction relative to the beginning of the function body). 57 | 58 | Example: 59 | 60 | ``` 61 | (module 62 | (type (;0;) (func (param i32 result i32))) 63 | (func (@metadata.code.hotness "\01") $test (type 0) 64 | (@metadata.code.branch_hint "\00") if 65 | i32.const 0 66 | local.set 0 67 | end 68 | local.get 1 69 | (@metadata.code.custom "aaa\13bb") return 70 | ) 71 | ) 72 | ``` 73 | 74 | ## Code Metadata well-known types 75 | 76 | Currently the following type of Code Metadata are defined: 77 | 78 | ### Branch Hints 79 | 80 | - section name: `metadata.code.branch_hint` 81 | - binary format: 82 | 83 | ``` 84 | codemetadatainstance(branch_hint) ::= funcpos: u32 85 | size: 0x01 86 | data: branchhint 87 | branch_hint ::= unlikely | likely 88 | unlikely ::= 0x00 89 | likely ::= 0x01 90 | ``` 91 | 92 | Branch hints can appear only before a `if` or `br_if` instruction, and are considered attached to it. 93 | Code transformations that remove the instruction should remove the associated instance, and transformations that flip the direction of the branch should preserve the hint but flip the hint. 94 | 95 | ## Trace Instruction 96 | 97 | - section name: metadata.code.trace_inst 98 | - binary format: 99 | 100 | ``` 101 | codemetadatainstance(trace_inst) ::= funcpos: u32 102 | size: u32v 103 | data: mark_id 104 | mark_id ::= u32 105 | ``` 106 | 107 | Trace marks can appear on any instruction and are considered attached to the instruction. If a code transformation reorders the instruction, the trace mark should move with it. If a code transformation removes the instruction, the trace mark should be removed. 108 | -------------------------------------------------------------------------------- /Coredump.md: -------------------------------------------------------------------------------- 1 | This document describes the usage of coredump for post-mortem debugging with 2 | WebAssembly. 3 | 4 | # Idea 5 | 6 | When WebAssembly enters a trap, it starts unwinding and collects debugging 7 | information. For each stack frame, collect the values in locals (includes 8 | function parameters) and on the stack. Along with binary offsets to resolve to 9 | source file locations. Finally, make a snapshot of the linear memory (or 10 | multiple linear memories when the [multi-memory] feature is used), tables and 11 | globals. 12 | 13 | All this information is saved to the file, called the coredump file. 14 | 15 | The post mortem analysis is done using the coredump and [DWARF] information. 16 | Similar to the debugging flow with [gdb]. 17 | 18 | # Implementation status 19 | 20 | Stability of this specification is **experimental**. 21 | 22 | Tools that support the generation of Wasm coredumps: 23 | - [wasm-edit] 24 | - [Wasmtime] 25 | 26 | Debugger that supports post-mortem debugging with Wasm coredumps: 27 | - [wasmgdb] 28 | 29 | ## Runtime support 30 | 31 | Most of the WebAssembly runtimes are already able to present a useful stacktrace 32 | on crash to the user. When they are configured to emit a coredump, they collect 33 | the debugging information and write a coredump file. 34 | 35 | An example output: 36 | 37 | ``` 38 | $ my-wasm-runtime module.wasm 39 | 40 | Exit 1: Uncaught RuntimeError: memory access out of bounds (core dumped). 41 | ``` 42 | 43 | A coredump file has been generated. 44 | 45 | For experimenting, runtime support is not strictly necessary. A tool can 46 | transform the Wasm binary to inject code that will manually unwind the stack and 47 | collect debugging information, for instance [wasm-edit coredump]. Such a 48 | transformation has important limitations; a trap caused by an invalid memory 49 | operation or exception in a host function might not be caught. 50 | 51 | ## Security and privacy considerations 52 | 53 | Using the WebAssembly linear memory for debugging exposes the risk of seeing, 54 | manipulating and/or collecting sensitive informations. 55 | 56 | For the user of Wasm coredumps, there's no particular security or privacy 57 | considerations. 58 | 59 | ## Debugger support 60 | 61 | [gdb] doesn't support Wasm coredump and it's unclear if it can. Wasm coredump 62 | differ from ELF coredump in a few significant ways: 63 | - Wasm semantics; usage of locals, globals and the stack. 64 | - The process image is only the Wasm linear memory. 65 | - etc. 66 | 67 | For experimenting, a custom tool has been built and mimics [gdb]: [wasmgdb]. 68 | 69 | It seems possible for Chrome's Wasm debugger extension to support Wasm 70 | coredumps. Challenges for coredumps in the web context would be to collect the 71 | instance's state as tools like emscripten (and of course most of a larger web 72 | app's state) are in JS rather than Wasm. 73 | 74 | # Coredump file format 75 | 76 | The coredump file is encoded using the [Wasm binary format], containing: 77 | - general information about the process. 78 | - the threads and stack frames. 79 | - a snapshot of the WebAssembly linear memory or relevant regions. 80 | 81 | The order in which they appear in the file is not important. 82 | 83 | As opposed to regular Wasm files, Wasm Coredumps are not [instantiated]. 84 | 85 | `u32` are encoded using [Wasm u32]. 86 | 87 | ## Process information 88 | 89 | General information about the process is stored in a [Custom section], called 90 | `core`. 91 | 92 | This custom section must only appear once in the coredump file. 93 | 94 | ``` 95 | core ::= customsec(process-info) 96 | process-info ::= 0x0 executable-name:name 97 | ``` 98 | 99 | ## Module information 100 | 101 | Information about the modules present in the coredump are stored in a [Custom 102 | section] called `coremodules`. 103 | 104 | This custom section must only appear once in the coredump file. 105 | 106 | This custom section establishes an index space of modules that can be referenced 107 | in the `coreinstances` custom section (see below). 108 | 109 | ``` 110 | coremodules ::= customsec(vec(coremodule)) 111 | coremodule ::= 0x0 module-name:name 112 | ``` 113 | 114 | The `module-name` may be a URL, file path, or other identifier for the module. 115 | 116 | ## Instance information 117 | 118 | Information about the instances present in the coredump are stored in a [Custom 119 | section] called `coreinstances`. 120 | 121 | This custom section must only appear once in the coredump file. 122 | 123 | This custom section establishes an index space of instances that can be 124 | referenced in `frame` productions within the `corestack` custom section (see 125 | below). 126 | 127 | ``` 128 | coreinstances ::= customsec(vec(coreinstance)) 129 | coreinstance ::= 0x0 moduleidx:u32 memories:vec(u32) globals:vec(u32) 130 | ``` 131 | 132 | Each `coreinstance` specifies: 133 | 134 | * Which module this is an instance of, via indexing into the `coremodules` index 135 | space. 136 | 137 | * Which of the coredump's memories are this instance's memories, via indexing 138 | into the memory index space. Memories are listed in instance order: the `i`th 139 | entry in `coreinstance::memories` is the coredump memory index of this 140 | instance's `i`th memory. 141 | 142 | * Which of the coredump's globals are this instance's globals, via indexing into 143 | the global index space. Globals are listed in instance order: the `i`th entry 144 | in `coreinstance::globals` is the coredump global index of this instance's 145 | `i`th global. 146 | 147 | ## Thread(s) and stack frames 148 | 149 | For each thread a [Custom section], called `corestack`, is used to store the 150 | debugging information. 151 | 152 | ``` 153 | corestack ::= customsec(thread-info vec(frame)) 154 | thread-info ::= 0x0 thread-name:name 155 | frame ::= 0x0 instanceidx:u32 funcidx:u32 codeoffset:u32 locals:vec(value) 156 | stack:vec(value) 157 | ``` 158 | 159 | The frames in a `corestack` production are listed from youngest to oldest. 160 | 161 | > Example: If `f` calls `g` calls `h`, and `h` traps and the runtime creates a 162 | > coredump, then the coredump's `corestack` will list the frames in this order: 163 | > `h`, `g`, `f`. 164 | 165 | The `instanceidx` is an index into the `coreinstances` index space, describing 166 | which instance is associated with this stack frame. 167 | 168 | `funcidx` is the WebAssembly function index in the instance's module and 169 | `codeoffset` is the instruction's offset relative to the function's start. 170 | 171 | > Note: implementations may leave `codeoffset` offset empty if unknown. Setting 172 | > 0 will point to the function's start. 173 | 174 | Local and stack values are encoded using one byte for the type (similar to 175 | Wasm's [Number Types]) followed by bytes representing the actual value: 176 | ``` 177 | value ::= 0x01 => ∅ 178 | | 0x7F n:i32 => n 179 | | 0x7E n:i64 => n 180 | | 0x7D n:f32 => n 181 | | 0x7C n:f64 => n 182 | ``` 183 | 184 | The special byte `0x01` is used to represent a missing value, usually because it 185 | was optimized out by the WebAssembly engine. 186 | 187 | ## Memory 188 | 189 | Each instance's memory is captured in the [Memory Section] and [Data Section]. 190 | 191 | To determine which memory is associated with which instance(s), you can use the 192 | mapping defined in `coreinstances`. 193 | 194 | > Note: A single memory may be associated with multiple instances if it is, for 195 | > example, defined and exported by one instance and imported by another. 196 | 197 | > Note: A memory's data may be captured either entirely as one active data 198 | > segment, or as multiple data segments. The latter can be used as a space 199 | > saving mechanism to avoid long runs of zeroes or it can be used to represent 200 | > partial coredumps. 201 | 202 | ## Globals 203 | 204 | Globals are captured in the [Global Section] as constant, non-mutable globals. 205 | 206 | To determine which global is associated with which instance(s), you can use the 207 | mapping defined in `coreinstances`. 208 | 209 | > Note: A single global may be associated with multiple instances if it is, for 210 | > example, defined and exported by one instance and imported by another. 211 | 212 | # Demo 213 | 214 | Please have a look at the demonstration using the experimental support and 215 | tooling: [demo]. 216 | 217 | # Useful links 218 | 219 | - [ELF coredump] 220 | - [Wasmer FrameInfo] 221 | 222 | [Wasm Vectors]: https://webassembly.github.io/spec/core/binary/conventions.html#binary-vec 223 | [ELF coredump]: https://www.gabriel.urdhr.fr/2015/05/29/core-file/ 224 | [Core dump on Wikipedia]: https://en.wikipedia.org/wiki/Core_dump 225 | [gdb]: https://linux.die.net/man/1/gdb 226 | [wasm-edit coredump]: https://github.com/xtuc/wasm-coredump/blob/main/bin/rewriter/src/rewriter.rs 227 | [wasm-edit]: https://github.com/xtuc/wasm-coredump/tree/main/bin/rewriter 228 | [wasmgdb]: https://github.com/xtuc/wasm-coredump/tree/main/bin/wasmgdb 229 | [DWARF]: https://yurydelendik.github.io/webassembly-dwarf 230 | [Wasmer FrameInfo]: https://docs.rs/wasmer/latest/wasmer/struct.FrameInfo.html 231 | [Wasm u32]: https://webassembly.github.io/spec/core/binary/values.html#binary-int 232 | [demo]: https://github.com/xtuc/wasm-coredump/blob/main/bin/wasmgdb/demo.md 233 | [multi-memory]: https://github.com/WebAssembly/multi-memory 234 | [Wasm binary format]: https://webassembly.github.io/spec/core/binary/index.html 235 | [Data Section]: https://webassembly.github.io/spec/core/binary/modules.html#data-section 236 | [Custom section]: https://webassembly.github.io/spec/core/binary/modules.html#binary-customsec 237 | [Memory Section]: https://webassembly.github.io/spec/core/binary/modules.html#binary-memsec 238 | [instantiated]: https://webassembly.github.io/spec/core/exec/modules.html#instantiation 239 | [Global Section]: https://webassembly.github.io/spec/core/binary/modules.html#binary-globalsec 240 | [Number Types]: https://webassembly.github.io/spec/core/binary/types.html#binary-numtype 241 | [Wasmtime]: https://wasmtime.dev 242 | -------------------------------------------------------------------------------- /Debugging.md: -------------------------------------------------------------------------------- 1 | This document describes conventions regarding debugging. 2 | 3 | # DWARF 4 | 5 | It is a goal to support DWARF in WebAssembly, see 6 | [the proposed additions to DWARF](https://yurydelendik.github.io/webassembly-dwarf/) 7 | for how that is planned to work. 8 | 9 | ## Embedded DWARF 10 | 11 | The proposal allows [embedding the DWARF sections](https://yurydelendik.github.io/webassembly-dwarf/#embedding-DWARF) 12 | as WebAssembly custom sections with the same name (`.debug_*`) and raw data as in the DWARF spec. 13 | 14 | ## External DWARF 15 | 16 | The proposal also allows keeping the DWARF information 17 | [external to the Wasm](https://yurydelendik.github.io/webassembly-dwarf/#external-DWARF). 18 | When doing so, the main Wasm file does not need to contain any debug info, and 19 | instead has a custom section with the name `external_debug_info`. That section 20 | contains: 21 | 22 | | Field | Type | Description | 23 | | ------------ | ----------- | --------------------------------- | 24 | | url_name_len | `varuint32` | Length of `url_name_str` in bytes | 25 | | url_name_str | `bytes` | URL to debug info file | 26 | 27 | `url_name` is the location of a file containing DWARF debug info. That file is 28 | a Wasm container, which includes DWARF in Wasm custom sections, in the same 29 | format as they would appear normally in a Wasm file. Note that the container may 30 | also contain other sections, such as the code and data sections in the original 31 | Wasm file. 32 | 33 | # Source maps 34 | 35 | Adoption of DWARF is a fairly recent addition to WebAssembly, and many toolchains still 36 | support [Source Map](https://sourcemaps.info/spec.html) based debugging as well (or instead). 37 | 38 | Source map is an external JSON file that specifies how to map a (zero-based) line and column 39 | position in generated code to a file, line, and column location in the source. For 40 | WebAssembly binary locations, the line number is always 1, and the column number 41 | is interpreted as a byte offset into the WebAssembly binary content. 42 | Source locations are interpreted as in the source map spec. 43 | 44 | On the WebAssembly side, the URL of such Source Map file is stored in a custom section with the name 45 | `sourceMappingURL`. That section contains: 46 | 47 | | Field | Type | Description | 48 | | ------------ | ----------- | --------------------------------- | 49 | | url_name_len | `varuint32` | Length of `url_name_str` in bytes | 50 | | url_name_str | `bytes` | URL to the Source Map file | 51 | -------------------------------------------------------------------------------- /DynamicLinking.md: -------------------------------------------------------------------------------- 1 | WebAssembly Dynamic Linking 2 | =========================== 3 | 4 | This document describes the current WebAssembly dynamic linking ABI used by 5 | emscripten and by the llvm backend when targeting emscripten. 6 | 7 | Note: This ABI is still a work in progress. There is no stable ABI yet. 8 | 9 | # Dynamic Libraries 10 | 11 | A WebAssembly dynamic library is a WebAssembly binary with a special custom 12 | section that indicates this is a dynamic library and contains additional 13 | information needed by the loader. 14 | 15 | ## The "dylink.0" Section 16 | 17 | The "dylink.0" is a custom section, the existence of which signals that the 18 | module conforms the dynaminc linking ABI described in this document. This 19 | section is expected to be the very first section in the module. 20 | 21 | A "dylink.0" consists of a series of sub-sections using the same format as found 22 | in the ["names"][names_sec] section: 23 | 24 | | Field | Type | Description | 25 | | ----------- | ------------- | ------------------------------------ | 26 | | subsections | `subsection*` | sequence of `subsection` | 27 | 28 | Each `subsection` is encoded as: 29 | 30 | | Field | Type | Description | 31 | | ------------ | ----------- | ------------------------------------ | 32 | | type | `uint8` | code identifying type of subsection | 33 | | payload_len | `varuint32` | size of this subsection in bytes | 34 | | payload_data | `bytes` | content of this subsection, of length `payload_len` | 35 | 36 | The current list of valid `type` codes are: 37 | 38 | - `1 / WASM_DYLINK_MEM_INFO` - Specifies the memory and table space requirements of the module 39 | 40 | - `2 / WASM_DYLINK_NEEDED` - Specifies external modules that this one depends on. 41 | 42 | - `3 / WASM_DYLINK_EXPORT_INFO` - Specify additional metadata about exports. 43 | 44 | - `4 / WASM_DYLINK_IMPORT_INFO` - Specify additional metadata about imports. 45 | 46 | - `5 / WASM_DYLINK_RUNTIME_PATH` - Specify the runtime path, corresponding to `DT_RUNPATH` in an ELF `.dynamic` section. 47 | 48 | For `WASM_DYLINK_MEM_INFO` the following fields are present in the 49 | subsection: 50 | 51 | | Field | Type | Description | 52 | | ---------------------- | --------------- | ------------------------------ | 53 | | memorysize | `varuint32` | Size of the memory area the loader should reserve for the module, which will begin at `env.__memory_base` | 54 | | memoryalignment | `varuint32` | The required alignment of the memory area, in bytes, encoded as a power of 2. | 55 | | tablesize | `varuint32` | Size of the table area the loader should reserve for the module, which will begin at `env.__table_base` | 56 | | tablealignment | `varuint32` | The required alignment of the table area, in elements, encoded as a power of 2. | 57 | 58 | For `WASM_DYLINK_NEEDED` the following fields are present in the 59 | subsection: 60 | 61 | | Field | Type | Description | 62 | | ---------------------- | --------------- | ------------------------------ | 63 | | needed_dynlibs_count | `varuint32` | Number of needed shared libraries | 64 | | needed_dynlibs_entries | `string*` | Repeated string names of dynamic libraries | 65 | 66 | The "string" type is defined as: 67 | 68 | | Field | Type | Description | 69 | | -------------- | ----------- | ----------------------------------- | 70 | | string_len | `varuint32` | Length of `string_payload` in bytes | 71 | | string_payload | `bytes` | valid UTF-8 byte sequence | 72 | 73 | `env.__memory_base` and `env.__table_base` are `i32` imports that contain 74 | offsets into the linked memory and table, respectively. If the dynamic library 75 | has `memorysize > 0` then the loader will reserve room in memory of that size 76 | and initialize it to zero (note: can be larger than the memory segments in the 77 | module, if the dynamic library wants additional space) at offset 78 | `env.__memory_base`, and similarly for the table (where initialization is to 79 | `null`, i.e., a trap will occur if it is called). The allocated regions of the 80 | table and memory are guaranteed to be at least as aligned as the library 81 | requests in the `memoryalignment` and `tablealignment` properties. The library 82 | can then place memory and table segments at the proper locations using those 83 | imports. 84 | 85 | If `needed_dynlibs_count > 0` then the loader, before loading the library, will 86 | first load needed libraries specified by `needed_dynlibs_entries`. 87 | 88 | For `WASM_DYLINK_EXPORT_INFO` the following fields are present in the 89 | subsection: 90 | 91 | | Field | Type | Description | 92 | | ------------------- | --------------- | --------------------- | 93 | | export_info_count | `varuint32` | Number of export info | 94 | | export_info_entries | `export_info*` | Repeated export info | 95 | 96 | The "export_info" type is defined as: 97 | 98 | | Field | Type | Description | 99 | | ----- | ----------- | ---------------------------------------- | 100 | | name | `string` | The name of the export | 101 | | flags | `varuint32` | Symbol flags for the export | 102 | 103 | For `WASM_DYLINK_IMPORT_INFO` the following fields are present in the 104 | subsection: 105 | 106 | | Field | Type | Description | 107 | | ------------------- | --------------- | --------------------- | 108 | | import_info_count | `varuint32` | Number of import info | 109 | | import_info_entries | `import_info*` | Repeated import info | 110 | 111 | The "import_info" type is defined as: 112 | 113 | | Field | Type | Description | 114 | | -------| ----------- | ---------------------------------------- | 115 | | module | `string` | The module name of the import | 116 | | field | `string` | The field name of the import | 117 | | flags | `varuint32` | Symbol flags for the export | 118 | 119 | The set of possible symbol flags are the same as those specified in 120 | [Linking](Linking.md). 121 | 122 | For `WASM_DYLINK_RUNTIME_PATH` the following fields are present in the 123 | subsection: 124 | 125 | | Field | Type | Description | 126 | | ---------------------- | --------------- | ------------------------------------- | 127 | | runtime_path_count | `varuint32` | Number of runtime_path entries | 128 | | runtime_path_entries | `string*` | string values of runtime_path entries | 129 | 130 | The "dylink" section should be the very first section in the module; this allows 131 | detection of whether a binary is a dynamic library without having to scan the 132 | entire contents. 133 | 134 | [names_sec]: https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md#name-section 135 | 136 | ## Interface and usage 137 | 138 | A WebAssembly dynamic library must obey certain conventions. In addition to 139 | the `dylink` section described above a module may import the following globals 140 | that will be provided by the dynamic loader: 141 | 142 | * `env.memory` - A wasm memory that is shared between all wasm modules that 143 | make up the program. 144 | * `env.__indirect_function_table` - A wasm table that is shared between all 145 | wasm modules that make up the program. 146 | * `env.__stack_pointer` - A mutable `i32` global representing the explicit 147 | stack pointer as an offset into the above memory. 148 | * `env.__memory_base` - An immutable `i32` global representing the offset in 149 | the above memory which has been reserved and zero-initialized for this 150 | module, as described earlier. The module can use this global in the 151 | initializer of its data segments so that they loaded at the correct address. 152 | * `env.__table_base` - An immutable `i32` global representing the offset in the 153 | above table which has been reserved for this module, as described earlier. 154 | The module can use this global in the intializer of its table element 155 | segments so that they loaded at the correct offset. 156 | 157 | ### Relocations 158 | 159 | WebAssembly dynamic libraries do not require relocations in the code section. 160 | This allows for streaming compilation and better code sharing, and reduces the 161 | complexity of the dynamic linker. For external symbols this is achieved by 162 | referencing WebAssembly imports. For internal symbols we introduce two new 163 | relocation types for accessing data and functions address relative to 164 | `__memory_base` and `__table_base` global: 165 | 166 | - `11 / R_WASM_MEMORY_ADDR_REL_SLEB,` - a memory address relative to the 167 | `__memory_base` wasm global. Used in position independent code (`-fPIC`) 168 | where absolute memory addresses are not known at link time. 169 | - `12 / R_WASM_TABLE_INDEX_REL_SLEB` - a function address (table index) 170 | relative to the `__table_base` wasm global. Used in position indepenent code 171 | (`-fPIC`) where absolute function addresses are not known at link time. 172 | - `17 / R_WASM_MEMORY_ADDR_REL_SLEB64` - the 64-bit counterpart of 173 | `R_WASM_MEMORY_ADDR_REL_SLEB`. 174 | - `21 / R_WASM_MEMORY_ADDR_TLS_SLEB` (in LLVM 12.0) - an offset from the 175 | `__tls_base` symbol encoded as a 5-byte [varint32]. Used for PIC case to avoid 176 | absolute relocation. 177 | - `25 / R_WASM_MEMORY_ADDR_TLS_SLEB64` (in LLVM 13.0) - the 64-bit counterpart 178 | of `R_WASM_MEMORY_ADDR_TLS_SLEB`. 179 | 180 | All code that gets linked into a WebAssembly dynamic library must be compiled 181 | as position independent. The corresponding absolute relocation types 182 | (R_WASM_MEMORY_ADDR_SLEB and R_WASM_TABLE_INDEX_SLEB) are not permitted in 183 | position independent code and will be rejected at link time. 184 | 185 | For relocation within the data segments a runtime fixup may be required. For 186 | example, if the address of an external symbol is stored in global data. In this 187 | case the dynamic library must generate code to apply these relocations at 188 | startup. The module can export a function called `__wasm_apply_data_relocs`. 189 | If it is so exported, the loader will call it after the module is instantiated, 190 | and before any other function, including `__wasm_call_ctors`, is called. 191 | 192 | ### Imports 193 | 194 | Functions are directly imported from the `env` module (e.g. 195 | `env.enternal_func`). Data addresses and function addresses are imported as 196 | WebAssembly globals that store the memory offset or table offset of the symbol. 197 | Such address are imported from `GOT.mem` and `GOT.func` respectively. The `GOT` 198 | prefix is borrowed from the ELF linking world and stands for "Global Offset 199 | Table". In WebAssembly the GOT is modeled as a set of imported wasm globals. 200 | 201 | For example, a dynamic library might import and use an external data symbol as 202 | follows: 203 | 204 | ```wasm 205 | (import "GOT.mem" "foo" (global $foo_addr (mut i32)) 206 | ... 207 | ... 208 | get_global $foo_addr 209 | i32.load 210 | ``` 211 | 212 | And an external function symbol as follows: 213 | 214 | ```wasm 215 | (import "GOT.func" "bar" (global $bar_addr (mut i32))) 216 | ... 217 | ... 218 | get_global $bar_addr 219 | call_indirect 220 | ``` 221 | 222 | Note: This has no effect on exports, or the import of functions for direct call. 223 | 224 | The imported global must be mutable as the dynamic linker might need to 225 | modify the value after instantiation. 226 | 227 | ### Text format of `dylink.0` 228 | 229 | The text format for the `dylink.0` custom section uses [annotations proposal] 230 | extension to the WebAssembly text format. The text format looks like: 231 | 232 | [annotations proposal]: https://github.com/WebAssembly/annotations 233 | 234 | ```wasm 235 | (module $libc.so 236 | (@dylink.0 237 | (mem-info (memory 208392 4) (table 31 0)) 238 | (import-info "env" "__main_argc_argv" binding-weak undefined) 239 | ) 240 | ) 241 | ``` 242 | 243 | or 244 | 245 | ``` 246 | (module $libbar.so 247 | (@dylink.0 248 | (needed "libfoo.so" "libc.so") 249 | (export-info "my_tls_variable_1" tls) 250 | (export-info "my_tls_variable_2" tls) 251 | ) 252 | ) 253 | ``` 254 | 255 | The `(@dylink.0 ...)` structure must be placed directly within a `(module 256 | ...)` declaration and must be placed at the beginning of the module. Within 257 | `@dylink.0` there is a list of four possible parenthesis-delimited fields that 258 | correspond to the subsections within `dylink.0`: 259 | 260 | * `(mem-info ...)` 261 | * `(needed ...)` 262 | * `(export-info ...)` 263 | * `(import-info ...)` 264 | 265 | The `dylink.0` subsections are emitted in the same order they're listed within 266 | the `@dylink.0` annotation. The `export-info` and `import-info` subsections 267 | concatenate adjacent entries into one subsection. 268 | 269 | ```wasm 270 | (module 271 | (@dylink.0 272 | ;; these two symbols are concatenated into one subsection 273 | (export-info "a" tls) 274 | (export-info "b" tls) 275 | 276 | ;; this generates a second subsection 277 | (import-info "env" "c" binding-weak undefined) 278 | ) 279 | ) 280 | ``` 281 | 282 | would produce two subsections where the first one has type 283 | `WASM_DYLINK_EXPORT_INFO` with two symbols. 284 | 285 | **`mem-info`** 286 | 287 | The `mem-info` section optionally contains `(memory ..)` and `(table ..)` 288 | entries. These correspond to the memory size/alignment and table size/alignment. 289 | If not specified the defaults are 0. 290 | 291 | For example: 292 | 293 | ```wasm 294 | (module 295 | (@dylink.0 296 | (mem-info (memory 100 1)) ;; 100-byte memory with 1-byte alignment 297 | ;; 0-entry table with 0 alignment 298 | 299 | (mem-info (table 10 2)) ;; 0-byte memory with 0-byte alignment 300 | ;; 10-entry table with 2 alignment 301 | 302 | (mem-info 303 | (memory 100 1) 304 | (table 10 2)) 305 | ) 306 | ) 307 | ``` 308 | 309 | **`needed`** 310 | 311 | The `needed` section contains a list of strings which are the needed modules 312 | present in `WASM_DYLINK_NEEDED`: 313 | 314 | ```wasm 315 | (module 316 | (@dylink.0 317 | (needed "libfoo.so" "libbar.so") 318 | ) 319 | ) 320 | ``` 321 | 322 | ** `runtime-path` ** 323 | 324 | The `runtime-path` contains a list of paths. The loader should look in these 325 | directories to locate `needed` dependencies that do not contain a slash in their 326 | name. 327 | 328 | Dynamic string tokens: The loader should expand certain string tokens appearing 329 | in the `runtime-path`. The tokens are as follows: 330 | 331 | * `$ORIGIN` and `${ORIGIN}` -- these expand to the directory containing the 332 | shared object. 333 | 334 | **`export-info` / `import-info`** 335 | 336 | The `export-info` and `import-info` constructs correspond to 337 | `WASM_DYLINK_EXPORT_INFO` and `WASM_DYLINK_IMPORT_INFO`. Each structure 338 | specifies information on a single symbol. After the symbol is a list of flags or 339 | integer values for flags. For example: 340 | 341 | ```wasm 342 | (module 343 | (@dylink.0 344 | (import-info "env" "__main_argc_argv" binding-weak undefined) 345 | (export-info "my_tls_variable_1" tls) 346 | ) 347 | ) 348 | ``` 349 | 350 | Supported flags are: 351 | 352 | * `binding-weak` - `WASM_SYM_BINDING_WEAK` 353 | * `binding-local` - `WASM_SYM_BINDING_LOCAL` 354 | * `visibility-hidden` - `WASM_SYM_VISIBILITY_HIDDEN` 355 | * `undefined` - `WASM_SYM_UNDEFINED` 356 | * `exported` - `WASM_SYM_EXPORTED` 357 | * `explicit-name` - `WASM_SYM_EXPLICIT_NAME` 358 | * `no-strip` - `WASM_SYM_NO_STRIP` 359 | * `tls` - `WASM_SYM_TLS` 360 | * `absolute` - `WASM_SYM_ABSOLUTE` 361 | 362 | Flags can also be specified with an integer literal and the integer literal may 363 | have more than one bit set as well. Note that many of these flags aren't used in 364 | `dylink.0` but instead are used as part of the `linking` section, the current 365 | implementation in `wasm-ld` of emitting `dylink.0` only uses `import-info` for 366 | `binding-weak` symbols and `export-info` for `tls` symbols. 367 | 368 | ### Exports 369 | 370 | Functions are directly exported as WebAssembly function exports. Exported 371 | addresses (i.e., exported memory locations or exported table locations) are 372 | exported as i32 WebAssembly globals. However since exports are static, modules 373 | connect export the final relocated addresses (i.e. they cannot add 374 | `__memory_base` before exporting). Thus, the exported address is before 375 | relocation; the loader, which knows `__memory_base`, can then calculate the 376 | final relocated address. 377 | 378 | ### Note for memory/table exports 379 | 380 | The commonly used C conventions including WASIp1 require modules to 381 | export the `memory` memory and the `__indirect_function_table` table. 382 | 383 | However, because PIE executables with this dynamic-linking convention 384 | are already importing these instance resources, it's redundant to 385 | export them as well. For that reason, for PIE executables, we don't 386 | require these resources exported. 387 | 388 | Shared libraries don't need to export these resources either. 389 | Instead, they should import these resources, since they share the memory 390 | and function table with the main module. (The runtime linkers 391 | can validate if it's actually the case and reject loading modules 392 | otherwise.) 393 | 394 | On the other hand, non-PIE executables need to export these instance 395 | resources as usual. 396 | 397 | ## Implementation Status 398 | 399 | ### LLVM Implementation 400 | 401 | When llvm is run with `--relocation-model=pic` (a.k.a `-fPIC`) it will generate 402 | code that accesses non-DSO-local addresses via the `GOT.mem` and `GOT.func` 403 | entries. Such code must then be linked with either `-shared` to produce a 404 | shared library or `-pie` to produced a dynamically linked executable. 405 | 406 | ### WASI-SDK 407 | 408 | [WASI-SDK] 21.0 and later ships shared builds of its libraries including libc. 409 | 410 | Note: You might need 411 | `-Xlinker --export-if-defined=__main_argc_argv` to workaround 412 | a [wasi-libc bug]. 413 | 414 | [WASI-SDK]: https://github.com/WebAssembly/wasi-sdk 415 | 416 | [wasi-libc bug]: https://github.com/WebAssembly/wasi-libc/issues/485 417 | 418 | Note: WASI-SDK 25.0 ships an LLVM version with 419 | [an issue for non-PIE executable]. 420 | 421 | [an issue for non-PIE executable]: https://github.com/llvm/llvm-project/issues/107387 422 | 423 | ### Emscripten 424 | 425 | Emscripten can load WebAssembly dynamic libraries either at startup (using 426 | `RUNTIME_LINKED_LIBS`) or dynamically (using `dlopen`/`dlsym`/etc). 427 | See `test_dylink_*` and `test_dlfcn_*` in the test suite for examples. 428 | 429 | Emscripten can create WebAssembly dynamic libraries with its `SIDE_MODULE` 430 | option, see [the wiki](https://github.com/kripken/emscripten/wiki/WebAssembly-Standalone). 431 | 432 | ### toywasm 433 | 434 | Toywasm's [libdyld] library implements dynamic linking. 435 | It supports both of PIE and non-PIE executables. 436 | It also provides dlopen-like host functions. 437 | 438 | [libdyld]: https://github.com/yamt/toywasm/tree/master/libdyld 439 | -------------------------------------------------------------------------------- /EHScheme.md: -------------------------------------------------------------------------------- 1 | # WebAssembly Exception Handling Scheme 2 | 3 | This document describes the plans for a new exception handling scheme for 4 | WebAssembly, regarding what each tool components does and how they interact with 5 | each other to implement the scheme. 6 | 7 | Here we describe a new exception handling scheme for WebAssembly for the 8 | toolchain side to generate compatible wasm binary files to support the 9 | aforementioned [WebAssembly exception handling proposal][eh_proposal]. 10 | 11 | We use [the exception IR designed for Windows EH][llvm_win_eh] for the Wasm IR 12 | because of its well-defined EH pad scopes and hierarchies between them, we 13 | use [the Itanium EH ABI][itanium_abi] for the communication between user code 14 | and libraries. 15 | 16 | --- 17 | 18 | ## Background 19 | 20 | ### WebAssembly try-catch Blocks 21 | 22 | WebAssembly's `try` and `catch` instructions are structured as follows: 23 | ``` 24 | try 25 | instruction* 26 | catch (C++ tag) 27 | instruction* 28 | catch (Another language's tag) 29 | instruction* 30 | ... 31 | catch_all 32 | instruction* 33 | try_end 34 | ``` 35 | A `catch` instruction in WebAssembly does not correspond to a C++ `catch` 36 | clause. **In WebAssembly, there is a single `catch` instruction for all C++ 37 | exceptions.** `catch` instruction with tags for other languages and `catch_all` 38 | instructions are not generated for the current version of implementation. **All 39 | catch clauses for various C++ types go into this big `catch (C++ tag)` block.** 40 | Each language will have a tag number assigned to it, so you can think the C++ 41 | tag as a fixed integer here. So the structure for the prototype will look like 42 | ``` 43 | try 44 | instruction* 45 | catch (C++ tag) 46 | instruction* 47 | try_end 48 | ``` 49 | 50 | So for example, if we have this C++ code: 51 | ```cpp 52 | try { 53 | foo(); // may throw 54 | } catch (int n) { 55 | printf("int caught"); 56 | } catch (float f) { 57 | printf("float caught"); 58 | } 59 | ``` 60 | 61 | The resulting grouping of WebAssembly instructions will be, in pseudocode, like 62 | this: 63 | ``` 64 | try 65 | foo(); 66 | catch (C++ tag) 67 | if thrown exception is int 68 | printf("int caught"); 69 | else if thrown exception is float 70 | printf("float caught"); 71 | else 72 | throw exception to the caller 73 | try_end 74 | ``` 75 | 76 | When a 77 | [`throw`][eh_proposal#throwing-an-exception] 78 | instruction throws an exception within a `try` block or functions called from 79 | it, the control flow is transferred to `catch (C++ tag)` instruction, after 80 | which the thrown exception object is placed on top of WebAssembly value stack. 81 | This means, from user code's point of view, `catch` instruction returns the 82 | thrown exception object. For more information, refer to [Try-catch 83 | blocks][eh_proposal_try_catch_blocks] section in the exception proposal. 84 | 85 | 86 | ### C++ Libraries 87 | 88 | Here we only discuss C++ libraries because currenly we only support C++ 89 | exceptions, but every language that supports exceptions should have some kind of 90 | libraries that play similar roles, which we can extend to support WebAssembly 91 | exceptions once we add support for that language. 92 | 93 | Two C++ runtime libraries participate in exception handling: [C++ ABI 94 | library](https://clang.llvm.org/docs/Toolchain.html#c-abi-library) and [Unwind 95 | library](https://clang.llvm.org/docs/Toolchain.html#unwind-library). 96 | 97 | The C++ ABI library provides an implementation of the library portion of the 98 | Itanium C++ ABI, covering both the [support functionality in the main Itanium 99 | C++ ABI document][itanium_abi] and [Level II of the exception handling 100 | support][itanium_abi_cxx_abi]. References to the functions and objects in this 101 | library are implicitly generated by Clang when compiling C++ code. Broadly used 102 | implementations of this spec include LLVM's [libc++abi][llvm_libcxxabi] and GNU 103 | GCC's 104 | [libsupc++](https://github.com/gcc-mirror/gcc/tree/master/libstdc%2B%2B-v3/libsupc%2B%2B). 105 | 106 | The unwind library provides a family of `_Unwind_*` functions implementing the 107 | language-neutral stack unwinding portion of the Itanium C++ ABI ([Level 108 | I][itanium_abi_base_abi]). It is a dependency of the C++ ABI library, and 109 | sometimes is a dependency of other runtimes. GNU GCC's 110 | [libgcc_s](https://github.com/gcc-mirror/gcc/tree/master/libgcc) has an 111 | integrated unwinder. libunwind has a separate library for the unwinder and there 112 | are several implementations including [LLVM's libunwind][llvm_libunwind]. 113 | 114 | Our implementation is based on LLVM's libc++abi and libunwind. 115 | Our ports of the libraries, which contain Wasm EH specific changes, are in 116 | https://github.com/emscripten-core/emscripten/tree/main/system/lib/libcxxabi and 117 | https://github.com/emscripten-core/emscripten/tree/main/system/lib/libunwind. 118 | 119 | 120 | ## Why New Exception Handing Scheme? 121 | 122 | Currently there are several exception handling schemes supported by major 123 | compilers such as GCC or LLVM. LLVM supports four kinds of exception handling 124 | schemes: Dwarf CFI, SjLj (setjmp/longjmp), ARM (EABI), and WinEH. Then why do we 125 | need the support for a new exception handling scheme in a compiler as well as 126 | libraries supporting C++ ABI? 127 | 128 | The most distinguished aspect about WebAssembly EH that necessiates a new 129 | exception handling scheme is WebAssembly code is not allowed to inspect or 130 | modify the call stack, and cannot jump indirectly. As a result, when an 131 | exception is thrown, the stack is unwound by not the unwind library but the VM. 132 | This affects various components of WebAssembly EH that will be discussed in 133 | detail in this document. 134 | 135 | The definition of an exception handling scheme can be different when defined 136 | from a compiler's point of view and when from libraries. LLVM currently supports 137 | four exception handling schemes: Dwarf CFI, SjLj, ARMEH, and WinEH, where all of 138 | them use Itanium C++ ABI with an exception of WinEH. ARMEH resembles Dwarf CFI 139 | in many ways other than a few architectural differences. Unwind libraries 140 | implement different unwinding mechanism for many architectures, each of which 141 | can be considered as a separate scheme. We will refer to the WebAssembly 142 | exception handling scheme as WebAssembly EH in short in this document. 143 | 144 | In this document we mostly describe WebAssembly EH using comparisons with with 145 | two Itanium-based schemes: Dwarf CFI and SjLj. Even though the unwinding process 146 | itself is very different, code transformation required by compiler and the way 147 | C++ ABI library and unwind library communicate partly resemble that of SjLj 148 | exception handling scheme. 149 | 150 | --- 151 | 152 | ## Direct Personality Function Call 153 | 154 | ### Stack Unwinding and Personality Function 155 | 156 | For other schemes, stack unwinding is performed by the unwind library: for 157 | example, DWARF CFI scheme uses call frame information stored in DWARF format to 158 | access callers' frames, whereas SjLj scheme traverses in-memory chain of 159 | structures recorded for every try clause to find a matching catch site. And at 160 | every call frame with try-catch clauses, these exception handling schemes call 161 | the _personality function_ in the C++ ABI library to check if we need to stop at 162 | the call frame, in which case there is a matching catch site or cleanup actions 163 | to perform. 164 | 165 | **Unlike this process, WebAssembly unwinding process is performed by a VM, and 166 | it stops at every call frame that has `catch (C++ tag)` instruction.** From 167 | WebAssembly code's point of view, after a 168 | [`throw`][eh_proposal_throwing_an_exception] instruction within a try block 169 | throws, the control flow is magically transferred to a corresponding `catch (C++ 170 | tag)` instruction, which returns an exception object. So the unwinding process 171 | is completely hidden from WebAssembly code, which means the personality function 172 | cannot be called before control returns to the compiler-generated user code. 173 | 174 | For example, in Dwarf CFI scheme, after the personality function figures out 175 | which frame to stop, the function does three things (in SjLj scheme the 176 | personality function doesn't do the landing pad setting because it uses 177 | `longjmp`): 178 | * Sets IP to the start of a matching landing pad block (so that the unwinder 179 | will jump to this block after the personality routine returns). 180 | * Gives the address of the thrown exception object. 181 | * Gives the _selector value_ corresponding to the type of exception thrown. 182 | 183 | Can WebAssembly EH get all this information without calling a personality 184 | function? Program control flow is transferred to `catch (C++ tag)` instruction 185 | by the unwinder in a VM; WebAssembly code cannot access or modify IP. 186 | WebAssembly `catch` instruction's result is the address of a thrown object. 187 | **But we cannot get a selector without calling a personality function.** In 188 | WebAssembly EH, the personality function is _directly_ called from the 189 | compiler-generated user code rather than from the unwind library. To do that, 190 | WebAssembly compiler inserts a call to the personality function at the start of 191 | each landing pad. 192 | 193 | 194 | ### Landing Pad Code 195 | 196 | In exception handling schemes based on Itanium C++ ABI, C++ `throw` keyword is 197 | compiled into a call to [`__cxa_throw`][__cxa_throw] function, which 198 | [calls](https://github.com/emscripten-core/emscripten/blob/19607820c447a13fd8d0b7680c56148427d6e1b8/system/lib/libcxxabi/src/cxa_exception.cpp#L288-L292) 199 | `_Unwind_RaiseException` (in Dwarf CFI scheme) or `_Unwind_SjLj_RaiseException` 200 | (in SjLj scheme) to start an unwinding process. These `_Unwind_RaiseException`/ 201 | `_Unwind_SjLj_RaiseException` functions performs the actual stack unwinding 202 | process and calls the personality function for each eligible call frame. You can 203 | see libcxxabi's personality function implementation 204 | [here][__gxx_personality_wasm0]. 205 | 206 | As discussed above, in WebAssembly EH stack unwinding is not done by the unwind 207 | library, the compiler inserts a call to a personality function, more precisely, 208 | a _wrapper_ to the personality function after WebAssembly `catch` instruction, 209 | passing the thrown exception object returned from the `catch` instruction. The 210 | wrapper function lives in the unwind library, and its signature will be 211 | ```cpp 212 | _Unwind_Reason_Code _Unwind_CallPersonality(void *exception_ptr); 213 | ``` 214 | 215 | Even though the wrapper signature looks simple, we use an auxiliary data 216 | structure to pass more information from the compiler-generated user code to the 217 | personality function and retrieve a selector computed after the function 218 | returns. The structure is used as a communication channel: we set input 219 | parameters within the structure before calling the wrapper function, and reads 220 | output parameters after the function returns. This structure lives in the unwind 221 | library and this is how it looks like: 222 | ```cpp 223 | struct _Unwind_LandingPadContext { 224 | // Input information to personality function 225 | uintptr_t lpad_index; // landing pad index 226 | __personality_routine personality; // personality function 227 | uintptr_t lsda; // LSDA address 228 | 229 | // Output information computed by personality function 230 | uintptr_t selector; // selector value, used to select a C++ catch clause 231 | }; 232 | 233 | // Communication channel between WebAssembly code and personality function 234 | struct _Unwind_LandingPadContext __wasm_lpad_context = ...; 235 | 236 | // Personality function wrapper 237 | _Unwind_Reason_Code _Unwind_CallPersonality(void *exception_ptr) { 238 | struct _Unwind_Exception *exception_obj = 239 | (struct _Unwind_Exception *)exception_ptr; 240 | 241 | // Call personality function 242 | _Unwind_Reason_Code ret = (*__wasm_lpad_context->personality)( 243 | 1, _UA_CLEANUP_PHASE, exception_obj->exception_class, exception_obj, 244 | (struct _Unwind_Context *)__wasm_lpad_context); 245 | return ret; 246 | } 247 | ``` 248 | 249 | As you can see in the code above, here's the list of input and output parameters 250 | communicated throw `__wasm_lpad_context`: 251 | * Input parameters 252 | * Landing pad index 253 | * Personality function address 254 | * LSDA information (exception handling table) address 255 | * Output parameters 256 | * Selector value 257 | 258 | These three input parameters are not directly passed to the personality function 259 | as arguments, but are read from it using various `_Unwind_Get*` functions in 260 | unwind library API. The output parameter, a selector value is also not directly 261 | returned by the personality function but will be set by the personality function 262 | using `_Unwind_SetGR`. (`SetGR` here means setting a general register, and it 263 | does set a physical register in Dwarf CFI. But for SjLj and WebAssembly schemes 264 | it sets some field in a data structure instead.) 265 | 266 | When looking for a matching catch site in each call frame, what the personality 267 | function does is querying the call site table within the current function's LSDA 268 | (Language Specipic Data Area), also known as exception handling table or 269 | `gcc_except_table`, with a call site information. For example, the table answers 270 | queries such as "If an exception is thrown at this call site, which action table 271 | entry should I check?" In Dwarf CFI scheme, the offset of actual callsite 272 | address relative to function start address is used as callsite information. In 273 | SjLj scheme, each callsite that can throw has an index starting from 0, and the 274 | indices serve as callsite information to query the action table. In WebAssembly 275 | EH, because a call to the personality function wrapper is inserted at the start 276 | of each landing pad, we give each landing pad an index starting from 0 and use 277 | this as callsite information. We also need to pass the address of the 278 | personality function so that the wrapper can call it. The address of LSDA for 279 | the current function is also required because the personality function examines 280 | the tables there to look for a matching catch site. 281 | 282 | Putting it all together, below is an example of code snippet the compiler 283 | inserts at the beginning of each landing pad. (This is C-style pseudocode; the 284 | real code inserted will be in IR or assembly level.) 285 | ```cpp 286 | // Gets a thrown exception object 287 | void *exn = catch(0); // WebAssembly catch instruction 288 | 289 | // Set input parameters 290 | __wasm_lpad_context.lpad_index = index; 291 | __wasm_lpad_context.personality = __gxx_personality_v0; 292 | __wasm_lpad_context.lsda = &GCC_except_table0; // LSDA symbol of this function 293 | 294 | // Call personality wrapper function 295 | _Unwind_CallPersonality(exn); 296 | 297 | // Retrieve output parameter 298 | int selector = __wasm_lpad_context.selector; 299 | 300 | // use exn and selector hereafter 301 | ``` 302 | 303 | --- 304 | 305 | ## No Two-Phase Unwinding 306 | 307 | Itanium-style two-phase unwinding typically consists of two phases: search and 308 | cleanup. In the search phase, call frames are searched to find a matching catch 309 | site that can catch the type of exception thrown or one that needs some cleanup 310 | action as the stack is unwound. If one is found, it enters the cleanup phase in 311 | which the unwinder stops at the stack frame with the matching catch site found 312 | and starts to run the code there. (The whole search in the second phase is 313 | usually avoided by reusing cached information from the first search phase.) If 314 | no matching clause is found in the first phase, the program aborts. 315 | 316 | **WebAssembly unwinder does not perform two-phase unwinding.** Therefore, 317 | effectively, it only runs the second, cleanup phase. As discussed, because the 318 | unwinding is done by a VM, the unwind library and the C++ ABI library cannot 319 | drive its two-phase unwinding. Because we do not have any cached information 320 | from the first search stage, we do full searches as in the first search stage of 321 | two-phase unwinding. 322 | 323 | --- 324 | 325 | ## LSDA Information 326 | 327 | LSDA (Language Specific Data Area) contains various tables used by the 328 | personality function to check if there is any matching catch sites or cleanup 329 | code to run. Every function that has landing pads has its own LSDA information 330 | area. Usually symbols with prefix `GCC_except_table` or `gcc_except_table` are 331 | used to denote the start of a LSDA information. For some exception handling 332 | schemes LSDA information is stored in its own section, but WebAssembly uses the 333 | data section. 334 | 335 | There are three tables in WebAssembly LSDA information: 336 | * Call site table 337 | * Maps call sites (landing pad indices) to action table entries. 338 | * Action table 339 | * Each entry contains the current action (type information and whether to 340 | catch it or filter it) and the next action entry to proceed. Refers to type 341 | information table on which type to catch or filter. 342 | * Type information table 343 | * List of type information 344 | 345 | In WebAssembly EH, the formats of the action table and the type information 346 | table are the same with that of Dwarf CFI and SjLj scheme. The primary 347 | difference of our scheme is we use landing pad indices as call sites. 348 | 349 | ```text 350 | Exception Handling Table Layout: 351 | 352 | +-----------------+--------+----------------------+ 353 | | lpStartEncoding | (char) | always DW_EH_PE_omit | 354 | +---------+-------+--------+---------------+----------+ 355 | | lpStart | (encoded with lpStartEncoding) | Not used | 356 | +---------+-----+--------+-----------------+---------------+ 357 | | ttypeEncoding | (char) | Encoding of the type_info table | 358 | +---------------+-+------+----+----------------------------+----------------+ 359 | | classInfoOffset | (ULEB128) | Offset to type_info table, defaults to null | 360 | +-----------------++--------+-+----------------------------+----------------+ 361 | | callSiteEncoding | (char) | Encoding for Call Site Table | 362 | +------------------+--+-----+-----+------------------------+--------------------------+ 363 | | callSiteTableLength | (ULEB128) | Call Site Table length, used to find Action table | 364 | +---------------------+-----------+---------------------------------------------------+ 365 | +---------------------+-----------+------------------------------------------------+ 366 | | Beginning of Call Site Table landing pad index is a index into this | 367 | | table. | 368 | | +-------------+---------------------------------+------------------------------+ | 369 | | | landingPad | (ULEB128) | landingpad index | | 370 | | | actionEntry | (ULEB128) | Action Table Index 1-based | | 371 | | | | | actionEntry == 0 -> cleanup | | 372 | | +-------------+---------------------------------+------------------------------+ | 373 | | ... | 374 | +----------------------------------------------------------------------------------+ 375 | +---------------------------------------------------------------------+ 376 | | Beginning of Action Table ttypeIndex == 0 : cleanup | 377 | | ... ttypeIndex > 0 : catch | 378 | | ttypeIndex < 0 : exception spec | 379 | | +--------------+-----------+--------------------------------------+ | 380 | | | ttypeIndex | (SLEB128) | Index into type_info Table (1-based) | | 381 | | | actionOffset | (SLEB128) | Offset into next Action Table entry | | 382 | | +--------------+-----------+--------------------------------------+ | 383 | | ... | 384 | +---------------------------------------------------------------------+-----------------+ 385 | | type_info Table, but classInfoOffset does *not* point here! | 386 | | +----------------+------------------------------------------------+-----------------+ | 387 | | | Nth type_info* | Encoded with ttypeEncoding, 0 means catch(...) | ttypeIndex == N | | 388 | | +----------------+------------------------------------------------+-----------------+ | 389 | | ... | 390 | | +----------------+------------------------------------------------+-----------------+ | 391 | | | 1st type_info* | Encoded with ttypeEncoding, 0 means catch(...) | ttypeIndex == 1 | | 392 | | +----------------+------------------------------------------------+-----------------+ | 393 | | +---------------------------------------+-----------+------------------------------+ | 394 | | | 1st ttypeIndex for 1st exception spec | (ULEB128) | classInfoOffset points here! | | 395 | | | ... | (ULEB128) | | | 396 | | | Mth ttypeIndex for 1st exception spec | (ULEB128) | | | 397 | | | 0 | (ULEB128) | | | 398 | | +---------------------------------------+------------------------------------------+ | 399 | | ... | 400 | | +---------------------------------------+------------------------------------------+ | 401 | | | 0 | (ULEB128) | throw() | | 402 | | +---------------------------------------+------------------------------------------+ | 403 | | ... | 404 | | +---------------------------------------+------------------------------------------+ | 405 | | | 1st ttypeIndex for Nth exception spec | (ULEB128) | | | 406 | | | ... | (ULEB128) | | | 407 | | | Mth ttypeIndex for Nth exception spec | (ULEB128) | | | 408 | | | 0 | (ULEB128) | | | 409 | | +---------------------------------------+------------------------------------------+ | 410 | +---------------------------------------------------------------------------------------+ 411 | ``` 412 | 413 | You can see the exception table structure for DwarfCFI and SjLj scheme 414 | [here](https://github.com/emscripten-core/emscripten/blob/19607820c447a13fd8d0b7680c56148427d6e1b8/system/lib/libcxxabi/src/cxa_personality.cpp#L60-L155). 415 | Other than call site table, the structure for WebAssembly EH is mostly the same. 416 | 417 | --- 418 | 419 | ## WebAssembly C++ Exception Handling ABI 420 | 421 | We discussed in a [prior section](#landing-pad-code) about some additions 422 | required to the C++ ABI library and the unwind library to implement WebAssembly 423 | EH. Here we list up required additional data structure/functions and 424 | WebAssembly's implementation of required APIs. 425 | 426 | ### Compiler Builtins 427 | 428 | This section describes compiler builtins that require support from compiler 429 | implementations. 430 | 431 | ##### __builtin_wasm_throw 432 | ``` 433 | void __builtin_wasm_throw(unsigned int, void *); 434 | ``` 435 | A call to this builtin function is converted to a WebAssembly 436 | [`throw`][eh_proposal_throwing_an_exception] instruction in the instruction 437 | selection stage in the backend. This builtin function is used to implement 438 | exception-throwing functions in the base ABI. 439 | 440 | ##### __builtin_wasm_rethrow 441 | ``` 442 | void __builtin_wasm_rethrow(); 443 | ``` 444 | A call to this builtin function is converted to a WebAssembly 445 | [`rethrow`][eh_proposal_rethrowing_an_exception] instruction in the instruction 446 | selection stage in the backend. This builtin function is used to implement 447 | rethrowing exceptions in the base API. 448 | 449 | 450 | ### Base ABI 451 | 452 | This section defines the unwind library interface, expected to be provided by 453 | any Itanium ABI-compliant system. This is the interface on which the C++ ABI 454 | exception-handling facilities are built. This section describes what WebAssembly 455 | version of the ABI functions do and additional data structures or functions we 456 | need to add. For the complete Itanium C++ base ABI, refer to the spec 457 | [here][itanium_abi_base_abi]. 458 | 459 | 460 | #### Data Structures 461 | 462 | ##### Landing Pad Context 463 | This serves as a communication channel between WebAssembly code and the 464 | personality function. A global variable `__wasm_lpad_context` is an instance of 465 | this data structure. 466 | 467 | ```cpp 468 | struct _Unwind_LandingPadContext { 469 | // Input information to personality function 470 | uintptr_t lpad_index; // landing pad index 471 | __personality_routine personality; // personality function 472 | uintptr_t lsda; // LSDA address 473 | 474 | // Output information computed by personality function 475 | uintptr_t selector; // selector value 476 | }; 477 | 478 | // Communication channel between WebAssembly code and personality function 479 | struct _Unwind_LandingPadContext __wasm_lpad_context = ...; 480 | ``` 481 | 482 | 483 | #### Throwing an Exception 484 | 485 | ##### _Unwind_RaiseException 486 | ```cpp 487 | _Unwind_Reason_Code 488 | _Unwind_RaiseException(struct _Unwind_Exception *exception_object); 489 | ``` 490 | Raise an exception using the [`__builtin_wasm_throw` 491 | builtin](#__builtin_wasm_throw), which will be converted to WebAssembly 492 | [`throw`][eh_proposal_throwing_an_exception] instruction. The arguments to the 493 | builtin are the tag number for C++ and a pointer to an exception object. 494 | 495 | ##### _Unwind_ForcedUnwind 496 | Not used. 497 | 498 | ##### _Unwind_Resume 499 | ```cpp 500 | void _Unwind_Resume(struct _Unwind_Exception *exception_object); 501 | ``` 502 | Resume propagation of an existing exception. Unlike other `_Unwind_*` functions 503 | that are called from the C++ ABI library, this is called from compiler-generated 504 | user code. In other exception handling schemes, this function is mostly used 505 | when a call frame does not have a matching catch site but has cleanup code to 506 | run so that the unwinder stops there only to run the cleanup and resume the 507 | exception's propagation. But in WebAssembly EH, because the unwinder stops at 508 | every call frame with landing pads, this runs on every call frame with landing 509 | pads that does not have a matching catch site. This function also makes use of 510 | [`__builtin_wasm_throw` builtin](#__builtin_wasm_throw) to resume the 511 | propagation of an exception. 512 | 513 | 514 | #### Context Management 515 | 516 | ##### _Unwind_GetGR / _Unwind_SetGR 517 | ```cpp 518 | uint64 _Unwind_GetGR(struct _Unwind_Context *context, int index); 519 | void 520 | _Unwind_SetGR(struct _Unwind_Context *context, int index, uint64 new_value); 521 | ``` 522 | The meaning of the original API name is it gets/sets the value of the given 523 | general register. But in WebAssembly EH, `_Unwind_SetGR` is only used to [set a 524 | selector 525 | value](https://github.com/emscripten-core/emscripten/blob/19607820c447a13fd8d0b7680c56148427d6e1b8/system/lib/libunwind/src/Unwind-wasm.c#L77) 526 | to a data structure used as a communication channel 527 | (`__wasm_lpad_context.selector`). 528 | 529 | In WebAssembly EH, `_Unwind_SetGR` expects the first argument to be a pointer to 530 | `struct _Unwind_LandingPadContext` instance, and only 1 is accepted as the 531 | second argument, in which case it sets the first argument's `selector` field. 532 | `_Unwind_GetGR` is not used. 533 | 534 | ##### _Unwind_GetIP / _Unwind_SetIP 535 | ```cpp 536 | uint64 _Unwind_GetIP(struct _Unwind_Context *context); 537 | void _Unwind_SetIP(struct _Unwind_Context *context, uint64 new_value); 538 | ``` 539 | This sets/gets a real IP address in Dwarf CFI, but in our scheme `_Unwind_GetIP` 540 | returns the value of (landing pad index + 1). The landing pad index is set by 541 | compiler-generated user code to `__wasm_lpad_context.lpad_index` as discussed in 542 | [Landing Pad Code](#landing-pad-code). This information is used in the 543 | personality function to query the call site table. `_Unwind_SetIP` is not used. 544 | 545 | ##### _Unwind_GetLanguageSpecificData 546 | ```cpp 547 | uint64 _Unwind_GetLanguageSpecificData(struct _Unwind_Context *context); 548 | ``` 549 | Returns the address of the current function's LSDA information 550 | (`__wasm_lpad_context.lsda`), set by compiler-generated user code as discussed 551 | in [Landing Pad Code](#landing-pad-code). 552 | 553 | ##### _Unwind_GetRegionStart 554 | Not used. 555 | 556 | 557 | #### Personality Routine 558 | 559 | ##### Personality Function Wrapper 560 | A wrapper function used to call the actual personality function. This is 561 | supposed to be called from compiler-generated user code. Refer to [Landing Pad 562 | Code](#landing-pad-code) for details. 563 | 564 | ```cpp 565 | _Unwind_Reason_Code _Unwind_CallPersonality(void *exception_ptr) { 566 | struct _Unwind_Exception *exception_obj = 567 | (struct _Unwind_Exception *)exception_ptr; 568 | 569 | // Call personality function 570 | _Unwind_Reason_Code ret = (*__wasm_lpad_context->personality)( 571 | 1, _UA_CLEANUP_PHASE, exception_obj->exception_class, exception_obj, 572 | (struct _Unwind_Context *)__wasm_lpad_context); 573 | return ret; 574 | } 575 | ``` 576 | 577 | ##### Transferring Control to a Landing Pad 578 | Transferring program control to a landing pad is done by not the unwind library 579 | but the VM. Refer to [Stack Unwinding and Personality 580 | Function](#stack-unwinding-and-personality-function) section for details. 581 | 582 | 583 | ### C++ ABI 584 | 585 | The second level of specification is the minimum required to allow 586 | interoperability of C++ implementations. This part contains the definition of an 587 | exception object, and various high-level APIs including functions required to 588 | allocate / throw / catch / rethrow an exception object. Functions in this 589 | section rely on the [base API][itanium_abi_base_abi] to do low-level 590 | architecture-dependent tasks. WebAssembly EH does not have a lot of things to 591 | add on this level because architecture-dependent components are usually taken 592 | care of in the base API level. But we still need some modifications on the 593 | personality function and functions called from it to handle some subtle 594 | differences between WebAssembly EH and other schemes, such as Dwarf CFI or SjLj. 595 | For the complete Itanium C++ ABI, refer to the spec [here][itanium_abi_cxx_abi]. 596 | 597 | --- 598 | 599 | ## References 600 | 601 | * [Exception Handling using the Windows Runtime](https://llvm.org/docs/ExceptionHandling.html#exception-handling-using-the-windows-runtime) 602 | * [Itanium C++ ABI: Exception Handling](https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html) 603 | 604 | * Github repos 605 | * [llvm](https://github.com/llvm/llvm-project) 606 | * [libcxxabi](https://github.com/emscripten-core/emscripten/tree/main/system/lib/libcxxabi) 607 | * [libunwind](https://github.com/emscripten-core/emscripten/tree/main/system/lib/libunwind) 608 | 609 | 610 | [llvm_wasm_backend]: https://github.com/llvm/llvm-project/tree/main/llvm/lib/Target/WebAssembly 611 | [llvm_libcxxabi]: https://github.com/llvm/llvm-project/tree/main/libcxxabi 612 | [llvm_libunwind]: https://github.com/llvm/llvm-project/tree/main/libunwind 613 | [llvm_win_eh]: https://llvm.org/docs/ExceptionHandling.html#exception-handling-using-the-windows-runtime 614 | 615 | [binaryen]: https://github.com/WebAssembly/binaryen 616 | [emscripten]: https://github.com/emscripten-core/emscripten 617 | [emscripten_libcxxabi]: https://github.com/emscripten-core/emscripten/tree/main/system/lib/libcxxabi 618 | [emscripten_libunwind]: https://github.com/emscripten-core/emscripten/tree/main/system/lib/libunwind 619 | 620 | [eh_proposal]: https://github.com/WebAssembly/exception-handling/blob/main/proposals/exception-handling/Exceptions.md 621 | [eh_proposal_try_catch_blocks]: https://github.com/WebAssembly/exception-handling/blob/main/proposals/exception-handling/Exceptions.md#try-catch-blocks 622 | [eh_proposal_throwing_an_exception]: https://github.com/WebAssembly/exception-handling/blob/main/proposals/exception-handling/Exceptions.md#throwing-an-exception 623 | [eh_proposal_rethrowing_an_exception]: https://github.com/WebAssembly/exception-handling/blob/main/proposals/exception-handling/Exceptions.md#rethrowing-an-exception 624 | 625 | [itanium_abi]: https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html 626 | [itanium_abi_cxx_abi]: https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html#cxx-abi 627 | [itanium_abi_base_abi]: https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html#base_abi 628 | 629 | [__cxa_throw]: https://github.com/emscripten-core/emscripten/blob/19607820c447a13fd8d0b7680c56148427d6e1b8/system/lib/libcxxabi/src/cxa_exception.cpp#L263-L304 630 | [__gxx_personality_wasm0]: https://github.com/emscripten-core/emscripten/blob/19607820c447a13fd8d0b7680c56148427d6e1b8/system/lib/libcxxabi/src/cxa_personality.cpp#L910-L1003 631 | -------------------------------------------------------------------------------- /ItaniumLikeC++ABI.md: -------------------------------------------------------------------------------- 1 | This document describes the "Itanium-like" C++ ABI for WebAssembly. As mentioned 2 | in [README](README.md), it's not the only possible C++ ABI or even the only 3 | possible Itanium-derived C++ ABI for WebAssembly. It is the ABI that the 4 | clang/LLVM WebAssembly backend is currently using, and any other C++ compiler 5 | wishing to be ABI-compatible with it. 6 | 7 | Most details follow 8 | [the base Itanium C++ ABI](https://itanium-cxx-abi.github.io/cxx-abi/abi.html). 9 | 10 | The following is a brief summary of deviations from this base: 11 | 12 | - The least-significant bit of the `adj` field of a member-function pointer is 13 | used to indicate whether the indicated function is virtual. 14 | - Member functions are not specially aligned. 15 | - Constructors and destructors return `this`. 16 | - Guard variables are 32-bit on wasm32. 17 | - Unused bits of guard variables are reserved. 18 | - Inline functions are never key functions. 19 | - C++11 POD rules are used to determine tail padding. 20 | 21 | The following are ideas for additional deviations that are being considered: 22 | 23 | - The Itanium C++ name mangling rules have special-case abbreviations for 24 | std::string, std::allocator, and a few others, however libc++ doesn’t get to 25 | take advantage of them because it uses a versioned namespace. It may be 26 | useful to add new special-cases to cover libc++’s mangled names for 27 | std::string et al. 28 | - There’s an interesting idea for a vtable optimization described 29 | [here](https://llvm.org/bugs/show_bug.cgi?id=26723) that’s worth thinking 30 | about. 31 | - Alternatively, the design of vtables may radically change to take better 32 | advantage of WebAssembly’s function table mechanisms. 33 | - Trivially copyable classes may be passed by value rather than by pointer. 34 | This would cover a lot of common C++ classes such as std::pair. 35 | 36 | This is just an initial sketch of the kind of content we plan to have here. 37 | Obviously it would be desirable to go into a lot more detail. 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The Artistic License 2.0 2 | 3 | Copyright (c) 2000-2006, The Perl Foundation. 4 | 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | This license establishes the terms under which a given free software 11 | Package may be copied, modified, distributed, and/or redistributed. 12 | The intent is that the Copyright Holder maintains some artistic 13 | control over the development of that Package while still keeping the 14 | Package available as open source and free software. 15 | 16 | You are always permitted to make arrangements wholly outside of this 17 | license directly with the Copyright Holder of a given Package. If the 18 | terms of this license do not permit the full use that you propose to 19 | make of the Package, you should contact the Copyright Holder and seek 20 | a different licensing arrangement. 21 | 22 | Definitions 23 | 24 | "Copyright Holder" means the individual(s) or organization(s) 25 | named in the copyright notice for the entire Package. 26 | 27 | "Contributor" means any party that has contributed code or other 28 | material to the Package, in accordance with the Copyright Holder's 29 | procedures. 30 | 31 | "You" and "your" means any person who would like to copy, 32 | distribute, or modify the Package. 33 | 34 | "Package" means the collection of files distributed by the 35 | Copyright Holder, and derivatives of that collection and/or of 36 | those files. A given Package may consist of either the Standard 37 | Version, or a Modified Version. 38 | 39 | "Distribute" means providing a copy of the Package or making it 40 | accessible to anyone else, or in the case of a company or 41 | organization, to others outside of your company or organization. 42 | 43 | "Distributor Fee" means any fee that you charge for Distributing 44 | this Package or providing support for this Package to another 45 | party. It does not mean licensing fees. 46 | 47 | "Standard Version" refers to the Package if it has not been 48 | modified, or has been modified only in ways explicitly requested 49 | by the Copyright Holder. 50 | 51 | "Modified Version" means the Package, if it has been changed, and 52 | such changes were not explicitly requested by the Copyright 53 | Holder. 54 | 55 | "Original License" means this Artistic License as Distributed with 56 | the Standard Version of the Package, in its current version or as 57 | it may be modified by The Perl Foundation in the future. 58 | 59 | "Source" form means the source code, documentation source, and 60 | configuration files for the Package. 61 | 62 | "Compiled" form means the compiled bytecode, object code, binary, 63 | or any other form resulting from mechanical transformation or 64 | translation of the Source form. 65 | 66 | 67 | Permission for Use and Modification Without Distribution 68 | 69 | (1) You are permitted to use the Standard Version and create and use 70 | Modified Versions for any purpose without restriction, provided that 71 | you do not Distribute the Modified Version. 72 | 73 | 74 | Permissions for Redistribution of the Standard Version 75 | 76 | (2) You may Distribute verbatim copies of the Source form of the 77 | Standard Version of this Package in any medium without restriction, 78 | either gratis or for a Distributor Fee, provided that you duplicate 79 | all of the original copyright notices and associated disclaimers. At 80 | your discretion, such verbatim copies may or may not include a 81 | Compiled form of the Package. 82 | 83 | (3) You may apply any bug fixes, portability changes, and other 84 | modifications made available from the Copyright Holder. The resulting 85 | Package will still be considered the Standard Version, and as such 86 | will be subject to the Original License. 87 | 88 | 89 | Distribution of Modified Versions of the Package as Source 90 | 91 | (4) You may Distribute your Modified Version as Source (either gratis 92 | or for a Distributor Fee, and with or without a Compiled form of the 93 | Modified Version) provided that you clearly document how it differs 94 | from the Standard Version, including, but not limited to, documenting 95 | any non-standard features, executables, or modules, and provided that 96 | you do at least ONE of the following: 97 | 98 | (a) make the Modified Version available to the Copyright Holder 99 | of the Standard Version, under the Original License, so that the 100 | Copyright Holder may include your modifications in the Standard 101 | Version. 102 | 103 | (b) ensure that installation of your Modified Version does not 104 | prevent the user installing or running the Standard Version. In 105 | addition, the Modified Version must bear a name that is different 106 | from the name of the Standard Version. 107 | 108 | (c) allow anyone who receives a copy of the Modified Version to 109 | make the Source form of the Modified Version available to others 110 | under 111 | 112 | (i) the Original License or 113 | 114 | (ii) a license that permits the licensee to freely copy, 115 | modify and redistribute the Modified Version using the same 116 | licensing terms that apply to the copy that the licensee 117 | received, and requires that the Source form of the Modified 118 | Version, and of any works derived from it, be made freely 119 | available in that license fees are prohibited but Distributor 120 | Fees are allowed. 121 | 122 | 123 | Distribution of Compiled Forms of the Standard Version 124 | or Modified Versions without the Source 125 | 126 | (5) You may Distribute Compiled forms of the Standard Version without 127 | the Source, provided that you include complete instructions on how to 128 | get the Source of the Standard Version. Such instructions must be 129 | valid at the time of your distribution. If these instructions, at any 130 | time while you are carrying out such distribution, become invalid, you 131 | must provide new instructions on demand or cease further distribution. 132 | If you provide valid instructions or cease distribution within thirty 133 | days after you become aware that the instructions are invalid, then 134 | you do not forfeit any of your rights under this license. 135 | 136 | (6) You may Distribute a Modified Version in Compiled form without 137 | the Source, provided that you comply with Section 4 with respect to 138 | the Source of the Modified Version. 139 | 140 | 141 | Aggregating or Linking the Package 142 | 143 | (7) You may aggregate the Package (either the Standard Version or 144 | Modified Version) with other packages and Distribute the resulting 145 | aggregation provided that you do not charge a licensing fee for the 146 | Package. Distributor Fees are permitted, and licensing fees for other 147 | components in the aggregation are permitted. The terms of this license 148 | apply to the use and Distribution of the Standard or Modified Versions 149 | as included in the aggregation. 150 | 151 | (8) You are permitted to link Modified and Standard Versions with 152 | other works, to embed the Package in a larger work of your own, or to 153 | build stand-alone binary or bytecode versions of applications that 154 | include the Package, and Distribute the result without restriction, 155 | provided the result does not expose a direct interface to the Package. 156 | 157 | 158 | Items That are Not Considered Part of a Modified Version 159 | 160 | (9) Works (including, but not limited to, modules and scripts) that 161 | merely extend or make use of the Package, do not, by themselves, cause 162 | the Package to be a Modified Version. In addition, such works are not 163 | considered parts of the Package itself, and are not subject to the 164 | terms of this license. 165 | 166 | 167 | General Provisions 168 | 169 | (10) Any use, modification, and distribution of the Standard or 170 | Modified Versions is governed by this Artistic License. By using, 171 | modifying or distributing the Package, you accept this license. Do not 172 | use, modify, or distribute the Package, if you do not accept this 173 | license. 174 | 175 | (11) If your Modified Version has been derived from a Modified 176 | Version made by someone other than you, you are nevertheless required 177 | to ensure that your Modified Version complies with the requirements of 178 | this license. 179 | 180 | (12) This license does not grant you the right to use any trademark, 181 | service mark, tradename, or logo of the Copyright Holder. 182 | 183 | (13) This license includes the non-exclusive, worldwide, 184 | free-of-charge patent license to make, have made, use, offer to sell, 185 | sell, import and otherwise transfer the Package with respect to any 186 | patent claims licensable by the Copyright Holder that are necessarily 187 | infringed by the Package. If you institute patent litigation 188 | (including a cross-claim or counterclaim) against any party alleging 189 | that the Package constitutes direct or contributory patent 190 | infringement, then this Artistic License to you shall terminate on the 191 | date that such litigation is filed. 192 | 193 | (14) Disclaimer of Warranty: 194 | THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS 195 | IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED 196 | WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR 197 | NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL 198 | LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL 199 | BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 200 | DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF 201 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 202 | -------------------------------------------------------------------------------- /Lime.md: -------------------------------------------------------------------------------- 1 | # The Lime Series 2 | 3 | Lime is a series of defined and stable subsets of [WebAssembly features] that producers 4 | and consumers can both use to promote interoperability. It is intended to be implemented 5 | by producers such as LLVM, using features such as LLVM's concept of target CPUs. Once a 6 | Lime configuration is defined, it will be stable and not add or remove any features. 7 | 8 | Lime configuration names include a version number, such as "Lime1". When there is a 9 | need to add or remove features, a new Lime configuration with a new version number will 10 | be defined, such as "Lime2". 11 | 12 | Lime aims for features which do not involve significant new runtime cost or complexity, 13 | and can be implemented in mobile devices and other highly constrained environments. 14 | 15 | The name "Lime" was inspired by abbreviating *Li*near *Me*mory, as this series currently 16 | lacks wasm-gc and is therefore focused on linear-memory languages or language implementations. 17 | 18 | ## The configurations 19 | 20 | The following Lime configurations have been defined: 21 | - [Lime1](#lime1) 22 | 23 | ### Lime1 24 | 25 | The Lime1 target consists of [WebAssembly 1.0] plus the following standardized 26 | ([phase-5]) features: 27 | 28 | - [mutable-globals] 29 | - [multivalue] 30 | - [sign-ext] 31 | - [nontrapping-fptoint] 32 | - [bulk-memory-opt] 33 | - [extended-const] 34 | - [call-indirect-overlong] 35 | 36 | [WebAssembly features]: https://webassembly.org/features/ 37 | [WebAssembly 1.0]: https://www.w3.org/TR/wasm-core-1/ 38 | [phase-5]: https://github.com/WebAssembly/meetings/blob/main/process/phases.md#5-the-feature-is-standardized-working-group 39 | [mutable-globals]: https://github.com/WebAssembly/mutable-global/blob/master/proposals/mutable-global/Overview.md 40 | [multivalue]: https://github.com/WebAssembly/spec/blob/master/proposals/multi-value/Overview.md 41 | [sign-ext]: https://github.com/WebAssembly/spec/blob/master/proposals/sign-extension-ops/Overview.md 42 | [nontrapping-fptoint]: https://github.com/WebAssembly/spec/blob/master/proposals/nontrapping-float-to-int-conversion/Overview.md 43 | [bulk-memory-opt]: #bulk-memory-opt 44 | [extended-const]: https://github.com/WebAssembly/extended-const/blob/main/proposals/extended-const/Overview.md 45 | [call-indirect-overlong]: #call-indirect-overlong 46 | 47 | ## Feature subsets 48 | 49 | [WebAssembly features] sometimes contain several features combined into a 50 | single proposal to simplify the standardization process, but can have very 51 | different implementation considerations. This section defines subsets of 52 | standardized features for use in Lime configurations. 53 | 54 | ### bulk-memory-opt 55 | 56 | bulk-memory-opt is a subset of the [bulk-memory] feature that contains just the 57 | `memory.copy` and `memory.fill` instructions. 58 | 59 | It does not include the table instructions, `memory.init`, or `data.drop`. 60 | 61 | ### call-indirect-overlong 62 | 63 | call-indirect-overlong is a subset of the [reference-types] feature that contains 64 | just the change to the `call_indirect` instruction encoding to change the zero 65 | byte to an LEB encoding which may have an overlong encoding. 66 | 67 | It does not include the actual reference types. 68 | 69 | [bulk-memory]: https://github.com/WebAssembly/bulk-memory-operations/blob/master/proposals/bulk-memory-operations/Overview.md 70 | [reference-types]: https://github.com/WebAssembly/reference-types/blob/master/proposals/reference-types/Overview.md 71 | -------------------------------------------------------------------------------- /Linking.md: -------------------------------------------------------------------------------- 1 | # WebAssembly Object File Linking 2 | 3 | This document describes the WebAssembly object file format and the ABI used for 4 | statically linking them to produce an executable WebAssembly module. This is 5 | currently implemented in the clang/LLVM WebAssembly 6 | backend and other tools such as binaryen and wabt. As mentioned in 7 | [README](README.md), this is not part of the official WebAssembly specification 8 | and other runtimes may choose to follow a different set of linking conventions. 9 | 10 | ## Overview 11 | 12 | Each translation unit is compiled into a WebAssembly object file. These files 13 | are themselves valid WebAssembly module binaries but are not expected to be 14 | directly executable and have certain additional constraints. In order to 15 | distinguish object files from executable WebAssembly modules the linker can 16 | check for the presence of the ["linking"](#linking-metadata-section) custom 17 | section which must exist in all object files. 18 | 19 | The goal of the linker is to take one or more WebAssembly object files and merge 20 | them into a single executable module. In order to achieve this the following 21 | tasks need to be performed: 22 | 23 | - Merging of function sections (re-numbering functions) 24 | - Merging of globals sections (re-numbering globals) 25 | - Merging of event sections (re-numbering events) 26 | - Merging of table sections (re-numbering tables) 27 | - Merging of data segments (re-positioning data with [limitations](#limitations)) 28 | - Resolving undefined external references 29 | - Synthesizing functions to call constructors and perform other initialization 30 | 31 | The linking technique described here is designed to be fast, and avoids having 32 | to disassemble the code section. The extra metadata required by the linker 33 | is stored in a custom ["linking"](#linking-metadata-section) section and zero or 34 | more relocation sections whose names begin with "reloc.". For each section that 35 | requires relocation a "reloc" section will be present in the wasm file. By 36 | convention the reloc section names end with the name of the section that they 37 | refer to: e.g. "reloc.CODE" for code section relocations. However, everything 38 | after the period is ignored and the specific target section is encoded in the 39 | reloc section itself. 40 | 41 | The linker additionally checks that linked object files were built targeting 42 | compatible feature sets. Unlike native targets, WebAssembly has no runtime 43 | feature detection, and the presence of unsupported features causes a binary to 44 | fail to validate. It is therefore important for the user to have explicit 45 | control over the features used in the output binary and for the linker to 46 | provide helpful errors when instructed to link incompatible or disallowed 47 | features. This feature information is stored in a custom ["target feature 48 | section"](#target-features-section). 49 | 50 | ## Relocation Sections 51 | 52 | A relocation section is a user-defined section with a name starting with 53 | "reloc." Relocation sections start with an identifier specifying which 54 | section they apply to, and must be sequenced in the module after that 55 | section. 56 | 57 | Relocation sections can only target code, data and custom sections. All other 58 | sections are synthetic sections: that is, rather than being `memcpy`'d into 59 | place as the code and data sections are, they are created from scratch by the 60 | linker. 61 | 62 | The "reloc." custom sections must come after the 63 | ["linking"](#linking-metadata-section) custom section in order to validate 64 | relocation indices. 65 | 66 | Any LEB128-encoded values should be maximally padded so that they can be 67 | rewritten without affecting the position of any other bytes. For instance, the 68 | function index 3 should be encoded as `0x83 0x80 0x80 0x80 0x00`. 69 | 70 | Relocations contain the following fields: 71 | 72 | | Field | Type | Description | 73 | | ----------| ------------------- | ------------------------------- | 74 | | section | `varuint32` | the index of the target section | 75 | | count | `varuint32` | count of entries to follow | 76 | | entries | `relocation_entry*` | sequence of relocation entries | 77 | 78 | A `relocation_entry` begins with: 79 | 80 | | Field | Type | Description | 81 | | -------- | ------------------- | ------------------------------ | 82 | | type | `uint8` | the relocation type | 83 | | offset | `varuint32` | offset of the value to rewrite (relative to the relevant section's contents: offset zero is immediately after the id and size of the section) | 84 | | index | `varuint32` | the index of the symbol used (or, for `R_WASM_TYPE_INDEX_LEB` relocations, the index of the type) | 85 | 86 | A relocation type can be one of the following: 87 | 88 | - `0 / R_WASM_FUNCTION_INDEX_LEB` (since LLVM 10.0) - a function index encoded 89 | as a 5-byte [varuint32]. Used for the immediate argument of a `call` 90 | instruction. 91 | - `1 / R_WASM_TABLE_INDEX_SLEB` (since LLVM 10.0) - a function table index 92 | encoded as a 5-byte [varint32]. Used to refer to the immediate argument of a 93 | `i32.const` instruction, e.g. taking the address of a function. 94 | - `2 / R_WASM_TABLE_INDEX_I32` (since LLVM 10.0) - a function table index 95 | encoded as a [uint32], e.g. taking the address of a function in a static data 96 | initializer. 97 | - `3 / R_WASM_MEMORY_ADDR_LEB` (since LLVM 10.0) - a linear memory index 98 | encoded as a 5-byte [varuint32]. Used for the immediate argument of a `load` or 99 | `store` instruction, e.g. directly loading from or storing to a C++ global. 100 | - `4 / R_WASM_MEMORY_ADDR_SLEB` (since LLVM 10.0) - a linear memory index 101 | encoded as a 5-byte [varint32]. Used for the immediate argument of a `i32.const` 102 | instruction, e.g. taking the address of a C++ global. 103 | - `5 / R_WASM_MEMORY_ADDR_I32` (since LLVM 10.0) - a linear memory index 104 | encoded as a [uint32], e.g. taking the address of a C++ global in a static data 105 | initializer. 106 | - `6 / R_WASM_TYPE_INDEX_LEB` (since LLVM 10.0) - a type index encoded as 107 | a 5-byte [varuint32], e.g. the type immediate in a `call_indirect`. 108 | - `7 / R_WASM_GLOBAL_INDEX_LEB` (since LLVM 10.0) - a global index encoded as a 109 | 5-byte [varuint32], e.g. the index immediate in a `get_global`. 110 | - `8 / R_WASM_FUNCTION_OFFSET_I32` (since LLVM 10.0) - a byte offset within 111 | code section for the specific function encoded as a [uint32]. The offsets start 112 | at the actual function code excluding its size field. 113 | - `9 / R_WASM_SECTION_OFFSET_I32` (since LLVM 10.0) - a byte offset from start 114 | of the specified section encoded as a [uint32]. 115 | - `10 / R_WASM_EVENT_INDEX_LEB` (since LLVM 10.0) - an event index encoded as a 116 | 5-byte [varuint32]. Used for the immediate argument of a `throw` and `if_except` 117 | instruction. 118 | - `13 / R_WASM_GLOBAL_INDEX_I32` (since LLVM 11.0) - a global index encoded as 119 | [uint32]. 120 | - `14 / R_WASM_MEMORY_ADDR_LEB64` (since LLVM 11.0) - the 64-bit counterpart of 121 | `R_WASM_MEMORY_ADDR_LEB`. A 64-bit linear memory index encoded as a 10-byte 122 | [varuint64], Used for the immediate argument of a `load` or `store` instruction 123 | on a 64-bit linear memory array. 124 | - `15 / R_WASM_MEMORY_ADDR_SLEB64` (since LLVM 11.0) - the 64-bit counterpart 125 | of `R_WASM_MEMORY_ADDR_SLEB`. A 64-bit linear memory index encoded as a 10-byte 126 | [varint64]. Used for the immediate argument of a `i64.const` instruction. 127 | - `16 / R_WASM_MEMORY_ADDR_I64` (since LLVM 11.0) - the 64-bit counterpart of 128 | `R_WASM_MEMORY_ADDR`. A 64-bit linear memory index encoded as a [uint64], e.g. 129 | taking the 64-bit address of a C++ global in a static data initializer. 130 | - `18 / R_WASM_TABLE_INDEX_SLEB64` (in LLVM 12.0) - the 64-bit counterpart 131 | of `R_WASM_TABLE_INDEX_SLEB`. A function table index encoded as a 10-byte 132 | [varint64]. Used to refer to the immediate argument of a `i64.const` 133 | instruction, e.g. taking the address of a function in Wasm64. 134 | - `19 / R_WASM_TABLE_INDEX_I64` (in LLVM 12.0) - the 64-bit counterpart of 135 | `R_WASM_TABLE_INDEX_I32`. A function table index encoded as a [uint64], e.g. 136 | taking the address of a function in a static data initializer. 137 | - `20 / R_WASM_TABLE_NUMBER_LEB` (in LLVM 12.0) - a table number encoded as 138 | a 5-byte [varuint32]. Used for the table immediate argument in the table.* 139 | instructions. 140 | - `22 / R_WASM_FUNCTION_OFFSET_I64` (in LLVM 12.0) - the 64-bit counterpart 141 | of `R_WASM_FUNCTION_OFFSET_I32`. A byte offset within code section for the 142 | specific function encoded as a [uint64]. 143 | - `23 / R_WASM_MEMORY_ADDR_LOCREL_I32` (in LLVM 13.0) - a byte offset between 144 | the relocating address and a linear memory index encoded as a [uint32]. Used 145 | for pointer-relative addressing. 146 | - `24 / R_WASM_TABLE_INDEX_REL_SLEB64` (in LLVM 13.0) - the 64-bit counterpart 147 | of `R_WASM_TABLE_INDEX_REL_SLEB`. A function table index encoded as a 10-byte 148 | [varint64]. 149 | - `26 / R_WASM_FUNCTION_INDEX_I32` (in LLVM 17.0) - a function index encoded as 150 | a [uint32]. Used in custom sections for function annotations (`__attribute__((annotate()))`). 151 | 152 | **Note**: Please note that the 64bit relocations are not yet stable and 153 | therefore, subject to change. 154 | 155 | [varuint32]: https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md#varuintn 156 | [varuint64]: https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md#varuintn 157 | [varint32]: https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md#varintn 158 | [varint64]: https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md#varintn 159 | [uint32]: https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md#uintn 160 | [uint64]: https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md#uintn 161 | 162 | For `R_WASM_MEMORY_ADDR_*`, `R_WASM_FUNCTION_OFFSET_I32`, and 163 | `R_WASM_SECTION_OFFSET_I32` relocations (and their 64-bit counterparts) the 164 | following field is additionally present: 165 | 166 | | Field | Type | Description | 167 | | ------ | ---------------- | ----------------------------------- | 168 | | addend | `varint32` | addend to add to the address | 169 | 170 | Note that for all relocation types, the bytes being relocated: 171 | * from `offset` to `offset + 5` for LEB/SLEB relocations; 172 | * from `offset` to `offset + 10` for LEB64/SLEB64 relocations; 173 | * from `offset` to `offset + 4` for I32 relocations; 174 | * or from `offset` to `offset + 8` for I64; 175 | 176 | must lie within the section to which the relocation applies (as offsets are relative 177 | to the section's contents, this means that they cannot be too large). In addition, 178 | the bytes being relocated may not overlap the boundary between the section's chunks, 179 | where such a distinction exists (it may not for custom sections). For example, for 180 | relocations applied to the CODE section, a relocation cannot straddle two 181 | functions, and for the DATA section relocations must lie within a data element's 182 | body. 183 | 184 | ## Linking Metadata Section 185 | 186 | A linking metadata section is a user-defined section with the name 187 | "linking". 188 | 189 | The "linking" custom section must be after the [data 190 | section](https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md#data-section) 191 | in order to validate data symbols. 192 | 193 | A linking metadata section begins with a version number which is then followed 194 | by a series of sub-sections laid out in the same way as the ["names"][names_sec] 195 | section: 196 | 197 | | Field | Type | Description | 198 | | ----------- | ------------- | ------------------------------------ | 199 | | version | `varuint32` | the version of linking metadata contained in this section. Currently: 2 | 200 | | subsections | `subsection*` | sequence of `subsection` | 201 | 202 | This `version` allows for breaking changes to be made to the format described 203 | here. Tools can then choose to reject inputs containing unexpected versions. 204 | 205 | Each `subsection` is encoded as: 206 | 207 | | Field | Type | Description | 208 | | ------------ | ----------- | ------------------------------------ | 209 | | type | `uint8` | code identifying type of subsection | 210 | | payload_len | `varuint32` | size of this subsection in bytes | 211 | | payload_data | `bytes` | content of this subsection, of length `payload_len` | 212 | 213 | The current list of valid `type` codes are: 214 | 215 | - `5 / WASM_SEGMENT_INFO` - Extra metadata about the data segments. 216 | 217 | - `6 / WASM_INIT_FUNCS` - Specifies a list of constructor functions to be called 218 | at startup. These constructors will be called in priority order after memory 219 | has been initialized. 220 | 221 | - `7 / WASM_COMDAT_INFO` - Specifies the COMDAT groups of associated linking 222 | objects, which are linked only once and all together. 223 | 224 | - `8 / WASM_SYMBOL_TABLE` - Specifies extra information about the symbols present 225 | in the module. 226 | 227 | ### Segment Info Subsection 228 | 229 | For `WASM_SEGMENT_INFO` the following fields are present in the 230 | subsection: 231 | 232 | | Field | Type | Description | 233 | | ----------- | ------------ | -------------------------------- | 234 | | count | `varuint32` | number of `segment` in segments | 235 | | segments | `segment*` | sequence of `segment` | 236 | 237 | where a `segment` is encoded as: 238 | 239 | | Field | Type | Description | 240 | | ------------ | ------------ | --------------------------------------------- | 241 | | name_len | `varuint32` | length of `name_data` in bytes | 242 | | name_data | `bytes` | UTF-8 encoding of the segment's name | 243 | | alignment | `varuint32` | The required alignment of the segment, encoded as a power of 2 | 244 | | flags | `varuint32` | a bitfield containing flags for this segment | 245 | 246 | The current set of valid flag for segments are: 247 | - `1 / WASM_SEGMENT_FLAG_STRINGS` - Signals that the segment contains only null terminated strings allowing the linker to perform merging. 248 | - `2 / WASM_SEGMENT_FLAG_TLS` - The segment contains thread-local data. This means that a unique copy of this segment will be created for each thread. 249 | - `4 / WASM_SEG_FLAG_RETAIN` - If the object file is included in the final link, the segment should be retained in the final output regardless of whether it is used by the program. 250 | 251 | ### Init Functions Subsection 252 | 253 | For `WASM_INIT_FUNCS` the following fields are present in the 254 | subsection: 255 | 256 | | Field | Type | Description | 257 | | ----------- | ------------ | ------------------------------------- | 258 | | count | `varuint32` | number of init functions that follow | 259 | | functions | `init_func*` | sequence of `init_func` | 260 | 261 | where an `init_func` is encoded as: 262 | 263 | | Field | Type | Description | 264 | | ------------ | ----------- | ------------------------------------------------------------ | 265 | | priority | `varuint32` | priority of the init function | 266 | | symbol_index | `varuint32` | the symbol index of init function (*not* the function index) | 267 | 268 | The `WASM_INIT_FUNC` subsection must come after the `WASM_SYMBOL_TABLE` subsection. 269 | 270 | ### Symbol Table Subsection 271 | 272 | For `WASM_SYMBOL_TABLE` the following fields are present in the 273 | subsection: 274 | 275 | | Field | Type | Description | 276 | | ------ | --------------- | ---------------------------- | 277 | | count | `varuint32` | number of `syminfo` in infos | 278 | | infos | `syminfo*` | sequence of `syminfo` | 279 | 280 | where a `syminfo` is encoded as: 281 | 282 | | Field | Type | Description | 283 | | ------------ | -------------- | ------------------------------------------- | 284 | | kind | `uint8` | The symbol type. One of: | 285 | | | | `0 / SYMTAB_FUNCTION` | 286 | | | | `1 / SYMTAB_DATA` | 287 | | | | `2 / SYMTAB_GLOBAL` | 288 | | | | `3 / SYMTAB_SECTION` | 289 | | | | `4 / SYMTAB_EVENT` | 290 | | | | `5 / SYMTAB_TABLE` | 291 | | flags | `varuint32` | a bitfield containing flags for this symbol | 292 | 293 | For functions, globals, events and tables, we reference an existing Wasm object, which 294 | is either an import or a defined function/global/event/table (recall that the operand of a 295 | Wasm `call` instruction uses an index space consisting of the function imports 296 | followed by the defined functions, and similarly `get_global` for global imports 297 | and definitions and `throw` for event imports and definitions). 298 | 299 | If a symbols refers to an import, and the 300 | `WASM_SYM_EXPLICIT_NAME` flag is not set, then the name is taken from the 301 | import; otherwise the `syminfo` specifies the symbol's name. 302 | 303 | | Field | Type | Description | 304 | | ------------ | -------------- | ------------------------------------------- | 305 | | index | `varuint32` | the index of the Wasm object corresponding to the symbol, which references an import if and only if the `WASM_SYM_UNDEFINED` flag is set | 306 | | name_len | `varuint32` ? | the optional length of `name_data` in bytes, omitted if `index` references an import | 307 | | name_data | `bytes` ? | UTF-8 encoding of the symbol name, omitted if `index` references an import | 308 | 309 | For data symbols: 310 | 311 | | Field | Type | Description | 312 | | ------------ | -------------- | ------------------------------------------- | 313 | | name_len | `varuint32` | the length of `name_data` in bytes | 314 | | name_data | `bytes` | UTF-8 encoding of the symbol name | 315 | | index | `varuint32` ? | the index of the data segment; provided if the symbol is defined | 316 | | offset | `varuint32` ? | the offset within the segment; provided if the symbol is defined; must be <= the segment's size | 317 | | size | `varuint32` ? | the size (which can be zero); provided if the symbol is defined; `offset + size` must be <= the segment's size | 318 | 319 | For section symbols: 320 | 321 | | Field | Type | Description | 322 | | ------------ | -------------- | ------------------------------------------- | 323 | | section | `varuint32` | the index of the target section | 324 | 325 | The current set of valid flags for symbols are: 326 | 327 | - `1 / WASM_SYM_BINDING_WEAK` - Indicating that this is a weak symbol. When 328 | linking multiple modules defining the same symbol, all weak definitions are 329 | discarded if any strong definitions exist; then if multiple weak definitions 330 | exist all but one (unspecified) are discarded; and finally it is an error if 331 | more than one definition remains. 332 | - `2 / WASM_SYM_BINDING_LOCAL` - Indicating that this is a local symbol (this 333 | is exclusive with `WASM_SYM_BINDING_WEAK`). Local symbols are not to be 334 | exported, or linked to other modules/sections. The names of all non-local 335 | symbols must be unique, but the names of local symbols are not considered for 336 | uniqueness. A local function or global symbol cannot reference an import. 337 | - `4 / WASM_SYM_VISIBILITY_HIDDEN` - Indicating that this is a hidden symbol. 338 | Hidden symbols are not to be exported when performing the final link, but 339 | may be linked to other modules. 340 | - `0x10 / WASM_SYM_UNDEFINED` - Indicating that this symbol is not defined. 341 | For non-data symbols, this must match whether the symbol is an import 342 | or is defined; for data symbols, determines whether a segment is specified. 343 | - `0x20 / WASM_SYM_EXPORTED` - The symbol is intended to be exported from the 344 | wasm module to the host environment. This differs from the visibility flags 345 | in that it effects the static linker. 346 | - `0x40 / WASM_SYM_EXPLICIT_NAME` - The symbol uses an explicit symbol name, 347 | rather than reusing the name from a wasm import. This allows it to remap 348 | imports from foreign WebAssembly modules into local symbols with different 349 | names. 350 | - `0x80 / WASM_SYM_NO_STRIP` - The symbol is intended to be included in the 351 | linker output, regardless of whether it is used by the program. 352 | - `0x100 / WASM_SYM_TLS` - The symbol resides in thread local storage. 353 | - `0x200 / WASM_SYM_ABSOLUTE` - The symbol represents an absolute address. This 354 | means it's offset is relative to the start of the wasm memory as opposed to 355 | being relative to a data segment. 356 | 357 | ### COMDAT Info Subsection 358 | 359 | For `WASM_COMDAT_INFO` the following fields are present in the 360 | subsection: 361 | 362 | | Field | Type | Description | 363 | | ------- | ----------- | ---------------------------------------------- | 364 | | count | `varuint32` | Number of `Comdat` in `comdats` | 365 | | comdats | `comdat*` | Sequence of `Comdat` 366 | 367 | where a `comdat` is encoded as: 368 | 369 | | Field | Type | Description | 370 | | ----------- | ------------- | ----------------------------------------- | 371 | | name_len | `varuint32` | length of `name_str` in bytes | 372 | | name_str | `bytes` | UTF-8 encoding of the name | 373 | | flags | `varuint32` | Must be zero, no flags currently defined | 374 | | count | `varuint32` | Number of `comdat_sym` in `comdat_syms` | 375 | | comdat_syms | `comdat_sym*` | Sequence of `comdat_sym` | 376 | 377 | and where a `comdat_sym` is encoded as: 378 | 379 | | Field | Type | Description | 380 | | -------- | -------------- | ------------------------------------------- | 381 | | kind | `uint8` | Type of symbol, one of: | 382 | | | | * `0 / WASM_COMDAT_DATA`, a data segment | 383 | | | | * `1 / WASM_COMDAT_FUNCTION` | 384 | | | | * `2 / WASM_COMDAT_GLOBAL` | 385 | | | | * `3 / WASM_COMDAT_EVENT` | 386 | | | | * `4 / WASM_COMDAT_TABLE` | 387 | | | | * `5 / WASM_COMDAT_SECTION` | 388 | | index | `varuint32` | Index of the data segment/function/global/event/table in the Wasm module (depending on kind). The function/global/event/table must not be an import. | 389 | 390 | ## Target Features Section 391 | 392 | The target features section is an optional custom section with the name 393 | "target_features". The target features section must come after the 394 | ["producers"](./ProducersSection.md) section. 395 | 396 | The contents of the target features section is a vector of entries: 397 | 398 | | Field | Type | Description | 399 | | ------- | ------- | ---------------------------------------- | 400 | | prefix | `byte` | See below. | 401 | | feature | `bytes` | The name of the feature. Must be unique. | 402 | 403 | The recognized prefix bytes and their meanings are below. When the user does not 404 | supply a set of allowed features explicitly, the set of allowed features is 405 | taken to be the set of used features. Any feature not mentioned in an object's 406 | target features section is not used by that object, but is not necessarily 407 | prohibited in the final binary. 408 | 409 | | Prefix | Meaning | 410 | | ---------- | ------- | 411 | | 0x2b (`+`) | This object uses this feature, and the link fails if this feature is not in the allowed set. | 412 | | 0x2d (`-`) | This object does not use this feature, and the link fails if this feature is in the allowed set. | 413 | 414 | The generally accepted features are: 415 | 416 | 1. `atomics` 417 | 1. `bulk-memory` 418 | 1. `bulk-memory-opt` 419 | 1. `call-indirect-overlong` 420 | 1. `exception-handling` 421 | 1. `extended-const` 422 | 1. `memory64` 423 | 1. `multimemory` 424 | 1. `multivalue` 425 | 1. `mutable-globals` 426 | 1. `nontrapping-fptoint` 427 | 1. `reference-types` 428 | 1. `relaxed-simd` 429 | 1. `sign-ext` 430 | 1. `simd128` 431 | 1. `tail-call` 432 | 433 | These features generally correspond to feature proposals as standardized in the CG with two exceptions: 434 | `bulk-memory-opt` refers to the `memory.copy` and `memory.fill` operations (a subset of `bulk-memory`). 435 | `call-indirect-overlong` allows the table field of the `call_indirect` instruction to be encoded 436 | as an LEB (which allows multibyte "overlong" encodings of small integers); this is a subset of the 437 | `reference-types` proposal. 438 | 439 | ## Merging Global Sections 440 | 441 | Merging of the global sections requires the re-numbering of globals. This 442 | follows the normal rules for defining symbols: if two object files provide the 443 | same global symbol strongly, there is a link error; if two object files provide 444 | the symbol weakly, one is chosen. 445 | 446 | When creating non-relocatable output, the Wasm output shall have an import for 447 | each undefined strong symbol, and an export for each defined symbol with 448 | non-local linkage and non-hidden visibility. 449 | 450 | The linker may provide certain symbols itself, even if not defined by any 451 | object file. For example, the `__stack_pointer` symbol may be provided at 452 | link-time. 453 | 454 | ## Merging Event Sections 455 | 456 | Events are meant to represent various control-flow changing constructs of wasm. 457 | Currently, we have a 458 | [proposal](https://github.com/WebAssembly/exception-handling/blob/master/proposals/exception-handling/Exceptions.md) 459 | for one kind of events: exceptions, but the event section can be used to support 460 | other kinds of events in future as well. The event section is a list of declared 461 | events associated with the module. 462 | 463 | Merging of the event sections requires the re-numbering of events. This follows 464 | the normal rules for defining symbols: if two object files provide the same 465 | event symbol strongly, there is a link error; if two object files provide the 466 | symbol weakly, one is chosen. 467 | 468 | When creating non-relocatable output, the Wasm output shall have an import for 469 | each undefined strong symbol, and an export for each defined symbol with 470 | non-local linkage and non-hidden visibility. 471 | 472 | ## Merging Function Sections 473 | 474 | Merging of the function sections requires the re-numbering of functions. This 475 | requires modification to code sections at each location where a function 476 | index is embedded. There are currently two ways in which function indices are 477 | stored in the code section: 478 | 479 | 1. Immediate argument of the `call` instruction (calling a function) 480 | 2. Immediate argument of the `i32.const` instruction (taking the address of a 481 | function). 482 | 483 | The immediate argument of all such instructions are stored as padded LEB128 such 484 | that they can be rewritten without altering the size of the code section. For 485 | each such instruction a `R_WASM_FUNCTION_INDEX_LEB` or `R_WASM_TABLE_INDEX_SLEB` 486 | `reloc` entry is generated pointing to the offset of the immediate within the 487 | code section. 488 | 489 | The same technique applies for all function calls whether the function is 490 | imported or defined locally. 491 | 492 | When creating non-relocatable output, the Wasm output shall have an import for 493 | each undefined strong symbol, and an export for each defined symbol with 494 | non-local linkage and non-hidden visibility. 495 | 496 | ## Merging Data Sections 497 | 498 | Merging of data sections is performed by creating a new data section from the 499 | data segments in the object files. Data symbols (e.g. C/C+ globals) are 500 | represented in the object file as Wasm data segments with an associated data 501 | symbol, so each linked data symbol pulls its associated data segment into the 502 | linked output. 503 | 504 | Segments are merged according their type: segments with a common prefix such as 505 | `.data` or `.rodata` are merged into a single segment in the output data 506 | section. It is an error if this behavior would merge shared and unshared 507 | segments. 508 | 509 | The output data section is formed, essentially, by concatenating the data 510 | sections of the input files. Since the final location in linear memory of any 511 | given symbol is not known until link time, all references to data addresses with 512 | the code and data sections generate `R_WASM_MEMORY_ADDR_*` relocation entries, 513 | which reference a data symbol. 514 | 515 | Segments are linked as a whole, and a segment is either entirely included or 516 | excluded from the link. 517 | 518 | ## Merging Custom Sections 519 | 520 | Merging of custom sections is performed by concatenating all payloads for the 521 | customs sections with the same name. The section symbol will refer the resulting 522 | section, this means that the relocation entries addend that refer 523 | the referred custom section fields shall be adjusted to take new offset 524 | into account. 525 | 526 | ## COMDATs 527 | 528 | A COMDAT group may contain one or more functions, data segments, and/or custom sections. 529 | The linker will include all of these elements with a given group name from one object file, 530 | and will exclude any element with this group name from all other object files. 531 | 532 | ## Processing Relocations 533 | 534 | The final code and data sections are written out with relocations applied. 535 | 536 | `R_WASM_TYPE_INDEX_LEB` relocations cannot fail. The output Wasm file 537 | shall contain a newly-synthesised type section which contains entries for all 538 | functions and type relocations in the output. 539 | `R_WASM_TABLE_INDEX_*` relocations cannot fail. The output Wasm file shall 540 | contain a newly-synthesised table, which contains an entry for all defined or 541 | imported symbols referenced by table relocations. The output table elements 542 | shall begin at a non-zero offset within the table, so that a `call_indirect 0` 543 | instruction is guaranteed to fail. Finally, when processing table relocations 544 | for symbols which have neither an import nor a definition (namely, 545 | weakly-undefined function symbols), the value `0` is written out as the value 546 | of the relocation. 547 | 548 | `R_WASM_FUNCTION_INDEX_LEB` relocations may fail to be processed, in 549 | which case linking fails. This occurs if there is a weakly-undefined function 550 | symbol, in which case there is no legal value that can be written as the target 551 | of any `call` instruction. The frontend must generate calls to undefined weak 552 | symbols via a `call_indirect` instruction. 553 | 554 | `R_WASM_GLOBAL_INDEX_LEB` relocations may fail to be processed, in which 555 | case linking fails. This occurs if there is a weakly-undefined global symbol, 556 | in which case there is no legal value that can be written as the target of any 557 | `get_global` or `set_global` instruction. (This means the frontend must not 558 | generate weak globals which may not be defined; a definition or import must 559 | exist for all global symbols in the linked output.) 560 | 561 | `R_WASM_MEMORY_*` relocations cannot fail. The relocation's value is the offset 562 | within the linear memory of the symbol within the output segment, plus the 563 | symbol's addend. If the symbol is undefined (whether weak or strong), the value 564 | of the relocation shall be `0`. 565 | 566 | `R_WASM_FUNCTION_OFFSET_I32` relocations cannot fail. The values shall be 567 | adjusted to reflect new offsets in the code section. 568 | 569 | `R_WASM_SECTION_OFFSET_I32` relocation cannot fail. The values shall be 570 | adjusted to reflect new offsets in the combined sections. 571 | 572 | `R_WASM_EVENT_INDEX_LEB` relocations may fail to be processed, in which 573 | case linking fails. This occurs if there is a weakly-undefined event symbol, in 574 | which case there is no legal value that can be written as the target of any 575 | `throw` and `if_except` instruction. (This means the frontend must not generate 576 | weak events which may not be defined; a definition or import must exist for all 577 | event symbols in the linked output.) 578 | 579 | [names_sec]: https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md#name-section 580 | 581 | ## Start Section 582 | 583 | By default the static linker should not output a WebAssembly start 584 | section. Constructors are instead called from a synthetic function 585 | `__wasm_call_ctors` that the runtime and embedder should arrange to have called 586 | after instantiation. `__wasm_call_ctors` is not exported by default because it 587 | may be called by some other startup function defined by the runtime. For the 588 | embedder to call it directly it should be exported like any other function. 589 | 590 | Rationale: Use of the WebAssembly start function was considered for running 591 | static constructors and/or the main entry point to the program. However, 592 | running arbitrary code in the start section is currently problematic due to the 593 | fact the module exports not available to the embedder at the time when the start 594 | function runs. A common example is the module memory itself. If the code in 595 | the start function wants to transfer any data to the embedder (e.g. `printf`) 596 | this will not work as the embedded cannot yet access the modules memory. This 597 | extends to all embedder functions that might want to call back into the module. 598 | 599 | If some future version of the WebAssembly spec allows for module exports to be 600 | available during execution of the start function it will make sense to 601 | reconsider this. 602 | 603 | When shared memory is requested, a start function will be emitted to initialize 604 | memory as described below. 605 | 606 | ## Experimental Threading Support 607 | 608 | By default all atomics and TLS are currently lowered to WebAssembly MVP and 609 | threads are not supported. However, when enabled, llvm does support an 610 | exprimental multithreading ABI based on the WebAssembly threads proposal. These 611 | features are used to support threading in Emscripten. 612 | 613 | The next section describes compatibility between threading features and MVP, and 614 | the following sections describe shared memory and TLS implementation based on 615 | bulk memory and experimental threading support. 616 | 617 | ### Lowering Atomics and TLS to MVP 618 | 619 | MVP WebAssembly does not include support for atomic operations or the bulk 620 | memory operations necessary to implement thread-local storage. As a result, any 621 | atomics or TLS present at the source level must be lowered to non-atomic 622 | operations and normal storage when targeting MVP WebAssembly. This is safe as 623 | long as the resulting MVP object files are not used in a multi-threaded context. 624 | 625 | To enforce this safety guarantee, the linker will error out if a shared memory 626 | is requested but the `atomics` target feature is disallowed in the target 627 | features section of any input objects. The compiler is responsible for marking 628 | `atomics` disallowed and thereby preventing thread-unsafe linking if either 629 | atomic operations or TLS are stripped during compilation. If the compiler 630 | removes either one of atomic operations or TLS, the resulting object may only be 631 | used with a single thread with an unshared memory, so the other one should be 632 | removed as well. 633 | 634 | If `atomics` or `bulk-memory` is not available during compilation but the source 635 | does not contain atomic operations or TLS, then the result is a 636 | "thread-agnostic" object that neither uses nor disallows the `atomics` feature. 637 | Thread-agnostic objects can be safely linked with objects that do or do not use 638 | `atomics`, although not both at the same time. 639 | 640 | ### Shared Memory and Passive Segments 641 | 642 | When shared memory is enabled, all data segments will be emitted as [passive 643 | segments][passive_segments] to prevent each thread from reinitializing 644 | memory. In a web context, using active segments would cause memory to be 645 | reinitialized every time the module is instantiated on a new WebWorker as part 646 | of spawning a new thread. The `memory.init` instructions that initialize these 647 | passive segments and the `data.drop` instructions that mark them collectible 648 | will be emitted into a synthetic function `__wasm_init_memory` that is made the 649 | WebAssembly start function and called automatically on instantiation but is not 650 | exported. `__wasm_init_memory` shall perform any synchronization necessary to 651 | ensure that no thread returns from instantiation until memory has been fully 652 | initialized, even if a module is instantiated on multiple threads 653 | simultaneously. This synchronization may involve waiting, but waiting is 654 | disallowed in some Web contexts such as on the main thread or in Audio worklets. 655 | For instantiation to succeed on all threads, the embedder must guarantee for 656 | each thread in a context that disallows waiting that the thread either wins the 657 | race and becomes responsible for initializing memory or that it is initialized 658 | after memory has already been initialized[1]. To make the `memory.init` and 659 | `data.drop` instructions valid, a [DataCount section][datacount_section] will 660 | also be emitted. 661 | 662 | Note that `memory.init` and the DataCount section are features of the 663 | bulk-memory proposal, not the atomics proposal, so any engine that supports 664 | threads needs to support both of these proposals. 665 | 666 | [1] In LLVM 13 and earlier, embedders had to guarantee that threads on contexts 667 | that disallow waiting had to win the race to initialize memory. That meant that 668 | there could only be one such thread in the system. 669 | 670 | [passive_segments]: https://github.com/WebAssembly/bulk-memory-operations/blob/master/proposals/bulk-memory-operations/Overview.md#design 671 | [datacount_section]: https://github.com/WebAssembly/bulk-memory-operations/blob/master/proposals/bulk-memory-operations/Overview.md#datacount-section 672 | 673 | ### Thread Local Storage 674 | 675 | Currently, thread-local storage is only supported in the main WASM module 676 | and cannot be accessed outside of it. This corresponds to the ELF local 677 | exec TLS model. 678 | 679 | Additionally, thread local storage depends on bulk memory instructions, and 680 | therefore support depends on the bulk memory proposal. 681 | 682 | All thread local variables will be merged into one passive segment called 683 | `.tdata`. This section contains the starting values for all TLS variables. 684 | The thread local block of every thread will be initialized with this segment. 685 | 686 | In a threaded build, the linker will create: 687 | 688 | * an immutable global variable of type `i32` called `__tls_size`. 689 | Its value is the total size of the thread local block for the module, 690 | i.e. the sum of the sizes of all thread local variables plus padding. 691 | This value will be `0` if there are no thread-local variables. 692 | * an immutable global variable of type `i32` called `__tls_align`. 693 | Its value is the alignment requirement of the thread local block, in bytes, 694 | and will be a power of 2. The value will be `1` if there are no thread-local 695 | variables. 696 | * a mutable global `i32` called `__tls_base`, with a `i32.const 0` initializer. 697 | * a global function called `__wasm_init_tls` with signature `(i32) -> ()`. 698 | 699 | To initialize thread-local storage, a thread should do the equivalent of the 700 | following pseudo-code upon startup: 701 | 702 | (if (global.get __tls_size) (then 703 | (call __wasm_init_tls 704 | (call aligned_alloc 705 | (global.get __tls_align) 706 | (call roundUpToMultipleOf 707 | (global.get __tls_align) 708 | (global.get __tls_size)))))) 709 | 710 | `__wasm_init_tls` takes a pointer argument containing the memory block to use 711 | as the thread local storage block of the current thread. It should do nothing if 712 | there are no thread-local variables. Otherwise, the memory block will be 713 | initialized with the passive segment `.tdata` via the `memory.init` instruction. 714 | It will then set `__tls_base` to the address of the memory block passed to 715 | `__wasm_init_tls`. 716 | 717 | Note that `__tls_size` is not necessarily a multiple of `__tls_align`. In order to 718 | use `aligned_alloc`, we must round the size up to be a multiple of `__tls_align`. 719 | 720 | The relocations for thread local variables shall resolve into offsets relative to 721 | the start of the TLS block. As such, adding the value of `__tls_base` yields the 722 | actual address of the variable. For example, a variable called `tls_var` would 723 | have its address computed as follows: 724 | 725 | (i32.add (global.get __tls_base) (i32.const tls_var)) 726 | 727 | The variable can then be used as normal. Upon thread exit, the runtime should free 728 | the memory allocated for the TLS block. 729 | 730 | ### Limitations 731 | 732 | - There is currently no support for passive data segments. The relocation types 733 | necessary for referencing such segments (e.g. in `data.drop` or `memory.init` 734 | instruction) do not yet exist. 735 | - There is currently no support for table element segments, either active or 736 | passive. 737 | -------------------------------------------------------------------------------- /ProducersSection.md: -------------------------------------------------------------------------------- 1 | # Producers Section 2 | 3 | The purpose of the producers section is to provide an optional, 4 | highly-structured record of all the distinct tools that were used to produce 5 | a given WebAssembly module. A primary purpose of this record is to allow 6 | broad analysis of toolchain usage in the wild, which can help inform both wasm 7 | producers and consumers. 8 | 9 | The producers section is a 10 | [custom section](https://webassembly.github.io/spec/core/binary/modules.html#custom-section) 11 | and thus has no semantic effects and can be stripped at any time. 12 | Since the producers section is relatively small, tools are encouraged to emit 13 | the section or include themselves in an existing section by default, keeping 14 | the producers section even in release builds. 15 | 16 | WebAssembly consumers should avoid using the producers section to derive 17 | optimization hints. To ensure portable performance, hints should be 18 | standardized in a separate custom section, probably in the core spec's 19 | [Custom Sections appendix](https://webassembly.github.io/spec/core/appendix/custom.html). 20 | 21 | An additional goal of the producers section is to provide a discrete, but 22 | easily-growable [list of known tools/languages](#known-list) for each 23 | record field. This avoids the skew that otherwise happens with unstructured 24 | strings. Unknown names do not invalidate an otherwise-valid producers section. 25 | However, wasm consumers may provide less accurate telemetry results for unknown 26 | names or even emit diagnostics encouraging the name to be put on the known list. 27 | 28 | Since version information is useful, but highly-variable, each field value 29 | is accompanied with a version string so that the name can remain stable 30 | over time without requiring frequent updates to the known list. 31 | 32 | ## Custom Section 33 | 34 | Custom section `name` field: `producers` 35 | 36 | The producers section may appear only once, and only after the 37 | [Name section](https://webassembly.github.io/spec/core/appendix/custom.html#name-section). 38 | 39 | The producers section contains a sequence of fields with unique names, where the 40 | end of the last field must coincide with the last byte of the producers section: 41 | 42 | | Field | Type | Description | 43 | | ----------- | ----------- | ----------- | 44 | | field_count | `varuint32` | number of fields that follow | 45 | | fields | `field*` | sequence of field_count `field` records | 46 | 47 | where a `field` is encoded as: 48 | 49 | | Field | Type | Description | 50 | | ----------------- | ---- | ----------- | 51 | | field_name | [name][name-ref] | name of this field | 52 | | field_value_count | `varuint32` | number of value strings that follow | 53 | | field_values | `versioned-name*` | sequence of field_value_count name-value pairs | 54 | 55 | where a `versioned-name` is encoded as: 56 | 57 | | Field | Type | Description | 58 | | ------- | ---- | ----------- | 59 | | name | [name][name-ref] | name of the language/tool | 60 | | version | [name][name-ref] | version of the language/tool | 61 | 62 | with the additional constraint that each field_name in the list must be unique 63 | and found in the first column of the following table, and each of a given field_name's 64 | field_values's name strings must be unique and found in the second column of 65 | the field_name's row. 66 | 67 | | field_name | field_value name strings | 68 | | -------------- | -------------------- | 69 | | `language` | [source language list](#source-languages) | 70 | | `processed-by` | [individual tool list](#individual-tools) | 71 | | `sdk` | [SDK list](#sdks) | 72 | 73 | [name-ref]: https://webassembly.github.io/spec/core/binary/values.html#names 74 | 75 | ## Known list 76 | 77 | The following lists contain all the known names for the fields listed above. 78 | **If your tool is not on this list and you'd like it to be, please submit a PR.** 79 | 80 | ### Source Languages 81 | 82 | It is possible for multiple source languages to be present in a single module 83 | when the output of multiple compiled languages are statically linked together. 84 | 85 | * `wat` 86 | * `C` 87 | * `C++` 88 | * `Rust` 89 | * `JavaScript` 90 | 91 | ### Individual Tools 92 | 93 | It is possible (and common) for multiple tools to be used in the overall 94 | pipeline that produces and optimizes a given wasm module. 95 | 96 | * `wabt` 97 | * `LLVM` 98 | * `clang` 99 | * `lld` 100 | * `Binaryen` 101 | * `rustc` 102 | * `wasm-bindgen` 103 | * `wasm-pack` 104 | * `webassemblyjs` 105 | * `wasm-snip` 106 | * `Javy` 107 | 108 | ### SDKs 109 | 110 | While an SDK is technically just another tool, the `sdk` field designates the 111 | top-level "thing" that the developer installs and interacts with directly to 112 | produce the wasm module. 113 | 114 | * `Emscripten` 115 | * `Webpack` 116 | 117 | ## Text format 118 | 119 | The text format for the `producers` custom section uses [annotations proposal] 120 | extension to the WebAssembly text format. The text format looks like: 121 | 122 | [annotations proposal]: https://github.com/WebAssembly/annotations 123 | 124 | ```wasm 125 | (module 126 | (@producers 127 | (processed-by "rustc" "1.78.0 (9b00956e5 2024-04-29)") 128 | (language "Rust" "1.78.0") 129 | ) 130 | ) 131 | ``` 132 | 133 | The `(@producers ...)` structure must be placed directly within a `(module 134 | ...)` declaration. Within `@producers` there is a list of parenthesis-delimited 135 | fields. The three accepted fields correspond to the three possible `field_name`s 136 | above: 137 | 138 | * `(language ...)` 139 | * `(processed-by ...)` 140 | * `(sdk ...)` 141 | 142 | Each field takes two strings corresponding to the `name` and `version` fields of 143 | the `versioned-name` construction in the custom section. For example: 144 | 145 | ```wasm 146 | (module 147 | (@producers 148 | (language "C" "18.1.2") 149 | (processed-by "LLVM" "18.1.2") 150 | (sdk "Emscripten" "3.1.60") 151 | ) 152 | ) 153 | ``` 154 | 155 | The three fields can be specified in any order and any number of times. 156 | 157 | ```wasm 158 | (module 159 | (@producers 160 | (sdk "Emscripten" "3.1.60") 161 | (processed-by "LLVM" "18.1.2") 162 | (language "C" "18.1.2") 163 | (processed-by "LLVM" "17.1.0") 164 | (language "Rust" "1.78.0") 165 | (processed-by "clang" "18.1.2") 166 | ) 167 | ) 168 | ``` 169 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | WebAssembly Tool Conventions 2 | ============================ 3 | 4 | This repository holds documents describing *conventions* useful for coordinating 5 | interoperability between wasm-related tools. This includes descriptions of 6 | intermediate file formats, conventions for mapping high-level language types, 7 | names, and abstraction features to WebAssembly types, identifiers, and 8 | implementations, and schemes for supporting debuggers or other tools. 9 | 10 | These conventions are not part of the WebAssembly standard, and are not required 11 | of WebAssembly-consuming implementations to execute WebAssembly code. Tools 12 | producing and working with WebAssembly in other ways also need not follow any of 13 | these conventions. They exist only to support tools that wish to interoperate 14 | with other tools at a higher abstraction level than just WebAssembly itself. 15 | 16 | These conventions are also not exclusive. There could be multiple conventions 17 | for a given language for a given purpose. There are natural benefits to 18 | interoperability, but there are many reasons where having more than one way to 19 | do things can also make sense in many circumstances. 20 | -------------------------------------------------------------------------------- /SetjmpLongjmp.md: -------------------------------------------------------------------------------- 1 | # C setjmp/longjmp in WebAssembly 2 | 3 | ## Overview 4 | 5 | This document describes a convention to implement C setjmp/longjmp via 6 | [WebAssembly exception-handling proposal]. 7 | 8 | This document also briefly mentions another convention based on JavaScript 9 | exceptions. 10 | 11 | [WebAssembly exception-handling proposal]: https://github.com/WebAssembly/exception-handling 12 | 13 | ## Runtime ABI 14 | 15 | ### Linear memory structures 16 | 17 | This convention uses a few structures on the WebAssembly linear memory. 18 | 19 | #### Reserved area in jmp_buf 20 | 21 | The first 6 words of C jmp_buf is reserved for the use by the runtime. 22 | ("words" here are C pointer types specified in the [C ABI].) 23 | It should have large enough alignment to store C pointers. 24 | The actual contents of this area are private to the runtime implementation. 25 | 26 | [C ABI]: BasicCABI.md 27 | 28 | ##### Notes about the size of reserved area in jmp_buf 29 | 30 | Emscripten has been using 6 `unsigned long`s. (`unsigned long [6]`) 31 | 32 | GCC and Clang uses `intptr_t [5]` for their [setjmp/longjmp builtins]. 33 | It isn't relevant right now though, because LLVM's WebAssembly target 34 | doesn't provide these builtins. 35 | 36 | [setjmp/longjmp builtins]: https://gcc.gnu.org/onlinedocs/gcc/Nonlocal-Gotos.html 37 | 38 | #### __WasmLongjmpArgs 39 | 40 | An equivalent of the following structure is used to associate necessary 41 | data to the WebAssembly exception. 42 | 43 | ```c 44 | struct __WasmLongjmpArgs { 45 | void *env; // a pointer to jmp_buf 46 | int val; 47 | }; 48 | ``` 49 | 50 | The lifetime of this structure is rather short. It lives only during a 51 | single longjmp execution. 52 | A runtime can use a part of `jmp_buf` for this structure. It's also ok to use 53 | a separate thread-local storage to place this structure. A runtime without 54 | multi-threading support can simply place this structure in a global variable. 55 | 56 | ### Exception tag 57 | 58 | This convention uses a WebAssembly exception to perform a non-local jump 59 | for C `longjmp`. 60 | 61 | The exception is created with an exception tag named `__c_longjmp`. 62 | The name is used for both of [static linking](Linking.md) and 63 | [dynamic linking](DynamicLinking.md). 64 | The type of exception tag is `(param i32)`. (Or, `(param i64)` for [memory64]) 65 | The parameter is the address of the `__WasmLongjmpArgs` structure on the 66 | linear memory. 67 | 68 | [memory64]: https://github.com/WebAssembly/memory64 69 | 70 | ### Functions 71 | 72 | ```c 73 | void __wasm_setjmp(jmp_buf env, uint32_t label, void *func_invocation_id); 74 | uint32_t __wasm_setjmp_test(jmp_buf env, void *func_invocation_id); 75 | void __wasm_longjmp(jmp_buf env, int val); 76 | ``` 77 | 78 | `__wasm_setjmp` records the necessary data in the `env` so that it can be 79 | used by `__wasm_longjmp` later. 80 | `label` is a non-zero identifier to distinguish setjmp call-sites within 81 | the function. Note that a C function can contain multiple setjmp() calls. 82 | `func_invocation_id` is the identifier to distinguish invocations of this 83 | C function. Note that, when a C function which calls setjmp() is invoked 84 | recursively, setjmp/longjmp needs to distinguish them. 85 | 86 | `__wasm_setjmp_test` tests if the longjmp target belongs to the current 87 | function invocation. if it does, this function returns the `label` value 88 | saved by `__wasm_setjmp`. Otherwise, it returns 0. 89 | 90 | `__wasm_longjmp` is similar to C `longjmp`. 91 | If `val` is 0, it's `__wasm_longjmp`'s responsibility to convert it to 1. 92 | It performs a long jump by filling a `__WasmLongjmpArgs` structure and 93 | throwing an exception with its address. The exception is created with 94 | the `__c_longjmp` exception tag. 95 | 96 | ## Code conversion 97 | 98 | The C compiler detects `setjmp` and `longjmp` calls in a program and 99 | converts them into the corresponding WebAssembly exception-handling 100 | instructions and calls to the above mentioned runtime ABI. 101 | 102 | ### Functions calling setjmp() 103 | 104 | On the function entry, the compiler would generate the logic to create 105 | the identifier of this function invocation, typically by performing an 106 | equivalent of `alloca(1)`. Note that the alloca size is not important 107 | because the pointer is merely used as an identifier and never be dereferenced. 108 | 109 | Also, the compiler converts C `setjmp` calls to `__wasm_setjmp` calls. 110 | 111 | For each setjmp callsite, the compiler allocates non-zero identifier called 112 | "label". The label value passed to `__wasm_setjmp` is recorded by the 113 | runtime and returned by later `__wasm_setjmp_test` when processing a longjmp 114 | to the corresponding jmp_buf. 115 | 116 | Also, for code blocks which possibly call `longjmp` directly or indirectly, 117 | the compiler generates instructions to catch and process exceptions with 118 | the `__c_longjmp` exception tag accordingly. 119 | 120 | When catching the exception, the compiler-generated logic calls 121 | `__wasm_setjmp_test` to see if the exception is for this invocation 122 | of this function. 123 | If it is, `__wasm_setjmp_test` returns the non-zero label value recorded by 124 | the last `__wasm_setjmp` call for the jmp_buf. The compiler-generated logic 125 | can use the label value to pretend a return from the corresponding setjmp. 126 | Otherwise, `__wasm_setjmp_test` returns 0. In that case, the 127 | compiler-generated logic should rethrow the exception by calling 128 | `__wasm_longjmp` so that it can be eventually caught by the right function. 129 | 130 | For an example, a C function like this would be converted like 131 | the following pseudo code. 132 | ```c 133 | void f(void) { 134 | jmp_buf env; 135 | if (!setjmp(env)) { 136 | might_call_longjmp(env); 137 | } 138 | } 139 | ``` 140 | 141 | ```wat 142 | $func_invocation_id = alloca(1) 143 | 144 | ;; 100 is a label generated by the compiler 145 | call $__wasm_setjmp($env, 100, $func_invocation_id) 146 | 147 | block 148 | block (result i32) 149 | try_table (catch $__c_longjmp 0) 150 | call $might_call_longjmp 151 | end 152 | ;; might_call_longjmp didn't call longjmp 153 | br 1 154 | end 155 | ;; might_call_longjmp called longjmp 156 | pop __WasmLongjmpArgs pointer from the operand stack 157 | $env = __WasmLongjmpArgs.env 158 | $val = __WasmLongjmpArgs.val 159 | $label = $__wasm_setjmp_test($env, $func_invocation_id) 160 | if ($label == 0) { 161 | ;; not for us. rethrow. 162 | call $__wasm_longjmp($env, $val) 163 | } 164 | ;; ours. 165 | ;; somehow jump to the block corresponding to the $label 166 | ... 167 | ... 168 | end 169 | ``` 170 | 171 | ### Longjmp calls 172 | 173 | The compiler converts C `longjmp` calls to `__wasm_longjmp` calls. 174 | 175 | ## Dynamic-linking consideration 176 | 177 | In case of [dynamic-linking], it's the dynamic linker's responsibility 178 | to provide the exception tag for this convention with the name 179 | "env.__c_longjmp". Modules should import the tag so that cross-module 180 | longjmp works. 181 | 182 | [dynamic-linking]: DynamicLinking.md 183 | 184 | ## Emscripten JavaScript-based exceptions 185 | 186 | Emscripten has a mode to use JavaScript-based exceptions instead of 187 | WebAssembly exceptions. In that mode, `emscripten_longjmp` function, 188 | which throws a JavaScript exception, is used instead of `__wasm_longjmp`. 189 | 190 | ```c 191 | void emscripten_longjmp(uintptr_t env, int val); 192 | ``` 193 | 194 | The compiler translates C function calls which possibly ends up with 195 | calling `longjmp` to indirect calls via a JavaScript wrapper which 196 | catches the JavaScript exception. 197 | 198 | ## Implementations 199 | 200 | * LLVM (19 and later) has a pass ([WebAssemblyLowerEmscriptenEHSjLj.cpp]) 201 | to perform the convertion mentioned above. It can be enabled with the 202 | `-mllvm -wasm-enable-sjlj` option. 203 | 204 | Note: as of writing this, LLVM produces a bit older version of 205 | exception-handling instructions. (`try`, `delegate`, etc) 206 | binaryen has a conversion from the old instructions to the latest 207 | instructions. (`try_table` etc.) 208 | 209 | * Emscripten (3.1.57 or later) has the runtime support ([emscripten_setjmp.c]) 210 | for the convention documented above. 211 | 212 | * wasi-libc has the runtime support ([wasi-libc rt.c]) for the convention 213 | documented above. 214 | 215 | [WebAssemblyLowerEmscriptenEHSjLj.cpp]: https://github.com/llvm/llvm-project/blob/70deb7bfe90af91c68454b70683fbe98feaea87d/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp 216 | 217 | [emscripten_setjmp.c]: https://github.com/emscripten-core/emscripten/blob/7d66497d96cdcffa394ad67d87f7118137edf9ab/system/lib/compiler-rt/emscripten_setjmp.c 218 | 219 | [wasi-libc rt.c]: https://github.com/WebAssembly/wasi-libc/blob/d03829489904d38c624f6de9983190f1e5e7c9c5/libc-top-half/musl/src/setjmp/wasm32/rt.c 220 | 221 | ## Future directions 222 | 223 | * `__WasmLongjmpArgs` can be replaced with WebAssembly multivalue. 224 | 225 | * Or, alternatively, we can make `__wasm_setjmp_test` take the 226 | `__WasmLongjmpArgs` pointer so that we can drop the `__WasmLongjmpArgs` 227 | structure layout from the ABI. 228 | 229 | * It might be simpler for the complier-generated catching logic to rethrow 230 | the exception with the `rethrow`/`throw_ref` instruction instead of 231 | calling `__wasm_longjmp`. Or, it might be simpler to make 232 | `__wasm_setjmp_test` rethow the exception internally. 233 | 234 | * If/When WebAssembly exception gets more ubiquitous, we might want to move 235 | the runtime to compiler-rt. 236 | -------------------------------------------------------------------------------- /Signatures.md: -------------------------------------------------------------------------------- 1 | # WebAssembly module signatures 2 | 3 | This document describes a digital signature format specifically designed for WebAssembly modules. 4 | 5 | It satisfies the following requirements: 6 | 7 | - Is is possible to verify a module before execution. 8 | - It is possible to add signed custom sections to an already signed module. 9 | - It is possible to verify a subset of the module sections, at predefined boundaries. 10 | - The entire module doesn't have to fit in memory in order for a signature to be verified. 11 | - Signatures can be embedded in a custom section, or provided separately ("detached signatures"). 12 | - Multiple signatures and algorithms can be used to sign a single module. 13 | - Signing an entire module doesn't require the module to be modified. 14 | 15 | Signatures have no semantic effects. A runtime that doesn't support signatures can ignore them. 16 | 17 | Note: this is still a work in progress. 18 | 19 | ## Discussion venues 20 | 21 | The [WebAssembly Modules Signatures](https://github.com/wasm-signatures/design) repository is the main discussion venue for this project. 22 | 23 | We also hold bimonthly open meetings. See the above repository for details. 24 | 25 | ## Custom sections 26 | 27 | Two custom section types are required for this signature format: 28 | 29 | - Custom sections named `signature`, storing signature data, when this information is embedded in the module. 30 | - Custom sections named `signature_delimiter`, separating consecutive sections that can be signed and verified independently. 31 | 32 | Example structure of a module with an embedded signature and delimiters: 33 | 34 | | sections | 35 | | ----------------------------------------- | 36 | | signature | 37 | | part _(one or more consecutive sections)_ | 38 | | delimiter | 39 | | part _(one or more consecutive sections)_ | 40 | | delimiter | 41 | | ... | 42 | | part _(one or more consecutive sections)_ | 43 | | delimiter | 44 | 45 | ## Parts and delimiters 46 | 47 | A module can be split into one or more parts (one or more consecutive sections). 48 | Each part is followd by a delimiter. A delimiter is a custom section named `signature_delimiter`, containing a 16 byte random string. 49 | 50 | | sections | 51 | | ---------------------------------------------- | 52 | | `p1` = input part 1 _(one or more sections)_ | 53 | | `d1` = delimiter 1 | 54 | | `p2` = input part 2 _(one or more sections)_ | 55 | | `d2` = delimiter 2 | 56 | | ... | 57 | | `pn` = input part `n` _(one or more sections)_ | 58 | | `dn` = delimiter `n` | 59 | 60 | If a signature covers the entire module (i.e. there is only one part), the delimiter is optional. 61 | 62 | However, its absence prevents additional sections to be added and signed later. 63 | 64 | ## Signature data 65 | 66 | The signature data is a concatenation of the following: 67 | 68 | - An identifier representing the version of the specification the module was signed with. 69 | - An identifier representing the hash function whose output will be signed. 70 | - A sequence of hashes and their signatures. 71 | 72 | A hash is computed for all the parts to be signed: 73 | 74 | `hn = H(pn‖dn)` 75 | 76 | A signature is computed on the concatenation of these hashes: 77 | 78 | `hashes = h1 ‖ h2 ‖ … ‖ hn` 79 | 80 | `s = Sign(k, "wasmsig" ‖ spec_version ‖ hash_id ‖ hashes)` 81 | 82 | One or more signatures can be associated with `hashes`, allowing multiple parties to sign the same data. 83 | 84 | The signature data can either be stored in the payload of a custom section named `signature`, or provided separately. 85 | 86 | If embedded in a module, the section must be the first section of the module. 87 | 88 | The signature data contains a sequence of signatures, where the end of the last signature must coincide with the last byte of the data. 89 | 90 | | Field | Type | Description | 91 | | ------------------- | ----------- | --------------------------------------------- | 92 | | spec_version | `byte` | Specification version (`0x01`) | 93 | | hash_fn | `byte` | Hash function identifier (`0x01` for SHA-256) | 94 | | signed_hashes_count | `varuint32` | Number of signed hashes | 95 | | signed_hashes* | `byte` | Sequence of hashes and their signatures | 96 | 97 | where `signed_hashes` is encoded as: 98 | 99 | | Field | Type | Description | 100 | | --------------- | ------------ | ------------------------------------------------- | 101 | | hashes_count | `varuint32` | Number of the concatenated hashes in bytes | 102 | | hashes | `bytes` | Concatenated hashes of the signed sections | 103 | | signature_count | `varuint32` | Number of signatures | 104 | | signatures | `signature*` | Sequence of `signature_count` `signature` records | 105 | 106 | where a `signature` is encoded as: 107 | 108 | | Field | Type | Description | 109 | | ------------- | ----------- | ---------------------------------------------------------- | 110 | | key_id_len | `varuint32` | Public key identifier length in bytes (can be `0`) | 111 | | key_id | `bytes` | Public key identifier | 112 | | signature_id | `byte` | Signature algorithm identifier | 113 | | signature_len | `varuint32` | Signature length in bytes | 114 | | signature | `bytes` | Signature for `hashes` that can be verified using `key_id` | 115 | 116 | ## Signature verification algorithm for an entire module 117 | 118 | 1. Verify the presence of the signature section, extract the specification version, the hash function to use and the signatures. 119 | 2. Check that at least one of the signatures is valid for `hashes`. If not, return an error and stop. 120 | 3. Split `hashes` (included in the signature) into `h1 … hn` 121 | 4. Read the module, computing the hash of every `(pi, di)` tuple with `i ∈ {1 … n}`, immediately returning an error if the output doesn't match `hi` 122 | 5. Return an error if the number of the number of hashes doesn't match the number of parts. 123 | 124 | ## Partial signatures 125 | 126 | The above format is compatible with partial signatures, i.e. signatures ignoring one or more parts. 127 | 128 | In order to do so, a signer only includes hashes of relevant parts. 129 | 130 | ## Partial verification 131 | 132 | The format is compatible with partial verification, i.e. verification of an arbitrary subset of a module: 133 | 134 | 1. Verify the presence of the header, extract the specification version, the hash function to use and the signatures. 135 | 2. Check that at least one of the signatures is valid for `hashes`. If not, return an error and stop. 136 | 3. Split `hashes` (included in the signature) into `h1 … hm` with `m` being the last section to verify. 137 | 4. Read the module, computing the hash of the `(pi, di)` tuples to verify, immediately returning an error if the output doesn't match `hi`. 138 | 5. Return an error if the number of the number of hashes doesn't match the number of parts to verify. 139 | 140 | Notes: 141 | 142 | - Subset verification doesn't require additional signatures, as verification is always made using the full set `hashes`. 143 | - Verifiers don't learn any information about removed sections due to delimiters containing random bits. 144 | 145 | By default, partial signatures must be ignored by WebAssembly runtimes. An explicit configuration is required to accept a partially signed module. 146 | 147 | ## Equivalence between embedded and detached signatures 148 | 149 | Signatures can be embedded in a module, or detached, i.e. not stored in the module itself but provided separately. 150 | 151 | A detached signature is equivalent to the payload of a `signature` custom section. 152 | 153 | Given an existing signed module with an embedded signature, the signature can be detached by: 154 | 155 | - Copying the payload of the `signature` custom section 156 | - Removing the `signature` custom section. 157 | 158 | Reciprocally, a detached signature can be embedded by adding a `signature` custom section, whose payload is a copy of the detached signature. 159 | 160 | Implementations should accept signatures as an optional parameter. If this parameter is not defined, the signature is assumed to be embedded, but the verification function remains the same. 161 | 162 | ## Algorithms and identifiers 163 | 164 | Identifier for the current version of the specification: `0x01` 165 | 166 | A conformant implementation must include support for the following hash functions: 167 | 168 | | Function | Identifier | 169 | | -------- | ---------- | 170 | | SHA-256 | `0x01` | 171 | 172 | ## Signature algorithms and key serialization 173 | 174 | For interoperability purposes, a conformant implementation must include support for the following signature systems: 175 | 176 | - Ed25519 (RFC8032) 177 | 178 | Public and private keys must include the algorithm and parameters they were created for. 179 | 180 | | Key type | Serialized key size | Identifier | 181 | | ------------------ | ------------------- | ---------- | 182 | | Ed25519 public key | 1 + 32 bytes | `0x01` | 183 | | Ed25519 key pair | 1 + 64 bytes | `0x81` | 184 | 185 | Ed25519 algorithm identifier: `0x01`. 186 | 187 | Representation of Ed25519 keys: 188 | 189 | - Ed25519 public key: 190 | 191 | `0x01 ‖ public key (32 bytes)` 192 | 193 | - Ed25519 key pair: 194 | 195 | `0x81 ‖ secret key (32 bytes) ‖ public key (32 bytes)` 196 | 197 | Implementations may support additional signatures schemes and key encoding formats. 198 | 199 | ## Appendix A. Examples 200 | 201 | The following examples assume the following unsigned module structure as a common starting point: 202 | 203 | ```text 204 | 0: type section 205 | 1: import section 206 | 2: function section 207 | 3: table section 208 | 4: memory section 209 | 5: global section 210 | 6: export section 211 | 7: element section 212 | 8: code section 213 | 9: data section 214 | 10: custom section: [.debug_info] 215 | 11: custom section: [.debug_macinfo] 216 | 12: custom section: [.debug_loc] 217 | 13: custom section: [.debug_ranges] 218 | 14: custom section: [.debug_abbrev] 219 | 15: custom section: [.debug_line] 220 | 16: custom section: [.debug_str] 221 | 17: custom section: [name] 222 | 18: custom section: [producers] 223 | ``` 224 | 225 | ### Signatures for the entire module. 226 | 227 | Signed module structure: 228 | 229 | ```text 230 | 0: custom section: [signature] 231 | 1: type section 232 | 2: import section 233 | 3: function section 234 | 4: table section 235 | 5: memory section 236 | 6: global section 237 | 7: export section 238 | 8: element section 239 | 9: code section 240 | 10: data section 241 | 11: custom section: [.debug_info] 242 | 12: custom section: [.debug_macinfo] 243 | 13: custom section: [.debug_loc] 244 | 14: custom section: [.debug_ranges] 245 | 15: custom section: [.debug_abbrev] 246 | 16: custom section: [.debug_line] 247 | 17: custom section: [.debug_str] 248 | 18: custom section: [name] 249 | 19: custom section: [producers] 250 | 20: custom section: [signature_delimiter] 251 | ``` 252 | 253 | Content of the signature section, for a single signature: 254 | 255 | - `0x01` (spec_version) 256 | - `0x01` (hash_fn) 257 | - `1` (signed_hashes_count) 258 | - signed_hashes: 259 | - `1` (hashes_count) 260 | - `<32 bytes>` (hashes=SHA-256(sections 1..end)) 261 | - `1` (`signatures_count`) 262 | - signature: 263 | - `0` (`key_id_len` - no key ID) 264 | - `0x01` (Ed25519 algorithm identifier) 265 | - `64` (`signature_len`) 266 | - `<64 bytes>` (Ed22519(k, hashes)) 267 | 268 | ### Signatures allowing partial verification. 269 | 270 | In this example, a signature can be verified for any of the following ranges of sections: 271 | 272 | - 1..10 (until the custom sections) 273 | - 1..17 (code, data and debugging information) 274 | - 1..end (entire module) 275 | 276 | ```text 277 | 0: custom section: [signature] 278 | 1: type section 279 | 2: import section 280 | 3: function section 281 | 4: table section 282 | 5: memory section 283 | 6: global section 284 | 7: export section 285 | 8: element section 286 | 9: code section 287 | 10: data section 288 | 11: custom section: [signature_delimiter] 289 | 12: custom section: [.debug_info] 290 | 13: custom section: [.debug_macinfo] 291 | 14: custom section: [.debug_loc] 292 | 15: custom section: [.debug_ranges] 293 | 16: custom section: [.debug_abbrev] 294 | 17: custom section: [.debug_line] 295 | 18: custom section: [.debug_str] 296 | 19: custom section: [signature_delimiter] 297 | 20: custom section: [name] 298 | 21: custom section: [producers] 299 | 22: custom section: [signature_delimiter] 300 | ``` 301 | 302 | Content of the signature section, for a single signature: 303 | 304 | - `0x01` (spec_version) 305 | - `0x01` (hash_fn) 306 | - `1` (signed_hashes_count) 307 | - signed_hashes: 308 | - `3` (hashes_count) 309 | - `<96 bytes>` (hashes=SHA-256(sections 1..12) ‖ SHA-256(sections 1..20) ‖ SHA-256(sections 1..end)) 310 | - `1` (signatures_count) 311 | - signature: 312 | - `0` (key_id_len - no key ID) 313 | - `0x01` (Ed25519 algorithm identifier) 314 | - `64` (signature_len) 315 | - `<64 bytes>` (Ed22519(k, hashes)) 316 | 317 | Variant with two signatures for the same content and key identifiers: 318 | 319 | - `0x01` (spec_version) 320 | - `0x01` (hash_fn) 321 | - `1` (signed_hashes_count) 322 | - signed_hashes: 323 | - `3` (hashes_count) 324 | - `<96 bytes>` (hashes=SHA-256(sections 1..12) ‖ SHA-256(sections 1..20) ‖ SHA-256(sections 1..end)) 325 | - `2` (signatures_count) 326 | - signature_1: 327 | - `5` (key_id_len) 328 | - `"first"` (key_id) 329 | - `0x01` (Ed25519 algorithm identifier) 330 | - `64` (`signature_len`) 331 | - `<64 bytes>` (Ed22519(k_first, hashes)) 332 | - signature_2: 333 | - `6` (key_id_len) 334 | - `"second"` (key_id) 335 | - `0x01` (Ed25519 identifier) 336 | - `64` (`signature_len`) 337 | - `<64 bytes>` (Ed22519(k_second, hashes)) 338 | -------------------------------------------------------------------------------- /SwiftABI.md: -------------------------------------------------------------------------------- 1 | This document describes the Swift ABI for WebAssembly. As mentioned in README, it's not the only possible Swift ABI. It is the ABI that the clang/LLVM WebAssembly backend is currently using, and any other Swift compiler wishing to be ABI-compatible with it. 2 | 3 | Most parts of the ABI follow [the Swift ABI document in the official compiler repository](https://github.com/apple/swift/tree/master/docs/ABI) 4 | 5 | This document only describes what is necessary to be treated specially on WebAssembly. 6 | 7 | ## Swift Calling Convention 8 | 9 | Swift calling convention (`swiftcc` attribute in LLVM) is based on C calling convention as described [here](https://github.com/apple/swift/blob/master/docs/ABI/CallingConvention.rst) 10 | 11 | Swiftcc on WebAssembly is a little different from swiftcc on other architectures. 12 | 13 | On non-WebAssembly architectures, swiftcc accepts extra tail parameters that are attributed with swifterror or swiftself by a caller at the LLVM IR level and swifterror is always placed after swiftself. Even if the callee doesn't have these parameters at the LLVM IR level, the invocation succeeds by ignoring extra parameters. 14 | 15 | But WebAssembly strictly checks that [callee and caller signatures are the same](https://github.com/WebAssembly/design/blob/master/Semantics.md#calls). 16 | So at WebAssembly level, all swiftcc functions end up with extra arguments and all function definitions and invocations explicitly have additional tail parameters to fill swifterror and swiftself. 17 | 18 | For example, Swift global function `func foo(_ value: Int)` is lowered as `func (param i32 i32 i32)` at WebAssembly level. 19 | 20 | If you export swiftcc function and call it, you need the tail parameters. If the function did not have swiftself or swifterror at the IR level (and placeholders were added during lowering), then a placeholder may be passed any pointer size value. But if the embedding environment is JS, then missing params will be added as JS undefined and coerced to i32 as 0, so you don't need to fill them. This JS convention rule is documented at https://webassembly.github.io/spec/js-api/index.html 21 | --------------------------------------------------------------------------------