1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 22:57:44 +00:00

LibWasm: Add execution hooks and a debugger mode to the wasm tool

This is useful for debugging *our* implementation of wasm :P
This commit is contained in:
Ali Mohammad Pur 2021-05-21 21:10:44 +04:30 committed by Ali Mohammad Pur
parent f740667fa1
commit ba5da79617
8 changed files with 299 additions and 4 deletions

View file

@ -113,6 +113,8 @@ InstantiationResult AbstractMachine::instantiate(const Module& module, Vector<Ex
entry.expression(),
1);
Configuration config { m_store };
config.pre_interpret_hook = &pre_interpret_hook;
config.post_interpret_hook = &post_interpret_hook;
config.set_frame(move(frame));
auto result = config.execute();
// What if this traps?
@ -143,6 +145,8 @@ InstantiationResult AbstractMachine::instantiate(const Module& module, Vector<Ex
data.offset,
1);
Configuration config { m_store };
config.pre_interpret_hook = &pre_interpret_hook;
config.post_interpret_hook = &post_interpret_hook;
config.set_frame(move(frame));
auto result = config.execute();
size_t offset = 0;
@ -281,7 +285,10 @@ Optional<InstantiationError> AbstractMachine::allocate_all(const Module& module,
Result AbstractMachine::invoke(FunctionAddress address, Vector<Value> arguments)
{
return Configuration { m_store }.call(address, move(arguments));
Configuration configuration { m_store };
configuration.pre_interpret_hook = &pre_interpret_hook;
configuration.post_interpret_hook = &post_interpret_hook;
return configuration.call(address, move(arguments));
}
void Linker::link(const ModuleInstance& instance)

View file

@ -16,6 +16,7 @@
namespace Wasm {
class Configuration;
struct Interpreter;
struct InstantiationError {
String error { "Unknown error" };
@ -445,6 +446,9 @@ public:
auto& store() const { return m_store; }
auto& store() { return m_store; }
Function<bool(Configuration&, InstructionPointer&, const Instruction&)> pre_interpret_hook;
Function<bool(Configuration&, InstructionPointer&, const Instruction&, const Interpreter&)> post_interpret_hook;
private:
Optional<InstantiationError> allocate_all(const Module&, ModuleInstance&, Vector<ExternValue>&, Vector<Value>& global_values);
Store m_store;

View file

@ -53,6 +53,9 @@ Result Configuration::call(FunctionAddress address, Vector<Value> arguments)
Result Configuration::execute()
{
Interpreter interpreter;
interpreter.pre_interpret_hook = pre_interpret_hook;
interpreter.post_interpret_hook = post_interpret_hook;
interpreter.interpret(*this);
if (interpreter.did_trap())
return Trap {};

View file

@ -40,6 +40,9 @@ public:
void dump_stack();
Function<bool(Configuration&, InstructionPointer&, const Instruction&)>* pre_interpret_hook { nullptr };
Function<bool(Configuration&, InstructionPointer&, const Instruction&, const Interpreter&)>* post_interpret_hook { nullptr };
private:
Store& m_store;
Frame* m_current_frame { nullptr };

View file

@ -126,6 +126,8 @@ void Interpreter::call_address(Configuration& configuration, FunctionAddress add
args.prepend(move(*configuration.stack().pop().get<NonnullOwnPtr<Value>>()));
}
Configuration function_configuration { configuration.store() };
function_configuration.pre_interpret_hook = pre_interpret_hook;
function_configuration.post_interpret_hook = post_interpret_hook;
function_configuration.depth() = configuration.depth() + 1;
auto result = function_configuration.call(address, move(args));
if (result.is_trap()) {
@ -338,8 +340,25 @@ Vector<NonnullOwnPtr<Value>> Interpreter::pop_values(Configuration& configuratio
void Interpreter::interpret(Configuration& configuration, InstructionPointer& ip, const Instruction& instruction)
{
dbgln_if(WASM_TRACE_DEBUG, "Executing instruction {} at ip {}", instruction_name(instruction.opcode()), ip.value());
if constexpr (WASM_TRACE_DEBUG)
configuration.dump_stack();
if (pre_interpret_hook && *pre_interpret_hook) {
auto result = pre_interpret_hook->operator()(configuration, ip, instruction);
if (!result) {
m_do_trap = true;
return;
}
}
ScopeGuard guard { [&] {
if (post_interpret_hook && *post_interpret_hook) {
auto result = post_interpret_hook->operator()(configuration, ip, instruction, *this);
if (!result) {
m_do_trap = true;
return;
}
}
} };
switch (instruction.opcode().value()) {
case Instructions::unreachable.value():
m_do_trap = true;

View file

@ -13,6 +13,10 @@ namespace Wasm {
struct Interpreter {
void interpret(Configuration&);
bool did_trap() const { return m_do_trap; }
void clear_trap() { m_do_trap = false; }
Function<bool(Configuration&, InstructionPointer&, const Instruction&)>* pre_interpret_hook { nullptr };
Function<bool(Configuration&, InstructionPointer&, const Instruction&, const Interpreter&)>* post_interpret_hook { nullptr };
private:
void interpret(Configuration&, InstructionPointer&, const Instruction&);