Merge pull request #23420 from jtattermusch/win_better_debugging2

Improve windows crash handler for tests
pull/23856/head
Jan Tattermusch 5 years ago committed by GitHub
commit 35f64979da
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 83
      test/core/util/test_config.cc

@ -61,45 +61,7 @@ static unsigned seed(void) { return (unsigned)_getpid(); }
#pragma comment(lib, "dbghelp.lib") #pragma comment(lib, "dbghelp.lib")
#endif #endif
static void print_current_stack() { static void print_stack_from_context(HANDLE thread, CONTEXT c) {
typedef USHORT(WINAPI * CaptureStackBackTraceType)(
__in ULONG, __in ULONG, __out PVOID*, __out_opt PULONG);
CaptureStackBackTraceType func = (CaptureStackBackTraceType)(GetProcAddress(
LoadLibrary(_T("kernel32.dll")), "RtlCaptureStackBackTrace"));
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(wchar_t), 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: %016I64X %ls - %016I64X\n", i,
(DWORD64)callers_stack[i], symbol->Name, (DWORD64)symbol->Address);
fflush(stderr);
}
free(symbol);
}
static void print_stack_from_context(CONTEXT c) {
STACKFRAME s; // in/out stackframe STACKFRAME s; // in/out stackframe
memset(&s, 0, sizeof(s)); memset(&s, 0, sizeof(s));
DWORD imageType; DWORD imageType;
@ -135,26 +97,51 @@ static void print_stack_from_context(CONTEXT c) {
#endif #endif
HANDLE process = GetCurrentProcess(); HANDLE process = GetCurrentProcess();
HANDLE thread = GetCurrentThread();
SYMBOL_INFOW* symbol = SYMBOL_INFOW* symbol =
(SYMBOL_INFOW*)calloc(sizeof(SYMBOL_INFOW) + 256 * sizeof(wchar_t), 1); (SYMBOL_INFOW*)calloc(sizeof(SYMBOL_INFOW) + 256 * sizeof(wchar_t), 1);
symbol->MaxNameLen = 255; symbol->MaxNameLen = 255;
symbol->SizeOfStruct = sizeof(SYMBOL_INFOW); symbol->SizeOfStruct = sizeof(SYMBOL_INFOW);
while (StackWalk(imageType, process, thread, &s, &c, 0, const unsigned short MAX_CALLERS_SHOWN =
SymFunctionTableAccess, SymGetModuleBase, 0)) { 8192; // avoid flooding the stderr if stacktrace is way too long
BOOL has_symbol = for (int frame = 0; frame < MAX_CALLERS_SHOWN &&
SymFromAddrW(process, (DWORD64)(s.AddrPC.Offset), 0, symbol); StackWalk(imageType, process, thread, &s, &c, 0,
fwprintf( SymFunctionTableAccess, SymGetModuleBase, 0);
stderr, L"*** %016I64X %ls - %016I64X\n", (DWORD64)(s.AddrPC.Offset), frame++) {
has_symbol ? symbol->Name : L"<<no symbol>>", (DWORD64)symbol->Address); PWSTR symbol_name = L"<<no symbol>>";
DWORD64 symbol_address = 0;
if (SymFromAddrW(process, (DWORD64)(s.AddrPC.Offset), 0, symbol)) {
symbol_name = symbol->Name;
symbol_address = (DWORD64)symbol->Address;
}
PWSTR file_name = L"<<no line info>>";
int line_number = 0;
IMAGEHLP_LINE64 line;
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
DWORD displacement = 0;
if (SymGetLineFromAddrW64(process, (DWORD64)(s.AddrPC.Offset),
&displacement, &line)) {
file_name = line.FileName;
line_number = (int)line.LineNumber;
}
fwprintf(stderr, L"*** %d: %016I64X %ls - %016I64X (%ls:%d)\n", frame,
(DWORD64)(s.AddrPC.Offset), symbol_name, symbol_address, file_name,
line_number);
fflush(stderr); fflush(stderr);
} }
free(symbol); free(symbol);
} }
static void print_current_stack() {
CONTEXT context;
RtlCaptureContext(&context);
print_stack_from_context(GetCurrentThread(), context);
}
static LONG crash_handler(struct _EXCEPTION_POINTERS* ex_info) { static LONG crash_handler(struct _EXCEPTION_POINTERS* ex_info) {
fprintf(stderr, "Exception handler called, dumping information\n"); fprintf(stderr, "Exception handler called, dumping information\n");
bool try_to_print_stack = true; bool try_to_print_stack = true;
@ -168,7 +155,7 @@ static LONG crash_handler(struct _EXCEPTION_POINTERS* ex_info) {
exrec = exrec->ExceptionRecord; exrec = exrec->ExceptionRecord;
} }
if (try_to_print_stack) { if (try_to_print_stack) {
print_stack_from_context(*ex_info->ContextRecord); print_stack_from_context(GetCurrentThread(), *ex_info->ContextRecord);
} }
if (IsDebuggerPresent()) { if (IsDebuggerPresent()) {
__debugbreak(); __debugbreak();

Loading…
Cancel
Save