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