diff options
author | Denys Vlasenko | 2012-01-30 12:15:22 +0100 |
---|---|---|
committer | Denys Vlasenko | 2012-01-30 12:15:22 +0100 |
commit | da2b2da6a708edffcc3b405ab5fd7f3f11af5d33 (patch) | |
tree | aad306641009c4faccf419327d3b9ed724d52df5 | |
parent | 1c7724bf2acb6ebe28b24bd6da3b740e716b46cf (diff) | |
download | busybox-da2b2da6a708edffcc3b405ab5fd7f3f11af5d33.zip busybox-da2b2da6a708edffcc3b405ab5fd7f3f11af5d33.tar.gz |
init: add a segv debugging aid, disabled by default
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | init/init.c | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/init/init.c b/init/init.c index c540faa..7248946 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 <syslog.h> #include <paths.h> @@ -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 <execinfo.h> +# include <sys/ucontext.h> +#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 |