diff options
| author | Xavier Del Campo Romero <xavi.dcr@tutanota.com> | 2023-11-26 22:43:30 +0100 |
|---|---|---|
| committer | Xavier Del Campo Romero <xavi.dcr@tutanota.com> | 2023-12-29 23:36:21 +0100 |
| commit | 52c18e60929b64285d4bb333f87482d954c9b2e0 (patch) | |
| tree | 836ab3a01d160f45cda4f5a28522fc0bf471011c /src/load.c | |
First commitfirst-step
Diffstat (limited to 'src/load.c')
| -rw-r--r-- | src/load.c | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/src/load.c b/src/load.c new file mode 100644 index 0000000..3ae3bae --- /dev/null +++ b/src/load.c @@ -0,0 +1,204 @@ +#include <wasmfs.h> +#include <sections.h> +#include <wasm_types.h> +#include <errno.h> +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +static int failed_read(FILE *const f) +{ + return fprintf(stderr, "%s: fread(3) failed, feof=%d, ferror=%d\n", + __func__, feof(f), ferror(f)); +} + +static int check_magic(FILE *const f) +{ + static const uint8_t m[] = {'\0', 'a', 's', 'm'}; + uint8_t magic[sizeof m]; + + if (!fread(magic, sizeof magic, 1, f)) + { + failed_read(f); + return -1; + } + else if (memcmp(magic, m, sizeof magic)) + { + fprintf(stderr, "%s: wrong magic bytes\n", __func__); + return -1; + } + + return 0; +} + +static int check_version(FILE *const f) +{ + static const uint8_t v[] = {1, 0, 0, 0}; + uint8_t version[sizeof v]; + + if (!fread(version, sizeof version, 1, f)) + { + failed_read(f); + return -1; + } + else if (memcmp(version, v, sizeof version)) + { + fprintf(stderr, "%s: wrong version\n", __func__); + return -1; + } + + return 0; +} + +static int load_section(struct wasmfs *const w, FILE *const f) +{ + enum + { + CUSTOM, + TYPE, + IMPORT, + FUNCTION, + TABLE, + MEMORY, + GLOBAL, + EXPORT, + START, + ELEMENT, + CODE, + DATA + }; + + static int (*const fn[])(struct wasmfs *, FILE *, unsigned long) = + { + [CUSTOM] = section_custom, + [TYPE] = section_type, + [IMPORT] = section_import, + [FUNCTION] = section_function, + [TABLE] = section_table, + [MEMORY] = section_memory, + [GLOBAL] = section_global, + [EXPORT] = section_export, + [START] = section_start, + [ELEMENT] = section_element, + [CODE] = section_code, + [DATA] = section_data + }; + + varuint7 section; + varuint32 len; + int ret; + + if (varuint7_read(f, §ion)) + { + if (feof(f)) + return 0; + + fprintf(stderr, "%s: varuint7_read failed\n", __func__); + return 1; + } + else if (section >= sizeof fn / sizeof *fn) + { + fprintf(stderr, "%s: invalid section %u\n", __func__, + (unsigned)section); + return 1; + } + else if (varuint32_read(f, &len)) + { + fprintf(stderr, "%s: varuint32_read failed\n", __func__); + return 1; + } + else if ((ret = fn[section](w, f, len))) + fprintf(stderr, "%s: failed to load section %u\n", __func__, + (unsigned)section); + + return ret; +} + +static int load_sections(struct wasmfs *const w, FILE *const f) +{ + while (!feof(f)) + if (load_section(w, f)) + { + fprintf(stderr, "%s: load_section failed\n", __func__); + return -1; + } + + return 0; +} + +static int load(struct wasmfs *const w, FILE *const f) +{ + if (check_magic(f)) + { + fprintf(stderr, "%s: load_magic failed\n", __func__); + return -1; + } + else if (check_version(f)) + { + fprintf(stderr, "%s: check_version failed\n", __func__); + return -1; + } + else if (load_sections(w, f)) + { + fprintf(stderr, "%s: load_sections failed\n", __func__); + return -1; + } + + return 0; +} + +struct wasmfs *wasmfs_load(const char *const path) +{ + struct wasmfs *ret = NULL, *w = NULL; + char *pathdup = NULL; + FILE *const f = fopen(path, "rb"); + const size_t sz = strlen(path) + 1; + + if (!f) + { + fprintf(stderr, "%s: fopen(3) %s: %s\n", __func__, path, + strerror(errno)); + goto end; + } + else if (!(w = malloc(sizeof *w))) + { + fprintf(stderr, "%s: malloc(3) w: %s\n", __func__, strerror(errno)); + goto end; + } + else if (!(pathdup = malloc(sz))) + { + fprintf(stderr, "%s: malloc(3) pathdup: %s\n", __func__, + strerror(errno)); + goto end; + } + + memcpy(pathdup, path, sz); + + *w = (const struct wasmfs) + { + .path = pathdup + }; + + if (load(w, f)) + { + fprintf(stderr, "%s: load failed\n", __func__); + goto end; + } + + ret = w; + +end: + if (f && fclose(f)) + { + fprintf(stderr, "%s: fclose(3) %s: %s\n", __func__, path, + strerror(errno)); + ret = NULL; + } + + if (!ret) + wasmfs_unload(w); + + return ret; +} |
