This page follows the binary format chapter of the WebAssembly core specification, release 3.0, which includes everything in 1.0 and 2.0. Features added by 2.0 and 3.0 are marked; a 1.0 module uses only the unmarked parts. Type encodings are on the types page and opcodes on instructions.
Values
| Kind | Encoding |
|---|---|
| byte | One byte. |
u32, u64 | Unsigned LEB128: seven bits per byte, lowest group first, top bit set on every byte but the last. At most ⌈N/7⌉ bytes (5 for u32, 10 for u64); unused bits of the last byte must be zero. Trailing zero groups are allowed within that length. |
s32, s33, s64 | Signed LEB128, two’s complement, at most ⌈N/7⌉ bytes; the unused bits of the last byte must be 0 for a positive value and 1 for a negative one. |
i32, i64 | Uninterpreted integers (such as i32.const values) are written as signed LEB128. |
f32, f64 | IEEE 754 bit pattern, 4 or 8 bytes, little-endian. |
| vec(T) | A u32 count, then that many T. |
| name | vec(byte) holding UTF-8 text. |
| index | A u32 (type, function, table, memory, global, tag, element, data, local, label and field indices). |
Examples: u32 624485 is E5 8E 26; s32 −1 is 7F; s32 64 is
C0 00.
Preamble
| Offset | Size | Field | Value |
|---|---|---|---|
0 | 4 | magic | 00 61 73 6D (\0asm) |
4 | 4 | version | 01 00 00 00: version 1, little-endian (still 1 in release 3.0). |
Sections
After the preamble come sections, each:
| Field | Encoding | Meaning |
|---|---|---|
| id | byte | Section ID, below. |
| size | u32 | Length of the contents in bytes. It must match the contents exactly. |
| contents | size bytes | Depends on the ID. |
| ID | Section | Contents | Since |
|---|---|---|---|
0 | custom | name, then any bytes | 1.0 |
1 | type | vec(rectype) | 1.0 (recursive types 3.0) |
2 | import | vec(import) | 1.0 |
3 | function | vec(typeidx) | 1.0 |
4 | table | vec(table) | 1.0 |
5 | memory | vec(memtype) | 1.0 |
6 | global | vec(global) | 1.0 |
7 | export | vec(export) | 1.0 |
8 | start | funcidx | 1.0 |
9 | element | vec(elem) | 1.0 (flags 1–7 in 2.0) |
10 | code | vec(code) | 1.0 |
11 | data | vec(data) | 1.0 (flags 1–2 in 2.0) |
12 | data count | u32 | 2.0 |
13 | tag | vec(tagtype) | 3.0 |
Every section is optional; a missing one counts as empty. Custom sections may appear anywhere, any number of times. The others appear at most once each and in this order, which differs from the ID order: type, import, function, table, memory, tag, global, export, start, element, data count, code, data. The function and code sections must have the same number of entries.
Section contents
Custom (0)
A name, then bytes to the end of the section. Custom sections do not affect how the module runs, and errors in them must not make the module invalid. The standard defines one, the name section.
Import (2)
| Field | Encoding |
|---|---|
| module | name |
| name | name |
| description | a kind byte and its type: 00 typeidx (function), 01 tabletype, 02 memtype, 03 globaltype, 04 tagtype (3.0) |
Function (3)
One type index per function the module defines; the bodies are in the code section, in the same order.
Table (4)
| Form | Encoding |
|---|---|
| plain | a tabletype; elements start as ref.null |
| with initialiser (3.0) | 40 00, a tabletype, then an expression giving the initial value |
Memory (5)
One memtype each. Releases 1.0 and 2.0 allow at most one memory (imported or defined); 3.0 allows several, chosen by a memory index in instructions.
Global (6)
A globaltype, then a constant expression for the initial value.
Export (7)
| Field | Encoding |
|---|---|
| name | name |
| kind | 00 function, 01 table, 02 memory, 03 global, 04 tag (3.0) |
| index | u32 into that index space |
Start (8)
The index of the module’s start function.
Element (9)
Element segments initialise tables. Each starts with a u32 flags value:
| Flags | Mode | Encoding after the flags |
|---|---|---|
0 | active, table 0 | offset expr, vec(funcidx) |
1 | passive | elemkind, vec(funcidx) |
2 | active, any table | tableidx, offset expr, elemkind, vec(funcidx) |
3 | declarative | elemkind, vec(funcidx) |
4 | active, table 0 | offset expr, vec(expr); function reference type |
5 | passive | reftype, vec(expr) |
6 | active, any table | tableidx, offset expr, reftype, vec(expr) |
7 | declarative | reftype, vec(expr) |
Bit 0 set: passive or declarative. Bit 1: with bit 0 clear, an explicit table
index; with bit 0 set, declarative rather than passive. Bit 2: the elements are
expressions with a reference type, rather than function indices with an elemkind.
The elemkind byte is 00 (function references); the specification notes
that more kinds may come later.
Code (10)
| Field | Encoding | Meaning |
|---|---|---|
| size | u32 | Bytes of the rest of this entry. |
| locals | vec(u32 count, valtype) | Runs of locals: count locals of each type. Parameters come first in the local index space; the total must stay below 232. |
| body | expr | Instructions ending with 0B. |
Data (11)
| Flags | Mode | Encoding after the flags |
|---|---|---|
0 | active, memory 0 | offset expr, vec(byte) |
1 | passive | vec(byte) |
2 | active, any memory | memidx, offset expr, vec(byte) |
Bit 0 marks a passive segment and bit 1 an explicit memory index.
Data count (12)
The number of data segments, so that code can be validated in one pass. It must
match the data section, and must be present if any code uses a data index
(memory.init, data.drop, array.new_data,
array.init_data).
Tag (13)
Exception tags, each a tagtype: 00 and the index of a function type
whose parameters are the exception’s values.
The name section
A custom section named name, placed after the data section, that gives
names to the module’s items for debuggers. It holds subsections, each a byte ID, a u32
size and the contents, in increasing ID order, each ID at most once.
| ID | Subsection | Contents |
|---|---|---|
0 | module name | name |
1 | function names | namemap by function index |
2 | local names | indirect namemap: by function index, then local index |
4 | type names | namemap by type index |
10 | field names | indirect namemap: by struct type index, then field index |
11 | tag names | namemap by tag index |
A namemap is vec(index, name), sorted by index with no duplicates. An indirect namemap is vec(index, namemap). IDs 3 and 5 to 9 are not defined by the specification.
Example
A module exporting a function f that returns 42:
00 61 73 6D 01 00 00 00 preamble
01 05 01 60 00 01 7F type section: 1 type, func () -> (i32)
03 02 01 00 function section: 1 function, type 0
07 05 01 01 66 00 00 export section: "f", function 0
0A 06 01 04 00 41 2A 0B code section: 1 body of 4 bytes:
no locals, i32.const 42, end
Sources
The WebAssembly core
specification, release 3.0: binary format chapters “Conventions” (lists),
“Values” (LEB128, floats, names), “Modules” (preamble, sections, every section’s
contents, order) and “Instructions” (i32.const, used in the example);
appendix “Custom Sections” (name section); appendix “Change History” (what 2.0 and
3.0 added). The LEB128 examples and the module bytes are worked out from those
rules.