First commit
This commit is contained in:
commit
36c1820e58
|
@ -0,0 +1,46 @@
|
|||
# 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/.
|
||||
|
||||
cmake_minimum_required(VERSION 3.19)
|
||||
project(nanowasm C)
|
||||
option(NW_LOG "Enables logging to stderr" ON)
|
||||
add_library(${PROJECT_NAME})
|
||||
target_include_directories(${PROJECT_NAME} PUBLIC include
|
||||
PRIVATE private_include)
|
||||
|
||||
set(cflags_np
|
||||
-ffunction-sections
|
||||
-fdata-sections
|
||||
-pedantic
|
||||
-Wall
|
||||
-std=c99
|
||||
)
|
||||
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
set(cflags_np ${cflags_np} -Og)
|
||||
elseif(CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||
set(cflags_np ${cflags_np} -Os)
|
||||
endif()
|
||||
|
||||
include(CheckCompilerFlag)
|
||||
|
||||
foreach(f ${cflags_np})
|
||||
string(REPLACE "-" "_" var supported_${f})
|
||||
check_compiler_flag(C ${f} ${var})
|
||||
|
||||
if(${var})
|
||||
target_compile_options(${PROJECT_NAME} PRIVATE ${f})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(NW_LOG)
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE ENABLE_LOG)
|
||||
endif()
|
||||
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES C_STANDARD 99 C_EXTENSIONS OFF)
|
||||
add_subdirectory(src)
|
||||
add_subdirectory(test)
|
|
@ -0,0 +1,373 @@
|
|||
Mozilla Public License Version 2.0
|
||||
==================================
|
||||
|
||||
1. Definitions
|
||||
--------------
|
||||
|
||||
1.1. "Contributor"
|
||||
means each individual or legal entity that creates, contributes to
|
||||
the creation of, or owns Covered Software.
|
||||
|
||||
1.2. "Contributor Version"
|
||||
means the combination of the Contributions of others (if any) used
|
||||
by a Contributor and that particular Contributor's Contribution.
|
||||
|
||||
1.3. "Contribution"
|
||||
means Covered Software of a particular Contributor.
|
||||
|
||||
1.4. "Covered Software"
|
||||
means Source Code Form to which the initial Contributor has attached
|
||||
the notice in Exhibit A, the Executable Form of such Source Code
|
||||
Form, and Modifications of such Source Code Form, in each case
|
||||
including portions thereof.
|
||||
|
||||
1.5. "Incompatible With Secondary Licenses"
|
||||
means
|
||||
|
||||
(a) that the initial Contributor has attached the notice described
|
||||
in Exhibit B to the Covered Software; or
|
||||
|
||||
(b) that the Covered Software was made available under the terms of
|
||||
version 1.1 or earlier of the License, but not also under the
|
||||
terms of a Secondary License.
|
||||
|
||||
1.6. "Executable Form"
|
||||
means any form of the work other than Source Code Form.
|
||||
|
||||
1.7. "Larger Work"
|
||||
means a work that combines Covered Software with other material, in
|
||||
a separate file or files, that is not Covered Software.
|
||||
|
||||
1.8. "License"
|
||||
means this document.
|
||||
|
||||
1.9. "Licensable"
|
||||
means having the right to grant, to the maximum extent possible,
|
||||
whether at the time of the initial grant or subsequently, any and
|
||||
all of the rights conveyed by this License.
|
||||
|
||||
1.10. "Modifications"
|
||||
means any of the following:
|
||||
|
||||
(a) any file in Source Code Form that results from an addition to,
|
||||
deletion from, or modification of the contents of Covered
|
||||
Software; or
|
||||
|
||||
(b) any new file in Source Code Form that contains any Covered
|
||||
Software.
|
||||
|
||||
1.11. "Patent Claims" of a Contributor
|
||||
means any patent claim(s), including without limitation, method,
|
||||
process, and apparatus claims, in any patent Licensable by such
|
||||
Contributor that would be infringed, but for the grant of the
|
||||
License, by the making, using, selling, offering for sale, having
|
||||
made, import, or transfer of either its Contributions or its
|
||||
Contributor Version.
|
||||
|
||||
1.12. "Secondary License"
|
||||
means either the GNU General Public License, Version 2.0, the GNU
|
||||
Lesser General Public License, Version 2.1, the GNU Affero General
|
||||
Public License, Version 3.0, or any later versions of those
|
||||
licenses.
|
||||
|
||||
1.13. "Source Code Form"
|
||||
means the form of the work preferred for making modifications.
|
||||
|
||||
1.14. "You" (or "Your")
|
||||
means an individual or a legal entity exercising rights under this
|
||||
License. For legal entities, "You" includes any entity that
|
||||
controls, is controlled by, or is under common control with You. For
|
||||
purposes of this definition, "control" means (a) the power, direct
|
||||
or indirect, to cause the direction or management of such entity,
|
||||
whether by contract or otherwise, or (b) ownership of more than
|
||||
fifty percent (50%) of the outstanding shares or beneficial
|
||||
ownership of such entity.
|
||||
|
||||
2. License Grants and Conditions
|
||||
--------------------------------
|
||||
|
||||
2.1. Grants
|
||||
|
||||
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||
non-exclusive license:
|
||||
|
||||
(a) under intellectual property rights (other than patent or trademark)
|
||||
Licensable by such Contributor to use, reproduce, make available,
|
||||
modify, display, perform, distribute, and otherwise exploit its
|
||||
Contributions, either on an unmodified basis, with Modifications, or
|
||||
as part of a Larger Work; and
|
||||
|
||||
(b) under Patent Claims of such Contributor to make, use, sell, offer
|
||||
for sale, have made, import, and otherwise transfer either its
|
||||
Contributions or its Contributor Version.
|
||||
|
||||
2.2. Effective Date
|
||||
|
||||
The licenses granted in Section 2.1 with respect to any Contribution
|
||||
become effective for each Contribution on the date the Contributor first
|
||||
distributes such Contribution.
|
||||
|
||||
2.3. Limitations on Grant Scope
|
||||
|
||||
The licenses granted in this Section 2 are the only rights granted under
|
||||
this License. No additional rights or licenses will be implied from the
|
||||
distribution or licensing of Covered Software under this License.
|
||||
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
||||
Contributor:
|
||||
|
||||
(a) for any code that a Contributor has removed from Covered Software;
|
||||
or
|
||||
|
||||
(b) for infringements caused by: (i) Your and any other third party's
|
||||
modifications of Covered Software, or (ii) the combination of its
|
||||
Contributions with other software (except as part of its Contributor
|
||||
Version); or
|
||||
|
||||
(c) under Patent Claims infringed by Covered Software in the absence of
|
||||
its Contributions.
|
||||
|
||||
This License does not grant any rights in the trademarks, service marks,
|
||||
or logos of any Contributor (except as may be necessary to comply with
|
||||
the notice requirements in Section 3.4).
|
||||
|
||||
2.4. Subsequent Licenses
|
||||
|
||||
No Contributor makes additional grants as a result of Your choice to
|
||||
distribute the Covered Software under a subsequent version of this
|
||||
License (see Section 10.2) or under the terms of a Secondary License (if
|
||||
permitted under the terms of Section 3.3).
|
||||
|
||||
2.5. Representation
|
||||
|
||||
Each Contributor represents that the Contributor believes its
|
||||
Contributions are its original creation(s) or it has sufficient rights
|
||||
to grant the rights to its Contributions conveyed by this License.
|
||||
|
||||
2.6. Fair Use
|
||||
|
||||
This License is not intended to limit any rights You have under
|
||||
applicable copyright doctrines of fair use, fair dealing, or other
|
||||
equivalents.
|
||||
|
||||
2.7. Conditions
|
||||
|
||||
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
|
||||
in Section 2.1.
|
||||
|
||||
3. Responsibilities
|
||||
-------------------
|
||||
|
||||
3.1. Distribution of Source Form
|
||||
|
||||
All distribution of Covered Software in Source Code Form, including any
|
||||
Modifications that You create or to which You contribute, must be under
|
||||
the terms of this License. You must inform recipients that the Source
|
||||
Code Form of the Covered Software is governed by the terms of this
|
||||
License, and how they can obtain a copy of this License. You may not
|
||||
attempt to alter or restrict the recipients' rights in the Source Code
|
||||
Form.
|
||||
|
||||
3.2. Distribution of Executable Form
|
||||
|
||||
If You distribute Covered Software in Executable Form then:
|
||||
|
||||
(a) such Covered Software must also be made available in Source Code
|
||||
Form, as described in Section 3.1, and You must inform recipients of
|
||||
the Executable Form how they can obtain a copy of such Source Code
|
||||
Form by reasonable means in a timely manner, at a charge no more
|
||||
than the cost of distribution to the recipient; and
|
||||
|
||||
(b) You may distribute such Executable Form under the terms of this
|
||||
License, or sublicense it under different terms, provided that the
|
||||
license for the Executable Form does not attempt to limit or alter
|
||||
the recipients' rights in the Source Code Form under this License.
|
||||
|
||||
3.3. Distribution of a Larger Work
|
||||
|
||||
You may create and distribute a Larger Work under terms of Your choice,
|
||||
provided that You also comply with the requirements of this License for
|
||||
the Covered Software. If the Larger Work is a combination of Covered
|
||||
Software with a work governed by one or more Secondary Licenses, and the
|
||||
Covered Software is not Incompatible With Secondary Licenses, this
|
||||
License permits You to additionally distribute such Covered Software
|
||||
under the terms of such Secondary License(s), so that the recipient of
|
||||
the Larger Work may, at their option, further distribute the Covered
|
||||
Software under the terms of either this License or such Secondary
|
||||
License(s).
|
||||
|
||||
3.4. Notices
|
||||
|
||||
You may not remove or alter the substance of any license notices
|
||||
(including copyright notices, patent notices, disclaimers of warranty,
|
||||
or limitations of liability) contained within the Source Code Form of
|
||||
the Covered Software, except that You may alter any license notices to
|
||||
the extent required to remedy known factual inaccuracies.
|
||||
|
||||
3.5. Application of Additional Terms
|
||||
|
||||
You may choose to offer, and to charge a fee for, warranty, support,
|
||||
indemnity or liability obligations to one or more recipients of Covered
|
||||
Software. However, You may do so only on Your own behalf, and not on
|
||||
behalf of any Contributor. You must make it absolutely clear that any
|
||||
such warranty, support, indemnity, or liability obligation is offered by
|
||||
You alone, and You hereby agree to indemnify every Contributor for any
|
||||
liability incurred by such Contributor as a result of warranty, support,
|
||||
indemnity or liability terms You offer. You may include additional
|
||||
disclaimers of warranty and limitations of liability specific to any
|
||||
jurisdiction.
|
||||
|
||||
4. Inability to Comply Due to Statute or Regulation
|
||||
---------------------------------------------------
|
||||
|
||||
If it is impossible for You to comply with any of the terms of this
|
||||
License with respect to some or all of the Covered Software due to
|
||||
statute, judicial order, or regulation then You must: (a) comply with
|
||||
the terms of this License to the maximum extent possible; and (b)
|
||||
describe the limitations and the code they affect. Such description must
|
||||
be placed in a text file included with all distributions of the Covered
|
||||
Software under this License. Except to the extent prohibited by statute
|
||||
or regulation, such description must be sufficiently detailed for a
|
||||
recipient of ordinary skill to be able to understand it.
|
||||
|
||||
5. Termination
|
||||
--------------
|
||||
|
||||
5.1. The rights granted under this License will terminate automatically
|
||||
if You fail to comply with any of its terms. However, if You become
|
||||
compliant, then the rights granted under this License from a particular
|
||||
Contributor are reinstated (a) provisionally, unless and until such
|
||||
Contributor explicitly and finally terminates Your grants, and (b) on an
|
||||
ongoing basis, if such Contributor fails to notify You of the
|
||||
non-compliance by some reasonable means prior to 60 days after You have
|
||||
come back into compliance. Moreover, Your grants from a particular
|
||||
Contributor are reinstated on an ongoing basis if such Contributor
|
||||
notifies You of the non-compliance by some reasonable means, this is the
|
||||
first time You have received notice of non-compliance with this License
|
||||
from such Contributor, and You become compliant prior to 30 days after
|
||||
Your receipt of the notice.
|
||||
|
||||
5.2. If You initiate litigation against any entity by asserting a patent
|
||||
infringement claim (excluding declaratory judgment actions,
|
||||
counter-claims, and cross-claims) alleging that a Contributor Version
|
||||
directly or indirectly infringes any patent, then the rights granted to
|
||||
You by any and all Contributors for the Covered Software under Section
|
||||
2.1 of this License shall terminate.
|
||||
|
||||
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
|
||||
end user license agreements (excluding distributors and resellers) which
|
||||
have been validly granted by You or Your distributors under this License
|
||||
prior to termination shall survive termination.
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 6. Disclaimer of Warranty *
|
||||
* ------------------------- *
|
||||
* *
|
||||
* Covered Software is provided under this License on an "as is" *
|
||||
* basis, without warranty of any kind, either expressed, implied, or *
|
||||
* statutory, including, without limitation, warranties that the *
|
||||
* Covered Software is free of defects, merchantable, fit for a *
|
||||
* particular purpose or non-infringing. The entire risk as to the *
|
||||
* quality and performance of the Covered Software is with You. *
|
||||
* Should any Covered Software prove defective in any respect, You *
|
||||
* (not any Contributor) assume the cost of any necessary servicing, *
|
||||
* repair, or correction. This disclaimer of warranty constitutes an *
|
||||
* essential part of this License. No use of any Covered Software is *
|
||||
* authorized under this License except under this disclaimer. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
************************************************************************
|
||||
* *
|
||||
* 7. Limitation of Liability *
|
||||
* -------------------------- *
|
||||
* *
|
||||
* Under no circumstances and under no legal theory, whether tort *
|
||||
* (including negligence), contract, or otherwise, shall any *
|
||||
* Contributor, or anyone who distributes Covered Software as *
|
||||
* permitted above, be liable to You for any direct, indirect, *
|
||||
* special, incidental, or consequential damages of any character *
|
||||
* including, without limitation, damages for lost profits, loss of *
|
||||
* goodwill, work stoppage, computer failure or malfunction, or any *
|
||||
* and all other commercial damages or losses, even if such party *
|
||||
* shall have been informed of the possibility of such damages. This *
|
||||
* limitation of liability shall not apply to liability for death or *
|
||||
* personal injury resulting from such party's negligence to the *
|
||||
* extent applicable law prohibits such limitation. Some *
|
||||
* jurisdictions do not allow the exclusion or limitation of *
|
||||
* incidental or consequential damages, so this exclusion and *
|
||||
* limitation may not apply to You. *
|
||||
* *
|
||||
************************************************************************
|
||||
|
||||
8. Litigation
|
||||
-------------
|
||||
|
||||
Any litigation relating to this License may be brought only in the
|
||||
courts of a jurisdiction where the defendant maintains its principal
|
||||
place of business and such litigation shall be governed by laws of that
|
||||
jurisdiction, without reference to its conflict-of-law provisions.
|
||||
Nothing in this Section shall prevent a party's ability to bring
|
||||
cross-claims or counter-claims.
|
||||
|
||||
9. Miscellaneous
|
||||
----------------
|
||||
|
||||
This License represents the complete agreement concerning the subject
|
||||
matter hereof. If any provision of this License is held to be
|
||||
unenforceable, such provision shall be reformed only to the extent
|
||||
necessary to make it enforceable. Any law or regulation which provides
|
||||
that the language of a contract shall be construed against the drafter
|
||||
shall not be used to construe this License against a Contributor.
|
||||
|
||||
10. Versions of the License
|
||||
---------------------------
|
||||
|
||||
10.1. New Versions
|
||||
|
||||
Mozilla Foundation is the license steward. Except as provided in Section
|
||||
10.3, no one other than the license steward has the right to modify or
|
||||
publish new versions of this License. Each version will be given a
|
||||
distinguishing version number.
|
||||
|
||||
10.2. Effect of New Versions
|
||||
|
||||
You may distribute the Covered Software under the terms of the version
|
||||
of the License under which You originally received the Covered Software,
|
||||
or under the terms of any subsequent version published by the license
|
||||
steward.
|
||||
|
||||
10.3. Modified Versions
|
||||
|
||||
If you create software not governed by this License, and you want to
|
||||
create a new license for such software, you may create and use a
|
||||
modified version of this License if you rename the license and remove
|
||||
any references to the name of the license steward (except to note that
|
||||
such modified license differs from this License).
|
||||
|
||||
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
||||
Licenses
|
||||
|
||||
If You choose to distribute Source Code Form that is Incompatible With
|
||||
Secondary Licenses under the terms of this version of the License, the
|
||||
notice described in Exhibit B of this License must be attached.
|
||||
|
||||
Exhibit A - Source Code Form License Notice
|
||||
-------------------------------------------
|
||||
|
||||
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/.
|
||||
|
||||
If it is not possible or desirable to put the notice in a particular
|
||||
file, then You may include the notice in a location (such as a LICENSE
|
||||
file in a relevant directory) where a recipient would be likely to look
|
||||
for such a notice.
|
||||
|
||||
You may add additional accurate notices of copyright ownership.
|
||||
|
||||
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
||||
---------------------------------------------------------
|
||||
|
||||
This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
defined by the Mozilla Public License, v. 2.0.
|
|
@ -0,0 +1,27 @@
|
|||
# `nanowasm`, a tiny WebAssembly/Wasm interpreter
|
||||
|
||||
This project aims to provide the most minimal Wasm interpreter possible in
|
||||
strictly portable ISO C99.
|
||||
|
||||
## Features
|
||||
|
||||
- Portable, ISO C99 implementation
|
||||
- Suitable for resource-constrained devices.
|
||||
- Does not require dynamic memory allocation.
|
||||
|
||||
## What `nanowasm` is not
|
||||
|
||||
As opposed to other interpreters, `nanowasm` prefers lower memory usage
|
||||
rather than run-time performance. Therefore, it should not be unfairly
|
||||
compared _performance_-wise against other interpreters.
|
||||
|
||||
## License
|
||||
|
||||
```
|
||||
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/.
|
||||
```
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
#ifndef NANOWASM_H
|
||||
#define NANOWASM_H
|
||||
|
||||
#include <nanowasm/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
int nw_load(const struct nw_mod_cfg *cfg, struct nw_mod *m);
|
||||
int nw_start(const struct nw_inst_cfg *icfg, struct nw_inst *i);
|
||||
enum nw_state nw_run(struct nw_inst *i);
|
||||
int nw_stop(struct nw_inst *i);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
#ifndef NANOWASM_TYPES_H
|
||||
#define NANOWASM_TYPES_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
union nw_value
|
||||
{
|
||||
long i32;
|
||||
long long i64;
|
||||
float f32;
|
||||
double f64;
|
||||
/* TODO: define {de}serialization between Wasm and host. */
|
||||
void *p;
|
||||
};
|
||||
|
||||
enum nw_kind
|
||||
{
|
||||
NW_KIND_FUNCTION,
|
||||
NW_KIND_TABLE,
|
||||
NW_KIND_MEMORY,
|
||||
NW_KIND_GLOBAL
|
||||
};
|
||||
|
||||
struct nw_args
|
||||
{
|
||||
const union nw_value *args;
|
||||
size_t n;
|
||||
};
|
||||
|
||||
struct nw_buf
|
||||
{
|
||||
void *buf;
|
||||
size_t n;
|
||||
};
|
||||
|
||||
enum nw_state
|
||||
{
|
||||
NW_STATE_AGAIN,
|
||||
NW_STATE_RETURNED,
|
||||
NW_STATE_EXCEPTION,
|
||||
NW_STATE_FATAL
|
||||
};
|
||||
|
||||
struct nw_mod_cfg
|
||||
{
|
||||
const struct nw_import
|
||||
{
|
||||
enum nw_kind kind;
|
||||
const char *module, *field;
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
/* This must follow the format below, whitespace ignored:
|
||||
* [return type]([param type][, ...])
|
||||
* For convenience, the interpreter can do automatic checks on
|
||||
* pointer arguments and/or return values if using '*' as type.
|
||||
* Examples:
|
||||
* "()"
|
||||
* "i32(f32)"
|
||||
* "*(f64, i32, *, i64)"
|
||||
* As per WebAssembly MVP spec, multiple return types are not
|
||||
* supported yet. */
|
||||
const char *signature;
|
||||
int (*fn)(const struct nw_args *params,
|
||||
union nw_value *ret, void *user);
|
||||
} function;
|
||||
} u;
|
||||
} *imports;
|
||||
|
||||
size_t n_imports;
|
||||
const char *path;
|
||||
void *user;
|
||||
};
|
||||
|
||||
struct nw_interp_cfg
|
||||
{
|
||||
struct nw_buf stack, heap;
|
||||
};
|
||||
|
||||
struct nw_inst_cfg
|
||||
{
|
||||
struct nw_interp_cfg interp;
|
||||
const struct nw_mod *m;
|
||||
};
|
||||
|
||||
struct nw_mod
|
||||
{
|
||||
struct
|
||||
{
|
||||
long type, import, function, table, memory, global, export,
|
||||
start, element, code, data;
|
||||
} sections;
|
||||
|
||||
struct nw_mod_cfg cfg;
|
||||
};
|
||||
|
||||
struct nw_inst
|
||||
{
|
||||
struct nw_interp
|
||||
{
|
||||
FILE *f;
|
||||
const char *exception;
|
||||
bool exit;
|
||||
struct nw_interp_cfg cfg;
|
||||
size_t stack_i, heap_i;
|
||||
} interp;
|
||||
|
||||
union nw_inst_state
|
||||
{
|
||||
int retval;
|
||||
const char *exception;
|
||||
} state;
|
||||
|
||||
const struct nw_mod *m;
|
||||
};
|
||||
|
||||
#define NW_BUF(sz) {.buf = (char[sz]){0}, .n = sz}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
#ifndef FSTRING_H
|
||||
#define FSTRING_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int fstrcmp(const char *str, FILE *f, bool abort);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
#ifndef INTERP_H
|
||||
#define INTERP_H
|
||||
|
||||
#include <nanowasm/nw.h>
|
||||
#include <opcodes.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
struct interp_set
|
||||
{
|
||||
const enum opcode *opcodes;
|
||||
size_t n;
|
||||
};
|
||||
|
||||
extern const struct interp_set interp_initexpr_set;
|
||||
|
||||
int interp_start(const struct nw_interp_cfg *cfg, struct nw_interp *i);
|
||||
int interp_run(struct nw_interp *i);
|
||||
int interp_run_limited(struct nw_interp *i, const struct interp_set *ops);
|
||||
int interp_check_opcode(uint8_t op, FILE *f);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
#ifndef LEB128_H
|
||||
#define LEB128_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int leb128_read_unsigned(FILE *f, unsigned maxbits, unsigned long long *out);
|
||||
int leb128_read_signed(FILE *f, unsigned maxbits, long long *out);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
#ifndef LOG_H
|
||||
#define LOG_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef ENABLE_LOG
|
||||
#define LOG(...) fprintf(stderr, __VA_ARGS__)
|
||||
#else
|
||||
#define LOG(...)
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
#ifndef OPCODES_H
|
||||
#define OPCODES_H
|
||||
|
||||
enum opcode
|
||||
{
|
||||
OP_UNREACHABLE,
|
||||
OP_NOP,
|
||||
OP_BLOCK,
|
||||
OP_LOOP,
|
||||
OP_IF,
|
||||
OP_ELSE,
|
||||
OP_END = 0xb,
|
||||
OP_BR,
|
||||
OP_BR_IF,
|
||||
OP_BR_TABLE,
|
||||
OP_RETURN = 0xf,
|
||||
OP_CALL,
|
||||
OP_CALL_INDIRECT,
|
||||
OP_DROP = 0x1a,
|
||||
OP_SELECT,
|
||||
OP_GET_LOCAL = 0x20,
|
||||
OP_SET_LOCAL,
|
||||
OP_TEE_LOCAL,
|
||||
OP_GET_GLOBAL,
|
||||
OP_SET_GLOBAL,
|
||||
OP_I32_LOAD = 0x28,
|
||||
OP_I64_LOAD,
|
||||
OP_F32_LOAD,
|
||||
OP_F64_LOAD,
|
||||
OP_I32_LOAD8_S,
|
||||
OP_I32_LOAD8_U,
|
||||
OP_I32_LOAD16_S,
|
||||
OP_I32_LOAD16_U,
|
||||
OP_I64_LOAD8_S,
|
||||
OP_I64_LOAD8_U,
|
||||
OP_I64_LOAD16_S,
|
||||
OP_I64_LOAD16_U,
|
||||
OP_I64_LOAD32_S,
|
||||
OP_I64_LOAD32_U,
|
||||
OP_I32_STORE,
|
||||
OP_I64_STORE,
|
||||
OP_F32_STORE,
|
||||
OP_F64_STORE,
|
||||
OP_I32_STORE8,
|
||||
OP_I32_STORE16,
|
||||
OP_I64_STORE8,
|
||||
OP_I64_STORE16,
|
||||
OP_I64_STORE32,
|
||||
OP_CURRENT_MEMORY,
|
||||
OP_GROW_MEMORY,
|
||||
OP_I32_CONST,
|
||||
OP_I64_CONST,
|
||||
OP_F32_CONST,
|
||||
OP_F64_CONST,
|
||||
OP_I32_SUB = 0x6b
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
#ifndef OPS_H
|
||||
#define OPS_H
|
||||
|
||||
#include <nanowasm/nw.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int op_unreachable(struct nw_interp *i);
|
||||
int op_nop(struct nw_interp *i);
|
||||
int op_block(struct nw_interp *i);
|
||||
int op_loop(struct nw_interp *i);
|
||||
int op_if(struct nw_interp *i);
|
||||
int op_else(struct nw_interp *i);
|
||||
int op_end(struct nw_interp *i);
|
||||
int op_br(struct nw_interp *i);
|
||||
int op_br_if(struct nw_interp *i);
|
||||
int op_br_table(struct nw_interp *i);
|
||||
int op_return(struct nw_interp *i);
|
||||
int op_call(struct nw_interp *i);
|
||||
int op_call_indirect(struct nw_interp *i);
|
||||
int op_get_local(struct nw_interp *i);
|
||||
int op_set_local(struct nw_interp *i);
|
||||
int op_tee_local(struct nw_interp *i);
|
||||
int op_get_global(struct nw_interp *i);
|
||||
int op_set_global(struct nw_interp *i);
|
||||
int op_i32_load(struct nw_interp *i);
|
||||
int op_i32_store(struct nw_interp *i);
|
||||
int op_current_memory(struct nw_interp *i);
|
||||
int op_i32_const(struct nw_interp *i);
|
||||
int op_i64_const(struct nw_interp *i);
|
||||
int op_f32_const(struct nw_interp *i);
|
||||
int op_f64_const(struct nw_interp *i);
|
||||
int op_i32_sub(struct nw_interp *i);
|
||||
|
||||
int check_unreachable(FILE *f);
|
||||
int check_nop(FILE *f);
|
||||
int check_block(FILE *f);
|
||||
int check_loop(FILE *f);
|
||||
int check_if(FILE *f);
|
||||
int check_else(FILE *f);
|
||||
int check_end(FILE *f);
|
||||
int check_br(FILE *f);
|
||||
int check_br_if(FILE *f);
|
||||
int check_br_table(FILE *f);
|
||||
int check_return(FILE *f);
|
||||
int check_call(FILE *f);
|
||||
int check_call_indirect(FILE *f);
|
||||
int check_get_local(FILE *f);
|
||||
int check_set_local(FILE *f);
|
||||
int check_tee_local(FILE *f);
|
||||
int check_get_global(FILE *f);
|
||||
int check_set_global(FILE *f);
|
||||
int check_i32_load(FILE *f);
|
||||
int check_i32_store(FILE *f);
|
||||
int check_i32_const(FILE *f);
|
||||
int check_i64_const(FILE *f);
|
||||
int check_f32_const(FILE *f);
|
||||
int check_f64_const(FILE *f);
|
||||
int check_i32_sub(FILE *f);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
#ifndef SEARCH_H
|
||||
#define SEARCH_H
|
||||
|
||||
#include <nanowasm/nw.h>
|
||||
#include <stdio.h>
|
||||
|
||||
struct search_fn
|
||||
{
|
||||
long start;
|
||||
};
|
||||
|
||||
int search_exported_fn(const char *fn, const struct nw_mod *m, FILE *f,
|
||||
struct search_fn *out);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
#ifndef SECTIONS_H
|
||||
#define SECTIONS_H
|
||||
|
||||
#include <nanowasm/nw.h>
|
||||
#include <wasm_types.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
struct section
|
||||
{
|
||||
const struct nw_mod_cfg *cfg;
|
||||
FILE *f;
|
||||
};
|
||||
|
||||
int section_custom_check(const struct section *s, struct nw_mod *m, unsigned long len);
|
||||
int section_type_check(const struct section *s, struct nw_mod *m, unsigned long len);
|
||||
int section_import_check(const struct section *s, struct nw_mod *m, unsigned long len);
|
||||
int section_function_check(const struct section *s, struct nw_mod *m, unsigned long len);
|
||||
int section_table_check(const struct section *s, struct nw_mod *m, unsigned long len);
|
||||
int section_memory_check(const struct section *s, struct nw_mod *m, unsigned long len);
|
||||
int section_global_check(const struct section *s, struct nw_mod *m, unsigned long len);
|
||||
int section_export_check(const struct section *s, struct nw_mod *m, unsigned long len);
|
||||
int section_start_check(const struct section *s, struct nw_mod *m, unsigned long len);
|
||||
int section_element_check(const struct section *s, struct nw_mod *m, unsigned long len);
|
||||
int section_code_check(const struct section *s, struct nw_mod *m, unsigned long len);
|
||||
int section_data_check(const struct section *s, struct nw_mod *m, unsigned long len);
|
||||
|
||||
struct section_function
|
||||
{
|
||||
varuint32 type;
|
||||
};
|
||||
|
||||
struct section_type
|
||||
{
|
||||
int dummy;
|
||||
};
|
||||
|
||||
int section_function(const struct section *s, const struct nw_mod *const m,
|
||||
varuint32 idx, struct section_function *f);
|
||||
int section_type(const struct section *s, struct section_type *t);
|
||||
|
||||
int check_resizable_limits(FILE *f);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
#ifndef WASM_TYPES_H
|
||||
#define WASM_TYPES_H
|
||||
|
||||
#include <nanowasm/nw.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
typedef bool varuint1;
|
||||
typedef signed char varint7;
|
||||
typedef unsigned char varuint7;
|
||||
typedef unsigned long varuint32;
|
||||
typedef long varint32;
|
||||
typedef unsigned long long varuint64;
|
||||
typedef long long varint64;
|
||||
|
||||
int varuint1_read(FILE *f, varuint1 *out);
|
||||
int varint7_read(FILE *f, varint7 *out);
|
||||
int varuint7_read(FILE *f, varuint7 *out);
|
||||
int varuint32_read(FILE *f, varuint32 *out);
|
||||
int varint32_read(FILE *f, varint32 *out);
|
||||
int varuint64_read(FILE *f, varuint64 *out);
|
||||
int varint64_read(FILE *f, varint64 *out);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,20 @@
|
|||
# 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/.
|
||||
|
||||
target_sources(${PROJECT_NAME} PRIVATE
|
||||
fstrcmp.c
|
||||
interp.c
|
||||
leb128.c
|
||||
load.c
|
||||
run.c
|
||||
search.c
|
||||
start.c
|
||||
stop.c
|
||||
types.c
|
||||
)
|
||||
add_subdirectory(op)
|
||||
add_subdirectory(section)
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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 <fstring.h>
|
||||
#include <log.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int fstrcmp(const char *str, FILE *const f, const bool abort)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
for (size_t i = 0; i < strlen(str); 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;
|
||||
}
|
||||
else if (byte != str[i])
|
||||
{
|
||||
if (abort)
|
||||
return -1;
|
||||
else
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,180 @@
|
|||
/*
|
||||
* 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 <nanowasm/nw.h>
|
||||
#include <log.h>
|
||||
#include <interp.h>
|
||||
#include <opcodes.h>
|
||||
#include <ops.h>
|
||||
#include <wasm_types.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static const enum opcode initexpr_opcodes[] =
|
||||
{
|
||||
OP_NOP,
|
||||
OP_END,
|
||||
OP_I32_CONST,
|
||||
OP_I64_CONST,
|
||||
OP_F32_CONST,
|
||||
OP_F64_CONST
|
||||
};
|
||||
|
||||
const struct interp_set interp_initexpr_set =
|
||||
{
|
||||
.opcodes = initexpr_opcodes,
|
||||
.n = sizeof initexpr_opcodes / sizeof *initexpr_opcodes
|
||||
};
|
||||
|
||||
static int (*const ops[])(struct nw_interp *) =
|
||||
{
|
||||
[OP_UNREACHABLE] = op_unreachable,
|
||||
[OP_NOP] = op_nop,
|
||||
[OP_BLOCK] = op_block,
|
||||
[OP_LOOP] = op_loop,
|
||||
[OP_IF] = op_if,
|
||||
[OP_ELSE] = op_else,
|
||||
[OP_END] = op_end,
|
||||
[OP_BR] = op_br,
|
||||
[OP_BR_IF] = op_br_if,
|
||||
[OP_BR_TABLE] = op_br_table,
|
||||
[OP_RETURN] = op_return,
|
||||
[OP_CALL] = op_call,
|
||||
[OP_CALL_INDIRECT] = op_call_indirect,
|
||||
[OP_GET_LOCAL] = op_get_local,
|
||||
[OP_SET_LOCAL] = op_set_local,
|
||||
[OP_TEE_LOCAL] = op_tee_local,
|
||||
[OP_GET_GLOBAL] = op_get_global,
|
||||
[OP_SET_GLOBAL] = op_set_global,
|
||||
[OP_I32_LOAD] = op_i32_load,
|
||||
[OP_I32_STORE] = op_i32_store,
|
||||
[OP_I32_CONST] = op_i32_const,
|
||||
[OP_I64_CONST] = op_i64_const,
|
||||
[OP_F32_CONST] = op_f32_const,
|
||||
[OP_F64_CONST] = op_f64_const,
|
||||
[OP_I32_SUB] = op_i32_sub
|
||||
};
|
||||
|
||||
int interp_run(struct nw_interp *const i)
|
||||
{
|
||||
uint8_t op;
|
||||
|
||||
if (!fread(&op, sizeof op, 1, i->f))
|
||||
{
|
||||
LOG("%s: fread(3) failed, feof=%d, ferror=%d\n", __func__, feof(i->f),
|
||||
ferror(i->f));
|
||||
return 1;
|
||||
}
|
||||
else if (op >= sizeof ops / sizeof *ops)
|
||||
{
|
||||
LOG("%s: invalid opcode %#" PRIx8 "\n", __func__, op);
|
||||
return 1;
|
||||
}
|
||||
else if (!ops[op])
|
||||
{
|
||||
LOG("%s: unsupported opcode %#" PRIx8 "\n", __func__, op);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return ops[op](i);
|
||||
}
|
||||
|
||||
static int run_opcode_limited(struct nw_interp *const in,
|
||||
const struct interp_set *const set)
|
||||
{
|
||||
uint8_t op;
|
||||
|
||||
if (!fread(&op, sizeof op, 1, in->f))
|
||||
{
|
||||
LOG("%s: fread(3) failed, feof=%d, ferror=%d\n",
|
||||
__func__, feof(in->f), ferror(in->f));
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < set->n; i++)
|
||||
if (op == set->opcodes[i])
|
||||
return ops[op](in);
|
||||
|
||||
LOG("%s: unexpected opcode %#" PRIx8 "\n", __func__, op);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int interp_run_limited(struct nw_interp *const i,
|
||||
const struct interp_set *const set)
|
||||
{
|
||||
while (!i->exit)
|
||||
if (run_opcode_limited(i, set))
|
||||
{
|
||||
LOG("%s: run_opcode_limited failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int interp_check_opcode(const uint8_t op, FILE *const f)
|
||||
{
|
||||
static int (*const checks[])(FILE *) =
|
||||
{
|
||||
[OP_UNREACHABLE] = check_unreachable,
|
||||
[OP_NOP] = check_nop,
|
||||
[OP_BLOCK] = check_block,
|
||||
[OP_LOOP] = check_loop,
|
||||
[OP_IF] = check_if,
|
||||
[OP_ELSE] = check_else,
|
||||
[OP_END] = check_end,
|
||||
[OP_BR] = check_br,
|
||||
[OP_BR_IF] = check_br_if,
|
||||
[OP_BR_TABLE] = check_br_table,
|
||||
[OP_RETURN] = check_return,
|
||||
[OP_CALL] = check_call,
|
||||
[OP_CALL_INDIRECT] = check_call_indirect,
|
||||
[OP_GET_LOCAL] = check_get_local,
|
||||
[OP_SET_LOCAL] = check_set_local,
|
||||
[OP_TEE_LOCAL] = check_tee_local,
|
||||
[OP_GET_GLOBAL] = check_get_global,
|
||||
[OP_SET_GLOBAL] = check_set_global,
|
||||
[OP_I32_LOAD] = check_i32_load,
|
||||
[OP_I32_STORE] = check_i32_store,
|
||||
[OP_I32_CONST] = check_i32_const,
|
||||
[OP_I64_CONST] = check_i64_const,
|
||||
[OP_F32_CONST] = check_f32_const,
|
||||
[OP_F64_CONST] = check_f64_const,
|
||||
[OP_I32_SUB] = check_i32_sub
|
||||
};
|
||||
|
||||
if (op >= sizeof checks / sizeof *checks)
|
||||
{
|
||||
LOG("%s: invalid opcode %#" PRIx8 "\n", __func__, op);
|
||||
return 1;
|
||||
}
|
||||
else if (!checks[op])
|
||||
{
|
||||
LOG("%s: unsupported opcode %#" PRIx8 "\n", __func__, op);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return checks[op](f);
|
||||
}
|
||||
|
||||
int interp_start(const struct nw_interp_cfg *const cfg,
|
||||
struct nw_interp *const i)
|
||||
{
|
||||
*i = (const struct nw_interp)
|
||||
{
|
||||
.cfg = *cfg
|
||||
};
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* 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 <leb128.h>
|
||||
#include <log.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* The functions below are (somewhat heavily) modified versions of those
|
||||
* provided by the wac project: https://github.com/kanaka/wac */
|
||||
|
||||
/*
|
||||
* Copyright (C) Joel Martin <github@martintribe.org>
|
||||
* The wac project is licensed under the MPL 2.0 (Mozilla Public License
|
||||
* 2.0). The text of the MPL 2.0 license is included below and can be
|
||||
* found at https://www.mozilla.org/MPL/2.0/
|
||||
*/
|
||||
|
||||
static int read_LEB(FILE *const f, const unsigned maxbits,
|
||||
const bool sign, unsigned long long *const out)
|
||||
{
|
||||
unsigned long long result = 0;
|
||||
unsigned shift = 0, bcnt = 0;
|
||||
uint8_t byte;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (!fread(&byte, sizeof byte, 1, f))
|
||||
return -1;
|
||||
|
||||
result |= (unsigned long long)(byte & 0x7f) << shift;
|
||||
shift += 7;
|
||||
|
||||
if (!(byte & 0x80))
|
||||
break;
|
||||
else if (++bcnt > (maxbits + 7 - 1) / 7)
|
||||
{
|
||||
LOG("%s: overflow\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (sign && (shift < maxbits) && (byte & 0x40))
|
||||
result |= -1ll << shift;
|
||||
|
||||
*out = result;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int leb128_read_unsigned(FILE *const f, const unsigned maxbits,
|
||||
unsigned long long *const out)
|
||||
{
|
||||
return read_LEB(f, maxbits, false, out);
|
||||
}
|
||||
|
||||
int leb128_read_signed(FILE *const f, const unsigned maxbits,
|
||||
long long *const out)
|
||||
{
|
||||
unsigned long long value;
|
||||
const int ret = read_LEB(f, maxbits, true, &value);
|
||||
|
||||
*out = value;
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,178 @@
|
|||
/*
|
||||
* 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 <log.h>
|
||||
#include <nanowasm/nw.h>
|
||||
#include <sections.h>
|
||||
#include <wasm_types.h>
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static int check_magic(FILE *const f)
|
||||
{
|
||||
static const uint8_t m[] = {'\0', 'a', 's', 'm'};
|
||||
uint8_t magic[sizeof m];
|
||||
|
||||
if (!fread(magic, sizeof magic, 1, f))
|
||||
{
|
||||
LOG("%s: fread(3) failed, feof=%d, ferror=%d\n",
|
||||
__func__, feof(f), ferror(f));
|
||||
return -1;
|
||||
}
|
||||
else if (memcmp(magic, m, sizeof magic))
|
||||
{
|
||||
LOG("%s: wrong magic bytes\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_version(FILE *const f)
|
||||
{
|
||||
static const uint8_t v[] = {1, 0, 0, 0};
|
||||
uint8_t version[sizeof v];
|
||||
|
||||
if (!fread(version, sizeof version, 1, f))
|
||||
{
|
||||
LOG("%s: fread(3) failed, feof=%d, ferror=%d\n", __func__, feof(f),
|
||||
ferror(f));
|
||||
return -1;
|
||||
}
|
||||
else if (memcmp(version, v, sizeof version))
|
||||
{
|
||||
LOG("%s: wrong version\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int load_section(const struct nw_mod_cfg *const cfg,
|
||||
struct nw_mod *const m, FILE *const f)
|
||||
{
|
||||
static int (*const fn[])(const struct section *, struct nw_mod *,
|
||||
unsigned long) =
|
||||
{
|
||||
section_custom_check,
|
||||
section_type_check,
|
||||
section_import_check,
|
||||
section_function_check,
|
||||
section_table_check,
|
||||
section_memory_check,
|
||||
section_global_check,
|
||||
section_export_check,
|
||||
section_start_check,
|
||||
section_element_check,
|
||||
section_code_check,
|
||||
section_data_check
|
||||
};
|
||||
|
||||
const struct section s =
|
||||
{
|
||||
.cfg = cfg,
|
||||
.f = f
|
||||
};
|
||||
|
||||
varuint7 section;
|
||||
varuint32 len;
|
||||
int ret;
|
||||
|
||||
if (varuint7_read(f, §ion))
|
||||
{
|
||||
if (feof(f))
|
||||
return 0;
|
||||
|
||||
LOG("%s: varuint7_read failed\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
else if (section >= sizeof fn / sizeof *fn)
|
||||
{
|
||||
LOG("%s: invalid section %u\n", __func__, (unsigned)section);
|
||||
return 1;
|
||||
}
|
||||
else if (varuint32_read(f, &len))
|
||||
{
|
||||
LOG("%s: varuint32_read failed\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
else if ((ret = fn[section](&s, m, len)))
|
||||
LOG("%s: failed to load section %u\n", __func__, (unsigned)section);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int load_sections(const struct nw_mod_cfg *const cfg,
|
||||
struct nw_mod *const m, FILE *const f)
|
||||
{
|
||||
while (!feof(f))
|
||||
if (load_section(cfg, m, f))
|
||||
{
|
||||
LOG("%s: load_section failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int load(const struct nw_mod_cfg *const cfg, struct nw_mod *const m,
|
||||
FILE *const f)
|
||||
{
|
||||
if (check_magic(f))
|
||||
{
|
||||
LOG("%s: load_magic failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
else if (check_version(f))
|
||||
{
|
||||
LOG("%s: check_version failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
else if (load_sections(cfg, m, f))
|
||||
{
|
||||
LOG("%s: load_sections failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nw_load(const struct nw_mod_cfg *const cfg, struct nw_mod *const m)
|
||||
{
|
||||
int ret = -1;
|
||||
FILE *const f = fopen(cfg->path, "rb");
|
||||
|
||||
*m = (const struct nw_mod){.cfg = *cfg};
|
||||
|
||||
if (!f)
|
||||
{
|
||||
LOG("%s: fopen(3) %s: %s\n", __func__, cfg->path, strerror(errno));
|
||||
goto end;
|
||||
}
|
||||
else if (load(cfg, m, f))
|
||||
{
|
||||
LOG("%s: load failed\n", __func__);
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
end:
|
||||
if (f && fclose(f))
|
||||
{
|
||||
LOG("%s: fclose(3) %s: %s\n", __func__, cfg->path, strerror(errno));
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
# 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/.
|
||||
|
||||
add_subdirectory(call)
|
||||
add_subdirectory(constants)
|
||||
add_subdirectory(control_flow)
|
||||
add_subdirectory(memory)
|
||||
add_subdirectory(numeric)
|
||||
add_subdirectory(variable_access)
|
|
@ -0,0 +1,11 @@
|
|||
# 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/.
|
||||
|
||||
target_sources(${PROJECT_NAME} PRIVATE
|
||||
call.c
|
||||
call_indirect.c
|
||||
)
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* 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 <log.h>
|
||||
#include <ops.h>
|
||||
#include <nanowasm/nw.h>
|
||||
#include <wasm_types.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static int op(struct nw_interp *const i, FILE *const f)
|
||||
{
|
||||
varuint32 function_index;
|
||||
|
||||
if (varuint32_read(f, &function_index))
|
||||
{
|
||||
LOG("%s: varuint32_read failed\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int op_call(struct nw_interp *const i)
|
||||
{
|
||||
return op(i, i->f);
|
||||
}
|
||||
|
||||
int check_call(FILE *const f)
|
||||
{
|
||||
return op(NULL, f);
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* 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 <log.h>
|
||||
#include <ops.h>
|
||||
#include <nanowasm/nw.h>
|
||||
#include <wasm_types.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static int op(struct nw_interp *const i, FILE *const f)
|
||||
{
|
||||
varuint32 type_index;
|
||||
varuint1 reserved;
|
||||
|
||||
if (varuint32_read(f, &type_index))
|
||||
{
|
||||
LOG("%s: varuint32_read failed\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
else if (varuint1_read(f, &reserved))
|
||||
{
|
||||
LOG("%s: varuint1_read failed\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
else if (reserved)
|
||||
{
|
||||
LOG("%s: unexpected non-zero reserved value %u\n",
|
||||
__func__, (unsigned)reserved);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int op_call_indirect(struct nw_interp *const i)
|
||||
{
|
||||
return op(i, i->f);
|
||||
}
|
||||
|
||||
int check_call_indirect(FILE *const f)
|
||||
{
|
||||
return op(NULL, f);
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
# 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/.
|
||||
|
||||
target_sources(${PROJECT_NAME} PRIVATE
|
||||
f32_const.c
|
||||
f64_const.c
|
||||
i32_const.c
|
||||
i64_const.c
|
||||
)
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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 <log.h>
|
||||
#include <ops.h>
|
||||
#include <nanowasm/nw.h>
|
||||
#include <wasm_types.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static int op(struct nw_interp *const i, FILE *const f)
|
||||
{
|
||||
varuint32 value;
|
||||
|
||||
if (varuint32_read(f, &value))
|
||||
{
|
||||
LOG("%s: varuint32_read failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int op_f32_const(struct nw_interp *const i)
|
||||
{
|
||||
return op(i, i->f);
|
||||
}
|
||||
|
||||
int check_f32_const(FILE *const f)
|
||||
{
|
||||
return op(NULL, f);
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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 <log.h>
|
||||
#include <ops.h>
|
||||
#include <nanowasm/nw.h>
|
||||
#include <wasm_types.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static int op(struct nw_interp *const i, FILE *const f)
|
||||
{
|
||||
varuint64 value;
|
||||
|
||||
if (varuint64_read(f, &value))
|
||||
{
|
||||
LOG("%s: varuint64_read failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int op_f64_const(struct nw_interp *const i)
|
||||
{
|
||||
return op(i, i->f);
|
||||
}
|
||||
|
||||
int check_f64_const(FILE *const f)
|
||||
{
|
||||
return op(NULL, f);
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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 <log.h>
|
||||
#include <ops.h>
|
||||
#include <nanowasm/nw.h>
|
||||
#include <wasm_types.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static int op(struct nw_interp *const i, FILE *const f)
|
||||
{
|
||||
varint32 value;
|
||||
|
||||
if (varint32_read(f, &value))
|
||||
{
|
||||
LOG("%s: varint32_read failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int op_i32_const(struct nw_interp *const i)
|
||||
{
|
||||
return op(i, i->f);
|
||||
}
|
||||
|
||||
int check_i32_const(FILE *const f)
|
||||
{
|
||||
return op(NULL, f);
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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 <log.h>
|
||||
#include <ops.h>
|
||||
#include <nanowasm/nw.h>
|
||||
#include <wasm_types.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static int op(struct nw_interp *const i, FILE *const f)
|
||||
{
|
||||
varint64 value;
|
||||
|
||||
if (varint64_read(f, &value))
|
||||
{
|
||||
LOG("%s: varint32_read failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int op_i64_const(struct nw_interp *const i)
|
||||
{
|
||||
return op(i, i->f);
|
||||
}
|
||||
|
||||
int check_i64_const(FILE *const f)
|
||||
{
|
||||
return op(NULL, f);
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
# 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/.
|
||||
|
||||
target_sources(${PROJECT_NAME} PRIVATE
|
||||
block.c
|
||||
br.c
|
||||
br_if.c
|
||||
br_table.c
|
||||
else.c
|
||||
end.c
|
||||
if.c
|
||||
loop.c
|
||||
nop.c
|
||||
return.c
|
||||
unreachable.c
|
||||
)
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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 <log.h>
|
||||
#include <ops.h>
|
||||
#include <nanowasm/nw.h>
|
||||
#include <wasm_types.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static int op(struct nw_interp *const i, FILE *const f)
|
||||
{
|
||||
varint7 sig;
|
||||
|
||||
if (varint7_read(f, &sig))
|
||||
{
|
||||
LOG("%s: varint7_read failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int op_block(struct nw_interp *const i)
|
||||
{
|
||||
return op(i, i->f);
|
||||
}
|
||||
|
||||
int check_block(FILE *const f)
|
||||
{
|
||||
return op(NULL, f);
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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 <log.h>
|
||||
#include <ops.h>
|
||||
#include <nanowasm/nw.h>
|
||||
#include <wasm_types.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static int op(struct nw_interp *const i, FILE *const f)
|
||||
{
|
||||
varuint32 relative_depth;
|
||||
|
||||
if (varuint32_read(f, &relative_depth))
|
||||
{
|
||||
LOG("%s: varuint32_read failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int op_br(struct nw_interp *const i)
|
||||
{
|
||||
return op(i, i->f);
|
||||
}
|
||||
|
||||
int check_br(FILE *const f)
|
||||
{
|
||||
return op(NULL, f);
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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 <log.h>
|
||||
#include <ops.h>
|
||||
#include <nanowasm/nw.h>
|
||||
#include <wasm_types.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static int op(struct nw_interp *const i, FILE *const f)
|
||||
{
|
||||
varuint32 relative_depth;
|
||||
|
||||
if (varuint32_read(f, &relative_depth))
|
||||
{
|
||||
LOG("%s: varuint32_read failed\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int op_br_if(struct nw_interp *const i)
|
||||
{
|
||||
return op(i, i->f);
|
||||
}
|
||||
|
||||
int check_br_if(FILE *const f)
|
||||
{
|
||||
return op(NULL, f);
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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 <log.h>
|
||||
#include <ops.h>
|
||||
#include <nanowasm/nw.h>
|
||||
#include <wasm_types.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static int op(struct nw_interp *const i, FILE *const f)
|
||||
{
|
||||
varuint32 target_count, default_target;
|
||||
|
||||
if (varuint32_read(f, &target_count))
|
||||
{
|
||||
LOG("%s: varuint32_read target_count failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (varuint32 i = 0; i < target_count; i++)
|
||||
{
|
||||
varuint32 target_table;
|
||||
|
||||
if (varuint32_read(f, &target_table))
|
||||
{
|
||||
LOG("%s: varuint32_read target_table failed\n",
|
||||
__func__);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (varuint32_read(f, &default_target))
|
||||
{
|
||||
LOG("%s: varuint32_read default_target failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int op_br_table(struct nw_interp *const i)
|
||||
{
|
||||
return op(i, i->f);
|
||||
}
|
||||
|
||||
int check_br_table(FILE *const f)
|
||||
{
|
||||
return op(NULL, f);
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* 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 <ops.h>
|
||||
#include <nanowasm/nw.h>
|
||||
|
||||
int op_else(struct nw_interp *const i)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int check_else(FILE *const f)
|
||||
{
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* 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 <ops.h>
|
||||
#include <nanowasm/nw.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
int op_end(struct nw_interp *const i)
|
||||
{
|
||||
i->exit = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int check_end(FILE *const f)
|
||||
{
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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 <log.h>
|
||||
#include <ops.h>
|
||||
#include <nanowasm/nw.h>
|
||||
#include <wasm_types.h>
|
||||
|
||||
static int op(struct nw_interp *const i, FILE *const f)
|
||||
{
|
||||
varint7 sig;
|
||||
|
||||
if (varint7_read(f, &sig))
|
||||
{
|
||||
LOG("%s: varint7_read failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int op_if(struct nw_interp *const i)
|
||||
{
|
||||
return op(i, i->f);
|
||||
}
|
||||
|
||||
int check_if(FILE *const f)
|
||||
{
|
||||
return op(NULL, f);
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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 <log.h>
|
||||
#include <ops.h>
|
||||
#include <nanowasm/nw.h>
|
||||
#include <wasm_types.h>
|
||||
|
||||
static int op(struct nw_interp *const i, FILE *const f)
|
||||
{
|
||||
varint7 sig;
|
||||
|
||||
if (varint7_read(f, &sig))
|
||||
{
|
||||
LOG("%s: varint7_read failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int op_loop(struct nw_interp *const i)
|
||||
{
|
||||
return op(i, i->f);
|
||||
}
|
||||
|
||||
int check_loop(FILE *const f)
|
||||
{
|
||||
return op(NULL, f);
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* 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 <ops.h>
|
||||
#include <nanowasm/nw.h>
|
||||
#include <interp.h>
|
||||
|
||||
int op_nop(struct nw_interp *const i)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int check_nop(FILE *const f)
|
||||
{
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* 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 <ops.h>
|
||||
#include <nanowasm/nw.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int op_return(struct nw_interp *const i)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int check_return(FILE *const f)
|
||||
{
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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 <ops.h>
|
||||
#include <nanowasm/nw.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int op_unreachable(struct nw_interp *const i)
|
||||
{
|
||||
i->exception = "Unreachable instruction";
|
||||
i->exit = true;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int check_unreachable(FILE *const f)
|
||||
{
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
# 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/.
|
||||
|
||||
target_sources(${PROJECT_NAME} PRIVATE
|
||||
current_memory.c
|
||||
i32_load.c
|
||||
i32_store.c
|
||||
)
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* 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 <log.h>
|
||||
#include <ops.h>
|
||||
#include <nanowasm/nw.h>
|
||||
#include <wasm_types.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static int op(struct nw_interp *const i, FILE *const f)
|
||||
{
|
||||
varuint1 reserved;
|
||||
|
||||
if (varuint1_read(f, &reserved))
|
||||
{
|
||||
LOG("%s: varuint1_read failed\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
else if (reserved)
|
||||
{
|
||||
LOG("%s: unexpected non-zero reserved value %u\n",
|
||||
__func__, (unsigned)reserved);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int op_current_memory(struct nw_interp *const i)
|
||||
{
|
||||
return op(i, i->f);
|
||||
}
|
||||
|
||||
int check_current_memory(FILE *const f)
|
||||
{
|
||||
return op(NULL, f);
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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 <log.h>
|
||||
#include <ops.h>
|
||||
#include <nanowasm/nw.h>
|
||||
#include <wasm_types.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static int op(struct nw_interp *const i, FILE *const f)
|
||||
{
|
||||
varint32 flags, offset;
|
||||
|
||||
if (varint32_read(f, &flags))
|
||||
{
|
||||
LOG("%s: varint32_read flags failed\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
else if (varint32_read(f, &offset))
|
||||
{
|
||||
LOG("%s: varint32_read offset failed\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int op_i32_load(struct nw_interp *const i)
|
||||
{
|
||||
return op(i, i->f);
|
||||
}
|
||||
|
||||
int check_i32_load(FILE *const f)
|
||||
{
|
||||
return op(NULL, f);
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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 <log.h>
|
||||
#include <ops.h>
|
||||
#include <nanowasm/nw.h>
|
||||
#include <wasm_types.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static int op(struct nw_interp *const i, FILE *const f)
|
||||
{
|
||||
varint32 flags, offset;
|
||||
|
||||
if (varint32_read(f, &flags))
|
||||
{
|
||||
LOG("%s: varint32_read flags failed\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
else if (varint32_read(f, &offset))
|
||||
{
|
||||
LOG("%s: varint32_read offset failed\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int op_i32_store(struct nw_interp *const i)
|
||||
{
|
||||
return op(i, i->f);
|
||||
}
|
||||
|
||||
int check_i32_store(FILE *const f)
|
||||
{
|
||||
return op(NULL, f);
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
# 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/.
|
||||
|
||||
target_sources(${PROJECT_NAME} PRIVATE
|
||||
i32_sub.c
|
||||
)
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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 <log.h>
|
||||
#include <ops.h>
|
||||
#include <nanowasm/nw.h>
|
||||
#include <wasm_types.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int op_i32_sub(struct nw_interp *const i)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int check_i32_sub(FILE *const f)
|
||||
{
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
# 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/.
|
||||
|
||||
target_sources(${PROJECT_NAME} PRIVATE
|
||||
get_global.c
|
||||
get_local.c
|
||||
set_global.c
|
||||
set_local.c
|
||||
tee_local.c
|
||||
)
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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 <log.h>
|
||||
#include <ops.h>
|
||||
#include <nanowasm/nw.h>
|
||||
#include <wasm_types.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static int op(struct nw_interp *const i, FILE *const f)
|
||||
{
|
||||
varuint32 global_index;
|
||||
|
||||
if (varuint32_read(f, &global_index))
|
||||
{
|
||||
LOG("%s: varuint32_read failed\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int op_get_global(struct nw_interp *const i)
|
||||
{
|
||||
return op(i, i->f);
|
||||
}
|
||||
|
||||
int check_get_global(FILE *const f)
|
||||
{
|
||||
return op(NULL, f);
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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 <log.h>
|
||||
#include <ops.h>
|
||||
#include <nanowasm/nw.h>
|
||||
#include <wasm_types.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static int op(struct nw_interp *const i, FILE *const f)
|
||||
{
|
||||
varuint32 local_index;
|
||||
|
||||
if (varuint32_read(f, &local_index))
|
||||
{
|
||||
LOG("%s: varuint32_read failed\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int op_get_local(struct nw_interp *const i)
|
||||
{
|
||||
return op(i, i->f);
|
||||
}
|
||||
|
||||
int check_get_local(FILE *const f)
|
||||
{
|
||||
return op(NULL, f);
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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 <log.h>
|
||||
#include <ops.h>
|
||||
#include <nanowasm/nw.h>
|
||||
#include <wasm_types.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static int op(struct nw_interp *const i, FILE *const f)
|
||||
{
|
||||
varuint32 global_index;
|
||||
|
||||
if (varuint32_read(f, &global_index))
|
||||
{
|
||||
LOG("%s: varuint32_read failed\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int op_set_global(struct nw_interp *const i)
|
||||
{
|
||||
return op(i, i->f);
|
||||
}
|
||||
|
||||
int check_set_global(FILE *const f)
|
||||
{
|
||||
return op(NULL, f);
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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 <log.h>
|
||||
#include <ops.h>
|
||||
#include <nanowasm/nw.h>
|
||||
#include <wasm_types.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static int op(struct nw_interp *const i, FILE *const f)
|
||||
{
|
||||
varuint32 local_index;
|
||||
|
||||
if (varuint32_read(f, &local_index))
|
||||
{
|
||||
LOG("%s: varuint32_read failed\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int op_set_local(struct nw_interp *const i)
|
||||
{
|
||||
return op(i, i->f);
|
||||
}
|
||||
|
||||
int check_set_local(FILE *const f)
|
||||
{
|
||||
return op(NULL, f);
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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 <log.h>
|
||||
#include <ops.h>
|
||||
#include <nanowasm/nw.h>
|
||||
#include <wasm_types.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static int op(struct nw_interp *const i, FILE *const f)
|
||||
{
|
||||
varuint32 local_index;
|
||||
|
||||
if (varuint32_read(f, &local_index))
|
||||
{
|
||||
LOG("%s: varuint32_read failed\n", __func__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int op_tee_local(struct nw_interp *const i)
|
||||
{
|
||||
return op(i, i->f);
|
||||
}
|
||||
|
||||
int check_tee_local(FILE *const f)
|
||||
{
|
||||
return op(NULL, f);
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* 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 <nanowasm/nw.h>
|
||||
#include <log.h>
|
||||
#include <search.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
enum nw_state nw_run(struct nw_inst *const i)
|
||||
{
|
||||
return NW_STATE_AGAIN;
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* 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 <search.h>
|
||||
#include <log.h>
|
||||
#include <fstring.h>
|
||||
#include <sections.h>
|
||||
#include <nanowasm/nw.h>
|
||||
#include <wasm_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 (!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_fn_start(const char *const fn, 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;
|
||||
|
||||
if (section_function(&s, m, index, &sf))
|
||||
{
|
||||
LOG("%s: section_function failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int search_exported_fn(const char *const fn, const struct nw_mod *const m,
|
||||
FILE *const f, struct search_fn *const out)
|
||||
{
|
||||
varuint32 index;
|
||||
|
||||
if (ensure_export(fn, m, f, &index))
|
||||
{
|
||||
LOG("%s: %s not an exported function\n", __func__, fn);
|
||||
return -1;
|
||||
}
|
||||
else if (get_fn_start(fn, m, f, index, out))
|
||||
{
|
||||
LOG("%s: get_fn_start %s failed\n", __func__, fn);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
# 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/.
|
||||
|
||||
target_sources(${PROJECT_NAME} PRIVATE
|
||||
code.c
|
||||
common.c
|
||||
custom.c
|
||||
data.c
|
||||
element.c
|
||||
export.c
|
||||
function.c
|
||||
global.c
|
||||
import.c
|
||||
memory.c
|
||||
start.c
|
||||
table.c
|
||||
type.c
|
||||
)
|
|
@ -0,0 +1,247 @@
|
|||
/*
|
||||
* 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 <log.h>
|
||||
#include <nanowasm/nw.h>
|
||||
#include <opcodes.h>
|
||||
#include <interp.h>
|
||||
#include <sections.h>
|
||||
#include <wasm_types.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
static int check_body(FILE *const f, const unsigned long n)
|
||||
{
|
||||
unsigned long rem = n;
|
||||
|
||||
while (rem)
|
||||
{
|
||||
const long before = ftell(f);
|
||||
uint8_t byte;
|
||||
|
||||
if (before < 0)
|
||||
{
|
||||
LOG("%s: ftell(3) before: %s\n", __func__, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
else if (!fread(&byte, sizeof byte, 1, f))
|
||||
{
|
||||
LOG("%s: fread(3) failed, feof=%d, ferror=%d\n",
|
||||
__func__, feof(f), ferror(f));
|
||||
return -1;
|
||||
}
|
||||
else if (rem == 1 && byte != OP_END)
|
||||
{
|
||||
LOG("%s: unexpected opcode %#" PRIx8 " at body end\n",
|
||||
__func__, byte);
|
||||
return -1;
|
||||
}
|
||||
else if (interp_check_opcode(byte, f))
|
||||
{
|
||||
LOG("%s: interp_check_opcode failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
const long after = ftell(f);
|
||||
|
||||
if (after < 0)
|
||||
{
|
||||
LOG("%s: ftell(3) after: %s\n", __func__, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
rem -= after - before;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_type(FILE *const f)
|
||||
{
|
||||
varint7 type;
|
||||
|
||||
if (varint7_read(f, &type))
|
||||
{
|
||||
LOG("%s: varint7_read failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_local(FILE *const f)
|
||||
{
|
||||
varuint32 count;
|
||||
|
||||
if (varuint32_read(f, &count))
|
||||
{
|
||||
LOG("%s: varuint32_read failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
else if (check_type(f))
|
||||
{
|
||||
LOG("%s: check_type failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_locals(FILE *const f)
|
||||
{
|
||||
varuint32 local_count;
|
||||
|
||||
if (varuint32_read(f, &local_count))
|
||||
{
|
||||
LOG("%s: varuint32_read local_count failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (varuint32 i = 0; i < local_count; i++)
|
||||
if (check_local(f))
|
||||
{
|
||||
LOG("%s: check_local failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_function_body(FILE *const f)
|
||||
{
|
||||
varuint32 body_size;
|
||||
|
||||
if (varuint32_read(f, &body_size))
|
||||
{
|
||||
LOG("%s: varuint32_read body_size failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
const long start = ftell(f);
|
||||
|
||||
if (start < 0)
|
||||
{
|
||||
LOG("%s: ftell(3) start: %s\n", __func__, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
else if (check_locals(f))
|
||||
{
|
||||
LOG("%s: check_locals failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
const long end = ftell(f);
|
||||
|
||||
if (end < 0)
|
||||
{
|
||||
LOG("%s: ftell(3) end: %s\n", __func__, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
const unsigned long consumed = end - start;
|
||||
|
||||
if (consumed > body_size)
|
||||
{
|
||||
LOG("%s: exceeded function body size\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
else if (check_body(f, body_size - consumed))
|
||||
{
|
||||
LOG("%s: check_body failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* TODO: add function body pointers to struct nanowasm. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_function_bodies(FILE *const f)
|
||||
{
|
||||
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_function_body(f))
|
||||
{
|
||||
LOG("%s: check_function_body failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check(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;
|
||||
}
|
||||
else if (check_function_bodies(f))
|
||||
{
|
||||
LOG("%s: check_function_bodies 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_code_check(const struct section *const s, struct nw_mod *const m,
|
||||
const unsigned long len)
|
||||
{
|
||||
FILE *const f = s->f;
|
||||
|
||||
if (m->sections.code)
|
||||
{
|
||||
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(f, len))
|
||||
{
|
||||
LOG("%s: check failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
m->sections.code = offset;
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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 <log.h>
|
||||
#include <sections.h>
|
||||
#include <wasm_types.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int check_resizable_limits(FILE *const f)
|
||||
{
|
||||
varuint1 flags;
|
||||
varuint32 initial;
|
||||
|
||||
if (varuint1_read(f, &flags))
|
||||
{
|
||||
LOG("%s: varuint1_read failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
else if (varuint32_read(f, &initial))
|
||||
{
|
||||
LOG("%s: varuint32_read failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (flags)
|
||||
{
|
||||
varuint32 maximum;
|
||||
|
||||
if (varuint32_read(f, &maximum))
|
||||
{
|
||||
LOG("%s: varuint32_read failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* 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 <log.h>
|
||||
#include <sections.h>
|
||||
#include <nanowasm/nw.h>
|
||||
#include <wasm_types.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int section_custom_check(const struct section *const s, struct nw_mod *const m,
|
||||
const unsigned long len)
|
||||
{
|
||||
FILE *const f = s->f;
|
||||
|
||||
if (fseek(f, len, SEEK_CUR))
|
||||
{
|
||||
LOG("%s: fseek(3): %s\n", __func__, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* 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 <nanowasm/nw.h>
|
||||
#include <sections.h>
|
||||
#include <wasm_types.h>
|
||||
|
||||
int section_data_check(const struct section *const s, struct nw_mod *const m,
|
||||
const unsigned long len)
|
||||
{
|
||||
return -1;
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* 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 <sections.h>
|
||||
#include <nanowasm/nw.h>
|
||||
|
||||
int section_element_check(const struct section *const s,
|
||||
struct nw_mod *const m, const unsigned long len)
|
||||
{
|
||||
return -1;
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* 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 <log.h>
|
||||
#include <sections.h>
|
||||
#include <nanowasm/nw.h>
|
||||
#include <wasm_types.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
static int check_string(FILE *const f)
|
||||
{
|
||||
varuint32 len;
|
||||
|
||||
if (varuint32_read(f, &len))
|
||||
{
|
||||
LOG("%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))
|
||||
{
|
||||
LOG("%s: fread(3) failed, feof=%d, ferror=%d\n",
|
||||
__func__, feof(f), ferror(f));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_kind(FILE *const f)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_index(FILE *const f)
|
||||
{
|
||||
varuint32 index;
|
||||
|
||||
if (varuint32_read(f, &index))
|
||||
{
|
||||
LOG("%s: varuint32_read failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_export_entry(FILE *const f)
|
||||
{
|
||||
if (check_string(f))
|
||||
{
|
||||
LOG("%s: check_string failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
else if (check_kind(f))
|
||||
{
|
||||
LOG("%s: check_kind failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
else if (check_index(f))
|
||||
{
|
||||
LOG("%s: check_index failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check(FILE *const f, const unsigned long len)
|
||||
{
|
||||
const long start = ftell(f);
|
||||
varuint32 count;
|
||||
|
||||
if (start < 0)
|
||||
{
|
||||
LOG("%s: ftell(3): %s\n", __func__, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
else if (varuint32_read(f, &count))
|
||||
{
|
||||
LOG("%s: varuint32_read failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (varuint32 i = 0; i < count; i++)
|
||||
if (check_export_entry(f))
|
||||
{
|
||||
LOG("%s: check_export_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_export_check(const struct section *const s, struct nw_mod *const m,
|
||||
const unsigned long len)
|
||||
{
|
||||
FILE *const f = s->f;
|
||||
|
||||
if (m->sections.export)
|
||||
{
|
||||
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(f, len))
|
||||
{
|
||||
LOG("%s: check failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
m->sections.export = offset;
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* 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 <log.h>
|
||||
#include <sections.h>
|
||||
#include <nanowasm/nw.h>
|
||||
#include <wasm_types.h>
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
static int run(FILE *const f, const varuint32 idx,
|
||||
struct section_function *const out)
|
||||
{
|
||||
varuint32 count;
|
||||
|
||||
if (varuint32_read(f, &count))
|
||||
{
|
||||
LOG("%s: varuint32_read count failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (varuint32 i = 0; i < count; i++)
|
||||
{
|
||||
varuint32 type;
|
||||
|
||||
if (varuint32_read(f, &type))
|
||||
{
|
||||
LOG("%s: varuint32_read type failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (out && i == idx)
|
||||
{
|
||||
out->type = type;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (out)
|
||||
{
|
||||
LOG("%s: could not find function index %ju\n", __func__,
|
||||
(uintmax_t)idx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int section_function_check(const struct section *const s,
|
||||
struct nw_mod *const m, const unsigned long len)
|
||||
{
|
||||
FILE *const f = s->f;
|
||||
|
||||
if (m->sections.function)
|
||||
{
|
||||
LOG("%s: ignoring duplicate section\n", __func__);
|
||||
return fseek(f, len, SEEK_CUR);
|
||||
}
|
||||
|
||||
const long start = ftell(f);
|
||||
|
||||
if (start < 0)
|
||||
{
|
||||
LOG("%s: ftell(3): %s\n", __func__, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
else if (run(f, 0, NULL))
|
||||
{
|
||||
LOG("%s: run 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;
|
||||
}
|
||||
|
||||
m->sections.function = start;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int section_function(const struct section *const s,
|
||||
const struct nw_mod *const m, const varuint32 idx,
|
||||
struct section_function *const f)
|
||||
{
|
||||
const long offset = m->sections.function;
|
||||
|
||||
if (offset <= 0)
|
||||
{
|
||||
LOG("%s: function section not found", __func__);
|
||||
return -1;
|
||||
}
|
||||
else if (fseek(s->f, offset, SEEK_SET))
|
||||
{
|
||||
LOG("%s: fseek(3): %s\n", __func__, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return run(s->f, idx, f);
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* 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 <log.h>
|
||||
#include <sections.h>
|
||||
#include <nanowasm/nw.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))
|
||||
{
|
||||
LOG("%s: varint7_read failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
else if (varuint1_read(f, &g->mutability))
|
||||
{
|
||||
LOG("%s: varuint1_read failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check(FILE *const f, const unsigned long len)
|
||||
{
|
||||
struct global_type g;
|
||||
const long start = ftell(f);
|
||||
struct nw_interp i = {.f = f};
|
||||
|
||||
if (start < 0)
|
||||
{
|
||||
LOG("%s: ftell(3): %s\n", __func__, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
else if (check_global_type(f, &g))
|
||||
{
|
||||
LOG("%s: check_global_type\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
else if (interp_run_limited(&i, &interp_initexpr_set))
|
||||
{
|
||||
LOG("%s: interp_run 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_global_check(const struct section *const s, struct nw_mod *const m,
|
||||
const unsigned long len)
|
||||
{
|
||||
FILE *const f = s->f;
|
||||
|
||||
if (m->sections.global)
|
||||
{
|
||||
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(f, len))
|
||||
{
|
||||
LOG("%s: check failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
m->sections.global = offset;
|
||||
return 0;
|
||||
}
|
|
@ -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 <sections.h>
|
||||
#include <fstring.h>
|
||||
#include <log.h>
|
||||
#include <wasm_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;
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* 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 <log.h>
|
||||
#include <sections.h>
|
||||
#include <nanowasm/nw.h>
|
||||
#include <wasm_types.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
static int check_memory_type(FILE *const f)
|
||||
{
|
||||
return check_resizable_limits(f);
|
||||
}
|
||||
|
||||
static int check(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_memory_type(f))
|
||||
{
|
||||
LOG("%s: check_memory_type 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_memory_check(const struct section *const s, struct nw_mod *const m,
|
||||
const unsigned long len)
|
||||
{
|
||||
FILE *const f = s->f;
|
||||
|
||||
if (m->sections.memory)
|
||||
{
|
||||
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(f, len))
|
||||
{
|
||||
LOG("%s: check failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
m->sections.memory = offset;
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* 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 <sections.h>
|
||||
#include <nanowasm/nw.h>
|
||||
#include <wasm_types.h>
|
||||
|
||||
int section_start_check(const struct section *const s, struct nw_mod *const m,
|
||||
const unsigned long len)
|
||||
{
|
||||
return -1;
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* 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 <log.h>
|
||||
#include <sections.h>
|
||||
#include <nanowasm/nw.h>
|
||||
#include <wasm_types.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
static int check_table_type(FILE *const f)
|
||||
{
|
||||
enum {ANYFUNC = 0x70};
|
||||
varint7 elem_type;
|
||||
|
||||
if (varint7_read(f, &elem_type))
|
||||
{
|
||||
LOG("%s: varint7_read failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
else if (elem_type != ANYFUNC)
|
||||
{
|
||||
LOG("%s: expected %x, got %x", __func__, ANYFUNC,
|
||||
(int)elem_type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return check_resizable_limits(f);
|
||||
}
|
||||
|
||||
static int check(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_table_type(f))
|
||||
{
|
||||
LOG("%s: check_table_type 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_table_check(const struct section *const s, struct nw_mod *const m,
|
||||
const unsigned long len)
|
||||
{
|
||||
FILE *const f = s->f;
|
||||
|
||||
if (m->sections.table)
|
||||
{
|
||||
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(f, len))
|
||||
{
|
||||
LOG("%s: check failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
m->sections.table = offset;
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* 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 <log.h>
|
||||
#include <sections.h>
|
||||
#include <nanowasm/nw.h>
|
||||
#include <wasm_types.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
static int check_value_type(FILE *const f)
|
||||
{
|
||||
varint7 value_type;
|
||||
|
||||
if (varint7_read(f, &value_type))
|
||||
{
|
||||
LOG("%s: varint7_read failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_func_type(FILE *const f)
|
||||
{
|
||||
varint7 form;
|
||||
varuint32 param_count;
|
||||
|
||||
if (varint7_read(f, &form))
|
||||
{
|
||||
LOG("%s: varint7_read failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
else if (varuint32_read(f, ¶m_count))
|
||||
{
|
||||
LOG("%s: varuint32_read failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (varuint32 i = 0; i < param_count; i++)
|
||||
if (check_value_type(f))
|
||||
{
|
||||
LOG("%s: check_value_type failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
varuint1 return_count;
|
||||
|
||||
if (varuint1_read(f, &return_count))
|
||||
{
|
||||
LOG("%s: varuint1_read failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
else if (return_count && check_value_type(f))
|
||||
{
|
||||
LOG("%s: check_value_type 2 failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check(FILE *const f, const unsigned long len)
|
||||
{
|
||||
const long start = ftell(f);
|
||||
varuint32 count;
|
||||
|
||||
if (start < 0)
|
||||
{
|
||||
LOG("%s: ftell(3): %s\n", __func__, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
else if (varuint32_read(f, &count))
|
||||
{
|
||||
LOG("%s: varuint32_read failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (varuint32 i = 0; i < count; i++)
|
||||
if (check_func_type(f))
|
||||
{
|
||||
LOG("%s: check_func_type 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_type_check(const struct section *const s, struct nw_mod *const m,
|
||||
const unsigned long len)
|
||||
{
|
||||
FILE *const f = s->f;
|
||||
|
||||
if (m->sections.type)
|
||||
{
|
||||
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(f, len))
|
||||
{
|
||||
LOG("%s: check failed\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
m->sections.type = offset;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int section_type(const struct section *const s, struct section_type *const out)
|
||||
{
|
||||
return -1;
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* 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 <nanowasm/nw.h>
|
||||
#include <interp.h>
|
||||
#include <log.h>
|
||||
#include <search.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int nw_start(const struct nw_inst_cfg *const icfg, struct nw_inst *const i)
|
||||
{
|
||||
int ret = -1;
|
||||
const struct nw_mod *const m = icfg->m;
|
||||
const struct nw_mod_cfg *const mcfg = &m->cfg;
|
||||
FILE *const f = fopen(mcfg->path, "rb");
|
||||
struct search_fn fn;
|
||||
|
||||
if (!f)
|
||||
{
|
||||
LOG("%s: fopen(3) %s: %s\n", __func__, mcfg->path, strerror(errno));
|
||||
goto end;
|
||||
}
|
||||
else if (m->sections.start)
|
||||
{
|
||||
/* TODO. */
|
||||
}
|
||||
else if (search_exported_fn("_start", m, f, &fn))
|
||||
{
|
||||
LOG("%s: search_exported_fn failed\n", __func__);
|
||||
goto end;
|
||||
}
|
||||
else if (fseek(f, fn.start, SEEK_SET))
|
||||
{
|
||||
LOG("%s: fseek(3): %s\n", __func__, strerror(errno));
|
||||
goto end;
|
||||
}
|
||||
|
||||
*i = (const struct nw_inst){.m = m};
|
||||
|
||||
if (interp_start(&icfg->interp, &i->interp))
|
||||
{
|
||||
fprintf(stderr, "%s: interp_start failed\n", __func__);
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
end:
|
||||
|
||||
if (ret && f && fclose(f))
|
||||
{
|
||||
LOG("%s: fclose(3) %s: %s\n", __func__, mcfg->path, strerror(errno));
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* 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 <nanowasm/nw.h>
|
||||
#include <log.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int nw_stop(struct nw_inst *const i)
|
||||
{
|
||||
struct nw_interp *const in = &i->interp;
|
||||
|
||||
if (i && in->f && fclose(in->f))
|
||||
{
|
||||
LOG("%s: fclose(3): %s\n", __func__, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* 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 <leb128.h>
|
||||
#include <wasm_types.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int varuint1_read(FILE *const f, varuint1 *const out)
|
||||
{
|
||||
unsigned long long value;
|
||||
|
||||
if (leb128_read_unsigned(f, 1, &value))
|
||||
return -1;
|
||||
|
||||
*out = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int varint7_read(FILE *const f, varint7 *const out)
|
||||
{
|
||||
long long value;
|
||||
|
||||
if (leb128_read_signed(f, 7, &value))
|
||||
return -1;
|
||||
|
||||
*out = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int varuint7_read(FILE *const f, varuint7 *const out)
|
||||
{
|
||||
unsigned long long value;
|
||||
|
||||
if (leb128_read_unsigned(f, 7, &value))
|
||||
return -1;
|
||||
|
||||
*out = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int varuint32_read(FILE *const f, varuint32 *out)
|
||||
{
|
||||
unsigned long long value;
|
||||
|
||||
if (leb128_read_unsigned(f, 32, &value))
|
||||
return -1;
|
||||
|
||||
*out = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int varint32_read(FILE *const f, varint32 *const out)
|
||||
{
|
||||
long long value;
|
||||
|
||||
if (leb128_read_signed(f, 32, &value))
|
||||
return -1;
|
||||
|
||||
*out = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int varuint64_read(FILE *const f, varuint64 *const out)
|
||||
{
|
||||
unsigned long long value;
|
||||
|
||||
if (leb128_read_unsigned(f, 64, &value))
|
||||
return -1;
|
||||
|
||||
*out = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int varint64_read(FILE *const f, varint64 *const out)
|
||||
{
|
||||
long long value;
|
||||
|
||||
if (leb128_read_signed(f, 64, &value))
|
||||
return -1;
|
||||
|
||||
*out = value;
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* 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 <nanowasm/nw.h>
|
||||
#include <wasm_types.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
void nw_unload(struct nw_mod *const m)
|
||||
{
|
||||
free(m);
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
# 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/.
|
||||
|
||||
cmake_minimum_required(VERSION 3.18)
|
||||
project(test C)
|
||||
add_executable(${PROJECT_NAME} main.c)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE nanowasm)
|
||||
|
||||
include(CheckLinkerFlag)
|
||||
set(ldflags -Wl,--gc-sections)
|
||||
|
||||
foreach(f ${ldflags})
|
||||
string(REPLACE "-" "_" var supported_${f})
|
||||
string(REPLACE "," "_" var ${var})
|
||||
check_linker_flag(C ${f} ${var})
|
||||
|
||||
if(${var})
|
||||
target_link_options(${PROJECT_NAME} PRIVATE ${f})
|
||||
endif()
|
||||
endforeach()
|
Binary file not shown.
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* 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 <nanowasm/nw.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static int proc_exit(const struct nw_args *const params,
|
||||
union nw_value *const ret, void *const user)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
static const struct nw_import imports[] =
|
||||
{
|
||||
{
|
||||
.kind = NW_KIND_FUNCTION,
|
||||
.module = "wasi_snapshot_preview1",
|
||||
.field = "proc_exit",
|
||||
.u.function =
|
||||
{
|
||||
.signature = "i32()",
|
||||
.fn = proc_exit
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static const struct nw_mod_cfg cfg =
|
||||
{
|
||||
.path = "example.wasm",
|
||||
.imports = imports,
|
||||
.n_imports = sizeof imports / sizeof *imports
|
||||
};
|
||||
|
||||
struct nw_mod m;
|
||||
|
||||
if (nw_load(&cfg, &m))
|
||||
{
|
||||
fprintf(stderr, "%s: nw_load failed\n", __func__);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
const struct nw_inst_cfg icfg =
|
||||
{
|
||||
.interp =
|
||||
{
|
||||
.stack = NW_BUF(1024),
|
||||
.heap = NW_BUF(1024),
|
||||
},
|
||||
|
||||
.m = &m
|
||||
};
|
||||
|
||||
struct nw_inst inst;
|
||||
|
||||
if (nw_start(&icfg, &inst))
|
||||
{
|
||||
fprintf(stderr, "%s: nw_start failed\n", __func__);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
const union nw_inst_state *s = &inst.state;
|
||||
|
||||
again:
|
||||
switch (nw_run(&inst))
|
||||
{
|
||||
case NW_STATE_AGAIN:
|
||||
goto again;
|
||||
|
||||
case NW_STATE_RETURNED:
|
||||
fprintf(stderr, "instance returned %d\n", s->retval);
|
||||
break;
|
||||
|
||||
case NW_STATE_EXCEPTION:
|
||||
fprintf(stderr, "exception: %s\n", s->exception);
|
||||
return EXIT_FAILURE;
|
||||
|
||||
case NW_STATE_FATAL:
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
Loading…
Reference in New Issue