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