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