Signals.inc revision 5d2f8c31556b6a5ce29d2cad314bc48af879c5b3
1496c277a6d161413e3f6976c9991ddccd8ecae8aReid Spencer//===- Win32/Signals.cpp - Win32 Signals Implementation ---------*- C++ -*-===//
284ba14f6d016ab181f1fd5de8050e1b9bbc83904Mikhail Glushenkov//
3496c277a6d161413e3f6976c9991ddccd8ecae8aReid Spencer//                     The LLVM Compiler Infrastructure
4496c277a6d161413e3f6976c9991ddccd8ecae8aReid Spencer//
54ee451de366474b9c228b4e5fa573795a715216dChris Lattner// This file is distributed under the University of Illinois Open Source
64ee451de366474b9c228b4e5fa573795a715216dChris Lattner// License. See LICENSE.TXT for details.
784ba14f6d016ab181f1fd5de8050e1b9bbc83904Mikhail Glushenkov//
8496c277a6d161413e3f6976c9991ddccd8ecae8aReid Spencer//===----------------------------------------------------------------------===//
9496c277a6d161413e3f6976c9991ddccd8ecae8aReid Spencer//
10496c277a6d161413e3f6976c9991ddccd8ecae8aReid Spencer// This file provides the Win32 specific implementation of the Signals class.
11496c277a6d161413e3f6976c9991ddccd8ecae8aReid Spencer//
12496c277a6d161413e3f6976c9991ddccd8ecae8aReid Spencer//===----------------------------------------------------------------------===//
13496c277a6d161413e3f6976c9991ddccd8ecae8aReid Spencer
141f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "Windows.h"
15ced4110f5b068b9b64e3a55a9ee57b621ce4acb1Reid Spencer#include <stdio.h>
1690b54138834a057179c7a02931217ab5a82ed389Reid Spencer#include <vector>
1748fe63526e35ddaee7e98879596a569911f41319Sebastian Redl#include <algorithm>
1890b54138834a057179c7a02931217ab5a82ed389Reid Spencer
1923a1cf3e085325783ef2e4078308f913cba5012eJeff Cohen#ifdef __MINGW32__
2048fdf91d0f17b19bb7345156b928689df94d0c6cReid Spencer #include <imagehlp.h>
21f6cbc0fd6494e50c48ebe4b5eecde1c70bcd5165Reid Spencer#else
2248fdf91d0f17b19bb7345156b928689df94d0c6cReid Spencer #include <dbghelp.h>
23f6cbc0fd6494e50c48ebe4b5eecde1c70bcd5165Reid Spencer#endif
24f6cbc0fd6494e50c48ebe4b5eecde1c70bcd5165Reid Spencer#include <psapi.h>
2590b54138834a057179c7a02931217ab5a82ed389Reid Spencer
260bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer#ifdef _MSC_VER
270bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer #pragma comment(lib, "psapi.lib")
280bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer #pragma comment(lib, "dbghelp.lib")
290bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer#elif __MINGW32__
3048fdf91d0f17b19bb7345156b928689df94d0c6cReid Spencer #if ((HAVE_LIBIMAGEHLP != 1) || (HAVE_LIBPSAPI != 1))
3148fdf91d0f17b19bb7345156b928689df94d0c6cReid Spencer  #error "libimagehlp.a & libpsapi.a should be present"
3248fdf91d0f17b19bb7345156b928689df94d0c6cReid Spencer #endif
330bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer // The version of g++ that comes with MinGW does *not* properly understand
340bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer // the ll format specifier for printf. However, MinGW passes the format
350bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer // specifiers on to the MSVCRT entirely, and the CRT understands the ll
360bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer // specifier. So these warnings are spurious in this case. Since we compile
370bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer // with -Wall, this will generate these warnings which should be ignored. So
380bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer // we will turn off the warnings for this just file. However, MinGW also does
390bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer // not support push and pop for diagnostics, so we have to manually turn it
400bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer // back on at the end of the file.
410bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer #pragma GCC diagnostic ignored "-Wformat"
420bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer #pragma GCC diagnostic ignored "-Wformat-extra-args"
430bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer
44cda065df614dbf7ca0f6a169e9536d2241539b75Anton Korobeynikov #if !defined(__MINGW64_VERSION_MAJOR)
45cda065df614dbf7ca0f6a169e9536d2241539b75Anton Korobeynikov // MinGW.org does not have updated support for the 64-bit versions of the
46cda065df614dbf7ca0f6a169e9536d2241539b75Anton Korobeynikov // DebugHlp APIs. So we will have to load them manually. The structures and
47cda065df614dbf7ca0f6a169e9536d2241539b75Anton Korobeynikov // method signatures were pulled from DbgHelp.h in the Windows Platform SDK,
48cda065df614dbf7ca0f6a169e9536d2241539b75Anton Korobeynikov // and adjusted for brevity.
490bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer typedef struct _IMAGEHLP_LINE64 {
500bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer   DWORD    SizeOfStruct;
510bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer   PVOID    Key;
520bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer   DWORD    LineNumber;
530bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer   PCHAR    FileName;
540bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer   DWORD64  Address;
550bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer } IMAGEHLP_LINE64, *PIMAGEHLP_LINE64;
560bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer
570bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer typedef struct _IMAGEHLP_SYMBOL64 {
580bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer   DWORD   SizeOfStruct;
590bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer   DWORD64 Address;
600bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer   DWORD   Size;
610bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer   DWORD   Flags;
620bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer   DWORD   MaxNameLength;
630bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer   CHAR    Name[1];
640bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer } IMAGEHLP_SYMBOL64, *PIMAGEHLP_SYMBOL64;
650bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer
660bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer typedef struct _tagADDRESS64 {
670bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer   DWORD64       Offset;
680bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer   WORD          Segment;
690bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer   ADDRESS_MODE  Mode;
700bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer } ADDRESS64, *LPADDRESS64;
710bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer
720bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer typedef struct _KDHELP64 {
730bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer   DWORD64   Thread;
740bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer   DWORD   ThCallbackStack;
750bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer   DWORD   ThCallbackBStore;
760bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer   DWORD   NextCallback;
770bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer   DWORD   FramePointer;
780bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer   DWORD64   KiCallUserMode;
790bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer   DWORD64   KeUserCallbackDispatcher;
800bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer   DWORD64   SystemRangeStart;
810bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer   DWORD64   KiUserExceptionDispatcher;
820bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer   DWORD64   StackBase;
830bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer   DWORD64   StackLimit;
840bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer   DWORD64   Reserved[5];
850bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer } KDHELP64, *PKDHELP64;
860bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer
870bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer typedef struct _tagSTACKFRAME64 {
880bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer   ADDRESS64   AddrPC;
890bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer   ADDRESS64   AddrReturn;
900bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer   ADDRESS64   AddrFrame;
910bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer   ADDRESS64   AddrStack;
920bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer   ADDRESS64   AddrBStore;
930bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer   PVOID       FuncTableEntry;
940bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer   DWORD64     Params[4];
950bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer   BOOL        Far;
960bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer   BOOL        Virtual;
970bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer   DWORD64     Reserved[3];
980bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer   KDHELP64    KdHelp;
990bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer } STACKFRAME64, *LPSTACKFRAME64;
1000bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer
1010bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencertypedef BOOL (__stdcall *PREAD_PROCESS_MEMORY_ROUTINE64)(HANDLE hProcess,
1020bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer                      DWORD64 qwBaseAddress, PVOID lpBuffer, DWORD nSize,
1030bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer                      LPDWORD lpNumberOfBytesRead);
1040bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer
1050bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencertypedef PVOID (__stdcall *PFUNCTION_TABLE_ACCESS_ROUTINE64)( HANDLE ahProcess,
1060bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer                      DWORD64 AddrBase);
1070bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer
1080bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencertypedef DWORD64 (__stdcall *PGET_MODULE_BASE_ROUTINE64)(HANDLE hProcess,
1090bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer                      DWORD64 Address);
1100bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer
1110bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencertypedef DWORD64 (__stdcall *PTRANSLATE_ADDRESS_ROUTINE64)(HANDLE hProcess,
1120bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer                      HANDLE hThread, LPADDRESS64 lpaddr);
1130bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer
1140bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencertypedef BOOL (WINAPI *fpStackWalk64)(DWORD, HANDLE, HANDLE, LPSTACKFRAME64,
1150bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer                      PVOID, PREAD_PROCESS_MEMORY_ROUTINE64,
1160bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer                      PFUNCTION_TABLE_ACCESS_ROUTINE64,
1170bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer                      PGET_MODULE_BASE_ROUTINE64,
1180bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer                      PTRANSLATE_ADDRESS_ROUTINE64);
1190bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencerstatic fpStackWalk64 StackWalk64;
1200bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer
1210bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencertypedef DWORD64 (WINAPI *fpSymGetModuleBase64)(HANDLE, DWORD64);
1220bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencerstatic fpSymGetModuleBase64 SymGetModuleBase64;
1230bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer
1240bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencertypedef BOOL (WINAPI *fpSymGetSymFromAddr64)(HANDLE, DWORD64,
1250bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer                      PDWORD64, PIMAGEHLP_SYMBOL64);
1260bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencerstatic fpSymGetSymFromAddr64 SymGetSymFromAddr64;
1270bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer
1280bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencertypedef BOOL (WINAPI *fpSymGetLineFromAddr64)(HANDLE, DWORD64,
1290bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer                      PDWORD, PIMAGEHLP_LINE64);
1300bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencerstatic fpSymGetLineFromAddr64 SymGetLineFromAddr64;
1310bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer
1320bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencertypedef PVOID (WINAPI *fpSymFunctionTableAccess64)(HANDLE, DWORD64);
1330bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencerstatic fpSymFunctionTableAccess64 SymFunctionTableAccess64;
1340bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer
1350bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencerstatic bool load64BitDebugHelp(void) {
1360bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer  HMODULE hLib = ::LoadLibrary("Dbghelp.dll");
1370bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer  if (hLib) {
1380bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer    StackWalk64 = (fpStackWalk64)
1390bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer                      ::GetProcAddress(hLib, "StackWalk64");
1400bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer    SymGetModuleBase64 = (fpSymGetModuleBase64)
1410bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer                      ::GetProcAddress(hLib, "SymGetModuleBase64");
1420bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer    SymGetSymFromAddr64 = (fpSymGetSymFromAddr64)
1430bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer                      ::GetProcAddress(hLib, "SymGetSymFromAddr64");
1440bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer    SymGetLineFromAddr64 = (fpSymGetLineFromAddr64)
1450bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer                      ::GetProcAddress(hLib, "SymGetLineFromAddr64");
1460bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer    SymFunctionTableAccess64 = (fpSymFunctionTableAccess64)
1470bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer                     ::GetProcAddress(hLib, "SymFunctionTableAccess64");
1480bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer  }
1490bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer  return StackWalk64 != NULL;
1500bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer}
151cda065df614dbf7ca0f6a169e9536d2241539b75Anton Korobeynikov #endif // !defined(__MINGW64_VERSION_MAJOR)
1520bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer#endif // __MINGW32__
15390b54138834a057179c7a02931217ab5a82ed389Reid Spencer
15490b54138834a057179c7a02931217ab5a82ed389Reid Spencer// Forward declare.
15590b54138834a057179c7a02931217ab5a82ed389Reid Spencerstatic LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep);
15690b54138834a057179c7a02931217ab5a82ed389Reid Spencerstatic BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType);
15790b54138834a057179c7a02931217ab5a82ed389Reid Spencer
158ee841a1a8735805f84d609ae105bec92525033c6Jeff Cohen// InterruptFunction - The function to call if ctrl-c is pressed.
159ee841a1a8735805f84d609ae105bec92525033c6Jeff Cohenstatic void (*InterruptFunction)() = 0;
160ee841a1a8735805f84d609ae105bec92525033c6Jeff Cohen
161ced4110f5b068b9b64e3a55a9ee57b621ce4acb1Reid Spencerstatic std::vector<llvm::sys::Path> *FilesToRemove = NULL;
16235033a5876aa27ea5729bc29b41bb4460a303cadChris Lattnerstatic std::vector<std::pair<void(*)(void*), void*> > *CallBacksToRun = 0;
16390b54138834a057179c7a02931217ab5a82ed389Reid Spencerstatic bool RegisteredUnhandledExceptionFilter = false;
1647b60a15abc155196d9515a1e242ec0137afff753Reid Spencerstatic bool CleanupExecuted = false;
165df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbarstatic bool ExitOnUnhandledExceptions = false;
1667b60a15abc155196d9515a1e242ec0137afff753Reid Spencerstatic PTOP_LEVEL_EXCEPTION_FILTER OldFilter = NULL;
167298d6c14ca1936677aaf6cca3efc569b6e53d294Reid Spencer
168298d6c14ca1936677aaf6cca3efc569b6e53d294Reid Spencer// Windows creates a new thread to execute the console handler when an event
169298d6c14ca1936677aaf6cca3efc569b6e53d294Reid Spencer// (such as CTRL/C) occurs.  This causes concurrency issues with the above
170298d6c14ca1936677aaf6cca3efc569b6e53d294Reid Spencer// globals which this critical section addresses.
17190b54138834a057179c7a02931217ab5a82ed389Reid Spencerstatic CRITICAL_SECTION CriticalSection;
17290b54138834a057179c7a02931217ab5a82ed389Reid Spencer
173496c277a6d161413e3f6976c9991ddccd8ecae8aReid Spencernamespace llvm {
174496c277a6d161413e3f6976c9991ddccd8ecae8aReid Spencer
175496c277a6d161413e3f6976c9991ddccd8ecae8aReid Spencer//===----------------------------------------------------------------------===//
17684ba14f6d016ab181f1fd5de8050e1b9bbc83904Mikhail Glushenkov//=== WARNING: Implementation here must contain only Win32 specific code
17790b54138834a057179c7a02931217ab5a82ed389Reid Spencer//===          and must not be UNIX code
178496c277a6d161413e3f6976c9991ddccd8ecae8aReid Spencer//===----------------------------------------------------------------------===//
179496c277a6d161413e3f6976c9991ddccd8ecae8aReid Spencer
1803be2d12bdec9ec3a244aae695d3b586ac27dcfdeDaniel Dunbar#ifdef _MSC_VER
181df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar/// CRTReportHook - Function called on a CRT debugging event.
182df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbarstatic int CRTReportHook(int ReportType, char *Message, int *Return) {
183df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar  // Don't cause a DebugBreak() on return.
184df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar  if (Return)
185df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar    *Return = 0;
186df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar
187df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar  switch (ReportType) {
188df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar  default:
189df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar  case _CRT_ASSERT:
190df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar    fprintf(stderr, "CRT assert: %s\n", Message);
191df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar    // FIXME: Is there a way to just crash? Perhaps throw to the unhandled
192df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar    // exception code? Perhaps SetErrorMode() handles this.
193df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar    _exit(3);
194df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar    break;
195df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar  case _CRT_ERROR:
196df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar    fprintf(stderr, "CRT error: %s\n", Message);
197df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar    // FIXME: Is there a way to just crash? Perhaps throw to the unhandled
198df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar    // exception code? Perhaps SetErrorMode() handles this.
199df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar    _exit(3);
200df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar    break;
201df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar  case _CRT_WARN:
202df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar    fprintf(stderr, "CRT warn: %s\n", Message);
203df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar    break;
204df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar  }
205df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar
206df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar  // Don't call _CrtDbgReport.
207df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar  return TRUE;
208df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar}
2093be2d12bdec9ec3a244aae695d3b586ac27dcfdeDaniel Dunbar#endif
21090b54138834a057179c7a02931217ab5a82ed389Reid Spencer
211df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbarstatic void RegisterHandler() {
212cda065df614dbf7ca0f6a169e9536d2241539b75Anton Korobeynikov#if __MINGW32__ && !defined(__MINGW64_VERSION_MAJOR)
213cda065df614dbf7ca0f6a169e9536d2241539b75Anton Korobeynikov  // On MinGW.org, we need to load up the symbols explicitly, because the
2140bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer  // Win32 framework they include does not have support for the 64-bit
2150bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer  // versions of the APIs we need.  If we cannot load up the APIs (which
2160bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer  // would be unexpected as they should exist on every version of Windows
2170bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer  // we support), we will bail out since there would be nothing to report.
2180bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer  if (!load64BitDebugHelp()) {
2190bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer    assert(false && "These APIs should always be available");
2200bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer    return;
2210bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer  }
2220bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer#endif
2230bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer
2247b60a15abc155196d9515a1e242ec0137afff753Reid Spencer  if (RegisteredUnhandledExceptionFilter) {
225298d6c14ca1936677aaf6cca3efc569b6e53d294Reid Spencer    EnterCriticalSection(&CriticalSection);
22690b54138834a057179c7a02931217ab5a82ed389Reid Spencer    return;
227298d6c14ca1936677aaf6cca3efc569b6e53d294Reid Spencer  }
22890b54138834a057179c7a02931217ab5a82ed389Reid Spencer
22990b54138834a057179c7a02931217ab5a82ed389Reid Spencer  // Now's the time to create the critical section.  This is the first time
23090b54138834a057179c7a02931217ab5a82ed389Reid Spencer  // through here, and there's only one thread.
23190b54138834a057179c7a02931217ab5a82ed389Reid Spencer  InitializeCriticalSection(&CriticalSection);
23290b54138834a057179c7a02931217ab5a82ed389Reid Spencer
23390b54138834a057179c7a02931217ab5a82ed389Reid Spencer  // Enter it immediately.  Now if someone hits CTRL/C, the console handler
23490b54138834a057179c7a02931217ab5a82ed389Reid Spencer  // can't proceed until the globals are updated.
23590b54138834a057179c7a02931217ab5a82ed389Reid Spencer  EnterCriticalSection(&CriticalSection);
23690b54138834a057179c7a02931217ab5a82ed389Reid Spencer
23790b54138834a057179c7a02931217ab5a82ed389Reid Spencer  RegisteredUnhandledExceptionFilter = true;
2387b60a15abc155196d9515a1e242ec0137afff753Reid Spencer  OldFilter = SetUnhandledExceptionFilter(LLVMUnhandledExceptionFilter);
23990b54138834a057179c7a02931217ab5a82ed389Reid Spencer  SetConsoleCtrlHandler(LLVMConsoleCtrlHandler, TRUE);
24090b54138834a057179c7a02931217ab5a82ed389Reid Spencer
241df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar  // Environment variable to disable any kind of crash dialog.
242df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar  if (getenv("LLVM_DISABLE_CRT_DEBUG")) {
243a8bbe707dc0c397d4020e7348fda64b3cb2a0e21NAKAMURA Takumi#ifdef _MSC_VER
244df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar    _CrtSetReportHook(CRTReportHook);
245a8bbe707dc0c397d4020e7348fda64b3cb2a0e21NAKAMURA Takumi#endif
246ac25e44d8905e88f91f998ce27a82cea641f5ff9NAKAMURA Takumi    SetErrorMode(SEM_FAILCRITICALERRORS |
247ac25e44d8905e88f91f998ce27a82cea641f5ff9NAKAMURA Takumi                 SEM_NOGPFAULTERRORBOX |
248ac25e44d8905e88f91f998ce27a82cea641f5ff9NAKAMURA Takumi                 SEM_NOOPENFILEERRORBOX);
2493be2d12bdec9ec3a244aae695d3b586ac27dcfdeDaniel Dunbar    ExitOnUnhandledExceptions = true;
250df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar  }
251df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar
25290b54138834a057179c7a02931217ab5a82ed389Reid Spencer  // IMPORTANT NOTE: Caller must call LeaveCriticalSection(&CriticalSection) or
25390b54138834a057179c7a02931217ab5a82ed389Reid Spencer  // else multi-threading problems will ensue.
25490b54138834a057179c7a02931217ab5a82ed389Reid Spencer}
25590b54138834a057179c7a02931217ab5a82ed389Reid Spencer
256496c277a6d161413e3f6976c9991ddccd8ecae8aReid Spencer// RemoveFileOnSignal - The public API
25705545755676b9ff35d244e55d749a15e28bb228bReid Spencerbool sys::RemoveFileOnSignal(const sys::Path &Filename, std::string* ErrMsg) {
25890b54138834a057179c7a02931217ab5a82ed389Reid Spencer  RegisterHandler();
25990b54138834a057179c7a02931217ab5a82ed389Reid Spencer
26005545755676b9ff35d244e55d749a15e28bb228bReid Spencer  if (CleanupExecuted) {
26105545755676b9ff35d244e55d749a15e28bb228bReid Spencer    if (ErrMsg)
26205545755676b9ff35d244e55d749a15e28bb228bReid Spencer      *ErrMsg = "Process terminating -- cannot register for removal";
26305545755676b9ff35d244e55d749a15e28bb228bReid Spencer    return true;
26405545755676b9ff35d244e55d749a15e28bb228bReid Spencer  }
2657b60a15abc155196d9515a1e242ec0137afff753Reid Spencer
26690b54138834a057179c7a02931217ab5a82ed389Reid Spencer  if (FilesToRemove == NULL)
267ced4110f5b068b9b64e3a55a9ee57b621ce4acb1Reid Spencer    FilesToRemove = new std::vector<sys::Path>;
26890b54138834a057179c7a02931217ab5a82ed389Reid Spencer
26998601218901190d9d3bb5ebccae659f8db265b5dReid Spencer  FilesToRemove->push_back(Filename);
27090b54138834a057179c7a02931217ab5a82ed389Reid Spencer
27190b54138834a057179c7a02931217ab5a82ed389Reid Spencer  LeaveCriticalSection(&CriticalSection);
27205545755676b9ff35d244e55d749a15e28bb228bReid Spencer  return false;
273496c277a6d161413e3f6976c9991ddccd8ecae8aReid Spencer}
274496c277a6d161413e3f6976c9991ddccd8ecae8aReid Spencer
27541154114f64c1531764236e9268d2a5ac52e3e91Dan Gohman// DontRemoveFileOnSignal - The public API
27641154114f64c1531764236e9268d2a5ac52e3e91Dan Gohmanvoid sys::DontRemoveFileOnSignal(const sys::Path &Filename) {
27741154114f64c1531764236e9268d2a5ac52e3e91Dan Gohman  if (FilesToRemove == NULL)
27841154114f64c1531764236e9268d2a5ac52e3e91Dan Gohman    return;
27941154114f64c1531764236e9268d2a5ac52e3e91Dan Gohman
2802172f3cd971d7446123f8bdc72b381adde0ea559NAKAMURA Takumi  RegisterHandler();
2812172f3cd971d7446123f8bdc72b381adde0ea559NAKAMURA Takumi
28241154114f64c1531764236e9268d2a5ac52e3e91Dan Gohman  FilesToRemove->push_back(Filename);
28341154114f64c1531764236e9268d2a5ac52e3e91Dan Gohman  std::vector<sys::Path>::reverse_iterator I =
28441154114f64c1531764236e9268d2a5ac52e3e91Dan Gohman  std::find(FilesToRemove->rbegin(), FilesToRemove->rend(), Filename);
28541154114f64c1531764236e9268d2a5ac52e3e91Dan Gohman  if (I != FilesToRemove->rend())
28641154114f64c1531764236e9268d2a5ac52e3e91Dan Gohman    FilesToRemove->erase(I.base()-1);
28741154114f64c1531764236e9268d2a5ac52e3e91Dan Gohman
28841154114f64c1531764236e9268d2a5ac52e3e91Dan Gohman  LeaveCriticalSection(&CriticalSection);
28941154114f64c1531764236e9268d2a5ac52e3e91Dan Gohman}
29041154114f64c1531764236e9268d2a5ac52e3e91Dan Gohman
291496c277a6d161413e3f6976c9991ddccd8ecae8aReid Spencer/// PrintStackTraceOnErrorSignal - When an error signal (such as SIBABRT or
292496c277a6d161413e3f6976c9991ddccd8ecae8aReid Spencer/// SIGSEGV) is delivered to the process, print a stack trace and then exit.
29390b54138834a057179c7a02931217ab5a82ed389Reid Spencervoid sys::PrintStackTraceOnErrorSignal() {
29490b54138834a057179c7a02931217ab5a82ed389Reid Spencer  RegisterHandler();
29590b54138834a057179c7a02931217ab5a82ed389Reid Spencer  LeaveCriticalSection(&CriticalSection);
29690b54138834a057179c7a02931217ab5a82ed389Reid Spencer}
29790b54138834a057179c7a02931217ab5a82ed389Reid Spencer
298fa8c292ebd893b3effef4ead9c88d261c628c340Chris Lattner
299fa8c292ebd893b3effef4ead9c88d261c628c340Chris Lattnervoid sys::SetInterruptFunction(void (*IF)()) {
300ee841a1a8735805f84d609ae105bec92525033c6Jeff Cohen  RegisterHandler();
30164fe58490d28b7f7ba3ecb78fd9290688ded8f0cJeff Cohen  InterruptFunction = IF;
302ee841a1a8735805f84d609ae105bec92525033c6Jeff Cohen  LeaveCriticalSection(&CriticalSection);
303fa8c292ebd893b3effef4ead9c88d261c628c340Chris Lattner}
30448fe63526e35ddaee7e98879596a569911f41319Sebastian Redl
30548fe63526e35ddaee7e98879596a569911f41319Sebastian Redl
30648fe63526e35ddaee7e98879596a569911f41319Sebastian Redl/// AddSignalHandler - Add a function to be called when a signal is delivered
30748fe63526e35ddaee7e98879596a569911f41319Sebastian Redl/// to the process.  The handler can have a cookie passed to it to identify
30848fe63526e35ddaee7e98879596a569911f41319Sebastian Redl/// what instance of the handler it is.
30948fe63526e35ddaee7e98879596a569911f41319Sebastian Redlvoid sys::AddSignalHandler(void (*FnPtr)(void *), void *Cookie) {
31048fe63526e35ddaee7e98879596a569911f41319Sebastian Redl  if (CallBacksToRun == 0)
31148fe63526e35ddaee7e98879596a569911f41319Sebastian Redl    CallBacksToRun = new std::vector<std::pair<void(*)(void*), void*> >();
31248fe63526e35ddaee7e98879596a569911f41319Sebastian Redl  CallBacksToRun->push_back(std::make_pair(FnPtr, Cookie));
31348fe63526e35ddaee7e98879596a569911f41319Sebastian Redl  RegisterHandler();
31461633368cfc04697d8e2030d66ab220464298acaTorok Edwin  LeaveCriticalSection(&CriticalSection);
31548fe63526e35ddaee7e98879596a569911f41319Sebastian Redl}
316496c277a6d161413e3f6976c9991ddccd8ecae8aReid Spencer}
317496c277a6d161413e3f6976c9991ddccd8ecae8aReid Spencer
31890b54138834a057179c7a02931217ab5a82ed389Reid Spencerstatic void Cleanup() {
31990b54138834a057179c7a02931217ab5a82ed389Reid Spencer  EnterCriticalSection(&CriticalSection);
32090b54138834a057179c7a02931217ab5a82ed389Reid Spencer
3217b60a15abc155196d9515a1e242ec0137afff753Reid Spencer  // Prevent other thread from registering new files and directories for
3227b60a15abc155196d9515a1e242ec0137afff753Reid Spencer  // removal, should we be executing because of the console handler callback.
3237b60a15abc155196d9515a1e242ec0137afff753Reid Spencer  CleanupExecuted = true;
3247b60a15abc155196d9515a1e242ec0137afff753Reid Spencer
3257b60a15abc155196d9515a1e242ec0137afff753Reid Spencer  // FIXME: open files cannot be deleted.
3267b60a15abc155196d9515a1e242ec0137afff753Reid Spencer
32790b54138834a057179c7a02931217ab5a82ed389Reid Spencer  if (FilesToRemove != NULL)
32890b54138834a057179c7a02931217ab5a82ed389Reid Spencer    while (!FilesToRemove->empty()) {
329ac356602f2fa0be3d198ada31c51c36d38a6f6ecChris Lattner      FilesToRemove->back().eraseFromDisk();
33090b54138834a057179c7a02931217ab5a82ed389Reid Spencer      FilesToRemove->pop_back();
33190b54138834a057179c7a02931217ab5a82ed389Reid Spencer    }
33290b54138834a057179c7a02931217ab5a82ed389Reid Spencer
33335033a5876aa27ea5729bc29b41bb4460a303cadChris Lattner  if (CallBacksToRun)
33435033a5876aa27ea5729bc29b41bb4460a303cadChris Lattner    for (unsigned i = 0, e = CallBacksToRun->size(); i != e; ++i)
33535033a5876aa27ea5729bc29b41bb4460a303cadChris Lattner      (*CallBacksToRun)[i].first((*CallBacksToRun)[i].second);
33690b54138834a057179c7a02931217ab5a82ed389Reid Spencer
33790b54138834a057179c7a02931217ab5a82ed389Reid Spencer  LeaveCriticalSection(&CriticalSection);
33890b54138834a057179c7a02931217ab5a82ed389Reid Spencer}
33990b54138834a057179c7a02931217ab5a82ed389Reid Spencer
340fb89e08413878571c1c1fc6ff15cdbf5cd8692dcDaniel Dunbarvoid llvm::sys::RunInterruptHandlers() {
341fb89e08413878571c1c1fc6ff15cdbf5cd8692dcDaniel Dunbar  Cleanup();
342fb89e08413878571c1c1fc6ff15cdbf5cd8692dcDaniel Dunbar}
343fb89e08413878571c1c1fc6ff15cdbf5cd8692dcDaniel Dunbar
34490b54138834a057179c7a02931217ab5a82ed389Reid Spencerstatic LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep) {
34511d03f690e7fe019c33c3a066a9171c61f6d61f9Mikhail Glushenkov  Cleanup();
34684ba14f6d016ab181f1fd5de8050e1b9bbc83904Mikhail Glushenkov
3476d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov  // Initialize the STACKFRAME structure.
3480bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer  STACKFRAME64 StackFrame;
3496d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov  memset(&StackFrame, 0, sizeof(StackFrame));
3506d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov
3510bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer  DWORD machineType;
3520bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer#if defined(_M_X64)
3530bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer  machineType = IMAGE_FILE_MACHINE_AMD64;
3540bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer  StackFrame.AddrPC.Offset = ep->ContextRecord->Rip;
3550bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer  StackFrame.AddrPC.Mode = AddrModeFlat;
3560bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer  StackFrame.AddrStack.Offset = ep->ContextRecord->Rsp;
3570bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer  StackFrame.AddrStack.Mode = AddrModeFlat;
3580bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer  StackFrame.AddrFrame.Offset = ep->ContextRecord->Rbp;
3590bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer  StackFrame.AddrFrame.Mode = AddrModeFlat;
3600bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer#elif defined(_M_IX86)
3610bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer  machineType = IMAGE_FILE_MACHINE_I386;
3626d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov  StackFrame.AddrPC.Offset = ep->ContextRecord->Eip;
3636d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov  StackFrame.AddrPC.Mode = AddrModeFlat;
3646d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov  StackFrame.AddrStack.Offset = ep->ContextRecord->Esp;
3656d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov  StackFrame.AddrStack.Mode = AddrModeFlat;
3666d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov  StackFrame.AddrFrame.Offset = ep->ContextRecord->Ebp;
3676d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov  StackFrame.AddrFrame.Mode = AddrModeFlat;
3680bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer#endif
3696d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov
3706d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov  HANDLE hProcess = GetCurrentProcess();
3716d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov  HANDLE hThread = GetCurrentThread();
3726d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov
3736d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov  // Initialize the symbol handler.
3746d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov  SymSetOptions(SYMOPT_DEFERRED_LOADS|SYMOPT_LOAD_LINES);
3756d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov  SymInitialize(hProcess, NULL, TRUE);
3766d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov
3776d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov  while (true) {
3780bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer    if (!StackWalk64(machineType, hProcess, hThread, &StackFrame,
3790bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer                   ep->ContextRecord, NULL, SymFunctionTableAccess64,
3800bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer                   SymGetModuleBase64, NULL)) {
3816d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov      break;
3826d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov    }
3836d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov
3846d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov    if (StackFrame.AddrFrame.Offset == 0)
3856d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov      break;
3866d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov
3876d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov    // Print the PC in hexadecimal.
3880bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer    DWORD64 PC = StackFrame.AddrPC.Offset;
3890bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer#if defined(_M_X64)
3900bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer    fprintf(stderr, "0x%016llX", PC);
3910bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer#elif defined(_M_IX86)
3920bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer    fprintf(stderr, "0x%08lX", static_cast<DWORD>(PC));
3930bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer#endif
3946d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov
3956d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov    // Print the parameters.  Assume there are four.
3960bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer#if defined(_M_X64)
3970bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer    fprintf(stderr, " (0x%016llX 0x%016llX 0x%016llX 0x%016llX)",
3980bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer                StackFrame.Params[0],
3990bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer                StackFrame.Params[1],
4000bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer                StackFrame.Params[2],
4010bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer                StackFrame.Params[3]);
4020bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer#elif defined(_M_IX86)
4036d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov    fprintf(stderr, " (0x%08lX 0x%08lX 0x%08lX 0x%08lX)",
4040bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer                static_cast<DWORD>(StackFrame.Params[0]),
4050bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer                static_cast<DWORD>(StackFrame.Params[1]),
4060bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer                static_cast<DWORD>(StackFrame.Params[2]),
4070bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer                static_cast<DWORD>(StackFrame.Params[3]));
4080bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer#endif
4096d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov    // Verify the PC belongs to a module in this process.
4100bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer    if (!SymGetModuleBase64(hProcess, PC)) {
4116d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov      fputs(" <unknown module>\n", stderr);
4126d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov      continue;
4136d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov    }
41490b54138834a057179c7a02931217ab5a82ed389Reid Spencer
4156d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov    // Print the symbol name.
4166d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov    char buffer[512];
4170bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer    IMAGEHLP_SYMBOL64 *symbol = reinterpret_cast<IMAGEHLP_SYMBOL64 *>(buffer);
4180bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer    memset(symbol, 0, sizeof(IMAGEHLP_SYMBOL64));
4190bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer    symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
4200bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer    symbol->MaxNameLength = 512 - sizeof(IMAGEHLP_SYMBOL64);
4216d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov
4220bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer    DWORD64 dwDisp;
4230bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer    if (!SymGetSymFromAddr64(hProcess, PC, &dwDisp, symbol)) {
42490b54138834a057179c7a02931217ab5a82ed389Reid Spencer      fputc('\n', stderr);
4256d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov      continue;
4266d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov    }
4276d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov
4286d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov    buffer[511] = 0;
4296d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov    if (dwDisp > 0)
4300bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer      fprintf(stderr, ", %s() + 0x%llX bytes(s)", symbol->Name, dwDisp);
4316d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov    else
4326d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov      fprintf(stderr, ", %s", symbol->Name);
4336d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov
4346d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov    // Print the source file and line number information.
4350bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer    IMAGEHLP_LINE64 line;
4360bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer    DWORD dwLineDisp;
4376d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov    memset(&line, 0, sizeof(line));
4386d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov    line.SizeOfStruct = sizeof(line);
4390bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer    if (SymGetLineFromAddr64(hProcess, PC, &dwLineDisp, &line)) {
4406d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov      fprintf(stderr, ", %s, line %lu", line.FileName, line.LineNumber);
4410bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer      if (dwLineDisp > 0)
4420bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer        fprintf(stderr, " + 0x%lX byte(s)", dwLineDisp);
44390b54138834a057179c7a02931217ab5a82ed389Reid Spencer    }
4440ccb93034a47303509ee2c89b8bf13956a510b94Chuck Rose III
4456d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov    fputc('\n', stderr);
4466d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov  }
4476d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov
448df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar  if (ExitOnUnhandledExceptions)
4495d2f8c31556b6a5ce29d2cad314bc48af879c5b3NAKAMURA Takumi    _exit(ep->ExceptionRecord->ExceptionCode);
450df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar
45190b54138834a057179c7a02931217ab5a82ed389Reid Spencer  // Allow dialog box to pop up allowing choice to start debugger.
4527b60a15abc155196d9515a1e242ec0137afff753Reid Spencer  if (OldFilter)
4537b60a15abc155196d9515a1e242ec0137afff753Reid Spencer    return (*OldFilter)(ep);
4547b60a15abc155196d9515a1e242ec0137afff753Reid Spencer  else
4557b60a15abc155196d9515a1e242ec0137afff753Reid Spencer    return EXCEPTION_CONTINUE_SEARCH;
45690b54138834a057179c7a02931217ab5a82ed389Reid Spencer}
45790b54138834a057179c7a02931217ab5a82ed389Reid Spencer
45890b54138834a057179c7a02931217ab5a82ed389Reid Spencerstatic BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType) {
45964fe58490d28b7f7ba3ecb78fd9290688ded8f0cJeff Cohen  // We are running in our very own thread, courtesy of Windows.
460ee841a1a8735805f84d609ae105bec92525033c6Jeff Cohen  EnterCriticalSection(&CriticalSection);
46190b54138834a057179c7a02931217ab5a82ed389Reid Spencer  Cleanup();
46290b54138834a057179c7a02931217ab5a82ed389Reid Spencer
463ee841a1a8735805f84d609ae105bec92525033c6Jeff Cohen  // If an interrupt function has been set, go and run one it; otherwise,
464ee841a1a8735805f84d609ae105bec92525033c6Jeff Cohen  // the process dies.
465ee841a1a8735805f84d609ae105bec92525033c6Jeff Cohen  void (*IF)() = InterruptFunction;
466ee841a1a8735805f84d609ae105bec92525033c6Jeff Cohen  InterruptFunction = 0;      // Don't run it on another CTRL-C.
467ee841a1a8735805f84d609ae105bec92525033c6Jeff Cohen
468ee841a1a8735805f84d609ae105bec92525033c6Jeff Cohen  if (IF) {
46964fe58490d28b7f7ba3ecb78fd9290688ded8f0cJeff Cohen    // Note: if the interrupt function throws an exception, there is nothing
47064fe58490d28b7f7ba3ecb78fd9290688ded8f0cJeff Cohen    // to catch it in this thread so it will kill the process.
47164fe58490d28b7f7ba3ecb78fd9290688ded8f0cJeff Cohen    IF();                     // Run it now.
472ee841a1a8735805f84d609ae105bec92525033c6Jeff Cohen    LeaveCriticalSection(&CriticalSection);
473ee841a1a8735805f84d609ae105bec92525033c6Jeff Cohen    return TRUE;              // Don't kill the process.
474ee841a1a8735805f84d609ae105bec92525033c6Jeff Cohen  }
475ee841a1a8735805f84d609ae105bec92525033c6Jeff Cohen
476298d6c14ca1936677aaf6cca3efc569b6e53d294Reid Spencer  // Allow normal processing to take place; i.e., the process dies.
477ee841a1a8735805f84d609ae105bec92525033c6Jeff Cohen  LeaveCriticalSection(&CriticalSection);
47890b54138834a057179c7a02931217ab5a82ed389Reid Spencer  return FALSE;
479496c277a6d161413e3f6976c9991ddccd8ecae8aReid Spencer}
4800bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer
4810bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer#if __MINGW32__
4820bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer // We turned these warnings off for this file so that MinGW-g++ doesn't
4830bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer // complain about the ll format specifiers used.  Now we are turning the
4840bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer // warnings back on.  If MinGW starts to support diagnostic stacks, we can
4850bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer // replace this with a pop.
4860bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer #pragma GCC diagnostic warning "-Wformat"
4870bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer #pragma GCC diagnostic warning "-Wformat-extra-args"
4880bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer#endif
489