Home | History | Annotate | Download | only in Windows
      1 //===- Win32/Signals.cpp - Win32 Signals Implementation ---------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file provides the Win32 specific implementation of the Signals class.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 #include "llvm/Support/FileSystem.h"
     14 #include <algorithm>
     15 #include <signal.h>
     16 #include <stdio.h>
     17 
     18 #include "llvm/Support/Format.h"
     19 #include "llvm/Support/raw_ostream.h"
     20 
     21 // The Windows.h header must be after LLVM and standard headers.
     22 #include "WindowsSupport.h"
     23 
     24 #ifdef __MINGW32__
     25  #include <imagehlp.h>
     26 #else
     27  #include <dbghelp.h>
     28 #endif
     29 #include <psapi.h>
     30 
     31 #ifdef _MSC_VER
     32  #pragma comment(lib, "psapi.lib")
     33 #elif __MINGW32__
     34  #if (HAVE_LIBPSAPI != 1)
     35   #error "libpsapi.a should be present"
     36  #endif
     37  // The version of g++ that comes with MinGW does *not* properly understand
     38  // the ll format specifier for printf. However, MinGW passes the format
     39  // specifiers on to the MSVCRT entirely, and the CRT understands the ll
     40  // specifier. So these warnings are spurious in this case. Since we compile
     41  // with -Wall, this will generate these warnings which should be ignored. So
     42  // we will turn off the warnings for this just file. However, MinGW also does
     43  // not support push and pop for diagnostics, so we have to manually turn it
     44  // back on at the end of the file.
     45  #pragma GCC diagnostic ignored "-Wformat"
     46  #pragma GCC diagnostic ignored "-Wformat-extra-args"
     47 
     48  #if !defined(__MINGW64_VERSION_MAJOR)
     49  // MinGW.org does not have updated support for the 64-bit versions of the
     50  // DebugHlp APIs. So we will have to load them manually. The structures and
     51  // method signatures were pulled from DbgHelp.h in the Windows Platform SDK,
     52  // and adjusted for brevity.
     53  typedef struct _IMAGEHLP_LINE64 {
     54    DWORD    SizeOfStruct;
     55    PVOID    Key;
     56    DWORD    LineNumber;
     57    PCHAR    FileName;
     58    DWORD64  Address;
     59  } IMAGEHLP_LINE64, *PIMAGEHLP_LINE64;
     60 
     61  typedef struct _IMAGEHLP_SYMBOL64 {
     62    DWORD   SizeOfStruct;
     63    DWORD64 Address;
     64    DWORD   Size;
     65    DWORD   Flags;
     66    DWORD   MaxNameLength;
     67    CHAR    Name[1];
     68  } IMAGEHLP_SYMBOL64, *PIMAGEHLP_SYMBOL64;
     69 
     70  typedef struct _tagADDRESS64 {
     71    DWORD64       Offset;
     72    WORD          Segment;
     73    ADDRESS_MODE  Mode;
     74  } ADDRESS64, *LPADDRESS64;
     75 
     76  typedef struct _KDHELP64 {
     77    DWORD64   Thread;
     78    DWORD   ThCallbackStack;
     79    DWORD   ThCallbackBStore;
     80    DWORD   NextCallback;
     81    DWORD   FramePointer;
     82    DWORD64   KiCallUserMode;
     83    DWORD64   KeUserCallbackDispatcher;
     84    DWORD64   SystemRangeStart;
     85    DWORD64   KiUserExceptionDispatcher;
     86    DWORD64   StackBase;
     87    DWORD64   StackLimit;
     88    DWORD64   Reserved[5];
     89  } KDHELP64, *PKDHELP64;
     90 
     91  typedef struct _tagSTACKFRAME64 {
     92    ADDRESS64   AddrPC;
     93    ADDRESS64   AddrReturn;
     94    ADDRESS64   AddrFrame;
     95    ADDRESS64   AddrStack;
     96    ADDRESS64   AddrBStore;
     97    PVOID       FuncTableEntry;
     98    DWORD64     Params[4];
     99    BOOL        Far;
    100    BOOL        Virtual;
    101    DWORD64     Reserved[3];
    102    KDHELP64    KdHelp;
    103  } STACKFRAME64, *LPSTACKFRAME64;
    104  #endif // !defined(__MINGW64_VERSION_MAJOR)
    105 #endif // __MINGW32__
    106 
    107 typedef BOOL (__stdcall *PREAD_PROCESS_MEMORY_ROUTINE64)(HANDLE hProcess,
    108                       DWORD64 qwBaseAddress, PVOID lpBuffer, DWORD nSize,
    109                       LPDWORD lpNumberOfBytesRead);
    110 
    111 typedef PVOID (__stdcall *PFUNCTION_TABLE_ACCESS_ROUTINE64)( HANDLE ahProcess,
    112                       DWORD64 AddrBase);
    113 
    114 typedef DWORD64 (__stdcall *PGET_MODULE_BASE_ROUTINE64)(HANDLE hProcess,
    115                       DWORD64 Address);
    116 
    117 typedef DWORD64 (__stdcall *PTRANSLATE_ADDRESS_ROUTINE64)(HANDLE hProcess,
    118                       HANDLE hThread, LPADDRESS64 lpaddr);
    119 
    120 typedef BOOL (WINAPI *fpStackWalk64)(DWORD, HANDLE, HANDLE, LPSTACKFRAME64,
    121                       PVOID, PREAD_PROCESS_MEMORY_ROUTINE64,
    122                       PFUNCTION_TABLE_ACCESS_ROUTINE64,
    123                       PGET_MODULE_BASE_ROUTINE64,
    124                       PTRANSLATE_ADDRESS_ROUTINE64);
    125 static fpStackWalk64 fStackWalk64;
    126 
    127 typedef DWORD64 (WINAPI *fpSymGetModuleBase64)(HANDLE, DWORD64);
    128 static fpSymGetModuleBase64 fSymGetModuleBase64;
    129 
    130 typedef BOOL (WINAPI *fpSymGetSymFromAddr64)(HANDLE, DWORD64,
    131                       PDWORD64, PIMAGEHLP_SYMBOL64);
    132 static fpSymGetSymFromAddr64 fSymGetSymFromAddr64;
    133 
    134 typedef BOOL (WINAPI *fpSymGetLineFromAddr64)(HANDLE, DWORD64,
    135                       PDWORD, PIMAGEHLP_LINE64);
    136 static fpSymGetLineFromAddr64 fSymGetLineFromAddr64;
    137 
    138 typedef BOOL(WINAPI *fpSymGetModuleInfo64)(HANDLE hProcess, DWORD64 dwAddr,
    139                                            PIMAGEHLP_MODULE64 ModuleInfo);
    140 static fpSymGetModuleInfo64 fSymGetModuleInfo64;
    141 
    142 typedef PVOID (WINAPI *fpSymFunctionTableAccess64)(HANDLE, DWORD64);
    143 static fpSymFunctionTableAccess64 fSymFunctionTableAccess64;
    144 
    145 typedef DWORD (WINAPI *fpSymSetOptions)(DWORD);
    146 static fpSymSetOptions fSymSetOptions;
    147 
    148 typedef BOOL (WINAPI *fpSymInitialize)(HANDLE, PCSTR, BOOL);
    149 static fpSymInitialize fSymInitialize;
    150 
    151 typedef BOOL (WINAPI *fpEnumerateLoadedModules)(HANDLE,PENUMLOADED_MODULES_CALLBACK64,PVOID);
    152 static fpEnumerateLoadedModules fEnumerateLoadedModules;
    153 
    154 static bool load64BitDebugHelp(void) {
    155   HMODULE hLib = ::LoadLibraryW(L"Dbghelp.dll");
    156   if (hLib) {
    157     fStackWalk64 = (fpStackWalk64)
    158                       ::GetProcAddress(hLib, "StackWalk64");
    159     fSymGetModuleBase64 = (fpSymGetModuleBase64)
    160                       ::GetProcAddress(hLib, "SymGetModuleBase64");
    161     fSymGetSymFromAddr64 = (fpSymGetSymFromAddr64)
    162                       ::GetProcAddress(hLib, "SymGetSymFromAddr64");
    163     fSymGetLineFromAddr64 = (fpSymGetLineFromAddr64)
    164                       ::GetProcAddress(hLib, "SymGetLineFromAddr64");
    165     fSymGetModuleInfo64 = (fpSymGetModuleInfo64)
    166                       ::GetProcAddress(hLib, "SymGetModuleInfo64");
    167     fSymFunctionTableAccess64 = (fpSymFunctionTableAccess64)
    168                      ::GetProcAddress(hLib, "SymFunctionTableAccess64");
    169     fSymSetOptions = (fpSymSetOptions)::GetProcAddress(hLib, "SymSetOptions");
    170     fSymInitialize = (fpSymInitialize)::GetProcAddress(hLib, "SymInitialize");
    171     fEnumerateLoadedModules = (fpEnumerateLoadedModules)
    172       ::GetProcAddress(hLib, "EnumerateLoadedModules64");
    173   }
    174   return fStackWalk64 && fSymInitialize && fSymSetOptions;
    175 }
    176 
    177 using namespace llvm;
    178 
    179 // Forward declare.
    180 static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep);
    181 static BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType);
    182 
    183 // InterruptFunction - The function to call if ctrl-c is pressed.
    184 static void (*InterruptFunction)() = 0;
    185 
    186 static std::vector<std::string> *FilesToRemove = NULL;
    187 static bool RegisteredUnhandledExceptionFilter = false;
    188 static bool CleanupExecuted = false;
    189 static PTOP_LEVEL_EXCEPTION_FILTER OldFilter = NULL;
    190 
    191 // Windows creates a new thread to execute the console handler when an event
    192 // (such as CTRL/C) occurs.  This causes concurrency issues with the above
    193 // globals which this critical section addresses.
    194 static CRITICAL_SECTION CriticalSection;
    195 static bool CriticalSectionInitialized = false;
    196 
    197 enum {
    198 #if defined(_M_X64)
    199   NativeMachineType = IMAGE_FILE_MACHINE_AMD64
    200 #else
    201   NativeMachineType = IMAGE_FILE_MACHINE_I386
    202 #endif
    203 };
    204 
    205 static bool printStackTraceWithLLVMSymbolizer(llvm::raw_ostream &OS,
    206                                               HANDLE hProcess, HANDLE hThread,
    207                                               STACKFRAME64 &StackFrameOrig,
    208                                               CONTEXT *ContextOrig) {
    209   // StackWalk64 modifies the incoming stack frame and context, so copy them.
    210   STACKFRAME64 StackFrame = StackFrameOrig;
    211 
    212   // Copy the register context so that we don't modify it while we unwind. We
    213   // could use InitializeContext + CopyContext, but that's only required to get
    214   // at AVX registers, which typically aren't needed by StackWalk64. Reduce the
    215   // flag set to indicate that there's less data.
    216   CONTEXT Context = *ContextOrig;
    217   Context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
    218 
    219   static void *StackTrace[256];
    220   size_t Depth = 0;
    221   while (fStackWalk64(NativeMachineType, hProcess, hThread, &StackFrame,
    222                       &Context, 0, fSymFunctionTableAccess64,
    223                       fSymGetModuleBase64, 0)) {
    224     if (StackFrame.AddrFrame.Offset == 0)
    225       break;
    226     StackTrace[Depth++] = (void *)(uintptr_t)StackFrame.AddrPC.Offset;
    227     if (Depth >= array_lengthof(StackTrace))
    228       break;
    229   }
    230 
    231   return printSymbolizedStackTrace(&StackTrace[0], Depth, OS);
    232 }
    233 
    234 namespace {
    235 struct FindModuleData {
    236   void **StackTrace;
    237   int Depth;
    238   const char **Modules;
    239   intptr_t *Offsets;
    240   StringSaver *StrPool;
    241 };
    242 }
    243 
    244 static BOOL CALLBACK findModuleCallback(WIN32_ELMCB_PCSTR ModuleName,
    245                                         DWORD64 ModuleBase, ULONG ModuleSize,
    246                                         void *VoidData) {
    247   FindModuleData *Data = (FindModuleData*)VoidData;
    248   intptr_t Beg = ModuleBase;
    249   intptr_t End = Beg + ModuleSize;
    250   for (int I = 0; I < Data->Depth; I++) {
    251     if (Data->Modules[I])
    252       continue;
    253     intptr_t Addr = (intptr_t)Data->StackTrace[I];
    254     if (Beg <= Addr && Addr < End) {
    255       Data->Modules[I] = Data->StrPool->save(ModuleName);
    256       Data->Offsets[I] = Addr - Beg;
    257     }
    258   }
    259   return TRUE;
    260 }
    261 
    262 static bool findModulesAndOffsets(void **StackTrace, int Depth,
    263                                   const char **Modules, intptr_t *Offsets,
    264                                   const char *MainExecutableName,
    265                                   StringSaver &StrPool) {
    266   if (!fEnumerateLoadedModules)
    267     return false;
    268   FindModuleData Data;
    269   Data.StackTrace = StackTrace;
    270   Data.Depth = Depth;
    271   Data.Modules = Modules;
    272   Data.Offsets = Offsets;
    273   Data.StrPool = &StrPool;
    274   fEnumerateLoadedModules(GetCurrentProcess(), findModuleCallback, &Data);
    275   return true;
    276 }
    277 
    278 static void PrintStackTraceForThread(llvm::raw_ostream &OS, HANDLE hProcess,
    279                                      HANDLE hThread, STACKFRAME64 &StackFrame,
    280                                      CONTEXT *Context) {
    281   // Initialize the symbol handler.
    282   fSymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES);
    283   fSymInitialize(hProcess, NULL, TRUE);
    284 
    285   // Try llvm-symbolizer first. llvm-symbolizer knows how to deal with both PDBs
    286   // and DWARF, so it should do a good job regardless of what debug info or
    287   // linker is in use.
    288   if (printStackTraceWithLLVMSymbolizer(OS, hProcess, hThread, StackFrame,
    289                                         Context)) {
    290     return;
    291   }
    292 
    293   while (true) {
    294     if (!fStackWalk64(NativeMachineType, hProcess, hThread, &StackFrame,
    295                       Context, 0, fSymFunctionTableAccess64,
    296                       fSymGetModuleBase64, 0)) {
    297       break;
    298     }
    299 
    300     if (StackFrame.AddrFrame.Offset == 0)
    301       break;
    302 
    303     using namespace llvm;
    304     // Print the PC in hexadecimal.
    305     DWORD64 PC = StackFrame.AddrPC.Offset;
    306 #if defined(_M_X64)
    307     OS << format("0x%016llX", PC);
    308 #elif defined(_M_IX86)
    309     OS << format("0x%08lX", static_cast<DWORD>(PC));
    310 #endif
    311 
    312 // Print the parameters.  Assume there are four.
    313 #if defined(_M_X64)
    314     OS << format(" (0x%016llX 0x%016llX 0x%016llX 0x%016llX)",
    315             StackFrame.Params[0], StackFrame.Params[1], StackFrame.Params[2],
    316             StackFrame.Params[3]);
    317 #elif defined(_M_IX86)
    318     OS << format(" (0x%08lX 0x%08lX 0x%08lX 0x%08lX)",
    319             static_cast<DWORD>(StackFrame.Params[0]),
    320             static_cast<DWORD>(StackFrame.Params[1]),
    321             static_cast<DWORD>(StackFrame.Params[2]),
    322             static_cast<DWORD>(StackFrame.Params[3]));
    323 #endif
    324     // Verify the PC belongs to a module in this process.
    325     if (!fSymGetModuleBase64(hProcess, PC)) {
    326       OS << " <unknown module>\n";
    327       continue;
    328     }
    329 
    330     // Print the symbol name.
    331     char buffer[512];
    332     IMAGEHLP_SYMBOL64 *symbol = reinterpret_cast<IMAGEHLP_SYMBOL64 *>(buffer);
    333     memset(symbol, 0, sizeof(IMAGEHLP_SYMBOL64));
    334     symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
    335     symbol->MaxNameLength = 512 - sizeof(IMAGEHLP_SYMBOL64);
    336 
    337     DWORD64 dwDisp;
    338     if (!fSymGetSymFromAddr64(hProcess, PC, &dwDisp, symbol)) {
    339       OS << '\n';
    340       continue;
    341     }
    342 
    343     buffer[511] = 0;
    344     if (dwDisp > 0)
    345       OS << format(", %s() + 0x%llX bytes(s)", (const char*)symbol->Name,
    346                    dwDisp);
    347     else
    348       OS << format(", %s", (const char*)symbol->Name);
    349 
    350     // Print the source file and line number information.
    351     IMAGEHLP_LINE64 line = {};
    352     DWORD dwLineDisp;
    353     line.SizeOfStruct = sizeof(line);
    354     if (fSymGetLineFromAddr64(hProcess, PC, &dwLineDisp, &line)) {
    355       OS << format(", %s, line %lu", line.FileName, line.LineNumber);
    356       if (dwLineDisp > 0)
    357         OS << format(" + 0x%lX byte(s)", dwLineDisp);
    358     }
    359 
    360     OS << '\n';
    361   }
    362 }
    363 
    364 namespace llvm {
    365 
    366 //===----------------------------------------------------------------------===//
    367 //=== WARNING: Implementation here must contain only Win32 specific code
    368 //===          and must not be UNIX code
    369 //===----------------------------------------------------------------------===//
    370 
    371 #ifdef _MSC_VER
    372 /// AvoidMessageBoxHook - Emulates hitting "retry" from an "abort, retry,
    373 /// ignore" CRT debug report dialog.  "retry" raises an exception which
    374 /// ultimately triggers our stack dumper.
    375 static LLVM_ATTRIBUTE_UNUSED int
    376 AvoidMessageBoxHook(int ReportType, char *Message, int *Return) {
    377   // Set *Return to the retry code for the return value of _CrtDbgReport:
    378   // http://msdn.microsoft.com/en-us/library/8hyw4sy7(v=vs.71).aspx
    379   // This may also trigger just-in-time debugging via DebugBreak().
    380   if (Return)
    381     *Return = 1;
    382   // Don't call _CrtDbgReport.
    383   return TRUE;
    384 }
    385 
    386 #endif
    387 
    388 extern "C" void HandleAbort(int Sig) {
    389   if (Sig == SIGABRT) {
    390     LLVM_BUILTIN_TRAP;
    391   }
    392 }
    393 
    394 static void InitializeThreading() {
    395   if (CriticalSectionInitialized)
    396     return;
    397 
    398   // Now's the time to create the critical section. This is the first time
    399   // through here, and there's only one thread.
    400   InitializeCriticalSection(&CriticalSection);
    401   CriticalSectionInitialized = true;
    402 }
    403 
    404 static void RegisterHandler() {
    405   // If we cannot load up the APIs (which would be unexpected as they should
    406   // exist on every version of Windows we support), we will bail out since
    407   // there would be nothing to report.
    408   assert(load64BitDebugHelp() && "These APIs should always be available");
    409 
    410   if (RegisteredUnhandledExceptionFilter) {
    411     EnterCriticalSection(&CriticalSection);
    412     return;
    413   }
    414 
    415   InitializeThreading();
    416 
    417   // Enter it immediately.  Now if someone hits CTRL/C, the console handler
    418   // can't proceed until the globals are updated.
    419   EnterCriticalSection(&CriticalSection);
    420 
    421   RegisteredUnhandledExceptionFilter = true;
    422   OldFilter = SetUnhandledExceptionFilter(LLVMUnhandledExceptionFilter);
    423   SetConsoleCtrlHandler(LLVMConsoleCtrlHandler, TRUE);
    424 
    425   // IMPORTANT NOTE: Caller must call LeaveCriticalSection(&CriticalSection) or
    426   // else multi-threading problems will ensue.
    427 }
    428 
    429 // RemoveFileOnSignal - The public API
    430 bool sys::RemoveFileOnSignal(StringRef Filename, std::string* ErrMsg) {
    431   RegisterHandler();
    432 
    433   if (CleanupExecuted) {
    434     if (ErrMsg)
    435       *ErrMsg = "Process terminating -- cannot register for removal";
    436     return true;
    437   }
    438 
    439   if (FilesToRemove == NULL)
    440     FilesToRemove = new std::vector<std::string>;
    441 
    442   FilesToRemove->push_back(Filename);
    443 
    444   LeaveCriticalSection(&CriticalSection);
    445   return false;
    446 }
    447 
    448 // DontRemoveFileOnSignal - The public API
    449 void sys::DontRemoveFileOnSignal(StringRef Filename) {
    450   if (FilesToRemove == NULL)
    451     return;
    452 
    453   RegisterHandler();
    454 
    455   std::vector<std::string>::reverse_iterator I =
    456   std::find(FilesToRemove->rbegin(), FilesToRemove->rend(), Filename);
    457   if (I != FilesToRemove->rend())
    458     FilesToRemove->erase(I.base()-1);
    459 
    460   LeaveCriticalSection(&CriticalSection);
    461 }
    462 
    463 void sys::DisableSystemDialogsOnCrash() {
    464   // Crash to stack trace handler on abort.
    465   signal(SIGABRT, HandleAbort);
    466 
    467   // The following functions are not reliably accessible on MinGW.
    468 #ifdef _MSC_VER
    469   // We're already handling writing a "something went wrong" message.
    470   _set_abort_behavior(0, _WRITE_ABORT_MSG);
    471   // Disable Dr. Watson.
    472   _set_abort_behavior(0, _CALL_REPORTFAULT);
    473   _CrtSetReportHook(AvoidMessageBoxHook);
    474 #endif
    475 
    476   // Disable standard error dialog box.
    477   SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX |
    478                SEM_NOOPENFILEERRORBOX);
    479   _set_error_mode(_OUT_TO_STDERR);
    480 }
    481 
    482 /// PrintStackTraceOnErrorSignal - When an error signal (such as SIBABRT or
    483 /// SIGSEGV) is delivered to the process, print a stack trace and then exit.
    484 void sys::PrintStackTraceOnErrorSignal(bool DisableCrashReporting) {
    485   DisableSystemDialogsOnCrash();
    486   RegisterHandler();
    487   LeaveCriticalSection(&CriticalSection);
    488 }
    489 }
    490 
    491 #if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
    492 // Provide a prototype for RtlCaptureContext, mingw32 from mingw.org is
    493 // missing it but mingw-w64 has it.
    494 extern "C" VOID WINAPI RtlCaptureContext(PCONTEXT ContextRecord);
    495 #endif
    496 
    497 void llvm::sys::PrintStackTrace(raw_ostream &OS) {
    498   STACKFRAME64 StackFrame = {};
    499   CONTEXT Context = {};
    500   ::RtlCaptureContext(&Context);
    501 #if defined(_M_X64)
    502   StackFrame.AddrPC.Offset = Context.Rip;
    503   StackFrame.AddrStack.Offset = Context.Rsp;
    504   StackFrame.AddrFrame.Offset = Context.Rbp;
    505 #else
    506   StackFrame.AddrPC.Offset = Context.Eip;
    507   StackFrame.AddrStack.Offset = Context.Esp;
    508   StackFrame.AddrFrame.Offset = Context.Ebp;
    509 #endif
    510   StackFrame.AddrPC.Mode = AddrModeFlat;
    511   StackFrame.AddrStack.Mode = AddrModeFlat;
    512   StackFrame.AddrFrame.Mode = AddrModeFlat;
    513   PrintStackTraceForThread(OS, GetCurrentProcess(), GetCurrentThread(),
    514                            StackFrame, &Context);
    515 }
    516 
    517 
    518 void llvm::sys::SetInterruptFunction(void (*IF)()) {
    519   RegisterHandler();
    520   InterruptFunction = IF;
    521   LeaveCriticalSection(&CriticalSection);
    522 }
    523 
    524 
    525 /// AddSignalHandler - Add a function to be called when a signal is delivered
    526 /// to the process.  The handler can have a cookie passed to it to identify
    527 /// what instance of the handler it is.
    528 void llvm::sys::AddSignalHandler(void (*FnPtr)(void *), void *Cookie) {
    529   CallBacksToRun->push_back(std::make_pair(FnPtr, Cookie));
    530   RegisterHandler();
    531   LeaveCriticalSection(&CriticalSection);
    532 }
    533 
    534 static void Cleanup() {
    535   if (CleanupExecuted)
    536     return;
    537 
    538   EnterCriticalSection(&CriticalSection);
    539 
    540   // Prevent other thread from registering new files and directories for
    541   // removal, should we be executing because of the console handler callback.
    542   CleanupExecuted = true;
    543 
    544   // FIXME: open files cannot be deleted.
    545   if (FilesToRemove != NULL)
    546     while (!FilesToRemove->empty()) {
    547       llvm::sys::fs::remove(FilesToRemove->back());
    548       FilesToRemove->pop_back();
    549     }
    550   llvm::sys::RunSignalHandlers();
    551   LeaveCriticalSection(&CriticalSection);
    552 }
    553 
    554 void llvm::sys::RunInterruptHandlers() {
    555   // The interrupt handler may be called from an interrupt, but it may also be
    556   // called manually (such as the case of report_fatal_error with no registered
    557   // error handler). We must ensure that the critical section is properly
    558   // initialized.
    559   InitializeThreading();
    560   Cleanup();
    561 }
    562 
    563 static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep) {
    564   Cleanup();
    565 
    566   // Initialize the STACKFRAME structure.
    567   STACKFRAME64 StackFrame = {};
    568 
    569 #if defined(_M_X64)
    570   StackFrame.AddrPC.Offset = ep->ContextRecord->Rip;
    571   StackFrame.AddrPC.Mode = AddrModeFlat;
    572   StackFrame.AddrStack.Offset = ep->ContextRecord->Rsp;
    573   StackFrame.AddrStack.Mode = AddrModeFlat;
    574   StackFrame.AddrFrame.Offset = ep->ContextRecord->Rbp;
    575   StackFrame.AddrFrame.Mode = AddrModeFlat;
    576 #elif defined(_M_IX86)
    577   StackFrame.AddrPC.Offset = ep->ContextRecord->Eip;
    578   StackFrame.AddrPC.Mode = AddrModeFlat;
    579   StackFrame.AddrStack.Offset = ep->ContextRecord->Esp;
    580   StackFrame.AddrStack.Mode = AddrModeFlat;
    581   StackFrame.AddrFrame.Offset = ep->ContextRecord->Ebp;
    582   StackFrame.AddrFrame.Mode = AddrModeFlat;
    583 #endif
    584 
    585   HANDLE hProcess = GetCurrentProcess();
    586   HANDLE hThread = GetCurrentThread();
    587   PrintStackTraceForThread(llvm::errs(), hProcess, hThread, StackFrame,
    588                            ep->ContextRecord);
    589 
    590   _exit(ep->ExceptionRecord->ExceptionCode);
    591 }
    592 
    593 static BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType) {
    594   // We are running in our very own thread, courtesy of Windows.
    595   EnterCriticalSection(&CriticalSection);
    596   Cleanup();
    597 
    598   // If an interrupt function has been set, go and run one it; otherwise,
    599   // the process dies.
    600   void (*IF)() = InterruptFunction;
    601   InterruptFunction = 0;      // Don't run it on another CTRL-C.
    602 
    603   if (IF) {
    604     // Note: if the interrupt function throws an exception, there is nothing
    605     // to catch it in this thread so it will kill the process.
    606     IF();                     // Run it now.
    607     LeaveCriticalSection(&CriticalSection);
    608     return TRUE;              // Don't kill the process.
    609   }
    610 
    611   // Allow normal processing to take place; i.e., the process dies.
    612   LeaveCriticalSection(&CriticalSection);
    613   return FALSE;
    614 }
    615 
    616 #if __MINGW32__
    617  // We turned these warnings off for this file so that MinGW-g++ doesn't
    618  // complain about the ll format specifiers used.  Now we are turning the
    619  // warnings back on.  If MinGW starts to support diagnostic stacks, we can
    620  // replace this with a pop.
    621  #pragma GCC diagnostic warning "-Wformat"
    622  #pragma GCC diagnostic warning "-Wformat-extra-args"
    623 #endif
    624