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