checkasm: Prefer sigsetjmp()/siglongjmp() over SA_NODEFER

Also prefer re-setting the signal handler upon intercept in combination
with SA_RESETHAND over re-raising exceptions with the SIG_DFL handler.
This commit is contained in:
Henrik Gramner 2023-12-21 21:47:09 +01:00
parent 8501a4b201
commit d23e87f7ae
2 changed files with 23 additions and 20 deletions

View File

@ -36,7 +36,6 @@
#include "src/cpu.h"
#ifdef _WIN32
#include <windows.h>
#ifndef SIGBUS
/* non-standard, use the same value as mingw-w64 */
#define SIGBUS 10
@ -472,15 +471,18 @@ static LONG NTAPI signal_handler(EXCEPTION_POINTERS *const e) {
}
#endif
#else
static void signal_handler(int s);
static const struct sigaction signal_handler_act = {
.sa_handler = signal_handler,
.sa_flags = SA_RESETHAND,
};
static void signal_handler(const int s) {
if (state.catch_signals) {
state.catch_signals = 0;
sigaction(s, &signal_handler_act, NULL);
checkasm_load_context(s);
} else {
/* fall back to the default signal handler */
static const struct sigaction default_sa = { .sa_handler = SIG_DFL };
sigaction(s, &default_sa, NULL);
raise(s);
}
}
#endif
@ -671,14 +673,10 @@ int main(int argc, char *argv[]) {
SetConsoleMode(con, con_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
#endif
#else
const struct sigaction sa = {
.sa_handler = signal_handler,
.sa_flags = SA_NODEFER,
};
sigaction(SIGBUS, &sa, NULL);
sigaction(SIGFPE, &sa, NULL);
sigaction(SIGILL, &sa, NULL);
sigaction(SIGSEGV, &sa, NULL);
sigaction(SIGBUS, &signal_handler_act, NULL);
sigaction(SIGFPE, &signal_handler_act, NULL);
sigaction(SIGILL, &signal_handler_act, NULL);
sigaction(SIGSEGV, &signal_handler_act, NULL);
const char *const term = getenv("TERM");
use_printf_color = term && strcmp(term, "dumb") && isatty(2);

View File

@ -33,12 +33,17 @@
#include <stdint.h>
#include <stdlib.h>
#if !ARCH_X86_32 && defined(_WIN32)
#ifdef _WIN32
#include <windows.h>
#if ARCH_X86_32
#include <setjmp.h>
typedef jmp_buf checkasm_context;
#define checkasm_save_context() checkasm_handle_signal(setjmp(checkasm_context_buf))
#define checkasm_load_context(s) longjmp(checkasm_context_buf, s)
#elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
/* setjmp/longjmp on Windows on architectures using SEH (all except x86_32)
* will try to use SEH to unwind the stack, which doesn't work for assembly
* functions without unwind information. */
#include <windows.h>
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
typedef struct { CONTEXT c; int status; } checkasm_context;
#define checkasm_save_context() \
(checkasm_context_buf.status = 0, \
@ -54,9 +59,9 @@ typedef void* checkasm_context;
#endif
#else
#include <setjmp.h>
typedef jmp_buf checkasm_context;
#define checkasm_save_context() checkasm_handle_signal(setjmp(checkasm_context_buf))
#define checkasm_load_context(s) longjmp(checkasm_context_buf, s)
typedef sigjmp_buf checkasm_context;
#define checkasm_save_context() checkasm_handle_signal(sigsetjmp(checkasm_context_buf, 1))
#define checkasm_load_context(s) siglongjmp(checkasm_context_buf, s)
#endif
#include "include/common/attributes.h"