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 // Initialize the symbol handler. 297 fSymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES); 298 fSymInitialize(hProcess, NULL, TRUE); 299 300 // Try llvm-symbolizer first. llvm-symbolizer knows how to deal with both PDBs 301 // and DWARF, so it should do a good job regardless of what debug info or 302 // linker is in use. 303 if (printStackTraceWithLLVMSymbolizer(OS, hProcess, hThread, StackFrame, 304 Context)) { 305 return; 306 } 307 308 while (true) { 309 if (!fStackWalk64(NativeMachineType, hProcess, hThread, &StackFrame, 310 Context, 0, fSymFunctionTableAccess64, 311 fSymGetModuleBase64, 0)) { 312 break; 313 } 314 315 if (StackFrame.AddrFrame.Offset == 0) 316 break; 317 318 using namespace llvm; 319 // Print the PC in hexadecimal. 320 DWORD64 PC = StackFrame.AddrPC.Offset; 321#if defined(_M_X64) 322 OS << format("0x%016llX", PC); 323#elif defined(_M_IX86) 324 OS << format("0x%08lX", static_cast<DWORD>(PC)); 325#endif 326 327// Print the parameters. Assume there are four. 328#if defined(_M_X64) 329 OS << format(" (0x%016llX 0x%016llX 0x%016llX 0x%016llX)", 330 StackFrame.Params[0], StackFrame.Params[1], StackFrame.Params[2], 331 StackFrame.Params[3]); 332#elif defined(_M_IX86) 333 OS << format(" (0x%08lX 0x%08lX 0x%08lX 0x%08lX)", 334 static_cast<DWORD>(StackFrame.Params[0]), 335 static_cast<DWORD>(StackFrame.Params[1]), 336 static_cast<DWORD>(StackFrame.Params[2]), 337 static_cast<DWORD>(StackFrame.Params[3])); 338#endif 339 // Verify the PC belongs to a module in this process. 340 if (!fSymGetModuleBase64(hProcess, PC)) { 341 OS << " <unknown module>\n"; 342 continue; 343 } 344 345 // Print the symbol name. 346 char buffer[512]; 347 IMAGEHLP_SYMBOL64 *symbol = reinterpret_cast<IMAGEHLP_SYMBOL64 *>(buffer); 348 memset(symbol, 0, sizeof(IMAGEHLP_SYMBOL64)); 349 symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); 350 symbol->MaxNameLength = 512 - sizeof(IMAGEHLP_SYMBOL64); 351 352 DWORD64 dwDisp; 353 if (!fSymGetSymFromAddr64(hProcess, PC, &dwDisp, symbol)) { 354 OS << '\n'; 355 continue; 356 } 357 358 buffer[511] = 0; 359 if (dwDisp > 0) 360 OS << format(", %s() + 0x%llX bytes(s)", (const char*)symbol->Name, 361 dwDisp); 362 else 363 OS << format(", %s", (const char*)symbol->Name); 364 365 // Print the source file and line number information. 366 IMAGEHLP_LINE64 line = {}; 367 DWORD dwLineDisp; 368 line.SizeOfStruct = sizeof(line); 369 if (fSymGetLineFromAddr64(hProcess, PC, &dwLineDisp, &line)) { 370 OS << format(", %s, line %lu", line.FileName, line.LineNumber); 371 if (dwLineDisp > 0) 372 OS << format(" + 0x%lX byte(s)", dwLineDisp); 373 } 374 375 OS << '\n'; 376 } 377} 378 379namespace llvm { 380 381//===----------------------------------------------------------------------===// 382//=== WARNING: Implementation here must contain only Win32 specific code 383//=== and must not be UNIX code 384//===----------------------------------------------------------------------===// 385 386#ifdef _MSC_VER 387/// AvoidMessageBoxHook - Emulates hitting "retry" from an "abort, retry, 388/// ignore" CRT debug report dialog. "retry" raises an exception which 389/// ultimately triggers our stack dumper. 390static LLVM_ATTRIBUTE_UNUSED int 391AvoidMessageBoxHook(int ReportType, char *Message, int *Return) { 392 // Set *Return to the retry code for the return value of _CrtDbgReport: 393 // http://msdn.microsoft.com/en-us/library/8hyw4sy7(v=vs.71).aspx 394 // This may also trigger just-in-time debugging via DebugBreak(). 395 if (Return) 396 *Return = 1; 397 // Don't call _CrtDbgReport. 398 return TRUE; 399} 400 401#endif 402 403extern "C" void HandleAbort(int Sig) { 404 if (Sig == SIGABRT) { 405 LLVM_BUILTIN_TRAP; 406 } 407} 408 409static void InitializeThreading() { 410 if (CriticalSectionInitialized) 411 return; 412 413 // Now's the time to create the critical section. This is the first time 414 // through here, and there's only one thread. 415 InitializeCriticalSection(&CriticalSection); 416 CriticalSectionInitialized = true; 417} 418 419static void RegisterHandler() { 420 // If we cannot load up the APIs (which would be unexpected as they should 421 // exist on every version of Windows we support), we will bail out since 422 // there would be nothing to report. 423 if (!load64BitDebugHelp()) { 424 assert(false && "These APIs should always be available"); 425 return; 426 } 427 428 if (RegisteredUnhandledExceptionFilter) { 429 EnterCriticalSection(&CriticalSection); 430 return; 431 } 432 433 InitializeThreading(); 434 435 // Enter it immediately. Now if someone hits CTRL/C, the console handler 436 // can't proceed until the globals are updated. 437 EnterCriticalSection(&CriticalSection); 438 439 RegisteredUnhandledExceptionFilter = true; 440 OldFilter = SetUnhandledExceptionFilter(LLVMUnhandledExceptionFilter); 441 SetConsoleCtrlHandler(LLVMConsoleCtrlHandler, TRUE); 442 443 // IMPORTANT NOTE: Caller must call LeaveCriticalSection(&CriticalSection) or 444 // else multi-threading problems will ensue. 445} 446 447// RemoveFileOnSignal - The public API 448bool sys::RemoveFileOnSignal(StringRef Filename, std::string* ErrMsg) { 449 RegisterHandler(); 450 451 if (CleanupExecuted) { 452 if (ErrMsg) 453 *ErrMsg = "Process terminating -- cannot register for removal"; 454 return true; 455 } 456 457 if (FilesToRemove == NULL) 458 FilesToRemove = new std::vector<std::string>; 459 460 FilesToRemove->push_back(Filename); 461 462 LeaveCriticalSection(&CriticalSection); 463 return false; 464} 465 466// DontRemoveFileOnSignal - The public API 467void sys::DontRemoveFileOnSignal(StringRef Filename) { 468 if (FilesToRemove == NULL) 469 return; 470 471 RegisterHandler(); 472 473 std::vector<std::string>::reverse_iterator I = 474 find(reverse(*FilesToRemove), Filename); 475 if (I != FilesToRemove->rend()) 476 FilesToRemove->erase(I.base()-1); 477 478 LeaveCriticalSection(&CriticalSection); 479} 480 481void sys::DisableSystemDialogsOnCrash() { 482 // Crash to stack trace handler on abort. 483 signal(SIGABRT, HandleAbort); 484 485 // The following functions are not reliably accessible on MinGW. 486#ifdef _MSC_VER 487 // We're already handling writing a "something went wrong" message. 488 _set_abort_behavior(0, _WRITE_ABORT_MSG); 489 // Disable Dr. Watson. 490 _set_abort_behavior(0, _CALL_REPORTFAULT); 491 _CrtSetReportHook(AvoidMessageBoxHook); 492#endif 493 494 // Disable standard error dialog box. 495 SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | 496 SEM_NOOPENFILEERRORBOX); 497 _set_error_mode(_OUT_TO_STDERR); 498} 499 500/// PrintStackTraceOnErrorSignal - When an error signal (such as SIBABRT or 501/// SIGSEGV) is delivered to the process, print a stack trace and then exit. 502void sys::PrintStackTraceOnErrorSignal(StringRef Argv0, 503 bool DisableCrashReporting) { 504 ::Argv0 = Argv0; 505 506 if (DisableCrashReporting || getenv("LLVM_DISABLE_CRASH_REPORT")) 507 Process::PreventCoreFiles(); 508 509 DisableSystemDialogsOnCrash(); 510 RegisterHandler(); 511 LeaveCriticalSection(&CriticalSection); 512} 513} 514 515#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) 516// Provide a prototype for RtlCaptureContext, mingw32 from mingw.org is 517// missing it but mingw-w64 has it. 518extern "C" VOID WINAPI RtlCaptureContext(PCONTEXT ContextRecord); 519#endif 520 521void llvm::sys::PrintStackTrace(raw_ostream &OS) { 522 STACKFRAME64 StackFrame = {}; 523 CONTEXT Context = {}; 524 ::RtlCaptureContext(&Context); 525#if defined(_M_X64) 526 StackFrame.AddrPC.Offset = Context.Rip; 527 StackFrame.AddrStack.Offset = Context.Rsp; 528 StackFrame.AddrFrame.Offset = Context.Rbp; 529#else 530 StackFrame.AddrPC.Offset = Context.Eip; 531 StackFrame.AddrStack.Offset = Context.Esp; 532 StackFrame.AddrFrame.Offset = Context.Ebp; 533#endif 534 StackFrame.AddrPC.Mode = AddrModeFlat; 535 StackFrame.AddrStack.Mode = AddrModeFlat; 536 StackFrame.AddrFrame.Mode = AddrModeFlat; 537 PrintStackTraceForThread(OS, GetCurrentProcess(), GetCurrentThread(), 538 StackFrame, &Context); 539} 540 541 542void llvm::sys::SetInterruptFunction(void (*IF)()) { 543 RegisterHandler(); 544 InterruptFunction = IF; 545 LeaveCriticalSection(&CriticalSection); 546} 547 548 549/// AddSignalHandler - Add a function to be called when a signal is delivered 550/// to the process. The handler can have a cookie passed to it to identify 551/// what instance of the handler it is. 552void llvm::sys::AddSignalHandler(void (*FnPtr)(void *), void *Cookie) { 553 CallBacksToRun->push_back(std::make_pair(FnPtr, Cookie)); 554 RegisterHandler(); 555 LeaveCriticalSection(&CriticalSection); 556} 557 558static void Cleanup() { 559 if (CleanupExecuted) 560 return; 561 562 EnterCriticalSection(&CriticalSection); 563 564 // Prevent other thread from registering new files and directories for 565 // removal, should we be executing because of the console handler callback. 566 CleanupExecuted = true; 567 568 // FIXME: open files cannot be deleted. 569 if (FilesToRemove != NULL) 570 while (!FilesToRemove->empty()) { 571 llvm::sys::fs::remove(FilesToRemove->back()); 572 FilesToRemove->pop_back(); 573 } 574 llvm::sys::RunSignalHandlers(); 575 LeaveCriticalSection(&CriticalSection); 576} 577 578void llvm::sys::RunInterruptHandlers() { 579 // The interrupt handler may be called from an interrupt, but it may also be 580 // called manually (such as the case of report_fatal_error with no registered 581 // error handler). We must ensure that the critical section is properly 582 // initialized. 583 InitializeThreading(); 584 Cleanup(); 585} 586 587/// \brief Find the Windows Registry Key for a given location. 588/// 589/// \returns a valid HKEY if the location exists, else NULL. 590static HKEY FindWERKey(const llvm::Twine &RegistryLocation) { 591 HKEY Key; 592 if (ERROR_SUCCESS != ::RegOpenKeyExA(HKEY_LOCAL_MACHINE, 593 RegistryLocation.str().c_str(), 0, 594 KEY_QUERY_VALUE | KEY_READ, &Key)) 595 return NULL; 596 597 return Key; 598} 599 600/// \brief Populate ResultDirectory with the value for "DumpFolder" for a given 601/// Windows Registry key. 602/// 603/// \returns true if a valid value for DumpFolder exists, false otherwise. 604static bool GetDumpFolder(HKEY Key, 605 llvm::SmallVectorImpl<char> &ResultDirectory) { 606 using llvm::sys::windows::UTF16ToUTF8; 607 608 if (!Key) 609 return false; 610 611 DWORD BufferLengthBytes = 0; 612 613 if (ERROR_SUCCESS != ::RegGetValueW(Key, 0, L"DumpFolder", REG_EXPAND_SZ, 614 NULL, NULL, &BufferLengthBytes)) 615 return false; 616 617 SmallVector<wchar_t, MAX_PATH> Buffer(BufferLengthBytes); 618 619 if (ERROR_SUCCESS != ::RegGetValueW(Key, 0, L"DumpFolder", REG_EXPAND_SZ, 620 NULL, Buffer.data(), &BufferLengthBytes)) 621 return false; 622 623 DWORD ExpandBufferSize = ::ExpandEnvironmentStringsW(Buffer.data(), NULL, 0); 624 625 if (!ExpandBufferSize) 626 return false; 627 628 SmallVector<wchar_t, MAX_PATH> ExpandBuffer(ExpandBufferSize); 629 630 if (ExpandBufferSize != ::ExpandEnvironmentStringsW(Buffer.data(), 631 ExpandBuffer.data(), 632 ExpandBufferSize)) 633 return false; 634 635 if (UTF16ToUTF8(ExpandBuffer.data(), ExpandBufferSize - 1, ResultDirectory)) 636 return false; 637 638 return true; 639} 640 641/// \brief Populate ResultType with a valid MINIDUMP_TYPE based on the value of 642/// "DumpType" for a given Windows Registry key. 643/// 644/// According to 645/// https://msdn.microsoft.com/en-us/library/windows/desktop/bb787181(v=vs.85).aspx 646/// valid values for DumpType are: 647/// * 0: Custom dump 648/// * 1: Mini dump 649/// * 2: Full dump 650/// If "Custom dump" is specified then the "CustomDumpFlags" field is read 651/// containing a bitwise combination of MINIDUMP_TYPE values. 652/// 653/// \returns true if a valid value for ResultType can be set, false otherwise. 654static bool GetDumpType(HKEY Key, MINIDUMP_TYPE &ResultType) { 655 if (!Key) 656 return false; 657 658 DWORD DumpType; 659 DWORD TypeSize = sizeof(DumpType); 660 if (ERROR_SUCCESS != ::RegGetValueW(Key, NULL, L"DumpType", RRF_RT_REG_DWORD, 661 NULL, &DumpType, 662 &TypeSize)) 663 return false; 664 665 switch (DumpType) { 666 case 0: { 667 DWORD Flags = 0; 668 if (ERROR_SUCCESS != ::RegGetValueW(Key, NULL, L"CustomDumpFlags", 669 RRF_RT_REG_DWORD, NULL, &Flags, 670 &TypeSize)) 671 return false; 672 673 ResultType = static_cast<MINIDUMP_TYPE>(Flags); 674 break; 675 } 676 case 1: 677 ResultType = MiniDumpNormal; 678 break; 679 case 2: 680 ResultType = MiniDumpWithFullMemory; 681 break; 682 default: 683 return false; 684 } 685 return true; 686} 687 688/// \brief Write a Windows dump file containing process information that can be 689/// used for post-mortem debugging. 690/// 691/// \returns zero error code if a mini dump created, actual error code 692/// otherwise. 693static std::error_code WINAPI 694WriteWindowsDumpFile(PMINIDUMP_EXCEPTION_INFORMATION ExceptionInfo) { 695 using namespace llvm; 696 using namespace llvm::sys; 697 698 std::string MainExecutableName = fs::getMainExecutable(nullptr, nullptr); 699 StringRef ProgramName; 700 701 if (MainExecutableName.empty()) { 702 // If we can't get the executable filename, 703 // things are in worse shape than we realize 704 // and we should just bail out. 705 return mapWindowsError(::GetLastError()); 706 } 707 708 ProgramName = path::filename(MainExecutableName.c_str()); 709 710 // The Windows Registry location as specified at 711 // https://msdn.microsoft.com/en-us/library/windows/desktop/bb787181%28v=vs.85%29.aspx 712 // "Collecting User-Mode Dumps" that may optionally be set to collect crash 713 // dumps in a specified location. 714 StringRef LocalDumpsRegistryLocation = 715 "SOFTWARE\\Microsoft\\Windows\\Windows Error Reporting\\LocalDumps"; 716 717 // The key pointing to the Registry location that may contain global crash 718 // dump settings. This will be NULL if the location can not be found. 719 ScopedRegHandle DefaultLocalDumpsKey(FindWERKey(LocalDumpsRegistryLocation)); 720 721 // The key pointing to the Registry location that may contain 722 // application-specific crash dump settings. This will be NULL if the 723 // location can not be found. 724 ScopedRegHandle AppSpecificKey( 725 FindWERKey(Twine(LocalDumpsRegistryLocation) + "\\" + ProgramName)); 726 727 // Look to see if a dump type is specified in the registry; first with the 728 // app-specific key and failing that with the global key. If none are found 729 // default to a normal dump (GetDumpType will return false either if the key 730 // is NULL or if there is no valid DumpType value at its location). 731 MINIDUMP_TYPE DumpType; 732 if (!GetDumpType(AppSpecificKey, DumpType)) 733 if (!GetDumpType(DefaultLocalDumpsKey, DumpType)) 734 DumpType = MiniDumpNormal; 735 736 // Look to see if a dump location is specified in the registry; first with the 737 // app-specific key and failing that with the global key. If none are found 738 // we'll just create the dump file in the default temporary file location 739 // (GetDumpFolder will return false either if the key is NULL or if there is 740 // no valid DumpFolder value at its location). 741 bool ExplicitDumpDirectorySet = true; 742 SmallString<MAX_PATH> DumpDirectory; 743 if (!GetDumpFolder(AppSpecificKey, DumpDirectory)) 744 if (!GetDumpFolder(DefaultLocalDumpsKey, DumpDirectory)) 745 ExplicitDumpDirectorySet = false; 746 747 int FD; 748 SmallString<MAX_PATH> DumpPath; 749 750 if (ExplicitDumpDirectorySet) { 751 if (std::error_code EC = fs::create_directories(DumpDirectory)) 752 return EC; 753 if (std::error_code EC = fs::createUniqueFile( 754 Twine(DumpDirectory) + "\\" + ProgramName + ".%%%%%%.dmp", FD, 755 DumpPath)) 756 return EC; 757 } else if (std::error_code EC = 758 fs::createTemporaryFile(ProgramName, "dmp", FD, DumpPath)) 759 return EC; 760 761 // Our support functions return a file descriptor but Windows wants a handle. 762 ScopedCommonHandle FileHandle(reinterpret_cast<HANDLE>(_get_osfhandle(FD))); 763 764 if (!fMiniDumpWriteDump(::GetCurrentProcess(), ::GetCurrentProcessId(), 765 FileHandle, DumpType, ExceptionInfo, NULL, NULL)) 766 return mapWindowsError(::GetLastError()); 767 768 llvm::errs() << "Wrote crash dump file \"" << DumpPath << "\"\n"; 769 return std::error_code(); 770} 771 772static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep) { 773 Cleanup(); 774 775 // We'll automatically write a Minidump file here to help diagnose 776 // the nasty sorts of crashes that aren't 100% reproducible from a set of 777 // inputs (or in the event that the user is unable or unwilling to provide a 778 // reproducible case). 779 if (!llvm::Process::AreCoreFilesPrevented()) { 780 MINIDUMP_EXCEPTION_INFORMATION ExceptionInfo; 781 ExceptionInfo.ThreadId = ::GetCurrentThreadId(); 782 ExceptionInfo.ExceptionPointers = ep; 783 ExceptionInfo.ClientPointers = FALSE; 784 785 if (std::error_code EC = WriteWindowsDumpFile(&ExceptionInfo)) 786 llvm::errs() << "Could not write crash dump file: " << EC.message() 787 << "\n"; 788 } 789 790 // Initialize the STACKFRAME structure. 791 STACKFRAME64 StackFrame = {}; 792 793#if defined(_M_X64) 794 StackFrame.AddrPC.Offset = ep->ContextRecord->Rip; 795 StackFrame.AddrPC.Mode = AddrModeFlat; 796 StackFrame.AddrStack.Offset = ep->ContextRecord->Rsp; 797 StackFrame.AddrStack.Mode = AddrModeFlat; 798 StackFrame.AddrFrame.Offset = ep->ContextRecord->Rbp; 799 StackFrame.AddrFrame.Mode = AddrModeFlat; 800#elif defined(_M_IX86) 801 StackFrame.AddrPC.Offset = ep->ContextRecord->Eip; 802 StackFrame.AddrPC.Mode = AddrModeFlat; 803 StackFrame.AddrStack.Offset = ep->ContextRecord->Esp; 804 StackFrame.AddrStack.Mode = AddrModeFlat; 805 StackFrame.AddrFrame.Offset = ep->ContextRecord->Ebp; 806 StackFrame.AddrFrame.Mode = AddrModeFlat; 807#endif 808 809 HANDLE hProcess = GetCurrentProcess(); 810 HANDLE hThread = GetCurrentThread(); 811 PrintStackTraceForThread(llvm::errs(), hProcess, hThread, StackFrame, 812 ep->ContextRecord); 813 814 _exit(ep->ExceptionRecord->ExceptionCode); 815} 816 817static BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType) { 818 // We are running in our very own thread, courtesy of Windows. 819 EnterCriticalSection(&CriticalSection); 820 Cleanup(); 821 822 // If an interrupt function has been set, go and run one it; otherwise, 823 // the process dies. 824 void (*IF)() = InterruptFunction; 825 InterruptFunction = 0; // Don't run it on another CTRL-C. 826 827 if (IF) { 828 // Note: if the interrupt function throws an exception, there is nothing 829 // to catch it in this thread so it will kill the process. 830 IF(); // Run it now. 831 LeaveCriticalSection(&CriticalSection); 832 return TRUE; // Don't kill the process. 833 } 834 835 // Allow normal processing to take place; i.e., the process dies. 836 LeaveCriticalSection(&CriticalSection); 837 return FALSE; 838} 839 840#if __MINGW32__ 841 // We turned these warnings off for this file so that MinGW-g++ doesn't 842 // complain about the ll format specifiers used. Now we are turning the 843 // warnings back on. If MinGW starts to support diagnostic stacks, we can 844 // replace this with a pop. 845 #pragma GCC diagnostic warning "-Wformat" 846 #pragma GCC diagnostic warning "-Wformat-extra-args" 847#endif 848