wasm file loader and header validation
This commit is contained in:
commit
174bfd1d46
7 files changed
+269
No files matched your search
+210
@@ -0,0 +1,210 @@
|
||||
format ELF executable 3
|
||||
entry start
|
||||
|
||||
SYS_EXIT = 1
|
||||
SYS_READ = 3
|
||||
SYS_WRITE = 4
|
||||
SYS_OPEN = 5
|
||||
SYS_CLOSE = 6
|
||||
|
||||
STDOUT = 1
|
||||
O_RDONLY = 0
|
||||
|
||||
WASM_MAGIC = 0x6D736100 ; "\0asm"
|
||||
WASM_VERSION = 0x00000001
|
||||
WASM_HEADER_SZ = 8
|
||||
FILE_BUF_SIZE = 4 * 1024 * 1024
|
||||
|
||||
segment readable executable
|
||||
|
||||
start:
|
||||
mov eax, [esp]
|
||||
cmp eax, 2
|
||||
jl .no_arg
|
||||
|
||||
mov eax, SYS_OPEN
|
||||
mov ebx, [esp + 8]
|
||||
mov ecx, O_RDONLY
|
||||
xor edx, edx
|
||||
int 0x80
|
||||
test eax, eax
|
||||
js .open_err
|
||||
mov [file_fd], eax
|
||||
|
||||
mov eax, SYS_READ
|
||||
mov ebx, [file_fd]
|
||||
mov ecx, file_buf
|
||||
mov edx, FILE_BUF_SIZE
|
||||
int 0x80
|
||||
test eax, eax
|
||||
js .read_err
|
||||
mov [file_size], eax
|
||||
|
||||
mov eax, SYS_CLOSE
|
||||
mov ebx, [file_fd]
|
||||
int 0x80
|
||||
|
||||
cmp dword [file_size], WASM_HEADER_SZ
|
||||
jl .too_small
|
||||
|
||||
mov eax, dword [file_buf]
|
||||
cmp eax, WASM_MAGIC
|
||||
jne .bad_magic
|
||||
|
||||
mov eax, dword [file_buf + 4]
|
||||
cmp eax, WASM_VERSION
|
||||
jne .bad_version
|
||||
|
||||
mov esi, msg_ok
|
||||
call print_str
|
||||
mov esi, msg_size
|
||||
call print_str
|
||||
mov eax, [file_size]
|
||||
call print_dec
|
||||
mov esi, msg_bytes
|
||||
call print_str
|
||||
|
||||
xor ebx, ebx
|
||||
jmp .exit
|
||||
|
||||
.no_arg:
|
||||
mov esi, msg_usage
|
||||
call print_str
|
||||
mov ebx, 1
|
||||
jmp .exit
|
||||
|
||||
.open_err:
|
||||
mov esi, msg_open_err
|
||||
call print_str
|
||||
mov ebx, 1
|
||||
jmp .exit
|
||||
|
||||
.read_err:
|
||||
mov esi, msg_read_err
|
||||
call print_str
|
||||
mov ebx, 1
|
||||
jmp .exit
|
||||
|
||||
.too_small:
|
||||
mov esi, msg_too_small
|
||||
call print_str
|
||||
mov ebx, 1
|
||||
jmp .exit
|
||||
|
||||
.bad_magic:
|
||||
mov esi, msg_bad_magic
|
||||
call print_str
|
||||
mov ebx, 1
|
||||
jmp .exit
|
||||
|
||||
.bad_version:
|
||||
mov esi, msg_bad_ver
|
||||
call print_str
|
||||
mov esi, msg_got_ver
|
||||
call print_str
|
||||
mov eax, dword [file_buf + 4]
|
||||
call print_hex32
|
||||
mov esi, msg_newline
|
||||
call print_str
|
||||
mov ebx, 1
|
||||
jmp .exit
|
||||
|
||||
.exit:
|
||||
mov eax, SYS_EXIT
|
||||
int 0x80
|
||||
|
||||
; esi = null-terminated string
|
||||
print_str:
|
||||
push eax ebx ecx edx esi
|
||||
mov edx, esi
|
||||
@@:
|
||||
cmp byte [edx], 0
|
||||
je @f
|
||||
inc edx
|
||||
jmp @b
|
||||
@@:
|
||||
sub edx, esi
|
||||
mov ecx, esi
|
||||
mov ebx, STDOUT
|
||||
mov eax, SYS_WRITE
|
||||
int 0x80
|
||||
pop esi edx ecx ebx eax
|
||||
ret
|
||||
|
||||
; eax = unsigned 32-bit integer
|
||||
print_dec:
|
||||
push eax ebx ecx edx esi
|
||||
mov ecx, 10
|
||||
lea esi, [dec_buf + 11]
|
||||
mov byte [esi], 0
|
||||
.loop:
|
||||
dec esi
|
||||
xor edx, edx
|
||||
div ecx
|
||||
add dl, '0'
|
||||
mov [esi], dl
|
||||
test eax, eax
|
||||
jnz .loop
|
||||
|
||||
push eax ebx ecx edx
|
||||
mov edx, esi
|
||||
@@:
|
||||
cmp byte [edx], 0
|
||||
je @f
|
||||
inc edx
|
||||
jmp @b
|
||||
@@:
|
||||
sub edx, esi
|
||||
mov ecx, esi
|
||||
mov ebx, STDOUT
|
||||
mov eax, SYS_WRITE
|
||||
int 0x80
|
||||
pop edx ecx ebx eax
|
||||
pop esi edx ecx ebx eax
|
||||
ret
|
||||
|
||||
; eax = 32-bit value printed as 0xHHHHHHHH
|
||||
print_hex32:
|
||||
push eax ebx ecx edx esi
|
||||
lea esi, [hex_buf]
|
||||
mov byte [esi], '0'
|
||||
mov byte [esi+1], 'x'
|
||||
mov ecx, 8
|
||||
add esi, 2
|
||||
.hex_loop:
|
||||
rol eax, 4
|
||||
mov edx, eax
|
||||
and edx, 0x0F
|
||||
mov dl, [hex_chars + edx]
|
||||
mov [esi], dl
|
||||
inc esi
|
||||
dec ecx
|
||||
jnz .hex_loop
|
||||
mov byte [esi], 0
|
||||
lea esi, [hex_buf]
|
||||
call print_str
|
||||
pop esi edx ecx ebx eax
|
||||
ret
|
||||
|
||||
segment readable writeable
|
||||
|
||||
msg_usage db 'Usage: wasm <file.wasm>', 10, 0
|
||||
msg_open_err db 'Error: cannot open file', 10, 0
|
||||
msg_read_err db 'Error: cannot read file', 10, 0
|
||||
msg_too_small db 'Error: file too small (less than 8 bytes)', 10, 0
|
||||
msg_bad_magic db 'Error: invalid wasm magic number (expected \0asm)', 10, 0
|
||||
msg_bad_ver db 'Error: unsupported wasm version', 10, 0
|
||||
msg_got_ver db ' got version: ', 0
|
||||
msg_ok db 'Valid wasm file', 10, 0
|
||||
msg_size db 'File size: ', 0
|
||||
msg_bytes db ' bytes', 10, 0
|
||||
msg_newline db 10, 0
|
||||
|
||||
hex_chars db '0123456789ABCDEF'
|
||||
hex_buf rb 12
|
||||
dec_buf rb 12
|
||||
|
||||
file_fd dd 0
|
||||
file_size dd 0
|
||||
|
||||
file_buf rb FILE_BUF_SIZE
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
#!/bin/sh
|
||||
# Compile all .wat files to .wasm
|
||||
# Run from the test/ directory
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
WAT_DIR="$SCRIPT_DIR/wat"
|
||||
WASM_DIR="$SCRIPT_DIR/wasm"
|
||||
|
||||
mkdir -p "$WASM_DIR"
|
||||
|
||||
for f in "$WAT_DIR"/*.wat; do
|
||||
base=$(basename "$f" .wat)
|
||||
wat2wasm "$f" -o "$WASM_DIR/$base.wasm"
|
||||
echo " $base.wat -> $base.wasm"
|
||||
done
|
||||
|
||||
# edge cases
|
||||
/usr/bin/printf '\x00asm\x02\x00\x00\x00' > "$WASM_DIR/badver.wasm"
|
||||
/usr/bin/printf '\x00bad\x01\x00\x00\x00' > "$WASM_DIR/badmagic.wasm"
|
||||
|
||||
Executable
+34
@@ -0,0 +1,34 @@
|
||||
#!/bin/sh
|
||||
# Run from the repo root
|
||||
|
||||
WASM=./src/wasm
|
||||
PASS=0
|
||||
FAIL=0
|
||||
TESTS=0
|
||||
|
||||
check() {
|
||||
TESTS=$((TESTS + 1))
|
||||
desc="$1"; shift
|
||||
expected="$1"; shift
|
||||
output=$("$@" 2>&1)
|
||||
if echo "$output" | grep -q "$expected"; then
|
||||
PASS=$((PASS + 1))
|
||||
echo " OK $desc"
|
||||
else
|
||||
FAIL=$((FAIL + 1))
|
||||
echo " FAIL $desc"
|
||||
echo " expected: $expected"
|
||||
echo " got: $output"
|
||||
fi
|
||||
}
|
||||
|
||||
echo "=== wasm runtime tests ==="
|
||||
|
||||
check "no arguments" "Usage:" $WASM
|
||||
check "valid wasm" "Valid wasm file" $WASM test/wasm/valid.wasm
|
||||
check "bad magic" "invalid wasm magic" $WASM test/wasm/badmagic.wasm
|
||||
check "bad version" "unsupported wasm" $WASM test/wasm/badver.wasm
|
||||
|
||||
echo ""
|
||||
echo "Results: $PASS/$TESTS passed, $FAIL failed"
|
||||
[ "$FAIL" -eq 0 ] && exit 0 || exit 1
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,5 @@
|
||||
(module
|
||||
(func (export "getSomething") (result i32)
|
||||
i32.const 42
|
||||
)
|
||||
)
|
||||
Reference in new issue
Block a user