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