182 lines
4.2 KiB
C
182 lines
4.2 KiB
C
/*
|
|
* 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/search.h>
|
|
#include <nw/log.h>
|
|
#include <nw/fstring.h>
|
|
#include <nw/sections.h>
|
|
#include <nanowasm/nw.h>
|
|
#include <nw/types.h>
|
|
#include <errno.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
|
|
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;
|
|
}
|