protoverse

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

commit ad3313f130e3d7cdd972a0f62fbd2b77f3f35a7a
parent 04ba5b3b2abecdd67d7cd2204cfebced579998be
Author: William Casarin <jb55@jb55.com>
Date:   Sun, 29 Nov 2020 16:37:34 -0800

Parse import sections

Diffstat:
Mdefault.nix | 2+-
Msrc/wasm.c | 179++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Msrc/wasm.h | 47++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 224 insertions(+), 4 deletions(-)

diff --git a/default.nix b/default.nix @@ -2,5 +2,5 @@ with pkgs; stdenv.mkDerivation { name = "protoverse"; - nativeBuildInputs = [ gdb wabt ]; + nativeBuildInputs = [ gdb wabt emscripten ]; } diff --git a/src/wasm.c b/src/wasm.c @@ -260,6 +260,21 @@ static const char *exportdesc_name(enum exportdesc desc) return "unknown"; } +static void print_import(struct import *import) +{ + printf("%s %s\n", import->module_name, import->name); +} + +static void print_import_section(struct importsec *importsec) +{ + int i; + printf("%d imports:\n", importsec->num_imports); + for (i = 0; i < importsec->num_imports; i++) { + printf(" "); + print_import(&importsec->imports[i]); + } +} + static void print_export_section(struct exportsec *exportsec) { int i; @@ -301,6 +316,7 @@ static void print_module(struct module *module) { print_type_section(&module->type_section); print_func_section(&module->func_section); + print_import_section(&module->import_section); print_export_section(&module->export_section); print_code_section(&module->code_section); } @@ -676,6 +692,162 @@ static int parse_function_section(struct wasm_parser *p, return 1; } +static int parse_mut(struct wasm_parser *p, enum mut *mut) +{ + if (consume_byte(&p->cur, mut_const)) { + *mut = mut_const; + return 1; + } + + if (consume_byte(&p->cur, mut_var)) { + *mut = mut_var; + return 1; + } + + note_error(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"); + return 0; + } + + return parse_mut(p, &g->mut); +} + +static int parse_limits(struct wasm_parser *p, struct limits *limits) +{ + unsigned char tag; + if (!pull_byte(&p->cur, &tag)) { + note_error(p, "oob"); + return 0; + } + + if (tag != limit_min || tag != limit_min_max) { + note_error(p, "invalid tag %02x", tag); + return 0; + } + + if (!leb128_read(&p->cur, &limits->min)) { + note_error(p, "min"); + return 0; + } + + if (tag == limit_min) + return 1; + + if (!leb128_read(&p->cur, &limits->max)) { + note_error(p, "max"); + return 0; + } + + return 1; +} + +static int parse_import_table(struct wasm_parser *p, struct limits *limits) +{ + if (!consume_byte(&p->cur, 0x70)) { + note_error(p, "elemtype != 0x70"); + return 0; + } + + if (!parse_limits(p, limits)) { + note_error(p, "limits"); + return 0; + } + + return 1; +} + +static int parse_importdesc(struct wasm_parser *p, struct importdesc *desc) +{ + unsigned char tag; + + if (!pull_byte(&p->cur, &tag)) { + note_error(p, "oom"); + return 0; + } + + desc->type = (enum import_type)tag; + + switch (desc->type) { + case import_func: + if (!leb128_read(&p->cur, &desc->typeidx)) { + note_error(p, "typeidx"); + return 0; + } + return 1; + + case import_table: + return parse_import_table(p, &desc->tabletype); + + case import_mem: + if (!parse_limits(p, &desc->memtype)) { + note_error(p, "memtype limits"); + return 0; + } + + return 1; + + case import_global: + if (!parse_globaltype(p, &desc->globaltype)) { + note_error(p, "globaltype"); + return 0; + } + + return 1; + } + + note_error(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"); + return 0; + } + + if (!parse_name(p, &import->name)) { + note_error(p, "name"); + return 0; + } + + if (!parse_importdesc(p, &import->import_desc)) { + note_error(p, "desc"); + return 0; + } + + return 1; +} + +static int parse_import_section(struct wasm_parser *p, struct importsec *importsec) +{ + unsigned int elems, i; + struct import *imports; + + if (!parse_vector(p, sizeof(*imports), &elems, (void**)&imports)) { + note_error(p, "imports"); + return 0; + } + + for (i = 0; i < elems; i++) { + if (!parse_import(p, &imports[i])) { + note_error(p, "import #%d", i); + return 0; + } + } + + importsec->imports = imports; + importsec->num_imports = elems; + + return 1; +} + /* type section is just a vector of function types */ static int parse_type_section(struct wasm_parser *p, struct typesec *typesec) { @@ -718,8 +890,11 @@ static int parse_section_by_tag(struct wasm_parser *p, enum section_tag tag, } return 1; case section_import: - note_error(p, "section_import parse not implemented"); - return 0; + if (!parse_import_section(p, &p->module.import_section)) { + note_error(p, "import section"); + return 0; + } + return 1; case section_function: if (!parse_function_section(p, &p->module.func_section)) { note_error(p, "function section"); diff --git a/src/wasm.h b/src/wasm.h @@ -16,11 +16,17 @@ enum valtype { f64 = 0x7C, }; -enum limits { +enum limit_type { limit_min = 0x00, limit_min_max = 0x01, }; +struct limits { + unsigned int min; + unsigned int max; + enum limit_type type; +}; + enum section_tag { section_custom, section_type, @@ -57,6 +63,44 @@ struct typesec { int num_functypes; }; +enum import_type { + import_func, + import_table, + import_mem, + import_global, +}; + +enum mut { + mut_const, + mut_var, +}; + +struct globaltype { + enum valtype valtype; + enum mut mut; +}; + +struct importdesc { + enum import_type type; + union { + unsigned int typeidx; + struct limits tabletype; + struct limits memtype; + struct globaltype globaltype; + }; +}; + +struct import { + const char *module_name; + const char *name; + struct importdesc import_desc; +}; + +struct importsec { + struct import *imports; + int num_imports; +}; + struct expr { unsigned char *instrs; int num_instrs; @@ -101,6 +145,7 @@ struct exportsec { struct module { struct typesec type_section; struct funcsec func_section; + struct importsec import_section; struct exportsec export_section; struct codesec code_section; };