LLVM  9.0.0svn
PrettyStackTrace.cpp
Go to the documentation of this file.
1 //===- PrettyStackTrace.cpp - Pretty Crash Handling -----------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines some helpful functions for dealing with the possibility of
10 // Unix signals occurring while your program is running.
11 //
12 //===----------------------------------------------------------------------===//
13 
15 #include "llvm-c/ErrorHandling.h"
16 #include "llvm/ADT/SmallString.h"
17 #include "llvm/Config/config.h" // Get autoconf configuration settings
18 #include "llvm/Support/Compiler.h"
19 #include "llvm/Support/Signals.h"
20 #include "llvm/Support/Watchdog.h"
22 
23 #include <cstdarg>
24 #include <cstdio>
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 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 #if CRASHREPORTER_ANNOTATIONS_VERSION < 5
91  = { CRASHREPORTER_ANNOTATIONS_VERSION, 0, 0, 0, 0, 0, 0 };
92 #else
93  = { CRASHREPORTER_ANNOTATIONS_VERSION, 0, 0, 0, 0, 0, 0, 0 };
94 #endif
95 }
96 #elif defined(__APPLE__) && HAVE_CRASHREPORTER_INFO
97 extern "C" const char *__crashreporter_info__
98  __attribute__((visibility("hidden"))) = 0;
99 asm(".desc ___crashreporter_info__, 0x10");
100 #endif
101 
102 /// CrashHandler - This callback is run if a fatal signal is delivered to the
103 /// process, it prints the pretty stack trace.
104 static void CrashHandler(void *) {
105 #ifndef __APPLE__
106  // On non-apple systems, just emit the crash stack trace to stderr.
108 #else
109  // Otherwise, emit to a smallvector of chars, send *that* to stderr, but also
110  // put it into __crashreporter_info__.
111  SmallString<2048> TmpStr;
112  {
113  raw_svector_ostream Stream(TmpStr);
114  PrintCurStackTrace(Stream);
115  }
116 
117  if (!TmpStr.empty()) {
118 #ifdef HAVE_CRASHREPORTERCLIENT_H
119  // Cast to void to avoid warning.
120  (void)CRSetCrashLogMessage(TmpStr.c_str());
121 #elif HAVE_CRASHREPORTER_INFO
122  __crashreporter_info__ = strdup(TmpStr.c_str());
123 #endif
124  errs() << TmpStr.str();
125  }
126 
127 #endif
128 }
129 
130 #endif // ENABLE_BACKTRACES
131 
133 #if ENABLE_BACKTRACES
134  // Link ourselves.
135  NextEntry = PrettyStackTraceHead;
136  PrettyStackTraceHead = this;
137 #endif
138 }
139 
141 #if ENABLE_BACKTRACES
142  assert(PrettyStackTraceHead == this &&
143  "Pretty stack trace entry destruction is out of order");
144  PrettyStackTraceHead = NextEntry;
145 #endif
146 }
147 
148 void PrettyStackTraceString::print(raw_ostream &OS) const { OS << Str << "\n"; }
149 
151  va_list AP;
152  va_start(AP, Format);
153  const int SizeOrError = vsnprintf(nullptr, 0, Format, AP);
154  va_end(AP);
155  if (SizeOrError < 0) {
156  return;
157  }
158 
159  const int Size = SizeOrError + 1; // '\0'
160  Str.resize(Size);
161  va_start(AP, Format);
162  vsnprintf(Str.data(), Size, Format, AP);
163  va_end(AP);
164 }
165 
166 void PrettyStackTraceFormat::print(raw_ostream &OS) const { OS << Str << "\n"; }
167 
169  OS << "Program arguments: ";
170  // Print the argument list.
171  for (unsigned i = 0, e = ArgC; i != e; ++i)
172  OS << ArgV[i] << ' ';
173  OS << '\n';
174 }
175 
176 #if ENABLE_BACKTRACES
177 static bool RegisterCrashPrinter() {
179  return false;
180 }
181 #endif
182 
184 #if ENABLE_BACKTRACES
185  // The first time this is called, we register the crash printer.
186  static bool HandlerRegistered = RegisterCrashPrinter();
187  (void)HandlerRegistered;
188 #endif
189 }
190 
192 #if ENABLE_BACKTRACES
193  return PrettyStackTraceHead;
194 #else
195  return nullptr;
196 #endif
197 }
198 
199 void llvm::RestorePrettyStackState(const void *Top) {
200 #if ENABLE_BACKTRACES
202  static_cast<PrettyStackTraceEntry *>(const_cast<void *>(Top));
203 #endif
204 }
205 
208 }
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.
This class represents lattice values for constants.
Definition: AllocatorList.h:23
A raw_ostream that writes to an SmallVector or SmallString.
Definition: raw_ostream.h:509
This class provides an abstraction for a timeout around an operation that must complete in a given am...
Definition: Watchdog.h:25
void EnablePrettyStackTrace()
StringRef str() const
Explicit conversion to StringRef.
Definition: SmallString.h:266
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:25
#define LLVM_THREAD_LOCAL
LLVM_THREAD_LOCAL A thread-local storage specifier which can be used with globals, extern globals, and static globals.
Definition: Compiler.h:512
void print(raw_ostream &OS) const override
print - Emit information about this stack frame to OS.
void LLVMEnablePrettyStackTrace()
Enable LLVM&#39;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...
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.
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.
PrettyStackTraceEntry * ReverseStackTrace(PrettyStackTraceEntry *Head)
LLVM_NODISCARD bool empty() const
Definition: SmallVector.h:55
const char * c_str()
Definition: SmallString.h:269
uint32_t Size
Definition: Profile.cpp:46
void AddSignalHandler(SignalHandlerCallback FnPtr, void *Cookie)
Add a function to be called when an abort/kill signal is delivered to the process.
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:45