From d1494635937f7812948d677bd7e0e7c3556d395d Mon Sep 17 00:00:00 2001 From: Shravan Narayan Date: Sat, 5 Nov 2022 19:01:03 -0400 Subject: [PATCH] wasm2c: add hook to allow a custom trap handler In production use cases, unwinding the stack before reporting an error throws away valuable information such as the stack trace. This hook allows the host to implement an alternate error recovery/reporting mechanism --- wasm2c/README.md | 13 ++++++++++--- wasm2c/wasm-rt-impl.c | 6 ++++++ wasm2c/wasm-rt.h | 7 +++++++ 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/wasm2c/README.md b/wasm2c/README.md index 5fd3e3755..19b12b6c2 100644 --- a/wasm2c/README.md +++ b/wasm2c/README.md @@ -299,9 +299,16 @@ initialize the runtime. `wasm_rt_free` frees any global state. `wasm_rt_is_initialized` can be used to confirm that the runtime has been initialized. -`wasm_rt_trap` is a function that is called when the module traps. Some -possible implementations are to throw a C++ exception, or to just abort the -program execution. +`wasm_rt_trap` is a function that is called when the module traps. Some possible +implementations are to throw a C++ exception, or to just abort the program +execution. The default runtime included in wasm2c unwinds the stack using +`longjmp`. You can overide this call to `longjmp` from the embeder by defining a +custom trap handler with the signature `void +wasm2c_custom_trap_handler(wasm_rt_trap_t code)` and compiling the runtime with +the with macro definition `#define WASM_RT_MEMCHECK_SIGNAL_HANDLER +wasm2c_custom_trap_handler`. It is recommended that you add this macro +definition via a compiler flag +(`-DWASM_RT_MEMCHECK_SIGNAL_HANDLER=wasm2c_custom_trap_handler` on clang/gcc). `wasm_rt_register_func_type` is a function that registers a function type. It is a variadic function where the first two arguments give the number of diff --git a/wasm2c/wasm-rt-impl.c b/wasm2c/wasm-rt-impl.c index 7187b2838..ac5a0a549 100644 --- a/wasm2c/wasm-rt-impl.c +++ b/wasm2c/wasm-rt-impl.c @@ -77,7 +77,13 @@ void wasm_rt_trap(wasm_rt_trap_t code) { #if WASM_RT_USE_STACK_DEPTH_COUNT wasm_rt_call_stack_depth = wasm_rt_saved_call_stack_depth; #endif + +#ifdef WASM_RT_TRAP_HANDLER + WASM_RT_TRAP_HANDLER(code); + wasm_rt_unreachable(); +#else WASM_RT_LONGJMP(wasm_rt_jmp_buf, code); +#endif } static bool func_types_are_equal(FuncType* a, FuncType* b) { diff --git a/wasm2c/wasm-rt.h b/wasm2c/wasm-rt.h index 29d564bbe..b420087d0 100644 --- a/wasm2c/wasm-rt.h +++ b/wasm2c/wasm-rt.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #ifdef __cplusplus @@ -44,6 +45,12 @@ extern "C" { #define wasm_rt_memcpy memcpy #endif +#if __has_builtin(__builtin_unreachable) +#define wasm_rt_unreachable __builtin_unreachable +#else +#define wasm_rt_unreachable abort +#endif + /** * Enable memory checking via a signal handler via the following definition: *