protoverse

A metaverse protocol
git clone git://jb55.com/protoverse
Log | Files | Refs | README | LICENSE

commit 1cb57204cc9f8c6bc3a797922a8a550bf64ec3eb
parent 94b5055bb6aa96b3241863171524f6ee0e5b8525
Author: William Casarin <jb55@jb55.com>
Date:   Tue, 13 Jul 2021 11:59:10 -0700

start to generalize error handling

Signed-off-by: William Casarin <jb55@jb55.com>

Diffstat:
MMakefile | 4++++
Msrc/cursor.h | 50++++++++++++++++++++++++++++++++++++++------------
Asrc/error.c | 27+++++++++++++++++++++++++++
Asrc/error.h | 28++++++++++++++++++++++++++++
Msrc/parse.c | 36++++++++++++++++++++----------------
Msrc/parse.h | 1-
Msrc/wasm.c | 433+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
Msrc/wasm.h | 7+++----
8 files changed, 377 insertions(+), 209 deletions(-)

diff --git a/Makefile b/Makefile @@ -3,6 +3,9 @@ CFLAGS = -Wno-error=unused-function -O2 -g -std=gnu90 -Wall -Wextra -Werror \ -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes \ -Wmissing-declarations -Wdeclaration-after-statement +debug: CFLAGS += -DDEBUG +debug: all + OBJS = src/io.o \ src/parse.o \ src/describe.o \ @@ -11,6 +14,7 @@ OBJS = src/io.o \ src/net.o \ src/varint.o \ src/parser.o \ + src/error.o \ src/wasm.o WASMS = wasm/hello-c.wasm \ diff --git a/src/cursor.h b/src/cursor.h @@ -63,6 +63,17 @@ static inline void *cursor_alloc(struct cursor *mem, unsigned long size) return ret; } +static inline int cursor_slice(struct cursor *mem, struct cursor *slice, size_t size) +{ + u8 *p; + if (!(p = cursor_alloc(mem, size))) { + return 0; + } + make_cursor(p, mem->p, slice); + return 1; +} + + static inline void copy_cursor(struct cursor *src, struct cursor *dest) { dest->start = src->start; @@ -81,8 +92,22 @@ static inline int pull_byte(struct cursor *cursor, u8 *c) return 1; } +static inline int cursor_pull_c_str(struct cursor *cursor, const char **str) +{ + *str = (const char*)cursor->p; + + for (; cursor->p < cursor->end; cursor->p++) { + if (*cursor->p == 0) { + cursor->p++; + return 1; + } + } + + return 0; +} + -static inline int push_byte(struct cursor *cursor, u8 c) +static inline int cursor_push_byte(struct cursor *cursor, u8 c) { if (unlikely(cursor->p + 1 > cursor->end)) { return 0; @@ -94,7 +119,7 @@ static inline int push_byte(struct cursor *cursor, u8 c) return 1; } -static inline int pull_data(struct cursor *cursor, u8 *data, int len) +static inline int cursor_pull(struct cursor *cursor, u8 *data, int len) { if (unlikely(cursor->p + len > cursor->end)) { return 0; @@ -118,7 +143,7 @@ static inline int pull_data_into_cursor(struct cursor *cursor, return 0; } - ok = pull_data(cursor, dest->p, len); + ok = cursor_pull(cursor, dest->p, len); if (!ok) return 0; *data = dest->p; @@ -175,13 +200,13 @@ static inline int push_varint(struct cursor *cursor, int n) n >>= 7; if (n == 0) { b &= 0x7F; - ok = push_byte(cursor, b); + ok = cursor_push_byte(cursor, b); len++; if (!ok) return 0; break; } - ok = push_byte(cursor, b); + ok = cursor_push_byte(cursor, b); len++; if (!ok) return 0; } @@ -213,9 +238,9 @@ static inline int pull_varint(struct cursor *cursor, int *n) return 0; } -static inline int pull_int(struct cursor *cursor, int *i) +static inline int cursor_pull_int(struct cursor *cursor, int *i) { - return pull_data(cursor, (u8*)i, sizeof(*i)); + return cursor_pull(cursor, (u8*)i, sizeof(*i)); } static inline int cursor_push_u16(struct cursor *cursor, u16 i) @@ -240,17 +265,16 @@ static inline int push_sized_str(struct cursor *cursor, const char *str, int len return cursor_push(cursor, (u8*)str, len); } -static inline int push_str(struct cursor *cursor, const char *str) +static inline int cursor_push_str(struct cursor *cursor, const char *str) { return cursor_push(cursor, (u8*)str, strlen(str)); } -static inline int push_c_str(struct cursor *cursor, const char *str) +static inline int cursor_push_c_str(struct cursor *cursor, const char *str) { - return push_str(cursor, str) && push_byte(cursor, 0); + return cursor_push_str(cursor, str) && cursor_push_byte(cursor, 0); } - /* TODO: push varint size */ static inline int push_prefixed_str(struct cursor *cursor, const char *str) { @@ -275,7 +299,7 @@ static inline int pull_prefixed_str(struct cursor *cursor, struct cursor *dest_b ok = pull_data_into_cursor(cursor, dest_buf, (unsigned char**)str, len); if (!ok) return 0; - ok = push_byte(dest_buf, 0); + ok = cursor_push_byte(dest_buf, 0); return 1; } @@ -291,6 +315,8 @@ static inline void cursor_print_around(struct cursor *cur, int range) { unsigned char *c; + printf("[%ld/%ld] ", cur->p - cur->start, cur->end - cur->start); + c = max(cur->p - range, cur->start); for (; c < cur->end && c < (cur->p + range); c++) { printf("%02x", *c); diff --git a/src/error.c b/src/error.c @@ -0,0 +1,27 @@ + +#include "error.h" + +#include <stdlib.h> +#include <stdarg.h> + +void note_error_(struct cursor *errs, struct cursor *p, const char *fmt, ...) +{ + static char buf[512]; + struct error err; + + va_list ap; + va_start(ap, fmt); + vsprintf(buf, fmt, ap); + va_end(ap); + + err.msg = (char*)errs->p; + err.pos = p->p - p->start; + + if (!cursor_push_error(errs, &err)) { + fprintf(stderr, "arena OOM when recording error, "); + fprintf(stderr, "cur->p at %ld, remaining %ld, strlen %ld\n", + p->p - p->start, p->end - p->p, strlen(buf)); + return; + } +} + diff --git a/src/error.h b/src/error.h @@ -0,0 +1,28 @@ + +#ifndef PROTOVERSE_ERROR_H +#define PROTOVERSE_ERROR_H + +#include "cursor.h" + +struct error { + int pos; + const char *msg; +}; + +#define note_error(errs, p, fmt, ...) note_error_(errs, p, "%s: " fmt, __FUNCTION__, ##__VA_ARGS__) + +static inline int cursor_push_error(struct cursor *cur, struct error *err) +{ + return cursor_push_int(cur, err->pos) && + cursor_push_c_str(cur, err->msg); +} + +static inline int cursor_pull_error(struct cursor *cur, struct error *err) +{ + return cursor_pull_int(cur, &err->pos) && + cursor_pull_c_str(cur, &err->msg); +} + +void note_error_(struct cursor *errs, struct cursor *p, const char *fmt, ...); + +#endif /* PROTOVERSE_ERROR_H */ diff --git a/src/parse.c b/src/parse.c @@ -87,9 +87,8 @@ static void copy_token_cursor(struct token_cursor *src, struct token_cursor *des memcpy(&dest->err_data, &src->err_data, sizeof(src->err_data)); } -void make_token_cursor(u8 *start, u8 *end, struct token_cursor *cursor) +static void init_token_cursor(struct token_cursor *cursor) { - make_cursor(start, end, &cursor->c); cursor->err = TE_OK; memset(&cursor->err_data, 0, sizeof(cursor->err_data)); } @@ -230,7 +229,7 @@ static int push_token_data(struct token_cursor *tokens, struct tok_str *str; #endif int ok; - ok = push_byte(&tokens->c, token); + ok = cursor_push_byte(&tokens->c, token); if (!ok) return 0; switch (token) { @@ -604,8 +603,8 @@ static int pull_token_data(struct cursor *tokens, union token *token, case T_STRING: case T_SYMBOL: case T_NUMBER: - ok = pull_data(tokens, (void*)&token->str, - sizeof(struct tok_str)); + ok = cursor_pull(tokens, (void*)&token->str, + sizeof(struct tok_str)); return ok; } @@ -1312,29 +1311,34 @@ close: int init_parser(struct parser *parser) { + struct cursor mem; + u8 *pmem; + int ok; + int attrs_size = sizeof(struct attribute) * 1024; int tokens_size = 2048; int cells_size = sizeof(struct cell) * 1024; + int memsize = attrs_size + tokens_size + cells_size; + + if (!(pmem = calloc(1, attrs_size + tokens_size + cells_size))) { + return 0; + } - u8 *token_buf = calloc(1, tokens_size); - u8 *attrs_buf = calloc(1, attrs_size); - u8 *cells_buf = calloc(1, cells_size); + make_cursor(pmem, pmem + memsize, &mem); - if (!token_buf) return 0; - if (!attrs_buf) return 0; - if (!cells_buf) return 0; + ok = + cursor_slice(&mem, &parser->cells, cells_size) && + cursor_slice(&mem, &parser->attributes, attrs_size) && + cursor_slice(&mem, &parser->tokens.c, tokens_size); + assert(ok); - make_cursor(cells_buf, cells_buf + cells_size, &parser->cells); - make_cursor(attrs_buf, attrs_buf + attrs_size, &parser->attributes); - make_token_cursor(token_buf, token_buf + tokens_size, &parser->tokens); + init_token_cursor(&parser->tokens); return 1; } int free_parser(struct parser *parser) { - free(parser->tokens.c.start); - free(parser->attributes.start); free(parser->cells.start); return 1; diff --git a/src/parse.h b/src/parse.h @@ -136,7 +136,6 @@ int init_parser(struct parser *parser); int free_parser(struct parser *parser); void print_cell(struct cursor *attributes, struct cell *cell); int tokenize_cells(unsigned char *buf, int buf_size, struct token_cursor *tokens); -void make_token_cursor(u8 *start, u8 *end, struct token_cursor *cursor); int parse_cell(struct parser *parser, u16 *index); void print_token_error(struct token_cursor *cursor); const char *cell_type_str(enum cell_type); diff --git a/src/wasm.c b/src/wasm.c @@ -2,6 +2,7 @@ #include "wasm.h" #include "parser.h" #include "debug.h" +#include "error.h" #include <stdarg.h> #include <stdio.h> @@ -10,20 +11,14 @@ #include <string.h> #include <stdint.h> -#define note_error(p, fmt, ...) note_error_(p, "%s: " fmt, __FUNCTION__, ##__VA_ARGS__) #define interp_error(p, fmt, ...) interp_error_(p, "%s: " fmt, __FUNCTION__, ##__VA_ARGS__) +#define parse_err(p, fmt, ...) note_error(&(p)->errs, &(p)->cur, fmt, ##__VA_ARGS__) #define ERR_STACK_SIZE 16 #define NUM_LOCALS 0xFFFF static const int MAX_LABELS = 128; -struct parse_error { - int pos; - char *msg; - struct parse_error *next; -}; - struct val { enum valtype type; union { @@ -74,6 +69,134 @@ static const char *valtype_name(enum valtype valtype) return "unk"; } +static char *instr_name(enum instr_tag tag) +{ + static char unk[6] = {0}; + + switch (tag) { + case i_unreachable: return "unreachable"; + case i_nop: return "nop"; + case i_block: return "block"; + case i_loop: return "loop"; + case i_if: return "if"; + case i_else: return "else"; + case i_end: return "end"; + case i_br: return "br"; + case i_br_if: return "br_if"; + case i_br_table: return "br_table"; + case i_return: return "return"; + case i_call: return "call"; + case i_call_indirect: return "call_indirect"; + case i_drop: return "drop"; + case i_select: return "select"; + case i_local_get: return "local_get"; + case i_local_set: return "local_set"; + case i_local_tee: return "local_tee"; + case i_global_get: return "global_get"; + case i_global_set: return "global_set"; + case i_i32_load: return "i32_load"; + case i_i64_load: return "i64_load"; + case i_f32_load: return "f32_load"; + case i_f64_load: return "f64_load"; + case i_i32_load8_s: return "i32_load8_s"; + case i_i32_load8_u: return "i32_load8_u"; + case i_i32_load16_s: return "i32_load16_s"; + case i_i32_load16_u: return "i32_load16_u"; + case i_i64_load8_s: return "i64_load8_s"; + case i_i64_load8_u: return "i64_load8_u"; + case i_i64_load16_s: return "i64_load16_s"; + case i_i64_load16_u: return "i64_load16_u"; + case i_i64_load32_s: return "i64_load32_s"; + case i_i64_load32_u: return "i64_load32_u"; + case i_i32_store: return "i32_store"; + case i_i64_store: return "i64_store"; + case i_f32_store: return "f32_store"; + case i_f64_store: return "f64_store"; + case i_i32_store8: return "i32_store8"; + case i_i32_store16: return "i32_store16"; + case i_i64_store8: return "i64_store8"; + case i_i64_store16: return "i64_store16"; + case i_i64_store32: return "i64_store32"; + case i_memory_size: return "memory_size"; + case i_memory_grow: return "memory_grow"; + case i_i32_const: return "i32_const"; + case i_i64_const: return "i64_const"; + case i_f32_const: return "f32_const"; + case i_f64_const: return "f64_const"; + case i_i32_eqz: return "i32_eqz"; + case i_i32_eq: return "i32_eq"; + case i_i32_ne: return "i32_ne"; + case i_i32_lt_s: return "i32_lt_s"; + case i_i32_lt_u: return "i32_lt_u"; + case i_i32_gt_s: return "i32_gt_s"; + case i_i32_gt_u: return "i32_gt_u"; + case i_i32_le_s: return "i32_le_s"; + case i_i32_le_u: return "i32_le_u"; + case i_i32_ge_s: return "i32_ge_s"; + case i_i32_ge_u: return "i32_ge_u"; + case i_i64_eqz: return "i64_eqz"; + case i_i64_eq: return "i64_eq"; + case i_i64_ne: return "i64_ne"; + case i_i64_lt_s: return "i64_lt_s"; + case i_i64_lt_u: return "i64_lt_u"; + case i_i64_gt_s: return "i64_gt_s"; + case i_i64_gt_u: return "i64_gt_u"; + case i_i64_le_s: return "i64_le_s"; + case i_i64_le_u: return "i64_le_u"; + case i_i64_ge_s: return "i64_ge_s"; + case i_i64_ge_u: return "i64_ge_u"; + case i_f32_eq: return "f32_eq"; + case i_f32_ne: return "f32_ne"; + case i_f32_lt: return "f32_lt"; + case i_f32_gt: return "f32_gt"; + case i_f32_le: return "f32_le"; + case i_f32_ge: return "f32_ge"; + case i_f64_eq: return "f64_eq"; + case i_f64_ne: return "f64_ne"; + case i_f64_lt: return "f64_lt"; + case i_f64_gt: return "f64_gt"; + case i_f64_le: return "f64_le"; + case i_f64_ge: return "f64_ge"; + case i_i32_clz: return "i32_clz"; + case i_i32_add: return "i32_add"; + case i_i32_sub: return "i32_sub"; + case i_i32_mul: return "i32_mul"; + case i_i32_div_s: return "i32_div_s"; + case i_i32_div_u: return "i32_div_u"; + case i_i32_rem_s: return "i32_rem_s"; + case i_i32_rem_u: return "i32_rem_u"; + case i_i32_and: return "i32_and"; + case i_i32_or: return "i32_or"; + case i_i32_xor: return "i32_xor"; + case i_i32_shl: return "i32_shl"; + case i_i32_shr_s: return "i32_shr_s"; + case i_i32_shr_u: return "i32_shr_u"; + case i_i32_rotl: return "i32_rotl"; + case i_i32_rotr: return "i32_rotr"; + case i_i64_clz: return "i64_clz"; + case i_i64_ctz: return "i64_ctz"; + case i_i64_popcnt: return "i64_popcnt"; + case i_i64_add: return "i64_add"; + case i_i64_sub: return "i64_sub"; + case i_i64_mul: return "i64_mul"; + case i_i64_div_s: return "i64_div_s"; + case i_i64_div_u: return "i64_div_u"; + case i_i64_rem_s: return "i64_rem_s"; + case i_i64_rem_u: return "i64_rem_u"; + case i_i64_and: return "i64_and"; + case i_i64_or: return "i64_or"; + case i_i64_xor: return "i64_xor"; + case i_i64_shl: return "i64_shl"; + case i_i64_shr_s: return "i64_shr_s"; + case i_i64_shr_u: return "i64_shr_u"; + case i_i64_rotl: return "i64_rotl"; + case i_i64_rotr: return "i64_rotr"; + } + + snprintf(unk, sizeof(unk), "0x%02x", tag); + return unk; +} + static void print_val(struct val *val) { switch (val->type) { @@ -190,60 +313,20 @@ static void interp_error_(struct wasm_interp *p, const char *fmt, ...) va_end(ap); } -static void note_error_(struct wasm_parser *p, const char *fmt, ...) +static void print_parse_backtrace(struct wasm_parser *p) { - static char buf[512]; - struct parse_error err; - struct parse_error *perr, *new_err; + struct cursor errs; + struct error err; - va_list ap; - va_start(ap, fmt); - vsprintf(buf, fmt, ap); - va_end(ap); - - perr = NULL; - err.msg = (char*)p->mem.p; - err.pos = p->cur.p - p->cur.start; - err.next = NULL; - - if (!push_c_str(&p->mem, buf)) { - fprintf(stderr, "arena OOM when recording parse error, "); - fprintf(stderr, "mem->p at %ld, remaining %ld, strlen %ld\n", - p->mem.p - p->mem.start, - p->mem.end - p->mem.p, - strlen(buf)); - return; - } - - new_err = (struct parse_error *)p->mem.p; + copy_cursor(&p->errs, &errs); + errs.p = errs.start; - if (!cursor_push(&p->mem, (unsigned char*)&err, sizeof(err))) { - fprintf(stderr, "arena OOM when pushing data, "); - fprintf(stderr, "mem->p at %ld, remaining %ld, data size %ld\n", - p->mem.p - p->mem.start, - p->mem.end - p->mem.p, - sizeof(err)); - return; - } - - for (perr = p->errors; perr != NULL;) { - if (perr == NULL || perr->next == NULL) - break; - perr = perr->next; - } - - if (p->errors == NULL) { - p->errors = new_err; - } else { - perr->next = new_err; - } -} - -static void print_parse_backtrace(struct wasm_parser *p) -{ - struct parse_error *err; - for (err = p->errors; err != NULL; err = err->next) { - fprintf(stderr, "%08x:%s\n", err->pos, err->msg); + while (errs.p < p->errs.end) { + if (!cursor_pull_error(&errs, &err)) { + fprintf(stderr, "backtrace: couldn't pull error\n"); + return; + } + fprintf(stderr, "%08x:%s\n", err.pos, err.msg); } } @@ -580,7 +663,7 @@ static int parse_valtype(struct wasm_parser *p, enum valtype *valtype) start = p->cur.p; if (!pull_byte(&p->cur, (unsigned char*)valtype)) { - note_error(p, "valtype tag oob"); + parse_err(p, "valtype tag oob"); return 0; } @@ -588,7 +671,7 @@ static int parse_valtype(struct wasm_parser *p, enum valtype *valtype) return 1; p->cur.p = start; - note_error(p, "%c is not a valid valtype tag", *valtype); + parse_err(p, "%c is not a valid valtype tag", *valtype); return 0; } @@ -603,20 +686,20 @@ static int parse_result_type(struct wasm_parser *p, struct resulttype *rt) start = p->mem.p; if (!leb128_read(&p->cur, (unsigned int*)&elems)) { - note_error(p, "vec len"); + parse_err(p, "vec len"); return 0; } for (i = 0; i < elems; i++) { if (!parse_valtype(p, &valtype)) { - note_error(p, "valtype #%d", i); + parse_err(p, "valtype #%d", i); p->mem.p = start; return 0; } - if (!push_byte(&p->mem, (unsigned char)valtype)) { - note_error(p, "valtype push data OOM #%d", i); + if (!cursor_push_byte(&p->mem, (unsigned char)valtype)) { + parse_err(p, "valtype push data OOM #%d", i); p->mem.p = start; return 0; } @@ -632,17 +715,17 @@ static int parse_result_type(struct wasm_parser *p, struct resulttype *rt) static int parse_func_type(struct wasm_parser *p, struct functype *func) { if (!consume_byte(&p->cur, FUNC_TYPE_TAG)) { - note_error(p, "type tag"); + parse_err(p, "type tag"); return 0; } if (!parse_result_type(p, &func->params)) { - note_error(p, "params"); + parse_err(p, "params"); return 0; } if (!parse_result_type(p, &func->result)) { - note_error(p, "result"); + parse_err(p, "result"); return 0; } @@ -653,18 +736,18 @@ static int parse_name(struct wasm_parser *p, const char **name) { unsigned int bytes; if (!leb128_read(&p->cur, &bytes)) { - note_error(p, "name len"); + parse_err(p, "name len"); return 0; } if (!pull_data_into_cursor(&p->cur, &p->mem, (unsigned char**)name, bytes)) { - note_error(p, "name string"); + parse_err(p, "name string"); return 0; } - if (!push_byte(&p->mem, 0)) { - note_error(p, "name null byte"); + if (!cursor_push_byte(&p->mem, 0)) { + parse_err(p, "name null byte"); return 0; } @@ -676,7 +759,7 @@ static int parse_export_desc(struct wasm_parser *p, enum exportdesc *desc) unsigned char byte; if (!pull_byte(&p->cur, &byte)) { - note_error(p, "export desc byte eof"); + parse_err(p, "export desc byte eof"); return 0; } @@ -689,24 +772,24 @@ static int parse_export_desc(struct wasm_parser *p, enum exportdesc *desc) return 1; } - note_error(p, "invalid tag: %x", byte); + parse_err(p, "invalid tag: %x", byte); return 0; } static int parse_export(struct wasm_parser *p, struct wexport *export) { if (!parse_name(p, &export->name)) { - note_error(p, "export name"); + parse_err(p, "export name"); return 0; } if (!parse_export_desc(p, &export->desc)) { - note_error(p, "export desc"); + parse_err(p, "export desc"); return 0; } if (!leb128_read(&p->cur, &export->index)) { - note_error(p, "export index"); + parse_err(p, "export index"); return 0; } @@ -716,12 +799,12 @@ static int parse_export(struct wasm_parser *p, struct wexport *export) static int parse_local(struct wasm_parser *p, struct local *local) { if (!leb128_read(&p->cur, &local->n)) { - note_error(p, "n"); + parse_err(p, "n"); return 0; } if (!parse_valtype(p, &local->valtype)) { - note_error(p, "valtype"); + parse_err(p, "valtype"); return 0; } @@ -732,14 +815,14 @@ static int parse_vector(struct wasm_parser *p, unsigned int item_size, unsigned int *elems, void **items) { if (!leb128_read(&p->cur, elems)) { - note_error(p, "len"); + parse_err(p, "len"); return 0; } *items = cursor_alloc(&p->mem, *elems * item_size); if (*items == NULL) { - note_error(p, "vector alloc oom"); + parse_err(p, "vector alloc oom"); return 0; } @@ -753,20 +836,20 @@ static int parse_func(struct wasm_parser *p, struct func *func) struct local *locals; if (!leb128_read(&p->cur, &size)) { - note_error(p, "code size"); + parse_err(p, "code size"); return 0; } start = p->cur.p; if (!parse_vector(p, sizeof(*locals), &elems, (void**)&locals)) { - note_error(p, "locals"); + parse_err(p, "locals"); return 0; } for (i = 0; i < elems; i++) { if (!parse_local(p, &locals[i])) { - note_error(p, "local #%d", i); + parse_err(p, "local #%d", i); return 0; } } @@ -777,7 +860,7 @@ static int parse_func(struct wasm_parser *p, struct func *func) if (!pull_data_into_cursor(&p->cur, &p->mem, &func->code.code, func->code.code_len)) { - note_error(p, "code oom"); + parse_err(p, "code oom"); return 0; } @@ -793,13 +876,13 @@ static int parse_code_section(struct wasm_parser *p, unsigned int elems, i; if (!parse_vector(p, sizeof(*funcs), &elems, (void**)&funcs)) { - note_error(p, "funcs"); + parse_err(p, "funcs"); return 0; } for (i = 0; i < elems; i++) { if (!parse_func(p, &funcs[i])) { - note_error(p, "func #%d", i); + parse_err(p, "func #%d", i); return 0; } } @@ -824,12 +907,12 @@ static int parse_reftype(struct wasm_parser *p, enum reftype *reftype) u8 tag; if (!pull_byte(&p->cur, &tag)) { - note_error(p, "reftype"); + parse_err(p, "reftype"); return 0; } if (!is_valid_reftype(tag)) { - note_error(p, "invalid reftype: 0x%x", reftype); + parse_err(p, "invalid reftype: 0x%x", reftype); return 0; } @@ -846,13 +929,13 @@ static int parse_export_section(struct wasm_parser *p, unsigned int elems, i; if (!parse_vector(p, sizeof(*exports), &elems, (void**)&exports)) { - note_error(p, "vector"); + parse_err(p, "vector"); return 0; } for (i = 0; i < elems; i++) { if (!parse_export(p, &exports[i])) { - note_error(p, "export #%d", i); + parse_err(p, "export #%d", i); return 0; } } @@ -867,17 +950,17 @@ static int parse_limits(struct wasm_parser *p, struct limits *limits) { unsigned char tag; if (!pull_byte(&p->cur, &tag)) { - note_error(p, "oob"); + parse_err(p, "oob"); return 0; } if (tag != limit_min && tag != limit_min_max) { - note_error(p, "invalid tag %02x", tag); + parse_err(p, "invalid tag %02x", tag); return 0; } if (!leb128_read(&p->cur, &limits->min)) { - note_error(p, "min"); + parse_err(p, "min"); return 0; } @@ -885,7 +968,7 @@ static int parse_limits(struct wasm_parser *p, struct limits *limits) return 1; if (!leb128_read(&p->cur, &limits->max)) { - note_error(p, "max"); + parse_err(p, "max"); return 0; } @@ -895,12 +978,12 @@ static int parse_limits(struct wasm_parser *p, struct limits *limits) static int parse_table(struct wasm_parser *p, struct table *table) { if (!parse_reftype(p, &table->reftype)) { - note_error(p, "reftype"); + parse_err(p, "reftype"); return 0; } if (!parse_limits(p, &table->limits)) { - note_error(p, "limits"); + parse_err(p, "limits"); return 0; } @@ -934,12 +1017,12 @@ static int parse_const_instr(struct wasm_parser *p) unsigned int n; if (!pull_byte(&p->cur, &tag)) { - note_error(p, "tag"); + parse_err(p, "tag"); return 0; } if (!is_valid_const_instr(tag)) { - note_error(p, "invalid const instr tag 0x%x", tag); + parse_err(p, "invalid const instr tag 0x%x", tag); p->cur.p--; return 0; } @@ -948,13 +1031,13 @@ static int parse_const_instr(struct wasm_parser *p) case const_i32: case const_i64: if (!leb128_read(&p->cur, &n)) { - note_error(p, "couldn't read integer"); + parse_err(p, "couldn't read integer"); return 0; } break; case const_f32: case const_f64: - note_error(p, "TODO parse float constants"); + parse_err(p, "TODO parse float constants"); return 0; } @@ -967,12 +1050,12 @@ static int parse_ref_instr(struct wasm_parser *p) unsigned int idx; if (!pull_byte(&p->cur, &tag)) { - note_error(p, "tag"); + parse_err(p, "tag"); return 0; } if (!is_valid_ref_instr(tag)) { - //note_error(p, "invalid ref instr tag 0x%x", tag); + //parse_err(p, "invalid ref instr tag 0x%x", tag); p->cur.p--; return 0; } @@ -980,7 +1063,7 @@ static int parse_ref_instr(struct wasm_parser *p) switch ((enum ref_instr)tag) { case ref_null: if (!parse_reftype(p, (enum reftype*)&tag)) { - note_error(p, "invalid ref.null instr reftype 0x%x", tag); + parse_err(p, "invalid ref.null instr reftype 0x%x", tag); return 0; } break; @@ -990,7 +1073,7 @@ static int parse_ref_instr(struct wasm_parser *p) case ref_func: if (!leb128_read(&p->cur, &idx)) { - note_error(p, "invalid ref.func idx"); + parse_err(p, "invalid ref.func idx"); return 0; } break; @@ -1016,7 +1099,7 @@ static int parse_const_expr(struct wasm_parser *p, struct expr *expr) } if (!parse_const_expr_instr(p)) { - note_error(p, "no constant expr found"); + parse_err(p, "no constant expr found"); return 0; } } @@ -1036,14 +1119,14 @@ static int parse_mut(struct wasm_parser *p, enum mut *mut) return 1; } - note_error(p, "unknown mut %02x", *p->cur.p); + parse_err(p, "unknown mut %02x", *p->cur.p); return 0; } static int parse_globaltype(struct wasm_parser *p, struct globaltype *g) { if (!parse_valtype(p, &g->valtype)) { - note_error(p, "valtype"); + parse_err(p, "valtype"); return 0; } @@ -1054,12 +1137,12 @@ static int parse_global(struct wasm_parser *p, struct global *global) { if (!parse_globaltype(p, &global->type)) { - note_error(p, "type"); + parse_err(p, "type"); return 0; } if (!parse_const_expr(p, &global->init)) { - note_error(p, "init code"); + parse_err(p, "init code"); return 0; } @@ -1073,13 +1156,13 @@ static int parse_global_section(struct wasm_parser *p, unsigned int elems, i; if (!parse_vector(p, sizeof(*globals), &elems, (void**)&globals)) { - note_error(p, "globals vector"); + parse_err(p, "globals vector"); return 0; } for (i = 0; i < elems; i++) { if (!parse_global(p, &globals[i])) { - note_error(p, "global #%d/%d", i+1, elems); + parse_err(p, "global #%d/%d", i+1, elems); return 0; } } @@ -1097,13 +1180,13 @@ static int parse_memory_section(struct wasm_parser *p, unsigned int elems, i; if (!parse_vector(p, sizeof(*mems), &elems, (void**)&mems)) { - note_error(p, "mems vector"); + parse_err(p, "mems vector"); return 0; } for (i = 0; i < elems; i++) { if (!parse_limits(p, &mems[i])) { - note_error(p, "memory #%d/%d", i+1, elems); + parse_err(p, "memory #%d/%d", i+1, elems); return 0; } } @@ -1118,7 +1201,7 @@ static int parse_start_section(struct wasm_parser *p, struct startsec *start_section) { if (!leb128_read(&p->cur, (unsigned int*)&start_section->start_fn)) { - note_error(p, "start_fn index"); + parse_err(p, "start_fn index"); return 0; } @@ -1129,12 +1212,12 @@ static inline int parse_byte_vector(struct wasm_parser *p, unsigned char **data, int *data_len) { if (!leb128_read(&p->cur, (unsigned int*)data_len)) { - note_error(p, "len"); + parse_err(p, "len"); return 0; } if (p->cur.p + *data_len > p->cur.end) { - note_error(p, "byte vector overflow"); + parse_err(p, "byte vector overflow"); return 0; } @@ -1149,13 +1232,13 @@ static int parse_wdata(struct wasm_parser *p, struct wdata *data) u8 tag; if (!pull_byte(&p->cur, &tag)) { - note_error(p, "tag"); + parse_err(p, "tag"); return 0; } if (tag > 2) { cursor_print_around(&p->cur, 10); - note_error(p, "invalid datasegment tag: 0x%x", tag); + parse_err(p, "invalid datasegment tag: 0x%x", tag); return 0; } @@ -1165,12 +1248,12 @@ static int parse_wdata(struct wasm_parser *p, struct wdata *data) data->active.mem_index = 0; if (!parse_const_expr(p, &data->active.offset_expr)) { - note_error(p, "const expr"); + parse_err(p, "const expr"); return 0; } if (!parse_byte_vector(p, &data->bytes, &data->bytes_len)) { - note_error(p, "bytes vector"); + parse_err(p, "bytes vector"); return 0; } @@ -1180,7 +1263,7 @@ static int parse_wdata(struct wasm_parser *p, struct wdata *data) data->mode = datamode_passive; if (!parse_byte_vector(p, &data->bytes, &data->bytes_len)) { - note_error(p, "passive bytes vector"); + parse_err(p, "passive bytes vector"); return 0; } @@ -1190,17 +1273,17 @@ static int parse_wdata(struct wasm_parser *p, struct wdata *data) data->mode = datamode_active; if (!leb128_read(&p->cur, (unsigned int*)&data->active.mem_index)) { - note_error(p, "read active data mem_index"); + parse_err(p, "read active data mem_index"); return 0; } if (!parse_const_expr(p, &data->active.offset_expr)) { - note_error(p, "read active data (w/ mem_index) offset_expr"); + parse_err(p, "read active data (w/ mem_index) offset_expr"); return 0; } if (!parse_byte_vector(p, &data->bytes, &data->bytes_len)) { - note_error(p, "active (w/ mem_index) bytes vector"); + parse_err(p, "active (w/ mem_index) bytes vector"); return 0; } @@ -1216,13 +1299,13 @@ static int parse_data_section(struct wasm_parser *p, struct datasec *section) unsigned int elems, i; if (!parse_vector(p, sizeof(*data), &elems, (void**)&data)) { - note_error(p, "datas vector"); + parse_err(p, "datas vector"); return 0; } for (i = 0; i < elems; i++) { if (!parse_wdata(p, &data[i])) { - note_error(p, "data segment #%d/%d", i+1, elems); + parse_err(p, "data segment #%d/%d", i+1, elems); return 0; } } @@ -1240,13 +1323,13 @@ static int parse_table_section(struct wasm_parser *p, unsigned int elems, i; if (!parse_vector(p, sizeof(*tables), &elems, (void**)&tables)) { - note_error(p, "tables vector"); + parse_err(p, "tables vector"); return 0; } for (i = 0; i < elems; i++) { if (!parse_table(p, &tables[i])) { - note_error(p, "table #%d/%d", i+1, elems); + parse_err(p, "table #%d/%d", i+1, elems); return 0; } } @@ -1264,13 +1347,13 @@ static int parse_function_section(struct wasm_parser *p, unsigned int i, elems; if (!parse_vector(p, sizeof(*indices), &elems, (void**)&indices)) { - note_error(p, "indices"); + parse_err(p, "indices"); return 0; } for (i = 0; i < elems; i++) { if (!leb128_read(&p->cur, &indices[i])) { - note_error(p, "typeidx #%d", i); + parse_err(p, "typeidx #%d", i); return 0; } } @@ -1284,12 +1367,12 @@ static int parse_function_section(struct wasm_parser *p, static int parse_import_table(struct wasm_parser *p, struct limits *limits) { if (!consume_byte(&p->cur, 0x70)) { - note_error(p, "elemtype != 0x70"); + parse_err(p, "elemtype != 0x70"); return 0; } if (!parse_limits(p, limits)) { - note_error(p, "limits"); + parse_err(p, "limits"); return 0; } @@ -1301,7 +1384,7 @@ static int parse_importdesc(struct wasm_parser *p, struct importdesc *desc) unsigned char tag; if (!pull_byte(&p->cur, &tag)) { - note_error(p, "oom"); + parse_err(p, "oom"); return 0; } @@ -1310,7 +1393,7 @@ static int parse_importdesc(struct wasm_parser *p, struct importdesc *desc) switch (desc->type) { case import_func: if (!leb128_read(&p->cur, &desc->typeidx)) { - note_error(p, "typeidx"); + parse_err(p, "typeidx"); return 0; } return 1; @@ -1320,7 +1403,7 @@ static int parse_importdesc(struct wasm_parser *p, struct importdesc *desc) case import_mem: if (!parse_limits(p, &desc->memtype)) { - note_error(p, "memtype limits"); + parse_err(p, "memtype limits"); return 0; } @@ -1328,31 +1411,31 @@ static int parse_importdesc(struct wasm_parser *p, struct importdesc *desc) case import_global: if (!parse_globaltype(p, &desc->globaltype)) { - note_error(p, "globaltype"); + parse_err(p, "globaltype"); return 0; } return 1; } - note_error(p, "unknown importdesc tag %02x", tag); + parse_err(p, "unknown importdesc tag %02x", tag); return 0; } static int parse_import(struct wasm_parser *p, struct import *import) { if (!parse_name(p, &import->module_name)) { - note_error(p, "module name"); + parse_err(p, "module name"); return 0; } if (!parse_name(p, &import->name)) { - note_error(p, "name"); + parse_err(p, "name"); return 0; } if (!parse_importdesc(p, &import->import_desc)) { - note_error(p, "desc"); + parse_err(p, "desc"); return 0; } @@ -1365,13 +1448,13 @@ static int parse_import_section(struct wasm_parser *p, struct importsec *imports struct import *imports; if (!parse_vector(p, sizeof(*imports), &elems, (void**)&imports)) { - note_error(p, "imports"); + parse_err(p, "imports"); return 0; } for (i = 0; i < elems; i++) { if (!parse_import(p, &imports[i])) { - note_error(p, "import #%d", i); + parse_err(p, "import #%d", i); return 0; } } @@ -1392,13 +1475,13 @@ static int parse_type_section(struct wasm_parser *p, struct typesec *typesec) typesec->functypes = NULL; if (!parse_vector(p, sizeof(*functypes), &elems, (void**)&functypes)) { - note_error(p, "functypes"); + parse_err(p, "functypes"); return 0; } for (i = 0; i < elems; i++) { if (!parse_func_type(p, &functypes[i])) { - note_error(p, "functype #%d", i); + parse_err(p, "functype #%d", i); return 0; } } @@ -1415,73 +1498,73 @@ static int parse_section_by_tag(struct wasm_parser *p, enum section_tag tag, (void)size; switch (tag) { case section_custom: - note_error(p, "section_custom parse not implemented"); + parse_err(p, "section_custom parse not implemented"); return 0; case section_type: if (!parse_type_section(p, &p->module.type_section)) { - note_error(p, "type section"); + parse_err(p, "type section"); return 0; } return 1; case section_import: if (!parse_import_section(p, &p->module.import_section)) { - note_error(p, "import section"); + parse_err(p, "import section"); return 0; } return 1; case section_function: if (!parse_function_section(p, &p->module.func_section)) { - note_error(p, "function section"); + parse_err(p, "function section"); return 0; } return 1; case section_table: if (!parse_table_section(p, &p->module.table_section)) { - note_error(p, "table section"); + parse_err(p, "table section"); return 0; } return 1; case section_memory: if (!parse_memory_section(p, &p->module.memory_section)) { - note_error(p, "memory section"); + parse_err(p, "memory section"); return 0; } return 1; case section_global: if (!parse_global_section(p, &p->module.global_section)) { - note_error(p, "global section"); + parse_err(p, "global section"); return 0; } return 1; case section_export: if (!parse_export_section(p, &p->module.export_section)) { - note_error(p, "export section"); + parse_err(p, "export section"); return 0; } return 1; case section_start: if (!parse_start_section(p, &p->module.start_section)) { - note_error(p, "start section"); + parse_err(p, "start section"); return 0; } return 1; case section_element: - note_error(p, "section_element parse not implemented"); + parse_err(p, "section_element parse not implemented"); return 0; case section_code: if (!parse_code_section(p, &p->module.code_section)) { - note_error(p, "code section"); + parse_err(p, "code section"); return 0; } return 1; case section_data: if (!parse_data_section(p, &p->module.data_section)) { - note_error(p, "data section"); + parse_err(p, "data section"); return 0; } return 1; default: - note_error(p, "invalid section tag"); + parse_err(p, "invalid section tag"); return 0; } @@ -1528,17 +1611,17 @@ static int parse_section(struct wasm_parser *p) unsigned int bytes; if (!parse_section_tag(&p->cur, &tag)) { - note_error(p, "section tag"); + parse_err(p, "section tag"); return 2; } if (!leb128_read(&p->cur, &bytes)) { - note_error(p, "section len"); + parse_err(p, "section len"); return 0; } if (!parse_section_by_tag(p, tag, bytes)) { - note_error(p, "%s (%d bytes)", section_name(tag), bytes); + parse_err(p, "%s (%d bytes)", section_name(tag), bytes); return 0; } @@ -1552,12 +1635,12 @@ int parse_wasm(struct wasm_parser *p) p->module.parsed = 0; if (!consume_bytes(&p->cur, WASM_MAGIC, sizeof(WASM_MAGIC))) { - note_error(p, "magic"); + parse_err(p, "magic"); goto fail; } if (!consume_u32(&p->cur, WASM_VERSION)) { - note_error(p, "version"); + parse_err(p, "version"); goto fail; } @@ -1566,7 +1649,7 @@ int parse_wasm(struct wasm_parser *p) break; if (!parse_section(p)) { - note_error(p, "section"); + parse_err(p, "section"); goto fail; } } @@ -1903,7 +1986,6 @@ static int parse_blocktype(struct cursor *cur, struct blocktype *blocktype) unsigned char byte; if (!pull_byte(cur, &byte)) { - cursor_print_around(cur, 10); printf("parse_blocktype: oob\n"); return 0; } @@ -2237,8 +2319,14 @@ static int interp_if(struct wasm_interp *interp) { struct val cond; struct blocktype blocktype; + struct cursor *code; + + if (!(code = interp_codeptr(interp))) { + interp_error(interp, "empty callstack?"); + return 0; + } - if (!parse_blocktype(&interp->cur, &blocktype)) { + if (!parse_blocktype(code, &blocktype)) { interp_error(interp, "couldn't parse blocktype"); return 0; } @@ -2262,7 +2350,10 @@ static int interp_if(struct wasm_interp *interp) static int interp_instr(struct wasm_interp *interp, unsigned char tag) { interp->ops++; - debug("executing 0x%0x\n", tag); + + debug("0x%03lX %s\n", + interp_codeptr(interp)->p - interp_codeptr(interp)->start, + instr_name(tag)); switch (tag) { case i_unreachable: return 1; @@ -2339,16 +2430,6 @@ static int find_start_function(struct module *module) return find_function(module, "start"); } -static int cursor_slice(struct cursor *mem, struct cursor *slice, size_t size) -{ - u8 *p; - if (!(p = cursor_alloc(mem, size))) { - return 0; - } - make_cursor(p, mem->p, slice); - return 1; -} - static inline int array_alloc(struct cursor *mem, struct array *a, int elems) { return cursor_slice(mem, &a->cur, elems * a->elem_size); diff --git a/src/wasm.h b/src/wasm.h @@ -397,10 +397,11 @@ struct callframe { struct wasm_interp { struct module *module; + struct cursor errors; /* struct error */ size_t ops; struct cursor cur; /* code */ - struct cursor callframes; /* struct cursor */ + struct cursor callframes; /* struct callframe */ struct cursor stack; /* struct val */ struct cursor mem; /* u8/mixed */ struct cursor locals; /* struct val */ @@ -413,15 +414,13 @@ struct wasm_interp { // instruction is encountered, the label index is pushed. When an // instruction is popped, we can resolve the label struct cursor resolver_stack; /* u32 */ - - struct parser_error *errors; }; struct wasm_parser { struct module module; struct cursor cur; struct cursor mem; - struct parse_error *errors; + struct cursor errs; };