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