1//===- Win32/Signals.cpp - Win32 Signals Implementation ---------*- C++ -*-===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8// 9// This file provides the Win32 specific implementation of the Signals class. 10// 11//===----------------------------------------------------------------------===// 12#include "llvm/Config/llvm-config.h" 13#include "llvm/Support/ConvertUTF.h" 14#include "llvm/Support/ExitCodes.h" 15#include "llvm/Support/FileSystem.h" 16#include "llvm/Support/Path.h" 17#include "llvm/Support/Process.h" 18#include "llvm/Support/WindowsError.h" 19#include <algorithm> 20#include <io.h> 21#include <signal.h> 22#include <stdio.h> 23 24#include "llvm/Support/Format.h" 25#include "llvm/Support/raw_ostream.h" 26 27// The Windows.h header must be after LLVM and standard headers. 28#include "llvm/Support/Windows/WindowsSupport.h" 29 30#ifdef __MINGW32__ 31#include <imagehlp.h> 32#else 33#include <crtdbg.h> 34#include <dbghelp.h> 35#endif 36#include <psapi.h> 37 38#ifdef _MSC_VER 39#pragma comment(lib, "psapi.lib") 40#elif __MINGW32__ 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#endif // __MINGW32__ 52 53typedef BOOL(__stdcall *PREAD_PROCESS_MEMORY_ROUTINE64)( 54 HANDLE hProcess, DWORD64 qwBaseAddress, PVOID lpBuffer, DWORD nSize, 55 LPDWORD lpNumberOfBytesRead); 56 57typedef PVOID(__stdcall *PFUNCTION_TABLE_ACCESS_ROUTINE64)(HANDLE ahProcess, 58 DWORD64 AddrBase); 59 60typedef DWORD64(__stdcall *PGET_MODULE_BASE_ROUTINE64)(HANDLE hProcess, 61 DWORD64 Address); 62 63typedef DWORD64(__stdcall *PTRANSLATE_ADDRESS_ROUTINE64)(HANDLE hProcess, 64 HANDLE hThread, 65 LPADDRESS64 lpaddr); 66 67typedef BOOL(WINAPI *fpMiniDumpWriteDump)(HANDLE, DWORD, HANDLE, MINIDUMP_TYPE, 68 PMINIDUMP_EXCEPTION_INFORMATION, 69 PMINIDUMP_USER_STREAM_INFORMATION, 70 PMINIDUMP_CALLBACK_INFORMATION); 71static fpMiniDumpWriteDump fMiniDumpWriteDump; 72 73typedef BOOL(WINAPI *fpStackWalk64)(DWORD, HANDLE, HANDLE, LPSTACKFRAME64, 74 PVOID, PREAD_PROCESS_MEMORY_ROUTINE64, 75 PFUNCTION_TABLE_ACCESS_ROUTINE64, 76 PGET_MODULE_BASE_ROUTINE64, 77 PTRANSLATE_ADDRESS_ROUTINE64); 78static fpStackWalk64 fStackWalk64; 79 80typedef DWORD64(WINAPI *fpSymGetModuleBase64)(HANDLE, DWORD64); 81static fpSymGetModuleBase64 fSymGetModuleBase64; 82 83typedef BOOL(WINAPI *fpSymGetSymFromAddr64)(HANDLE, DWORD64, PDWORD64, 84 PIMAGEHLP_SYMBOL64); 85static fpSymGetSymFromAddr64 fSymGetSymFromAddr64; 86 87typedef BOOL(WINAPI *fpSymGetLineFromAddr64)(HANDLE, DWORD64, PDWORD, 88 PIMAGEHLP_LINE64); 89static fpSymGetLineFromAddr64 fSymGetLineFromAddr64; 90 91typedef BOOL(WINAPI *fpSymGetModuleInfo64)(HANDLE hProcess, DWORD64 dwAddr, 92 PIMAGEHLP_MODULE64 ModuleInfo); 93static fpSymGetModuleInfo64 fSymGetModuleInfo64; 94 95typedef PVOID(WINAPI *fpSymFunctionTableAccess64)(HANDLE, DWORD64); 96static fpSymFunctionTableAccess64 fSymFunctionTableAccess64; 97 98typedef DWORD(WINAPI *fpSymSetOptions)(DWORD); 99static fpSymSetOptions fSymSetOptions; 100 101typedef BOOL(WINAPI *fpSymInitialize)(HANDLE, PCSTR, BOOL); 102static fpSymInitialize fSymInitialize; 103 104typedef BOOL(WINAPI *fpEnumerateLoadedModules)(HANDLE, 105 PENUMLOADED_MODULES_CALLBACK64, 106 PVOID); 107static fpEnumerateLoadedModules fEnumerateLoadedModules; 108 109static bool isDebugHelpInitialized() { 110 return fStackWalk64 && fSymInitialize && fSymSetOptions && fMiniDumpWriteDump; 111} 112 113static bool load64BitDebugHelp(void) { 114 HMODULE hLib = 115 ::LoadLibraryExA("Dbghelp.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); 116 if (hLib) { 117 fMiniDumpWriteDump = (fpMiniDumpWriteDump)(void *)::GetProcAddress( 118 hLib, "MiniDumpWriteDump"); 119 fStackWalk64 = (fpStackWalk64)(void *)::GetProcAddress(hLib, "StackWalk64"); 120 fSymGetModuleBase64 = (fpSymGetModuleBase64)(void *)::GetProcAddress( 121 hLib, "SymGetModuleBase64"); 122 fSymGetSymFromAddr64 = (fpSymGetSymFromAddr64)(void *)::GetProcAddress( 123 hLib, "SymGetSymFromAddr64"); 124 fSymGetLineFromAddr64 = (fpSymGetLineFromAddr64)(void *)::GetProcAddress( 125 hLib, "SymGetLineFromAddr64"); 126 fSymGetModuleInfo64 = (fpSymGetModuleInfo64)(void *)::GetProcAddress( 127 hLib, "SymGetModuleInfo64"); 128 fSymFunctionTableAccess64 = 129 (fpSymFunctionTableAccess64)(void *)::GetProcAddress( 130 hLib, "SymFunctionTableAccess64"); 131 fSymSetOptions = 132 (fpSymSetOptions)(void *)::GetProcAddress(hLib, "SymSetOptions"); 133 fSymInitialize = 134 (fpSymInitialize)(void *)::GetProcAddress(hLib, "SymInitialize"); 135 fEnumerateLoadedModules = 136 (fpEnumerateLoadedModules)(void *)::GetProcAddress( 137 hLib, "EnumerateLoadedModules64"); 138 } 139 return isDebugHelpInitialized(); 140} 141 142using namespace llvm; 143 144// Forward declare. 145static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep); 146static BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType); 147 148// The function to call if ctrl-c is pressed. 149static void (*InterruptFunction)() = 0; 150 151static std::vector<std::string> *FilesToRemove = NULL; 152static bool RegisteredUnhandledExceptionFilter = false; 153static bool CleanupExecuted = false; 154static PTOP_LEVEL_EXCEPTION_FILTER OldFilter = NULL; 155 156/// The function to call on "SIGPIPE" (one-time use only). 157static std::atomic<void (*)()> OneShotPipeSignalFunction(nullptr); 158 159// Windows creates a new thread to execute the console handler when an event 160// (such as CTRL/C) occurs. This causes concurrency issues with the above 161// globals which this critical section addresses. 162static CRITICAL_SECTION CriticalSection; 163static bool CriticalSectionInitialized = false; 164 165static StringRef Argv0; 166 167enum { 168#if defined(_M_X64) 169 NativeMachineType = IMAGE_FILE_MACHINE_AMD64 170#elif defined(_M_ARM64) 171 NativeMachineType = IMAGE_FILE_MACHINE_ARM64 172#elif defined(_M_IX86) 173 NativeMachineType = IMAGE_FILE_MACHINE_I386 174#elif defined(_M_ARM) 175 NativeMachineType = IMAGE_FILE_MACHINE_ARMNT 176#else 177 NativeMachineType = IMAGE_FILE_MACHINE_UNKNOWN 178#endif 179}; 180 181static bool printStackTraceWithLLVMSymbolizer(llvm::raw_ostream &OS, 182 HANDLE hProcess, HANDLE hThread, 183 STACKFRAME64 &StackFrameOrig, 184 CONTEXT *ContextOrig) { 185 // StackWalk64 modifies the incoming stack frame and context, so copy them. 186 STACKFRAME64 StackFrame = StackFrameOrig; 187 188 // Copy the register context so that we don't modify it while we unwind. We 189 // could use InitializeContext + CopyContext, but that's only required to get 190 // at AVX registers, which typically aren't needed by StackWalk64. Reduce the 191 // flag set to indicate that there's less data. 192 CONTEXT Context = *ContextOrig; 193 Context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER; 194 195 static void *StackTrace[256]; 196 size_t Depth = 0; 197 while (fStackWalk64(NativeMachineType, hProcess, hThread, &StackFrame, 198 &Context, 0, fSymFunctionTableAccess64, 199 fSymGetModuleBase64, 0)) { 200 if (StackFrame.AddrFrame.Offset == 0) 201 break; 202 StackTrace[Depth++] = (void *)(uintptr_t)StackFrame.AddrPC.Offset; 203 if (Depth >= std::size(StackTrace)) 204 break; 205 } 206 207 return printSymbolizedStackTrace(Argv0, &StackTrace[0], Depth, OS); 208} 209 210namespace { 211struct FindModuleData { 212 void **StackTrace; 213 int Depth; 214 const char **Modules; 215 intptr_t *Offsets; 216 StringSaver *StrPool; 217}; 218} // namespace 219 220static BOOL CALLBACK findModuleCallback(PCSTR ModuleName, DWORD64 ModuleBase, 221 ULONG ModuleSize, void *VoidData) { 222 FindModuleData *Data = (FindModuleData *)VoidData; 223 intptr_t Beg = ModuleBase; 224 intptr_t End = Beg + ModuleSize; 225 for (int I = 0; I < Data->Depth; I++) { 226 if (Data->Modules[I]) 227 continue; 228 intptr_t Addr = (intptr_t)Data->StackTrace[I]; 229 if (Beg <= Addr && Addr < End) { 230 Data->Modules[I] = Data->StrPool->save(ModuleName).data(); 231 Data->Offsets[I] = Addr - Beg; 232 } 233 } 234 return TRUE; 235} 236 237static bool findModulesAndOffsets(void **StackTrace, int Depth, 238 const char **Modules, intptr_t *Offsets, 239 const char *MainExecutableName, 240 StringSaver &StrPool) { 241 if (!fEnumerateLoadedModules) 242 return false; 243 FindModuleData Data; 244 Data.StackTrace = StackTrace; 245 Data.Depth = Depth; 246 Data.Modules = Modules; 247 Data.Offsets = Offsets; 248 Data.StrPool = &StrPool; 249 fEnumerateLoadedModules(GetCurrentProcess(), findModuleCallback, &Data); 250 return true; 251} 252 253static bool printMarkupContext(llvm::raw_ostream &OS, 254 const char *MainExecutableName) { 255 return false; 256} 257 258static void PrintStackTraceForThread(llvm::raw_ostream &OS, HANDLE hProcess, 259 HANDLE hThread, STACKFRAME64 &StackFrame, 260 CONTEXT *Context) { 261 // It's possible that DbgHelp.dll hasn't been loaded yet (e.g. if this 262 // function is called before the main program called `llvm::InitLLVM`). 263 // In this case just return, not stacktrace will be printed. 264 if (!isDebugHelpInitialized()) 265 return; 266 267 // Initialize the symbol handler. 268 fSymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES); 269 fSymInitialize(hProcess, NULL, TRUE); 270 271 // Try llvm-symbolizer first. llvm-symbolizer knows how to deal with both PDBs 272 // and DWARF, so it should do a good job regardless of what debug info or 273 // linker is in use. 274 if (printStackTraceWithLLVMSymbolizer(OS, hProcess, hThread, StackFrame, 275 Context)) { 276 return; 277 } 278 279 while (true) { 280 if (!fStackWalk64(NativeMachineType, hProcess, hThread, &StackFrame, 281 Context, 0, fSymFunctionTableAccess64, 282 fSymGetModuleBase64, 0)) { 283 break; 284 } 285 286 if (StackFrame.AddrFrame.Offset == 0) 287 break; 288 289 using namespace llvm; 290 // Print the PC in hexadecimal. 291 DWORD64 PC = StackFrame.AddrPC.Offset; 292#if defined(_M_X64) || defined(_M_ARM64) 293 OS << format("0x%016llX", PC); 294#elif defined(_M_IX86) || defined(_M_ARM) 295 OS << format("0x%08lX", static_cast<DWORD>(PC)); 296#endif 297 298 // Verify the PC belongs to a module in this process. 299 if (!fSymGetModuleBase64(hProcess, PC)) { 300 OS << " <unknown module>\n"; 301 continue; 302 } 303 304 IMAGEHLP_MODULE64 M; 305 memset(&M, 0, sizeof(IMAGEHLP_MODULE64)); 306 M.SizeOfStruct = sizeof(IMAGEHLP_MODULE64); 307 if (fSymGetModuleInfo64(hProcess, fSymGetModuleBase64(hProcess, PC), &M)) { 308 DWORD64 const disp = PC - M.BaseOfImage; 309 OS << format(", %s(0x%016llX) + 0x%llX byte(s)", 310 static_cast<char *>(M.ImageName), M.BaseOfImage, 311 static_cast<long long>(disp)); 312 } else { 313 OS << ", <unknown module>"; 314 } 315 316 // Print the symbol name. 317 char buffer[512]; 318 IMAGEHLP_SYMBOL64 *symbol = reinterpret_cast<IMAGEHLP_SYMBOL64 *>(buffer); 319 memset(symbol, 0, sizeof(IMAGEHLP_SYMBOL64)); 320 symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); 321 symbol->MaxNameLength = 512 - sizeof(IMAGEHLP_SYMBOL64); 322 323 DWORD64 dwDisp; 324 if (!fSymGetSymFromAddr64(hProcess, PC, &dwDisp, symbol)) { 325 OS << '\n'; 326 continue; 327 } 328 329 buffer[511] = 0; 330 OS << format(", %s() + 0x%llX byte(s)", static_cast<char *>(symbol->Name), 331 static_cast<long long>(dwDisp)); 332 333 // Print the source file and line number information. 334 IMAGEHLP_LINE64 line = {}; 335 DWORD dwLineDisp; 336 line.SizeOfStruct = sizeof(line); 337 if (fSymGetLineFromAddr64(hProcess, PC, &dwLineDisp, &line)) { 338 OS << format(", %s, line %lu + 0x%lX byte(s)", line.FileName, 339 line.LineNumber, dwLineDisp); 340 } 341 342 OS << '\n'; 343 } 344} 345 346namespace llvm { 347 348//===----------------------------------------------------------------------===// 349//=== WARNING: Implementation here must contain only Win32 specific code 350//=== and must not be UNIX code 351//===----------------------------------------------------------------------===// 352 353#ifdef _MSC_VER 354/// Emulates hitting "retry" from an "abort, retry, ignore" CRT debug report 355/// dialog. "retry" raises an exception which ultimately triggers our stack 356/// dumper. 357static LLVM_ATTRIBUTE_UNUSED int 358AvoidMessageBoxHook(int ReportType, char *Message, int *Return) { 359 // Set *Return to the retry code for the return value of _CrtDbgReport: 360 // http://msdn.microsoft.com/en-us/library/8hyw4sy7(v=vs.71).aspx 361 // This may also trigger just-in-time debugging via DebugBreak(). 362 if (Return) 363 *Return = 1; 364 // Don't call _CrtDbgReport. 365 return TRUE; 366} 367 368#endif 369 370extern "C" void HandleAbort(int Sig) { 371 if (Sig == SIGABRT) { 372 LLVM_BUILTIN_TRAP; 373 } 374} 375 376static void InitializeThreading() { 377 if (CriticalSectionInitialized) 378 return; 379 380 // Now's the time to create the critical section. This is the first time 381 // through here, and there's only one thread. 382 InitializeCriticalSection(&CriticalSection); 383 CriticalSectionInitialized = true; 384} 385 386static void RegisterHandler() { 387 // If we cannot load up the APIs (which would be unexpected as they should 388 // exist on every version of Windows we support), we will bail out since 389 // there would be nothing to report. 390 if (!load64BitDebugHelp()) { 391 assert(false && "These APIs should always be available"); 392 return; 393 } 394 395 if (RegisteredUnhandledExceptionFilter) { 396 EnterCriticalSection(&CriticalSection); 397 return; 398 } 399 400 InitializeThreading(); 401 402 // Enter it immediately. Now if someone hits CTRL/C, the console handler 403 // can't proceed until the globals are updated. 404 EnterCriticalSection(&CriticalSection); 405 406 RegisteredUnhandledExceptionFilter = true; 407 OldFilter = SetUnhandledExceptionFilter(LLVMUnhandledExceptionFilter); 408 SetConsoleCtrlHandler(LLVMConsoleCtrlHandler, TRUE); 409 410 // IMPORTANT NOTE: Caller must call LeaveCriticalSection(&CriticalSection) or 411 // else multi-threading problems will ensue. 412} 413 414// The public API 415bool sys::RemoveFileOnSignal(StringRef Filename, std::string *ErrMsg) { 416 RegisterHandler(); 417 418 if (CleanupExecuted) { 419 if (ErrMsg) 420 *ErrMsg = "Process terminating -- cannot register for removal"; 421 return true; 422 } 423 424 if (FilesToRemove == NULL) 425 FilesToRemove = new std::vector<std::string>; 426 427 FilesToRemove->push_back(std::string(Filename)); 428 429 LeaveCriticalSection(&CriticalSection); 430 return false; 431} 432 433// The public API 434void sys::DontRemoveFileOnSignal(StringRef Filename) { 435 if (FilesToRemove == NULL) 436 return; 437 438 RegisterHandler(); 439 440 std::vector<std::string>::reverse_iterator I = 441 find(reverse(*FilesToRemove), Filename); 442 if (I != FilesToRemove->rend()) 443 FilesToRemove->erase(I.base() - 1); 444 445 LeaveCriticalSection(&CriticalSection); 446} 447 448void sys::DisableSystemDialogsOnCrash() { 449 // Crash to stack trace handler on abort. 450 signal(SIGABRT, HandleAbort); 451 452 // The following functions are not reliably accessible on MinGW. 453#ifdef _MSC_VER 454 // We're already handling writing a "something went wrong" message. 455 _set_abort_behavior(0, _WRITE_ABORT_MSG); 456 // Disable Dr. Watson. 457 _set_abort_behavior(0, _CALL_REPORTFAULT); 458 _CrtSetReportHook(AvoidMessageBoxHook); 459#endif 460 461 // Disable standard error dialog box. 462 SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | 463 SEM_NOOPENFILEERRORBOX); 464 _set_error_mode(_OUT_TO_STDERR); 465} 466 467/// When an error signal (such as SIGABRT or SIGSEGV) is delivered to the 468/// process, print a stack trace and then exit. 469void sys::PrintStackTraceOnErrorSignal(StringRef Argv0, 470 bool DisableCrashReporting) { 471 ::Argv0 = Argv0; 472 473 if (DisableCrashReporting || getenv("LLVM_DISABLE_CRASH_REPORT")) 474 Process::PreventCoreFiles(); 475 476 DisableSystemDialogsOnCrash(); 477 RegisterHandler(); 478 LeaveCriticalSection(&CriticalSection); 479} 480} // namespace llvm 481 482#if LLVM_ENABLE_DEBUGLOC_TRACKING_ORIGIN 483#error DebugLoc origin-tracking currently unimplemented for Windows. 484#endif 485 486static void LocalPrintStackTrace(raw_ostream &OS, PCONTEXT C) { 487 STACKFRAME64 StackFrame{}; 488 CONTEXT Context{}; 489 if (!C) { 490 ::RtlCaptureContext(&Context); 491 C = &Context; 492 } 493#if defined(_M_X64) 494 StackFrame.AddrPC.Offset = Context.Rip; 495 StackFrame.AddrStack.Offset = Context.Rsp; 496 StackFrame.AddrFrame.Offset = Context.Rbp; 497#elif defined(_M_IX86) 498 StackFrame.AddrPC.Offset = Context.Eip; 499 StackFrame.AddrStack.Offset = Context.Esp; 500 StackFrame.AddrFrame.Offset = Context.Ebp; 501#elif defined(_M_ARM64) 502 StackFrame.AddrPC.Offset = Context.Pc; 503 StackFrame.AddrStack.Offset = Context.Sp; 504 StackFrame.AddrFrame.Offset = Context.Fp; 505#elif defined(_M_ARM) 506 StackFrame.AddrPC.Offset = Context.Pc; 507 StackFrame.AddrStack.Offset = Context.Sp; 508 StackFrame.AddrFrame.Offset = Context.R11; 509#endif 510 StackFrame.AddrPC.Mode = AddrModeFlat; 511 StackFrame.AddrStack.Mode = AddrModeFlat; 512 StackFrame.AddrFrame.Mode = AddrModeFlat; 513 PrintStackTraceForThread(OS, GetCurrentProcess(), GetCurrentThread(), 514 StackFrame, C); 515} 516 517void llvm::sys::PrintStackTrace(raw_ostream &OS, int Depth) { 518 // FIXME: Handle "Depth" parameter to print stack trace upto specified Depth 519 LocalPrintStackTrace(OS, nullptr); 520} 521 522void llvm::sys::SetInterruptFunction(void (*IF)()) { 523 RegisterHandler(); 524 InterruptFunction = IF; 525 LeaveCriticalSection(&CriticalSection); 526} 527 528void llvm::sys::SetInfoSignalFunction(void (*Handler)()) { 529 // Unimplemented. 530} 531 532void llvm::sys::SetOneShotPipeSignalFunction(void (*Handler)()) { 533 OneShotPipeSignalFunction.exchange(Handler); 534} 535 536void llvm::sys::DefaultOneShotPipeSignalHandler() { 537 llvm::sys::Process::Exit(EX_IOERR, /*NoCleanup=*/true); 538} 539 540void llvm::sys::CallOneShotPipeSignalHandler() { 541 if (auto OldOneShotPipeFunction = OneShotPipeSignalFunction.exchange(nullptr)) 542 OldOneShotPipeFunction(); 543} 544 545/// Add a function to be called when a signal is delivered to the process. The 546/// handler can have a cookie passed to it to identify what instance of the 547/// handler it is. 548void llvm::sys::AddSignalHandler(sys::SignalHandlerCallback FnPtr, 549 void *Cookie) { 550 insertSignalHandler(FnPtr, Cookie); 551 RegisterHandler(); 552 LeaveCriticalSection(&CriticalSection); 553} 554 555static void Cleanup(bool ExecuteSignalHandlers) { 556 if (CleanupExecuted) 557 return; 558 559 EnterCriticalSection(&CriticalSection); 560 561 // Prevent other thread from registering new files and directories for 562 // removal, should we be executing because of the console handler callback. 563 CleanupExecuted = true; 564 565 // FIXME: open files cannot be deleted. 566 if (FilesToRemove != NULL) 567 while (!FilesToRemove->empty()) { 568 llvm::sys::fs::remove(FilesToRemove->back()); 569 FilesToRemove->pop_back(); 570 } 571 572 if (ExecuteSignalHandlers) 573 llvm::sys::RunSignalHandlers(); 574 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(true); 585} 586 587/// 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/// 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/// 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, &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/// 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 struct ScopedCriticalSection { 695 ScopedCriticalSection() { EnterCriticalSection(&CriticalSection); } 696 ~ScopedCriticalSection() { LeaveCriticalSection(&CriticalSection); } 697 } SCS; 698 699 using namespace llvm; 700 using namespace llvm::sys; 701 702 std::string MainExecutableName = fs::getMainExecutable(nullptr, nullptr); 703 StringRef ProgramName; 704 705 if (MainExecutableName.empty()) { 706 // If we can't get the executable filename, 707 // things are in worse shape than we realize 708 // and we should just bail out. 709 return mapWindowsError(::GetLastError()); 710 } 711 712 ProgramName = path::filename(MainExecutableName.c_str()); 713 714 // The Windows Registry location as specified at 715 // https://msdn.microsoft.com/en-us/library/windows/desktop/bb787181%28v=vs.85%29.aspx 716 // "Collecting User-Mode Dumps" that may optionally be set to collect crash 717 // dumps in a specified location. 718 StringRef LocalDumpsRegistryLocation = 719 "SOFTWARE\\Microsoft\\Windows\\Windows Error Reporting\\LocalDumps"; 720 721 // The key pointing to the Registry location that may contain global crash 722 // dump settings. This will be NULL if the location can not be found. 723 ScopedRegHandle DefaultLocalDumpsKey(FindWERKey(LocalDumpsRegistryLocation)); 724 725 // The key pointing to the Registry location that may contain 726 // application-specific crash dump settings. This will be NULL if the 727 // location can not be found. 728 ScopedRegHandle AppSpecificKey( 729 FindWERKey(Twine(LocalDumpsRegistryLocation) + "\\" + ProgramName)); 730 731 // Look to see if a dump type is specified in the registry; first with the 732 // app-specific key and failing that with the global key. If none are found 733 // default to a normal dump (GetDumpType will return false either if the key 734 // is NULL or if there is no valid DumpType value at its location). 735 MINIDUMP_TYPE DumpType; 736 if (!GetDumpType(AppSpecificKey, DumpType)) 737 if (!GetDumpType(DefaultLocalDumpsKey, DumpType)) 738 DumpType = MiniDumpNormal; 739 740 // Look to see if a dump location is specified on the command line. If not, 741 // look to see if a dump location is specified in the registry; first with the 742 // app-specific key and failing that with the global key. If none are found 743 // we'll just create the dump file in the default temporary file location 744 // (GetDumpFolder will return false either if the key is NULL or if there is 745 // no valid DumpFolder value at its location). 746 bool ExplicitDumpDirectorySet = true; 747 SmallString<MAX_PATH> DumpDirectory(*CrashDiagnosticsDirectory); 748 if (DumpDirectory.empty()) 749 if (!GetDumpFolder(AppSpecificKey, DumpDirectory)) 750 if (!GetDumpFolder(DefaultLocalDumpsKey, DumpDirectory)) 751 ExplicitDumpDirectorySet = false; 752 753 int FD; 754 SmallString<MAX_PATH> DumpPath; 755 756 if (ExplicitDumpDirectorySet) { 757 if (std::error_code EC = fs::create_directories(DumpDirectory)) 758 return EC; 759 if (std::error_code EC = fs::createUniqueFile( 760 Twine(DumpDirectory) + "\\" + ProgramName + ".%%%%%%.dmp", FD, 761 DumpPath)) 762 return EC; 763 } else if (std::error_code EC = 764 fs::createTemporaryFile(ProgramName, "dmp", FD, DumpPath)) 765 return EC; 766 767 // Our support functions return a file descriptor but Windows wants a handle. 768 ScopedCommonHandle FileHandle(reinterpret_cast<HANDLE>(_get_osfhandle(FD))); 769 770 if (!fMiniDumpWriteDump(::GetCurrentProcess(), ::GetCurrentProcessId(), 771 FileHandle, DumpType, ExceptionInfo, NULL, NULL)) 772 return mapWindowsError(::GetLastError()); 773 774 llvm::errs() << "Wrote crash dump file \"" << DumpPath << "\"\n"; 775 return std::error_code(); 776} 777 778void sys::CleanupOnSignal(uintptr_t Context) { 779 LPEXCEPTION_POINTERS EP = (LPEXCEPTION_POINTERS)Context; 780 // Broken pipe is not a crash. 781 // 782 // 0xE0000000 is combined with the return code in the exception raised in 783 // CrashRecoveryContext::HandleExit(). 784 unsigned RetCode = EP->ExceptionRecord->ExceptionCode; 785 if (RetCode == (0xE0000000 | EX_IOERR)) 786 return; 787 LLVMUnhandledExceptionFilter(EP); 788} 789 790static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep) { 791 Cleanup(true); 792 793 // Write out the exception code. 794 if (ep && ep->ExceptionRecord) 795 llvm::errs() << format("Exception Code: 0x%08X", 796 ep->ExceptionRecord->ExceptionCode) 797 << "\n"; 798 799 // We'll automatically write a Minidump file here to help diagnose 800 // the nasty sorts of crashes that aren't 100% reproducible from a set of 801 // inputs (or in the event that the user is unable or unwilling to provide a 802 // reproducible case). 803 if (!llvm::sys::Process::AreCoreFilesPrevented()) { 804 MINIDUMP_EXCEPTION_INFORMATION ExceptionInfo; 805 ExceptionInfo.ThreadId = ::GetCurrentThreadId(); 806 ExceptionInfo.ExceptionPointers = ep; 807 ExceptionInfo.ClientPointers = FALSE; 808 809 if (std::error_code EC = WriteWindowsDumpFile(&ExceptionInfo)) 810 llvm::errs() << "Could not write crash dump file: " << EC.message() 811 << "\n"; 812 } 813 814 // Stack unwinding appears to modify the context. Copy it to preserve the 815 // caller's context. 816 CONTEXT ContextCopy; 817 if (ep) 818 memcpy(&ContextCopy, ep->ContextRecord, sizeof(ContextCopy)); 819 820 LocalPrintStackTrace(llvm::errs(), ep ? &ContextCopy : nullptr); 821 822 return EXCEPTION_EXECUTE_HANDLER; 823} 824 825static BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType) { 826 // We are running in our very own thread, courtesy of Windows. 827 EnterCriticalSection(&CriticalSection); 828 // This function is only ever called when a CTRL-C or similar control signal 829 // is fired. Killing a process in this way is normal, so don't trigger the 830 // signal handlers. 831 Cleanup(false); 832 833 // If an interrupt function has been set, go and run one it; otherwise, 834 // the process dies. 835 void (*IF)() = InterruptFunction; 836 InterruptFunction = 0; // Don't run it on another CTRL-C. 837 838 if (IF) { 839 // Note: if the interrupt function throws an exception, there is nothing 840 // to catch it in this thread so it will kill the process. 841 IF(); // Run it now. 842 LeaveCriticalSection(&CriticalSection); 843 return TRUE; // Don't kill the process. 844 } 845 846 // Allow normal processing to take place; i.e., the process dies. 847 LeaveCriticalSection(&CriticalSection); 848 return FALSE; 849} 850 851#if __MINGW32__ 852// We turned these warnings off for this file so that MinGW-g++ doesn't 853// complain about the ll format specifiers used. Now we are turning the 854// warnings back on. If MinGW starts to support diagnostic stacks, we can 855// replace this with a pop. 856#pragma GCC diagnostic warning "-Wformat" 857#pragma GCC diagnostic warning "-Wformat-extra-args" 858#endif 859 860void sys::unregisterHandlers() {} 861