From 27a4852201a41e7d6f8098cc05b7b0949ebc6af4 Mon Sep 17 00:00:00 2001 From: Tristan Gingold Date: Sun, 22 Nov 2015 19:02:05 +0100 Subject: backtrace: add support for windows and for llvm (via libbacktrace). --- src/grt/config/clock.c | 2 -- src/grt/config/jumps.c | 18 ++++++++++--- src/grt/config/win32.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 79 insertions(+), 9 deletions(-) (limited to 'src/grt/config') diff --git a/src/grt/config/clock.c b/src/grt/config/clock.c index 242af60..8f5d26f 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 00e17d3..2170943 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 63d11a2..79935e6 100644 --- a/src/grt/config/win32.c +++ b/src/grt/config/win32.c @@ -25,6 +25,8 @@ */ #include +#include +#include #include #include #include @@ -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 @@ -165,4 +226,3 @@ void __gnat_raise_program_error(void) abort (); } #endif - -- cgit