summaryrefslogtreecommitdiff
path: root/src/load.c
diff options
context:
space:
mode:
authorXavier Del Campo Romero <xavi.dcr@tutanota.com>2023-11-26 22:43:30 +0100
committerXavier Del Campo Romero <xavi.dcr@tutanota.com>2023-12-29 23:36:21 +0100
commit52c18e60929b64285d4bb333f87482d954c9b2e0 (patch)
tree836ab3a01d160f45cda4f5a28522fc0bf471011c /src/load.c
First commitfirst-step
Diffstat (limited to 'src/load.c')
-rw-r--r--src/load.c204
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, &section))
+ {
+ 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;
+}