1//===- Win32/Signals.cpp - Win32 Signals Implementation ---------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file provides the Win32 specific implementation of the Signals class. 11// 12//===----------------------------------------------------------------------===// 13#include "llvm/Support/FileSystem.h" 14#include <algorithm> 15#include <signal.h> 16#include <stdio.h> 17 18#include "llvm/Support/Format.h" 19#include "llvm/Support/raw_ostream.h" 20 21// The Windows.h header must be after LLVM and standard headers. 22#include "WindowsSupport.h" 23 24#ifdef __MINGW32__ 25 #include <imagehlp.h> 26#else 27 #include <dbghelp.h> 28#endif 29#include <psapi.h> 30 31#ifdef _MSC_VER 32 #pragma comment(lib, "psapi.lib") 33#elif __MINGW32__ 34 #if (HAVE_LIBPSAPI != 1) 35 #error "libpsapi.a should be present" 36 #endif 37 // The version of g++ that comes with MinGW does *not* properly understand 38 // the ll format specifier for printf. However, MinGW passes the format 39 // specifiers on to the MSVCRT entirely, and the CRT understands the ll 40 // specifier. So these warnings are spurious in this case. Since we compile 41 // with -Wall, this will generate these warnings which should be ignored. So 42 // we will turn off the warnings for this just file. However, MinGW also does 43 // not support push and pop for diagnostics, so we have to manually turn it 44 // back on at the end of the file. 45 #pragma GCC diagnostic ignored "-Wformat" 46 #pragma GCC diagnostic ignored "-Wformat-extra-args" 47 48 #if !defined(__MINGW64_VERSION_MAJOR) 49 // MinGW.org does not have updated support for the 64-bit versions of the 50 // DebugHlp APIs. So we will have to load them manually. The structures and 51 // method signatures were pulled from DbgHelp.h in the Windows Platform SDK, 52 // and adjusted for brevity. 53 typedef struct _IMAGEHLP_LINE64 { 54 DWORD SizeOfStruct; 55 PVOID Key; 56 DWORD LineNumber; 57 PCHAR FileName; 58 DWORD64 Address; 59 } IMAGEHLP_LINE64, *PIMAGEHLP_LINE64; 60 61 typedef struct _IMAGEHLP_SYMBOL64 { 62 DWORD SizeOfStruct; 63 DWORD64 Address; 64 DWORD Size; 65 DWORD Flags; 66 DWORD MaxNameLength; 67 CHAR Name[1]; 68 } IMAGEHLP_SYMBOL64, *PIMAGEHLP_SYMBOL64; 69 70 typedef struct _tagADDRESS64 { 71 DWORD64 Offset; 72 WORD Segment; 73 ADDRESS_MODE Mode; 74 } ADDRESS64, *LPADDRESS64; 75 76 typedef struct _KDHELP64 { 77 DWORD64 Thread; 78 DWORD ThCallbackStack; 79 DWORD ThCallbackBStore; 80 DWORD NextCallback; 81 DWORD FramePointer; 82 DWORD64 KiCallUserMode; 83 DWORD64 KeUserCallbackDispatcher; 84 DWORD64 SystemRangeStart; 85 DWORD64 KiUserExceptionDispatcher; 86 DWORD64 StackBase; 87 DWORD64 StackLimit; 88 DWORD64 Reserved[5]; 89 } KDHELP64, *PKDHELP64; 90 91 typedef struct _tagSTACKFRAME64 { 92 ADDRESS64 AddrPC; 93 ADDRESS64 AddrReturn; 94 ADDRESS64 AddrFrame; 95 ADDRESS64 AddrStack; 96 ADDRESS64 AddrBStore; 97 PVOID FuncTableEntry; 98 DWORD64 Params[4]; 99 BOOL Far; 100 BOOL Virtual; 101 DWORD64 Reserved[3]; 102 KDHELP64 KdHelp; 103 } STACKFRAME64, *LPSTACKFRAME64; 104 #endif // !defined(__MINGW64_VERSION_MAJOR) 105#endif // __MINGW32__ 106 107typedef BOOL (__stdcall *PREAD_PROCESS_MEMORY_ROUTINE64)(HANDLE hProcess, 108 DWORD64 qwBaseAddress, PVOID lpBuffer, DWORD nSize, 109 LPDWORD lpNumberOfBytesRead); 110 111typedef PVOID (__stdcall *PFUNCTION_TABLE_ACCESS_ROUTINE64)( HANDLE ahProcess, 112 DWORD64 AddrBase); 113 114typedef DWORD64 (__stdcall *PGET_MODULE_BASE_ROUTINE64)(HANDLE hProcess, 115 DWORD64 Address); 116 117typedef DWORD64 (__stdcall *PTRANSLATE_ADDRESS_ROUTINE64)(HANDLE hProcess, 118 HANDLE hThread, LPADDRESS64 lpaddr); 119 120typedef BOOL (WINAPI *fpStackWalk64)(DWORD, HANDLE, HANDLE, LPSTACKFRAME64, 121 PVOID, PREAD_PROCESS_MEMORY_ROUTINE64, 122 PFUNCTION_TABLE_ACCESS_ROUTINE64, 123 PGET_MODULE_BASE_ROUTINE64, 124 PTRANSLATE_ADDRESS_ROUTINE64); 125static fpStackWalk64 fStackWalk64; 126 127typedef DWORD64 (WINAPI *fpSymGetModuleBase64)(HANDLE, DWORD64); 128static fpSymGetModuleBase64 fSymGetModuleBase64; 129 130typedef BOOL (WINAPI *fpSymGetSymFromAddr64)(HANDLE, DWORD64, 131 PDWORD64, PIMAGEHLP_SYMBOL64); 132static fpSymGetSymFromAddr64 fSymGetSymFromAddr64; 133 134typedef BOOL (WINAPI *fpSymGetLineFromAddr64)(HANDLE, DWORD64, 135 PDWORD, PIMAGEHLP_LINE64); 136static fpSymGetLineFromAddr64 fSymGetLineFromAddr64; 137 138typedef BOOL(WINAPI *fpSymGetModuleInfo64)(HANDLE hProcess, DWORD64 dwAddr, 139 PIMAGEHLP_MODULE64 ModuleInfo); 140static fpSymGetModuleInfo64 fSymGetModuleInfo64; 141 142typedef PVOID (WINAPI *fpSymFunctionTableAccess64)(HANDLE, DWORD64); 143static fpSymFunctionTableAccess64 fSymFunctionTableAccess64; 144 145typedef DWORD (WINAPI *fpSymSetOptions)(DWORD); 146static fpSymSetOptions fSymSetOptions; 147 148typedef BOOL (WINAPI *fpSymInitialize)(HANDLE, PCSTR, BOOL); 149static fpSymInitialize fSymInitialize; 150 151typedef BOOL (WINAPI *fpEnumerateLoadedModules)(HANDLE,PENUMLOADED_MODULES_CALLBACK64,PVOID); 152static fpEnumerateLoadedModules fEnumerateLoadedModules; 153 154static bool load64BitDebugHelp(void) { 155 HMODULE hLib = ::LoadLibraryW(L"Dbghelp.dll"); 156 if (hLib) { 157 fStackWalk64 = (fpStackWalk64) 158 ::GetProcAddress(hLib, "StackWalk64"); 159 fSymGetModuleBase64 = (fpSymGetModuleBase64) 160 ::GetProcAddress(hLib, "SymGetModuleBase64"); 161 fSymGetSymFromAddr64 = (fpSymGetSymFromAddr64) 162 ::GetProcAddress(hLib, "SymGetSymFromAddr64"); 163 fSymGetLineFromAddr64 = (fpSymGetLineFromAddr64) 164 ::GetProcAddress(hLib, "SymGetLineFromAddr64"); 165 fSymGetModuleInfo64 = (fpSymGetModuleInfo64) 166 ::GetProcAddress(hLib, "SymGetModuleInfo64"); 167 fSymFunctionTableAccess64 = (fpSymFunctionTableAccess64) 168 ::GetProcAddress(hLib, "SymFunctionTableAccess64"); 169 fSymSetOptions = (fpSymSetOptions)::GetProcAddress(hLib, "SymSetOptions"); 170 fSymInitialize = (fpSymInitialize)::GetProcAddress(hLib, "SymInitialize"); 171 fEnumerateLoadedModules = (fpEnumerateLoadedModules) 172 ::GetProcAddress(hLib, "EnumerateLoadedModules64"); 173 } 174 return fStackWalk64 && fSymInitialize && fSymSetOptions; 175} 176 177using namespace llvm; 178 179// Forward declare. 180static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep); 181static BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType); 182 183// InterruptFunction - The function to call if ctrl-c is pressed. 184static void (*InterruptFunction)() = 0; 185 186static std::vector<std::string> *FilesToRemove = NULL; 187static bool RegisteredUnhandledExceptionFilter = false; 188static bool CleanupExecuted = false; 189static PTOP_LEVEL_EXCEPTION_FILTER OldFilter = NULL; 190 191// Windows creates a new thread to execute the console handler when an event 192// (such as CTRL/C) occurs. This causes concurrency issues with the above 193// globals which this critical section addresses. 194static CRITICAL_SECTION CriticalSection; 195static bool CriticalSectionInitialized = false; 196 197enum { 198#if defined(_M_X64) 199 NativeMachineType = IMAGE_FILE_MACHINE_AMD64 200#else 201 NativeMachineType = IMAGE_FILE_MACHINE_I386 202#endif 203}; 204 205static bool printStackTraceWithLLVMSymbolizer(llvm::raw_ostream &OS, 206 HANDLE hProcess, HANDLE hThread, 207 STACKFRAME64 &StackFrameOrig, 208 CONTEXT *ContextOrig) { 209 // StackWalk64 modifies the incoming stack frame and context, so copy them. 210 STACKFRAME64 StackFrame = StackFrameOrig; 211 212 // Copy the register context so that we don't modify it while we unwind. We 213 // could use InitializeContext + CopyContext, but that's only required to get 214 // at AVX registers, which typically aren't needed by StackWalk64. Reduce the 215 // flag set to indicate that there's less data. 216 CONTEXT Context = *ContextOrig; 217 Context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER; 218 219 static void *StackTrace[256]; 220 size_t Depth = 0; 221 while (fStackWalk64(NativeMachineType, hProcess, hThread, &StackFrame, 222 &Context, 0, fSymFunctionTableAccess64, 223 fSymGetModuleBase64, 0)) { 224 if (StackFrame.AddrFrame.Offset == 0) 225 break; 226 StackTrace[Depth++] = (void *)(uintptr_t)StackFrame.AddrPC.Offset; 227 if (Depth >= array_lengthof(StackTrace)) 228 break; 229 } 230 231 return printSymbolizedStackTrace(&StackTrace[0], Depth, OS); 232} 233 234namespace { 235struct FindModuleData { 236 void **StackTrace; 237 int Depth; 238 const char **Modules; 239 intptr_t *Offsets; 240 StringSaver *StrPool; 241}; 242} 243 244static BOOL CALLBACK findModuleCallback(WIN32_ELMCB_PCSTR ModuleName, 245 DWORD64 ModuleBase, ULONG ModuleSize, 246 void *VoidData) { 247 FindModuleData *Data = (FindModuleData*)VoidData; 248 intptr_t Beg = ModuleBase; 249 intptr_t End = Beg + ModuleSize; 250 for (int I = 0; I < Data->Depth; I++) { 251 if (Data->Modules[I]) 252 continue; 253 intptr_t Addr = (intptr_t)Data->StackTrace[I]; 254 if (Beg <= Addr && Addr < End) { 255 Data->Modules[I] = Data->StrPool->save(ModuleName); 256 Data->Offsets[I] = Addr - Beg; 257 } 258 } 259 return TRUE; 260} 261 262static bool findModulesAndOffsets(void **StackTrace, int Depth, 263 const char **Modules, intptr_t *Offsets, 264 const char *MainExecutableName, 265 StringSaver &StrPool) { 266 if (!fEnumerateLoadedModules) 267 return false; 268 FindModuleData Data; 269 Data.StackTrace = StackTrace; 270 Data.Depth = Depth; 271 Data.Modules = Modules; 272 Data.Offsets = Offsets; 273 Data.StrPool = &StrPool; 274 fEnumerateLoadedModules(GetCurrentProcess(), findModuleCallback, &Data); 275 return true; 276} 277 278static void PrintStackTraceForThread(llvm::raw_ostream &OS, HANDLE hProcess, 279 HANDLE hThread, STACKFRAME64 &StackFrame, 280 CONTEXT *Context) { 281 // Initialize the symbol handler. 282 fSymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_LOAD_LINES); 283 fSymInitialize(hProcess, NULL, TRUE); 284 285 // Try llvm-symbolizer first. llvm-symbolizer knows how to deal with both PDBs 286 // and DWARF, so it should do a good job regardless of what debug info or 287 // linker is in use. 288 if (printStackTraceWithLLVMSymbolizer(OS, hProcess, hThread, StackFrame, 289 Context)) { 290 return; 291 } 292 293 while (true) { 294 if (!fStackWalk64(NativeMachineType, hProcess, hThread, &StackFrame, 295 Context, 0, fSymFunctionTableAccess64, 296 fSymGetModuleBase64, 0)) { 297 break; 298 } 299 300 if (StackFrame.AddrFrame.Offset == 0) 301 break; 302 303 using namespace llvm; 304 // Print the PC in hexadecimal. 305 DWORD64 PC = StackFrame.AddrPC.Offset; 306#if defined(_M_X64) 307 OS << format("0x%016llX", PC); 308#elif defined(_M_IX86) 309 OS << format("0x%08lX", static_cast<DWORD>(PC)); 310#endif 311 312// Print the parameters. Assume there are four. 313#if defined(_M_X64) 314 OS << format(" (0x%016llX 0x%016llX 0x%016llX 0x%016llX)", 315 StackFrame.Params[0], StackFrame.Params[1], StackFrame.Params[2], 316 StackFrame.Params[3]); 317#elif defined(_M_IX86) 318 OS << format(" (0x%08lX 0x%08lX 0x%08lX 0x%08lX)", 319 static_cast<DWORD>(StackFrame.Params[0]), 320 static_cast<DWORD>(StackFrame.Params[1]), 321 static_cast<DWORD>(StackFrame.Params[2]), 322 static_cast<DWORD>(StackFrame.Params[3])); 323#endif 324 // Verify the PC belongs to a module in this process. 325 if (!fSymGetModuleBase64(hProcess, PC)) { 326 OS << " <unknown module>\n"; 327 continue; 328 } 329 330 // Print the symbol name. 331 char buffer[512]; 332 IMAGEHLP_SYMBOL64 *symbol = reinterpret_cast<IMAGEHLP_SYMBOL64 *>(buffer); 333 memset(symbol, 0, sizeof(IMAGEHLP_SYMBOL64)); 334 symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); 335 symbol->MaxNameLength = 512 - sizeof(IMAGEHLP_SYMBOL64); 336 337 DWORD64 dwDisp; 338 if (!fSymGetSymFromAddr64(hProcess, PC, &dwDisp, symbol)) { 339 OS << '\n'; 340 continue; 341 } 342 343 buffer[511] = 0; 344 if (dwDisp > 0) 345 OS << format(", %s() + 0x%llX bytes(s)", (const char*)symbol->Name, 346 dwDisp); 347 else 348 OS << format(", %s", (const char*)symbol->Name); 349 350 // Print the source file and line number information. 351 IMAGEHLP_LINE64 line = {}; 352 DWORD dwLineDisp; 353 line.SizeOfStruct = sizeof(line); 354 if (fSymGetLineFromAddr64(hProcess, PC, &dwLineDisp, &line)) { 355 OS << format(", %s, line %lu", line.FileName, line.LineNumber); 356 if (dwLineDisp > 0) 357 OS << format(" + 0x%lX byte(s)", dwLineDisp); 358 } 359 360 OS << '\n'; 361 } 362} 363 364namespace llvm { 365 366//===----------------------------------------------------------------------===// 367//=== WARNING: Implementation here must contain only Win32 specific code 368//=== and must not be UNIX code 369//===----------------------------------------------------------------------===// 370 371#ifdef _MSC_VER 372/// AvoidMessageBoxHook - Emulates hitting "retry" from an "abort, retry, 373/// ignore" CRT debug report dialog. "retry" raises an exception which 374/// ultimately triggers our stack dumper. 375static LLVM_ATTRIBUTE_UNUSED int 376AvoidMessageBoxHook(int ReportType, char *Message, int *Return) { 377 // Set *Return to the retry code for the return value of _CrtDbgReport: 378 // http://msdn.microsoft.com/en-us/library/8hyw4sy7(v=vs.71).aspx 379 // This may also trigger just-in-time debugging via DebugBreak(). 380 if (Return) 381 *Return = 1; 382 // Don't call _CrtDbgReport. 383 return TRUE; 384} 385 386#endif 387 388extern "C" void HandleAbort(int Sig) { 389 if (Sig == SIGABRT) { 390 LLVM_BUILTIN_TRAP; 391 } 392} 393 394static void InitializeThreading() { 395 if (CriticalSectionInitialized) 396 return; 397 398 // Now's the time to create the critical section. This is the first time 399 // through here, and there's only one thread. 400 InitializeCriticalSection(&CriticalSection); 401 CriticalSectionInitialized = true; 402} 403 404static void RegisterHandler() { 405 // If we cannot load up the APIs (which would be unexpected as they should 406 // exist on every version of Windows we support), we will bail out since 407 // there would be nothing to report. 408 assert(load64BitDebugHelp() && "These APIs should always be available"); 409 410 if (RegisteredUnhandledExceptionFilter) { 411 EnterCriticalSection(&CriticalSection); 412 return; 413 } 414 415 InitializeThreading(); 416 417 // Enter it immediately. Now if someone hits CTRL/C, the console handler 418 // can't proceed until the globals are updated. 419 EnterCriticalSection(&CriticalSection); 420 421 RegisteredUnhandledExceptionFilter = true; 422 OldFilter = SetUnhandledExceptionFilter(LLVMUnhandledExceptionFilter); 423 SetConsoleCtrlHandler(LLVMConsoleCtrlHandler, TRUE); 424 425 // IMPORTANT NOTE: Caller must call LeaveCriticalSection(&CriticalSection) or 426 // else multi-threading problems will ensue. 427} 428 429// RemoveFileOnSignal - The public API 430bool sys::RemoveFileOnSignal(StringRef Filename, std::string* ErrMsg) { 431 RegisterHandler(); 432 433 if (CleanupExecuted) { 434 if (ErrMsg) 435 *ErrMsg = "Process terminating -- cannot register for removal"; 436 return true; 437 } 438 439 if (FilesToRemove == NULL) 440 FilesToRemove = new std::vector<std::string>; 441 442 FilesToRemove->push_back(Filename); 443 444 LeaveCriticalSection(&CriticalSection); 445 return false; 446} 447 448// DontRemoveFileOnSignal - The public API 449void sys::DontRemoveFileOnSignal(StringRef Filename) { 450 if (FilesToRemove == NULL) 451 return; 452 453 RegisterHandler(); 454 455 std::vector<std::string>::reverse_iterator I = 456 std::find(FilesToRemove->rbegin(), FilesToRemove->rend(), Filename); 457 if (I != FilesToRemove->rend()) 458 FilesToRemove->erase(I.base()-1); 459 460 LeaveCriticalSection(&CriticalSection); 461} 462 463void sys::DisableSystemDialogsOnCrash() { 464 // Crash to stack trace handler on abort. 465 signal(SIGABRT, HandleAbort); 466 467 // The following functions are not reliably accessible on MinGW. 468#ifdef _MSC_VER 469 // We're already handling writing a "something went wrong" message. 470 _set_abort_behavior(0, _WRITE_ABORT_MSG); 471 // Disable Dr. Watson. 472 _set_abort_behavior(0, _CALL_REPORTFAULT); 473 _CrtSetReportHook(AvoidMessageBoxHook); 474#endif 475 476 // Disable standard error dialog box. 477 SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | 478 SEM_NOOPENFILEERRORBOX); 479 _set_error_mode(_OUT_TO_STDERR); 480} 481 482/// PrintStackTraceOnErrorSignal - When an error signal (such as SIBABRT or 483/// SIGSEGV) is delivered to the process, print a stack trace and then exit. 484void sys::PrintStackTraceOnErrorSignal(bool DisableCrashReporting) { 485 DisableSystemDialogsOnCrash(); 486 RegisterHandler(); 487 LeaveCriticalSection(&CriticalSection); 488} 489} 490 491#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) 492// Provide a prototype for RtlCaptureContext, mingw32 from mingw.org is 493// missing it but mingw-w64 has it. 494extern "C" VOID WINAPI RtlCaptureContext(PCONTEXT ContextRecord); 495#endif 496 497void llvm::sys::PrintStackTrace(raw_ostream &OS) { 498 STACKFRAME64 StackFrame = {}; 499 CONTEXT Context = {}; 500 ::RtlCaptureContext(&Context); 501#if defined(_M_X64) 502 StackFrame.AddrPC.Offset = Context.Rip; 503 StackFrame.AddrStack.Offset = Context.Rsp; 504 StackFrame.AddrFrame.Offset = Context.Rbp; 505#else 506 StackFrame.AddrPC.Offset = Context.Eip; 507 StackFrame.AddrStack.Offset = Context.Esp; 508 StackFrame.AddrFrame.Offset = Context.Ebp; 509#endif 510 StackFrame.AddrPC.Mode = AddrModeFlat; 511 StackFrame.AddrStack.Mode = AddrModeFlat; 512 StackFrame.AddrFrame.Mode = AddrModeFlat; 513 PrintStackTraceForThread(OS, GetCurrentProcess(), GetCurrentThread(), 514 StackFrame, &Context); 515} 516 517 518void llvm::sys::SetInterruptFunction(void (*IF)()) { 519 RegisterHandler(); 520 InterruptFunction = IF; 521 LeaveCriticalSection(&CriticalSection); 522} 523 524 525/// AddSignalHandler - Add a function to be called when a signal is delivered 526/// to the process. The handler can have a cookie passed to it to identify 527/// what instance of the handler it is. 528void llvm::sys::AddSignalHandler(void (*FnPtr)(void *), void *Cookie) { 529 CallBacksToRun->push_back(std::make_pair(FnPtr, Cookie)); 530 RegisterHandler(); 531 LeaveCriticalSection(&CriticalSection); 532} 533 534static void Cleanup() { 535 if (CleanupExecuted) 536 return; 537 538 EnterCriticalSection(&CriticalSection); 539 540 // Prevent other thread from registering new files and directories for 541 // removal, should we be executing because of the console handler callback. 542 CleanupExecuted = true; 543 544 // FIXME: open files cannot be deleted. 545 if (FilesToRemove != NULL) 546 while (!FilesToRemove->empty()) { 547 llvm::sys::fs::remove(FilesToRemove->back()); 548 FilesToRemove->pop_back(); 549 } 550 llvm::sys::RunSignalHandlers(); 551 LeaveCriticalSection(&CriticalSection); 552} 553 554void llvm::sys::RunInterruptHandlers() { 555 // The interrupt handler may be called from an interrupt, but it may also be 556 // called manually (such as the case of report_fatal_error with no registered 557 // error handler). We must ensure that the critical section is properly 558 // initialized. 559 InitializeThreading(); 560 Cleanup(); 561} 562 563static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep) { 564 Cleanup(); 565 566 // Initialize the STACKFRAME structure. 567 STACKFRAME64 StackFrame = {}; 568 569#if defined(_M_X64) 570 StackFrame.AddrPC.Offset = ep->ContextRecord->Rip; 571 StackFrame.AddrPC.Mode = AddrModeFlat; 572 StackFrame.AddrStack.Offset = ep->ContextRecord->Rsp; 573 StackFrame.AddrStack.Mode = AddrModeFlat; 574 StackFrame.AddrFrame.Offset = ep->ContextRecord->Rbp; 575 StackFrame.AddrFrame.Mode = AddrModeFlat; 576#elif defined(_M_IX86) 577 StackFrame.AddrPC.Offset = ep->ContextRecord->Eip; 578 StackFrame.AddrPC.Mode = AddrModeFlat; 579 StackFrame.AddrStack.Offset = ep->ContextRecord->Esp; 580 StackFrame.AddrStack.Mode = AddrModeFlat; 581 StackFrame.AddrFrame.Offset = ep->ContextRecord->Ebp; 582 StackFrame.AddrFrame.Mode = AddrModeFlat; 583#endif 584 585 HANDLE hProcess = GetCurrentProcess(); 586 HANDLE hThread = GetCurrentThread(); 587 PrintStackTraceForThread(llvm::errs(), hProcess, hThread, StackFrame, 588 ep->ContextRecord); 589 590 _exit(ep->ExceptionRecord->ExceptionCode); 591} 592 593static BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType) { 594 // We are running in our very own thread, courtesy of Windows. 595 EnterCriticalSection(&CriticalSection); 596 Cleanup(); 597 598 // If an interrupt function has been set, go and run one it; otherwise, 599 // the process dies. 600 void (*IF)() = InterruptFunction; 601 InterruptFunction = 0; // Don't run it on another CTRL-C. 602 603 if (IF) { 604 // Note: if the interrupt function throws an exception, there is nothing 605 // to catch it in this thread so it will kill the process. 606 IF(); // Run it now. 607 LeaveCriticalSection(&CriticalSection); 608 return TRUE; // Don't kill the process. 609 } 610 611 // Allow normal processing to take place; i.e., the process dies. 612 LeaveCriticalSection(&CriticalSection); 613 return FALSE; 614} 615 616#if __MINGW32__ 617 // We turned these warnings off for this file so that MinGW-g++ doesn't 618 // complain about the ll format specifiers used. Now we are turning the 619 // warnings back on. If MinGW starts to support diagnostic stacks, we can 620 // replace this with a pop. 621 #pragma GCC diagnostic warning "-Wformat" 622 #pragma GCC diagnostic warning "-Wformat-extra-args" 623#endif 624