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