Files
tinygo/src/runtime/runtime_unix.c
T
Ayke van Laethem 194396d715 unix: print a message when a fatal signal happens
Print a message for SIGBUS, SIGSEGV, and SIGILL when they happen.
These signals are always fatal, but it's very useful to know which of
them happened.

Also, it prints the location in the binary which can then be parsed by
`tinygo run` (see https://github.com/tinygo-org/tinygo/pull/4383).

While this does add some extra binary size, it's for Linux and MacOS
(systems that typically have plenty of RAM/storage) and could be very
useful when debugging some low-level crash such as a runtime bug.
2024-08-15 02:00:28 +02:00

57 lines
1.5 KiB
C

//go:build none
// This file is included on Darwin and Linux (despite the //go:build line above).
#define _GNU_SOURCE
#define _XOPEN_SOURCE
#include <signal.h>
#include <unistd.h>
#include <stdint.h>
#include <ucontext.h>
#include <string.h>
void tinygo_handle_fatal_signal(int sig, uintptr_t addr);
static void signal_handler(int sig, siginfo_t *info, void *context) {
ucontext_t* uctx = context;
uintptr_t addr = 0;
#if __APPLE__
#if __arm64__
addr = uctx->uc_mcontext->__ss.__pc;
#elif __x86_64__
addr = uctx->uc_mcontext->__ss.__rip;
#else
#error unknown architecture
#endif
#elif __linux__
// Note: this can probably be simplified using the MC_PC macro in musl,
// but this works for now.
#if __arm__
addr = uctx->uc_mcontext.arm_pc;
#elif __i386__
addr = uctx->uc_mcontext.gregs[REG_EIP];
#elif __x86_64__
addr = uctx->uc_mcontext.gregs[REG_RIP];
#else // aarch64, mips, maybe others
addr = uctx->uc_mcontext.pc;
#endif
#else
#error unknown platform
#endif
tinygo_handle_fatal_signal(sig, addr);
}
void tinygo_register_fatal_signals(void) {
struct sigaction act = { 0 };
// SA_SIGINFO: we want the 2 extra parameters
// SA_RESETHAND: only catch the signal once (the handler will re-raise the signal)
act.sa_flags = SA_SIGINFO | SA_RESETHAND;
act.sa_sigaction = &signal_handler;
// Register the signal handler for common issues. There are more signals,
// which can be added if needed.
sigaction(SIGBUS, &act, NULL);
sigaction(SIGILL, &act, NULL);
sigaction(SIGSEGV, &act, NULL);
}