summaryrefslogtreecommitdiff
path: root/src/grt/config/win32.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/grt/config/win32.c')
-rw-r--r--src/grt/config/win32.c68
1 files changed, 64 insertions, 4 deletions
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 <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
-