LLVM  4.0.0
PrettyStackTrace.cpp
Go to the documentation of this file.
1 //===- PrettyStackTrace.cpp - Pretty Crash Handling -----------------------===//
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 defines some helpful functions for dealing with the possibility of
11 // Unix signals occurring while your program is running.
12 //
13 //===----------------------------------------------------------------------===//
14 
16 #include "llvm-c/ErrorHandling.h"
17 #include "llvm/ADT/SmallString.h"
18 #include "llvm/Config/config.h" // Get autoconf configuration settings
19 #include "llvm/Support/Compiler.h"
20 #include "llvm/Support/Signals.h"
21 #include "llvm/Support/Watchdog.h"
23 
24 #include <cstdarg>
25 #include <tuple>
26 
27 #ifdef HAVE_CRASHREPORTERCLIENT_H
28 #include <CrashReporterClient.h>
29 #endif
30 
31 using namespace llvm;
32 
33 // If backtrace support is not enabled, compile out support for pretty stack
34 // traces. This has the secondary effect of not requiring thread local storage
35 // when backtrace support is disabled.
36 #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES
37 
38 // We need a thread local pointer to manage the stack of our stack trace
39 // objects, but we *really* cannot tolerate destructors running and do not want
40 // to pay any overhead of synchronizing. As a consequence, we use a raw
41 // thread-local variable.
43 
44 namespace llvm {
46  PrettyStackTraceEntry *Prev = nullptr;
47  while (Head)
48  std::tie(Prev, Head, Head->NextEntry) =
49  std::make_tuple(Head, Head->NextEntry, Prev);
50  return Prev;
51 }
52 }
53 
54 static void PrintStack(raw_ostream &OS) {
55  // Print out the stack in reverse order. To avoid recursion (which is likely
56  // to fail if we crashed due to stack overflow), we do an up-front pass to
57  // reverse the stack, then print it, then reverse it again.
58  unsigned ID = 0;
59  PrettyStackTraceEntry *ReversedStack =
61  for (const PrettyStackTraceEntry *Entry = ReversedStack; Entry;
62  Entry = Entry->getNextEntry()) {
63  OS << ID++ << ".\t";
64  sys::Watchdog W(5);
65  Entry->print(OS);
66  }
67  llvm::ReverseStackTrace(ReversedStack);
68 }
69 
70 /// PrintCurStackTrace - Print the current stack trace to the specified stream.
71 static void PrintCurStackTrace(raw_ostream &OS) {
72  // Don't print an empty trace.
73  if (!PrettyStackTraceHead) return;
74 
75  // If there are pretty stack frames registered, walk and emit them.
76  OS << "Stack dump:\n";
77 
78  PrintStack(OS);
79  OS.flush();
80 }
81 
82 // Integrate with crash reporter libraries.
83 #if defined (__APPLE__) && defined(HAVE_CRASHREPORTERCLIENT_H)
84 // If any clients of llvm try to link to libCrashReporterClient.a themselves,
85 // only one crash info struct will be used.
86 extern "C" {
87 CRASH_REPORTER_CLIENT_HIDDEN
88 struct crashreporter_annotations_t gCRAnnotations
89  __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION)))
90  = { CRASHREPORTER_ANNOTATIONS_VERSION, 0, 0, 0, 0, 0, 0 };
91 }
92 #elif defined(__APPLE__) && HAVE_CRASHREPORTER_INFO
93 extern "C" const char *__crashreporter_info__
94  __attribute__((visibility("hidden"))) = 0;
95 asm(".desc ___crashreporter_info__, 0x10");
96 #endif
97 
98 /// CrashHandler - This callback is run if a fatal signal is delivered to the
99 /// process, it prints the pretty stack trace.
100 static void CrashHandler(void *) {
101 #ifndef __APPLE__
102  // On non-apple systems, just emit the crash stack trace to stderr.
104 #else
105  // Otherwise, emit to a smallvector of chars, send *that* to stderr, but also
106  // put it into __crashreporter_info__.
107  SmallString<2048> TmpStr;
108  {
109  raw_svector_ostream Stream(TmpStr);
110  PrintCurStackTrace(Stream);
111  }
112 
113  if (!TmpStr.empty()) {
114 #ifdef HAVE_CRASHREPORTERCLIENT_H
115  // Cast to void to avoid warning.
116  (void)CRSetCrashLogMessage(std::string(TmpStr.str()).c_str());
117 #elif HAVE_CRASHREPORTER_INFO
118  __crashreporter_info__ = strdup(std::string(TmpStr.str()).c_str());
119 #endif
120  errs() << TmpStr.str();
121  }
122 
123 #endif
124 }
125 
126 // defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES
127 #endif
128 
130 #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES
131  // Link ourselves.
132  NextEntry = PrettyStackTraceHead;
133  PrettyStackTraceHead = this;
134 #endif
135 }
136 
138 #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES
139  assert(PrettyStackTraceHead == this &&
140  "Pretty stack trace entry destruction is out of order");
141  PrettyStackTraceHead = NextEntry;
142 #endif
143 }
144 
145 void PrettyStackTraceString::print(raw_ostream &OS) const { OS << Str << "\n"; }
146 
148  va_list AP;
149  va_start(AP, Format);
150  const int SizeOrError = vsnprintf(nullptr, 0, Format, AP);
151  va_end(AP);
152  if (SizeOrError < 0) {
153  return;
154  }
155 
156  const int Size = SizeOrError + 1; // '\0'
157  Str.resize(Size);
158  va_start(AP, Format);
159  vsnprintf(Str.data(), Size, Format, AP);
160  va_end(AP);
161 }
162 
163 void PrettyStackTraceFormat::print(raw_ostream &OS) const { OS << Str << "\n"; }
164 
166  OS << "Program arguments: ";
167  // Print the argument list.
168  for (unsigned i = 0, e = ArgC; i != e; ++i)
169  OS << ArgV[i] << ' ';
170  OS << '\n';
171 }
172 
173 #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES
174 static bool RegisterCrashPrinter() {
176  return false;
177 }
178 #endif
179 
181 #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES
182  // The first time this is called, we register the crash printer.
183  static bool HandlerRegistered = RegisterCrashPrinter();
184  (void)HandlerRegistered;
185 #endif
186 }
187 
189 #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES
190  return PrettyStackTraceHead;
191 #else
192  return nullptr;
193 #endif
194 }
195 
196 void llvm::RestorePrettyStackState(const void *Top) {
197 #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES
199  static_cast<PrettyStackTraceEntry *>(const_cast<void *>(Top));
200 #endif
201 }
202 
205 }
void RestorePrettyStackState(const void *State)
Restores the topmost element of the "pretty" stack state to State, which should come from a previous ...
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
size_t i
A raw_ostream that writes to an SmallVector or SmallString.
Definition: raw_ostream.h:490
This class provides an abstraction for a timeout around an operation that must complete in a given am...
Definition: Watchdog.h:26
void EnablePrettyStackTrace()
const PrettyStackTraceEntry * getNextEntry() const
getNextEntry - Return the next entry in the list of frames.
__attribute__((weak)) int LLVMFuzzerInitialize(int *argc
LLVM_NODISCARD bool empty() const
Definition: SmallVector.h:60
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:26
#define LLVM_THREAD_LOCAL
LLVM_THREAD_LOCAL
Definition: Compiler.h:489
void print(raw_ostream &OS) const override
print - Emit information about this stack frame to OS.
void LLVMEnablePrettyStackTrace()
Enable LLVM's built-in stack trace code.
static void PrintCurStackTrace(raw_ostream &OS)
PrintCurStackTrace - Print the current stack trace to the specified stream.
PrettyStackTraceEntry - This class is used to represent a frame of the "pretty" stack trace that is d...
SmallVectorImpl< T >::const_pointer c_str(SmallVectorImpl< T > &str)
const void * SavePrettyStackState()
Returns the topmost element of the "pretty" stack state.
static void PrintStack(raw_ostream &OS)
PrettyStackTraceFormat(const char *Format,...)
static LLVM_THREAD_LOCAL PrettyStackTraceEntry * PrettyStackTraceHead
static bool RegisterCrashPrinter()
void print(raw_ostream &OS) const override
print - Emit information about this stack frame to OS.
StringRef str() const
Explicit conversion to StringRef.
Definition: SmallString.h:267
static void CrashHandler(void *)
CrashHandler - This callback is run if a fatal signal is delivered to the process, it prints the pretty stack trace.
void print(raw_ostream &OS) const override
print - Emit information about this stack frame to OS.
pointer data()
Return a pointer to the vector's buffer, even if empty().
Definition: SmallVector.h:142
PrettyStackTraceEntry * ReverseStackTrace(PrettyStackTraceEntry *Head)
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
void AddSignalHandler(void(*FnPtr)(void *), void *Cookie)
AddSignalHandler - Add a function to be called when an abort/kill signal is delivered to the process...
void resize(size_type N)
Definition: SmallVector.h:352