Signals.inc revision b7e2188f7fb9a1c1cb6dbd32b206e44b11b4a157
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 14b7e2188f7fb9a1c1cb6dbd32b206e44b11b4a157Rafael Espindola#include "llvm/Support/PathV1.h" 15b7e2188f7fb9a1c1cb6dbd32b206e44b11b4a157Rafael Espindola 161f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "Windows.h" 17d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include <algorithm> 18ced4110f5b068b9b64e3a55a9ee57b621ce4acb1Reid Spencer#include <stdio.h> 1990b54138834a057179c7a02931217ab5a82ed389Reid Spencer#include <vector> 2090b54138834a057179c7a02931217ab5a82ed389Reid Spencer 2123a1cf3e085325783ef2e4078308f913cba5012eJeff Cohen#ifdef __MINGW32__ 2248fdf91d0f17b19bb7345156b928689df94d0c6cReid Spencer #include <imagehlp.h> 23f6cbc0fd6494e50c48ebe4b5eecde1c70bcd5165Reid Spencer#else 2448fdf91d0f17b19bb7345156b928689df94d0c6cReid Spencer #include <dbghelp.h> 25f6cbc0fd6494e50c48ebe4b5eecde1c70bcd5165Reid Spencer#endif 26f6cbc0fd6494e50c48ebe4b5eecde1c70bcd5165Reid Spencer#include <psapi.h> 2790b54138834a057179c7a02931217ab5a82ed389Reid Spencer 280bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer#ifdef _MSC_VER 290bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer #pragma comment(lib, "psapi.lib") 300bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer #pragma comment(lib, "dbghelp.lib") 310bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer#elif __MINGW32__ 3248fdf91d0f17b19bb7345156b928689df94d0c6cReid Spencer #if ((HAVE_LIBIMAGEHLP != 1) || (HAVE_LIBPSAPI != 1)) 3348fdf91d0f17b19bb7345156b928689df94d0c6cReid Spencer #error "libimagehlp.a & libpsapi.a should be present" 3448fdf91d0f17b19bb7345156b928689df94d0c6cReid Spencer #endif 350bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer // The version of g++ that comes with MinGW does *not* properly understand 360bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer // the ll format specifier for printf. However, MinGW passes the format 370bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer // specifiers on to the MSVCRT entirely, and the CRT understands the ll 380bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer // specifier. So these warnings are spurious in this case. Since we compile 390bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer // with -Wall, this will generate these warnings which should be ignored. So 400bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer // we will turn off the warnings for this just file. However, MinGW also does 410bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer // not support push and pop for diagnostics, so we have to manually turn it 420bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer // back on at the end of the file. 430bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer #pragma GCC diagnostic ignored "-Wformat" 440bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer #pragma GCC diagnostic ignored "-Wformat-extra-args" 450bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer 46cda065df614dbf7ca0f6a169e9536d2241539b75Anton Korobeynikov #if !defined(__MINGW64_VERSION_MAJOR) 47cda065df614dbf7ca0f6a169e9536d2241539b75Anton Korobeynikov // MinGW.org does not have updated support for the 64-bit versions of the 48cda065df614dbf7ca0f6a169e9536d2241539b75Anton Korobeynikov // DebugHlp APIs. So we will have to load them manually. The structures and 49cda065df614dbf7ca0f6a169e9536d2241539b75Anton Korobeynikov // method signatures were pulled from DbgHelp.h in the Windows Platform SDK, 50cda065df614dbf7ca0f6a169e9536d2241539b75Anton Korobeynikov // and adjusted for brevity. 510bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer typedef struct _IMAGEHLP_LINE64 { 520bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer DWORD SizeOfStruct; 530bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer PVOID Key; 540bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer DWORD LineNumber; 550bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer PCHAR FileName; 560bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer DWORD64 Address; 570bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer } IMAGEHLP_LINE64, *PIMAGEHLP_LINE64; 580bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer 590bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer typedef struct _IMAGEHLP_SYMBOL64 { 600bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer DWORD SizeOfStruct; 610bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer DWORD64 Address; 620bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer DWORD Size; 630bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer DWORD Flags; 640bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer DWORD MaxNameLength; 650bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer CHAR Name[1]; 660bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer } IMAGEHLP_SYMBOL64, *PIMAGEHLP_SYMBOL64; 670bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer 680bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer typedef struct _tagADDRESS64 { 690bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer DWORD64 Offset; 700bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer WORD Segment; 710bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer ADDRESS_MODE Mode; 720bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer } ADDRESS64, *LPADDRESS64; 730bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer 740bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer typedef struct _KDHELP64 { 750bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer DWORD64 Thread; 760bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer DWORD ThCallbackStack; 770bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer DWORD ThCallbackBStore; 780bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer DWORD NextCallback; 790bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer DWORD FramePointer; 800bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer DWORD64 KiCallUserMode; 810bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer DWORD64 KeUserCallbackDispatcher; 820bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer DWORD64 SystemRangeStart; 830bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer DWORD64 KiUserExceptionDispatcher; 840bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer DWORD64 StackBase; 850bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer DWORD64 StackLimit; 860bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer DWORD64 Reserved[5]; 870bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer } KDHELP64, *PKDHELP64; 880bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer 890bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer typedef struct _tagSTACKFRAME64 { 900bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer ADDRESS64 AddrPC; 910bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer ADDRESS64 AddrReturn; 920bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer ADDRESS64 AddrFrame; 930bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer ADDRESS64 AddrStack; 940bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer ADDRESS64 AddrBStore; 950bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer PVOID FuncTableEntry; 960bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer DWORD64 Params[4]; 970bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer BOOL Far; 980bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer BOOL Virtual; 990bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer DWORD64 Reserved[3]; 1000bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer KDHELP64 KdHelp; 1010bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer } STACKFRAME64, *LPSTACKFRAME64; 1020bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer 1030bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencertypedef BOOL (__stdcall *PREAD_PROCESS_MEMORY_ROUTINE64)(HANDLE hProcess, 1040bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer DWORD64 qwBaseAddress, PVOID lpBuffer, DWORD nSize, 1050bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer LPDWORD lpNumberOfBytesRead); 1060bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer 1070bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencertypedef PVOID (__stdcall *PFUNCTION_TABLE_ACCESS_ROUTINE64)( HANDLE ahProcess, 1080bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer DWORD64 AddrBase); 1090bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer 1100bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencertypedef DWORD64 (__stdcall *PGET_MODULE_BASE_ROUTINE64)(HANDLE hProcess, 1110bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer DWORD64 Address); 1120bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer 1130bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencertypedef DWORD64 (__stdcall *PTRANSLATE_ADDRESS_ROUTINE64)(HANDLE hProcess, 1140bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer HANDLE hThread, LPADDRESS64 lpaddr); 1150bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer 1160bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencertypedef BOOL (WINAPI *fpStackWalk64)(DWORD, HANDLE, HANDLE, LPSTACKFRAME64, 1170bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer PVOID, PREAD_PROCESS_MEMORY_ROUTINE64, 1180bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer PFUNCTION_TABLE_ACCESS_ROUTINE64, 1190bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer PGET_MODULE_BASE_ROUTINE64, 1200bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer PTRANSLATE_ADDRESS_ROUTINE64); 1210bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencerstatic fpStackWalk64 StackWalk64; 1220bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer 1230bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencertypedef DWORD64 (WINAPI *fpSymGetModuleBase64)(HANDLE, DWORD64); 1240bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencerstatic fpSymGetModuleBase64 SymGetModuleBase64; 1250bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer 1260bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencertypedef BOOL (WINAPI *fpSymGetSymFromAddr64)(HANDLE, DWORD64, 1270bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer PDWORD64, PIMAGEHLP_SYMBOL64); 1280bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencerstatic fpSymGetSymFromAddr64 SymGetSymFromAddr64; 1290bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer 1300bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencertypedef BOOL (WINAPI *fpSymGetLineFromAddr64)(HANDLE, DWORD64, 1310bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer PDWORD, PIMAGEHLP_LINE64); 1320bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencerstatic fpSymGetLineFromAddr64 SymGetLineFromAddr64; 1330bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer 1340bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencertypedef PVOID (WINAPI *fpSymFunctionTableAccess64)(HANDLE, DWORD64); 1350bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencerstatic fpSymFunctionTableAccess64 SymFunctionTableAccess64; 1360bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer 1370bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencerstatic bool load64BitDebugHelp(void) { 1380bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer HMODULE hLib = ::LoadLibrary("Dbghelp.dll"); 1390bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer if (hLib) { 1400bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer StackWalk64 = (fpStackWalk64) 1410bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer ::GetProcAddress(hLib, "StackWalk64"); 1420bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer SymGetModuleBase64 = (fpSymGetModuleBase64) 1430bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer ::GetProcAddress(hLib, "SymGetModuleBase64"); 1440bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer SymGetSymFromAddr64 = (fpSymGetSymFromAddr64) 1450bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer ::GetProcAddress(hLib, "SymGetSymFromAddr64"); 1460bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer SymGetLineFromAddr64 = (fpSymGetLineFromAddr64) 1470bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer ::GetProcAddress(hLib, "SymGetLineFromAddr64"); 1480bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer SymFunctionTableAccess64 = (fpSymFunctionTableAccess64) 1490bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer ::GetProcAddress(hLib, "SymFunctionTableAccess64"); 1500bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer } 1510bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer return StackWalk64 != NULL; 1520bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer} 153cda065df614dbf7ca0f6a169e9536d2241539b75Anton Korobeynikov #endif // !defined(__MINGW64_VERSION_MAJOR) 1540bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer#endif // __MINGW32__ 15590b54138834a057179c7a02931217ab5a82ed389Reid Spencer 15690b54138834a057179c7a02931217ab5a82ed389Reid Spencer// Forward declare. 15790b54138834a057179c7a02931217ab5a82ed389Reid Spencerstatic LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep); 15890b54138834a057179c7a02931217ab5a82ed389Reid Spencerstatic BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType); 15990b54138834a057179c7a02931217ab5a82ed389Reid Spencer 160ee841a1a8735805f84d609ae105bec92525033c6Jeff Cohen// InterruptFunction - The function to call if ctrl-c is pressed. 161ee841a1a8735805f84d609ae105bec92525033c6Jeff Cohenstatic void (*InterruptFunction)() = 0; 162ee841a1a8735805f84d609ae105bec92525033c6Jeff Cohen 163b7e2188f7fb9a1c1cb6dbd32b206e44b11b4a157Rafael Espindolastatic std::vector<std::string> *FilesToRemove = NULL; 16435033a5876aa27ea5729bc29b41bb4460a303cadChris Lattnerstatic std::vector<std::pair<void(*)(void*), void*> > *CallBacksToRun = 0; 16590b54138834a057179c7a02931217ab5a82ed389Reid Spencerstatic bool RegisteredUnhandledExceptionFilter = false; 1667b60a15abc155196d9515a1e242ec0137afff753Reid Spencerstatic bool CleanupExecuted = false; 167df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbarstatic bool ExitOnUnhandledExceptions = false; 1687b60a15abc155196d9515a1e242ec0137afff753Reid Spencerstatic PTOP_LEVEL_EXCEPTION_FILTER OldFilter = NULL; 169298d6c14ca1936677aaf6cca3efc569b6e53d294Reid Spencer 170298d6c14ca1936677aaf6cca3efc569b6e53d294Reid Spencer// Windows creates a new thread to execute the console handler when an event 171298d6c14ca1936677aaf6cca3efc569b6e53d294Reid Spencer// (such as CTRL/C) occurs. This causes concurrency issues with the above 172298d6c14ca1936677aaf6cca3efc569b6e53d294Reid Spencer// globals which this critical section addresses. 17390b54138834a057179c7a02931217ab5a82ed389Reid Spencerstatic CRITICAL_SECTION CriticalSection; 17490b54138834a057179c7a02931217ab5a82ed389Reid Spencer 175496c277a6d161413e3f6976c9991ddccd8ecae8aReid Spencernamespace llvm { 176496c277a6d161413e3f6976c9991ddccd8ecae8aReid Spencer 177496c277a6d161413e3f6976c9991ddccd8ecae8aReid Spencer//===----------------------------------------------------------------------===// 17884ba14f6d016ab181f1fd5de8050e1b9bbc83904Mikhail Glushenkov//=== WARNING: Implementation here must contain only Win32 specific code 17990b54138834a057179c7a02931217ab5a82ed389Reid Spencer//=== and must not be UNIX code 180496c277a6d161413e3f6976c9991ddccd8ecae8aReid Spencer//===----------------------------------------------------------------------===// 181496c277a6d161413e3f6976c9991ddccd8ecae8aReid Spencer 1823be2d12bdec9ec3a244aae695d3b586ac27dcfdeDaniel Dunbar#ifdef _MSC_VER 1839463c0f3da8e325fea96e36540da18cadaa3f303Reid Kleckner/// AvoidMessageBoxHook - Emulates hitting "retry" from an "abort, retry, 1849463c0f3da8e325fea96e36540da18cadaa3f303Reid Kleckner/// ignore" CRT debug report dialog. "retry" raises an exception which 1859463c0f3da8e325fea96e36540da18cadaa3f303Reid Kleckner/// ultimately triggers our stack dumper. 1869463c0f3da8e325fea96e36540da18cadaa3f303Reid Klecknerstatic int AvoidMessageBoxHook(int ReportType, char *Message, int *Return) { 1879463c0f3da8e325fea96e36540da18cadaa3f303Reid Kleckner // Set *Return to the retry code for the return value of _CrtDbgReport: 1889463c0f3da8e325fea96e36540da18cadaa3f303Reid Kleckner // http://msdn.microsoft.com/en-us/library/8hyw4sy7(v=vs.71).aspx 1899463c0f3da8e325fea96e36540da18cadaa3f303Reid Kleckner // This may also trigger just-in-time debugging via DebugBreak(). 1909463c0f3da8e325fea96e36540da18cadaa3f303Reid Kleckner if (Return) 1919463c0f3da8e325fea96e36540da18cadaa3f303Reid Kleckner *Return = 1; 1929463c0f3da8e325fea96e36540da18cadaa3f303Reid Kleckner // Don't call _CrtDbgReport. 1939463c0f3da8e325fea96e36540da18cadaa3f303Reid Kleckner return TRUE; 1949463c0f3da8e325fea96e36540da18cadaa3f303Reid Kleckner} 1959463c0f3da8e325fea96e36540da18cadaa3f303Reid Kleckner 196df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar/// CRTReportHook - Function called on a CRT debugging event. 197df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbarstatic int CRTReportHook(int ReportType, char *Message, int *Return) { 198df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar // Don't cause a DebugBreak() on return. 199df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar if (Return) 200df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar *Return = 0; 201df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar 202df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar switch (ReportType) { 203df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar default: 204df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar case _CRT_ASSERT: 205df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar fprintf(stderr, "CRT assert: %s\n", Message); 206df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar // FIXME: Is there a way to just crash? Perhaps throw to the unhandled 207df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar // exception code? Perhaps SetErrorMode() handles this. 208df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar _exit(3); 209df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar break; 210df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar case _CRT_ERROR: 211df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar fprintf(stderr, "CRT error: %s\n", Message); 212df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar // FIXME: Is there a way to just crash? Perhaps throw to the unhandled 213df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar // exception code? Perhaps SetErrorMode() handles this. 214df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar _exit(3); 215df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar break; 216df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar case _CRT_WARN: 217df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar fprintf(stderr, "CRT warn: %s\n", Message); 218df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar break; 219df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar } 220df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar 221df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar // Don't call _CrtDbgReport. 222df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar return TRUE; 223df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar} 2243be2d12bdec9ec3a244aae695d3b586ac27dcfdeDaniel Dunbar#endif 22590b54138834a057179c7a02931217ab5a82ed389Reid Spencer 226df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbarstatic void RegisterHandler() { 227cda065df614dbf7ca0f6a169e9536d2241539b75Anton Korobeynikov#if __MINGW32__ && !defined(__MINGW64_VERSION_MAJOR) 228cda065df614dbf7ca0f6a169e9536d2241539b75Anton Korobeynikov // On MinGW.org, we need to load up the symbols explicitly, because the 2290bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer // Win32 framework they include does not have support for the 64-bit 2300bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer // versions of the APIs we need. If we cannot load up the APIs (which 2310bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer // would be unexpected as they should exist on every version of Windows 2320bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer // we support), we will bail out since there would be nothing to report. 2330bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer if (!load64BitDebugHelp()) { 2340bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer assert(false && "These APIs should always be available"); 2350bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer return; 2360bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer } 2370bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer#endif 2380bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer 2397b60a15abc155196d9515a1e242ec0137afff753Reid Spencer if (RegisteredUnhandledExceptionFilter) { 240298d6c14ca1936677aaf6cca3efc569b6e53d294Reid Spencer EnterCriticalSection(&CriticalSection); 24190b54138834a057179c7a02931217ab5a82ed389Reid Spencer return; 242298d6c14ca1936677aaf6cca3efc569b6e53d294Reid Spencer } 24390b54138834a057179c7a02931217ab5a82ed389Reid Spencer 24490b54138834a057179c7a02931217ab5a82ed389Reid Spencer // Now's the time to create the critical section. This is the first time 24590b54138834a057179c7a02931217ab5a82ed389Reid Spencer // through here, and there's only one thread. 24690b54138834a057179c7a02931217ab5a82ed389Reid Spencer InitializeCriticalSection(&CriticalSection); 24790b54138834a057179c7a02931217ab5a82ed389Reid Spencer 24890b54138834a057179c7a02931217ab5a82ed389Reid Spencer // Enter it immediately. Now if someone hits CTRL/C, the console handler 24990b54138834a057179c7a02931217ab5a82ed389Reid Spencer // can't proceed until the globals are updated. 25090b54138834a057179c7a02931217ab5a82ed389Reid Spencer EnterCriticalSection(&CriticalSection); 25190b54138834a057179c7a02931217ab5a82ed389Reid Spencer 25290b54138834a057179c7a02931217ab5a82ed389Reid Spencer RegisteredUnhandledExceptionFilter = true; 2537b60a15abc155196d9515a1e242ec0137afff753Reid Spencer OldFilter = SetUnhandledExceptionFilter(LLVMUnhandledExceptionFilter); 25490b54138834a057179c7a02931217ab5a82ed389Reid Spencer SetConsoleCtrlHandler(LLVMConsoleCtrlHandler, TRUE); 25590b54138834a057179c7a02931217ab5a82ed389Reid Spencer 2569463c0f3da8e325fea96e36540da18cadaa3f303Reid Kleckner#ifdef _MSC_VER 2579463c0f3da8e325fea96e36540da18cadaa3f303Reid Kleckner const char *EnableMsgbox = getenv("LLVM_ENABLE_CRT_REPORT"); 2589463c0f3da8e325fea96e36540da18cadaa3f303Reid Kleckner if (!EnableMsgbox || strcmp("0", EnableMsgbox) == 0) { 2599463c0f3da8e325fea96e36540da18cadaa3f303Reid Kleckner // Setting a report hook overrides the default behavior of popping an "abort, 2609463c0f3da8e325fea96e36540da18cadaa3f303Reid Kleckner // retry, or ignore" dialog. 2619463c0f3da8e325fea96e36540da18cadaa3f303Reid Kleckner _CrtSetReportHook(AvoidMessageBoxHook); 2629463c0f3da8e325fea96e36540da18cadaa3f303Reid Kleckner } 2639463c0f3da8e325fea96e36540da18cadaa3f303Reid Kleckner#endif 2649463c0f3da8e325fea96e36540da18cadaa3f303Reid Kleckner 265df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar // Environment variable to disable any kind of crash dialog. 26608713b37c367b9db29058092c46b41981a74ceffArgyrios Kyrtzidis if (getenv("LLVM_DISABLE_CRASH_REPORT")) { 267a8bbe707dc0c397d4020e7348fda64b3cb2a0e21NAKAMURA Takumi#ifdef _MSC_VER 268df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar _CrtSetReportHook(CRTReportHook); 269a8bbe707dc0c397d4020e7348fda64b3cb2a0e21NAKAMURA Takumi#endif 270ac25e44d8905e88f91f998ce27a82cea641f5ff9NAKAMURA Takumi SetErrorMode(SEM_FAILCRITICALERRORS | 271ac25e44d8905e88f91f998ce27a82cea641f5ff9NAKAMURA Takumi SEM_NOGPFAULTERRORBOX | 272ac25e44d8905e88f91f998ce27a82cea641f5ff9NAKAMURA Takumi SEM_NOOPENFILEERRORBOX); 2733be2d12bdec9ec3a244aae695d3b586ac27dcfdeDaniel Dunbar ExitOnUnhandledExceptions = true; 274df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar } 275df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar 27690b54138834a057179c7a02931217ab5a82ed389Reid Spencer // IMPORTANT NOTE: Caller must call LeaveCriticalSection(&CriticalSection) or 27790b54138834a057179c7a02931217ab5a82ed389Reid Spencer // else multi-threading problems will ensue. 27890b54138834a057179c7a02931217ab5a82ed389Reid Spencer} 27990b54138834a057179c7a02931217ab5a82ed389Reid Spencer 280496c277a6d161413e3f6976c9991ddccd8ecae8aReid Spencer// RemoveFileOnSignal - The public API 281b7e2188f7fb9a1c1cb6dbd32b206e44b11b4a157Rafael Espindolabool sys::RemoveFileOnSignal(StringRef Filename, std::string* ErrMsg) { 28290b54138834a057179c7a02931217ab5a82ed389Reid Spencer RegisterHandler(); 28390b54138834a057179c7a02931217ab5a82ed389Reid Spencer 28405545755676b9ff35d244e55d749a15e28bb228bReid Spencer if (CleanupExecuted) { 28505545755676b9ff35d244e55d749a15e28bb228bReid Spencer if (ErrMsg) 28605545755676b9ff35d244e55d749a15e28bb228bReid Spencer *ErrMsg = "Process terminating -- cannot register for removal"; 28705545755676b9ff35d244e55d749a15e28bb228bReid Spencer return true; 28805545755676b9ff35d244e55d749a15e28bb228bReid Spencer } 2897b60a15abc155196d9515a1e242ec0137afff753Reid Spencer 29090b54138834a057179c7a02931217ab5a82ed389Reid Spencer if (FilesToRemove == NULL) 291b7e2188f7fb9a1c1cb6dbd32b206e44b11b4a157Rafael Espindola FilesToRemove = new std::vector<std::string>; 29290b54138834a057179c7a02931217ab5a82ed389Reid Spencer 29398601218901190d9d3bb5ebccae659f8db265b5dReid Spencer FilesToRemove->push_back(Filename); 29490b54138834a057179c7a02931217ab5a82ed389Reid Spencer 29590b54138834a057179c7a02931217ab5a82ed389Reid Spencer LeaveCriticalSection(&CriticalSection); 29605545755676b9ff35d244e55d749a15e28bb228bReid Spencer return false; 297496c277a6d161413e3f6976c9991ddccd8ecae8aReid Spencer} 298496c277a6d161413e3f6976c9991ddccd8ecae8aReid Spencer 29941154114f64c1531764236e9268d2a5ac52e3e91Dan Gohman// DontRemoveFileOnSignal - The public API 300b7e2188f7fb9a1c1cb6dbd32b206e44b11b4a157Rafael Espindolavoid sys::DontRemoveFileOnSignal(StringRef Filename) { 30141154114f64c1531764236e9268d2a5ac52e3e91Dan Gohman if (FilesToRemove == NULL) 30241154114f64c1531764236e9268d2a5ac52e3e91Dan Gohman return; 30341154114f64c1531764236e9268d2a5ac52e3e91Dan Gohman 3042172f3cd971d7446123f8bdc72b381adde0ea559NAKAMURA Takumi RegisterHandler(); 3052172f3cd971d7446123f8bdc72b381adde0ea559NAKAMURA Takumi 30641154114f64c1531764236e9268d2a5ac52e3e91Dan Gohman FilesToRemove->push_back(Filename); 307b7e2188f7fb9a1c1cb6dbd32b206e44b11b4a157Rafael Espindola std::vector<std::string>::reverse_iterator I = 30841154114f64c1531764236e9268d2a5ac52e3e91Dan Gohman std::find(FilesToRemove->rbegin(), FilesToRemove->rend(), Filename); 30941154114f64c1531764236e9268d2a5ac52e3e91Dan Gohman if (I != FilesToRemove->rend()) 31041154114f64c1531764236e9268d2a5ac52e3e91Dan Gohman FilesToRemove->erase(I.base()-1); 31141154114f64c1531764236e9268d2a5ac52e3e91Dan Gohman 31241154114f64c1531764236e9268d2a5ac52e3e91Dan Gohman LeaveCriticalSection(&CriticalSection); 31341154114f64c1531764236e9268d2a5ac52e3e91Dan Gohman} 31441154114f64c1531764236e9268d2a5ac52e3e91Dan Gohman 315496c277a6d161413e3f6976c9991ddccd8ecae8aReid Spencer/// PrintStackTraceOnErrorSignal - When an error signal (such as SIBABRT or 316496c277a6d161413e3f6976c9991ddccd8ecae8aReid Spencer/// SIGSEGV) is delivered to the process, print a stack trace and then exit. 31790b54138834a057179c7a02931217ab5a82ed389Reid Spencervoid sys::PrintStackTraceOnErrorSignal() { 31890b54138834a057179c7a02931217ab5a82ed389Reid Spencer RegisterHandler(); 31990b54138834a057179c7a02931217ab5a82ed389Reid Spencer LeaveCriticalSection(&CriticalSection); 32090b54138834a057179c7a02931217ab5a82ed389Reid Spencer} 32190b54138834a057179c7a02931217ab5a82ed389Reid Spencer 322f48acd5ecd2616623f441f2922d8b4c637e3cd6cArgyrios Kyrtzidisvoid llvm::sys::PrintStackTrace(FILE *) { 323f48acd5ecd2616623f441f2922d8b4c637e3cd6cArgyrios Kyrtzidis // FIXME: Implement. 324f48acd5ecd2616623f441f2922d8b4c637e3cd6cArgyrios Kyrtzidis} 325f48acd5ecd2616623f441f2922d8b4c637e3cd6cArgyrios Kyrtzidis 326fa8c292ebd893b3effef4ead9c88d261c628c340Chris Lattner 327fa8c292ebd893b3effef4ead9c88d261c628c340Chris Lattnervoid sys::SetInterruptFunction(void (*IF)()) { 328ee841a1a8735805f84d609ae105bec92525033c6Jeff Cohen RegisterHandler(); 32964fe58490d28b7f7ba3ecb78fd9290688ded8f0cJeff Cohen InterruptFunction = IF; 330ee841a1a8735805f84d609ae105bec92525033c6Jeff Cohen LeaveCriticalSection(&CriticalSection); 331fa8c292ebd893b3effef4ead9c88d261c628c340Chris Lattner} 33248fe63526e35ddaee7e98879596a569911f41319Sebastian Redl 33348fe63526e35ddaee7e98879596a569911f41319Sebastian Redl 33448fe63526e35ddaee7e98879596a569911f41319Sebastian Redl/// AddSignalHandler - Add a function to be called when a signal is delivered 33548fe63526e35ddaee7e98879596a569911f41319Sebastian Redl/// to the process. The handler can have a cookie passed to it to identify 33648fe63526e35ddaee7e98879596a569911f41319Sebastian Redl/// what instance of the handler it is. 33748fe63526e35ddaee7e98879596a569911f41319Sebastian Redlvoid sys::AddSignalHandler(void (*FnPtr)(void *), void *Cookie) { 33848fe63526e35ddaee7e98879596a569911f41319Sebastian Redl if (CallBacksToRun == 0) 33948fe63526e35ddaee7e98879596a569911f41319Sebastian Redl CallBacksToRun = new std::vector<std::pair<void(*)(void*), void*> >(); 34048fe63526e35ddaee7e98879596a569911f41319Sebastian Redl CallBacksToRun->push_back(std::make_pair(FnPtr, Cookie)); 34148fe63526e35ddaee7e98879596a569911f41319Sebastian Redl RegisterHandler(); 34261633368cfc04697d8e2030d66ab220464298acaTorok Edwin LeaveCriticalSection(&CriticalSection); 34348fe63526e35ddaee7e98879596a569911f41319Sebastian Redl} 344496c277a6d161413e3f6976c9991ddccd8ecae8aReid Spencer} 345496c277a6d161413e3f6976c9991ddccd8ecae8aReid Spencer 34690b54138834a057179c7a02931217ab5a82ed389Reid Spencerstatic void Cleanup() { 34790b54138834a057179c7a02931217ab5a82ed389Reid Spencer EnterCriticalSection(&CriticalSection); 34890b54138834a057179c7a02931217ab5a82ed389Reid Spencer 3497b60a15abc155196d9515a1e242ec0137afff753Reid Spencer // Prevent other thread from registering new files and directories for 3507b60a15abc155196d9515a1e242ec0137afff753Reid Spencer // removal, should we be executing because of the console handler callback. 3517b60a15abc155196d9515a1e242ec0137afff753Reid Spencer CleanupExecuted = true; 3527b60a15abc155196d9515a1e242ec0137afff753Reid Spencer 3537b60a15abc155196d9515a1e242ec0137afff753Reid Spencer // FIXME: open files cannot be deleted. 3547b60a15abc155196d9515a1e242ec0137afff753Reid Spencer 35590b54138834a057179c7a02931217ab5a82ed389Reid Spencer if (FilesToRemove != NULL) 35690b54138834a057179c7a02931217ab5a82ed389Reid Spencer while (!FilesToRemove->empty()) { 357b7e2188f7fb9a1c1cb6dbd32b206e44b11b4a157Rafael Espindola sys::Path(FilesToRemove->back()).eraseFromDisk(); 35890b54138834a057179c7a02931217ab5a82ed389Reid Spencer FilesToRemove->pop_back(); 35990b54138834a057179c7a02931217ab5a82ed389Reid Spencer } 36090b54138834a057179c7a02931217ab5a82ed389Reid Spencer 36135033a5876aa27ea5729bc29b41bb4460a303cadChris Lattner if (CallBacksToRun) 36235033a5876aa27ea5729bc29b41bb4460a303cadChris Lattner for (unsigned i = 0, e = CallBacksToRun->size(); i != e; ++i) 36335033a5876aa27ea5729bc29b41bb4460a303cadChris Lattner (*CallBacksToRun)[i].first((*CallBacksToRun)[i].second); 36490b54138834a057179c7a02931217ab5a82ed389Reid Spencer 36590b54138834a057179c7a02931217ab5a82ed389Reid Spencer LeaveCriticalSection(&CriticalSection); 36690b54138834a057179c7a02931217ab5a82ed389Reid Spencer} 36790b54138834a057179c7a02931217ab5a82ed389Reid Spencer 368fb89e08413878571c1c1fc6ff15cdbf5cd8692dcDaniel Dunbarvoid llvm::sys::RunInterruptHandlers() { 369fb89e08413878571c1c1fc6ff15cdbf5cd8692dcDaniel Dunbar Cleanup(); 370fb89e08413878571c1c1fc6ff15cdbf5cd8692dcDaniel Dunbar} 371fb89e08413878571c1c1fc6ff15cdbf5cd8692dcDaniel Dunbar 37290b54138834a057179c7a02931217ab5a82ed389Reid Spencerstatic LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep) { 37311d03f690e7fe019c33c3a066a9171c61f6d61f9Mikhail Glushenkov Cleanup(); 37484ba14f6d016ab181f1fd5de8050e1b9bbc83904Mikhail Glushenkov 3756d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov // Initialize the STACKFRAME structure. 3760bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer STACKFRAME64 StackFrame; 3776d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov memset(&StackFrame, 0, sizeof(StackFrame)); 3786d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov 3790bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer DWORD machineType; 3800bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer#if defined(_M_X64) 3810bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer machineType = IMAGE_FILE_MACHINE_AMD64; 3820bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer StackFrame.AddrPC.Offset = ep->ContextRecord->Rip; 3830bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer StackFrame.AddrPC.Mode = AddrModeFlat; 3840bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer StackFrame.AddrStack.Offset = ep->ContextRecord->Rsp; 3850bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer StackFrame.AddrStack.Mode = AddrModeFlat; 3860bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer StackFrame.AddrFrame.Offset = ep->ContextRecord->Rbp; 3870bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer StackFrame.AddrFrame.Mode = AddrModeFlat; 3880bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer#elif defined(_M_IX86) 3890bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer machineType = IMAGE_FILE_MACHINE_I386; 3906d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov StackFrame.AddrPC.Offset = ep->ContextRecord->Eip; 3916d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov StackFrame.AddrPC.Mode = AddrModeFlat; 3926d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov StackFrame.AddrStack.Offset = ep->ContextRecord->Esp; 3936d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov StackFrame.AddrStack.Mode = AddrModeFlat; 3946d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov StackFrame.AddrFrame.Offset = ep->ContextRecord->Ebp; 3956d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov StackFrame.AddrFrame.Mode = AddrModeFlat; 3960bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer#endif 3976d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov 3986d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov HANDLE hProcess = GetCurrentProcess(); 3996d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov HANDLE hThread = GetCurrentThread(); 4006d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov 4016d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov // Initialize the symbol handler. 4026d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov SymSetOptions(SYMOPT_DEFERRED_LOADS|SYMOPT_LOAD_LINES); 4036d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov SymInitialize(hProcess, NULL, TRUE); 4046d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov 4056d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov while (true) { 4060bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer if (!StackWalk64(machineType, hProcess, hThread, &StackFrame, 4070bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer ep->ContextRecord, NULL, SymFunctionTableAccess64, 4080bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer SymGetModuleBase64, NULL)) { 4096d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov break; 4106d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov } 4116d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov 4126d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov if (StackFrame.AddrFrame.Offset == 0) 4136d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov break; 4146d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov 4156d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov // Print the PC in hexadecimal. 4160bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer DWORD64 PC = StackFrame.AddrPC.Offset; 4170bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer#if defined(_M_X64) 4180bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer fprintf(stderr, "0x%016llX", PC); 4190bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer#elif defined(_M_IX86) 4200bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer fprintf(stderr, "0x%08lX", static_cast<DWORD>(PC)); 4210bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer#endif 4226d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov 4236d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov // Print the parameters. Assume there are four. 4240bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer#if defined(_M_X64) 4250bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer fprintf(stderr, " (0x%016llX 0x%016llX 0x%016llX 0x%016llX)", 4260bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer StackFrame.Params[0], 4270bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer StackFrame.Params[1], 4280bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer StackFrame.Params[2], 4290bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer StackFrame.Params[3]); 4300bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer#elif defined(_M_IX86) 4316d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov fprintf(stderr, " (0x%08lX 0x%08lX 0x%08lX 0x%08lX)", 4320bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer static_cast<DWORD>(StackFrame.Params[0]), 4330bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer static_cast<DWORD>(StackFrame.Params[1]), 4340bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer static_cast<DWORD>(StackFrame.Params[2]), 4350bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer static_cast<DWORD>(StackFrame.Params[3])); 4360bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer#endif 4376d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov // Verify the PC belongs to a module in this process. 4380bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer if (!SymGetModuleBase64(hProcess, PC)) { 4396d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov fputs(" <unknown module>\n", stderr); 4406d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov continue; 4416d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov } 44290b54138834a057179c7a02931217ab5a82ed389Reid Spencer 4436d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov // Print the symbol name. 4446d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov char buffer[512]; 4450bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer IMAGEHLP_SYMBOL64 *symbol = reinterpret_cast<IMAGEHLP_SYMBOL64 *>(buffer); 4460bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer memset(symbol, 0, sizeof(IMAGEHLP_SYMBOL64)); 4470bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); 4480bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer symbol->MaxNameLength = 512 - sizeof(IMAGEHLP_SYMBOL64); 4496d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov 4500bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer DWORD64 dwDisp; 4510bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer if (!SymGetSymFromAddr64(hProcess, PC, &dwDisp, symbol)) { 45290b54138834a057179c7a02931217ab5a82ed389Reid Spencer fputc('\n', stderr); 4536d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov continue; 4546d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov } 4556d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov 4566d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov buffer[511] = 0; 4576d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov if (dwDisp > 0) 4580bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer fprintf(stderr, ", %s() + 0x%llX bytes(s)", symbol->Name, dwDisp); 4596d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov else 4606d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov fprintf(stderr, ", %s", symbol->Name); 4616d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov 4626d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov // Print the source file and line number information. 4630bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer IMAGEHLP_LINE64 line; 4640bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer DWORD dwLineDisp; 4656d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov memset(&line, 0, sizeof(line)); 4666d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov line.SizeOfStruct = sizeof(line); 4670bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer if (SymGetLineFromAddr64(hProcess, PC, &dwLineDisp, &line)) { 4686d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov fprintf(stderr, ", %s, line %lu", line.FileName, line.LineNumber); 4690bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer if (dwLineDisp > 0) 4700bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer fprintf(stderr, " + 0x%lX byte(s)", dwLineDisp); 47190b54138834a057179c7a02931217ab5a82ed389Reid Spencer } 4720ccb93034a47303509ee2c89b8bf13956a510b94Chuck Rose III 4736d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov fputc('\n', stderr); 4746d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov } 4756d8ac5ac6d87451d52651ba5e6cc0abffb4c264eMikhail Glushenkov 476df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar if (ExitOnUnhandledExceptions) 4775d2f8c31556b6a5ce29d2cad314bc48af879c5b3NAKAMURA Takumi _exit(ep->ExceptionRecord->ExceptionCode); 478df3388492bc2bfc73b3e0195693e2f67f10dcf52Daniel Dunbar 47990b54138834a057179c7a02931217ab5a82ed389Reid Spencer // Allow dialog box to pop up allowing choice to start debugger. 4807b60a15abc155196d9515a1e242ec0137afff753Reid Spencer if (OldFilter) 4817b60a15abc155196d9515a1e242ec0137afff753Reid Spencer return (*OldFilter)(ep); 4827b60a15abc155196d9515a1e242ec0137afff753Reid Spencer else 4837b60a15abc155196d9515a1e242ec0137afff753Reid Spencer return EXCEPTION_CONTINUE_SEARCH; 48490b54138834a057179c7a02931217ab5a82ed389Reid Spencer} 48590b54138834a057179c7a02931217ab5a82ed389Reid Spencer 48690b54138834a057179c7a02931217ab5a82ed389Reid Spencerstatic BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType) { 48764fe58490d28b7f7ba3ecb78fd9290688ded8f0cJeff Cohen // We are running in our very own thread, courtesy of Windows. 488ee841a1a8735805f84d609ae105bec92525033c6Jeff Cohen EnterCriticalSection(&CriticalSection); 48990b54138834a057179c7a02931217ab5a82ed389Reid Spencer Cleanup(); 49090b54138834a057179c7a02931217ab5a82ed389Reid Spencer 491ee841a1a8735805f84d609ae105bec92525033c6Jeff Cohen // If an interrupt function has been set, go and run one it; otherwise, 492ee841a1a8735805f84d609ae105bec92525033c6Jeff Cohen // the process dies. 493ee841a1a8735805f84d609ae105bec92525033c6Jeff Cohen void (*IF)() = InterruptFunction; 494ee841a1a8735805f84d609ae105bec92525033c6Jeff Cohen InterruptFunction = 0; // Don't run it on another CTRL-C. 495ee841a1a8735805f84d609ae105bec92525033c6Jeff Cohen 496ee841a1a8735805f84d609ae105bec92525033c6Jeff Cohen if (IF) { 49764fe58490d28b7f7ba3ecb78fd9290688ded8f0cJeff Cohen // Note: if the interrupt function throws an exception, there is nothing 49864fe58490d28b7f7ba3ecb78fd9290688ded8f0cJeff Cohen // to catch it in this thread so it will kill the process. 49964fe58490d28b7f7ba3ecb78fd9290688ded8f0cJeff Cohen IF(); // Run it now. 500ee841a1a8735805f84d609ae105bec92525033c6Jeff Cohen LeaveCriticalSection(&CriticalSection); 501ee841a1a8735805f84d609ae105bec92525033c6Jeff Cohen return TRUE; // Don't kill the process. 502ee841a1a8735805f84d609ae105bec92525033c6Jeff Cohen } 503ee841a1a8735805f84d609ae105bec92525033c6Jeff Cohen 504298d6c14ca1936677aaf6cca3efc569b6e53d294Reid Spencer // Allow normal processing to take place; i.e., the process dies. 505ee841a1a8735805f84d609ae105bec92525033c6Jeff Cohen LeaveCriticalSection(&CriticalSection); 50690b54138834a057179c7a02931217ab5a82ed389Reid Spencer return FALSE; 507496c277a6d161413e3f6976c9991ddccd8ecae8aReid Spencer} 5080bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer 5090bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer#if __MINGW32__ 5100bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer // We turned these warnings off for this file so that MinGW-g++ doesn't 5110bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer // complain about the ll format specifiers used. Now we are turning the 5120bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer // warnings back on. If MinGW starts to support diagnostic stacks, we can 5130bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer // replace this with a pop. 5140bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer #pragma GCC diagnostic warning "-Wformat" 5150bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer #pragma GCC diagnostic warning "-Wformat-extra-args" 5160bcd9c70b12b684706fbc0e337a827fd73c4f30aMichael J. Spencer#endif 517