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