From da2b2da6a708edffcc3b405ab5fd7f3f11af5d33 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 30 Jan 2012 12:15:22 +0100 Subject: init: add a segv debugging aid, disabled by default Signed-off-by: Denys Vlasenko --- init/init.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) (limited to 'init') diff --git a/init/init.c b/init/init.c index c540faa70..724894698 100644 --- a/init/init.c +++ b/init/init.c @@ -108,6 +108,8 @@ //config: Note that on Linux, init attempts to detect serial terminal and //config: sets TERM to "vt102" if one is found. +#define DEBUG_SEGV_HANDLER 0 + #include "libbb.h" #include #include @@ -118,6 +120,15 @@ #endif #include "reboot.h" /* reboot() constants */ +#if DEBUG_SEGV_HANDLER +# undef _GNU_SOURCE +# define _GNU_SOURCE 1 +# undef __USE_GNU +# define __USE_GNU 1 +# include +# include +#endif + /* Used only for sanitizing purposes in set_sane_term() below. On systems where * the baud rate is stored in a separate field, we can safely disable them. */ #ifndef CBAUD @@ -957,6 +968,33 @@ static int check_delayed_sigs(void) } } +#if DEBUG_SEGV_HANDLER +static +void handle_sigsegv(int sig, siginfo_t *info, void *ucontext) +{ + long ip; + ucontext_t *uc; + + uc = ucontext; + ip = uc->uc_mcontext.gregs[REG_EIP]; + fdprintf(2, "signal:%d address:0x%lx ip:0x%lx\n", + sig, + /* this is void*, but using %p would print "(null)" + * even for ptrs which are not exactly 0, but, say, 0x123: + */ + (long)info->si_addr, + ip); + { + /* glibc extension */ + void *array[50]; + int size; + size = backtrace(array, 50); + backtrace_symbols_fd(array, size, 2); + } + for (;;) sleep(9999); +} +#endif + int init_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int init_main(int argc UNUSED_PARAM, char **argv) { @@ -964,6 +1002,19 @@ int init_main(int argc UNUSED_PARAM, char **argv) return kill(1, SIGHUP); } +#if DEBUG_SEGV_HANDLER + { + struct sigaction sa; + memset(&sa, 0, sizeof(sa)); + sa.sa_sigaction = handle_sigsegv; + sa.sa_flags = SA_SIGINFO; + sigaction(SIGSEGV, &sa, NULL); + sigaction(SIGILL, &sa, NULL); + sigaction(SIGFPE, &sa, NULL); + sigaction(SIGBUS, &sa, NULL); + } +#endif + if (!DEBUG_INIT) { /* Expect to be invoked as init with PID=1 or be invoked as linuxrc */ if (getpid() != 1 -- cgit v1.2.3