Add tests that trap, and fix handling of SIGFPE on x86.

This commit is contained in:
Dan Gohman
2018-11-27 06:29:07 -08:00
parent 35627cf37f
commit 2a760ae5e8
4 changed files with 62 additions and 22 deletions

View File

@@ -0,0 +1,11 @@
(module
(func $foo (result i32)
i32.const 1
i32.const 0
i32.div_s
)
(func $main
(drop (call $foo))
)
(start $main)
)

View File

@@ -0,0 +1,9 @@
(module
(func $foo
(call $main)
)
(func $main
(call $foo)
)
(start $main)
)

View File

@@ -0,0 +1,9 @@
(module
(func $foo
(unreachable)
)
(func $main
(call $foo)
)
(start $main)
)

View File

@@ -592,22 +592,17 @@ MachExceptionHandlerThread(void *arg)
#else // If not Windows or Mac, assume Unix #else // If not Windows or Mac, assume Unix
#ifdef __mips__ static struct sigaction sPrevSIGSEGVHandler;
static const uint32_t kWasmTrapSignal = SIGFPE;
#else
static const uint32_t kWasmTrapSignal = SIGILL;
#endif
static struct sigaction sPrevSEGVHandler;
static struct sigaction sPrevSIGBUSHandler; static struct sigaction sPrevSIGBUSHandler;
static struct sigaction sPrevWasmTrapHandler; static struct sigaction sPrevSIGILLHandler;
static struct sigaction sPrevSIGFPEHandler;
static void static void
WasmTrapHandler(int signum, siginfo_t* info, void* context) WasmTrapHandler(int signum, siginfo_t* info, void* context)
{ {
if (!sAlreadyHandlingTrap) { if (!sAlreadyHandlingTrap) {
AutoHandlingTrap aht; AutoHandlingTrap aht;
assert(signum == SIGSEGV || signum == SIGBUS || signum == kWasmTrapSignal); assert(signum == SIGSEGV || signum == SIGBUS || signum == SIGFPE || signum == SIGILL);
if (HandleTrap(static_cast<CONTEXT*>(context))) { if (HandleTrap(static_cast<CONTEXT*>(context))) {
return; return;
} }
@@ -615,9 +610,10 @@ WasmTrapHandler(int signum, siginfo_t* info, void* context)
struct sigaction* previousSignal = nullptr; struct sigaction* previousSignal = nullptr;
switch (signum) { switch (signum) {
case SIGSEGV: previousSignal = &sPrevSEGVHandler; break; case SIGSEGV: previousSignal = &sPrevSIGSEGVHandler; break;
case SIGBUS: previousSignal = &sPrevSIGBUSHandler; break; case SIGBUS: previousSignal = &sPrevSIGBUSHandler; break;
case kWasmTrapSignal: previousSignal = &sPrevWasmTrapHandler; break; case SIGFPE: previousSignal = &sPrevSIGFPEHandler; break;
case SIGILL: previousSignal = &sPrevSIGILLHandler; break;
} }
assert(previousSignal); assert(previousSignal);
@@ -696,8 +692,8 @@ EnsureEagerSignalHandlers()
faultHandler.sa_flags = SA_SIGINFO | SA_NODEFER | SA_ONSTACK; faultHandler.sa_flags = SA_SIGINFO | SA_NODEFER | SA_ONSTACK;
faultHandler.sa_sigaction = WasmTrapHandler; faultHandler.sa_sigaction = WasmTrapHandler;
sigemptyset(&faultHandler.sa_mask); sigemptyset(&faultHandler.sa_mask);
if (sigaction(SIGSEGV, &faultHandler, &sPrevSEGVHandler)) { if (sigaction(SIGSEGV, &faultHandler, &sPrevSIGSEGVHandler)) {
perror("unable to install segv handler"); perror("unable to install SIGSEGV handler");
abort(); abort();
} }
@@ -708,21 +704,36 @@ EnsureEagerSignalHandlers()
busHandler.sa_sigaction = WasmTrapHandler; busHandler.sa_sigaction = WasmTrapHandler;
sigemptyset(&busHandler.sa_mask); sigemptyset(&busHandler.sa_mask);
if (sigaction(SIGBUS, &busHandler, &sPrevSIGBUSHandler)) { if (sigaction(SIGBUS, &busHandler, &sPrevSIGBUSHandler)) {
perror("unable to install sigbus handler"); perror("unable to install SIGBUS handler");
abort(); abort();
} }
# endif # endif
// Install a handler to handle the instructions that are emitted to implement # if !defined(__mips__)
// wasm traps. // Wasm traps for MIPS currently only raise integer overflow fp exception.
struct sigaction trapHandler; struct sigaction illHandler;
trapHandler.sa_flags = SA_SIGINFO | SA_NODEFER | SA_ONSTACK; illHandler.sa_flags = SA_SIGINFO | SA_NODEFER | SA_ONSTACK;
trapHandler.sa_sigaction = WasmTrapHandler; illHandler.sa_sigaction = WasmTrapHandler;
sigemptyset(&trapHandler.sa_mask); sigemptyset(&illHandler.sa_mask);
if (sigaction(kWasmTrapSignal, &trapHandler, &sPrevWasmTrapHandler)) { if (sigaction(SIGILL, &illHandler, &sPrevSIGILLHandler)) {
perror("unable to install wasm trap handler"); perror("unable to install wasm SIGILL handler");
abort(); abort();
} }
# endif
# if defined(__i386__) || defined(__x86_64__) || defined(__mips__)
// x86 uses SIGFPE to report division by zero, and wasm traps for MIPS
// currently raise integer overflow fp exception.
struct sigaction fpeHandler;
fpeHandler.sa_flags = SA_SIGINFO | SA_NODEFER | SA_ONSTACK;
fpeHandler.sa_sigaction = WasmTrapHandler;
sigemptyset(&fpeHandler.sa_mask);
if (sigaction(SIGFPE, &fpeHandler, &sPrevSIGFPEHandler)) {
perror("unable to install wasm SIGFPE handler");
abort();
}
# endif
#endif #endif
return true; return true;