Skip to content
Snippets Groups Projects
Commit ce2b3084 authored by Craig Tiller's avatar Craig Tiller
Browse files

Get stack traces in crash dumps working for Windows

parent f4f57f07
No related branches found
No related tags found
No related merge requests found
...@@ -38,6 +38,8 @@ ...@@ -38,6 +38,8 @@
#include "src/core/support/string.h" #include "src/core/support/string.h"
#include <stdlib.h> #include <stdlib.h>
#include <signal.h> #include <signal.h>
#include <stdio.h>
#include <stdbool.h>
double g_fixture_slowdown_factor = 1.0; double g_fixture_slowdown_factor = 1.0;
...@@ -52,14 +54,115 @@ static unsigned seed(void) { return _getpid(); } ...@@ -52,14 +54,115 @@ static unsigned seed(void) { return _getpid(); }
#endif #endif
#if GPR_WINDOWS_CRASH_HANDLER #if GPR_WINDOWS_CRASH_HANDLER
LONG crash_handler(struct _EXCEPTION_POINTERS *ex_info) { #include "DbgHelp.h"
gpr_log(GPR_DEBUG, "Exception handler called, dumping information");
while (ex_info->ExceptionRecord) { #pragma comment(lib, "dbghelp.lib")
DWORD code = ex_info->ExceptionRecord->ExceptionCode;
DWORD flgs = ex_info->ExceptionRecord->ExceptionFlags; static void print_current_stack() {
PVOID addr = ex_info->ExceptionRecord->ExceptionAddress; typedef USHORT(WINAPI *CaptureStackBackTraceType)(__in ULONG, __in ULONG, __out PVOID*, __out_opt PULONG);
gpr_log("code: %x - flags: %d - address: %p", code, flgs, addr); CaptureStackBackTraceType func = (CaptureStackBackTraceType)(GetProcAddress(LoadLibrary(L"kernel32.dll"), "RtlCaptureStackBackTrace"));
ex_info->ExceptionRecord = ex_info->ExceptionRecord->ExceptionRecord;
if (func == NULL)
return; // WOE 29.SEP.2010
// Quote from Microsoft Documentation:
// ## Windows Server 2003 and Windows XP:
// ## The sum of the FramesToSkip and FramesToCapture parameters must be less than 63.
#define MAX_CALLERS 62
void * callers_stack[MAX_CALLERS];
unsigned short frames;
SYMBOL_INFOW * symbol;
HANDLE process;
process = GetCurrentProcess();
SymInitialize(process, NULL, TRUE);
frames = (func)(0, MAX_CALLERS, callers_stack, NULL);
symbol = (SYMBOL_INFOW *)calloc(sizeof(SYMBOL_INFOW) + 256 * sizeof(char), 1);
symbol->MaxNameLen = 255;
symbol->SizeOfStruct = sizeof(SYMBOL_INFOW);
const unsigned short MAX_CALLERS_SHOWN = 32;
frames = frames < MAX_CALLERS_SHOWN ? frames : MAX_CALLERS_SHOWN;
for (unsigned int i = 0; i < frames; i++) {
SymFromAddrW(process, (DWORD64)(callers_stack[i]), 0, symbol);
fwprintf(stderr, L"*** %d: %016I64LX %ls - 0x%0X\n", i, (DWORD64)callers_stack[i], symbol->Name, symbol->Address);
}
free(symbol);
}
static void print_stack_from_context(CONTEXT c) {
STACKFRAME s; // in/out stackframe
memset(&s, 0, sizeof(s));
DWORD imageType;
#ifdef _M_IX86
// normally, call ImageNtHeader() and use machine info from PE header
imageType = IMAGE_FILE_MACHINE_I386;
s.AddrPC.Offset = c.Eip;
s.AddrPC.Mode = AddrModeFlat;
s.AddrFrame.Offset = c.Ebp;
s.AddrFrame.Mode = AddrModeFlat;
s.AddrStack.Offset = c.Esp;
s.AddrStack.Mode = AddrModeFlat;
#elif _M_X64
imageType = IMAGE_FILE_MACHINE_AMD64;
s.AddrPC.Offset = c.Rip;
s.AddrPC.Mode = AddrModeFlat;
s.AddrFrame.Offset = c.Rsp;
s.AddrFrame.Mode = AddrModeFlat;
s.AddrStack.Offset = c.Rsp;
s.AddrStack.Mode = AddrModeFlat;
#elif _M_IA64
imageType = IMAGE_FILE_MACHINE_IA64;
s.AddrPC.Offset = c.StIIP;
s.AddrPC.Mode = AddrModeFlat;
s.AddrFrame.Offset = c.IntSp;
s.AddrFrame.Mode = AddrModeFlat;
s.AddrBStore.Offset = c.RsBSP;
s.AddrBStore.Mode = AddrModeFlat;
s.AddrStack.Offset = c.IntSp;
s.AddrStack.Mode = AddrModeFlat;
#else
#error "Platform not supported!"
#endif
HANDLE process = GetCurrentProcess();
HANDLE thread = GetCurrentThread();
SYMBOL_INFOW *symbol = (SYMBOL_INFOW *)calloc(sizeof(SYMBOL_INFOW) + 256 * sizeof(char), 1);
symbol->MaxNameLen = 255;
symbol->SizeOfStruct = sizeof(SYMBOL_INFOW);
while (StackWalk(imageType,
process,
thread,
&s,
&c,
0,
SymFunctionTableAccess,
SymGetModuleBase,
0)) {
BOOL has_symbol = SymFromAddrW(process, (DWORD64)(s.AddrPC.Offset), 0, symbol);
fwprintf(stderr, L"*** %016I64LX %ls - 0x%0X\n", (DWORD64)(s.AddrPC.Offset), has_symbol ? symbol->Name : L"<<no symbol>>", symbol->Address);
}
free(symbol);
}
static LONG crash_handler(struct _EXCEPTION_POINTERS *ex_info) {
fprintf(stderr, "Exception handler called, dumping information\n");
bool try_to_print_stack = true;
PEXCEPTION_RECORD exrec = ex_info->ExceptionRecord;
while (exrec) {
DWORD code = exrec->ExceptionCode;
DWORD flgs = exrec->ExceptionFlags;
PVOID addr = exrec->ExceptionAddress;
if (code == EXCEPTION_STACK_OVERFLOW) try_to_print_stack = false;
fprintf(stderr, "code: %x - flags: %d - address: %p\n", code, flgs, addr);
exrec = exrec->ExceptionRecord;
}
if (try_to_print_stack) {
print_stack_from_context(*ex_info->ContextRecord);
} }
if (IsDebuggerPresent()) { if (IsDebuggerPresent()) {
__debugbreak(); __debugbreak();
...@@ -69,8 +172,9 @@ LONG crash_handler(struct _EXCEPTION_POINTERS *ex_info) { ...@@ -69,8 +172,9 @@ LONG crash_handler(struct _EXCEPTION_POINTERS *ex_info) {
return EXCEPTION_EXECUTE_HANDLER; return EXCEPTION_EXECUTE_HANDLER;
} }
void abort_handler(int sig) { static void abort_handler(int sig) {
gpr_log(GPR_DEBUG, "Abort handler called."); fprintf(stderr, "Abort handler called.");
print_current_stack(NULL);
if (IsDebuggerPresent()) { if (IsDebuggerPresent()) {
__debugbreak(); __debugbreak();
} else { } else {
...@@ -79,6 +183,9 @@ void abort_handler(int sig) { ...@@ -79,6 +183,9 @@ void abort_handler(int sig) {
} }
static void install_crash_handler() { static void install_crash_handler() {
if (!SymInitialize(GetCurrentProcess(), NULL, TRUE)) {
fprintf(stderr, "SymInitialize failed: %d", GetLastError());
}
SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)crash_handler); SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)crash_handler);
_set_abort_behavior(0, _WRITE_ABORT_MSG); _set_abort_behavior(0, _WRITE_ABORT_MSG);
_set_abort_behavior(0, _CALL_REPORTFAULT); _set_abort_behavior(0, _CALL_REPORTFAULT);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment