aboutsummaryrefslogtreecommitdiffstats
path: root/src/grt/config
diff options
context:
space:
mode:
authorTristan Gingold <gingold@adacore.com>2015-11-22 19:02:05 +0100
committerTristan Gingold <gingold@adacore.com>2015-11-22 19:02:05 +0100
commit27a4852201a41e7d6f8098cc05b7b0949ebc6af4 (patch)
tree91e6effe2be75fedb2e39e2eb374975c5666f206 /src/grt/config
parent92b0b82ea32982b94eb8bf19a0b498d92053fffe (diff)
downloadghdl-27a4852201a41e7d6f8098cc05b7b0949ebc6af4.tar.gz
ghdl-27a4852201a41e7d6f8098cc05b7b0949ebc6af4.tar.bz2
ghdl-27a4852201a41e7d6f8098cc05b7b0949ebc6af4.zip
backtrace: add support for windows and for llvm (via libbacktrace).
Diffstat (limited to 'src/grt/config')
-rw-r--r--src/grt/config/clock.c2
-rw-r--r--src/grt/config/jumps.c18
-rw-r--r--src/grt/config/win32.c68
3 files changed, 79 insertions, 9 deletions
diff --git a/src/grt/config/clock.c b/src/grt/config/clock.c
index 242af604b..8f5d26fc9 100644
--- a/src/grt/config/clock.c
+++ b/src/grt/config/clock.c
@@ -34,8 +34,6 @@ grt_get_clk_tck (void)
void
grt_get_times (int *wall, int *user, int *sys)
{
- clock_t res;
-
*wall = clock ();
*user = 0;
*sys = 0;
diff --git a/src/grt/config/jumps.c b/src/grt/config/jumps.c
index 00e17d37d..2170943d6 100644
--- a/src/grt/config/jumps.c
+++ b/src/grt/config/jumps.c
@@ -81,10 +81,10 @@ static JMP_BUF run_env;
#define NEED_SIGBUS_HANDLER
#endif
-static struct sigaction prev_sigfpe_act;
+static struct sigaction prev_sigsegv_act;
#ifdef NEED_SIGFPE_HANDLER
-static struct sigaction prev_sigsegv_act;
+static struct sigaction prev_sigfpe_act;
#endif
#ifdef NEED_SIGBUS_HANDLER
static struct sigaction prev_sigbus_act;
@@ -105,15 +105,27 @@ get_bt_from_ucontext (void *uctxt, struct backtrace_addrs *bt)
#endif
#if defined (__linux__) && defined (__x86_64__)
- ucontext *u = (ucontext *)uctxt;
+ ucontext_t *u = (ucontext_t *)uctxt;
pc = (void *)u->uc_mcontext.gregs[REG_RIP];
#endif
+#if defined (__linux__) && defined (__i386__)
+ ucontext_t *u = (ucontext_t *)uctxt;
+ pc = (void *)u->uc_mcontext.gregs[REG_EIP];
+#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;
+ return;
#endif
+
+ for (i = 0; i < bt->size; i++)
+ if (bt->addrs[i] == pc)
+ {
+ bt->skip = i;
+ break;
+ }
}
/* Handler for SIGFPE signal.
diff --git a/src/grt/config/win32.c b/src/grt/config/win32.c
index 63d11a23e..79935e6f0 100644
--- a/src/grt/config/win32.c
+++ b/src/grt/config/win32.c
@@ -25,6 +25,8 @@
*/
#include <windows.h>
+#include <winbase.h>
+#include <dbghelp.h>
#include <stdio.h>
#include <setjmp.h>
#include <assert.h>
@@ -47,19 +49,74 @@ struct exception_registration
void *handler;
};
+/* Save bactktrace from CTXT to BT, the first SKIP frames are skipped.
+ We need to use StackWalk64 as apparently CaptureStackBackTrace doesn't
+ work over JIT'ed code. I suppose it checks whether PC belongs to the text
+ section of an image. */
+
+static void
+get_bt_from_context (struct backtrace_addrs *bt, CONTEXT *ctxt, int skip)
+{
+ STACKFRAME64 frame;
+ unsigned mach;
+
+ bt->size = 0;
+ bt->skip = 0;
+ memset (&frame, 0, sizeof (frame));
+
+#ifdef __i386__
+ mach = IMAGE_FILE_MACHINE_I386;
+
+ frame.AddrPC.Offset = ctxt->Eip;
+ frame.AddrPC.Mode = AddrModeFlat;
+ frame.AddrFrame.Offset = ctxt->Ebp;
+ frame.AddrFrame.Mode = AddrModeFlat;
+ frame.AddrStack.Offset = ctxt->Esp;
+ frame.AddrStack.Mode = AddrModeFlat;
+
+#elif defined (__x86_64__)
+ mach = IMAGE_FILE_MACHINE_AMD64;
+
+ frame.AddrPC.Offset = ctxt->Rip;
+ frame.AddrPC.Mode = AddrModeFlat;
+ frame.AddrFrame.Offset = ctx->Rsp;
+ frame.AddrFrame.Mode = AddrModeFlat;
+ frame.AddrStack.Offset = ctx->Rsp;
+ frame.AddrStack.Mode = AddrModeFlat;
+
+#else
+# warning "platform not supported"
+ return;
+#endif
+
+ while (bt->size < sizeof (bt->addrs) / sizeof (bt->addrs[0]))
+ {
+ if (skip > 0)
+ skip--;
+ else
+ bt->addrs[bt->size++] = (void *) frame.AddrPC.Offset;
+
+ if (!StackWalk64 (mach, GetCurrentProcess (), GetCurrentThread (),
+ &frame, ctxt, NULL, NULL, NULL, NULL))
+ break;
+ }
+}
+
static EXCEPTION_DISPOSITION
ghdl_SEH_handler (struct _EXCEPTION_RECORD* ExceptionRecord,
void *EstablisherFrame,
struct _CONTEXT* ContextRecord,
void *DispatcherContext)
{
+ struct backtrace_addrs bt;
const char *msg = "";
switch (ExceptionRecord->ExceptionCode)
{
case EXCEPTION_ACCESS_VIOLATION:
/* Pc is ExceptionRecord->ExceptionAddress. */
- grt_null_access_error (NULL);
+ get_bt_from_context (&bt, ContextRecord, 1);
+ grt_null_access_error (&bt);
break;
case EXCEPTION_FLT_DENORMAL_OPERAND:
@@ -76,7 +133,8 @@ ghdl_SEH_handler (struct _EXCEPTION_RECORD* ExceptionRecord,
break;
case EXCEPTION_INT_OVERFLOW:
- grt_overflow_error (NULL);
+ get_bt_from_context (&bt, ContextRecord, 1);
+ grt_overflow_error (&bt);
break;
case EXCEPTION_STACK_OVERFLOW:
@@ -134,7 +192,10 @@ __ghdl_run_through_longjump (int (*func)(void))
void
grt_save_backtrace (struct backtrace_addrs *bt, int skip)
{
- bt->size = 0;
+ CONTEXT ctxt;
+
+ RtlCaptureContext (&ctxt);
+ get_bt_from_context (bt, &ctxt, skip + 1);
}
#include <math.h>
@@ -165,4 +226,3 @@ void __gnat_raise_program_error(void)
abort ();
}
#endif
-