diff options
author | Tristan Gingold | 2015-11-18 21:45:45 +0100 |
---|---|---|
committer | Tristan Gingold | 2015-11-19 05:47:59 +0100 |
commit | 92b0b82ea32982b94eb8bf19a0b498d92053fffe (patch) | |
tree | 70b04f103d145dc01d31870e50b5e6a654dc20e0 /src/grt/config | |
parent | ff4bc5fb13a997a1d00596578b6d7deb5c0b0da6 (diff) | |
download | ghdl-92b0b82ea32982b94eb8bf19a0b498d92053fffe.tar.gz ghdl-92b0b82ea32982b94eb8bf19a0b498d92053fffe.tar.bz2 ghdl-92b0b82ea32982b94eb8bf19a0b498d92053fffe.zip |
Add symbolizer (for mcode).
Display a backtrace in case of failed check or assert failure.
Diffstat (limited to 'src/grt/config')
-rw-r--r-- | src/grt/config/grt_itf.h | 40 | ||||
-rw-r--r-- | src/grt/config/jumps.c | 104 | ||||
-rw-r--r-- | src/grt/config/win32.c | 17 |
3 files changed, 136 insertions, 25 deletions
diff --git a/src/grt/config/grt_itf.h b/src/grt/config/grt_itf.h new file mode 100644 index 0000000..1b17c3a --- /dev/null +++ b/src/grt/config/grt_itf.h @@ -0,0 +1,40 @@ +/* Declarations to interface with Ada code. + Copyright (C) 2015 Tristan Gingold. + + GHDL 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, or (at your option) any later + version. + + GHDL 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 GCC; see the file COPYING. If not, write to the Free + Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. + + As a special exception, if other files instantiate generics from this + unit, or you link this unit with other files to produce an executable, + this unit does not by itself cause the resulting executable to be + covered by the GNU General Public License. This exception does not + however invalidate any other reasons why the executable file might be + covered by the GNU Public License. +*/ + +struct backtrace_addrs +{ + int size; + int skip; + void *addrs[32]; +}; + +void grt_save_backtrace (struct backtrace_addrs *bt, int skip); + +extern void grt_overflow_error (struct backtrace_addrs *bt); +extern void grt_null_access_error (struct backtrace_addrs *bt); + +void __ghdl_maybe_return_via_longjump (int val); +int __ghdl_run_through_longjump (int (*func)(void)); diff --git a/src/grt/config/jumps.c b/src/grt/config/jumps.c index a544f83..00e17d3 100644 --- a/src/grt/config/jumps.c +++ b/src/grt/config/jumps.c @@ -29,11 +29,17 @@ #include <signal.h> #include <fcntl.h> -#if defined (__linux__) && defined (__i386__) -/* On i386/Linux, the context must be inspected. */ +#if defined (__linux__) || defined (__APPLE__) +#define HAVE_BACKTRACE 1 #include <sys/ucontext.h> #endif +#ifdef HAVE_BACKTRACE +#include <execinfo.h> +#endif + +#include "grt_itf.h" + /* There is a simple setjmp/longjmp mechanism used to report failures. We have the choice between 3 mechanisms: * USE_BUITLIN_SJLJ: gcc builtin setjmp/longjmp, very fast but gcc specific. @@ -70,49 +76,89 @@ typedef jmp_buf JMP_BUF; static int run_env_en; static JMP_BUF run_env; -extern void grt_overflow_error (void); -extern void grt_null_access_error (void); - #ifdef __APPLE__ #define NEED_SIGFPE_HANDLER +#define NEED_SIGBUS_HANDLER #endif static struct sigaction prev_sigfpe_act; +#ifdef NEED_SIGFPE_HANDLER +static struct sigaction prev_sigsegv_act; +#endif +#ifdef NEED_SIGBUS_HANDLER +static struct sigaction prev_sigbus_act; +#endif + +static void +get_bt_from_ucontext (void *uctxt, struct backtrace_addrs *bt) +{ + void *pc = NULL; + int i; + +#ifdef HAVE_BACKTRACE + bt->size = backtrace (bt->addrs, sizeof (bt->addrs) / sizeof (void *)); + bt->skip = 0; +#else + bt->size = 0; + return; +#endif + +#if defined (__linux__) && defined (__x86_64__) + ucontext *u = (ucontext *)uctxt; + pc = (void *)u->uc_mcontext.gregs[REG_RIP]; +#endif +#if defined (__APPLE__) && defined (__i386__) + ucontext_t *u = (ucontext_t *)uctxt; + pc = (void *)u->uc_mcontext->__ss.__eip; + bt->skip = 3; /* This frame + sighandler + trampoline + marker - pc. */ + bt->addrs[3] = pc; +#endif +} + /* Handler for SIGFPE signal. It is also raised in case of overflow (i386 linux). */ -static void grt_overflow_handler (int signo, siginfo_t *info, void *ptr) +static void +grt_overflow_handler (int signo, siginfo_t *info, void *ptr) { - grt_overflow_error (); -} + struct backtrace_addrs bt; -static struct sigaction prev_sigsegv_act; + get_bt_from_ucontext (ptr, &bt); + grt_overflow_error (&bt); +} /* Posix handler for overflow. This is used only by mcode. */ -static void grt_sigsegv_handler (int signo, siginfo_t *info, void *ptr) +static void +grt_sigsegv_handler (int signo, siginfo_t *info, void *ptr) { -#if defined (__linux__) && defined (__i386__) - ucontext_t *uctxt = (ucontext_t *)ptr; + struct backtrace_addrs bt; - /* Linux generates a SIGSEGV (!) for an overflow exception. */ - if (uctxt->uc_mcontext.gregs[REG_TRAPNO] == 4) + get_bt_from_ucontext (ptr, &bt); + +#if defined (__linux__) && defined (__i386__) + if (signo == SIGSEGV) { - grt_overflow_error (); + ucontext_t *uctxt = (ucontext_t *)ptr; + + /* Linux generates a SIGSEGV (!) for an overflow exception. */ + if (uctxt->uc_mcontext.gregs[REG_TRAPNO] == 4) + grt_overflow_error (&bt); } #endif /* We loose. */ - grt_null_access_error (); + grt_null_access_error (&bt); } -static void grt_signal_setup (void) +static void +grt_signal_setup (void) { { struct sigaction sigsegv_act; sigsegv_act.sa_sigaction = &grt_sigsegv_handler; sigemptyset (&sigsegv_act.sa_mask); - sigsegv_act.sa_flags = SA_ONSTACK | SA_SIGINFO; + sigsegv_act.sa_flags = SA_SIGINFO; #ifdef SA_ONESHOT sigsegv_act.sa_flags |= SA_ONESHOT; #elif defined (SA_RESETHAND) @@ -122,6 +168,10 @@ static void grt_signal_setup (void) /* We don't care about the return status. If the handler is not installed, then some feature are lost. */ sigaction (SIGSEGV, &sigsegv_act, &prev_sigsegv_act); + +#ifdef NEED_SIGBUS_HANDLER + sigaction (SIGBUS, &sigsegv_act, &prev_sigbus_act); +#endif } #ifdef NEED_SIGFPE_HANDLER @@ -137,10 +187,15 @@ static void grt_signal_setup (void) #endif } -static void grt_signal_restore (void) +static void +grt_signal_restore (void) { sigaction (SIGSEGV, &prev_sigsegv_act, NULL); +#ifdef NEED_SIGBUS_HANDLER + sigaction (SIGBUS, &prev_sigbus_act, NULL); +#endif + #ifdef NEED_SIGFPE_HANDLER sigaction (SIGFPE, &prev_sigfpe_act, NULL); #endif @@ -167,3 +222,14 @@ __ghdl_run_through_longjump (int (*func)(void)) run_env_en = 0; return res; } + +void +grt_save_backtrace (struct backtrace_addrs *bt, int skip) +{ +#ifdef HAVE_BACKTRACE + bt->size = backtrace (bt->addrs, sizeof (bt->addrs) / sizeof (void *)); + bt->skip = skip + 1; +#else + bt->size = 0; +#endif +} diff --git a/src/grt/config/win32.c b/src/grt/config/win32.c index 869c7ca..63d11a2 100644 --- a/src/grt/config/win32.c +++ b/src/grt/config/win32.c @@ -30,13 +30,11 @@ #include <assert.h> #include <excpt.h> +#include "grt_itf.h" + static int run_env_en; static jmp_buf run_env; -extern void grt_overflow_error (void); -extern void grt_null_access_error (void); -void __ghdl_maybe_return_via_longjump (int val); - static EXCEPTION_DISPOSITION ghdl_SEH_handler (struct _EXCEPTION_RECORD* ExceptionRecord, void *EstablisherFrame, @@ -60,7 +58,8 @@ ghdl_SEH_handler (struct _EXCEPTION_RECORD* ExceptionRecord, switch (ExceptionRecord->ExceptionCode) { case EXCEPTION_ACCESS_VIOLATION: - grt_null_access_error (); + /* Pc is ExceptionRecord->ExceptionAddress. */ + grt_null_access_error (NULL); break; case EXCEPTION_FLT_DENORMAL_OPERAND: @@ -77,7 +76,7 @@ ghdl_SEH_handler (struct _EXCEPTION_RECORD* ExceptionRecord, break; case EXCEPTION_INT_OVERFLOW: - grt_overflow_error (); + grt_overflow_error (NULL); break; case EXCEPTION_STACK_OVERFLOW: @@ -132,6 +131,12 @@ __ghdl_run_through_longjump (int (*func)(void)) return res; } +void +grt_save_backtrace (struct backtrace_addrs *bt, int skip) +{ + bt->size = 0; +} + #include <math.h> double acosh (double x) |