summaryrefslogtreecommitdiff
path: root/src/section/global.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/section/global.c')
-rw-r--r--src/section/global.c110
1 files changed, 110 insertions, 0 deletions
diff --git a/src/section/global.c b/src/section/global.c
new file mode 100644
index 0000000..5616e21
--- /dev/null
+++ b/src/section/global.c
@@ -0,0 +1,110 @@
+#include <sections.h>
+#include <interp.h>
+#include <wasm_types.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+struct global_type
+{
+ varint7 value_type;
+ varuint1 mutability;
+};
+
+static int check_global_type(FILE *const f, struct global_type *const g)
+{
+ if (varint7_read(f, &g->value_type))
+ {
+ fprintf(stderr, "%s: varint7_read failed\n", __func__);
+ return -1;
+ }
+ else if (varuint1_read(f, &g->mutability))
+ {
+ fprintf(stderr, "%s: varuint1_read failed\n", __func__);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int check(FILE *const f, const unsigned long len)
+{
+ int ret = -1;
+ struct global_type g;
+ struct interp *i = NULL;
+ const long start = ftell(f);
+ const struct interp_cfg cfg =
+ {
+ .f = f
+ };
+
+ if (start < 0)
+ {
+ fprintf(stderr, "%s: ftell(3): %s\n", __func__, strerror(errno));
+ return -1;
+ }
+ else if (check_global_type(f, &g))
+ {
+ fprintf(stderr, "%s: check_global_type\n", __func__);
+ goto end;
+ }
+ else if (!(i = interp_alloc(&cfg)))
+ {
+ fprintf(stderr, "%s: interp_alloc failed\n", __func__);
+ goto end;
+ }
+ else if (interp_run_limited(i, &interp_initexpr_set))
+ {
+ fprintf(stderr, "%s: interp_run failed\n", __func__);
+ goto end;
+ }
+
+ const long end = ftell(f);
+
+ if (end < 0)
+ {
+ fprintf(stderr, "%s: ftell(3): %s\n", __func__, strerror(errno));
+ return -1;
+ }
+
+ const unsigned long size = end - start;
+
+ if (size != len)
+ {
+ fprintf(stderr, "%s: size exceeded (%lu expected, got %lu)\n",
+ __func__, len, size);
+ return -1;
+ }
+
+ ret = 0;
+
+end:
+ interp_free(i);
+ return ret;
+}
+
+int section_global(struct wasmfs *const w, FILE *const f,
+ const unsigned long len)
+{
+ if (w->sections.global)
+ {
+ fprintf(stderr, "%s: ignoring duplicate section\n", __func__);
+ return 0;
+ }
+
+ const long offset = ftell(f);
+
+ if (offset < 0)
+ {
+ fprintf(stderr, "%s: ftell(3): %s\n", __func__, strerror(errno));
+ return -1;
+ }
+ else if (check(f, len))
+ {
+ fprintf(stderr, "%s: check failed\n", __func__);
+ return -1;
+ }
+
+ w->sections.global = offset;
+ return 0;
+}