/* * 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 #include #include #include #include #include #include #include #include static int ensure_export(const char *const fn, const struct nw_mod *const m, FILE *const f, varuint32 *const out) { if (!m->sections.export) { LOG("%s: export section not found", __func__); return -1; } else if (fseek(f, m->sections.export, SEEK_SET)) { LOG("%s: fseek(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++) { varuint32 len; bool found = false; if (varuint32_read(f, &len)) { LOG("%s: varuint32_read failed\n", __func__); return -1; } else if (len != strlen(fn)) { if (fseek(f, len, SEEK_CUR)) { LOG("%s: fseek(3): %s\n", __func__, strerror(errno)); return -1; } } else if (!fstrcmp(fn, f, false)) found = true; 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; } varuint32 index; if (varuint32_read(f, &index)) { LOG("%s: varuint32_read failed\n", __func__); return -1; } else if (found) { if (kind != NW_KIND_FUNCTION) { LOG("%s: expected kind %d, got %d\n", __func__, NW_KIND_FUNCTION, kind); return -1; } *out = index; return 0; } } return -1; } static int get_function_index(const struct nw_mod *const m, const varuint32 index, varuint32 *const findex) { const size_t n = m->cfg.n_imports; if (index < n) { LOG("%s: index (%lu) must be greater than number of imports (%zu)\n", __func__, (unsigned long)index, n); return -1; } *findex = index - n; return 0; } static int get_fn_start(const struct nw_mod *const m, FILE *const f, const varuint32 index, struct search_fn *const out) { const struct section s = { .cfg = &m->cfg, .f = f }; struct section_function sf; struct section_code c; if (section_function(&s, m, index, &sf)) { LOG("%s: section_function failed\n", __func__); return -1; } else if (section_code(&s, m, index, &c)) { LOG("%s: section_code failed\n", __func__); return -1; } out->start = c.start; out->index = index; return 0; } int search_exported_fn(const char *const fn, const struct nw_mod *const m, FILE *const f, struct search_fn *const out) { varuint32 index, findex; if (ensure_export(fn, m, f, &index)) { LOG("%s: %s not an exported function\n", __func__, fn); return -1; } else if (get_function_index(m, index, &findex)) { LOG("%s: get_function_index failed\n", __func__); return -1; } else if (get_fn_start(m, f, findex, out)) { LOG("%s: get_fn_start %s failed\n", __func__, fn); return -1; } return 0; } int search_fn(const varuint32 index, const struct nw_mod *const m, FILE *const f, struct search_fn *const out) { varuint32 findex; if (get_function_index(m, index, &findex)) { LOG("%s: get_function_index failed\n", __func__); return -1; } else if (get_fn_start(m, f, findex, out)) { LOG("%s: get_fn_start failed\n", __func__); return -1; } return 0; }