wasm: add WASM 1.0 binary parser and disassembler
Implements a WASM 1.0 binary parser for KolibriOS written in x86 FASM. Parses all 12 sections of the WASM binary format and prints disassembly output. Tested against real WASM binaries. Sections implemented: type, import, function, table, memory, global, export, start, element, data, custom. Code section parsing is planned for the next commit.
This commit is contained in:
1 parent
f305d3425d
commit
e16589e95e
10 files changed
+2026
No files matched your search
@@ -0,0 +1,7 @@
|
||||
*.swp
|
||||
*.swo
|
||||
*.swn
|
||||
*~
|
||||
*.bin
|
||||
*.o
|
||||
*.obj
|
||||
@@ -0,0 +1,178 @@
|
||||
# kolibrios-wasm
|
||||
|
||||
A WebAssembly 1.0 runtime for [KolibriOS](http://kolibrios.org/), written in x86 FASM assembly.
|
||||
|
||||
## Status
|
||||
|
||||
Work in progress. Current state:
|
||||
|
||||
- Binary parser: WIP, tested on Linux and KolibriOS
|
||||
- Validator: Not Started
|
||||
- Interpreter: Not Started
|
||||
|
||||
## What it does
|
||||
|
||||
Parses WebAssembly 1.0 binary files according to the
|
||||
[WebAssembly 1.0 spec](https://webassembly.github.io/multi-value/core/_download/WebAssembly.pdf).
|
||||
|
||||
The parser currently:
|
||||
- Validates the magic number and version header
|
||||
- Fully parses all 12 WASM 1.0 sections
|
||||
- Decodes LEB128 u32, s32 integers as specified in the spec
|
||||
- Validates section boundaries — catches malformed binaries
|
||||
- Prints human-readable disassembly of all decoded data
|
||||
- Disassembles all 172 WASM 1.0 opcodes in function bodies (code section in progress)
|
||||
- Tested against real WASM binaries on both Linux and KolibriOS (QEMU)
|
||||
|
||||
## Project structure
|
||||
```
|
||||
src/
|
||||
core/
|
||||
wasm_const.inc # Wasm 1.0 binary format constants
|
||||
wasm_name.inc # Value type name strings
|
||||
wasm_func.inc # LEB128 decoder
|
||||
wasm_parser.inc # Binary parser
|
||||
kolibrios/
|
||||
includes/ # KolibriOS standard includes
|
||||
kolibrios_main.asm # KolibriOS entry point
|
||||
wasm_kolibrios_interface.inc # Console output macros
|
||||
linux/
|
||||
linux_main.asm # Linux entry point
|
||||
wasm_linux_interface.inc # libc output macros
|
||||
tests/
|
||||
simple.wasm
|
||||
ekun.wasm
|
||||
```
|
||||
|
||||
## Building
|
||||
|
||||
### Linux
|
||||
|
||||
Requires FASM and GCC (32-bit).
|
||||
```bash
|
||||
fasm src/linux/linux_main.asm linux_main.o
|
||||
gcc -m32 -o parser linux_main.o -nostartfiles -lc -Wl,-e,_start
|
||||
./parser tests/simple.wasm
|
||||
```
|
||||
|
||||
### KolibriOS
|
||||
|
||||
Requires FASM.
|
||||
```bash
|
||||
fasm src/kolibrios/kolibrios_main.asm wasm_dis.kex
|
||||
```
|
||||
|
||||
Copy `wasm_dis.kex` to KolibriOS and run from the console:
|
||||
```
|
||||
wasm_dis test.wasm
|
||||
```
|
||||
|
||||
## Output
|
||||
|
||||
Both platforms produce identical output. Example against a real wasm binary:
|
||||
```
|
||||
./src/parser tests/ekun.wasm
|
||||
Parsing Sections...
|
||||
|
||||
Section 1: Type (288 bytes):
|
||||
Vec of functype (Length: 45):
|
||||
functype[0]:
|
||||
Params(0):
|
||||
Result(0):
|
||||
|
||||
functype[1]:
|
||||
Params(3): i32 i32 i32
|
||||
Result(1): i32
|
||||
|
||||
functype[2]:
|
||||
Params(1): i32
|
||||
Result(1): i32
|
||||
|
||||
functype[3]:
|
||||
Params(1): i32
|
||||
Result(0):
|
||||
|
||||
functype[4]:
|
||||
Params(2): i32 i32
|
||||
Result(1): i32
|
||||
|
||||
functype[5]:
|
||||
Params(0):
|
||||
Result(1): i32
|
||||
|
||||
functype[6]:
|
||||
Params(2): i32 i32
|
||||
Result(0):
|
||||
|
||||
functype[7]:
|
||||
Params(3): i32 i32 i32
|
||||
Result(0):
|
||||
|
||||
functype[8]:
|
||||
Params(5): i32 i64 i64 i64 i64
|
||||
Result(0):
|
||||
|
||||
functype[9]:
|
||||
Params(4): i32 i32 i32 i32
|
||||
Result(1): i32
|
||||
|
||||
Section 2: Import (260 bytes)
|
||||
Vec of Import (Length: 9)
|
||||
module: env name: exit Import type: typeidx (3)
|
||||
module: env name: emscripten_asm_const_int Import type: typeidx (1)
|
||||
module: env name: _emscripten_memcpy_js Import type: typeidx (7)
|
||||
module: env name: emscripten_date_now Import type: typeidx (21)
|
||||
module: wasi_snapshot_preview1 name: fd_close Import type: typeidx (2)
|
||||
module: wasi_snapshot_preview1 name: fd_write Import type: typeidx (9)
|
||||
module: wasi_snapshot_preview1 name: fd_read Import type: typeidx (9)
|
||||
module: env name: emscripten_resize_heap Import type: typeidx (2)
|
||||
module: wasi_snapshot_preview1 name: fd_seek Import type: typeidx (12)
|
||||
|
||||
Section 3: Function (249 bytes)
|
||||
Vector of Typeidx: 0 3 3 3 3 2 1 3 4 4 6 3 3 0 2 3 3 0 0 5 6 5 10 3 3 2 3 2 2 6 5 10 2 5 6 1 7 3 5 4 3 4 3 1 1 9 3 2 4 4 5 2 4 6 1 1 1 2 2 2 6 6 2 0 3 0 3 5 3 6 3 6 0 3 7 6 7 7 7 7 3 0 3 0 4 3 0 5 0 0 1 0 0 7 0 0 0 0 0 0 0 0 0 0 0 0 6 0 0 0 0 0 11 0 0 0 0 0 0 0 0 0 0 0 2 5 1 1 5 1 2 3 2 4 4 4 4 2 2 3 1 9 2 2 9 1 4 1 1 11 22 11 15 15 11 23 24 16 16 11 25 26 27 28 5 5 5 0 2 2 1 13 13 1 4 4 2 1 1 1 29 2 17 8 14 30 8 31 10 2 32 33 34 10 35 4 17 12 36 7 2 10 37 19 19 38 1 18 6 39 1 9 1 2 1 4 5 2 2 1 3 4 4 6 8 14 20 20 8 40 41 6 6 5 5 14 8 8 8 42 3 3 2 5 43 12 44
|
||||
|
||||
Section 4: Table (4 bytes)
|
||||
Vector of Tabletype (Length: 1):
|
||||
Tabletype with limit min: (44), and unbounded max
|
||||
|
||||
Section 5: Memory (6 bytes)
|
||||
Vector of Memtype (Length: 1):
|
||||
Memtype: with limit min: (258), and max: (258)
|
||||
|
||||
Section 6: Global (8 bytes)
|
||||
Vector of Global (Length: 1):
|
||||
Globaltype: i32 (var)
|
||||
init: i32.const 99936
|
||||
|
||||
Section 7: Export (198 bytes)
|
||||
Vector of Export (Length: 9):
|
||||
name: memory Export type: memidx (0)
|
||||
name: __wasm_call_ctors Export type: funcidx (9)
|
||||
name: __indirect_function_table Export type: tableidx (0)
|
||||
name: run_from_js Export type: funcidx (71)
|
||||
name: disassemble_from_js Export type: funcidx (73)
|
||||
name: _emscripten_stack_restore Export type: funcidx (250)
|
||||
name: _emscripten_stack_alloc Export type: funcidx (251)
|
||||
name: emscripten_stack_get_current Export type: funcidx (252)
|
||||
name: dynCall_jiji Export type: funcidx (254)
|
||||
|
||||
Section 9: Element (61 bytes)
|
||||
Vector of Elem (Length: 1)
|
||||
tableidx: 0
|
||||
offset: i32.const 1
|
||||
vector of funcidx: 109 110 111 112 113 107 108 114 98 117 119 123 131 120 122 125 126 127 128 118 129 130 105 106 116 74 103 104 132 100 101 83 85 86 87 88 178 179 181 182 216 217 221
|
||||
```
|
||||
|
||||
## Dependencies
|
||||
|
||||
- [FASM](https://flatassembler.net/)
|
||||
- GCC with 32-bit support: Linux build only, for linking libc
|
||||
- KolibriOS with console.obj: KolibriOS build only
|
||||
|
||||
## Notes
|
||||
|
||||
The Linux build exists purely for development and testing. The KolibriOS build
|
||||
is the actual target. Both builds share the same core parser in `src/core/` and
|
||||
produce identical output, only the platform interface differs.
|
||||
|
||||
This project is being developed as a GSoC 2026 contribution for KolibriOS.
|
||||
@@ -0,0 +1,251 @@
|
||||
; SPDX-License-Identifier: GPL-2.0-only
|
||||
; Reshare - Shared Resources Daemon
|
||||
;
|
||||
; Copyright (C) 2026 KolibriOS Team
|
||||
|
||||
;--------------------------------------------------------------------------
|
||||
; wasm_const.inc - WebAssembly 1.0 Binary Format Constants
|
||||
; Reference: Chapter 5 (Binary Format) of Wasm 1.0 spec
|
||||
; Reference Url: https://webassembly.github.io/multi-value/core/_download/WebAssembly.pdf
|
||||
;---------------------------------------------------------------------------
|
||||
|
||||
; GENERAL
|
||||
WASM_MAGIC = 0x6d736100 ; '\0asm' in little endian
|
||||
WASM_VERSION = 0x00000001
|
||||
|
||||
; SECTIONS
|
||||
SECTION_CUSTOM = 0x00
|
||||
SECTION_TYPE = 0x01
|
||||
SECTION_IMPORT = 0x02
|
||||
SECTION_FUNCTION = 0x03
|
||||
SECTION_TABLE = 0x04
|
||||
SECTION_MEMORY = 0x05
|
||||
SECTION_GLOBAL = 0x06
|
||||
SECTION_EXPORT = 0x07
|
||||
SECTION_START = 0x08
|
||||
SECTION_ELEMENT = 0x09
|
||||
SECTION_CODE = 0x0A
|
||||
SECTION_DATA = 0x0B
|
||||
|
||||
; Value Types
|
||||
VAL_I32 = 0x7F
|
||||
VAL_I64 = 0x7E
|
||||
VAL_F32 = 0x7D
|
||||
VAL_F64 = 0x7C
|
||||
|
||||
; Import and Export Sections
|
||||
FUNC_DESC = 0x00
|
||||
TABLE_DESC = 0x01
|
||||
MEM_DESC = 0x02
|
||||
GLOBAL_DESC = 0x03
|
||||
|
||||
; blocktype
|
||||
BLOCK_EMPTY = 0x40
|
||||
|
||||
; function type
|
||||
FUNC_START = 0x60
|
||||
|
||||
; limits
|
||||
LIMIT_MIN_ONLY = 0x00
|
||||
LIMIT_MIN_MAX = 0x01
|
||||
|
||||
; table type
|
||||
ELEM_FUNCREF = 0x70
|
||||
|
||||
; Global type
|
||||
GLOBAL_CONST = 0x00
|
||||
GLOBAL_VAR = 0x01
|
||||
|
||||
; Instructions
|
||||
; Control Instructions
|
||||
OP_UNREACHABLE = 0x00
|
||||
OP_NOP = 0x01
|
||||
OP_BLOCK = 0x02
|
||||
OP_LOOP = 0x03
|
||||
OP_IF = 0x04
|
||||
OP_ELSE = 0x05
|
||||
OP_BR = 0x0C
|
||||
OP_BR_IF = 0x0D
|
||||
OP_BR_TABLE = 0x0E
|
||||
OP_RETURN = 0x0F
|
||||
OP_END = 0x0B
|
||||
OP_CALL = 0x10
|
||||
OP_CALL_INDIRECT = 0x11
|
||||
|
||||
; Parametric instructions
|
||||
OP_DROP = 0x1A
|
||||
OP_SELECT = 0x1B
|
||||
|
||||
; Variable Instructions
|
||||
OP_LOCAL_GET = 0x20
|
||||
OP_LOCAL_SET = 0x21
|
||||
OP_LOCAL_TEE = 0x22
|
||||
OP_GLOBAL_GET = 0x23
|
||||
OP_GLOBAL_SET = 0x24
|
||||
|
||||
;memor8y instruction
|
||||
OP_I32_LOAD = 0x28
|
||||
OP_I64_LOAD = 0x29
|
||||
OP_F32_LOAD = 0x2A
|
||||
OP_F64_LOAD = 0x2B
|
||||
OP_I32_LOAD8_S = 0x2C
|
||||
OP_I32_LOAD8_U = 0x2D
|
||||
OP_I32_LOAD16_S = 0x2E
|
||||
OP_I32_LOAD16_U = 0x2F
|
||||
OP_I64_LOAD8_S = 0x30
|
||||
OP_I64_LOAD8_U = 0x31
|
||||
OP_I64_LOAD16_S = 0x32
|
||||
OP_I64_LOAD16_U = 0x33
|
||||
OP_I64_LOAD32_S = 0x34
|
||||
OP_I64_LOAD32_U = 0x35
|
||||
OP_I32_STORE = 0x36
|
||||
OP_I64_STORE = 0x37
|
||||
OP_F32_STORE = 0x38
|
||||
OP_F64_STORE = 0x39
|
||||
OP_I32_STORE8 = 0x3A
|
||||
OP_I32_STORE16 = 0x3B
|
||||
OP_I64_STORE8 = 0x3C
|
||||
OP_I64_STORE16 = 0x3D
|
||||
OP_I64_STORE32 = 0x3E
|
||||
OP_MEMORY_SIZE = 0x3F
|
||||
OP_MEMORY_GROW = 0x40
|
||||
|
||||
; Numeric Instructions
|
||||
OP_I32_CONST = 0x41
|
||||
OP_I64_CONST = 0x42
|
||||
OP_F32_CONST = 0x43
|
||||
OP_F64_CONST = 0x44
|
||||
|
||||
OP_I32_EQZ = 0x45
|
||||
OP_I32_EQ = 0x46
|
||||
OP_I32_NE = 0x47
|
||||
OP_I32_LT_S = 0x48
|
||||
OP_I32_LT_U = 0x49
|
||||
OP_I32_GT_S = 0x4A
|
||||
OP_I32_GT_U = 0x4B
|
||||
OP_I32_LE_S = 0x4C
|
||||
OP_I32_LE_U = 0x4D
|
||||
OP_I32_GE_S = 0x4E
|
||||
OP_I32_GE_U = 0x4F
|
||||
|
||||
OP_I64_EQZ = 0x50
|
||||
OP_I64_EQ = 0x51
|
||||
OP_I64_NE = 0x52
|
||||
OP_I64_LT_S = 0x53
|
||||
OP_I64_LT_U = 0x54
|
||||
OP_I64_GT_S = 0x55
|
||||
OP_I64_GT_U = 0x56
|
||||
OP_I64_LE_S = 0x57
|
||||
OP_I64_LE_U = 0x58
|
||||
OP_I64_GE_S = 0x59
|
||||
OP_I64_GE_U = 0x5A
|
||||
|
||||
OP_F32_EQ = 0x5B
|
||||
OP_F32_NE = 0x5C
|
||||
OP_F32_LT = 0x5D
|
||||
OP_F32_GT = 0x5E
|
||||
OP_F32_LE = 0x5F
|
||||
OP_F32_GE = 0x60
|
||||
|
||||
OP_F64_EQ = 0x61
|
||||
OP_F64_NE = 0x62
|
||||
OP_F64_LT = 0x63
|
||||
OP_F64_GT = 0x64
|
||||
OP_F64_LE = 0x65
|
||||
OP_F64_GE = 0x66
|
||||
|
||||
OP_I32_CLZ = 0x67
|
||||
OP_I32_CTZ = 0x68
|
||||
OP_I32_POPCNT = 0x69
|
||||
OP_I32_ADD = 0x6A
|
||||
OP_I32_SUB = 0x6B
|
||||
OP_I32_MUL = 0x6C
|
||||
OP_I32_DIV_S = 0x6D
|
||||
OP_I32_DIV_U = 0x6E
|
||||
OP_I32_REM_S = 0x6F
|
||||
OP_I32_REM_U = 0x70
|
||||
OP_I32_AND = 0x71
|
||||
OP_I32_OR = 0x72
|
||||
OP_I32_XOR = 0x73
|
||||
OP_I32_SHL = 0x74
|
||||
OP_I32_SHR_S = 0x75
|
||||
OP_I32_SHR_U = 0x76
|
||||
OP_I32_ROTL = 0x77
|
||||
OP_I32_ROTR = 0x78
|
||||
|
||||
OP_I64_CLZ = 0x79
|
||||
OP_I64_CTZ = 0x7A
|
||||
OP_I64_POPCNT = 0x7B
|
||||
OP_I64_ADD = 0x7C
|
||||
OP_I64_SUB = 0x7D
|
||||
OP_I64_MUL = 0x7E
|
||||
OP_I64_DIV_S = 0x7F
|
||||
OP_I64_DIV_U = 0x80
|
||||
OP_I64_REM_S = 0x81
|
||||
OP_I64_REM_U = 0x82
|
||||
OP_I64_AND = 0x83
|
||||
OP_I64_OR = 0x84
|
||||
OP_I64_XOR = 0x85
|
||||
OP_I64_SHL = 0x86
|
||||
OP_I64_SHR_S = 0x87
|
||||
OP_I64_SHR_U = 0x88
|
||||
OP_I64_ROTL = 0x89
|
||||
OP_I64_ROTR = 0x8A
|
||||
|
||||
|
||||
OP_F32_ABS = 0x8B
|
||||
OP_F32_NEG = 0x8C
|
||||
OP_F32_CEIL = 0x8D
|
||||
OP_F32_FLOOR = 0x8E
|
||||
OP_F32_TRUNC = 0x8F
|
||||
OP_F32_NEAREST = 0x90
|
||||
OP_F32_SQRT = 0x91
|
||||
OP_F32_ADD = 0x92
|
||||
OP_F32_SUB = 0x93
|
||||
OP_F32_MUL = 0x94
|
||||
OP_F32_DIV = 0x95
|
||||
OP_F32_MIN = 0x96
|
||||
OP_F32_MAX = 0x97
|
||||
OP_F32_COPYSIGN = 0x98
|
||||
|
||||
OP_F64_ABS = 0x99
|
||||
OP_F64_NEG = 0x9A
|
||||
OP_F64_CEIL = 0x9B
|
||||
OP_F64_FLOOR = 0x9C
|
||||
OP_F64_TRUNC = 0x9D
|
||||
OP_F64_NEAREST = 0x9E
|
||||
OP_F64_SQRT = 0x9F
|
||||
OP_F64_ADD = 0xA0
|
||||
OP_F64_SUB = 0xA1
|
||||
OP_F64_MUL = 0xA2
|
||||
OP_F64_DIV = 0xA3
|
||||
OP_F64_MIN = 0xA4
|
||||
OP_F64_MAX = 0xA5
|
||||
OP_F64_COPYSIGN = 0xA6
|
||||
|
||||
; Conversions
|
||||
OP_I32_WRAP_I64 = 0xA7
|
||||
OP_I32_TRUNC_F32_S = 0xA8
|
||||
OP_I32_TRUNC_F32_U = 0xA9
|
||||
OP_I32_TRUNC_F64_S = 0xAA
|
||||
OP_I32_TRUNC_F64_U = 0xAB
|
||||
OP_I64_EXTEND_I32_S = 0xAC
|
||||
OP_I64_EXTEND_I32_U = 0xAD
|
||||
OP_I64_TRUNC_F32_S = 0xAE
|
||||
OP_I64_TRUNC_F32_U = 0xAF
|
||||
OP_I64_TRUNC_F64_S = 0xB0
|
||||
OP_I64_TRUNC_F64_U = 0xB1
|
||||
OP_F32_CONVERT_I32_S = 0xB2
|
||||
OP_F32_CONVERT_I32_U = 0xB3
|
||||
OP_F32_CONVERT_I64_S = 0xB4
|
||||
OP_F32_CONVERT_I64_U = 0xB5
|
||||
OP_F32_DEMOTE_F64 = 0xB6
|
||||
OP_F64_CONVERT_I32_S = 0xB7
|
||||
OP_F64_CONVERT_I32_U = 0xB8
|
||||
OP_F64_CONVERT_I64_S = 0xB9
|
||||
OP_F64_CONVERT_I64_U = 0xBA
|
||||
OP_F64_PROMOTE_F32 = 0xBB
|
||||
OP_I32_REINTERPRET_F32 = 0xBC
|
||||
OP_I64_REINTERPRET_F64 = 0xBD
|
||||
OP_F32_REINTERPRET_I32 = 0xBE
|
||||
OP_F64_REINTERPRET_I64 = 0xBF
|
||||
@@ -0,0 +1,100 @@
|
||||
; SPDX-License-Identifier: GPL-2.0-only
|
||||
; Reshare - Shared Resources Daemon
|
||||
;
|
||||
; Copyright (C) 2026 KolibriOS Team
|
||||
;----------------------------------------------------
|
||||
; wasm_func.inc: Utility functions for wasm
|
||||
;---------------------------------------------------
|
||||
|
||||
|
||||
;---------------------------------------------------
|
||||
; decode_leb128_u32
|
||||
;
|
||||
; decode an unsigned leb128 number
|
||||
; use the algorithm described by Wikipedia: https://en.wikipedia.org/wiki/LEB128
|
||||
;
|
||||
; accept: ebx a pointer to the address to decode
|
||||
; move ebx past the leb128 number
|
||||
; wasm allows multiple 0 to follow unsigned leb128, our decoder just discard it
|
||||
; automatically because the shift would overflow the register
|
||||
; --------------------------------------------------
|
||||
|
||||
leb128_decode_u32:
|
||||
push ecx
|
||||
push esi
|
||||
push edx
|
||||
xor eax, eax ; accumulator
|
||||
xor ecx, ecx ; shift amount
|
||||
.loop:
|
||||
cmp ecx, 35
|
||||
jge .error
|
||||
movzx esi, byte [ebx]
|
||||
advance
|
||||
mov edx, esi
|
||||
and edx, 0x7F
|
||||
shl edx, cl
|
||||
or eax, edx
|
||||
add ecx, 7
|
||||
cmp ecx, 35
|
||||
jne .continue
|
||||
test esi, 0xf0
|
||||
jnz .terminal_error
|
||||
.continue:
|
||||
test esi, 0x80
|
||||
jnz .loop
|
||||
pop edx
|
||||
pop esi
|
||||
pop ecx
|
||||
ret
|
||||
.terminal_error:
|
||||
println "Error while decoding leb128 integer: u32 terminal bytes can not have upper bits set"
|
||||
jmp parse_error
|
||||
.error:
|
||||
println "Error while decoding leb128 integer: u32 must not exceed 5 bytes"
|
||||
jmp parse_error
|
||||
|
||||
leb128_decode_s32:
|
||||
push ecx
|
||||
push esi
|
||||
push edx
|
||||
xor eax, eax ; accumulator
|
||||
xor ecx, ecx ; shift amount
|
||||
.loop:
|
||||
cmp ecx, 35
|
||||
jge .error
|
||||
movzx esi, byte [ebx]
|
||||
advance
|
||||
mov edx, esi
|
||||
and edx, 0x7F
|
||||
shl edx, cl
|
||||
or eax, edx
|
||||
add ecx, 7
|
||||
test esi, 0x80
|
||||
jnz .loop
|
||||
cmp ecx, 32
|
||||
jge .done
|
||||
test esi, 0x40
|
||||
jz .done
|
||||
xor esi, esi
|
||||
not esi
|
||||
shl esi, cl
|
||||
or eax, esi
|
||||
.done:
|
||||
pop edx
|
||||
pop esi
|
||||
pop ecx
|
||||
ret
|
||||
.error:
|
||||
println "Error while decoding leb128 integer: i32 must not exceed 4 bytes"
|
||||
jmp parse_error
|
||||
|
||||
|
||||
leb128_decode_s64:
|
||||
push ecx
|
||||
push esi
|
||||
push edx
|
||||
push ebp
|
||||
push edi
|
||||
xor eax, eax
|
||||
.loop:
|
||||
|
||||
@@ -0,0 +1,411 @@
|
||||
; SPDX-License-Identifier: GPL-2.0-only
|
||||
; Reshare - Shared Resources Daemon
|
||||
;
|
||||
; Copyright (C) 2026 KolibriOS Team
|
||||
|
||||
; valtype
|
||||
str_i32 db "i32", 0
|
||||
str_i64 db "i64", 0
|
||||
str_f32 db "f32", 0
|
||||
str_f64 db "f64", 0
|
||||
valtype:
|
||||
dd VAL_I32, str_i32
|
||||
dd VAL_I64, str_i64
|
||||
dd VAL_F32, str_f32
|
||||
dd VAL_F64, str_f64
|
||||
dd 0
|
||||
|
||||
str_op_unreachable db "unreachable", 0
|
||||
str_op_nop db "nop", 0
|
||||
str_op_block db "block", 0
|
||||
str_op_loop db "loop", 0
|
||||
str_op_if db "if", 0
|
||||
str_op_br db "br", 0
|
||||
str_op_br_if db "br_if", 0
|
||||
str_op_br_table db "br_table", 0
|
||||
str_op_return db "return", 0
|
||||
str_op_call db "call", 0
|
||||
str_op_call_indirect db "call_indirect", 0
|
||||
str_op_drop db "drop", 0
|
||||
str_op_select db "select", 0
|
||||
str_op_local_get db "local.get", 0
|
||||
str_op_local_set db "local.set", 0
|
||||
str_op_local_tee db "local.tee", 0
|
||||
str_op_global_get db "global.get", 0
|
||||
str_op_global_set db "global.set", 0
|
||||
str_op_i32_load db "i32.load", 0
|
||||
str_op_i64_load db "i64.load", 0
|
||||
str_op_f32_load db "f32.load", 0
|
||||
str_op_f64_load db "f64.load", 0
|
||||
str_op_i32_load8_s db "i32.load8_s", 0
|
||||
str_op_i32_load8_u db "i32.load8_u", 0
|
||||
str_op_i32_load16_s db "i32.load16_s", 0
|
||||
str_op_i32_load16_u db "i32.load16_u", 0
|
||||
str_op_i64_load8_s db "i64.load8_s", 0
|
||||
str_op_i64_load8_u db "i64.load8_u", 0
|
||||
str_op_i64_load16_s db "i64.load16_s", 0
|
||||
str_op_i64_load16_u db "i64.load16_u", 0
|
||||
str_op_i64_load32_s db "i64.load32_s", 0
|
||||
str_op_i64_load32_u db "i64.load32_u", 0
|
||||
str_op_i32_store db "i32.store", 0
|
||||
str_op_i64_store db "i64.store", 0
|
||||
str_op_f32_store db "f32.store", 0
|
||||
str_op_f64_store db "f64.store", 0
|
||||
str_op_i32_store8 db "i32.store8", 0
|
||||
str_op_i32_store16 db "i32.store16", 0
|
||||
str_op_i64_store8 db "i64.store8", 0
|
||||
str_op_i64_store16 db "i64.store16", 0
|
||||
str_op_i64_store32 db "i64.store32", 0
|
||||
str_op_memory_size db "memory.size", 0
|
||||
str_op_memory_grow db "memory.grow", 0
|
||||
str_op_i32_const db "i32.const", 0
|
||||
str_op_i64_const db "i64.const", 0
|
||||
str_op_f32_const db "f32.const", 0
|
||||
str_op_f64_const db "f64.const", 0
|
||||
str_op_i32_eqz db "i32.eqz", 0
|
||||
str_op_i32_eq db "i32.eq", 0
|
||||
str_op_i32_ne db "i32.ne", 0
|
||||
str_op_i32_lt_s db "i32.lt_s", 0
|
||||
str_op_i32_lt_u db "i32.lt_u", 0
|
||||
str_op_i32_gt_s db "i32.gt_s", 0
|
||||
str_op_i32_gt_u db "i32.gt_u", 0
|
||||
str_op_i32_le_s db "i32.le_s", 0
|
||||
str_op_i32_le_u db "i32.le_u", 0
|
||||
str_op_i32_ge_s db "i32.ge_s", 0
|
||||
str_op_i32_ge_u db "i32.ge_u", 0
|
||||
str_op_i64_eqz db "i64.eqz", 0
|
||||
str_op_i64_eq db "i64.eq", 0
|
||||
str_op_i64_ne db "i64.ne", 0
|
||||
str_op_i64_lt_s db "i64.lt_s", 0
|
||||
str_op_i64_lt_u db "i64.lt_u", 0
|
||||
str_op_i64_gt_s db "i64.gt_s", 0
|
||||
str_op_i64_gt_u db "i64.gt_u", 0
|
||||
str_op_i64_le_s db "i64.le_s", 0
|
||||
str_op_i64_le_u db "i64.le_u", 0
|
||||
str_op_i64_ge_s db "i64.ge_s", 0
|
||||
str_op_i64_ge_u db "i64.ge_u", 0
|
||||
str_op_f32_eq db "f32.eq", 0
|
||||
str_op_f32_ne db "f32.ne", 0
|
||||
str_op_f32_lt db "f32.lt", 0
|
||||
str_op_f32_gt db "f32.gt", 0
|
||||
str_op_f32_le db "f32.le", 0
|
||||
str_op_f32_ge db "f32.ge", 0
|
||||
str_op_f64_eq db "f64.eq", 0
|
||||
str_op_f64_ne db "f64.ne", 0
|
||||
str_op_f64_lt db "f64.lt", 0
|
||||
str_op_f64_gt db "f64.gt", 0
|
||||
str_op_f64_le db "f64.le", 0
|
||||
str_op_f64_ge db "f64.ge", 0
|
||||
str_op_i32_clz db "i32.clz", 0
|
||||
str_op_i32_ctz db "i32.ctz", 0
|
||||
str_op_i32_popcnt db "i32.popcnt", 0
|
||||
str_op_i32_add db "i32.add", 0
|
||||
str_op_i32_sub db "i32.sub", 0
|
||||
str_op_i32_mul db "i32.mul", 0
|
||||
str_op_i32_div_s db "i32.div_s", 0
|
||||
str_op_i32_div_u db "i32.div_u", 0
|
||||
str_op_i32_rem_s db "i32.rem_s", 0
|
||||
str_op_i32_rem_u db "i32.rem_u", 0
|
||||
str_op_i32_and db "i32.and", 0
|
||||
str_op_i32_or db "i32.or", 0
|
||||
str_op_i32_xor db "i32.xor", 0
|
||||
str_op_i32_shl db "i32.shl", 0
|
||||
str_op_i32_shr_s db "i32.shr_s", 0
|
||||
str_op_i32_shr_u db "i32.shr_u", 0
|
||||
str_op_i32_rotl db "i32.rotl", 0
|
||||
str_op_i32_rotr db "i32.rotr", 0
|
||||
str_op_i64_clz db "i64.clz", 0
|
||||
str_op_i64_ctz db "i64.ctz", 0
|
||||
str_op_i64_popcnt db "i64.popcnt", 0
|
||||
str_op_i64_add db "i64.add", 0
|
||||
str_op_i64_sub db "i64.sub", 0
|
||||
str_op_i64_mul db "i64.mul", 0
|
||||
str_op_i64_div_s db "i64.div_s", 0
|
||||
str_op_i64_div_u db "i64.div_u", 0
|
||||
str_op_i64_rem_s db "i64.rem_s", 0
|
||||
str_op_i64_rem_u db "i64.rem_u", 0
|
||||
str_op_i64_and db "i64.and", 0
|
||||
str_op_i64_or db "i64.or", 0
|
||||
str_op_i64_xor db "i64.xor", 0
|
||||
str_op_i64_shl db "i64.shl", 0
|
||||
str_op_i64_shr_s db "i64.shr_s", 0
|
||||
str_op_i64_shr_u db "i64.shr_u", 0
|
||||
str_op_i64_rotl db "i64.rotl", 0
|
||||
str_op_i64_rotr db "i64.rotr", 0
|
||||
str_op_f32_abs db "f32.abs", 0
|
||||
str_op_f32_neg db "f32.neg", 0
|
||||
str_op_f32_ceil db "f32.ceil", 0
|
||||
str_op_f32_floor db "f32.floor", 0
|
||||
str_op_f32_trunc db "f32.trunc", 0
|
||||
str_op_f32_nearest db "f32.nearest", 0
|
||||
str_op_f32_sqrt db "f32.sqrt", 0
|
||||
str_op_f32_add db "f32.add", 0
|
||||
str_op_f32_sub db "f32.sub", 0
|
||||
str_op_f32_mul db "f32.mul", 0
|
||||
str_op_f32_div db "f32.div", 0
|
||||
str_op_f32_min db "f32.min", 0
|
||||
str_op_f32_max db "f32.max", 0
|
||||
str_op_f32_copysign db "f32.copysign", 0
|
||||
str_op_f64_abs db "f64.abs", 0
|
||||
str_op_f64_neg db "f64.neg", 0
|
||||
str_op_f64_ceil db "f64.ceil", 0
|
||||
str_op_f64_floor db "f64.floor", 0
|
||||
str_op_f64_trunc db "f64.trunc", 0
|
||||
str_op_f64_nearest db "f64.nearest", 0
|
||||
str_op_f64_sqrt db "f64.sqrt", 0
|
||||
str_op_f64_add db "f64.add", 0
|
||||
str_op_f64_sub db "f64.sub", 0
|
||||
str_op_f64_mul db "f64.mul", 0
|
||||
str_op_f64_div db "f64.div", 0
|
||||
str_op_f64_min db "f64.min", 0
|
||||
str_op_f64_max db "f64.max", 0
|
||||
str_op_f64_copysign db "f64.copysign", 0
|
||||
str_op_i32_wrap_i64 db "i32.wrap_i64", 0
|
||||
str_op_i32_trunc_f32_s db "i32.trunc_f32_s", 0
|
||||
str_op_i32_trunc_f32_u db "i32.trunc_f32_u", 0
|
||||
str_op_i32_trunc_f64_s db "i32.trunc_f64_s", 0
|
||||
str_op_i32_trunc_f64_u db "i32.trunc_f64_u", 0
|
||||
str_op_i64_extend_i32_s db "i64.extend_i32_s", 0
|
||||
str_op_i64_extend_i32_u db "i64.extend_i32_u", 0
|
||||
str_op_i64_trunc_f32_s db "i64.trunc_f32_s", 0
|
||||
str_op_i64_trunc_f32_u db "i64.trunc_f32_u", 0
|
||||
str_op_i64_trunc_f64_s db "i64.trunc_f64_s", 0
|
||||
str_op_i64_trunc_f64_u db "i64.trunc_f64_u", 0
|
||||
str_op_f32_convert_i32_s db "f32.convert_i32_s", 0
|
||||
str_op_f32_convert_i32_u db "f32.convert_i32_u", 0
|
||||
str_op_f32_convert_i64_s db "f32.convert_i64_s", 0
|
||||
str_op_f32_convert_i64_u db "f32.convert_i64_u", 0
|
||||
str_op_f32_demote_f64 db "f32.demote_f64", 0
|
||||
str_op_f64_convert_i32_s db "f64.convert_i32_s", 0
|
||||
str_op_f64_convert_i32_u db "f64.convert_i32_u", 0
|
||||
str_op_f64_convert_i64_s db "f64.convert_i64_s", 0
|
||||
str_op_f64_convert_i64_u db "f64.convert_i64_u", 0
|
||||
str_op_f64_promote_f32 db "f64.promote_f32", 0
|
||||
str_op_i32_reinterpret_f32 db "i32.reinterpret_f32", 0
|
||||
str_op_i64_reinterpret_f64 db "i64.reinterpret_f64", 0
|
||||
str_op_f32_reinterpret_i32 db "f32.reinterpret_i32", 0
|
||||
str_op_f64_reinterpret_i64 db "f64.reinterpret_i64", 0
|
||||
str_invalid db "<invalid>", 0
|
||||
|
||||
opcode_str_table:
|
||||
dd str_op_unreachable
|
||||
dd str_op_nop
|
||||
dd str_op_block
|
||||
dd str_op_loop
|
||||
dd str_op_if
|
||||
rept 7 { dd str_invalid } ; shouldn't be printed
|
||||
|
||||
dd str_op_br
|
||||
dd str_op_br_if
|
||||
dd str_op_br_table
|
||||
dd str_op_return
|
||||
dd str_op_call
|
||||
dd str_op_call_indirect
|
||||
rept 8 { dd str_invalid }
|
||||
|
||||
dd str_op_drop
|
||||
dd str_op_select
|
||||
rept 4 { dd str_invalid }
|
||||
|
||||
dd str_op_local_get
|
||||
dd str_op_local_set
|
||||
dd str_op_local_tee
|
||||
dd str_op_global_get
|
||||
dd str_op_global_set
|
||||
rept 3 {dd str_invalid}
|
||||
|
||||
dd str_op_i32_load
|
||||
dd str_op_i64_load
|
||||
dd str_op_f32_load
|
||||
dd str_op_f64_load
|
||||
dd str_op_i32_load8_s
|
||||
dd str_op_i32_load8_u
|
||||
dd str_op_i32_load16_s
|
||||
dd str_op_i32_load16_u
|
||||
|
||||
dd str_op_i64_load8_s
|
||||
dd str_op_i64_load8_u
|
||||
dd str_op_i64_load16_s
|
||||
dd str_op_i64_load16_u
|
||||
dd str_op_i64_load32_s
|
||||
dd str_op_i64_load32_u
|
||||
|
||||
dd str_op_i32_store
|
||||
dd str_op_i64_store
|
||||
dd str_op_f32_store
|
||||
dd str_op_f64_store
|
||||
dd str_op_i32_store8
|
||||
dd str_op_i32_store16
|
||||
dd str_op_i64_store8
|
||||
dd str_op_i64_store16
|
||||
dd str_op_i64_store32
|
||||
dd str_op_memory_size
|
||||
dd str_op_memory_grow
|
||||
dd str_op_i32_const
|
||||
dd str_op_i64_const
|
||||
dd str_op_f32_const
|
||||
dd str_op_f64_const
|
||||
|
||||
dd str_op_i32_eqz
|
||||
dd str_op_i32_eq
|
||||
dd str_op_i32_ne
|
||||
dd str_op_i32_lt_s
|
||||
dd str_op_i32_lt_u
|
||||
dd str_op_i32_gt_s
|
||||
dd str_op_i32_gt_u
|
||||
dd str_op_i32_le_s
|
||||
dd str_op_i32_le_u
|
||||
dd str_op_i32_ge_s
|
||||
dd str_op_i32_ge_u
|
||||
|
||||
dd str_op_i64_eqz
|
||||
dd str_op_i64_eq
|
||||
dd str_op_i64_ne
|
||||
dd str_op_i64_lt_s
|
||||
dd str_op_i64_lt_u
|
||||
dd str_op_i64_gt_s
|
||||
dd str_op_i64_gt_u
|
||||
dd str_op_i64_le_s
|
||||
dd str_op_i64_le_u
|
||||
dd str_op_i64_ge_s
|
||||
dd str_op_i64_ge_u
|
||||
|
||||
dd str_op_f32_eq
|
||||
dd str_op_f32_ne
|
||||
dd str_op_f32_lt
|
||||
dd str_op_f32_gt
|
||||
dd str_op_f32_le
|
||||
dd str_op_f32_ge
|
||||
|
||||
dd str_op_f64_eq
|
||||
dd str_op_f64_ne
|
||||
dd str_op_f64_lt
|
||||
dd str_op_f64_gt
|
||||
dd str_op_f64_le
|
||||
dd str_op_f64_ge
|
||||
|
||||
dd str_op_i32_clz
|
||||
dd str_op_i32_ctz
|
||||
dd str_op_i32_popcnt
|
||||
dd str_op_i32_add
|
||||
dd str_op_i32_sub
|
||||
dd str_op_i32_mul
|
||||
dd str_op_i32_div_s
|
||||
dd str_op_i32_div_u
|
||||
dd str_op_i32_rem_s
|
||||
dd str_op_i32_rem_u
|
||||
dd str_op_i32_and
|
||||
dd str_op_i32_or
|
||||
dd str_op_i32_xor
|
||||
dd str_op_i32_shl
|
||||
dd str_op_i32_shr_s
|
||||
dd str_op_i32_shr_u
|
||||
dd str_op_i32_rotl
|
||||
dd str_op_i32_rotr
|
||||
|
||||
dd str_op_i64_clz
|
||||
dd str_op_i64_ctz
|
||||
dd str_op_i64_popcnt
|
||||
dd str_op_i64_add
|
||||
dd str_op_i64_sub
|
||||
dd str_op_i64_mul
|
||||
dd str_op_i64_div_s
|
||||
dd str_op_i64_div_u
|
||||
dd str_op_i64_rem_s
|
||||
dd str_op_i64_rem_u
|
||||
dd str_op_i64_and
|
||||
dd str_op_i64_or
|
||||
dd str_op_i64_xor
|
||||
dd str_op_i64_shl
|
||||
dd str_op_i64_shr_s
|
||||
dd str_op_i64_shr_u
|
||||
dd str_op_i64_rotl
|
||||
dd str_op_i64_rotr
|
||||
|
||||
dd str_op_f32_abs
|
||||
dd str_op_f32_neg
|
||||
dd str_op_f32_ceil
|
||||
dd str_op_f32_floor
|
||||
dd str_op_f32_trunc
|
||||
dd str_op_f32_nearest
|
||||
dd str_op_f32_sqrt
|
||||
dd str_op_f32_add
|
||||
dd str_op_f32_sub
|
||||
dd str_op_f32_mul
|
||||
dd str_op_f32_div
|
||||
dd str_op_f32_min
|
||||
dd str_op_f32_max
|
||||
dd str_op_f32_copysign
|
||||
|
||||
dd str_op_f64_abs
|
||||
dd str_op_f64_neg
|
||||
dd str_op_f64_ceil
|
||||
dd str_op_f64_floor
|
||||
dd str_op_f64_trunc
|
||||
dd str_op_f64_nearest
|
||||
dd str_op_f64_sqrt
|
||||
dd str_op_f64_add
|
||||
dd str_op_f64_sub
|
||||
dd str_op_f64_mul
|
||||
dd str_op_f64_div
|
||||
dd str_op_f64_min
|
||||
dd str_op_f64_max
|
||||
dd str_op_f64_copysign
|
||||
|
||||
dd str_op_i32_wrap_i64
|
||||
dd str_op_i32_trunc_f32_s
|
||||
dd str_op_i32_trunc_f32_u
|
||||
dd str_op_i32_trunc_f64_s
|
||||
dd str_op_i32_trunc_f64_u
|
||||
dd str_op_i64_extend_i32_s
|
||||
dd str_op_i64_extend_i32_u
|
||||
dd str_op_i64_trunc_f32_s
|
||||
dd str_op_i64_trunc_f32_u
|
||||
dd str_op_i64_trunc_f64_s
|
||||
dd str_op_i64_trunc_f64_u
|
||||
dd str_op_f32_convert_i32_s
|
||||
dd str_op_f32_convert_i32_u
|
||||
dd str_op_f32_convert_i64_s
|
||||
dd str_op_f32_convert_i64_u
|
||||
dd str_op_f32_demote_f64
|
||||
dd str_op_f64_convert_i32_s
|
||||
dd str_op_f64_convert_i32_u
|
||||
dd str_op_f64_convert_i64_s
|
||||
dd str_op_f64_convert_i64_u
|
||||
dd str_op_f64_promote_f32
|
||||
dd str_op_i32_reinterpret_f32
|
||||
dd str_op_i64_reinterpret_f64
|
||||
dd str_op_f32_reinterpret_i32
|
||||
dd str_op_f64_reinterpret_i64
|
||||
|
||||
assert ($ - opcode_str_table) = (192 * 4)
|
||||
|
||||
opcode_parse_table:
|
||||
dd parse_op_simple ;0x00
|
||||
dd parse_op_simple ; 0x01
|
||||
dd parse_op_block ; 0x02
|
||||
dd parse_op_block ; 0x03
|
||||
dd parse_op_if ; 0x04
|
||||
rept 7 { dd parse_error }; no opcode taken or opcode are part of other opcode
|
||||
dd parse_op_u32 ; 0x0c
|
||||
dd parse_op_u32 ; 0x0d
|
||||
dd parse_op_br_table ; 0x0e
|
||||
dd parse_op_simple ; 0x0f
|
||||
dd parse_op_u32 ; 0x10
|
||||
dd parse_call_indirect ; 0x11
|
||||
rept 8 { dd parse_error} ; 0x12 - 0x
|
||||
dd parse_op_simple ; 0x1a
|
||||
dd parse_op_simple ; 0x1b
|
||||
rept 4 { dd parse_error}
|
||||
rept 5 { dd parse_op_u32 } ; 0x20 - 0x24
|
||||
rept 3 { dd parse_error } ; 0x25 - 0x27 Reserved
|
||||
rept 23 { dd parse_op_memarg } ; 0x28 - 0x3e
|
||||
dd parse_mem_inst
|
||||
dd parse_mem_inst
|
||||
dd parse_op_i32
|
||||
dd parse_op_i64
|
||||
dd parse_op_f32
|
||||
dd parse_op_f64
|
||||
rept 123 { dd parse_op_simple }
|
||||
|
||||
assert ($ - opcode_parse_table) = (192 * 4)
|
||||
@@ -0,0 +1,897 @@
|
||||
; SPDX-License-Identifier: GPL-2.0-only
|
||||
; Reshare - Shared Resources Daemon
|
||||
;
|
||||
; Copyright (C) 2026 KolibriOS Team
|
||||
|
||||
|
||||
; ---------------------------------------------------------------------
|
||||
; wasm_parser.inc
|
||||
; WASM BINARY PARSER
|
||||
; Parse the Binary Format described in the Wasm 1.0 Spec
|
||||
; ---------------------------------------------------------------------
|
||||
|
||||
include 'wasm_const.inc'
|
||||
include 'wasm_name.inc'
|
||||
|
||||
buf_ptr dd ?
|
||||
buf_siz dd ?
|
||||
buf_end dd ?
|
||||
func_idx dd 0
|
||||
|
||||
parse_saved_esp dd 0
|
||||
parse_saved_ebp dd 0
|
||||
|
||||
macro advance{
|
||||
inc ebx
|
||||
}
|
||||
|
||||
include 'wasm_func.inc'
|
||||
|
||||
;---------------------------------------------
|
||||
; print a string word for a valtype
|
||||
; accept ebx - pointer holding valtype
|
||||
; return eax - 0 on success, 1 on error
|
||||
; --------------------------------------------
|
||||
|
||||
valtype_to_str:
|
||||
push esi
|
||||
mov esi, valtype
|
||||
.loop:
|
||||
cmp dword [esi], 0
|
||||
je .error
|
||||
movzx eax, byte [ebx]
|
||||
cmp [esi], eax
|
||||
je .found
|
||||
add esi, 8
|
||||
jmp .loop
|
||||
|
||||
.error:
|
||||
println "Unknown byte 0x%x", eax
|
||||
mov eax, 1
|
||||
pop esi
|
||||
ret
|
||||
.found:
|
||||
add esi, 4
|
||||
print " %s ", dword [esi]
|
||||
xor eax, eax
|
||||
.exit:
|
||||
pop esi
|
||||
ret
|
||||
|
||||
section_parse_table:
|
||||
dd parse_custom_sec
|
||||
dd parse_type_sec
|
||||
dd parse_import_sec
|
||||
dd parse_function_sec
|
||||
dd parse_table_sec
|
||||
dd parse_memory_sec
|
||||
dd parse_global_sec
|
||||
dd parse_export_sec
|
||||
dd parse_start_sec
|
||||
dd parse_element_sec
|
||||
dd parse_code_sec
|
||||
dd parse_data_sec
|
||||
|
||||
;----------------------------------------------------------
|
||||
; wasm_parse: Parse a Wasm Binary
|
||||
; INPUT:
|
||||
; eax - Buffer address containing the binary
|
||||
; ebx - Buffer size
|
||||
|
||||
; register usage
|
||||
; ebx - current pointer to buffer
|
||||
; eax - scratch register
|
||||
; ---------------------------------------------------------
|
||||
wasm_parse:
|
||||
; a wasm binary at least have a 4 bytes magic and 4 bytes header
|
||||
cmp ebx, 0x08
|
||||
jb .too_small
|
||||
mov [buf_ptr], eax
|
||||
mov [buf_siz], ebx
|
||||
lea ecx, [ebx + eax]
|
||||
mov [buf_end], ecx
|
||||
; println "Buf start: 0x%x, buf_size: %d, buf_end: 0x%x", eax, ebx, ecx
|
||||
mov ebx, eax
|
||||
; save for error recovery
|
||||
mov [parse_saved_esp], esp
|
||||
mov [parse_saved_ebp], ebp
|
||||
.parse_module:
|
||||
call check_header
|
||||
call parse_sections
|
||||
|
||||
.parse_end:
|
||||
println "Successfully parsed wasm binary"
|
||||
ret
|
||||
|
||||
.too_small:
|
||||
println "Refusing to parse a file of size: 0x%x without wasm header", ebx
|
||||
ret
|
||||
|
||||
check_header:
|
||||
cmp dword [ebx], WASM_MAGIC
|
||||
jne .magic_error
|
||||
add ebx, 4
|
||||
cmp dword [ebx], WASM_VERSION
|
||||
jne .version_error
|
||||
add ebx, 4
|
||||
ret
|
||||
.magic_error:
|
||||
println "Error, Magic Number 0x%x does not match required 0x%x", dword [ebx], WASM_MAGIC
|
||||
jmp parse_error
|
||||
|
||||
.version_error:
|
||||
println "Error, Version Number 0x%x does not match required 0x%x", dword [ebx], WASM_VERSION
|
||||
jmp parse_error
|
||||
|
||||
|
||||
; each binary part is a section
|
||||
parse_sections:
|
||||
println "Parsing Sections..."
|
||||
@@:
|
||||
movzx eax, byte [ebx]
|
||||
advance
|
||||
cmp eax, SECTION_DATA ; biggest section number in SECTION
|
||||
ja .section_skip
|
||||
call dword [section_parse_table + eax * 4]
|
||||
mov eax, [buf_end]
|
||||
cmp ebx, eax
|
||||
jge @f
|
||||
jmp @b
|
||||
.section_skip:
|
||||
println "In section skip"
|
||||
call leb128_decode_u32
|
||||
add ebx, eax
|
||||
mov eax, [buf_end]
|
||||
cmp ebx, eax
|
||||
jge @f
|
||||
jmp @b
|
||||
@@:
|
||||
ret
|
||||
|
||||
parse_custom_sec:
|
||||
call leb128_decode_u32
|
||||
println ""
|
||||
println "Section 0: Custom (%d bytes)", eax
|
||||
; do nothing but skip section
|
||||
lea esi, [ebx + eax] ; save end pointer to advance later
|
||||
; print name
|
||||
call leb128_decode_u32
|
||||
println " name: %.*s", eax, ebx ; write ebx of length eax
|
||||
mov ebx, esi ;skip
|
||||
ret
|
||||
|
||||
parse_type_sec:
|
||||
call leb128_decode_u32
|
||||
println ""
|
||||
println "Section 1: Type (%d bytes): ", eax
|
||||
|
||||
add eax, ebx
|
||||
push eax
|
||||
; type : vec<functype>
|
||||
call leb128_decode_u32
|
||||
println " Vec of functype (Length: %d): ", eax
|
||||
mov edi, eax
|
||||
.loop:
|
||||
test edi, edi
|
||||
jz .done
|
||||
call parse_functype
|
||||
dec edi
|
||||
jmp .loop
|
||||
|
||||
.done:
|
||||
pop esi
|
||||
cmp esi, ebx
|
||||
jne .error
|
||||
ret
|
||||
.error:
|
||||
println "Invalid section size for section: type"
|
||||
jmp parse_error
|
||||
|
||||
parse_functype: ; function start with 0x60
|
||||
cmp byte [ebx], FUNC_START
|
||||
je .continue
|
||||
|
||||
println "Invalid byte while parsing function. Function should start with %d", FUNC_START
|
||||
jmp parse_error
|
||||
|
||||
.continue:
|
||||
println " functype[%d]:", dword [func_idx]
|
||||
inc [func_idx]
|
||||
advance
|
||||
call parse_vec_param
|
||||
call parse_vec_result
|
||||
println ""
|
||||
ret
|
||||
|
||||
parse_vec_param:
|
||||
push edi
|
||||
call leb128_decode_u32
|
||||
mov edi, eax
|
||||
print " Params(%d): ", edi
|
||||
|
||||
.loop:
|
||||
test edi, edi
|
||||
jz .done
|
||||
call valtype_to_str
|
||||
test eax, eax
|
||||
ja parse_error
|
||||
advance
|
||||
dec edi
|
||||
jmp .loop
|
||||
.done:
|
||||
println ""
|
||||
pop edi
|
||||
ret
|
||||
|
||||
parse_vec_result:
|
||||
push edi
|
||||
call leb128_decode_u32
|
||||
mov edi, eax
|
||||
print " Result(%d): ", edi
|
||||
|
||||
.loop:
|
||||
test edi, edi
|
||||
jz .done
|
||||
call valtype_to_str
|
||||
test eax, eax
|
||||
ja parse_error
|
||||
advance
|
||||
dec edi
|
||||
jmp .loop
|
||||
.done:
|
||||
println ""
|
||||
pop edi
|
||||
ret
|
||||
|
||||
parse_import_sec:
|
||||
call leb128_decode_u32
|
||||
println ""
|
||||
println "Section 2: Import (%d bytes)", eax
|
||||
add eax, ebx
|
||||
push eax
|
||||
call leb128_decode_u32
|
||||
println " Vec of Import (Length: %d)", eax
|
||||
mov edi, eax
|
||||
|
||||
.loop:
|
||||
test edi, edi
|
||||
jz .done
|
||||
call parse_import
|
||||
dec edi
|
||||
jmp .loop
|
||||
.done:
|
||||
pop esi
|
||||
cmp ebx, esi
|
||||
jne .error
|
||||
ret
|
||||
.error:
|
||||
println "Invalid section size for import. ebx: (0x%x), esi: (0x%x", ebx, esi
|
||||
jmp parse_error
|
||||
|
||||
parse_import:
|
||||
; parse modname first
|
||||
call leb128_decode_u32
|
||||
print " module: %.*s", eax, ebx
|
||||
add ebx, eax
|
||||
; parse nm
|
||||
call leb128_decode_u32
|
||||
print " name: %.*s ", eax, ebx
|
||||
add ebx, eax
|
||||
|
||||
parse_importdesc:
|
||||
movzx eax, byte [ebx]
|
||||
advance
|
||||
test eax, eax
|
||||
je .typeidx
|
||||
cmp eax, 0x01
|
||||
je .tabletype
|
||||
cmp eax, 0x02
|
||||
je .memtype
|
||||
cmp eax, 0x03
|
||||
je .globaltype
|
||||
|
||||
.typeidx:
|
||||
call leb128_decode_u32
|
||||
println " Import type: typeidx (%d)", eax
|
||||
ret
|
||||
.tabletype:
|
||||
print " Import type: "
|
||||
jmp parse_table_type
|
||||
|
||||
.memtype:
|
||||
print " Import type: "
|
||||
jmp parse_memtype
|
||||
|
||||
.globaltype:
|
||||
print " Import type: "
|
||||
jmp parse_globaltype
|
||||
|
||||
|
||||
parse_table_type:
|
||||
cmp byte [ebx], 0x70
|
||||
je @f
|
||||
movzx eax, byte [ebx]
|
||||
println "Error: Expecting funcref element type buf found (0x%x)", eax
|
||||
jmp parse_error
|
||||
@@:
|
||||
advance
|
||||
print "Tabletype "
|
||||
jmp parse_limits
|
||||
|
||||
|
||||
|
||||
parse_memtype:
|
||||
print "Memtype: "
|
||||
parse_limits:
|
||||
movzx eax, byte [ebx]
|
||||
advance
|
||||
test eax, eax
|
||||
je .min
|
||||
cmp eax, LIMIT_MIN_MAX
|
||||
je .minmax
|
||||
println "Invalid Limit parsed"
|
||||
jmp parse_error
|
||||
.min:
|
||||
call leb128_decode_u32
|
||||
println " with limit min: (%d), and unbounded max", eax
|
||||
ret
|
||||
.minmax:
|
||||
call leb128_decode_u32
|
||||
print " with limit min: (%d)", eax
|
||||
call leb128_decode_u32
|
||||
println ", and max: (%d)", eax
|
||||
ret
|
||||
|
||||
|
||||
parse_globaltype:
|
||||
print "Globaltype: "
|
||||
call valtype_to_str
|
||||
test eax, eax
|
||||
jne .valtype_error
|
||||
advance
|
||||
movzx eax, byte[ebx]
|
||||
advance
|
||||
|
||||
; check if mutable or constant
|
||||
test eax, eax
|
||||
jne .check_var
|
||||
println "(const)"
|
||||
ret
|
||||
|
||||
.check_var:
|
||||
cmp eax, GLOBAL_VAR
|
||||
jne .mut_error
|
||||
println "(var)"
|
||||
ret
|
||||
|
||||
.valtype_error:
|
||||
movzx eax, byte [ebx]
|
||||
println " Invalid Valtype (0x%x)", eax
|
||||
jmp parse_error
|
||||
.mut_error:
|
||||
println " Invalid mutable type (%x)", eax
|
||||
jmp parse_error
|
||||
|
||||
|
||||
parse_function_sec:
|
||||
call leb128_decode_u32
|
||||
println ""
|
||||
println "Section 3: Function (%d bytes)", eax
|
||||
add eax, ebx
|
||||
push eax
|
||||
; function is vec(typeidx)
|
||||
|
||||
call leb128_decode_u32
|
||||
mov edi, eax
|
||||
print "Vector of Typeidx: "
|
||||
.loop:
|
||||
test edi, edi
|
||||
jz .done
|
||||
call leb128_decode_u32
|
||||
print " %d ", eax
|
||||
dec edi
|
||||
jmp .loop
|
||||
.done:
|
||||
pop esi
|
||||
cmp esi, ebx
|
||||
jne .error
|
||||
println ""
|
||||
ret
|
||||
.error:
|
||||
println "Error while parsing function section. Section size is incorrect"
|
||||
jmp parse_error
|
||||
|
||||
|
||||
parse_table_sec:
|
||||
call leb128_decode_u32
|
||||
println ""
|
||||
println "Section 4: Table (%d bytes)", eax
|
||||
add eax, ebx
|
||||
push eax
|
||||
; table is a vector of tabletype
|
||||
call leb128_decode_u32
|
||||
mov edi, eax
|
||||
println " Vector of Tabletype (Length: %d): ", edi
|
||||
.loop:
|
||||
test edi, edi
|
||||
jz .done
|
||||
print " "
|
||||
call parse_table_type
|
||||
dec edi
|
||||
jmp .loop
|
||||
.done:
|
||||
pop esi
|
||||
cmp ebx, esi
|
||||
jne .error
|
||||
ret
|
||||
.error:
|
||||
println "Error while parsing table section: Section size is incorrect"
|
||||
jmp parse_error
|
||||
|
||||
|
||||
parse_memory_sec:
|
||||
call leb128_decode_u32
|
||||
println ""
|
||||
println "Section 5: Memory (%d bytes)", eax
|
||||
add eax, ebx
|
||||
push eax
|
||||
; memory section is a vector of memtype
|
||||
call leb128_decode_u32
|
||||
println " Vector of Memtype (Length: %d): ", eax
|
||||
mov edi, eax
|
||||
|
||||
.loop:
|
||||
test edi, edi
|
||||
jz .done
|
||||
print " "
|
||||
call parse_memtype
|
||||
dec edi
|
||||
jmp .loop
|
||||
.done:
|
||||
pop esi
|
||||
cmp ebx, esi
|
||||
jne .error
|
||||
ret
|
||||
.error:
|
||||
println "Error while parsing memory section: Section size is incorrect"
|
||||
jmp parse_error
|
||||
|
||||
|
||||
parse_global_sec:
|
||||
call leb128_decode_u32
|
||||
println ""
|
||||
println "Section 6: Global (%d bytes)", eax
|
||||
add eax, ebx
|
||||
push eax
|
||||
; global section is a vector of global
|
||||
call leb128_decode_u32
|
||||
println " Vector of Global (Length: %d): ", eax
|
||||
mov edi, eax
|
||||
.loop:
|
||||
test edi, edi
|
||||
jz .done
|
||||
print " "
|
||||
call parse_globaltype
|
||||
print " init: "
|
||||
call parse_const_expr
|
||||
dec edi
|
||||
jmp .loop
|
||||
.done:
|
||||
pop esi
|
||||
cmp esi, ebx
|
||||
jne .error
|
||||
ret
|
||||
.error:
|
||||
println "Error while parsing global section: Section size is incorrect"
|
||||
jmp parse_error
|
||||
|
||||
|
||||
parse_export_sec:
|
||||
call leb128_decode_u32
|
||||
println ""
|
||||
println "Section 7: Export (%d bytes)", eax
|
||||
add eax, ebx
|
||||
push eax
|
||||
call leb128_decode_u32
|
||||
println " Vector of Export (Length: %d): ", eax
|
||||
mov edi, eax
|
||||
.loop:
|
||||
test edi, edi
|
||||
jz .done
|
||||
call parse_export
|
||||
dec edi
|
||||
jmp .loop
|
||||
.done:
|
||||
pop esi
|
||||
cmp esi, ebx
|
||||
jne .error
|
||||
ret
|
||||
.error:
|
||||
println "Error while parsing export section: Section size is incorrect"
|
||||
jmp parse_error
|
||||
|
||||
|
||||
parse_export:
|
||||
; parse nm
|
||||
call leb128_decode_u32
|
||||
print " name: %.*s ", eax, ebx
|
||||
add ebx, eax
|
||||
|
||||
movzx eax, byte [ebx]
|
||||
advance
|
||||
test eax, eax
|
||||
je .funcidx
|
||||
cmp eax, 0x01
|
||||
je .tableidx
|
||||
cmp eax, 0x02
|
||||
je .memidx
|
||||
cmp eax, 0x03
|
||||
je .globalidx
|
||||
|
||||
.funcidx:
|
||||
call leb128_decode_u32
|
||||
println " Export type: funcidx (%d)", eax
|
||||
ret
|
||||
|
||||
.tableidx:
|
||||
call leb128_decode_u32
|
||||
println " Export type: tableidx (%d)", eax
|
||||
ret
|
||||
|
||||
.memidx:
|
||||
call leb128_decode_u32
|
||||
println " Export type: memidx (%d)", eax
|
||||
ret
|
||||
|
||||
.globalidx:
|
||||
call leb128_decode_u32
|
||||
println " Export type: globalidx (%d)", eax
|
||||
ret
|
||||
|
||||
parse_start_sec:
|
||||
call leb128_decode_u32
|
||||
println ""
|
||||
println "Section 8: Start (%d bytes)", eax
|
||||
add eax, ebx
|
||||
push eax
|
||||
call leb128_decode_u32
|
||||
println " Function index: %d", eax
|
||||
pop eax
|
||||
cmp eax, ebx
|
||||
jne .error
|
||||
ret
|
||||
.error:
|
||||
println "Error while parsing start section: Section size is incorrect"
|
||||
jmp parse_error
|
||||
|
||||
|
||||
parse_element_sec:
|
||||
call leb128_decode_u32
|
||||
println ""
|
||||
println "Section 9: Element (%d bytes)", eax
|
||||
add eax, ebx
|
||||
push eax
|
||||
call leb128_decode_u32
|
||||
println " Vector of Elem (Length: %d)", eax
|
||||
mov edi, eax
|
||||
.loop:
|
||||
test edi, edi
|
||||
jz .done
|
||||
call parse_elem
|
||||
dec edi
|
||||
jmp .loop
|
||||
.done:
|
||||
pop esi
|
||||
cmp ebx, esi
|
||||
jne .error
|
||||
ret
|
||||
.error:
|
||||
println "Error while parsing element section: Section size is incorrect, supposed to end at 0x%x but ended at 0x%x", ebx, esi
|
||||
jmp parse_error
|
||||
|
||||
|
||||
parse_elem:
|
||||
call leb128_decode_u32
|
||||
println " tableidx: %d", eax
|
||||
println " offset"
|
||||
call parse_const_expr
|
||||
print " vector of funcidx: "
|
||||
call leb128_decode_u32
|
||||
push edi
|
||||
mov edi, eax
|
||||
.loop:
|
||||
test edi, edi
|
||||
jz .done
|
||||
call leb128_decode_u32
|
||||
print " %d ", eax
|
||||
dec edi
|
||||
jmp .loop
|
||||
.done:
|
||||
pop edi
|
||||
println ""
|
||||
ret
|
||||
|
||||
|
||||
parse_code_sec:
|
||||
call leb128_decode_u32
|
||||
println ""
|
||||
println "Section 10: Code (%d bytes) - Skipping", eax
|
||||
add ebx, eax
|
||||
ret
|
||||
|
||||
|
||||
parse_data_sec:
|
||||
call leb128_decode_u32
|
||||
println ""
|
||||
println "Section 11: Data (%d bytes)", eax
|
||||
add eax, ebx
|
||||
push eax
|
||||
call leb128_decode_u32
|
||||
println " Vector of Data (Length: %d)", eax
|
||||
mov edi, eax
|
||||
.loop:
|
||||
test edi, edi
|
||||
jz .done
|
||||
call parse_data
|
||||
dec edi
|
||||
jmp .loop
|
||||
.done:
|
||||
pop esi
|
||||
cmp ebx, esi
|
||||
jne .error
|
||||
ret
|
||||
.error:
|
||||
println "Error while parsing Data section: Section size is incorrect"
|
||||
jmp parse_error
|
||||
|
||||
|
||||
parse_data:
|
||||
call leb128_decode_u32
|
||||
println " memidx: %d", eax
|
||||
call parse_const_expr
|
||||
print " vector of bytes:"
|
||||
call leb128_decode_u32
|
||||
push edi
|
||||
mov edi, eax
|
||||
.loop:
|
||||
test edi, edi
|
||||
jz .done
|
||||
movzx esi, byte [ebx]
|
||||
advance
|
||||
print " 0x%x", esi
|
||||
dec edi
|
||||
jmp .loop
|
||||
.done:
|
||||
pop edi
|
||||
println ""
|
||||
ret
|
||||
|
||||
; -----------------------------------------------------------------
|
||||
; expression parsing
|
||||
; parse wasm instructions
|
||||
; -------------------------------------------------------------------
|
||||
parse_op_simple:
|
||||
movzx eax, byte [ebx]
|
||||
advance
|
||||
println " %s ", dword [opcode_str_table + eax * 4]
|
||||
ret
|
||||
|
||||
parse_op_u32:
|
||||
movzx esi, byte [ebx]
|
||||
advance
|
||||
call leb128_decode_u32
|
||||
println " %s %d", dword [opcode_str_table + esi * 4], eax
|
||||
ret
|
||||
|
||||
parse_op_memarg:
|
||||
push edi
|
||||
movzx esi, byte [ebx]
|
||||
advance
|
||||
call leb128_decode_u32
|
||||
mov edi, eax
|
||||
call leb128_decode_u32
|
||||
println "%s align=%d offset=%d", dword [opcode_str_table + esi * 4], edi, eax
|
||||
pop edi
|
||||
ret
|
||||
|
||||
parse_blocktype:
|
||||
cmp byte [ebx], 0x40
|
||||
je .exit
|
||||
print " (result "
|
||||
call valtype_to_str
|
||||
test eax, eax
|
||||
jne .error
|
||||
print ")"
|
||||
.exit:
|
||||
advance
|
||||
println ""
|
||||
ret
|
||||
.error:
|
||||
println "Error: Invalid valtype type while parsing blocktype"
|
||||
jmp parse_error
|
||||
|
||||
parse_op_block:
|
||||
movzx esi, byte [ebx]
|
||||
advance
|
||||
print " %s ", dword [opcode_str_table + esi * 4]
|
||||
call parse_blocktype
|
||||
.instr:
|
||||
jmp parse_expr
|
||||
.error:
|
||||
println "An error occurred while parsing %s expression", dword [opcode_str_table + esi * 4]
|
||||
jmp parse_error
|
||||
|
||||
|
||||
parse_op_if:
|
||||
push edi
|
||||
movzx esi, byte [ebx]
|
||||
advance
|
||||
print " %s ", dword [opcode_str_table + esi * 4]
|
||||
call parse_blocktype
|
||||
mov edi, 0x0b
|
||||
mov esi, 0x05
|
||||
.loop:
|
||||
movzx eax, byte[ebx]
|
||||
cmp eax ,edi
|
||||
je .done
|
||||
cmp eax, esi
|
||||
je .else
|
||||
call dword [opcode_parse_table + eax * 4]
|
||||
jmp .loop
|
||||
.else:
|
||||
advance
|
||||
println ""
|
||||
println "else"
|
||||
|
||||
@@:
|
||||
movzx eax, byte [ebx]
|
||||
advance
|
||||
cmp eax, edi
|
||||
je .done
|
||||
call dword [opcode_parse_table + eax * 4]
|
||||
jmp @b
|
||||
.done:
|
||||
advance
|
||||
pop edi
|
||||
println "end"
|
||||
ret
|
||||
|
||||
parse_op_br_table:
|
||||
movzx esi, byte [ebx]
|
||||
advance
|
||||
print " %s ", dword [opcode_str_table + esi * 4]
|
||||
call leb128_decode_u32
|
||||
push edi
|
||||
mov edi, eax
|
||||
.loop:
|
||||
test edi, edi
|
||||
jz .done
|
||||
call leb128_decode_u32
|
||||
print " %d", eax
|
||||
dec edi
|
||||
.done:
|
||||
call leb128_decode_u32
|
||||
println " labelidx: %d", eax
|
||||
pop edi
|
||||
ret
|
||||
|
||||
|
||||
parse_call_indirect:
|
||||
movzx esi, byte [ebx]
|
||||
advance
|
||||
call leb128_decode_u32
|
||||
println " %s (%d) " , dword [opcode_str_table + esi * 4], eax
|
||||
movzx eax, byte [ebx]
|
||||
advance
|
||||
cmp eax, 0
|
||||
jne .error
|
||||
ret
|
||||
.error:
|
||||
println "Error while parsing call_indirect, expected 0x00, but got 0x%x", eax
|
||||
jmp parse_error
|
||||
|
||||
parse_mem_inst:
|
||||
movzx esi, byte [ebx]
|
||||
advance
|
||||
println "%s", dword [opcode_str_table + esi * 4]
|
||||
movzx eax, byte[ebx]
|
||||
advance
|
||||
test eax, eax
|
||||
jnz .error
|
||||
ret
|
||||
|
||||
.error:
|
||||
println "Error while parsing memory instruction (%s): expected 0x00, but got 0x%x", dword [opcode_str_table + esi * 4], eax
|
||||
jmp parse_error
|
||||
|
||||
|
||||
parse_op_f64:
|
||||
movzx esi, byte [ebx]
|
||||
advance
|
||||
mov eax, [buf_end]
|
||||
sub eax, ebx
|
||||
cmp eax, 8
|
||||
jl .error
|
||||
print " %s ", dword [opcode_str_table + esi * 4]
|
||||
println "%lf", dword [ebx], dword [ebx + 4] ; argument are pushed in reversed order
|
||||
add ebx, 8
|
||||
ret
|
||||
.error:
|
||||
println "Error: Incomplete binary for f64"
|
||||
jmp parse_error
|
||||
|
||||
|
||||
parse_op_f32:
|
||||
movzx esi, byte [ebx]
|
||||
advance
|
||||
mov eax, [buf_end]
|
||||
sub eax, ebx
|
||||
cmp eax, 4
|
||||
jl .error
|
||||
movss xmm0, dword [ebx]
|
||||
add ebx, 4
|
||||
cvtss2sd xmm0, xmm0
|
||||
sub esp, 8
|
||||
movsd [esp], xmm0
|
||||
pop eax
|
||||
pop edx
|
||||
print "%s ", dword [opcode_str_table + esi * 4]
|
||||
println "%lf", edx, eax
|
||||
ret
|
||||
.error:
|
||||
println "Error: Incomplete binary for f32"
|
||||
jmp parse_error
|
||||
|
||||
|
||||
parse_expr:
|
||||
movzx esi, byte [ebx] ; read but don't advance so handler can handle their opcode themselves
|
||||
cmp esi, 0x0B
|
||||
je .done
|
||||
call dword [opcode_parse_table + esi * 4]
|
||||
jmp parse_expr
|
||||
.done:
|
||||
advance ; advance the end byte
|
||||
ret
|
||||
|
||||
parse_const_expr:
|
||||
movzx esi, byte [ebx]
|
||||
cmp esi, 0x0B
|
||||
je .error_empty ; empty const expr is invalid
|
||||
cmp esi, OP_GLOBAL_GET
|
||||
je .dispatch
|
||||
cmp esi, OP_I32_CONST
|
||||
jl .error
|
||||
cmp esi, OP_F64_CONST
|
||||
jg .error
|
||||
.dispatch:
|
||||
call dword [opcode_parse_table + esi * 4]
|
||||
movzx esi, byte [ebx]
|
||||
cmp esi, 0x0B
|
||||
jne .error_multiple
|
||||
advance
|
||||
ret
|
||||
.error_empty:
|
||||
println "Error: empty constant expression"
|
||||
jmp parse_error
|
||||
.error_multiple:
|
||||
println "Error: multiple instructions in constant expression"
|
||||
jmp parse_error
|
||||
.error:
|
||||
println "Error: invalid instruction in constant expression (0x%x)", esi
|
||||
jmp parse_error
|
||||
|
||||
parse_op_i32:
|
||||
movzx esi, byte [ebx]
|
||||
advance
|
||||
call leb128_decode_s32
|
||||
println "%s %d", dword [opcode_str_table + esi * 4], eax
|
||||
ret
|
||||
|
||||
parse_op_i64:
|
||||
ret
|
||||
|
||||
parse_error:
|
||||
println "Error occured while parsing"
|
||||
mov ebp, [parse_saved_ebp]
|
||||
mov esp, [parse_saved_esp]
|
||||
ret
|
||||
@@ -0,0 +1,117 @@
|
||||
; SPDX-License-Identifier: GPL-2.0-only
|
||||
; Reshare - Shared Resources Daemon
|
||||
;
|
||||
; Copyright (C) 2026 KolibriOS Team
|
||||
|
||||
format binary as ""
|
||||
|
||||
use32
|
||||
org 0
|
||||
|
||||
db 'MENUET01'
|
||||
dd 1
|
||||
dd START
|
||||
dd I_END
|
||||
dd MEM
|
||||
dd STACKTOP
|
||||
dd parameters
|
||||
dd 00
|
||||
|
||||
include 'wasm_kolibrios_interface.inc'
|
||||
include '../core/wasm_parser.inc'
|
||||
|
||||
START:
|
||||
mcall 68, 11
|
||||
stdcall dll.Load, @IMPORT
|
||||
or eax, eax
|
||||
|
||||
jnz .exit
|
||||
|
||||
cmp byte[parameters], 0
|
||||
je .no_file
|
||||
|
||||
; get file details
|
||||
mov eax, 70
|
||||
mov dword [file_info_struct], 5
|
||||
|
||||
mov dword [file_info_struct + 16], ddib_block
|
||||
mov dword [file_info_struct +21], parameters
|
||||
mov ebx, file_info_struct
|
||||
mcall
|
||||
test eax, eax
|
||||
jnz .file_details_error
|
||||
; get size (hopefully no wasm file doesn't exceed 4gb)
|
||||
mov ecx, dword [ddib_block + 32]
|
||||
mov [file_siz], ecx
|
||||
; println "Size gotten for file: %s is %d", parameters, ecx
|
||||
mov ebx, 12
|
||||
mov eax, 68
|
||||
mcall
|
||||
|
||||
|
||||
mov [file_ptr], eax
|
||||
|
||||
mov eax, 70
|
||||
mov ebx, [file_ptr]
|
||||
mov dword [file_info_struct], 0
|
||||
mov dword [file_info_struct + 4], 0
|
||||
mov dword [file_info_struct + 8], 0
|
||||
mov ecx, dword [file_siz]
|
||||
mov dword [file_info_struct + 12], ecx
|
||||
mov dword [file_info_struct + 16], ebx
|
||||
mov dword [file_info_struct + 20], 0
|
||||
mov dword [file_info_struct + 21], parameters
|
||||
mov ebx, file_info_struct
|
||||
mcall
|
||||
|
||||
test eax, eax
|
||||
jne .file_read_error
|
||||
|
||||
mov eax, [file_ptr]
|
||||
mov ebx, dword [file_siz]
|
||||
; println "Passing ptr: 0x0x, and size: %d to wasm_parse", eax, ebx
|
||||
call wasm_parse
|
||||
mov ebx, 13
|
||||
mov eax, 68
|
||||
mov ecx, [file_ptr]
|
||||
mcall
|
||||
jmp .exit
|
||||
|
||||
.no_file:
|
||||
println "Usage: wasm_dis <filename>"
|
||||
jmp .exit
|
||||
.file_details_error:
|
||||
println "An error occurred while getting details for file: %s", parameters
|
||||
jmp .exit
|
||||
|
||||
.file_read_error:
|
||||
println "An error occured while reading file: %s", parameters
|
||||
|
||||
.exit:
|
||||
print "Press any key to exit"
|
||||
invoke con_getc
|
||||
invoke con_exit, 1
|
||||
mov eax, -1
|
||||
mcall
|
||||
I_END:
|
||||
|
||||
file_info_struct:
|
||||
.fn dd 0
|
||||
.offset dd 0
|
||||
.offset2 dd 0
|
||||
.size dd 0
|
||||
.ptr dd 0
|
||||
.ecd db 0
|
||||
.path dd 0
|
||||
|
||||
file_ptr dd ?
|
||||
file_siz dd ?
|
||||
|
||||
rb 131072 ; reserve 128kb
|
||||
align 16
|
||||
|
||||
STACKTOP:
|
||||
|
||||
parameters rb 1024
|
||||
ddib_block rb 560 ; 40 bytes + at most 520 for bytes
|
||||
MEM:
|
||||
@@ -0,0 +1,65 @@
|
||||
; SPDX-License-Identifier: GPL-2.0-only
|
||||
; Reshare - Shared Resources Daemon
|
||||
;
|
||||
; Copyright (C) 2026 KolibriOS Team
|
||||
|
||||
|
||||
include '../../../../proc32.inc'
|
||||
include '../../../../macros.inc'
|
||||
include '../../../../dll.inc'
|
||||
include '../../../../string.inc'
|
||||
|
||||
align 16
|
||||
@IMPORT:
|
||||
library terminal, 'console.obj'
|
||||
|
||||
import terminal, \
|
||||
con_init, 'con_init', \
|
||||
con_exit, 'con_exit', \
|
||||
con_printf, 'con_printf', \
|
||||
con_getc, 'con_getch'
|
||||
|
||||
macro print str, [args]{
|
||||
common
|
||||
pusha
|
||||
local ..s, ..count, ..skip
|
||||
..count = 0
|
||||
jmp ..skip
|
||||
..s db str, 0
|
||||
|
||||
..skip:
|
||||
reverse
|
||||
match any, args \{
|
||||
push args
|
||||
..count = ..count + 1
|
||||
\}
|
||||
|
||||
common
|
||||
push ..s
|
||||
call [con_printf]
|
||||
add esp, 4 + (..count * 4)
|
||||
popa
|
||||
}
|
||||
|
||||
|
||||
macro println str, [args]{
|
||||
common
|
||||
pusha
|
||||
local ..s, ..skip, ..count
|
||||
..count = 0
|
||||
jmp ..skip
|
||||
..s db str, 10, 0
|
||||
..skip:
|
||||
|
||||
reverse
|
||||
match any, args \{
|
||||
push args
|
||||
..count = ..count + 1
|
||||
\}
|
||||
common
|
||||
push ..s
|
||||
call [con_printf]
|
||||
add esp, 4 + (..count * 4)
|
||||
popa
|
||||
}
|
||||
|
||||
Executable
BIN
Binary file not shown.
Binary file not shown.
Reference in new issue
Block a user