Skip to content

Commit

Permalink
wasm2c: Cleanup/separate code for heap and stack signal handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
shravanrn committed Dec 15, 2023
1 parent 4e043bb commit 54f8459
Show file tree
Hide file tree
Showing 13 changed files with 103 additions and 77 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ jobs:
runs-on: ubuntu-latest
env:
USE_NINJA: "1"
WASM2C_CFLAGS: "-DWASM_RT_USE_MMAP=1 -DWASM_RT_SKIP_SIGNAL_RECOVERY=1 -DWASM_RT_USE_STACK_DEPTH_COUNT=0 -DWASM2C_TEST_EMBEDDER_SIGNAL_HANDLING"
WASM2C_CFLAGS: "-DWASM_RT_USE_MMAP=1 -DWASM_RT_SKIP_SIGNAL_RECOVERY=1 -DWASM2C_TEST_EMBEDDER_SIGNAL_HANDLING"
steps:
- uses: actions/setup-python@v1
with:
Expand All @@ -182,4 +182,5 @@ jobs:
submodules: true
- run: sudo apt-get install ninja-build
- run: make clang-debug
- run: ./test/run-tests.py --exclude-dir memory64
- name: tests (excluding memory64)
run: ./test/run-tests.py --exclude-dir memory64
2 changes: 1 addition & 1 deletion src/prebuilt/wasm2c_source_declarations.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ R"w2c_template(
#define TRAP(x) (wasm_rt_trap(WASM_RT_TRAP_##x), 0)
)w2c_template"
R"w2c_template(
#if WASM_RT_USE_STACK_DEPTH_COUNT
#if WASM_RT_STACK_DEPTH_COUNT
)w2c_template"
R"w2c_template(#define FUNC_PROLOGUE \
)w2c_template"
Expand Down
2 changes: 1 addition & 1 deletion src/template/wasm2c.declarations.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

#define TRAP(x) (wasm_rt_trap(WASM_RT_TRAP_##x), 0)

#if WASM_RT_USE_STACK_DEPTH_COUNT
#if WASM_RT_STACK_DEPTH_COUNT
#define FUNC_PROLOGUE \
if (++wasm_rt_call_stack_depth > WASM_RT_MAX_CALL_STACK_DEPTH) \
TRAP(EXHAUSTION);
Expand Down
2 changes: 1 addition & 1 deletion test/wasm2c/add.txt
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ u32 w2c_test_add(w2c_test*, u32, u32);
#define TRAP(x) (wasm_rt_trap(WASM_RT_TRAP_##x), 0)
#if WASM_RT_USE_STACK_DEPTH_COUNT
#if WASM_RT_STACK_DEPTH_COUNT
#define FUNC_PROLOGUE \
if (++wasm_rt_call_stack_depth > WASM_RT_MAX_CALL_STACK_DEPTH) \
TRAP(EXHAUSTION);
Expand Down
2 changes: 1 addition & 1 deletion test/wasm2c/check-imports.txt
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ extern const u8 wasm2c_test_is64_env_0x5F_linear_memory;
#define TRAP(x) (wasm_rt_trap(WASM_RT_TRAP_##x), 0)
#if WASM_RT_USE_STACK_DEPTH_COUNT
#if WASM_RT_STACK_DEPTH_COUNT
#define FUNC_PROLOGUE \
if (++wasm_rt_call_stack_depth > WASM_RT_MAX_CALL_STACK_DEPTH) \
TRAP(EXHAUSTION);
Expand Down
2 changes: 1 addition & 1 deletion test/wasm2c/export-names.txt
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ void w2c_test_0xE20x9D0xA40xEF0xB80x8F(w2c_test*);
#define TRAP(x) (wasm_rt_trap(WASM_RT_TRAP_##x), 0)
#if WASM_RT_USE_STACK_DEPTH_COUNT
#if WASM_RT_STACK_DEPTH_COUNT
#define FUNC_PROLOGUE \
if (++wasm_rt_call_stack_depth > WASM_RT_MAX_CALL_STACK_DEPTH) \
TRAP(EXHAUSTION);
Expand Down
2 changes: 1 addition & 1 deletion test/wasm2c/hello.txt
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ void w2c_test_0x5Fstart(w2c_test*);
#define TRAP(x) (wasm_rt_trap(WASM_RT_TRAP_##x), 0)
#if WASM_RT_USE_STACK_DEPTH_COUNT
#if WASM_RT_STACK_DEPTH_COUNT
#define FUNC_PROLOGUE \
if (++wasm_rt_call_stack_depth > WASM_RT_MAX_CALL_STACK_DEPTH) \
TRAP(EXHAUSTION);
Expand Down
2 changes: 1 addition & 1 deletion test/wasm2c/minimal.txt
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ wasm_rt_func_type_t wasm2c_test_get_func_type(uint32_t param_count, uint32_t res
#define TRAP(x) (wasm_rt_trap(WASM_RT_TRAP_##x), 0)
#if WASM_RT_USE_STACK_DEPTH_COUNT
#if WASM_RT_STACK_DEPTH_COUNT
#define FUNC_PROLOGUE \
if (++wasm_rt_call_stack_depth > WASM_RT_MAX_CALL_STACK_DEPTH) \
TRAP(EXHAUSTION);
Expand Down
2 changes: 1 addition & 1 deletion test/wasm2c/tail-calls.txt
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ void wasm_tailcall_w2c_test_tailcaller(void **instance_ptr, void *tail_call_stac
#define TRAP(x) (wasm_rt_trap(WASM_RT_TRAP_##x), 0)
#if WASM_RT_USE_STACK_DEPTH_COUNT
#if WASM_RT_STACK_DEPTH_COUNT
#define FUNC_PROLOGUE \
if (++wasm_rt_call_stack_depth > WASM_RT_MAX_CALL_STACK_DEPTH) \
TRAP(EXHAUSTION);
Expand Down
2 changes: 1 addition & 1 deletion wasm2c/examples/fac/fac.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

#define TRAP(x) (wasm_rt_trap(WASM_RT_TRAP_##x), 0)

#if WASM_RT_USE_STACK_DEPTH_COUNT
#if WASM_RT_STACK_DEPTH_COUNT
#define FUNC_PROLOGUE \
if (++wasm_rt_call_stack_depth > WASM_RT_MAX_CALL_STACK_DEPTH) \
TRAP(EXHAUSTION);
Expand Down
107 changes: 54 additions & 53 deletions wasm2c/wasm-rt-impl.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@
#include <stdlib.h>
#include <string.h>

#if (WASM_RT_INSTALL_SIGNAL_HANDLER || !WASM_RT_USE_STACK_DEPTH_COUNT) && \
!defined(_WIN32)
#if WASM_RT_INSTALL_SIGNAL_HANDLER && !defined(_WIN32)
#include <signal.h>
#include <unistd.h>
#endif
Expand All @@ -39,17 +38,23 @@

#define PAGE_SIZE 65536

#ifndef NDEBUG
#define DEBUG_PRINTF(...) fprintf(stderr, __VA_ARGS__);
#else
#define DEBUG_PRINTF(...)
#endif

#if WASM_RT_INSTALL_SIGNAL_HANDLER
static bool g_signal_handler_installed = false;
#ifdef _WIN32
static void* g_sig_handler_handle = 0;
#endif
#endif

#if WASM_RT_USE_STACK_DEPTH_COUNT
#if WASM_RT_STACK_DEPTH_COUNT
WASM_RT_THREAD_LOCAL uint32_t wasm_rt_call_stack_depth;
WASM_RT_THREAD_LOCAL uint32_t wasm_rt_saved_call_stack_depth;
#elif WASM_RT_INSTALL_SIGNAL_HANDLER
#elif WASM_RT_STACK_EXHAUSTION_HANDLER
static WASM_RT_THREAD_LOCAL void* g_alt_stack = NULL;
#endif

Expand All @@ -65,7 +70,7 @@ extern void WASM_RT_GROW_FAILED_HANDLER();

void wasm_rt_trap(wasm_rt_trap_t code) {
assert(code != WASM_RT_TRAP_NONE);
#if WASM_RT_USE_STACK_DEPTH_COUNT
#if WASM_RT_STACK_DEPTH_COUNT
wasm_rt_call_stack_depth = wasm_rt_saved_call_stack_depth;
#endif

Expand Down Expand Up @@ -164,7 +169,45 @@ static void os_print_last_error(const char* msg) {
perror(msg);
}

#if !WASM_RT_USE_STACK_DEPTH_COUNT
#if WASM_RT_INSTALL_SIGNAL_HANDLER
static void os_signal_handler(int sig, siginfo_t* si, void* unused) {
if (si->si_code == SEGV_ACCERR) {
wasm_rt_trap(WASM_RT_TRAP_OOB);
} else {
wasm_rt_trap(WASM_RT_TRAP_EXHAUSTION);
}
}

static void os_install_signal_handler(void) {
struct sigaction sa;
memset(&sa, '\0', sizeof(sa));
sa.sa_flags = SA_SIGINFO;
#if WASM_RT_STACK_EXHAUSTION_HANDLER
sa.sa_flags |= SA_ONSTACK;
#endif
sigemptyset(&sa.sa_mask);
sa.sa_sigaction = os_signal_handler;

/* Install SIGSEGV and SIGBUS handlers, since macOS seems to use SIGBUS. */
if (sigaction(SIGSEGV, &sa, NULL) != 0 || sigaction(SIGBUS, &sa, NULL) != 0) {
perror("sigaction failed");
abort();
}
}

static void os_cleanup_signal_handler(void) {
/* Undo what was done in os_install_signal_handler */
struct sigaction sa;
memset(&sa, '\0', sizeof(sa));
sa.sa_handler = SIG_DFL;
if (sigaction(SIGSEGV, &sa, NULL) != 0 || sigaction(SIGBUS, &sa, NULL)) {
perror("sigaction failed");
abort();
}
}
#endif

#if WASM_RT_STACK_EXHAUSTION_HANDLER
static bool os_has_altstack_installed() {
/* check for altstack already in place */
stack_t ss;
Expand All @@ -175,18 +218,7 @@ static bool os_has_altstack_installed() {

return !(ss.ss_flags & SS_DISABLE);
}
#endif

#if WASM_RT_INSTALL_SIGNAL_HANDLER
static void os_signal_handler(int sig, siginfo_t* si, void* unused) {
if (si->si_code == SEGV_ACCERR) {
wasm_rt_trap(WASM_RT_TRAP_OOB);
} else {
wasm_rt_trap(WASM_RT_TRAP_EXHAUSTION);
}
}

#if !WASM_RT_USE_STACK_DEPTH_COUNT
/* These routines set up an altstack to handle SIGSEGV from stack overflow. */
static void os_allocate_and_install_altstack(void) {
/* verify altstack not already allocated */
Expand Down Expand Up @@ -229,10 +261,8 @@ static void os_disable_and_deallocate_altstack(void) {

if ((!g_alt_stack) || (ss.ss_flags & SS_DISABLE) ||
(ss.ss_sp != g_alt_stack) || (ss.ss_size != SIGSTKSZ)) {
#ifndef NDEBUG
fprintf(stderr,
"wasm-rt warning: alternate stack was modified unexpectedly\n");
#endif
DEBUG_PRINTF(
"wasm-rt warning: alternate stack was modified unexpectedly\n");
return;
}

Expand All @@ -247,35 +277,6 @@ static void os_disable_and_deallocate_altstack(void) {
}
#endif

static void os_install_signal_handler(void) {
struct sigaction sa;
memset(&sa, '\0', sizeof(sa));
sa.sa_flags = SA_SIGINFO;
#if !WASM_RT_USE_STACK_DEPTH_COUNT
sa.sa_flags |= SA_ONSTACK;
#endif
sigemptyset(&sa.sa_mask);
sa.sa_sigaction = os_signal_handler;

/* Install SIGSEGV and SIGBUS handlers, since macOS seems to use SIGBUS. */
if (sigaction(SIGSEGV, &sa, NULL) != 0 || sigaction(SIGBUS, &sa, NULL) != 0) {
perror("sigaction failed");
abort();
}
}

static void os_cleanup_signal_handler(void) {
/* Undo what was done in os_install_signal_handler */
struct sigaction sa;
memset(&sa, '\0', sizeof(sa));
sa.sa_handler = SIG_DFL;
if (sigaction(SIGSEGV, &sa, NULL) != 0 || sigaction(SIGBUS, &sa, NULL)) {
perror("sigaction failed");
abort();
}
}
#endif

#endif

void wasm_rt_init(void) {
Expand All @@ -290,7 +291,7 @@ void wasm_rt_init(void) {
}

bool wasm_rt_is_initialized(void) {
#if !WASM_RT_USE_STACK_DEPTH_COUNT
#if WASM_RT_STACK_EXHAUSTION_HANDLER
if (!os_has_altstack_installed()) {
return false;
}
Expand All @@ -312,13 +313,13 @@ void wasm_rt_free(void) {
}

void wasm_rt_init_thread(void) {
#if WASM_RT_INSTALL_SIGNAL_HANDLER && !WASM_RT_USE_STACK_DEPTH_COUNT
#if WASM_RT_STACK_EXHAUSTION_HANDLER
os_allocate_and_install_altstack();
#endif
}

void wasm_rt_free_thread(void) {
#if WASM_RT_INSTALL_SIGNAL_HANDLER && !WASM_RT_USE_STACK_DEPTH_COUNT
#if WASM_RT_STACK_EXHAUSTION_HANDLER
os_disable_and_deallocate_altstack();
#endif
}
Expand Down
2 changes: 1 addition & 1 deletion wasm2c/wasm-rt-impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ extern "C" {
/** A setjmp buffer used for handling traps. */
extern WASM_RT_THREAD_LOCAL wasm_rt_jmp_buf g_wasm_rt_jmp_buf;

#if WASM_RT_USE_STACK_DEPTH_COUNT
#if WASM_RT_STACK_DEPTH_COUNT
/** Saved call stack depth that will be restored in case a trap occurs. */
extern WASM_RT_THREAD_LOCAL uint32_t wasm_rt_saved_call_stack_depth;
#define WASM_RT_SAVE_STACK_DEPTH() \
Expand Down
48 changes: 36 additions & 12 deletions wasm2c/wasm-rt.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,17 +166,42 @@ extern "C" {
#define WASM_RT_INSTALL_SIGNAL_HANDLER 0
#endif

#ifndef WASM_RT_USE_STACK_DEPTH_COUNT
/* The signal handler on POSIX can detect call stack overflows. On windows, or
* platforms without a signal handler, we use stack depth counting. */
/* We need to detect and trap stack overflows. If we use a signal handler on
* POSIX systems, this can detect call stack overflows. On windows, or platforms
* without a signal handler, we use stack depth counting. */
#if !defined(WASM_RT_STACK_DEPTH_COUNT) && \
!defined(WASM_RT_STACK_EXHAUSTION_HANDLER)

#if WASM_RT_INSTALL_SIGNAL_HANDLER && !defined(_WIN32)
#define WASM_RT_USE_STACK_DEPTH_COUNT 0
#define WASM_RT_STACK_EXHAUSTION_HANDLER 1
#else
#define WASM_RT_USE_STACK_DEPTH_COUNT 1
#define WASM_RT_STACK_DEPTH_COUNT 1
#endif

#endif

// Ensure the stack macros are defined
#ifndef WASM_RT_STACK_DEPTH_COUNT
#define WASM_RT_STACK_DEPTH_COUNT 0
#endif
#ifndef WASM_RT_STACK_EXHAUSTION_HANDLER
#define WASM_RT_STACK_EXHAUSTION_HANDLER 0
#endif

#if (WASM_RT_STACK_EXHAUSTION_HANDLER + WASM_RT_STACK_DEPTH_COUNT) > 1
#error \
"Cannot specify multiple options from WASM_RT_STACK_EXHAUSTION_HANDLER , WASM_RT_STACK_DEPTH_COUNT"
#elif (WASM_RT_STACK_EXHAUSTION_HANDLER + WASM_RT_STACK_DEPTH_COUNT) == 0
#error \
"Must specify one of WASM_RT_STACK_EXHAUSTION_HANDLER , WASM_RT_STACK_DEPTH_COUNT"
#endif

#if WASM_RT_STACK_EXHAUSTION_HANDLER && !WASM_RT_INSTALL_SIGNAL_HANDLER
#error \
"WASM_RT_STACK_EXHAUSTION_HANDLER can only be used if WASM_RT_INSTALL_SIGNAL_HANDLER is enabled"
#endif

#if WASM_RT_USE_STACK_DEPTH_COUNT
#if WASM_RT_STACK_DEPTH_COUNT
/**
* When the signal handler cannot be used to detect stack overflows, stack depth
* is limited explicitly. The maximum stack depth before trapping can be
Expand All @@ -202,7 +227,7 @@ extern WASM_RT_THREAD_LOCAL uint32_t wasm_rt_call_stack_depth;
#define WASM_RT_NO_RETURN __attribute__((noreturn))
#endif

#if defined(__APPLE__) && !WASM_RT_USE_STACK_DEPTH_COUNT
#if defined(__APPLE__) && WASM_RT_STACK_EXHAUSTION_HANDLER
#define WASM_RT_MERGED_OOB_AND_EXHAUSTION_TRAPS 1
#else
#define WASM_RT_MERGED_OOB_AND_EXHAUSTION_TRAPS 0
Expand Down Expand Up @@ -279,7 +304,8 @@ typedef struct {
} wasm_rt_funcref_t;

/** Default (null) value of a funcref */
#define wasm_rt_funcref_null_value ((wasm_rt_funcref_t){NULL, NULL, {NULL}, NULL})
#define wasm_rt_funcref_null_value \
((wasm_rt_funcref_t){NULL, NULL, {NULL}, NULL})

/** The type of an external reference (opaque to WebAssembly). */
typedef void* wasm_rt_externref_t;
Expand Down Expand Up @@ -354,8 +380,7 @@ typedef struct {
jmp_buf buffer;
} wasm_rt_jmp_buf;

#if (WASM_RT_INSTALL_SIGNAL_HANDLER || (!WASM_RT_USE_STACK_DEPTH_COUNT)) && \
!defined(_WIN32)
#ifndef _WIN32
#define WASM_RT_SETJMP_SETBUF(buf) sigsetjmp(buf, 1)
#else
#define WASM_RT_SETJMP_SETBUF(buf) setjmp(buf)
Expand All @@ -364,8 +389,7 @@ typedef struct {
#define WASM_RT_SETJMP(buf) \
((buf).initialized = true, WASM_RT_SETJMP_SETBUF((buf).buffer))

#if (WASM_RT_INSTALL_SIGNAL_HANDLER || (!WASM_RT_USE_STACK_DEPTH_COUNT)) && \
!defined(_WIN32)
#ifndef _WIN32
#define WASM_RT_LONGJMP_UNCHECKED(buf, val) siglongjmp(buf, val)
#else
#define WASM_RT_LONGJMP_UNCHECKED(buf, val) longjmp(buf, val)
Expand Down

0 comments on commit 54f8459

Please sign in to comment.