Message ID | 1416925140-12019-1-git-send-email-colin.king@canonical.com |
---|---|
State | Accepted |
Headers | show |
On 14-11-25 10:19 PM, Colin King wrote: > From: Colin Ian King<colin.king@canonical.com> > > Bugs such as LP#1376448 have been hard to track down because > the target machine is not accessible and the user is not easily > able to pass over core dump information. In an attempt to at > least identify where a fault is occurring, this patch adds in > a SIGSEGV and SIGBUS handler that will dump to stderr a stack > trace. > > This patch also re-works some of signal() handlers in fwts to > ensure we save and restore the dump stack handler in a more > generic way for fwts. This also tidies up the old fashioned > signal() handler with the more modern signal handling mechanisms. > > Signed-off-by: Colin Ian King<colin.king@canonical.com> Acked-by: Alex Hung <alex.hung@canonical.com>
On 2014年11月25日 22:19, Colin King wrote: > From: Colin Ian King <colin.king@canonical.com> > > Bugs such as LP#1376448 have been hard to track down because > the target machine is not accessible and the user is not easily > able to pass over core dump information. In an attempt to at > least identify where a fault is occurring, this patch adds in > a SIGSEGV and SIGBUS handler that will dump to stderr a stack > trace. > > This patch also re-works some of signal() handlers in fwts to > ensure we save and restore the dump stack handler in a more > generic way for fwts. This also tidies up the old fashioned > signal() handler with the more modern signal handling mechanisms. > > Signed-off-by: Colin Ian King <colin.king@canonical.com> > --- > src/lib/include/fwts.h | 1 + > src/lib/include/fwts_backtrace.h | 29 ++++++++ > src/lib/src/Makefile.am | 1 + > src/lib/src/fwts_backtrace.c | 145 +++++++++++++++++++++++++++++++++++++++ > src/lib/src/fwts_cpu.c | 5 +- > src/lib/src/fwts_ioport.c | 27 ++++---- > src/lib/src/fwts_safe_mem.c | 7 +- > src/main.c | 2 + > 8 files changed, 198 insertions(+), 19 deletions(-) > create mode 100644 src/lib/include/fwts_backtrace.h > create mode 100644 src/lib/src/fwts_backtrace.c > > diff --git a/src/lib/include/fwts.h b/src/lib/include/fwts.h > index d98932b..d5fc231 100644 > --- a/src/lib/include/fwts.h > +++ b/src/lib/include/fwts.h > @@ -35,6 +35,7 @@ > #define FWTS_JSON_DATA_PATH DATAROOTDIR "/fwts" > > #include "fwts_version.h" > +#include "fwts_backtrace.h" > #include "fwts_types.h" > #include "fwts_binpaths.h" > #include "fwts_framework.h" > diff --git a/src/lib/include/fwts_backtrace.h b/src/lib/include/fwts_backtrace.h > new file mode 100644 > index 0000000..e0b0dde > --- /dev/null > +++ b/src/lib/include/fwts_backtrace.h > @@ -0,0 +1,29 @@ > +/* > + * Copyright (C) 2010-2014 Canonical > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License > + * as published by the Free Software Foundation; either version 2 > + * of the License, or (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. > + * > + */ > +#ifndef __FWTS_BACKTRACE__ > +#define __FWTS_BACKTRACE__ > + > +#include <signal.h> > + > +void fwts_print_backtrace(void); > +int fwts_fault_catch(void); > +void fwts_sig_handler_set(int signum, void (*handler)(int), struct sigaction *old_action); > +void fwts_sig_handler_restore(int signum, struct sigaction *old_action); > + > +#endif > diff --git a/src/lib/src/Makefile.am b/src/lib/src/Makefile.am > index 33f81f4..2f0bbcc 100644 > --- a/src/lib/src/Makefile.am > +++ b/src/lib/src/Makefile.am > @@ -29,6 +29,7 @@ libfwts_la_SOURCES = \ > fwts_acpid.c \ > fwts_alloc.c \ > fwts_args.c \ > + fwts_backtrace.c \ > fwts_battery.c \ > fwts_binpaths.c \ > fwts_button.c \ > diff --git a/src/lib/src/fwts_backtrace.c b/src/lib/src/fwts_backtrace.c > new file mode 100644 > index 0000000..eb84b48 > --- /dev/null > +++ b/src/lib/src/fwts_backtrace.c > @@ -0,0 +1,145 @@ > +/* > + * Copyright (C) 2010-2014 Canonical > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License > + * as published by the Free Software Foundation; either version 2 > + * of the License, or (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write to the Free Software > + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. > + * > + */ > +#include <execinfo.h> > +#include <stdio.h> > +#include <stdlib.h> > +#include <stdint.h> > +#include <stdbool.h> > +#include <inttypes.h> > +#include <string.h> > +#include <signal.h> > +#include <setjmp.h> > + > +#include "fwts.h" > + > +#define BACK_TRACE_SIZE (512) > + > +static sigjmp_buf jmp_env; > +static void *bt_buff[BACK_TRACE_SIZE]; > +static size_t bt_size = 0; > + > +/* > + * fwts_print_backtrace() > + * parse symbol backtrace and dump it in a easy > + * to read format. > + */ > +void fwts_print_backtrace(void) > +{ > + char **bt_strings; > + size_t i; > + > + fprintf(stderr, "Backtrace:\n"); > + if (bt_size) { > + bt_strings = backtrace_symbols(bt_buff, bt_size); > + > + for (i = 0; i < bt_size; i++) { > + /* > + * convert trace into output in form: > + * 0x00007fb04a493ec5 /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf5) > + */ > + char *addrstr = strstr(bt_strings[i], " [0x"); > + if (addrstr) { > + uint64_t addr; > + > + *addrstr = '\0'; > + addr = (uint64_t)strtoull(addrstr + 2, NULL, 16); > + fprintf(stderr, "0x%16.16" PRIx64 " %s\n", addr, bt_strings[i]); > + } > + } > + free(bt_strings); > + } else { > + fprintf(stderr, " No data\n"); > + } > + fprintf(stderr, "\n"); > + fflush(stdout); > +} > + > +/* > + * fwts_fault_handler() > + * catch a signal, save stack dump, jmp back or abort > + */ > +static void fwts_fault_handler(int signum) > +{ > + static bool already_handled = false; > + > + /* Capture backtrace and jmp back */ > + > + if (!already_handled) { > + already_handled = true; > + /* Capture backtrace from this stack context */ > + bt_size = backtrace(bt_buff, BACK_TRACE_SIZE); > + /* Jmp back to the sigsetjmp context */ > + siglongjmp(jmp_env, signum); > + } > + /* We've hit a fault before, so abort */ > + _exit(EXIT_FAILURE); > +} > + > +/* > + * fwts_sig_handler_set() > + * helper to set signal handler > + */ > +void fwts_sig_handler_set(int signum, void (*handler)(int), struct sigaction *old_action) > +{ > + struct sigaction new_action; > + > + memset(&new_action, 0, sizeof new_action); > + new_action.sa_handler = handler; > + sigemptyset(&new_action.sa_mask); > + > + (void)sigaction(signum, &new_action, old_action); > +} > + > +/* > + * fwts_sig_handler_restore() > + * helper to restore signal handler > + */ > +void fwts_sig_handler_restore(int signum, struct sigaction *old_action) > +{ > + (void)sigaction(signum, old_action, NULL); > +} > + > +/* > + * fwts_fault_catch() > + * catch segfaults and bus errors, dump stack > + * trace so we can see what's causing them > + */ > +int fwts_fault_catch(void) > +{ > + int ret; > + > + /* Trap segfaults and bus errors */ > + fwts_sig_handler_set(SIGSEGV, fwts_fault_handler, NULL); > + fwts_sig_handler_set(SIGBUS, fwts_fault_handler, NULL); > + > + ret = sigsetjmp(jmp_env, 1); > + /* > + * We reach here with ret == SIGNUM if the fault handler > + * longjmps back to here. Or we reach here with > + * ret == 0 if sigsetjmp has set the jmp_env up > + * correctly. > + */ > + if (ret) { > + fprintf(stderr, "\nCaught SIGNAL %d (%s), aborting.\n", > + ret, strsignal(ret)); > + fwts_print_backtrace(); > + exit(EXIT_FAILURE); > + } > + return FWTS_OK; > +} > diff --git a/src/lib/src/fwts_cpu.c b/src/lib/src/fwts_cpu.c > index 9cbbdef..fe78ee5 100644 > --- a/src/lib/src/fwts_cpu.c > +++ b/src/lib/src/fwts_cpu.c > @@ -377,7 +377,7 @@ int fwts_cpu_performance( > */ > static void fwts_cpu_consume_cycles(void) > { > - signal(SIGUSR1, fwts_cpu_consume_sighandler); > + fwts_sig_handler_set(SIGUSR1, fwts_cpu_consume_sighandler, NULL); > uint64_t i = 0; > > for (;;) { > @@ -410,8 +410,7 @@ int fwts_cpu_consume_start(void) > if ((fwts_cpu_pids = (pid_t*)calloc(fwts_cpu_num, sizeof(pid_t))) == NULL) > return FWTS_ERROR; > > - signal(SIGINT, fwts_cpu_sigint_handler); > - > + fwts_sig_handler_set(SIGINT, fwts_cpu_sigint_handler, NULL); > for (i=0;i<fwts_cpu_num;i++) { > pid_t pid; > > diff --git a/src/lib/src/fwts_ioport.c b/src/lib/src/fwts_ioport.c > index e433995..d0d661a 100644 > --- a/src/lib/src/fwts_ioport.c > +++ b/src/lib/src/fwts_ioport.c > @@ -27,6 +27,7 @@ > #include <setjmp.h> > > static sigjmp_buf jmpbuf; > +static struct sigaction old_action; > > /* > * If we hit a SIGSEGV then the port read > @@ -37,7 +38,7 @@ static void segv_handler(int dummy) > { > FWTS_UNUSED(dummy); > > - signal(SIGSEGV, SIG_DFL); > + fwts_sig_handler_restore(SIGSEGV, &old_action); > siglongjmp(jmpbuf, 1); > } > > @@ -50,9 +51,9 @@ int fwts_inb(uint32_t port, uint8_t *value) > if (sigsetjmp(jmpbuf, 1) != 0) > return FWTS_ERROR; > > - signal(SIGSEGV, segv_handler); > + fwts_sig_handler_set(SIGSEGV, segv_handler, &old_action); > *value = inb(port); > - signal(SIGSEGV, SIG_DFL); > + fwts_sig_handler_restore(SIGSEGV, &old_action); > > return FWTS_OK; > } > @@ -66,9 +67,9 @@ int fwts_inw(uint32_t port, uint16_t *value) > if (sigsetjmp(jmpbuf, 1) != 0) > return FWTS_ERROR; > > - signal(SIGSEGV, segv_handler); > + fwts_sig_handler_set(SIGSEGV, segv_handler, &old_action); > *value = inw(port); > - signal(SIGSEGV, SIG_DFL); > + fwts_sig_handler_restore(SIGSEGV, &old_action); > > return FWTS_OK; > } > @@ -82,9 +83,9 @@ int fwts_inl(uint32_t port, uint32_t *value) > if (sigsetjmp(jmpbuf, 1) != 0) > return FWTS_ERROR; > > - signal(SIGSEGV, segv_handler); > + fwts_sig_handler_set(SIGSEGV, segv_handler, &old_action); > *value = inl(port); > - signal(SIGSEGV, SIG_DFL); > + fwts_sig_handler_restore(SIGSEGV, &old_action); > > return FWTS_OK; > } > @@ -98,9 +99,9 @@ int fwts_outb(uint32_t port, uint8_t value) > if (sigsetjmp(jmpbuf, 1) != 0) > return FWTS_ERROR; > > - signal(SIGSEGV, segv_handler); > + fwts_sig_handler_set(SIGSEGV, segv_handler, &old_action); > outb(port, value); > - signal(SIGSEGV, SIG_DFL); > + fwts_sig_handler_restore(SIGSEGV, &old_action); > > return FWTS_OK; > } > @@ -114,9 +115,9 @@ int fwts_outw(uint32_t port, uint16_t value) > if (sigsetjmp(jmpbuf, 1) != 0) > return FWTS_ERROR; > > - signal(SIGSEGV, segv_handler); > + fwts_sig_handler_set(SIGSEGV, segv_handler, &old_action); > outw(port, value); > - signal(SIGSEGV, SIG_DFL); > + fwts_sig_handler_restore(SIGSEGV, &old_action); > > return FWTS_OK; > } > @@ -130,9 +131,9 @@ int fwts_outl(uint32_t port, uint32_t value) > if (sigsetjmp(jmpbuf, 1) != 0) > return FWTS_ERROR; > > - signal(SIGSEGV, segv_handler); > + fwts_sig_handler_set(SIGSEGV, segv_handler, &old_action); > outl(port, value); > - signal(SIGSEGV, SIG_DFL); > + fwts_sig_handler_restore(SIGSEGV, &old_action); > > return FWTS_OK; > } > diff --git a/src/lib/src/fwts_safe_mem.c b/src/lib/src/fwts_safe_mem.c > index 6fcfe1f..4d75ab3 100644 > --- a/src/lib/src/fwts_safe_mem.c > +++ b/src/lib/src/fwts_safe_mem.c > @@ -23,6 +23,7 @@ > #include "fwts.h" > > static sigjmp_buf jmpbuf; > +static struct sigaction old_action; > > /* > * If we hit a SIGSEGV then the port read > @@ -33,7 +34,7 @@ static void segv_handler(int dummy) > { > FWTS_UNUSED(dummy); > > - signal(SIGSEGV, SIG_DFL); > + fwts_sig_handler_restore(SIGSEGV, &old_action); > siglongjmp(jmpbuf, 1); > } > > @@ -48,9 +49,9 @@ int fwts_safe_memcpy(void *dst, const void *src, const size_t n) > if (sigsetjmp(jmpbuf, 1) != 0) > return FWTS_ERROR; > > - signal(SIGSEGV, segv_handler); > + fwts_sig_handler_set(SIGSEGV, segv_handler, &old_action); > memcpy(dst, src, n); > - signal(SIGSEGV, SIG_DFL); > + fwts_sig_handler_restore(SIGSEGV, &old_action); > > return FWTS_OK; > } > diff --git a/src/main.c b/src/main.c > index 56981d5..ef67b4c 100644 > --- a/src/main.c > +++ b/src/main.c > @@ -24,6 +24,8 @@ > > int main(int argc, char **argv) > { > + (void)fwts_fault_catch(); > + > if (fwts_framework_args(argc, argv) == FWTS_OK) > exit(EXIT_SUCCESS); > else Acked-by: Ivan Hu <ivan.hu@canonical.com>
diff --git a/src/lib/include/fwts.h b/src/lib/include/fwts.h index d98932b..d5fc231 100644 --- a/src/lib/include/fwts.h +++ b/src/lib/include/fwts.h @@ -35,6 +35,7 @@ #define FWTS_JSON_DATA_PATH DATAROOTDIR "/fwts" #include "fwts_version.h" +#include "fwts_backtrace.h" #include "fwts_types.h" #include "fwts_binpaths.h" #include "fwts_framework.h" diff --git a/src/lib/include/fwts_backtrace.h b/src/lib/include/fwts_backtrace.h new file mode 100644 index 0000000..e0b0dde --- /dev/null +++ b/src/lib/include/fwts_backtrace.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2010-2014 Canonical + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ +#ifndef __FWTS_BACKTRACE__ +#define __FWTS_BACKTRACE__ + +#include <signal.h> + +void fwts_print_backtrace(void); +int fwts_fault_catch(void); +void fwts_sig_handler_set(int signum, void (*handler)(int), struct sigaction *old_action); +void fwts_sig_handler_restore(int signum, struct sigaction *old_action); + +#endif diff --git a/src/lib/src/Makefile.am b/src/lib/src/Makefile.am index 33f81f4..2f0bbcc 100644 --- a/src/lib/src/Makefile.am +++ b/src/lib/src/Makefile.am @@ -29,6 +29,7 @@ libfwts_la_SOURCES = \ fwts_acpid.c \ fwts_alloc.c \ fwts_args.c \ + fwts_backtrace.c \ fwts_battery.c \ fwts_binpaths.c \ fwts_button.c \ diff --git a/src/lib/src/fwts_backtrace.c b/src/lib/src/fwts_backtrace.c new file mode 100644 index 0000000..eb84b48 --- /dev/null +++ b/src/lib/src/fwts_backtrace.c @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2010-2014 Canonical + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ +#include <execinfo.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdbool.h> +#include <inttypes.h> +#include <string.h> +#include <signal.h> +#include <setjmp.h> + +#include "fwts.h" + +#define BACK_TRACE_SIZE (512) + +static sigjmp_buf jmp_env; +static void *bt_buff[BACK_TRACE_SIZE]; +static size_t bt_size = 0; + +/* + * fwts_print_backtrace() + * parse symbol backtrace and dump it in a easy + * to read format. + */ +void fwts_print_backtrace(void) +{ + char **bt_strings; + size_t i; + + fprintf(stderr, "Backtrace:\n"); + if (bt_size) { + bt_strings = backtrace_symbols(bt_buff, bt_size); + + for (i = 0; i < bt_size; i++) { + /* + * convert trace into output in form: + * 0x00007fb04a493ec5 /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf5) + */ + char *addrstr = strstr(bt_strings[i], " [0x"); + if (addrstr) { + uint64_t addr; + + *addrstr = '\0'; + addr = (uint64_t)strtoull(addrstr + 2, NULL, 16); + fprintf(stderr, "0x%16.16" PRIx64 " %s\n", addr, bt_strings[i]); + } + } + free(bt_strings); + } else { + fprintf(stderr, " No data\n"); + } + fprintf(stderr, "\n"); + fflush(stdout); +} + +/* + * fwts_fault_handler() + * catch a signal, save stack dump, jmp back or abort + */ +static void fwts_fault_handler(int signum) +{ + static bool already_handled = false; + + /* Capture backtrace and jmp back */ + + if (!already_handled) { + already_handled = true; + /* Capture backtrace from this stack context */ + bt_size = backtrace(bt_buff, BACK_TRACE_SIZE); + /* Jmp back to the sigsetjmp context */ + siglongjmp(jmp_env, signum); + } + /* We've hit a fault before, so abort */ + _exit(EXIT_FAILURE); +} + +/* + * fwts_sig_handler_set() + * helper to set signal handler + */ +void fwts_sig_handler_set(int signum, void (*handler)(int), struct sigaction *old_action) +{ + struct sigaction new_action; + + memset(&new_action, 0, sizeof new_action); + new_action.sa_handler = handler; + sigemptyset(&new_action.sa_mask); + + (void)sigaction(signum, &new_action, old_action); +} + +/* + * fwts_sig_handler_restore() + * helper to restore signal handler + */ +void fwts_sig_handler_restore(int signum, struct sigaction *old_action) +{ + (void)sigaction(signum, old_action, NULL); +} + +/* + * fwts_fault_catch() + * catch segfaults and bus errors, dump stack + * trace so we can see what's causing them + */ +int fwts_fault_catch(void) +{ + int ret; + + /* Trap segfaults and bus errors */ + fwts_sig_handler_set(SIGSEGV, fwts_fault_handler, NULL); + fwts_sig_handler_set(SIGBUS, fwts_fault_handler, NULL); + + ret = sigsetjmp(jmp_env, 1); + /* + * We reach here with ret == SIGNUM if the fault handler + * longjmps back to here. Or we reach here with + * ret == 0 if sigsetjmp has set the jmp_env up + * correctly. + */ + if (ret) { + fprintf(stderr, "\nCaught SIGNAL %d (%s), aborting.\n", + ret, strsignal(ret)); + fwts_print_backtrace(); + exit(EXIT_FAILURE); + } + return FWTS_OK; +} diff --git a/src/lib/src/fwts_cpu.c b/src/lib/src/fwts_cpu.c index 9cbbdef..fe78ee5 100644 --- a/src/lib/src/fwts_cpu.c +++ b/src/lib/src/fwts_cpu.c @@ -377,7 +377,7 @@ int fwts_cpu_performance( */ static void fwts_cpu_consume_cycles(void) { - signal(SIGUSR1, fwts_cpu_consume_sighandler); + fwts_sig_handler_set(SIGUSR1, fwts_cpu_consume_sighandler, NULL); uint64_t i = 0; for (;;) { @@ -410,8 +410,7 @@ int fwts_cpu_consume_start(void) if ((fwts_cpu_pids = (pid_t*)calloc(fwts_cpu_num, sizeof(pid_t))) == NULL) return FWTS_ERROR; - signal(SIGINT, fwts_cpu_sigint_handler); - + fwts_sig_handler_set(SIGINT, fwts_cpu_sigint_handler, NULL); for (i=0;i<fwts_cpu_num;i++) { pid_t pid; diff --git a/src/lib/src/fwts_ioport.c b/src/lib/src/fwts_ioport.c index e433995..d0d661a 100644 --- a/src/lib/src/fwts_ioport.c +++ b/src/lib/src/fwts_ioport.c @@ -27,6 +27,7 @@ #include <setjmp.h> static sigjmp_buf jmpbuf; +static struct sigaction old_action; /* * If we hit a SIGSEGV then the port read @@ -37,7 +38,7 @@ static void segv_handler(int dummy) { FWTS_UNUSED(dummy); - signal(SIGSEGV, SIG_DFL); + fwts_sig_handler_restore(SIGSEGV, &old_action); siglongjmp(jmpbuf, 1); } @@ -50,9 +51,9 @@ int fwts_inb(uint32_t port, uint8_t *value) if (sigsetjmp(jmpbuf, 1) != 0) return FWTS_ERROR; - signal(SIGSEGV, segv_handler); + fwts_sig_handler_set(SIGSEGV, segv_handler, &old_action); *value = inb(port); - signal(SIGSEGV, SIG_DFL); + fwts_sig_handler_restore(SIGSEGV, &old_action); return FWTS_OK; } @@ -66,9 +67,9 @@ int fwts_inw(uint32_t port, uint16_t *value) if (sigsetjmp(jmpbuf, 1) != 0) return FWTS_ERROR; - signal(SIGSEGV, segv_handler); + fwts_sig_handler_set(SIGSEGV, segv_handler, &old_action); *value = inw(port); - signal(SIGSEGV, SIG_DFL); + fwts_sig_handler_restore(SIGSEGV, &old_action); return FWTS_OK; } @@ -82,9 +83,9 @@ int fwts_inl(uint32_t port, uint32_t *value) if (sigsetjmp(jmpbuf, 1) != 0) return FWTS_ERROR; - signal(SIGSEGV, segv_handler); + fwts_sig_handler_set(SIGSEGV, segv_handler, &old_action); *value = inl(port); - signal(SIGSEGV, SIG_DFL); + fwts_sig_handler_restore(SIGSEGV, &old_action); return FWTS_OK; } @@ -98,9 +99,9 @@ int fwts_outb(uint32_t port, uint8_t value) if (sigsetjmp(jmpbuf, 1) != 0) return FWTS_ERROR; - signal(SIGSEGV, segv_handler); + fwts_sig_handler_set(SIGSEGV, segv_handler, &old_action); outb(port, value); - signal(SIGSEGV, SIG_DFL); + fwts_sig_handler_restore(SIGSEGV, &old_action); return FWTS_OK; } @@ -114,9 +115,9 @@ int fwts_outw(uint32_t port, uint16_t value) if (sigsetjmp(jmpbuf, 1) != 0) return FWTS_ERROR; - signal(SIGSEGV, segv_handler); + fwts_sig_handler_set(SIGSEGV, segv_handler, &old_action); outw(port, value); - signal(SIGSEGV, SIG_DFL); + fwts_sig_handler_restore(SIGSEGV, &old_action); return FWTS_OK; } @@ -130,9 +131,9 @@ int fwts_outl(uint32_t port, uint32_t value) if (sigsetjmp(jmpbuf, 1) != 0) return FWTS_ERROR; - signal(SIGSEGV, segv_handler); + fwts_sig_handler_set(SIGSEGV, segv_handler, &old_action); outl(port, value); - signal(SIGSEGV, SIG_DFL); + fwts_sig_handler_restore(SIGSEGV, &old_action); return FWTS_OK; } diff --git a/src/lib/src/fwts_safe_mem.c b/src/lib/src/fwts_safe_mem.c index 6fcfe1f..4d75ab3 100644 --- a/src/lib/src/fwts_safe_mem.c +++ b/src/lib/src/fwts_safe_mem.c @@ -23,6 +23,7 @@ #include "fwts.h" static sigjmp_buf jmpbuf; +static struct sigaction old_action; /* * If we hit a SIGSEGV then the port read @@ -33,7 +34,7 @@ static void segv_handler(int dummy) { FWTS_UNUSED(dummy); - signal(SIGSEGV, SIG_DFL); + fwts_sig_handler_restore(SIGSEGV, &old_action); siglongjmp(jmpbuf, 1); } @@ -48,9 +49,9 @@ int fwts_safe_memcpy(void *dst, const void *src, const size_t n) if (sigsetjmp(jmpbuf, 1) != 0) return FWTS_ERROR; - signal(SIGSEGV, segv_handler); + fwts_sig_handler_set(SIGSEGV, segv_handler, &old_action); memcpy(dst, src, n); - signal(SIGSEGV, SIG_DFL); + fwts_sig_handler_restore(SIGSEGV, &old_action); return FWTS_OK; } diff --git a/src/main.c b/src/main.c index 56981d5..ef67b4c 100644 --- a/src/main.c +++ b/src/main.c @@ -24,6 +24,8 @@ int main(int argc, char **argv) { + (void)fwts_fault_catch(); + if (fwts_framework_args(argc, argv) == FWTS_OK) exit(EXIT_SUCCESS); else