added: better handling for bad math exceptions in debug env
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 28 Sep 2023 18:04:55 +0000 (13:04 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 28 Sep 2023 18:04:55 +0000 (13:04 -0500)
interpreter/include/vm.h
interpreter/src/vm/vm.c
interpreter/src/vm/vm_instrs.h
interpreter/src/wasm/engine.c

index 85a75789e2d63871833c6407763a25441c9e2ef2..77220270db78d43e9076c819a0653491bd102617 100644 (file)
@@ -119,6 +119,7 @@ struct ovm_engine_t {
 
 ovm_engine_t *ovm_engine_new(ovm_store_t *store);
 void          ovm_engine_delete(ovm_engine_t *engine);
+void          ovm_engine_enable_debug(ovm_engine_t *engine, debug_state_t *debug);
 bool          ovm_engine_memory_ensure_capacity(ovm_engine_t *engine, i64 minimum_size);
 void          ovm_engine_memory_copy(ovm_engine_t *engine, i64 target, void *data, i64 size);
 
index ecf4f0955e13474fbd4c71b2c8d958b596baf015..04c2d00b84a620059c08c7bdba82a5e163d0fb0d 100644 (file)
@@ -3,6 +3,7 @@
 #include "vm.h"
 
 #include <sys/mman.h>
+#include <signal.h>
 #include <x86intrin.h>
 #include <math.h> // REMOVE THIS!!!  only needed for sqrt
 #include <pthread.h>
@@ -172,6 +173,29 @@ void ovm_engine_delete(ovm_engine_t *engine) {
     bh_free(store->heap_allocator, engine);
 }
 
+static i32 hit_signaled_exception = 0;
+static void signal_handler(int signo, siginfo_t *info, void *context) {
+    hit_signaled_exception = 1;
+}
+
+void ovm_engine_enable_debug(ovm_engine_t *engine, debug_state_t *debug) {
+    engine->debug = debug;
+
+    struct sigaction sa;
+    sa.sa_sigaction = signal_handler;
+    sigemptyset(&sa.sa_mask);
+    sa.sa_flags = SA_RESTART | SA_SIGINFO;
+
+    sigaction(SIGQUIT, &sa, NULL);
+    sigaction(SIGPIPE, &sa, NULL);
+    sigaction(SIGTERM, &sa, NULL);
+    sigaction(SIGHUP, &sa, NULL);
+
+    // sigaction(SIGSEGV, &sa, NULL);
+    // sigaction(SIGFPE, &sa, NULL);
+    // sigaction(SIGINT, &sa, NULL);   Don't overload Ctrl+C
+}
+
 bool ovm_engine_memory_ensure_capacity(ovm_engine_t *engine, i64 minimum_size) {
     if (engine->memory_size >= minimum_size) return true;
 
@@ -413,6 +437,12 @@ static void __ovm_trigger_exception(ovm_state_t *state) {
 static void __ovm_debug_hook(ovm_engine_t *engine, ovm_state_t *state) {
     if (!state->debug) return;
 
+    if (hit_signaled_exception) {
+        __ovm_trigger_exception(state);
+        hit_signaled_exception = 0;
+        return;
+    }
+
     if (state->debug->run_count == 0) {
         state->debug->state = debug_state_pausing;
 
@@ -466,12 +496,14 @@ static void __ovm_debug_hook(ovm_engine_t *engine, ovm_state_t *state) {
 #define OVMI_DISPATCH_NAME ovmi_dispatch
 #define OVMI_DEBUG_HOOK ((void)0)
 #define OVMI_EXCEPTION_HOOK ((void)0)
+#define OVMI_DIVIDE_CHECK_HOOK(_) ((void)0)
 #include "./vm_instrs.h"
 
 #define OVMI_FUNC_NAME(n) ovmi_exec_debug_##n
 #define OVMI_DISPATCH_NAME ovmi_debug_dispatch
 #define OVMI_DEBUG_HOOK __ovm_debug_hook(state->engine, state)
 #define OVMI_EXCEPTION_HOOK __ovm_trigger_exception(state)
+#define OVMI_DIVIDE_CHECK_HOOK(ctype) if (VAL(instr->b).ctype == 0) __ovm_trigger_exception(state)
 #include "./vm_instrs.h"
 
 ovm_value_t ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t *program) {
@@ -480,7 +512,9 @@ ovm_value_t ovm_run_code(ovm_engine_t *engine, ovm_state_t *state, ovm_program_t
     ovm_assert(program);
 
     ovmi_instr_exec_t *exec_table = ovmi_dispatch;
-    if (state->debug) exec_table = ovmi_debug_dispatch;
+    if (state->debug) {
+        exec_table = ovmi_debug_dispatch;
+    }
 
     ovm_instr_t *code = program->code;
     u8 *memory = engine->memory;
index a9430f00434facfebc40d9a2494b2a6dbf99815a..312b6291cc062c5a1e9070344af26999c2a7e6d4 100644 (file)
@@ -82,10 +82,6 @@ OVMI_INSTR_EXEC(nop) {
 OVM_OP_EXEC(add, +)
 OVM_OP_EXEC(sub, -)
 OVM_OP_EXEC(mul, *)
-OVM_OP_EXEC(div_s, /)
-OVM_OP_UNSIGNED_EXEC(div, /)
-OVM_OP_INTEGER_UNSIGNED_EXEC(rem, %)
-OVM_OP_INTEGER_EXEC(rem_s, %)
 OVM_OP_INTEGER_UNSIGNED_EXEC(and, &)
 OVM_OP_INTEGER_UNSIGNED_EXEC(or, |)
 OVM_OP_INTEGER_UNSIGNED_EXEC(xor, ^)
@@ -95,6 +91,20 @@ OVM_OP_INTEGER_EXEC(sar, >>)
 
 #undef OVM_OP
 
+
+#define OVM_OP(t, op, ctype) \
+    ovm_assert(VAL(instr->a).type == t && VAL(instr->b).type == t); \
+    OVMI_DIVIDE_CHECK_HOOK(ctype); \
+    VAL(instr->r).ctype = VAL(instr->a).ctype op VAL(instr->b).ctype; \
+    VAL(instr->r).type = t;
+
+OVM_OP_EXEC(div_s, /)
+OVM_OP_UNSIGNED_EXEC(div, /)
+OVM_OP_INTEGER_UNSIGNED_EXEC(rem, %)
+OVM_OP_INTEGER_EXEC(rem_s, %)
+
+#undef OVM_OP
+
 #define OVM_OP(t, func, ctype) \
     ovm_assert(VAL(instr->a).type == t && VAL(instr->b).type == t); \
     VAL(instr->r).ctype = func( VAL(instr->a).ctype, VAL(instr->b).ctype ); \
@@ -641,4 +651,5 @@ static ovmi_instr_exec_t OVMI_DISPATCH_NAME[] = {
 #undef OVMI_DISPATCH_NAME
 #undef OVMI_DEBUG_HOOK
 #undef OVMI_EXCEPTION_HOOK
+#undef OVMI_DIVIDE_CHECK_HOOK
 
index 666779a73bb174f4543d8ca5bd457bc90d83e416..ef172c62049c24625906f7673fcc50089ab0730a 100644 (file)
@@ -20,7 +20,7 @@ wasm_engine_t *wasm_engine_new_with_config(wasm_config_t *config) {
     if (config && config->debug_enabled) {
         // This should maybe be moved elsewhere?
         debug_state_t *debug  = bh_alloc_item(store->heap_allocator, debug_state_t);
-        engine->engine->debug = debug;
+        ovm_engine_enable_debug(engine->engine, debug);
 
         debug_host_init(engine->engine->debug, engine->engine);
         debug->listen_path = config->listen_path;