protoverse

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

commit 22f1efd015b054f7a52916d37c62d9930184ac29
parent c5c6d4645ec00158de1ab291694701b957e3c6c0
Author: William Casarin <jb55@jb55.com>
Date:   Thu, 15 Jul 2021 10:03:17 -0700

I CAN PARSE C PROGRAMS!

Diffstat:
Msrc/cursor.h | 2+-
Msrc/wasm.c | 69++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
Msrc/wasm.h | 10+++++++++-
3 files changed, 68 insertions(+), 13 deletions(-)

diff --git a/src/cursor.h b/src/cursor.h @@ -321,7 +321,7 @@ 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); + printf("[%ld/%ld]\n", cur->p - cur->start, cur->end - cur->start); c = max(cur->p - range, cur->start); for (; c < cur->end && c < (cur->p + range); c++) { diff --git a/src/wasm.c b/src/wasm.c @@ -249,6 +249,9 @@ static inline int cursor_popdata(struct cursor *cur, unsigned char *dest, int le static inline int was_section_parsed(struct module *module, enum section_tag section) { + if (section == section_custom) + return module->custom_sections > 0; + return module->parsed & (1 << section); } @@ -496,6 +499,11 @@ static const char *get_function_name(struct module *module, int func_index) return "unknown"; } +static void print_element_section(struct elemsec *section) +{ + printf("%d elements\n", section->num_elements); +} + static void print_start_section(struct module *module) { int fn = module->start_section.start_fn; @@ -553,11 +561,20 @@ static void print_data_section(struct datasec *section) printf("%d data segments\n", section->num_datas); } +static void print_custom_section(struct customsec *section) +{ + printf("custom (%s) %d bytes\n", section->name, section->data_len); +} + static void print_section(struct module *module, enum section_tag section) { + u32 i; + switch (section) { case section_custom: - printf("TODO: print custom section\n"); + for (i = 0; i < module->custom_sections; i++) { + print_custom_section(&module->custom_section[i]); + } break; case section_type: print_type_section(&module->type_section); @@ -584,7 +601,7 @@ static void print_section(struct module *module, enum section_tag section) print_start_section(module); break; case section_element: - printf("TODO: print element section\n"); + print_element_section(&module->element_section); break; case section_code: print_code_section(&module->code_section); @@ -951,7 +968,8 @@ static int parse_reftype(struct wasm_parser *p, enum reftype *reftype) } if (!is_valid_reftype(tag)) { - parse_err(p, "invalid reftype: 0x%x", reftype); + cursor_print_around(&p->cur, 10); + parse_err(p, "invalid reftype: 0x%02x", tag); return 0; } @@ -1275,6 +1293,7 @@ static int parse_expr(struct wasm_parser *p, struct expr *expr) static int parse_element(struct wasm_parser *p, struct elem *elem) { u8 tag = 0; + unsigned int i; (void)elem; if (!pull_byte(&p->cur, &tag)) @@ -1291,8 +1310,14 @@ static int parse_element(struct wasm_parser *p, struct elem *elem) if (!parse_vector(p, sizeof(*elem->func_indices), &elem->num_func_indices, - (void**)&elem->func_indices)) + (void**)&elem->func_indices)) { return parse_err(p, "elem 0x00 func indices"); + } + + for (i = 0; i < elem->num_func_indices; i++) { + if (!leb128_read(&p->cur, &elem->func_indices[i])) + return parse_err(p, "func index %d read fail", i); + } elem->mode = elem_mode_active; elem->tableidx = 0; @@ -1306,6 +1331,22 @@ static int parse_element(struct wasm_parser *p, struct elem *elem) return 1; } +static int parse_custom_section(struct wasm_parser *p, u32 size, + struct customsec *section) +{ + u8 *start; + start = p->cur.p; + + if (!parse_name(p, &section->name)) + return parse_err(p, "name"); + + section->data = p->cur.p; + section->data_len = size - (p->cur.p - start); + p->cur.p += section->data_len; + p->module.custom_sections++; + + return 1; +} static int parse_element_section(struct wasm_parser *p, struct elemsec *elemsec) { @@ -1317,7 +1358,7 @@ static int parse_element_section(struct wasm_parser *p, struct elemsec *elemsec) for (i = 0; i < count; i++) { if (!parse_element(p, &elements[i])) - return parse_err(p, "element %d/%d", i+1, count); + return parse_err(p, "element %d of %d", i+1, count); } elemsec->num_elements = count; @@ -1631,13 +1672,15 @@ static int parse_type_section(struct wasm_parser *p, struct typesec *typesec) } static int parse_section_by_tag(struct wasm_parser *p, enum section_tag tag, - unsigned int size) + u32 size) { (void)size; switch (tag) { case section_custom: - parse_err(p, "section_custom parse not implemented"); - return 0; + if (!parse_custom_section(p, size, + &p->module.custom_section[p->module.custom_sections])) + return parse_err(p, "custom section"); + return 1; case section_type: if (!parse_type_section(p, &p->module.type_section)) { return parse_err(p, "type section"); @@ -1680,7 +1723,10 @@ static int parse_section_by_tag(struct wasm_parser *p, enum section_tag tag, return 1; case section_element: - return parse_element_section(p, &p->module.element_section); + if (!parse_element_section(p, &p->module.element_section)) { + return parse_err(p, "element section"); + } + return 1; case section_code: if (!parse_code_section(p, &p->module.code_section)) { @@ -1763,6 +1809,7 @@ static int parse_section(struct wasm_parser *p) int parse_wasm(struct wasm_parser *p) { p->module.parsed = 0; + p->module.custom_sections = 0; if (!consume_bytes(&p->cur, WASM_MAGIC, sizeof(WASM_MAGIC))) { parse_err(p, "magic"); @@ -1784,8 +1831,8 @@ int parse_wasm(struct wasm_parser *p) } } - debug("module parse success!\n\n"); print_module(&p->module); + debug("module parse success!\n\n"); return 1; fail: @@ -2675,7 +2722,7 @@ static int find_start_function(struct module *module) return module->start_section.start_fn; } - return find_function(module, "start"); + return find_function(module, "start") || find_function(module, "_start"); } static inline int array_alloc(struct cursor *mem, struct array *a, int elems) diff --git a/src/wasm.h b/src/wasm.h @@ -98,12 +98,18 @@ struct expr { struct elem { struct expr offset; int tableidx; - int *func_indices; + unsigned int *func_indices; unsigned int num_func_indices; enum elem_mode mode; enum reftype reftype; }; +struct customsec { + const char *name; + unsigned char *data; + int data_len; +}; + struct elemsec { struct elem *elements; int num_elements; @@ -413,6 +419,8 @@ struct startsec { struct module { unsigned int parsed; + unsigned int custom_sections; + struct customsec custom_section[32]; struct typesec type_section; struct funcsec func_section; struct importsec import_section;