LLVM  8.0.0svn
Signals.inc
Go to the documentation of this file.
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 //===----------------------------------------------------------------------===//
15 #include "llvm/Support/Path.h"
16 #include "llvm/Support/Process.h"
18 #include <algorithm>
19 #include <io.h>
20 #include <signal.h>
21 #include <stdio.h>
22 
23 #include "llvm/Support/Format.h"
25 
26 // The Windows.h header must be after LLVM and standard headers.
27 #include "WindowsSupport.h"
28 
29 #ifdef __MINGW32__
30  #include <imagehlp.h>
31 #else
32  #include <crtdbg.h>
33  #include <dbghelp.h>
34 #endif
35 #include <psapi.h>
36 
37 #ifdef _MSC_VER
38  #pragma comment(lib, "psapi.lib")
39 #elif __MINGW32__
40  // The version of g++ that comes with MinGW does *not* properly understand
41  // the ll format specifier for printf. However, MinGW passes the format
42  // specifiers on to the MSVCRT entirely, and the CRT understands the ll
43  // specifier. So these warnings are spurious in this case. Since we compile
44  // with -Wall, this will generate these warnings which should be ignored. So
45  // we will turn off the warnings for this just file. However, MinGW also does
46  // not support push and pop for diagnostics, so we have to manually turn it
47  // back on at the end of the file.
48  #pragma GCC diagnostic ignored "-Wformat"
49  #pragma GCC diagnostic ignored "-Wformat-extra-args"
50 
51  #if !defined(__MINGW64_VERSION_MAJOR)
52  // MinGW.org does not have updated support for the 64-bit versions of the
53  // DebugHlp APIs. So we will have to load them manually. The structures and
54  // method signatures were pulled from DbgHelp.h in the Windows Platform SDK,
55  // and adjusted for brevity.
56  typedef struct _IMAGEHLP_LINE64 {
57  DWORD SizeOfStruct;
58  PVOID Key;
59  DWORD LineNumber;
60  PCHAR FileName;
61  DWORD64 Address;
62  } IMAGEHLP_LINE64, *PIMAGEHLP_LINE64;
63 
64  typedef struct _IMAGEHLP_SYMBOL64 {
65  DWORD SizeOfStruct;
66  DWORD64 Address;
67  DWORD Size;
68  DWORD Flags;
69  DWORD MaxNameLength;
70  CHAR Name[1];
71  } IMAGEHLP_SYMBOL64, *PIMAGEHLP_SYMBOL64;
72 
73  typedef struct _tagADDRESS64 {
74  DWORD64 Offset;
75  WORD Segment;
76  ADDRESS_MODE Mode;
77  } ADDRESS64, *LPADDRESS64;
78 
79  typedef struct _KDHELP64 {
80  DWORD64 Thread;
81  DWORD ThCallbackStack;
82  DWORD ThCallbackBStore;
83  DWORD NextCallback;
84  DWORD FramePointer;
85  DWORD64 KiCallUserMode;
86  DWORD64 KeUserCallbackDispatcher;
87  DWORD64 SystemRangeStart;
88  DWORD64 KiUserExceptionDispatcher;
89  DWORD64 StackBase;
90  DWORD64 StackLimit;
91  DWORD64 Reserved[5];
92  } KDHELP64, *PKDHELP64;
93 
94  typedef struct _tagSTACKFRAME64 {
95  ADDRESS64 AddrPC;
96  ADDRESS64 AddrReturn;
97  ADDRESS64 AddrFrame;
98  ADDRESS64 AddrStack;
99  ADDRESS64 AddrBStore;
100  PVOID FuncTableEntry;
101  DWORD64 Params[4];
102  BOOL Far;
103  BOOL Virtual;
104  DWORD64 Reserved[3];
105  KDHELP64 KdHelp;
106  } STACKFRAME64, *LPSTACKFRAME64;
107  #endif // !defined(__MINGW64_VERSION_MAJOR)
108 #endif // __MINGW32__
109 
110 typedef BOOL (__stdcall *PREAD_PROCESS_MEMORY_ROUTINE64)(HANDLE hProcess,
111  DWORD64 qwBaseAddress, PVOID lpBuffer, DWORD nSize,
112  LPDWORD lpNumberOfBytesRead);
113 
114 typedef PVOID (__stdcall *PFUNCTION_TABLE_ACCESS_ROUTINE64)( HANDLE ahProcess,
115  DWORD64 AddrBase);
116 
117 typedef DWORD64 (__stdcall *PGET_MODULE_BASE_ROUTINE64)(HANDLE hProcess,
118  DWORD64 Address);
119 
120 typedef DWORD64 (__stdcall *PTRANSLATE_ADDRESS_ROUTINE64)(HANDLE hProcess,
121  HANDLE hThread, LPADDRESS64 lpaddr);
122 
123 typedef BOOL(WINAPI *fpMiniDumpWriteDump)(HANDLE, DWORD, HANDLE, MINIDUMP_TYPE,
124  PMINIDUMP_EXCEPTION_INFORMATION,
125  PMINIDUMP_USER_STREAM_INFORMATION,
126  PMINIDUMP_CALLBACK_INFORMATION);
127 static fpMiniDumpWriteDump fMiniDumpWriteDump;
128 
129 typedef 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);
134 static fpStackWalk64 fStackWalk64;
135 
136 typedef DWORD64 (WINAPI *fpSymGetModuleBase64)(HANDLE, DWORD64);
137 static fpSymGetModuleBase64 fSymGetModuleBase64;
138 
139 typedef BOOL (WINAPI *fpSymGetSymFromAddr64)(HANDLE, DWORD64,
140  PDWORD64, PIMAGEHLP_SYMBOL64);
141 static fpSymGetSymFromAddr64 fSymGetSymFromAddr64;
142 
143 typedef BOOL (WINAPI *fpSymGetLineFromAddr64)(HANDLE, DWORD64,
144  PDWORD, PIMAGEHLP_LINE64);
145 static fpSymGetLineFromAddr64 fSymGetLineFromAddr64;
146 
147 typedef BOOL(WINAPI *fpSymGetModuleInfo64)(HANDLE hProcess, DWORD64 dwAddr,
148  PIMAGEHLP_MODULE64 ModuleInfo);
149 static fpSymGetModuleInfo64 fSymGetModuleInfo64;
150 
151 typedef PVOID (WINAPI *fpSymFunctionTableAccess64)(HANDLE, DWORD64);
152 static fpSymFunctionTableAccess64 fSymFunctionTableAccess64;
153 
154 typedef DWORD (WINAPI *fpSymSetOptions)(DWORD);
155 static fpSymSetOptions fSymSetOptions;
156 
157 typedef BOOL (WINAPI *fpSymInitialize)(HANDLE, PCSTR, BOOL);
158 static fpSymInitialize fSymInitialize;
159 
160 typedef BOOL (WINAPI *fpEnumerateLoadedModules)(HANDLE,PENUMLOADED_MODULES_CALLBACK64,PVOID);
161 static fpEnumerateLoadedModules fEnumerateLoadedModules;
162 
163 static 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 
188 using namespace llvm;
189 
190 // Forward declare.
191 static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep);
192 static BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType);
193 
194 // The function to call if ctrl-c is pressed.
195 static void (*InterruptFunction)() = 0;
196 
197 static std::vector<std::string> *FilesToRemove = NULL;
198 static bool RegisteredUnhandledExceptionFilter = false;
199 static bool CleanupExecuted = false;
200 static 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.
205 static CRITICAL_SECTION CriticalSection;
206 static bool CriticalSectionInitialized = false;
207 
208 static StringRef Argv0;
209 
210 enum {
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 
224 static 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 
253 namespace {
254 struct FindModuleData {
255  void **StackTrace;
256  int Depth;
257  const char **Modules;
258  intptr_t *Offsets;
259  StringSaver *StrPool;
260 };
261 }
262 
263 static 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 
281 static 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 
297 static 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 
383 namespace 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.
394 static LLVM_ATTRIBUTE_UNUSED int
395 AvoidMessageBoxHook(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 
407 extern "C" void HandleAbort(int Sig) {
408  if (Sig == SIGABRT) {
410  }
411 }
412 
413 static 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 
423 static 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
452 bool 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
471 void 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 
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.
507  bool DisableCrashReporting) {
508  ::Argv0 = Argv0;
509 
510  if (DisableCrashReporting || getenv("LLVM_DISABLE_CRASH_REPORT"))
511  Process::PreventCoreFiles();
512 
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.
522 extern "C" VOID WINAPI RtlCaptureContext(PCONTEXT ContextRecord);
523 #endif
524 
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 
554 void 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.
565  void *Cookie) {
566  insertSignalHandler(FnPtr, Cookie);
567  RegisterHandler();
568  LeaveCriticalSection(&CriticalSection);
569 }
570 
571 static 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  }
588  LeaveCriticalSection(&CriticalSection);
589 }
590 
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.
603 static 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.
617 static 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.
667 static 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.
706 static std::error_code WINAPI
707 WriteWindowsDumpFile(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 
785 static 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).
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 
841 static 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
std::error_code create_directories(const Twine &path, bool IgnoreExisting=true, perms Perms=owner_all|group_all)
Create all the non-existent directories in path.
Definition: Path.cpp:915
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
LLVMContext & Context
uint64_t Thread
Definition: Profile.cpp:49
SI Whole Quad Mode
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
std::error_code createUniqueFile(const Twine &Model, int &ResultFD, SmallVectorImpl< char > &ResultPath, unsigned Mode=all_read|all_write)
Create a uniquely named file.
Definition: Path.cpp:766
std::error_code remove(const Twine &path, bool IgnoreNonExisting=true)
Remove path.
void(*)(void *) SignalHandlerCallback
Definition: Signals.h:59
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:124
static bool AreCoreFilesPrevented()
true if PreventCoreFiles has been called, false otherwise.
Definition: Process.cpp:90
Offsets
Offsets in bytes from the start of the input buffer.
Definition: SIInstrInfo.h:954
void DisableSystemDialogsOnCrash()
Disable all system dialog boxes that appear when the process crashes.
static bool findModulesAndOffsets(void **StackTrace, int Depth, const char **Modules, intptr_t *Offsets, const char *MainExecutableName, StringSaver &StrPool)
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
auto reverse(ContainerTy &&C, typename std::enable_if< has_rbegin< ContainerTy >::value >::type *=nullptr) -> decltype(make_range(C.rbegin(), C.rend()))
Definition: STLExtras.h:251
Key
PAL metadata keys.
#define LLVM_BUILTIN_TRAP
LLVM_BUILTIN_UNREACHABLE - On compilers which support it, expands to an expression which states that ...
Definition: Compiler.h:288
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:26
std::string getMainExecutable(const char *argv0, void *MainExecAddr)
Return the path to the main executable, given the value of argv[0] from program startup and the addre...
void RunSignalHandlers()
Definition: Signals.cpp:59
void PrintStackTraceOnErrorSignal(StringRef Argv0, bool DisableCrashReporting=false)
When an error signal (such as SIGABRT or SIGSEGV) is delivered to the process, print a stack trace an...
* if(!EatIfPresent(lltok::kw_thread_local)) return false
ParseOptionalThreadLocal := /*empty.
void PrintStackTrace(raw_ostream &OS)
Print the stack trace using the given raw_ostream object.
void RunInterruptHandlers()
This function runs all the registered interrupt handlers, including the removal of files registered b...
std::error_code mapWindowsError(unsigned EV)
void DontRemoveFileOnSignal(StringRef Filename)
This function removes a file from the list of files to be removed on signal delivery.
static LLVM_ATTRIBUTE_USED bool printSymbolizedStackTrace(StringRef Argv0, void **StackTrace, int Depth, llvm::raw_ostream &OS)
Helper that launches llvm-symbolizer and symbolizes a backtrace.
Definition: Signals.cpp:105
auto find(R &&Range, const T &Val) -> decltype(adl_begin(Range))
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:1063
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:847
constexpr size_t array_lengthof(T(&)[N])
Find the length of an array.
Definition: STLExtras.h:900
bool RemoveFileOnSignal(StringRef Filename, std::string *ErrMsg=nullptr)
This function registers signal handlers to ensure that if a signal gets delivered that the named file...
Saves strings in the provided stable storage and returns a StringRef with a stable character pointer...
Definition: StringSaver.h:22
Provides a library for accessing information about this process and other processes on the operating ...
StringRef filename(StringRef path, Style style=Style::native)
Get filename.
Definition: Path.cpp:590
std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, int &ResultFD, SmallVectorImpl< char > &ResultPath)
Create a file in the system temporary directory.
Definition: Path.cpp:811
#define I(x, y, z)
Definition: MD5.cpp:58
uint32_t Size
Definition: Profile.cpp:47
void AddSignalHandler(SignalHandlerCallback FnPtr, void *Cookie)
Add a function to be called when an abort/kill signal is delivered to the process.
std::string str() const
Return the twine contents as a std::string.
Definition: Twine.cpp:18
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static void insertSignalHandler(sys::SignalHandlerCallback FnPtr, void *Cookie)
Definition: Signals.cpp:74
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:46
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
#define LLVM_ATTRIBUTE_UNUSED
Definition: Compiler.h:147
void SetInterruptFunction(void(*IF)())
This function registers a function to be called when the user "interrupts" the program (typically by ...