Signals.inc revision 226633
1218885Sdim//===- Win32/Signals.cpp - Win32 Signals Implementation ---------*- C++ -*-===// 2218885Sdim// 3218885Sdim// The LLVM Compiler Infrastructure 4218885Sdim// 5218885Sdim// This file is distributed under the University of Illinois Open Source 6218885Sdim// License. See LICENSE.TXT for details. 7218885Sdim// 8218885Sdim//===----------------------------------------------------------------------===// 9218885Sdim// 10218885Sdim// This file provides the Win32 specific implementation of the Signals class. 11218885Sdim// 12218885Sdim//===----------------------------------------------------------------------===// 13218885Sdim 14218885Sdim#include "Windows.h" 15218885Sdim#include <stdio.h> 16218885Sdim#include <vector> 17218885Sdim#include <algorithm> 18218885Sdim 19218885Sdim#ifdef __MINGW32__ 20218885Sdim #include <imagehlp.h> 21218885Sdim#else 22218885Sdim #include <dbghelp.h> 23218885Sdim#endif 24218885Sdim#include <psapi.h> 25218885Sdim 26226633Sdim#ifdef _MSC_VER 27226633Sdim #pragma comment(lib, "psapi.lib") 28226633Sdim #pragma comment(lib, "dbghelp.lib") 29226633Sdim#elif __MINGW32__ 30218885Sdim #if ((HAVE_LIBIMAGEHLP != 1) || (HAVE_LIBPSAPI != 1)) 31218885Sdim #error "libimagehlp.a & libpsapi.a should be present" 32218885Sdim #endif 33226633Sdim // The version of g++ that comes with MinGW does *not* properly understand 34226633Sdim // the ll format specifier for printf. However, MinGW passes the format 35226633Sdim // specifiers on to the MSVCRT entirely, and the CRT understands the ll 36226633Sdim // specifier. So these warnings are spurious in this case. Since we compile 37226633Sdim // with -Wall, this will generate these warnings which should be ignored. So 38226633Sdim // we will turn off the warnings for this just file. However, MinGW also does 39226633Sdim // not support push and pop for diagnostics, so we have to manually turn it 40226633Sdim // back on at the end of the file. 41226633Sdim #pragma GCC diagnostic ignored "-Wformat" 42226633Sdim #pragma GCC diagnostic ignored "-Wformat-extra-args" 43218885Sdim 44226633Sdim #if !defined(__MINGW64_VERSION_MAJOR) 45226633Sdim // MinGW.org does not have updated support for the 64-bit versions of the 46226633Sdim // DebugHlp APIs. So we will have to load them manually. The structures and 47226633Sdim // method signatures were pulled from DbgHelp.h in the Windows Platform SDK, 48226633Sdim // and adjusted for brevity. 49226633Sdim typedef struct _IMAGEHLP_LINE64 { 50226633Sdim DWORD SizeOfStruct; 51226633Sdim PVOID Key; 52226633Sdim DWORD LineNumber; 53226633Sdim PCHAR FileName; 54226633Sdim DWORD64 Address; 55226633Sdim } IMAGEHLP_LINE64, *PIMAGEHLP_LINE64; 56226633Sdim 57226633Sdim typedef struct _IMAGEHLP_SYMBOL64 { 58226633Sdim DWORD SizeOfStruct; 59226633Sdim DWORD64 Address; 60226633Sdim DWORD Size; 61226633Sdim DWORD Flags; 62226633Sdim DWORD MaxNameLength; 63226633Sdim CHAR Name[1]; 64226633Sdim } IMAGEHLP_SYMBOL64, *PIMAGEHLP_SYMBOL64; 65226633Sdim 66226633Sdim typedef struct _tagADDRESS64 { 67226633Sdim DWORD64 Offset; 68226633Sdim WORD Segment; 69226633Sdim ADDRESS_MODE Mode; 70226633Sdim } ADDRESS64, *LPADDRESS64; 71226633Sdim 72226633Sdim typedef struct _KDHELP64 { 73226633Sdim DWORD64 Thread; 74226633Sdim DWORD ThCallbackStack; 75226633Sdim DWORD ThCallbackBStore; 76226633Sdim DWORD NextCallback; 77226633Sdim DWORD FramePointer; 78226633Sdim DWORD64 KiCallUserMode; 79226633Sdim DWORD64 KeUserCallbackDispatcher; 80226633Sdim DWORD64 SystemRangeStart; 81226633Sdim DWORD64 KiUserExceptionDispatcher; 82226633Sdim DWORD64 StackBase; 83226633Sdim DWORD64 StackLimit; 84226633Sdim DWORD64 Reserved[5]; 85226633Sdim } KDHELP64, *PKDHELP64; 86226633Sdim 87226633Sdim typedef struct _tagSTACKFRAME64 { 88226633Sdim ADDRESS64 AddrPC; 89226633Sdim ADDRESS64 AddrReturn; 90226633Sdim ADDRESS64 AddrFrame; 91226633Sdim ADDRESS64 AddrStack; 92226633Sdim ADDRESS64 AddrBStore; 93226633Sdim PVOID FuncTableEntry; 94226633Sdim DWORD64 Params[4]; 95226633Sdim BOOL Far; 96226633Sdim BOOL Virtual; 97226633Sdim DWORD64 Reserved[3]; 98226633Sdim KDHELP64 KdHelp; 99226633Sdim } STACKFRAME64, *LPSTACKFRAME64; 100226633Sdim 101226633Sdimtypedef BOOL (__stdcall *PREAD_PROCESS_MEMORY_ROUTINE64)(HANDLE hProcess, 102226633Sdim DWORD64 qwBaseAddress, PVOID lpBuffer, DWORD nSize, 103226633Sdim LPDWORD lpNumberOfBytesRead); 104226633Sdim 105226633Sdimtypedef PVOID (__stdcall *PFUNCTION_TABLE_ACCESS_ROUTINE64)( HANDLE ahProcess, 106226633Sdim DWORD64 AddrBase); 107226633Sdim 108226633Sdimtypedef DWORD64 (__stdcall *PGET_MODULE_BASE_ROUTINE64)(HANDLE hProcess, 109226633Sdim DWORD64 Address); 110226633Sdim 111226633Sdimtypedef DWORD64 (__stdcall *PTRANSLATE_ADDRESS_ROUTINE64)(HANDLE hProcess, 112226633Sdim HANDLE hThread, LPADDRESS64 lpaddr); 113226633Sdim 114226633Sdimtypedef BOOL (WINAPI *fpStackWalk64)(DWORD, HANDLE, HANDLE, LPSTACKFRAME64, 115226633Sdim PVOID, PREAD_PROCESS_MEMORY_ROUTINE64, 116226633Sdim PFUNCTION_TABLE_ACCESS_ROUTINE64, 117226633Sdim PGET_MODULE_BASE_ROUTINE64, 118226633Sdim PTRANSLATE_ADDRESS_ROUTINE64); 119226633Sdimstatic fpStackWalk64 StackWalk64; 120226633Sdim 121226633Sdimtypedef DWORD64 (WINAPI *fpSymGetModuleBase64)(HANDLE, DWORD64); 122226633Sdimstatic fpSymGetModuleBase64 SymGetModuleBase64; 123226633Sdim 124226633Sdimtypedef BOOL (WINAPI *fpSymGetSymFromAddr64)(HANDLE, DWORD64, 125226633Sdim PDWORD64, PIMAGEHLP_SYMBOL64); 126226633Sdimstatic fpSymGetSymFromAddr64 SymGetSymFromAddr64; 127226633Sdim 128226633Sdimtypedef BOOL (WINAPI *fpSymGetLineFromAddr64)(HANDLE, DWORD64, 129226633Sdim PDWORD, PIMAGEHLP_LINE64); 130226633Sdimstatic fpSymGetLineFromAddr64 SymGetLineFromAddr64; 131226633Sdim 132226633Sdimtypedef PVOID (WINAPI *fpSymFunctionTableAccess64)(HANDLE, DWORD64); 133226633Sdimstatic fpSymFunctionTableAccess64 SymFunctionTableAccess64; 134226633Sdim 135226633Sdimstatic bool load64BitDebugHelp(void) { 136226633Sdim HMODULE hLib = ::LoadLibrary("Dbghelp.dll"); 137226633Sdim if (hLib) { 138226633Sdim StackWalk64 = (fpStackWalk64) 139226633Sdim ::GetProcAddress(hLib, "StackWalk64"); 140226633Sdim SymGetModuleBase64 = (fpSymGetModuleBase64) 141226633Sdim ::GetProcAddress(hLib, "SymGetModuleBase64"); 142226633Sdim SymGetSymFromAddr64 = (fpSymGetSymFromAddr64) 143226633Sdim ::GetProcAddress(hLib, "SymGetSymFromAddr64"); 144226633Sdim SymGetLineFromAddr64 = (fpSymGetLineFromAddr64) 145226633Sdim ::GetProcAddress(hLib, "SymGetLineFromAddr64"); 146226633Sdim SymFunctionTableAccess64 = (fpSymFunctionTableAccess64) 147226633Sdim ::GetProcAddress(hLib, "SymFunctionTableAccess64"); 148226633Sdim } 149226633Sdim return StackWalk64 != NULL; 150226633Sdim} 151226633Sdim #endif // !defined(__MINGW64_VERSION_MAJOR) 152226633Sdim#endif // __MINGW32__ 153226633Sdim 154218885Sdim// Forward declare. 155218885Sdimstatic LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep); 156218885Sdimstatic BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType); 157218885Sdim 158218885Sdim// InterruptFunction - The function to call if ctrl-c is pressed. 159218885Sdimstatic void (*InterruptFunction)() = 0; 160218885Sdim 161218885Sdimstatic std::vector<llvm::sys::Path> *FilesToRemove = NULL; 162218885Sdimstatic std::vector<std::pair<void(*)(void*), void*> > *CallBacksToRun = 0; 163218885Sdimstatic bool RegisteredUnhandledExceptionFilter = false; 164218885Sdimstatic bool CleanupExecuted = false; 165218885Sdimstatic bool ExitOnUnhandledExceptions = false; 166218885Sdimstatic PTOP_LEVEL_EXCEPTION_FILTER OldFilter = NULL; 167218885Sdim 168218885Sdim// Windows creates a new thread to execute the console handler when an event 169218885Sdim// (such as CTRL/C) occurs. This causes concurrency issues with the above 170218885Sdim// globals which this critical section addresses. 171218885Sdimstatic CRITICAL_SECTION CriticalSection; 172218885Sdim 173218885Sdimnamespace llvm { 174218885Sdim 175218885Sdim//===----------------------------------------------------------------------===// 176218885Sdim//=== WARNING: Implementation here must contain only Win32 specific code 177218885Sdim//=== and must not be UNIX code 178218885Sdim//===----------------------------------------------------------------------===// 179218885Sdim 180218885Sdim#ifdef _MSC_VER 181218885Sdim/// CRTReportHook - Function called on a CRT debugging event. 182218885Sdimstatic int CRTReportHook(int ReportType, char *Message, int *Return) { 183218885Sdim // Don't cause a DebugBreak() on return. 184218885Sdim if (Return) 185218885Sdim *Return = 0; 186218885Sdim 187218885Sdim switch (ReportType) { 188218885Sdim default: 189218885Sdim case _CRT_ASSERT: 190218885Sdim fprintf(stderr, "CRT assert: %s\n", Message); 191218885Sdim // FIXME: Is there a way to just crash? Perhaps throw to the unhandled 192218885Sdim // exception code? Perhaps SetErrorMode() handles this. 193218885Sdim _exit(3); 194218885Sdim break; 195218885Sdim case _CRT_ERROR: 196218885Sdim fprintf(stderr, "CRT error: %s\n", Message); 197218885Sdim // FIXME: Is there a way to just crash? Perhaps throw to the unhandled 198218885Sdim // exception code? Perhaps SetErrorMode() handles this. 199218885Sdim _exit(3); 200218885Sdim break; 201218885Sdim case _CRT_WARN: 202218885Sdim fprintf(stderr, "CRT warn: %s\n", Message); 203218885Sdim break; 204218885Sdim } 205218885Sdim 206218885Sdim // Don't call _CrtDbgReport. 207218885Sdim return TRUE; 208218885Sdim} 209218885Sdim#endif 210218885Sdim 211218885Sdimstatic void RegisterHandler() { 212226633Sdim#if __MINGW32__ && !defined(__MINGW64_VERSION_MAJOR) 213226633Sdim // On MinGW.org, we need to load up the symbols explicitly, because the 214226633Sdim // Win32 framework they include does not have support for the 64-bit 215226633Sdim // versions of the APIs we need. If we cannot load up the APIs (which 216226633Sdim // would be unexpected as they should exist on every version of Windows 217226633Sdim // we support), we will bail out since there would be nothing to report. 218226633Sdim if (!load64BitDebugHelp()) { 219226633Sdim assert(false && "These APIs should always be available"); 220226633Sdim return; 221226633Sdim } 222226633Sdim#endif 223226633Sdim 224218885Sdim if (RegisteredUnhandledExceptionFilter) { 225218885Sdim EnterCriticalSection(&CriticalSection); 226218885Sdim return; 227218885Sdim } 228218885Sdim 229218885Sdim // Now's the time to create the critical section. This is the first time 230218885Sdim // through here, and there's only one thread. 231218885Sdim InitializeCriticalSection(&CriticalSection); 232218885Sdim 233218885Sdim // Enter it immediately. Now if someone hits CTRL/C, the console handler 234218885Sdim // can't proceed until the globals are updated. 235218885Sdim EnterCriticalSection(&CriticalSection); 236218885Sdim 237218885Sdim RegisteredUnhandledExceptionFilter = true; 238218885Sdim OldFilter = SetUnhandledExceptionFilter(LLVMUnhandledExceptionFilter); 239218885Sdim SetConsoleCtrlHandler(LLVMConsoleCtrlHandler, TRUE); 240218885Sdim 241218885Sdim // Environment variable to disable any kind of crash dialog. 242218885Sdim if (getenv("LLVM_DISABLE_CRT_DEBUG")) { 243218885Sdim#ifdef _MSC_VER 244218885Sdim _CrtSetReportHook(CRTReportHook); 245218885Sdim#endif 246218885Sdim SetErrorMode(SEM_FAILCRITICALERRORS | 247218885Sdim SEM_NOGPFAULTERRORBOX | 248218885Sdim SEM_NOOPENFILEERRORBOX); 249218885Sdim ExitOnUnhandledExceptions = true; 250218885Sdim } 251218885Sdim 252218885Sdim // IMPORTANT NOTE: Caller must call LeaveCriticalSection(&CriticalSection) or 253218885Sdim // else multi-threading problems will ensue. 254218885Sdim} 255218885Sdim 256218885Sdim// RemoveFileOnSignal - The public API 257218885Sdimbool sys::RemoveFileOnSignal(const sys::Path &Filename, std::string* ErrMsg) { 258218885Sdim RegisterHandler(); 259218885Sdim 260218885Sdim if (CleanupExecuted) { 261218885Sdim if (ErrMsg) 262218885Sdim *ErrMsg = "Process terminating -- cannot register for removal"; 263218885Sdim return true; 264218885Sdim } 265218885Sdim 266218885Sdim if (FilesToRemove == NULL) 267218885Sdim FilesToRemove = new std::vector<sys::Path>; 268218885Sdim 269218885Sdim FilesToRemove->push_back(Filename); 270218885Sdim 271218885Sdim LeaveCriticalSection(&CriticalSection); 272218885Sdim return false; 273218885Sdim} 274218885Sdim 275218885Sdim// DontRemoveFileOnSignal - The public API 276218885Sdimvoid sys::DontRemoveFileOnSignal(const sys::Path &Filename) { 277218885Sdim if (FilesToRemove == NULL) 278218885Sdim return; 279218885Sdim 280218885Sdim RegisterHandler(); 281218885Sdim 282218885Sdim FilesToRemove->push_back(Filename); 283218885Sdim std::vector<sys::Path>::reverse_iterator I = 284218885Sdim std::find(FilesToRemove->rbegin(), FilesToRemove->rend(), Filename); 285218885Sdim if (I != FilesToRemove->rend()) 286218885Sdim FilesToRemove->erase(I.base()-1); 287218885Sdim 288218885Sdim LeaveCriticalSection(&CriticalSection); 289218885Sdim} 290218885Sdim 291218885Sdim/// PrintStackTraceOnErrorSignal - When an error signal (such as SIBABRT or 292218885Sdim/// SIGSEGV) is delivered to the process, print a stack trace and then exit. 293218885Sdimvoid sys::PrintStackTraceOnErrorSignal() { 294218885Sdim RegisterHandler(); 295218885Sdim LeaveCriticalSection(&CriticalSection); 296218885Sdim} 297218885Sdim 298218885Sdim 299218885Sdimvoid sys::SetInterruptFunction(void (*IF)()) { 300218885Sdim RegisterHandler(); 301218885Sdim InterruptFunction = IF; 302218885Sdim LeaveCriticalSection(&CriticalSection); 303218885Sdim} 304218885Sdim 305218885Sdim 306218885Sdim/// AddSignalHandler - Add a function to be called when a signal is delivered 307218885Sdim/// to the process. The handler can have a cookie passed to it to identify 308218885Sdim/// what instance of the handler it is. 309218885Sdimvoid sys::AddSignalHandler(void (*FnPtr)(void *), void *Cookie) { 310218885Sdim if (CallBacksToRun == 0) 311218885Sdim CallBacksToRun = new std::vector<std::pair<void(*)(void*), void*> >(); 312218885Sdim CallBacksToRun->push_back(std::make_pair(FnPtr, Cookie)); 313218885Sdim RegisterHandler(); 314218885Sdim LeaveCriticalSection(&CriticalSection); 315218885Sdim} 316218885Sdim} 317218885Sdim 318218885Sdimstatic void Cleanup() { 319218885Sdim EnterCriticalSection(&CriticalSection); 320218885Sdim 321218885Sdim // Prevent other thread from registering new files and directories for 322218885Sdim // removal, should we be executing because of the console handler callback. 323218885Sdim CleanupExecuted = true; 324218885Sdim 325218885Sdim // FIXME: open files cannot be deleted. 326218885Sdim 327218885Sdim if (FilesToRemove != NULL) 328218885Sdim while (!FilesToRemove->empty()) { 329218885Sdim FilesToRemove->back().eraseFromDisk(); 330218885Sdim FilesToRemove->pop_back(); 331218885Sdim } 332218885Sdim 333218885Sdim if (CallBacksToRun) 334218885Sdim for (unsigned i = 0, e = CallBacksToRun->size(); i != e; ++i) 335218885Sdim (*CallBacksToRun)[i].first((*CallBacksToRun)[i].second); 336218885Sdim 337218885Sdim LeaveCriticalSection(&CriticalSection); 338218885Sdim} 339218885Sdim 340218885Sdimvoid llvm::sys::RunInterruptHandlers() { 341218885Sdim Cleanup(); 342218885Sdim} 343218885Sdim 344218885Sdimstatic LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep) { 345218885Sdim Cleanup(); 346218885Sdim 347218885Sdim // Initialize the STACKFRAME structure. 348226633Sdim STACKFRAME64 StackFrame; 349218885Sdim memset(&StackFrame, 0, sizeof(StackFrame)); 350218885Sdim 351226633Sdim DWORD machineType; 352226633Sdim#if defined(_M_X64) 353226633Sdim machineType = IMAGE_FILE_MACHINE_AMD64; 354226633Sdim StackFrame.AddrPC.Offset = ep->ContextRecord->Rip; 355226633Sdim StackFrame.AddrPC.Mode = AddrModeFlat; 356226633Sdim StackFrame.AddrStack.Offset = ep->ContextRecord->Rsp; 357226633Sdim StackFrame.AddrStack.Mode = AddrModeFlat; 358226633Sdim StackFrame.AddrFrame.Offset = ep->ContextRecord->Rbp; 359226633Sdim StackFrame.AddrFrame.Mode = AddrModeFlat; 360226633Sdim#elif defined(_M_IX86) 361226633Sdim machineType = IMAGE_FILE_MACHINE_I386; 362218885Sdim StackFrame.AddrPC.Offset = ep->ContextRecord->Eip; 363218885Sdim StackFrame.AddrPC.Mode = AddrModeFlat; 364218885Sdim StackFrame.AddrStack.Offset = ep->ContextRecord->Esp; 365218885Sdim StackFrame.AddrStack.Mode = AddrModeFlat; 366218885Sdim StackFrame.AddrFrame.Offset = ep->ContextRecord->Ebp; 367218885Sdim StackFrame.AddrFrame.Mode = AddrModeFlat; 368226633Sdim#endif 369218885Sdim 370218885Sdim HANDLE hProcess = GetCurrentProcess(); 371218885Sdim HANDLE hThread = GetCurrentThread(); 372218885Sdim 373218885Sdim // Initialize the symbol handler. 374218885Sdim SymSetOptions(SYMOPT_DEFERRED_LOADS|SYMOPT_LOAD_LINES); 375218885Sdim SymInitialize(hProcess, NULL, TRUE); 376218885Sdim 377218885Sdim while (true) { 378226633Sdim if (!StackWalk64(machineType, hProcess, hThread, &StackFrame, 379226633Sdim ep->ContextRecord, NULL, SymFunctionTableAccess64, 380226633Sdim SymGetModuleBase64, NULL)) { 381218885Sdim break; 382218885Sdim } 383218885Sdim 384218885Sdim if (StackFrame.AddrFrame.Offset == 0) 385218885Sdim break; 386218885Sdim 387218885Sdim // Print the PC in hexadecimal. 388226633Sdim DWORD64 PC = StackFrame.AddrPC.Offset; 389226633Sdim#if defined(_M_X64) 390226633Sdim fprintf(stderr, "0x%016llX", PC); 391226633Sdim#elif defined(_M_IX86) 392226633Sdim fprintf(stderr, "0x%08lX", static_cast<DWORD>(PC)); 393226633Sdim#endif 394218885Sdim 395218885Sdim // Print the parameters. Assume there are four. 396226633Sdim#if defined(_M_X64) 397226633Sdim fprintf(stderr, " (0x%016llX 0x%016llX 0x%016llX 0x%016llX)", 398226633Sdim StackFrame.Params[0], 399226633Sdim StackFrame.Params[1], 400226633Sdim StackFrame.Params[2], 401226633Sdim StackFrame.Params[3]); 402226633Sdim#elif defined(_M_IX86) 403218885Sdim fprintf(stderr, " (0x%08lX 0x%08lX 0x%08lX 0x%08lX)", 404226633Sdim static_cast<DWORD>(StackFrame.Params[0]), 405226633Sdim static_cast<DWORD>(StackFrame.Params[1]), 406226633Sdim static_cast<DWORD>(StackFrame.Params[2]), 407226633Sdim static_cast<DWORD>(StackFrame.Params[3])); 408226633Sdim#endif 409218885Sdim // Verify the PC belongs to a module in this process. 410226633Sdim if (!SymGetModuleBase64(hProcess, PC)) { 411218885Sdim fputs(" <unknown module>\n", stderr); 412218885Sdim continue; 413218885Sdim } 414218885Sdim 415218885Sdim // Print the symbol name. 416218885Sdim char buffer[512]; 417226633Sdim IMAGEHLP_SYMBOL64 *symbol = reinterpret_cast<IMAGEHLP_SYMBOL64 *>(buffer); 418226633Sdim memset(symbol, 0, sizeof(IMAGEHLP_SYMBOL64)); 419226633Sdim symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); 420226633Sdim symbol->MaxNameLength = 512 - sizeof(IMAGEHLP_SYMBOL64); 421218885Sdim 422226633Sdim DWORD64 dwDisp; 423226633Sdim if (!SymGetSymFromAddr64(hProcess, PC, &dwDisp, symbol)) { 424218885Sdim fputc('\n', stderr); 425218885Sdim continue; 426218885Sdim } 427218885Sdim 428218885Sdim buffer[511] = 0; 429218885Sdim if (dwDisp > 0) 430226633Sdim fprintf(stderr, ", %s() + 0x%llX bytes(s)", symbol->Name, dwDisp); 431218885Sdim else 432218885Sdim fprintf(stderr, ", %s", symbol->Name); 433218885Sdim 434218885Sdim // Print the source file and line number information. 435226633Sdim IMAGEHLP_LINE64 line; 436226633Sdim DWORD dwLineDisp; 437218885Sdim memset(&line, 0, sizeof(line)); 438218885Sdim line.SizeOfStruct = sizeof(line); 439226633Sdim if (SymGetLineFromAddr64(hProcess, PC, &dwLineDisp, &line)) { 440218885Sdim fprintf(stderr, ", %s, line %lu", line.FileName, line.LineNumber); 441226633Sdim if (dwLineDisp > 0) 442226633Sdim fprintf(stderr, " + 0x%lX byte(s)", dwLineDisp); 443218885Sdim } 444218885Sdim 445218885Sdim fputc('\n', stderr); 446218885Sdim } 447218885Sdim 448218885Sdim if (ExitOnUnhandledExceptions) 449218885Sdim _exit(-3); 450218885Sdim 451218885Sdim // Allow dialog box to pop up allowing choice to start debugger. 452218885Sdim if (OldFilter) 453218885Sdim return (*OldFilter)(ep); 454218885Sdim else 455218885Sdim return EXCEPTION_CONTINUE_SEARCH; 456218885Sdim} 457218885Sdim 458218885Sdimstatic BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType) { 459218885Sdim // We are running in our very own thread, courtesy of Windows. 460218885Sdim EnterCriticalSection(&CriticalSection); 461218885Sdim Cleanup(); 462218885Sdim 463218885Sdim // If an interrupt function has been set, go and run one it; otherwise, 464218885Sdim // the process dies. 465218885Sdim void (*IF)() = InterruptFunction; 466218885Sdim InterruptFunction = 0; // Don't run it on another CTRL-C. 467218885Sdim 468218885Sdim if (IF) { 469218885Sdim // Note: if the interrupt function throws an exception, there is nothing 470218885Sdim // to catch it in this thread so it will kill the process. 471218885Sdim IF(); // Run it now. 472218885Sdim LeaveCriticalSection(&CriticalSection); 473218885Sdim return TRUE; // Don't kill the process. 474218885Sdim } 475218885Sdim 476218885Sdim // Allow normal processing to take place; i.e., the process dies. 477218885Sdim LeaveCriticalSection(&CriticalSection); 478218885Sdim return FALSE; 479218885Sdim} 480226633Sdim 481226633Sdim#if __MINGW32__ 482226633Sdim // We turned these warnings off for this file so that MinGW-g++ doesn't 483226633Sdim // complain about the ll format specifiers used. Now we are turning the 484226633Sdim // warnings back on. If MinGW starts to support diagnostic stacks, we can 485226633Sdim // replace this with a pop. 486226633Sdim #pragma GCC diagnostic warning "-Wformat" 487226633Sdim #pragma GCC diagnostic warning "-Wformat-extra-args" 488226633Sdim#endif 489