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