8#error This file can only be compiled under Windows.
11#pragma comment(lib, "DbgHelp.lib")
28 if(QueryPerformanceCounter(&li) == FALSE)
36 if(QueryPerformanceFrequency(&li) == FALSE)
42 unsigned long long& work_set_size,
43 unsigned long long& work_set_size_peak,
44 unsigned long long& page_file_usage,
45 unsigned long long& page_file_usage_peak)
47 work_set_size = work_set_size_peak = page_file_usage = page_file_usage_peak = 0ull;
50 PROCESS_MEMORY_COUNTERS pmc;
51 memset(&pmc, 0,
sizeof(PROCESS_MEMORY_COUNTERS));
54 if(GetProcessMemoryInfo(GetCurrentProcess(), &pmc,
sizeof(PROCESS_MEMORY_COUNTERS)) != FALSE)
56 work_set_size = pmc.WorkingSetSize;
57 work_set_size_peak = pmc.PeakWorkingSetSize;
58 page_file_usage = pmc.PagefileUsage;
59 page_file_usage_peak = pmc.PeakPagefileUsage;
63 void dump_call_stack(CONTEXT& ctx, FILE* stream)
74 HANDLE prc = GetCurrentProcess();
75 HANDLE thr = GetCurrentThread();
78 IMAGEHLP_LINE64 img_line;
79 img_line.SizeOfStruct =
sizeof(IMAGEHLP_LINE64);
82 memset(&sim, 0,
sizeof(SYMBOL_INFO) + 512);
83 sim.si.MaxNameLen = 512;
84 sim.si.SizeOfStruct =
sizeof(SYMBOL_INFO);
87 SymInitialize(prc,
nullptr, TRUE);
90 STACKFRAME64 stack_frame;
91 memset(&stack_frame, 0,
sizeof(stack_frame));
94 int machine_type = IMAGE_FILE_MACHINE_AMD64;
95 stack_frame.AddrPC.Offset = ctx.Rip;
96 stack_frame.AddrFrame.Offset = ctx.Rbp;
97 stack_frame.AddrStack.Offset = ctx.Rsp;
99 int machine_type = IMAGE_FILE_MACHINE_I386;
100 stack_frame.AddrPC.Offset = ctx.Eip;
101 stack_frame.AddrFrame.Offset = ctx.Ebp;
102 stack_frame.AddrStack.Offset = ctx.Esp;
104 stack_frame.AddrPC.Mode = AddrModeFlat;
105 stack_frame.AddrFrame.Mode = AddrModeFlat;
106 stack_frame.AddrStack.Mode = AddrModeFlat;
112 fprintf(stream,
"\nCall-Stack Back-Trace:\n");
113 fprintf(stream,
"----------------------\n");
116 while (StackWalk64(machine_type, prc, thr, &stack_frame, &ctx,
nullptr,
117 &SymFunctionTableAccess64, &SymGetModuleBase64,
nullptr) != FALSE)
120 addr = stack_frame.AddrPC.Offset;
123 fprintf(stream,
"0x%0*I64X", 2*
int(
sizeof(
void*)), addr);
126 if(SymFromAddr(prc, addr, 0, &sim.si) != FALSE)
129 fprintf(stream,
": '%s'", sim.si.Name);
134 fprintf(stream,
": ???");
138 if(SymGetLineFromAddr64(prc, addr, &line_dsp, &img_line) != FALSE)
141 fprintf(stream,
" ['%s' @ %i]", img_line.FileName, img_line.LineNumber);
145 fprintf(stream,
"\n");
156 RtlCaptureContext(&ctx);
159 dump_call_stack(ctx2, stderr);
162 LONG WINAPI FeatWinExceptionFilter(LPEXCEPTION_POINTERS p)
165 fprintf(stderr,
"\n>>>>> FATAL ERROR <<<<<\n\n");
166 fprintf(stderr,
"Exception at 0x%0*I64X: ", 2*
int(
sizeof(
void*)), (DWORD64)p->ExceptionRecord->ExceptionAddress);
169 switch(p->ExceptionRecord->ExceptionCode)
172 case EXCEPTION_ACCESS_VIOLATION:
174 fprintf(stderr,
"Access Violation when ");
175 if(p->ExceptionRecord->ExceptionInformation[0] == 0)
176 fprintf(stderr,
"reading from");
178 fprintf(stderr,
"writing to");
179 fprintf(stderr,
" 0x%0*I64X\n", 2*
int(
sizeof(
void*)), (DWORD64)p->ExceptionRecord->ExceptionInformation[1]);
181 case EXCEPTION_ILLEGAL_INSTRUCTION:
182 fprintf(stderr,
"Illegal Instruction\n");
184 case EXCEPTION_IN_PAGE_ERROR:
185 fprintf(stderr,
"Page Error\n");
187 case EXCEPTION_STACK_OVERFLOW:
188 fprintf(stderr,
"Stack Overflow\n");
192 fprintf(stderr,
"Error 0x%08X\n", p->ExceptionRecord->ExceptionCode);
197 CONTEXT ctx = *p->ContextRecord;
198 dump_call_stack(ctx, stderr);
201 fprintf(stderr,
"\n>>>>> TERMINATING <<<<<\n");
205 return EXCEPTION_EXECUTE_HANDLER;
211 SetUnhandledExceptionFilter(FeatWinExceptionFilter);
217 SetErrorMode(GetErrorMode() | SEM_FAILCRITICALERRORS|SEM_NOGPFAULTERRORBOX|SEM_NOOPENFILEERRORBOX);
219 _set_abort_behavior(0, _WRITE_ABORT_MSG);
224 return GetCurrentProcessId();
void install_seh_filter()
Installs custom Windows Structured-Exception-Handler filter.
void dump_call_stack_to_stderr()
Dumps the call-stack to stderr.
void query_memory_usage(unsigned long long &work_set_size, unsigned long long &work_set_size_peak, unsigned long long &page_file_usage, unsigned long long &page_file_usage_peak)
Queries memory usage information.
long long query_performance_frequency()
Wraps around the QueryPerformanceCounter function.
void disable_error_prompts()
Disables Windows error dialog boxes.
unsigned long get_current_process_id()
Returns the Windows process ID for the current process.
long long query_performance_counter()
Wraps around the QueryPerformanceCounter function.