diff options
author | Tristan Gingold <gingold@adacore.com> | 2015-11-22 19:02:05 +0100 |
---|---|---|
committer | Tristan Gingold <gingold@adacore.com> | 2015-11-22 19:02:05 +0100 |
commit | 27a4852201a41e7d6f8098cc05b7b0949ebc6af4 (patch) | |
tree | 91e6effe2be75fedb2e39e2eb374975c5666f206 /src/grt/config/win32.c | |
parent | 92b0b82ea32982b94eb8bf19a0b498d92053fffe (diff) | |
download | ghdl-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/win32.c')
-rw-r--r-- | src/grt/config/win32.c | 68 |
1 files changed, 64 insertions, 4 deletions
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 - |