29 #pragma comment(lib, "psapi.lib")
30 #pragma comment(lib, "dbghelp.lib")
32 #if ((HAVE_LIBIMAGEHLP != 1) || (HAVE_LIBPSAPI != 1))
33 #error "libimagehlp.a & libpsapi.a should be present"
43 #pragma GCC diagnostic ignored "-Wformat"
44 #pragma GCC diagnostic ignored "-Wformat-extra-args"
46 #if !defined(__MINGW64_VERSION_MAJOR)
51 typedef struct _IMAGEHLP_LINE64 {
57 } IMAGEHLP_LINE64, *PIMAGEHLP_LINE64;
59 typedef struct _IMAGEHLP_SYMBOL64 {
66 } IMAGEHLP_SYMBOL64, *PIMAGEHLP_SYMBOL64;
68 typedef struct _tagADDRESS64 {
72 } ADDRESS64, *LPADDRESS64;
74 typedef struct _KDHELP64 {
76 DWORD ThCallbackStack;
77 DWORD ThCallbackBStore;
80 DWORD64 KiCallUserMode;
81 DWORD64 KeUserCallbackDispatcher;
82 DWORD64 SystemRangeStart;
83 DWORD64 KiUserExceptionDispatcher;
87 } KDHELP64, *PKDHELP64;
89 typedef struct _tagSTACKFRAME64 {
101 } STACKFRAME64, *LPSTACKFRAME64;
103 typedef BOOL (__stdcall *PREAD_PROCESS_MEMORY_ROUTINE64)(HANDLE hProcess,
104 DWORD64 qwBaseAddress, PVOID lpBuffer, DWORD nSize,
105 LPDWORD lpNumberOfBytesRead);
107 typedef PVOID (__stdcall *PFUNCTION_TABLE_ACCESS_ROUTINE64)( HANDLE ahProcess,
110 typedef DWORD64 (__stdcall *PGET_MODULE_BASE_ROUTINE64)(HANDLE hProcess,
113 typedef DWORD64 (__stdcall *PTRANSLATE_ADDRESS_ROUTINE64)(HANDLE hProcess,
114 HANDLE hThread, LPADDRESS64 lpaddr);
116 typedef BOOL (WINAPI *fpStackWalk64)(DWORD, HANDLE, HANDLE, LPSTACKFRAME64,
117 PVOID, PREAD_PROCESS_MEMORY_ROUTINE64,
118 PFUNCTION_TABLE_ACCESS_ROUTINE64,
119 PGET_MODULE_BASE_ROUTINE64,
120 PTRANSLATE_ADDRESS_ROUTINE64);
121 static fpStackWalk64 StackWalk64;
123 typedef DWORD64 (WINAPI *fpSymGetModuleBase64)(HANDLE, DWORD64);
124 static fpSymGetModuleBase64 SymGetModuleBase64;
126 typedef BOOL (WINAPI *fpSymGetSymFromAddr64)(HANDLE, DWORD64,
127 PDWORD64, PIMAGEHLP_SYMBOL64);
128 static fpSymGetSymFromAddr64 SymGetSymFromAddr64;
130 typedef BOOL (WINAPI *fpSymGetLineFromAddr64)(HANDLE, DWORD64,
131 PDWORD, PIMAGEHLP_LINE64);
132 static fpSymGetLineFromAddr64 SymGetLineFromAddr64;
134 typedef PVOID (WINAPI *fpSymFunctionTableAccess64)(HANDLE, DWORD64);
135 static fpSymFunctionTableAccess64 SymFunctionTableAccess64;
137 static bool load64BitDebugHelp(
void) {
138 HMODULE hLib = ::LoadLibraryW(L
"Dbghelp.dll");
140 StackWalk64 = (fpStackWalk64)
141 ::GetProcAddress(hLib,
"StackWalk64");
142 SymGetModuleBase64 = (fpSymGetModuleBase64)
143 ::GetProcAddress(hLib,
"SymGetModuleBase64");
144 SymGetSymFromAddr64 = (fpSymGetSymFromAddr64)
145 ::GetProcAddress(hLib,
"SymGetSymFromAddr64");
146 SymGetLineFromAddr64 = (fpSymGetLineFromAddr64)
147 ::GetProcAddress(hLib,
"SymGetLineFromAddr64");
148 SymFunctionTableAccess64 = (fpSymFunctionTableAccess64)
149 ::GetProcAddress(hLib,
"SymFunctionTableAccess64");
151 return StackWalk64 != NULL;
153 #endif // !defined(__MINGW64_VERSION_MAJOR)
154 #endif // __MINGW32__
157 static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep);
158 static BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType);
161 static void (*InterruptFunction)() = 0;
163 static std::vector<std::string> *FilesToRemove = NULL;
164 static std::vector<std::pair<void(*)(void*), void*> > *CallBacksToRun = 0;
165 static bool RegisteredUnhandledExceptionFilter =
false;
166 static bool CleanupExecuted =
false;
167 static bool ExitOnUnhandledExceptions =
false;
168 static PTOP_LEVEL_EXCEPTION_FILTER OldFilter = NULL;
173 static CRITICAL_SECTION CriticalSection;
186 static int AvoidMessageBoxHook(
int ReportType,
char *Message,
int *
Return) {
198 static void RegisterHandler() {
199 #if __MINGW32__ && !defined(__MINGW64_VERSION_MAJOR)
205 if (!load64BitDebugHelp()) {
206 assert(
false &&
"These APIs should always be available");
211 if (RegisteredUnhandledExceptionFilter) {
212 EnterCriticalSection(&CriticalSection);
218 InitializeCriticalSection(&CriticalSection);
222 EnterCriticalSection(&CriticalSection);
224 RegisteredUnhandledExceptionFilter =
true;
225 OldFilter = SetUnhandledExceptionFilter(LLVMUnhandledExceptionFilter);
226 SetConsoleCtrlHandler(LLVMConsoleCtrlHandler,
TRUE);
229 if (
getenv(
"LLVM_DISABLE_CRASH_REPORT")) {
231 _CrtSetReportHook(AvoidMessageBoxHook);
233 SetErrorMode(SEM_FAILCRITICALERRORS |
234 SEM_NOGPFAULTERRORBOX |
235 SEM_NOOPENFILEERRORBOX);
236 ExitOnUnhandledExceptions =
true;
247 if (CleanupExecuted) {
249 *ErrMsg =
"Process terminating -- cannot register for removal";
253 if (FilesToRemove == NULL)
254 FilesToRemove =
new std::vector<std::string>;
256 FilesToRemove->push_back(Filename);
258 LeaveCriticalSection(&CriticalSection);
264 if (FilesToRemove == NULL)
269 FilesToRemove->push_back(Filename);
271 std::find(FilesToRemove->rbegin(), FilesToRemove->rend(), Filename);
272 if (I != FilesToRemove->rend())
273 FilesToRemove->erase(I.base()-1);
275 LeaveCriticalSection(&CriticalSection);
282 LeaveCriticalSection(&CriticalSection);
292 InterruptFunction = IF;
293 LeaveCriticalSection(&CriticalSection);
301 if (CallBacksToRun == 0)
302 CallBacksToRun =
new std::vector<std::pair<void(*)(void*), void*> >();
303 CallBacksToRun->push_back(std::make_pair(FnPtr, Cookie));
305 LeaveCriticalSection(&CriticalSection);
309 static void Cleanup() {
310 EnterCriticalSection(&CriticalSection);
314 CleanupExecuted =
true;
318 if (FilesToRemove != NULL)
319 while (!FilesToRemove->empty()) {
322 FilesToRemove->pop_back();
326 for (
unsigned i = 0, e = CallBacksToRun->size(); i != e; ++i)
327 (*CallBacksToRun)[i].first((*CallBacksToRun)[i].second);
329 LeaveCriticalSection(&CriticalSection);
336 static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep) {
340 STACKFRAME64 StackFrame;
341 memset(&StackFrame, 0,
sizeof(StackFrame));
346 StackFrame.AddrPC.Offset = ep->ContextRecord->Rip;
347 StackFrame.AddrPC.Mode = AddrModeFlat;
348 StackFrame.AddrStack.Offset = ep->ContextRecord->Rsp;
349 StackFrame.AddrStack.Mode = AddrModeFlat;
350 StackFrame.AddrFrame.Offset = ep->ContextRecord->Rbp;
351 StackFrame.AddrFrame.Mode = AddrModeFlat;
352 #elif defined(_M_IX86)
354 StackFrame.AddrPC.Offset = ep->ContextRecord->Eip;
355 StackFrame.AddrPC.Mode = AddrModeFlat;
356 StackFrame.AddrStack.Offset = ep->ContextRecord->Esp;
357 StackFrame.AddrStack.Mode = AddrModeFlat;
358 StackFrame.AddrFrame.Offset = ep->ContextRecord->Ebp;
359 StackFrame.AddrFrame.Mode = AddrModeFlat;
362 HANDLE hProcess = GetCurrentProcess();
363 HANDLE hThread = GetCurrentThread();
366 SymSetOptions(SYMOPT_DEFERRED_LOADS|SYMOPT_LOAD_LINES);
367 SymInitialize(hProcess, NULL,
TRUE);
370 if (!StackWalk64(machineType, hProcess, hThread, &StackFrame,
371 ep->ContextRecord, NULL, SymFunctionTableAccess64,
372 SymGetModuleBase64, NULL)) {
376 if (StackFrame.AddrFrame.Offset == 0)
380 DWORD64 PC = StackFrame.AddrPC.Offset;
382 fprintf(stderr,
"0x%016llX", PC);
383 #elif defined(_M_IX86)
384 fprintf(stderr,
"0x%08lX", static_cast<DWORD>(PC));
389 fprintf(stderr,
" (0x%016llX 0x%016llX 0x%016llX 0x%016llX)",
390 StackFrame.Params[0],
391 StackFrame.Params[1],
392 StackFrame.Params[2],
393 StackFrame.Params[3]);
394 #elif defined(_M_IX86)
395 fprintf(stderr,
" (0x%08lX 0x%08lX 0x%08lX 0x%08lX)",
396 static_cast<DWORD>(StackFrame.Params[0]),
397 static_cast<DWORD>(StackFrame.Params[1]),
398 static_cast<DWORD>(StackFrame.Params[2]),
399 static_cast<DWORD>(StackFrame.Params[3]));
402 if (!SymGetModuleBase64(hProcess, PC)) {
403 fputs(
" <unknown module>\n", stderr);
409 IMAGEHLP_SYMBOL64 *symbol =
reinterpret_cast<IMAGEHLP_SYMBOL64 *
>(buffer);
410 memset(symbol, 0,
sizeof(IMAGEHLP_SYMBOL64));
411 symbol->SizeOfStruct =
sizeof(IMAGEHLP_SYMBOL64);
412 symbol->MaxNameLength = 512 -
sizeof(IMAGEHLP_SYMBOL64);
415 if (!SymGetSymFromAddr64(hProcess, PC, &dwDisp, symbol)) {
422 fprintf(stderr,
", %s() + 0x%llX bytes(s)", symbol->Name, dwDisp);
424 fprintf(stderr,
", %s", symbol->Name);
427 IMAGEHLP_LINE64 line;
429 memset(&line, 0,
sizeof(line));
430 line.SizeOfStruct =
sizeof(line);
431 if (SymGetLineFromAddr64(hProcess, PC, &dwLineDisp, &line)) {
432 fprintf(stderr,
", %s, line %lu", line.FileName, line.LineNumber);
434 fprintf(stderr,
" + 0x%lX byte(s)", dwLineDisp);
440 if (ExitOnUnhandledExceptions)
441 _exit(ep->ExceptionRecord->ExceptionCode);
445 return (*OldFilter)(ep);
447 return EXCEPTION_CONTINUE_SEARCH;
450 static BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType) {
452 EnterCriticalSection(&CriticalSection);
457 void (*IF)() = InterruptFunction;
458 InterruptFunction = 0;
464 LeaveCriticalSection(&CriticalSection);
469 LeaveCriticalSection(&CriticalSection);
478 #pragma GCC diagnostic warning "-Wformat"
479 #pragma GCC diagnostic warning "-Wformat-extra-args"
void PrintStackTraceOnErrorSignal()
Print a stack trace if a fatal signal occurs.
void RunInterruptHandlers()
void DontRemoveFileOnSignal(StringRef Filename)
int fputs(const char *s, FILE *stream);
int fprintf(FILE *stream, const char *format, ...);
Instr is a return instruction.
bool RemoveFileOnSignal(StringRef Filename, std::string *ErrMsg=0)
Remove a file if a fatal signal occurs.
int fputc(int c, FILE *stream);
error_code remove(const Twine &path, bool &existed)
Remove path. Equivalent to POSIX remove().
std::reverse_iterator< const_iterator > reverse_iterator
void PrintStackTrace(FILE *)
Print the stack trace using the given FILE object.
void SetInterruptFunction(void(*IF)())
Register a function to be called when ctrl-c is pressed.
char *getenv(const char *name);
void AddSignalHandler(void(*FnPtr)(void *), void *Cookie)