aboutsummaryrefslogtreecommitdiff
path: root/src/section/import.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/section/import.c')
-rw-r--r--src/section/import.c188
1 files changed, 188 insertions, 0 deletions
diff --git a/src/section/import.c b/src/section/import.c
new file mode 100644
index 0000000..06df4e1
--- /dev/null
+++ b/src/section/import.c
@@ -0,0 +1,188 @@
+#include <sections.h>
+#include <wasm_types.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+static int check_string(FILE *const f)
+{
+ varuint32 len;
+
+ if (varuint32_read(f, &len))
+ {
+ fprintf(stderr, "%s: varuint32_read failed\n", __func__);
+ return -1;
+ }
+
+ for (varuint32 i = 0; i < len; i++)
+ {
+ uint8_t byte;
+
+ if (!fread(&byte, sizeof byte, 1, f))
+ {
+ fprintf(stderr, "%s: fread(3) failed, feof=%d, ferror=%d\n",
+ __func__, feof(f), ferror(f));
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int check_function_kind(FILE *const f)
+{
+ varuint32 type;
+
+ if (varuint32_read(f, &type))
+ {
+ fprintf(stderr, "%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))
+ {
+ fprintf(stderr, "%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(FILE *const f)
+{
+ if (check_string(f))
+ {
+ fprintf(stderr, "%s: check_string module failed\n", __func__);
+ return -1;
+ }
+ else if (check_string(f))
+ {
+ fprintf(stderr, "%s: check_string field failed\n", __func__);
+ return -1;
+ }
+
+ uint8_t kind;
+
+ enum
+ {
+ FUNCTION,
+ TABLE,
+ MEMORY,
+ GLOBAL
+ };
+
+ if (!fread(&kind, sizeof kind, 1, f))
+ {
+ fprintf(stderr, "%s: fread(3) failed, feof=%d, ferror=%d\n",
+ __func__, feof(f), ferror(f));
+ return -1;
+ }
+
+ static int (*const fn[])(FILE *) =
+ {
+ [FUNCTION] = check_function_kind,
+ [TABLE] = check_table_kind,
+ [MEMORY] = check_memory_kind,
+ [GLOBAL] = check_global_kind
+ };
+
+ if (kind >= sizeof fn / sizeof *fn)
+ {
+ fprintf(stderr, "%s: unexpected kind %#" PRIx8 "\n", __func__, kind);
+ return -1;
+ }
+
+ return fn[kind](f);
+}
+
+static int check(FILE *const f, const unsigned long len)
+{
+ const long start = ftell(f);
+
+ if (start < 0)
+ {
+ fprintf(stderr, "%s: ftell(3): %s\n", __func__, strerror(errno));
+ return -1;
+ }
+
+ varuint32 count;
+
+ if (varuint32_read(f, &count))
+ {
+ fprintf(stderr, "%s: varuint32_read failed\n", __func__);
+ return -1;
+ }
+
+ for (varuint32 i = 0; i < count; i++)
+ if (check_import_entry(f))
+ {
+ fprintf(stderr, "%s: check_import_entry failed\n", __func__);
+ return -1;
+ }
+
+ 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;
+ }
+
+ return 0;
+}
+
+int section_import(struct wasmfs *const w, FILE *const f,
+ const unsigned long len)
+{
+ if (w->sections.import)
+ {
+ 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.import = offset;
+ return 0;
+}