aboutsummaryrefslogtreecommitdiff
path: root/src/section/import.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>2024-04-21 01:51:24 +0200
commitf25b015e5b668028c34974bbb22faa4105c26690 (patch)
tree28f2b08c17b3585d06694ad74004d0617eadb785 /src/section/import.c
downloadnanowasm-sync-f25b015e5b668028c34974bbb22faa4105c26690.tar.gz
First commit
Diffstat (limited to 'src/section/import.c')
-rw-r--r--src/section/import.c274
1 files changed, 274 insertions, 0 deletions
diff --git a/src/section/import.c b/src/section/import.c
new file mode 100644
index 0000000..5dd708e
--- /dev/null
+++ b/src/section/import.c
@@ -0,0 +1,274 @@
+/*
+ * nanowasm, a tiny WebAssembly/Wasm interpreter
+ * Copyright (C) 2023-2024 Xavier Del Campo Romero
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
+ */
+
+#include <nw/sections.h>
+#include <nw/fstring.h>
+#include <nw/log.h>
+#include <nw/types.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+static int dump_import_name(FILE *const f, const varuint32 len)
+{
+ for (varuint32 i = 0; i < len; i++)
+ {
+ uint8_t byte;
+
+ if (!fread(&byte, sizeof byte, 1, f))
+ {
+ LOG("%s: fread(3) failed, feof=%d, ferror=%d\n",
+ __func__, feof(f), ferror(f));
+ return -1;
+ }
+
+ LOG("%c", (char)byte);
+ }
+
+ return 0;
+}
+
+static int check_module_string(const struct nw_mod_cfg *const cfg,
+ FILE *const f)
+{
+ varuint32 len;
+
+ if (varuint32_read(f, &len))
+ {
+ LOG("%s: varuint32_read failed\n", __func__);
+ return -1;
+ }
+
+ for (size_t i = 0; i < cfg->n_imports; i++)
+ {
+ const struct nw_import *const im = &cfg->imports[i];
+ const char *const mod = im->module;
+
+ if (strlen(mod) == len)
+ {
+ const long offset = ftell(f);
+
+ if (offset < 0)
+ {
+ LOG("%s: ftell(3): %s\n", __func__, strerror(errno));
+ return -1;
+ }
+ else if (!fstrcmp(mod, f, true))
+ return 0;
+ else if (fseek(f, offset, SEEK_SET))
+ {
+ LOG("%s: fseek(3): %s\n", __func__, strerror(errno));
+ return -1;
+ }
+ }
+ }
+
+ LOG("%s: required imported module ", __func__);
+ dump_import_name(f, len);
+ LOG(" not found\n");
+ return -1;
+}
+
+static int check_field_string(const struct nw_mod_cfg *const cfg,
+ FILE *const f)
+{
+ varuint32 len;
+
+ if (varuint32_read(f, &len))
+ {
+ LOG("%s: varuint32_read failed\n", __func__);
+ return -1;
+ }
+
+ for (size_t i = 0; i < cfg->n_imports; i++)
+ {
+ const struct nw_import *const im = &cfg->imports[i];
+ const char *const field = im->field;
+
+ if (strlen(field) == len)
+ {
+ const long offset = ftell(f);
+
+ if (offset < 0)
+ {
+ LOG("%s: ftell(3): %s\n", __func__, strerror(errno));
+ return -1;
+ }
+ else if (!fstrcmp(field, f, true))
+ return 0;
+ else if (fseek(f, offset, SEEK_SET))
+ {
+ LOG("%s: fseek(3): %s\n", __func__, strerror(errno));
+ return -1;
+ }
+ }
+ }
+
+ LOG("%s: required imported field ", __func__);
+ dump_import_name(f, len);
+ LOG(" not found\n");
+ return -1;
+}
+
+static int check_function_kind(FILE *const f)
+{
+ varuint32 type;
+
+ if (varuint32_read(f, &type))
+ {
+ LOG("%s: varuint32_read failed\n", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int check_table_kind(FILE *const f)
+{
+ varint7 type;
+
+ if (varint7_read(f, &type))
+ {
+ LOG("%s: varint7_read failed\n", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int check_memory_kind(FILE *const f)
+{
+ /* TODO. */
+ return -1;
+}
+
+static int check_global_kind(FILE *const f)
+{
+ /* TODO. */
+ return -1;
+}
+
+static int check_import_entry(const struct nw_mod_cfg *const cfg,
+ FILE *const f)
+{
+ if (check_module_string(cfg, f))
+ {
+ LOG("%s: check_module_string failed\n", __func__);
+ return -1;
+ }
+ else if (check_field_string(cfg, f))
+ {
+ LOG("%s: check_field_string failed\n", __func__);
+ return -1;
+ }
+
+ uint8_t kind;
+
+ if (!fread(&kind, sizeof kind, 1, f))
+ {
+ LOG("%s: fread(3) failed, feof=%d, ferror=%d\n",
+ __func__, feof(f), ferror(f));
+ return -1;
+ }
+
+ static int (*const fn[])(FILE *) =
+ {
+ [NW_KIND_FUNCTION] = check_function_kind,
+ [NW_KIND_TABLE] = check_table_kind,
+ [NW_KIND_MEMORY] = check_memory_kind,
+ [NW_KIND_GLOBAL] = check_global_kind
+ };
+
+ if (kind >= sizeof fn / sizeof *fn)
+ {
+ LOG("%s: unexpected kind %#" PRIx8 "\n", __func__, kind);
+ return -1;
+ }
+
+ return fn[kind](f);
+}
+
+static int check(const struct nw_mod_cfg *const cfg, FILE *const f,
+ const unsigned long len)
+{
+ const long start = ftell(f);
+
+ if (start < 0)
+ {
+ LOG("%s: ftell(3): %s\n", __func__, strerror(errno));
+ return -1;
+ }
+
+ varuint32 count;
+
+ if (varuint32_read(f, &count))
+ {
+ LOG("%s: varuint32_read failed\n", __func__);
+ return -1;
+ }
+
+ for (varuint32 i = 0; i < count; i++)
+ if (check_import_entry(cfg, f))
+ {
+ LOG("%s: check_import_entry failed\n", __func__);
+ return -1;
+ }
+
+ const long end = ftell(f);
+
+ if (end < 0)
+ {
+ LOG("%s: ftell(3): %s\n", __func__, strerror(errno));
+ return -1;
+ }
+
+ const unsigned long size = end - start;
+
+ if (size != len)
+ {
+ LOG("%s: size exceeded (%lu expected, got %lu)\n",
+ __func__, len, size);
+ return -1;
+ }
+
+ return 0;
+}
+
+int section_import_check(const struct section *const s, struct nw_mod *m,
+ const unsigned long len)
+{
+ const struct nw_mod_cfg *const cfg = s->cfg;
+ FILE *const f = s->f;
+
+ if (m->sections.import)
+ {
+ LOG("%s: ignoring duplicate section\n", __func__);
+ return fseek(f, len, SEEK_CUR);
+ }
+
+ const long offset = ftell(f);
+
+ if (offset < 0)
+ {
+ LOG("%s: ftell(3): %s\n", __func__, strerror(errno));
+ return -1;
+ }
+ else if (check(cfg, f, len))
+ {
+ LOG("%s: check failed\n", __func__);
+ return -1;
+ }
+
+ m->sections.import = offset;
+ return 0;
+}