#if defined(WIN32) && defined(SNMALLOC_CI_BUILD) # include # include # include # include # include // Has to come after the PAL. # include # pragma comment(lib, "dbghelp.lib") void print_stack_trace() { DWORD error; HANDLE hProcess = GetCurrentProcess(); char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)]; PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO); pSymbol->MaxNameLen = MAX_SYM_NAME; SymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS); if (!SymInitialize(hProcess, NULL, TRUE)) { // SymInitialize failed error = GetLastError(); printf("SymInitialize returned error : %lu\n", error); return; } void* stack[1024]; DWORD count = CaptureStackBackTrace(0, 1024, stack, NULL); IMAGEHLP_LINE64 line; line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); for (int i = 0; count > 0; count--, i++) { DWORD64 dwDisplacement = 0; DWORD64 dwAddress = (DWORD64)stack[i]; if (SymFromAddr(hProcess, dwAddress, &dwDisplacement, pSymbol)) { DWORD dwDisplacement2 = 0; if (SymGetLineFromAddr64(hProcess, dwAddress, &dwDisplacement2, &line)) { std::cerr << "Frame: " << pSymbol->Name << " (" << line.FileName << ": " << line.LineNumber << ")" << std::endl; } else { std::cerr << "Frame: " << pSymbol->Name << std::endl; } } else { error = GetLastError(); std::cerr << "SymFromAddr returned error : " << error << std::endl; } } } void _cdecl error(int signal) { UNUSED(signal); puts("*****ABORT******"); print_stack_trace(); _exit(1); } # define CALL_LAST 0 LONG WINAPI VectoredHandler(struct _EXCEPTION_POINTERS* ExceptionInfo) { UNUSED(ExceptionInfo); puts("*****UNHANDLED EXCEPTION******"); print_stack_trace(); _exit(1); } void setup() { // Disable abort dialog box in CI builds. _set_error_mode(_OUT_TO_STDERR); _set_abort_behavior(0, _WRITE_ABORT_MSG); signal(SIGABRT, error); AddVectoredExceptionHandler(CALL_LAST, VectoredHandler); } #else void setup() {} #endif