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 "llvm/Support/Path.h" 15#include "llvm/Support/Process.h" 16#include "llvm/Support/WindowsError.h" 17#include <algorithm> 18#include <io.h> 19#include <signal.h> 20#include <stdio.h> 21 22#include "llvm/Support/Format.h" 23#include "llvm/Support/raw_ostream.h" 24 25// The Windows.h header must be after LLVM and standard headers. 26#include "WindowsSupport.h" 27 28#ifdef __MINGW32__ 29 #include <imagehlp.h> 30#else 31 #include <crtdbg.h> 32 #include <dbghelp.h> 33#endif 34#include <psapi.h> 35 36#ifdef _MSC_VER 37 #pragma comment(lib, "psapi.lib") 38#elif __MINGW32__ 39 #if (HAVE_LIBPSAPI != 1) 40 #error "libpsapi.a should be present" 41 #endif 42 // The version of g++ that comes with MinGW does *not* properly understand 43 // the ll format specifier for printf. However, MinGW passes the format 44 // specifiers on to the MSVCRT entirely, and the CRT understands the ll 45 // specifier. So these warnings are spurious in this case. Since we compile 46 // with -Wall, this will generate these warnings which should be ignored. So 47 // we will turn off the warnings for this just file. However, MinGW also does 48 // not support push and pop for diagnostics, so we have to manually turn it 49 // back on at the end of the file. 50 #pragma GCC diagnostic ignored "-Wformat" 51 #pragma GCC diagnostic ignored "-Wformat-extra-args" 52 53 #if !defined(__MINGW64_VERSION_MAJOR) 54 // MinGW.org does not have updated support for the 64-bit versions of the 55 // DebugHlp APIs. So we will have to load them manually. The structures and 56 // method signatures were pulled from DbgHelp.h in the Windows Platform SDK, 57 // and adjusted for brevity. 58 typedef struct _IMAGEHLP_LINE64 { 59 DWORD SizeOfStruct; 60 PVOID Key; 61 DWORD LineNumber; 62 PCHAR FileName; 63 DWORD64 Address; 64 } IMAGEHLP_LINE64, *PIMAGEHLP_LINE64; 65 66 typedef struct _IMAGEHLP_SYMBOL64 { 67 DWORD SizeOfStruct; 68 DWORD64 Address; 69 DWORD Size; 70 DWORD Flags; 71 DWORD MaxNameLength; 72 CHAR Name[1]; 73 } IMAGEHLP_SYMBOL64, *PIMAGEHLP_SYMBOL64; 74 75 typedef struct _tagADDRESS64 { 76 DWORD64 Offset; 77 WORD Segment; 78 ADDRESS_MODE Mode; 79 } ADDRESS64, *LPADDRESS64; 80 81 typedef struct _KDHELP64 { 82 DWORD64 Thread; 83 DWORD ThCallbackStack; 84 DWORD ThCallbackBStore; 85 DWORD NextCallback; 86 DWORD FramePointer; 87 DWORD64 KiCallUserMode; 88 DWORD64 KeUserCallbackDispatcher; 89 DWORD64 SystemRangeStart; 90 DWORD64 KiUserExceptionDispatcher; 91 DWORD64 StackBase; 92 DWORD64 StackLimit; 93 DWORD64 Reserved[5]; 94 } KDHELP64, *PKDHELP64; 95 96 typedef struct _tagSTACKFRAME64 { 97 ADDRESS64 AddrPC; 98 ADDRESS64 AddrReturn; 99 ADDRESS64 AddrFrame; 100 ADDRESS64 AddrStack; 101 ADDRESS64 AddrBStore; 102 PVOID FuncTableEntry; 103 DWORD64 Params[4]; 104 BOOL Far; 105 BOOL Virtual; 106 DWORD64 Reserved[3]; 107 KDHELP64 KdHelp; 108 } STACKFRAME64, *LPSTACKFRAME64; 109 #endif // !defined(__MINGW64_VERSION_MAJOR) 110#endif // __MINGW32__ 111 112typedef BOOL (__stdcall *PREAD_PROCESS_MEMORY_ROUTINE64)(HANDLE hProcess, 113 DWORD64 qwBaseAddress, PVOID lpBuffer, DWORD nSize, 114 LPDWORD lpNumberOfBytesRead); 115 116typedef PVOID (__stdcall *PFUNCTION_TABLE_ACCESS_ROUTINE64)( HANDLE ahProcess, 117 DWORD64 AddrBase); 118 119typedef DWORD64 (__stdcall *PGET_MODULE_BASE_ROUTINE64)(HANDLE hProcess, 120 DWORD64 Address); 121 122typedef DWORD64 (__stdcall *PTRANSLATE_ADDRESS_ROUTINE64)(HANDLE hProcess, 123 HANDLE hThread, LPADDRESS64 lpaddr); 124 125typedef BOOL(WINAPI *fpMiniDumpWriteDump)(HANDLE, DWORD, HANDLE, MINIDUMP_TYPE, 126 PMINIDUMP_EXCEPTION_INFORMATION, 127 PMINIDUMP_USER_STREAM_INFORMATION, 128 PMINIDUMP_CALLBACK_INFORMATION); 129static fpMiniDumpWriteDump fMiniDumpWriteDump; 130 131typedef BOOL (WINAPI *fpStackWalk64)(DWORD, HANDLE, HANDLE, LPSTACKFRAME64, 132 PVOID, PREAD_PROCESS_MEMORY_ROUTINE64, 133 PFUNCTION_TABLE_ACCESS_ROUTINE64, 134 PGET_MODULE_BASE_ROUTINE64, 135 PTRANSLATE_ADDRESS_ROUTINE64); 136static fpStackWalk64 fStackWalk64; 137 138typedef DWORD64 (WINAPI *fpSymGetModuleBase64)(HANDLE, DWORD64); 139static fpSymGetModuleBase64 fSymGetModuleBase64; 140 141typedef BOOL (WINAPI *fpSymGetSymFromAddr64)(HANDLE, DWORD64, 142 PDWORD64, PIMAGEHLP_SYMBOL64); 143static fpSymGetSymFromAddr64 fSymGetSymFromAddr64; 144 145typedef BOOL (WINAPI *fpSymGetLineFromAddr64)(HANDLE, DWORD64, 146 PDWORD, PIMAGEHLP_LINE64); 147static fpSymGetLineFromAddr64 fSymGetLineFromAddr64; 148 149typedef BOOL(WINAPI *fpSymGetModuleInfo64)(HANDLE hProcess, DWORD64 dwAddr, 150 PIMAGEHLP_MODULE64 ModuleInfo); 151static fpSymGetModuleInfo64 fSymGetModuleInfo64; 152 153typedef PVOID (WINAPI *fpSymFunctionTableAccess64)(HANDLE, DWORD64); 154static fpSymFunctionTableAccess64 fSymFunctionTableAccess64; 155 156typedef DWORD (WINAPI *fpSymSetOptions)(DWORD); 157static fpSymSetOptions fSymSetOptions; 158 159typedef BOOL (WINAPI *fpSymInitialize)(HANDLE, PCSTR, BOOL); 160static fpSymInitialize fSymInitialize; 161 162typedef BOOL (WINAPI *fpEnumerateLoadedModules)(HANDLE,PENUMLOADED_MODULES_CALLBACK64,PVOID); 163static fpEnumerateLoadedModules fEnumerateLoadedModules; 164 165static bool load64BitDebugHelp(void) { 166 HMODULE hLib = ::LoadLibraryW(L"Dbghelp.dll"); 167 if (hLib) { 168 fMiniDumpWriteDump = (fpMiniDumpWriteDump) 169 ::GetProcAddress(hLib, "MiniDumpWriteDump"); 170 fStackWalk64 = (fpStackWalk64) 171 ::GetProcAddress(hLib, "StackWalk64"); 172 fSymGetModuleBase64 = (fpSymGetModuleBase64) 173 ::GetProcAddress(hLib, "SymGetModuleBase64"); 174 fSymGetSymFromAddr64 = (fpSymGetSymFromAddr64) 175 ::GetProcAddress(hLib, "SymGetSymFromAddr64"); 176 fSymGetLineFromAddr64 = (fpSymGetLineFromAddr64) 177 ::GetProcAddress(hLib, "SymGetLineFromAddr64"); 178 fSymGetModuleInfo64 = (fpSymGetModuleInfo64) 179 ::GetProcAddress(hLib, "SymGetModuleInfo64"); 180 fSymFunctionTableAccess64 = (fpSymFunctionTableAccess64) 181 ::GetProcAddress(hLib, "SymFunctionTableAccess64"); 182 fSymSetOptions = (fpSymSetOptions)::GetProcAddress(hLib, "SymSetOptions"); 183 fSymInitialize = (fpSymInitialize)::GetProcAddress(hLib, "SymInitialize"); 184 fEnumerateLoadedModules = (fpEnumerateLoadedModules) 185 ::GetProcAddress(hLib, "EnumerateLoadedModules64"); 186 } 187 return fStackWalk64 && fSymInitialize && fSymSetOptions && fMiniDumpWriteDump; 188} 189 190using namespace llvm; 191 192// Forward declare. 193static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep); 194static BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType); 195 196// InterruptFunction - The function to call if ctrl-c is pressed. 197static void (*InterruptFunction)() = 0; 198 199static std::vector<std::string> *FilesToRemove = NULL; 200static bool RegisteredUnhandledExceptionFilter = false; 201static bool CleanupExecuted = false; 202static PTOP_LEVEL_EXCEPTION_FILTER OldFilter = NULL; 203 204// Windows creates a new thread to execute the console handler when an event 205// (such as CTRL/C) occurs. This causes concurrency issues with the above 206// globals which this critical section addresses. 207static CRITICAL_SECTION CriticalSection; 208static bool CriticalSectionInitialized = false; 209 210static StringRef Argv0; 211 212enum { 213#if defined(_M_X64) 214 NativeMachineType = IMAGE_FILE_MACHINE_AMD64 215#else 216 NativeMachineType = IMAGE_FILE_MACHINE_I386 217#endif 218}; 219 220static bool printStackTraceWithLLVMSymbolizer(llvm::raw_ostream &OS, 221 HANDLE hProcess, HANDLE hThread, 222 STACKFRAME64 &StackFrameOrig, 223 CONTEXT *ContextOrig) { 224 // StackWalk64 modifies the incoming stack frame and context, so copy them. 225 STACKFRAME64 StackFrame = StackFrameOrig; 226 227 // Copy the register context so that we don't modify it while we unwind. We 228 // could use InitializeContext + CopyContext, but that's only required to get 229 // at AVX registers, which typically aren't needed by StackWalk64. Reduce the 230 // flag set to indicate that there's less data. 231 CONTEXT Context = *ContextOrig; 232 Context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER; 233 234 static void *StackTrace[256]; 235 size_t Depth = 0; 236 while (fStackWalk64(NativeMachineType, hProcess, hThread, &StackFrame, 237 &Context, 0, fSymFunctionTableAccess64, 238 fSymGetModuleBase64, 0)) { 239 if (StackFrame.AddrFrame.Offset == 0) 240 break; 241 StackTrace[Depth++] = (void *)(uintptr_t)StackFrame.AddrPC.Offset; 242 if (Depth >= array_lengthof(StackTrace)) 243 break; 244 } 245 246 return printSymbolizedStackTrace(Argv0, &StackTrace[0], Depth, OS); 247} 248 249namespace { 250struct FindModuleData { 251 void **StackTrace; 252 int Depth; 253 const char **Modules; 254 intptr_t *Offsets; 255 StringSaver *StrPool; 256}; 257} 258 259static BOOL CALLBACK findModuleCallback(PCSTR ModuleName, 260 DWORD64 ModuleBase, ULONG ModuleSize, 261 void *VoidData) { 262 FindModuleData *Data = (FindModuleData*)VoidData; 263 intptr_t Beg = ModuleBase; 264 intptr_t End = Beg + ModuleSize; 265 for (int I = 0; I < Data->Depth; I++) { 266 if (Data->Modules[I]) 267 continue; 268 intptr_t Addr = (intptr_t)Data->StackTrace[I]; 269 if (Beg <= Addr && Addr < End) { 270 Data->Modules[I] = Data->StrPool->save(ModuleName).data(); 271 Data->Offsets[I] = Addr - Beg; 272 } 273 } 274 return TRUE; 275} 276 277static bool findModulesAndOffsets(void **StackTrace, int Depth, 278 const char **Modules, intptr_t *Offsets, 279 const char *MainExecutableName, 280 StringSaver &StrPool) { 281 if (!fEnumerateLoadedModules) 282 return false; 283 FindModuleData Data; 284 Data.StackTrace = StackTrace; 285 Data.Depth = Depth; 286 Data.Modules = Modules; 287 Data.Offsets = Offsets; 288 Data.StrPool = &StrPool; 289 fEnumerateLoadedModules(GetCurrentProcess(), findModuleCallback, &Data); 290 return true; 291} 292 293static void PrintStackTraceForThread(llvm::raw_ostream &OS, HANDLE hProcess, 294 HANDLE hThread, STACKFRAME64 &StackFrame, 295 CONTEXT *Context) { 296#if ENABLE_BACKTRACES 297 // Initialize the symbol handler. 298 fSymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES); 299 fSymInitialize(hProcess, NULL, TRUE); 300 301 // Try llvm-symbolizer first. llvm-symbolizer knows how to deal with both PDBs 302 // and DWARF, so it should do a good job regardless of what debug info or 303 // linker is in use. 304 if (printStackTraceWithLLVMSymbolizer(OS, hProcess, hThread, StackFrame, 305 Context)) { 306 return; 307 } 308 309 while (true) { 310 if (!fStackWalk64(NativeMachineType, hProcess, hThread, &StackFrame, 311 Context, 0, fSymFunctionTableAccess64, 312 fSymGetModuleBase64, 0)) { 313 break; 314 } 315 316 if (StackFrame.AddrFrame.Offset == 0) 317 break; 318 319 using namespace llvm; 320 // Print the PC in hexadecimal. 321 DWORD64 PC = StackFrame.AddrPC.Offset; 322#if defined(_M_X64) 323 OS << format("0x%016llX", PC); 324#elif defined(_M_IX86) 325 OS << format("0x%08lX", static_cast<DWORD>(PC)); 326#endif 327 328// Print the parameters. Assume there are four. 329#if defined(_M_X64) 330 OS << format(" (0x%016llX 0x%016llX 0x%016llX 0x%016llX)", 331 StackFrame.Params[0], StackFrame.Params[1], StackFrame.Params[2], 332 StackFrame.Params[3]); 333#elif defined(_M_IX86) 334 OS << format(" (0x%08lX 0x%08lX 0x%08lX 0x%08lX)", 335 static_cast<DWORD>(StackFrame.Params[0]), 336 static_cast<DWORD>(StackFrame.Params[1]), 337 static_cast<DWORD>(StackFrame.Params[2]), 338 static_cast<DWORD>(StackFrame.Params[3])); 339#endif 340 // Verify the PC belongs to a module in this process. 341 if (!fSymGetModuleBase64(hProcess, PC)) { 342 OS << " <unknown module>\n"; 343 continue; 344 } 345 346 // Print the symbol name. 347 char buffer[512]; 348 IMAGEHLP_SYMBOL64 *symbol = reinterpret_cast<IMAGEHLP_SYMBOL64 *>(buffer); 349 memset(symbol, 0, sizeof(IMAGEHLP_SYMBOL64)); 350 symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); 351 symbol->MaxNameLength = 512 - sizeof(IMAGEHLP_SYMBOL64); 352 353 DWORD64 dwDisp; 354 if (!fSymGetSymFromAddr64(hProcess, PC, &dwDisp, symbol)) { 355 OS << '\n'; 356 continue; 357 } 358 359 buffer[511] = 0; 360 if (dwDisp > 0) 361 OS << format(", %s() + 0x%llX bytes(s)", (const char*)symbol->Name, 362 dwDisp); 363 else 364 OS << format(", %s", (const char*)symbol->Name); 365 366 // Print the source file and line number information. 367 IMAGEHLP_LINE64 line = {}; 368 DWORD dwLineDisp; 369 line.SizeOfStruct = sizeof(line); 370 if (fSymGetLineFromAddr64(hProcess, PC, &dwLineDisp, &line)) { 371 OS << format(", %s, line %lu", line.FileName, line.LineNumber); 372 if (dwLineDisp > 0) 373 OS << format(" + 0x%lX byte(s)", dwLineDisp); 374 } 375 376 OS << '\n'; 377 } 378#endif 379} 380 381namespace llvm { 382 383//===----------------------------------------------------------------------===// 384//=== WARNING: Implementation here must contain only Win32 specific code 385//=== and must not be UNIX code 386//===----------------------------------------------------------------------===// 387 388#ifdef _MSC_VER 389/// AvoidMessageBoxHook - Emulates hitting "retry" from an "abort, retry, 390/// ignore" CRT debug report dialog. "retry" raises an exception which 391/// ultimately triggers our stack dumper. 392static LLVM_ATTRIBUTE_UNUSED int 393AvoidMessageBoxHook(int ReportType, char *Message, int *Return) { 394 // Set *Return to the retry code for the return value of _CrtDbgReport: 395 // http://msdn.microsoft.com/en-us/library/8hyw4sy7(v=vs.71).aspx 396 // This may also trigger just-in-time debugging via DebugBreak(). 397 if (Return) 398 *Return = 1; 399 // Don't call _CrtDbgReport. 400 return TRUE; 401} 402 403#endif 404 405extern "C" void HandleAbort(int Sig) { 406 if (Sig == SIGABRT) { 407 LLVM_BUILTIN_TRAP; 408 } 409} 410 411static void InitializeThreading() { 412 if (CriticalSectionInitialized) 413 return; 414 415 // Now's the time to create the critical section. This is the first time 416 // through here, and there's only one thread. 417 InitializeCriticalSection(&CriticalSection); 418 CriticalSectionInitialized = true; 419} 420 421static void RegisterHandler() { 422 // If we cannot load up the APIs (which would be unexpected as they should 423 // exist on every version of Windows we support), we will bail out since 424 // there would be nothing to report. 425 if (!load64BitDebugHelp()) { 426 assert(false && "These APIs should always be available"); 427 return; 428 } 429 430 if (RegisteredUnhandledExceptionFilter) { 431 EnterCriticalSection(&CriticalSection); 432 return; 433 } 434 435 InitializeThreading(); 436 437 // Enter it immediately. Now if someone hits CTRL/C, the console handler 438 // can't proceed until the globals are updated. 439 EnterCriticalSection(&CriticalSection); 440 441 RegisteredUnhandledExceptionFilter = true; 442 OldFilter = SetUnhandledExceptionFilter(LLVMUnhandledExceptionFilter); 443 SetConsoleCtrlHandler(LLVMConsoleCtrlHandler, TRUE); 444 445 // IMPORTANT NOTE: Caller must call LeaveCriticalSection(&CriticalSection) or 446 // else multi-threading problems will ensue. 447} 448 449// RemoveFileOnSignal - The public API 450bool sys::RemoveFileOnSignal(StringRef Filename, std::string* ErrMsg) { 451 RegisterHandler(); 452 453 if (CleanupExecuted) { 454 if (ErrMsg) 455 *ErrMsg = "Process terminating -- cannot register for removal"; 456 return true; 457 } 458 459 if (FilesToRemove == NULL) 460 FilesToRemove = new std::vector<std::string>; 461 462 FilesToRemove->push_back(Filename); 463 464 LeaveCriticalSection(&CriticalSection); 465 return false; 466} 467 468// DontRemoveFileOnSignal - The public API 469void sys::DontRemoveFileOnSignal(StringRef Filename) { 470 if (FilesToRemove == NULL) 471 return; 472 473 RegisterHandler(); 474 475 std::vector<std::string>::reverse_iterator I = 476 find(reverse(*FilesToRemove), Filename); 477 if (I != FilesToRemove->rend()) 478 FilesToRemove->erase(I.base()-1); 479 480 LeaveCriticalSection(&CriticalSection); 481} 482 483void sys::DisableSystemDialogsOnCrash() { 484 // Crash to stack trace handler on abort. 485 signal(SIGABRT, HandleAbort); 486 487 // The following functions are not reliably accessible on MinGW. 488#ifdef _MSC_VER 489 // We're already handling writing a "something went wrong" message. 490 _set_abort_behavior(0, _WRITE_ABORT_MSG); 491 // Disable Dr. Watson. 492 _set_abort_behavior(0, _CALL_REPORTFAULT); 493 _CrtSetReportHook(AvoidMessageBoxHook); 494#endif 495 496 // Disable standard error dialog box. 497 SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | 498 SEM_NOOPENFILEERRORBOX); 499 _set_error_mode(_OUT_TO_STDERR); 500} 501 502/// PrintStackTraceOnErrorSignal - When an error signal (such as SIBABRT or 503/// SIGSEGV) is delivered to the process, print a stack trace and then exit. 504void sys::PrintStackTraceOnErrorSignal(StringRef Argv0, 505 bool DisableCrashReporting) { 506 ::Argv0 = Argv0; 507 508 if (DisableCrashReporting || getenv("LLVM_DISABLE_CRASH_REPORT")) 509 Process::PreventCoreFiles(); 510 511 DisableSystemDialogsOnCrash(); 512 RegisterHandler(); 513 LeaveCriticalSection(&CriticalSection); 514} 515} 516 517#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) 518// Provide a prototype for RtlCaptureContext, mingw32 from mingw.org is 519// missing it but mingw-w64 has it. 520extern "C" VOID WINAPI RtlCaptureContext(PCONTEXT ContextRecord); 521#endif 522 523void llvm::sys::PrintStackTrace(raw_ostream &OS) { 524 STACKFRAME64 StackFrame = {}; 525 CONTEXT Context = {}; 526 ::RtlCaptureContext(&Context); 527#if defined(_M_X64) 528 StackFrame.AddrPC.Offset = Context.Rip; 529 StackFrame.AddrStack.Offset = Context.Rsp; 530 StackFrame.AddrFrame.Offset = Context.Rbp; 531#else 532 StackFrame.AddrPC.Offset = Context.Eip; 533 StackFrame.AddrStack.Offset = Context.Esp; 534 StackFrame.AddrFrame.Offset = Context.Ebp; 535#endif 536 StackFrame.AddrPC.Mode = AddrModeFlat; 537 StackFrame.AddrStack.Mode = AddrModeFlat; 538 StackFrame.AddrFrame.Mode = AddrModeFlat; 539 PrintStackTraceForThread(OS, GetCurrentProcess(), GetCurrentThread(), 540 StackFrame, &Context); 541} 542 543 544void llvm::sys::SetInterruptFunction(void (*IF)()) { 545 RegisterHandler(); 546 InterruptFunction = IF; 547 LeaveCriticalSection(&CriticalSection); 548} 549 550 551/// AddSignalHandler - Add a function to be called when a signal is delivered 552/// to the process. The handler can have a cookie passed to it to identify 553/// what instance of the handler it is. 554void llvm::sys::AddSignalHandler(void (*FnPtr)(void *), void *Cookie) { 555 CallBacksToRun->push_back(std::make_pair(FnPtr, Cookie)); 556 RegisterHandler(); 557 LeaveCriticalSection(&CriticalSection); 558} 559 560static void Cleanup() { 561 if (CleanupExecuted) 562 return; 563 564 EnterCriticalSection(&CriticalSection); 565 566 // Prevent other thread from registering new files and directories for 567 // removal, should we be executing because of the console handler callback. 568 CleanupExecuted = true; 569 570 // FIXME: open files cannot be deleted. 571 if (FilesToRemove != NULL) 572 while (!FilesToRemove->empty()) { 573 llvm::sys::fs::remove(FilesToRemove->back()); 574 FilesToRemove->pop_back(); 575 } 576 llvm::sys::RunSignalHandlers(); 577 LeaveCriticalSection(&CriticalSection); 578} 579 580void llvm::sys::RunInterruptHandlers() { 581 // The interrupt handler may be called from an interrupt, but it may also be 582 // called manually (such as the case of report_fatal_error with no registered 583 // error handler). We must ensure that the critical section is properly 584 // initialized. 585 InitializeThreading(); 586 Cleanup(); 587} 588 589/// \brief Find the Windows Registry Key for a given location. 590/// 591/// \returns a valid HKEY if the location exists, else NULL. 592static HKEY FindWERKey(const llvm::Twine &RegistryLocation) { 593 HKEY Key; 594 if (ERROR_SUCCESS != ::RegOpenKeyExA(HKEY_LOCAL_MACHINE, 595 RegistryLocation.str().c_str(), 0, 596 KEY_QUERY_VALUE | KEY_READ, &Key)) 597 return NULL; 598 599 return Key; 600} 601 602/// \brief Populate ResultDirectory with the value for "DumpFolder" for a given 603/// Windows Registry key. 604/// 605/// \returns true if a valid value for DumpFolder exists, false otherwise. 606static bool GetDumpFolder(HKEY Key, 607 llvm::SmallVectorImpl<char> &ResultDirectory) { 608 using llvm::sys::windows::UTF16ToUTF8; 609 610 if (!Key) 611 return false; 612 613 DWORD BufferLengthBytes = 0; 614 615 if (ERROR_SUCCESS != ::RegGetValueW(Key, 0, L"DumpFolder", REG_EXPAND_SZ, 616 NULL, NULL, &BufferLengthBytes)) 617 return false; 618 619 SmallVector<wchar_t, MAX_PATH> Buffer(BufferLengthBytes); 620 621 if (ERROR_SUCCESS != ::RegGetValueW(Key, 0, L"DumpFolder", REG_EXPAND_SZ, 622 NULL, Buffer.data(), &BufferLengthBytes)) 623 return false; 624 625 DWORD ExpandBufferSize = ::ExpandEnvironmentStringsW(Buffer.data(), NULL, 0); 626 627 if (!ExpandBufferSize) 628 return false; 629 630 SmallVector<wchar_t, MAX_PATH> ExpandBuffer(ExpandBufferSize); 631 632 if (ExpandBufferSize != ::ExpandEnvironmentStringsW(Buffer.data(), 633 ExpandBuffer.data(), 634 ExpandBufferSize)) 635 return false; 636 637 if (UTF16ToUTF8(ExpandBuffer.data(), ExpandBufferSize - 1, ResultDirectory)) 638 return false; 639 640 return true; 641} 642 643/// \brief Populate ResultType with a valid MINIDUMP_TYPE based on the value of 644/// "DumpType" for a given Windows Registry key. 645/// 646/// According to 647/// https://msdn.microsoft.com/en-us/library/windows/desktop/bb787181(v=vs.85).aspx 648/// valid values for DumpType are: 649/// * 0: Custom dump 650/// * 1: Mini dump 651/// * 2: Full dump 652/// If "Custom dump" is specified then the "CustomDumpFlags" field is read 653/// containing a bitwise combination of MINIDUMP_TYPE values. 654/// 655/// \returns true if a valid value for ResultType can be set, false otherwise. 656static bool GetDumpType(HKEY Key, MINIDUMP_TYPE &ResultType) { 657 if (!Key) 658 return false; 659 660 DWORD DumpType; 661 DWORD TypeSize = sizeof(DumpType); 662 if (ERROR_SUCCESS != ::RegGetValueW(Key, NULL, L"DumpType", RRF_RT_REG_DWORD, 663 NULL, &DumpType, 664 &TypeSize)) 665 return false; 666 667 switch (DumpType) { 668 case 0: { 669 DWORD Flags = 0; 670 if (ERROR_SUCCESS != ::RegGetValueW(Key, NULL, L"CustomDumpFlags", 671 RRF_RT_REG_DWORD, NULL, &Flags, 672 &TypeSize)) 673 return false; 674 675 ResultType = static_cast<MINIDUMP_TYPE>(Flags); 676 break; 677 } 678 case 1: 679 ResultType = MiniDumpNormal; 680 break; 681 case 2: 682 ResultType = MiniDumpWithFullMemory; 683 break; 684 default: 685 return false; 686 } 687 return true; 688} 689 690/// \brief Write a Windows dump file containing process information that can be 691/// used for post-mortem debugging. 692/// 693/// \returns zero error code if a mini dump created, actual error code 694/// otherwise. 695static std::error_code WINAPI 696WriteWindowsDumpFile(PMINIDUMP_EXCEPTION_INFORMATION ExceptionInfo) { 697 using namespace llvm; 698 using namespace llvm::sys; 699 700 std::string MainExecutableName = fs::getMainExecutable(nullptr, nullptr); 701 StringRef ProgramName; 702 703 if (MainExecutableName.empty()) { 704 // If we can't get the executable filename, 705 // things are in worse shape than we realize 706 // and we should just bail out. 707 return mapWindowsError(::GetLastError()); 708 } 709 710 ProgramName = path::filename(MainExecutableName.c_str()); 711 712 // The Windows Registry location as specified at 713 // https://msdn.microsoft.com/en-us/library/windows/desktop/bb787181%28v=vs.85%29.aspx 714 // "Collecting User-Mode Dumps" that may optionally be set to collect crash 715 // dumps in a specified location. 716 StringRef LocalDumpsRegistryLocation = 717 "SOFTWARE\\Microsoft\\Windows\\Windows Error Reporting\\LocalDumps"; 718 719 // The key pointing to the Registry location that may contain global crash 720 // dump settings. This will be NULL if the location can not be found. 721 ScopedRegHandle DefaultLocalDumpsKey(FindWERKey(LocalDumpsRegistryLocation)); 722 723 // The key pointing to the Registry location that may contain 724 // application-specific crash dump settings. This will be NULL if the 725 // location can not be found. 726 ScopedRegHandle AppSpecificKey( 727 FindWERKey(Twine(LocalDumpsRegistryLocation) + "\\" + ProgramName)); 728 729 // Look to see if a dump type is specified in the registry; first with the 730 // app-specific key and failing that with the global key. If none are found 731 // default to a normal dump (GetDumpType will return false either if the key 732 // is NULL or if there is no valid DumpType value at its location). 733 MINIDUMP_TYPE DumpType; 734 if (!GetDumpType(AppSpecificKey, DumpType)) 735 if (!GetDumpType(DefaultLocalDumpsKey, DumpType)) 736 DumpType = MiniDumpNormal; 737 738 // Look to see if a dump location is specified in the registry; first with the 739 // app-specific key and failing that with the global key. If none are found 740 // we'll just create the dump file in the default temporary file location 741 // (GetDumpFolder will return false either if the key is NULL or if there is 742 // no valid DumpFolder value at its location). 743 bool ExplicitDumpDirectorySet = true; 744 SmallString<MAX_PATH> DumpDirectory; 745 if (!GetDumpFolder(AppSpecificKey, DumpDirectory)) 746 if (!GetDumpFolder(DefaultLocalDumpsKey, DumpDirectory)) 747 ExplicitDumpDirectorySet = false; 748 749 int FD; 750 SmallString<MAX_PATH> DumpPath; 751 752 if (ExplicitDumpDirectorySet) { 753 if (std::error_code EC = fs::create_directories(DumpDirectory)) 754 return EC; 755 if (std::error_code EC = fs::createUniqueFile( 756 Twine(DumpDirectory) + "\\" + ProgramName + ".%%%%%%.dmp", FD, 757 DumpPath)) 758 return EC; 759 } else if (std::error_code EC = 760 fs::createTemporaryFile(ProgramName, "dmp", FD, DumpPath)) 761 return EC; 762 763 // Our support functions return a file descriptor but Windows wants a handle. 764 ScopedCommonHandle FileHandle(reinterpret_cast<HANDLE>(_get_osfhandle(FD))); 765 766 if (!fMiniDumpWriteDump(::GetCurrentProcess(), ::GetCurrentProcessId(), 767 FileHandle, DumpType, ExceptionInfo, NULL, NULL)) 768 return mapWindowsError(::GetLastError()); 769 770 llvm::errs() << "Wrote crash dump file \"" << DumpPath << "\"\n"; 771 return std::error_code(); 772} 773 774static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep) { 775 Cleanup(); 776 777 // We'll automatically write a Minidump file here to help diagnose 778 // the nasty sorts of crashes that aren't 100% reproducible from a set of 779 // inputs (or in the event that the user is unable or unwilling to provide a 780 // reproducible case). 781 if (!llvm::Process::AreCoreFilesPrevented()) { 782 MINIDUMP_EXCEPTION_INFORMATION ExceptionInfo; 783 ExceptionInfo.ThreadId = ::GetCurrentThreadId(); 784 ExceptionInfo.ExceptionPointers = ep; 785 ExceptionInfo.ClientPointers = FALSE; 786 787 if (std::error_code EC = WriteWindowsDumpFile(&ExceptionInfo)) 788 llvm::errs() << "Could not write crash dump file: " << EC.message() 789 << "\n"; 790 } 791 792 // Initialize the STACKFRAME structure. 793 STACKFRAME64 StackFrame = {}; 794 795#if defined(_M_X64) 796 StackFrame.AddrPC.Offset = ep->ContextRecord->Rip; 797 StackFrame.AddrPC.Mode = AddrModeFlat; 798 StackFrame.AddrStack.Offset = ep->ContextRecord->Rsp; 799 StackFrame.AddrStack.Mode = AddrModeFlat; 800 StackFrame.AddrFrame.Offset = ep->ContextRecord->Rbp; 801 StackFrame.AddrFrame.Mode = AddrModeFlat; 802#elif defined(_M_IX86) 803 StackFrame.AddrPC.Offset = ep->ContextRecord->Eip; 804 StackFrame.AddrPC.Mode = AddrModeFlat; 805 StackFrame.AddrStack.Offset = ep->ContextRecord->Esp; 806 StackFrame.AddrStack.Mode = AddrModeFlat; 807 StackFrame.AddrFrame.Offset = ep->ContextRecord->Ebp; 808 StackFrame.AddrFrame.Mode = AddrModeFlat; 809#endif 810 811 HANDLE hProcess = GetCurrentProcess(); 812 HANDLE hThread = GetCurrentThread(); 813 PrintStackTraceForThread(llvm::errs(), hProcess, hThread, StackFrame, 814 ep->ContextRecord); 815 816 _exit(ep->ExceptionRecord->ExceptionCode); 817} 818 819static BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType) { 820 // We are running in our very own thread, courtesy of Windows. 821 EnterCriticalSection(&CriticalSection); 822 Cleanup(); 823 824 // If an interrupt function has been set, go and run one it; otherwise, 825 // the process dies. 826 void (*IF)() = InterruptFunction; 827 InterruptFunction = 0; // Don't run it on another CTRL-C. 828 829 if (IF) { 830 // Note: if the interrupt function throws an exception, there is nothing 831 // to catch it in this thread so it will kill the process. 832 IF(); // Run it now. 833 LeaveCriticalSection(&CriticalSection); 834 return TRUE; // Don't kill the process. 835 } 836 837 // Allow normal processing to take place; i.e., the process dies. 838 LeaveCriticalSection(&CriticalSection); 839 return FALSE; 840} 841 842#if __MINGW32__ 843 // We turned these warnings off for this file so that MinGW-g++ doesn't 844 // complain about the ll format specifiers used. Now we are turning the 845 // warnings back on. If MinGW starts to support diagnostic stacks, we can 846 // replace this with a pop. 847 #pragma GCC diagnostic warning "-Wformat" 848 #pragma GCC diagnostic warning "-Wformat-extra-args" 849#endif 850