From 5c728cf0c41238d0d36e3760e442c799680fe4e2 Mon Sep 17 00:00:00 2001 From: Christian Helmuth Date: Tue, 17 Mar 2015 17:49:56 +0100 Subject: [PATCH] linux: log diagnostic message on exceptions Log the fact that a software exception will terminate the process and hint about more information available from the Linux kernel log. Fixes #1457 --- .../base-linux/src/base/thread/thread_env.cc | 32 +++++++++++++++++++ .../base-linux/src/platform/linux_syscalls.h | 4 +++ 2 files changed, 36 insertions(+) diff --git a/repos/base-linux/src/base/thread/thread_env.cc b/repos/base-linux/src/base/thread/thread_env.cc index 20b4db0541..15c87a2ad7 100644 --- a/repos/base-linux/src/base/thread/thread_env.cc +++ b/repos/base-linux/src/base/thread/thread_env.cc @@ -15,6 +15,8 @@ #include #include +#include + using namespace Genode; extern addr_t * __initial_sp; @@ -29,6 +31,31 @@ char **lx_environ; */ int main_thread_futex_counter __attribute__((aligned(sizeof(addr_t)))); +/** + * Signal handler for exceptions like segmentation faults + */ +static void exception_signal_handler(int signum) +{ + char const *reason = nullptr; + + switch (signum) { + case LX_SIGILL: reason = "Illegal instruction"; break; + case LX_SIGBUS: reason = "Bad memory access"; break; + case LX_SIGFPE: reason = "Floating point exception"; break; + case LX_SIGSEGV: reason = "Segmentation fault"; break; + + default: /* unexpected signal */ return; + } + PERR("%s (signum=%d), see Linux kernel log for details", reason, signum); + + /* + * We reset the signal handler to SIG_DFL and trigger exception again, + * i.e., terminate the process. + */ + lx_sigaction(signum, nullptr); + return; +} + /***************************** ** Startup library support ** @@ -46,4 +73,9 @@ void prepare_init_main_thread() * __initial_sp[3] = environ */ lx_environ = (char**)&__initial_sp[3]; + + lx_sigaction(LX_SIGILL, exception_signal_handler); + lx_sigaction(LX_SIGBUS, exception_signal_handler); + lx_sigaction(LX_SIGFPE, exception_signal_handler); + lx_sigaction(LX_SIGSEGV, exception_signal_handler); } diff --git a/repos/base-linux/src/platform/linux_syscalls.h b/repos/base-linux/src/platform/linux_syscalls.h index 6e0d47d9d6..702e370f57 100644 --- a/repos/base-linux/src/platform/linux_syscalls.h +++ b/repos/base-linux/src/platform/linux_syscalls.h @@ -209,7 +209,11 @@ inline int lx_munmap(void *addr, size_t length) enum { LX_SIGINT = 2, /* used by core to catch Control-C */ + LX_SIGILL = 4, /* exception: illegal instruction */ + LX_SIGBUS = 7, /* exception: bus error, i.e., bad memory access */ + LX_SIGFPE = 8, /* exception: floating point */ LX_SIGUSR1 = 10, /* used for cancel-blocking mechanism */ + LX_SIGSEGV = 11, /* exception: segmentation violation */ LX_SIGCHLD = 17, /* child process changed state, i.e., terminated */ LX_SIGCANCEL = 32, /* accoring to glibc, this equals SIGRTMIN, used for killing threads */