mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-19 20:01:20 +00:00
Fix LLVM object loader exceptions.
This commit is contained in:
@ -253,6 +253,7 @@ fn get_llvm_cxxflags() -> String {
|
|||||||
.split(&[' ', '\n'][..])
|
.split(&[' ', '\n'][..])
|
||||||
.filter(|word| !word.starts_with("-W"))
|
.filter(|word| !word.starts_with("-W"))
|
||||||
.filter(|word| word != &"-fno-exceptions")
|
.filter(|word| word != &"-fno-exceptions")
|
||||||
|
.filter(|word| word != &"-fno-rtti")
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(" ")
|
.join(" ")
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ struct UnwindPoint {
|
|||||||
UnwindPoint *prev;
|
UnwindPoint *prev;
|
||||||
jmp_buf stack;
|
jmp_buf stack;
|
||||||
std::function<void()> *f;
|
std::function<void()> *f;
|
||||||
std::unique_ptr<std::exception> exception;
|
std::unique_ptr<WasmException> exception;
|
||||||
};
|
};
|
||||||
|
|
||||||
static thread_local UnwindPoint *unwind_state = nullptr;
|
static thread_local UnwindPoint *unwind_state = nullptr;
|
||||||
@ -47,11 +47,11 @@ void catch_unwind(std::function<void()> &&f) {
|
|||||||
|
|
||||||
unwind_state = current.prev;
|
unwind_state = current.prev;
|
||||||
if (current.exception) {
|
if (current.exception) {
|
||||||
throw *current.exception;
|
throw std::move(current.exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void unsafe_unwind(std::exception *exception) {
|
void unsafe_unwind(WasmException *exception) {
|
||||||
UnwindPoint *state = unwind_state;
|
UnwindPoint *state = unwind_state;
|
||||||
if (state) {
|
if (state) {
|
||||||
state->exception.reset(exception);
|
state->exception.reset(exception);
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <exception>
|
#include <exception>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
@ -52,6 +53,17 @@ typedef struct {
|
|||||||
size_t data, vtable;
|
size_t data, vtable;
|
||||||
} box_any_t;
|
} box_any_t;
|
||||||
|
|
||||||
|
enum WasmTrapType {
|
||||||
|
Unreachable = 0,
|
||||||
|
IncorrectCallIndirectSignature = 1,
|
||||||
|
MemoryOutOfBounds = 2,
|
||||||
|
CallIndirectOOB = 3,
|
||||||
|
IllegalArithmetic = 4,
|
||||||
|
Unknown,
|
||||||
|
};
|
||||||
|
|
||||||
|
extern "C" void callback_trampoline(void *, void *);
|
||||||
|
|
||||||
struct MemoryManager : llvm::RuntimeDyld::MemoryManager {
|
struct MemoryManager : llvm::RuntimeDyld::MemoryManager {
|
||||||
public:
|
public:
|
||||||
MemoryManager(callbacks_t callbacks) : callbacks(callbacks) {}
|
MemoryManager(callbacks_t callbacks) : callbacks(callbacks) {}
|
||||||
@ -106,13 +118,26 @@ private:
|
|||||||
size_t stack_map_size = 0;
|
size_t stack_map_size = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct WasmErrorSink {
|
||||||
|
WasmTrapType *trap_out;
|
||||||
|
box_any_t *user_error;
|
||||||
|
};
|
||||||
|
|
||||||
struct WasmException : std::exception {
|
struct WasmException : std::exception {
|
||||||
public:
|
public:
|
||||||
virtual std::string description() const noexcept = 0;
|
virtual std::string description() const noexcept { return "unknown"; }
|
||||||
|
|
||||||
|
virtual const char *what() const noexcept override {
|
||||||
|
return "wasm exception";
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void write_error(WasmErrorSink &out) const noexcept {
|
||||||
|
*out.trap_out = WasmTrapType::Unknown;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void catch_unwind(std::function<void()> &&f);
|
void catch_unwind(std::function<void()> &&f);
|
||||||
[[noreturn]] void unsafe_unwind(std::exception *exception);
|
[[noreturn]] void unsafe_unwind(WasmException *exception);
|
||||||
|
|
||||||
struct UncatchableException : WasmException {
|
struct UncatchableException : WasmException {
|
||||||
public:
|
public:
|
||||||
@ -131,6 +156,10 @@ public:
|
|||||||
|
|
||||||
// The parts of a `Box<dyn Any>`.
|
// The parts of a `Box<dyn Any>`.
|
||||||
box_any_t error_data;
|
box_any_t error_data;
|
||||||
|
|
||||||
|
virtual void write_error(WasmErrorSink &out) const noexcept override {
|
||||||
|
*out.user_error = error_data;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BreakpointException : UncatchableException {
|
struct BreakpointException : UncatchableException {
|
||||||
@ -142,6 +171,11 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
uintptr_t callback;
|
uintptr_t callback;
|
||||||
|
|
||||||
|
virtual void write_error(WasmErrorSink &out) const noexcept override {
|
||||||
|
puts("CB TRAMPOLINE");
|
||||||
|
callback_trampoline(out.user_error, (void *)callback);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WasmModule {
|
struct WasmModule {
|
||||||
@ -165,16 +199,7 @@ private:
|
|||||||
|
|
||||||
struct WasmTrap : UncatchableException {
|
struct WasmTrap : UncatchableException {
|
||||||
public:
|
public:
|
||||||
enum Type {
|
WasmTrap(WasmTrapType type) : type(type) {}
|
||||||
Unreachable = 0,
|
|
||||||
IncorrectCallIndirectSignature = 1,
|
|
||||||
MemoryOutOfBounds = 2,
|
|
||||||
CallIndirectOOB = 3,
|
|
||||||
IllegalArithmetic = 4,
|
|
||||||
Unknown,
|
|
||||||
};
|
|
||||||
|
|
||||||
WasmTrap(Type type) : type(type) {}
|
|
||||||
|
|
||||||
virtual std::string description() const noexcept override {
|
virtual std::string description() const noexcept override {
|
||||||
std::ostringstream ss;
|
std::ostringstream ss;
|
||||||
@ -183,27 +208,31 @@ public:
|
|||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
Type type;
|
WasmTrapType type;
|
||||||
|
|
||||||
|
virtual void write_error(WasmErrorSink &out) const noexcept override {
|
||||||
|
*out.trap_out = type;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend std::ostream &operator<<(std::ostream &out, const Type &ty) {
|
friend std::ostream &operator<<(std::ostream &out, const WasmTrapType &ty) {
|
||||||
switch (ty) {
|
switch (ty) {
|
||||||
case Type::Unreachable:
|
case WasmTrapType::Unreachable:
|
||||||
out << "unreachable";
|
out << "unreachable";
|
||||||
break;
|
break;
|
||||||
case Type::IncorrectCallIndirectSignature:
|
case WasmTrapType::IncorrectCallIndirectSignature:
|
||||||
out << "incorrect call_indirect signature";
|
out << "incorrect call_indirect signature";
|
||||||
break;
|
break;
|
||||||
case Type::MemoryOutOfBounds:
|
case WasmTrapType::MemoryOutOfBounds:
|
||||||
out << "memory access out-of-bounds";
|
out << "memory access out-of-bounds";
|
||||||
break;
|
break;
|
||||||
case Type::CallIndirectOOB:
|
case WasmTrapType::CallIndirectOOB:
|
||||||
out << "call_indirect out-of-bounds";
|
out << "call_indirect out-of-bounds";
|
||||||
break;
|
break;
|
||||||
case Type::IllegalArithmetic:
|
case WasmTrapType::IllegalArithmetic:
|
||||||
out << "illegal arithmetic operation";
|
out << "illegal arithmetic operation";
|
||||||
break;
|
break;
|
||||||
case Type::Unknown:
|
case WasmTrapType::Unknown:
|
||||||
default:
|
default:
|
||||||
out << "unknown";
|
out << "unknown";
|
||||||
break;
|
break;
|
||||||
@ -226,7 +255,6 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
void callback_trampoline(void *, void *);
|
|
||||||
|
|
||||||
result_t module_load(const uint8_t *mem_ptr, size_t mem_size,
|
result_t module_load(const uint8_t *mem_ptr, size_t mem_size,
|
||||||
callbacks_t callbacks, WasmModule **module_out) {
|
callbacks_t callbacks, WasmModule **module_out) {
|
||||||
@ -239,7 +267,7 @@ result_t module_load(const uint8_t *mem_ptr, size_t mem_size,
|
|||||||
return RESULT_OK;
|
return RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[noreturn]] void throw_trap(WasmTrap::Type ty) {
|
[[noreturn]] void throw_trap(WasmTrapType ty) {
|
||||||
unsafe_unwind(new WasmTrap(ty));
|
unsafe_unwind(new WasmTrap(ty));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,27 +286,21 @@ void module_delete(WasmModule *module) { delete module; }
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool invoke_trampoline(trampoline_t trampoline, void *ctx, void *func,
|
bool invoke_trampoline(trampoline_t trampoline, void *ctx, void *func,
|
||||||
void *params, void *results, WasmTrap::Type *trap_out,
|
void *params, void *results, WasmTrapType *trap_out,
|
||||||
box_any_t *user_error, void *invoke_env) noexcept {
|
box_any_t *user_error, void *invoke_env) noexcept {
|
||||||
try {
|
try {
|
||||||
catch_unwind([trampoline, ctx, func, params, results]() {
|
catch_unwind([trampoline, ctx, func, params, results]() {
|
||||||
trampoline(ctx, func, params, results);
|
trampoline(ctx, func, params, results);
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
} catch (const WasmTrap &e) {
|
} catch (std::unique_ptr<WasmException> &e) {
|
||||||
*trap_out = e.type;
|
WasmErrorSink sink;
|
||||||
return false;
|
sink.trap_out = trap_out;
|
||||||
} catch (const UserException &e) {
|
sink.user_error = user_error;
|
||||||
*user_error = e.error_data;
|
e->write_error(sink);
|
||||||
return false;
|
|
||||||
} catch (const BreakpointException &e) {
|
|
||||||
callback_trampoline(user_error, (void *)e.callback);
|
|
||||||
return false;
|
|
||||||
} catch (const WasmException &e) {
|
|
||||||
*trap_out = WasmTrap::Type::Unknown;
|
|
||||||
return false;
|
return false;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
*trap_out = WasmTrap::Type::Unknown;
|
*trap_out = WasmTrapType::Unknown;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user