LLVM  16.0.0git
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/Config/config.h"
17 #include "llvm/Support/Compiler.h"
19 #include "llvm/Support/Signals.h"
20 #include "llvm/Support/Watchdog.h"
22 
23 #ifdef __APPLE__
24 #include "llvm/ADT/SmallString.h"
25 #endif
26 
27 #include <atomic>
28 #include <cassert>
29 #include <cstdarg>
30 #include <cstdio>
31 #include <cstring>
32 #include <tuple>
33 
34 #ifdef HAVE_CRASHREPORTERCLIENT_H
35 #include <CrashReporterClient.h>
36 #endif
37 
38 using namespace llvm;
39 
40 static const char *BugReportMsg =
41  "PLEASE submit a bug report to " BUG_REPORT_URL
42  " and include the crash backtrace.\n";
43 
44 // If backtrace support is not enabled, compile out support for pretty stack
45 // traces. This has the secondary effect of not requiring thread local storage
46 // when backtrace support is disabled.
47 #if ENABLE_BACKTRACES
48 
49 // We need a thread local pointer to manage the stack of our stack trace
50 // objects, but we *really* cannot tolerate destructors running and do not want
51 // to pay any overhead of synchronizing. As a consequence, we use a raw
52 // thread-local variable.
54 
55 // The use of 'volatile' here is to ensure that any particular thread always
56 // reloads the value of the counter. The 'std::atomic' allows us to specify that
57 // this variable is accessed in an unsychronized way (it's not actually
58 // synchronizing). This does technically mean that the value may not appear to
59 // be the same across threads running simultaneously on different CPUs, but in
60 // practice the worst that will happen is that we won't print a stack trace when
61 // we could have.
62 //
63 // This is initialized to 1 because 0 is used as a sentinel for "not enabled on
64 // the current thread". If the user happens to overflow an 'unsigned' with
65 // SIGINFO requests, it's possible that some threads will stop responding to it,
66 // but the program won't crash.
67 static volatile std::atomic<unsigned> GlobalSigInfoGenerationCounter =
68  ATOMIC_VAR_INIT(1);
70 
71 namespace llvm {
73  PrettyStackTraceEntry *Prev = nullptr;
74  while (Head)
75  std::tie(Prev, Head, Head->NextEntry) =
76  std::make_tuple(Head, Head->NextEntry, Prev);
77  return Prev;
78 }
79 } // namespace llvm
80 
81 static void PrintStack(raw_ostream &OS) {
82  // Print out the stack in reverse order. To avoid recursion (which is likely
83  // to fail if we crashed due to stack overflow), we do an up-front pass to
84  // reverse the stack, then print it, then reverse it again.
85  unsigned ID = 0;
87  nullptr};
88  PrettyStackTraceEntry *ReversedStack = ReverseStackTrace(SavedStack.get());
89  for (const PrettyStackTraceEntry *Entry = ReversedStack; Entry;
90  Entry = Entry->getNextEntry()) {
91  OS << ID++ << ".\t";
92  sys::Watchdog W(5);
93  Entry->print(OS);
94  }
95  llvm::ReverseStackTrace(ReversedStack);
96 }
97 
98 /// Print the current stack trace to the specified stream.
99 ///
100 /// Marked NOINLINE so it can be called from debuggers.
102 static void PrintCurStackTrace(raw_ostream &OS) {
103  // Don't print an empty trace.
104  if (!PrettyStackTraceHead) return;
105 
106  // If there are pretty stack frames registered, walk and emit them.
107  OS << "Stack dump:\n";
108 
109  PrintStack(OS);
110  OS.flush();
111 }
112 
113 // Integrate with crash reporter libraries.
114 #if defined (__APPLE__) && defined(HAVE_CRASHREPORTERCLIENT_H)
115 // If any clients of llvm try to link to libCrashReporterClient.a themselves,
116 // only one crash info struct will be used.
117 extern "C" {
118 CRASH_REPORTER_CLIENT_HIDDEN
119 struct crashreporter_annotations_t gCRAnnotations
120  __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION)))
121 #if CRASHREPORTER_ANNOTATIONS_VERSION < 5
122  = { CRASHREPORTER_ANNOTATIONS_VERSION, 0, 0, 0, 0, 0, 0 };
123 #else
124  = { CRASHREPORTER_ANNOTATIONS_VERSION, 0, 0, 0, 0, 0, 0, 0 };
125 #endif
126 }
127 #elif defined(__APPLE__) && HAVE_CRASHREPORTER_INFO
128 extern "C" const char *__crashreporter_info__
129  __attribute__((visibility("hidden"))) = 0;
130 asm(".desc ___crashreporter_info__, 0x10");
131 #endif
132 
133 static void setCrashLogMessage(const char *msg) LLVM_ATTRIBUTE_UNUSED;
134 static void setCrashLogMessage(const char *msg) {
135 #ifdef HAVE_CRASHREPORTERCLIENT_H
136  (void)CRSetCrashLogMessage(msg);
137 #elif HAVE_CRASHREPORTER_INFO
138  __crashreporter_info__ = msg;
139 #endif
140  // Don't reorder subsequent operations: whatever comes after might crash and
141  // we want the system crash handling to see the message we just set.
142  std::atomic_signal_fence(std::memory_order_seq_cst);
143 }
144 
145 #ifdef __APPLE__
146 using CrashHandlerString = SmallString<2048>;
147 using CrashHandlerStringStorage =
148  std::aligned_storage<sizeof(CrashHandlerString),
149  alignof(CrashHandlerString)>::type;
150 static CrashHandlerStringStorage crashHandlerStringStorage;
151 #endif
152 
153 /// This callback is run if a fatal signal is delivered to the process, it
154 /// prints the pretty stack trace.
155 static void CrashHandler(void *) {
156  errs() << BugReportMsg ;
157 
158 #ifndef __APPLE__
159  // On non-apple systems, just emit the crash stack trace to stderr.
161 #else
162  // Emit the crash stack trace to a SmallString, put it where the system crash
163  // handling will find it, and also send it to stderr.
164  //
165  // The SmallString is fairly large in the hope that we don't allocate (we're
166  // handling a fatal signal, something is already pretty wrong, allocation
167  // might not work). Further, we don't use a magic static in case that's also
168  // borked. We leak any allocation that does occur because the program is about
169  // to die anyways. This is technically racy if we were handling two fatal
170  // signals, however if we're in that situation a race is the least of our
171  // worries.
172  auto &crashHandlerString =
173  *new (&crashHandlerStringStorage) CrashHandlerString;
174 
175  // If we crash while trying to print the stack trace, we still want the system
176  // crash handling to have some partial information. That'll work out as long
177  // as the SmallString doesn't allocate. If it does allocate then the system
178  // crash handling will see some garbage because the inline buffer now contains
179  // a pointer.
180  setCrashLogMessage(crashHandlerString.c_str());
181 
182  {
183  raw_svector_ostream Stream(crashHandlerString);
184  PrintCurStackTrace(Stream);
185  }
186 
187  if (!crashHandlerString.empty()) {
188  setCrashLogMessage(crashHandlerString.c_str());
189  errs() << crashHandlerString.str();
190  } else
191  setCrashLogMessage("No crash information.");
192 #endif
193 }
194 
195 static void printForSigInfoIfNeeded() {
196  unsigned CurrentSigInfoGeneration =
197  GlobalSigInfoGenerationCounter.load(std::memory_order_relaxed);
199  ThreadLocalSigInfoGenerationCounter == CurrentSigInfoGeneration) {
200  return;
201  }
202 
204  ThreadLocalSigInfoGenerationCounter = CurrentSigInfoGeneration;
205 }
206 
207 #endif // ENABLE_BACKTRACES
208 
209 void llvm::setBugReportMsg(const char *Msg) {
210  BugReportMsg = Msg;
211 }
212 
213 const char *llvm::getBugReportMsg() {
214  return BugReportMsg;
215 }
216 
218 #if ENABLE_BACKTRACES
219  // Handle SIGINFO first, because we haven't finished constructing yet.
221  // Link ourselves.
222  NextEntry = PrettyStackTraceHead;
223  PrettyStackTraceHead = this;
224 #endif
225 }
226 
228 #if ENABLE_BACKTRACES
229  assert(PrettyStackTraceHead == this &&
230  "Pretty stack trace entry destruction is out of order");
231  PrettyStackTraceHead = NextEntry;
232  // Handle SIGINFO first, because we already started destructing.
234 #endif
235 }
236 
237 void PrettyStackTraceString::print(raw_ostream &OS) const { OS << Str << "\n"; }
238 
240  va_list AP;
241  va_start(AP, Format);
242  const int SizeOrError = vsnprintf(nullptr, 0, Format, AP);
243  va_end(AP);
244  if (SizeOrError < 0) {
245  return;
246  }
247 
248  const int Size = SizeOrError + 1; // '\0'
249  Str.resize(Size);
250  va_start(AP, Format);
251  vsnprintf(Str.data(), Size, Format, AP);
252  va_end(AP);
253 }
254 
255 void PrettyStackTraceFormat::print(raw_ostream &OS) const { OS << Str << "\n"; }
256 
258  OS << "Program arguments: ";
259  // Print the argument list.
260  for (int I = 0; I < ArgC; ++I) {
261  const bool HaveSpace = ::strchr(ArgV[I], ' ');
262  if (I)
263  OS << ' ';
264  if (HaveSpace)
265  OS << '"';
266  OS.write_escaped(ArgV[I]);
267  if (HaveSpace)
268  OS << '"';
269  }
270  OS << '\n';
271 }
272 
273 #if ENABLE_BACKTRACES
274 static bool RegisterCrashPrinter() {
276  return false;
277 }
278 #endif
279 
281 #if ENABLE_BACKTRACES
282  // The first time this is called, we register the crash printer.
283  static bool HandlerRegistered = RegisterCrashPrinter();
284  (void)HandlerRegistered;
285 #endif
286 }
287 
289 #if ENABLE_BACKTRACES
290  if (!ShouldEnable) {
292  return;
293  }
294 
295  // The first time this is called, we register the SIGINFO handler.
296  static bool HandlerRegistered = []{
298  GlobalSigInfoGenerationCounter.fetch_add(1, std::memory_order_relaxed);
299  });
300  return false;
301  }();
302  (void)HandlerRegistered;
303 
304  // Next, enable it for the current thread.
306  GlobalSigInfoGenerationCounter.load(std::memory_order_relaxed);
307 #endif
308 }
309 
311 #if ENABLE_BACKTRACES
312  return PrettyStackTraceHead;
313 #else
314  return nullptr;
315 #endif
316 }
317 
318 void llvm::RestorePrettyStackState(const void *Top) {
319 #if ENABLE_BACKTRACES
321  static_cast<PrettyStackTraceEntry *>(const_cast<void *>(Top));
322 #endif
323 }
324 
327 }
llvm::EnablePrettyStackTraceOnSigInfoForThisThread
void EnablePrettyStackTraceOnSigInfoForThisThread(bool ShouldEnable=true)
Enables (or disables) dumping a "pretty" stack trace when the user sends SIGINFO or SIGUSR1 to the cu...
Definition: PrettyStackTrace.cpp:288
Signals.h
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
BugReportMsg
static const char * BugReportMsg
Definition: PrettyStackTrace.cpp:40
LLVMEnablePrettyStackTrace
void LLVMEnablePrettyStackTrace()
Enable LLVM's built-in stack trace code.
Definition: PrettyStackTrace.cpp:325
llvm::RISCVFenceField::W
@ W
Definition: RISCVBaseInfo.h:266
llvm::raw_ostream::write_escaped
raw_ostream & write_escaped(StringRef Str, bool UseHexEscapes=false)
Output Str, turning '\', '\t', ' ', '"', and anything that doesn't satisfy llvm::isPrint into an esca...
Definition: raw_ostream.cpp:161
CrashHandler
static void CrashHandler(void *)
This callback is run if a fatal signal is delivered to the process, it prints the pretty stack trace.
Definition: PrettyStackTrace.cpp:155
llvm::errs
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
Definition: raw_ostream.cpp:891
Watchdog.h
LLVM_ATTRIBUTE_UNUSED
#define LLVM_ATTRIBUTE_UNUSED
Definition: Compiler.h:172
llvm::RestorePrettyStackState
void RestorePrettyStackState(const void *State)
Restores the topmost element of the "pretty" stack state to State, which should come from a previous ...
Definition: PrettyStackTrace.cpp:318
llvm::PrettyStackTraceEntry
PrettyStackTraceEntry - This class is used to represent a frame of the "pretty" stack trace that is d...
Definition: PrettyStackTrace.h:52
LLVM_THREAD_LOCAL
#define LLVM_THREAD_LOCAL
\macro LLVM_THREAD_LOCAL A thread-local storage specifier which can be used with globals,...
Definition: Compiler.h:527
SmallString.h
llvm::sys::SetInfoSignalFunction
void SetInfoSignalFunction(void(*Handler)())
Registers a function to be called when an "info" signal is delivered to the process.
llvm::PrettyStackTraceProgram::print
void print(raw_ostream &OS) const override
print - Emit information about this stack frame to OS.
Definition: PrettyStackTrace.cpp:257
llvm::ReverseStackTrace
PrettyStackTraceEntry * ReverseStackTrace(PrettyStackTraceEntry *Head)
Definition: PrettyStackTrace.cpp:72
llvm::PrettyStackTraceFormat::print
void print(raw_ostream &OS) const override
print - Emit information about this stack frame to OS.
Definition: PrettyStackTrace.cpp:255
PrintStack
static void PrintStack(raw_ostream &OS)
Definition: PrettyStackTrace.cpp:81
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
llvm::SmallVectorImpl::resize
void resize(size_type N)
Definition: SmallVector.h:624
llvm::raw_ostream::flush
void flush()
Definition: raw_ostream.h:185
GlobalSigInfoGenerationCounter
static volatile std::atomic< unsigned > GlobalSigInfoGenerationCounter
Definition: PrettyStackTrace.cpp:67
llvm::CallingConv::ID
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
llvm::SmallString
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:26
llvm::PrettyStackTraceEntry::~PrettyStackTraceEntry
virtual ~PrettyStackTraceEntry()
Definition: PrettyStackTrace.cpp:227
ThreadLocalSigInfoGenerationCounter
static LLVM_THREAD_LOCAL unsigned ThreadLocalSigInfoGenerationCounter
Definition: PrettyStackTrace.cpp:69
type
AMD64 Optimization Manual has some nice information about optimizing integer multiplication by a constant How much of it applies to Intel s X86 implementation There are definite trade offs to xmm0 cvttss2siq rdx jb L3 subss xmm0 rax cvttss2siq rdx xorq rdx rax ret instead of xmm1 cvttss2siq rcx movaps xmm2 subss xmm2 cvttss2siq rax rdx xorq rax ucomiss xmm0 cmovb rax ret Seems like the jb branch has high likelihood of being taken It would have saved a few instructions It s not possible to reference and DH registers in an instruction requiring REX prefix divb and mulb both produce results in AH If isel emits a CopyFromReg which gets turned into a movb and that can be allocated a r8b r15b To get around isel emits a CopyFromReg from AX and then right shift it down by and truncate it It s not pretty but it works We need some register allocation magic to make the hack go which would often require a callee saved register Callees usually need to keep this value live for most of their body so it doesn t add a significant burden on them We currently implement this in however this is suboptimal because it means that it would be quite awkward to implement the optimization for callers A better implementation would be to relax the LLVM IR rules for sret arguments to allow a function with an sret argument to have a non void return type
Definition: README-X86-64.txt:70
llvm::SavePrettyStackState
const void * SavePrettyStackState()
Returns the topmost element of the "pretty" stack state.
Definition: PrettyStackTrace.cpp:310
llvm::PrettyStackTraceString::print
void print(raw_ostream &OS) const override
print - Emit information about this stack frame to OS.
Definition: PrettyStackTrace.cpp:237
SaveAndRestore.h
__DATA
the multiplication has a latency of four as opposed to two cycles for the movl lea variant It appears gcc place string data with linkonce linkage in section coalesced instead of section __DATA
Definition: README.txt:260
PrettyStackTrace.h
I
#define I(x, y, z)
Definition: MD5.cpp:58
llvm::sys::AddSignalHandler
void AddSignalHandler(SignalHandlerCallback FnPtr, void *Cookie)
Add a function to be called when an abort/kill signal is delivered to the process.
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
RegisterCrashPrinter
static bool RegisterCrashPrinter()
Definition: PrettyStackTrace.cpp:274
if
if(llvm_vc STREQUAL "") set(fake_version_inc "$
Definition: CMakeLists.txt:14
Compiler.h
llvm::SaveAndRestore
A utility class that uses RAII to save and restore the value of a variable.
Definition: SaveAndRestore.h:21
setCrashLogMessage
static void setCrashLogMessage(const char *msg) LLVM_ATTRIBUTE_UNUSED
Definition: PrettyStackTrace.cpp:134
llvm::AMDGPU::SendMsg::Msg
const CustomOperand< const MCSubtargetInfo & > Msg[]
Definition: AMDGPUAsmUtils.cpp:39
llvm::setBugReportMsg
void setBugReportMsg(const char *Msg)
Replaces the generic bug report message that is output upon a crash.
Definition: PrettyStackTrace.cpp:209
ErrorHandling.h
PrintCurStackTrace
static LLVM_ATTRIBUTE_NOINLINE void PrintCurStackTrace(raw_ostream &OS)
Print the current stack trace to the specified stream.
Definition: PrettyStackTrace.cpp:102
llvm::getBugReportMsg
const char * getBugReportMsg()
Get the bug report message that will be output upon a crash.
Definition: PrettyStackTrace.cpp:213
LLVM_ATTRIBUTE_NOINLINE
#define LLVM_ATTRIBUTE_NOINLINE
LLVM_ATTRIBUTE_NOINLINE - On compilers where we have a directive to do so, mark a method "not for inl...
Definition: Compiler.h:220
printForSigInfoIfNeeded
static void printForSigInfoIfNeeded()
Definition: PrettyStackTrace.cpp:195
llvm::raw_svector_ostream
A raw_ostream that writes to an SmallVector or SmallString.
Definition: raw_ostream.h:658
llvm::sys::Watchdog
This class provides an abstraction for a timeout around an operation that must complete in a given am...
Definition: Watchdog.h:25
llvm::PrettyStackTraceEntry::PrettyStackTraceEntry
PrettyStackTraceEntry()
Definition: PrettyStackTrace.cpp:217
InlinePriorityMode::Size
@ Size
raw_ostream.h
PrettyStackTraceHead
static LLVM_THREAD_LOCAL PrettyStackTraceEntry * PrettyStackTraceHead
Definition: PrettyStackTrace.cpp:53
llvm::PrettyStackTraceFormat::PrettyStackTraceFormat
PrettyStackTraceFormat(const char *Format,...)
Definition: PrettyStackTrace.cpp:239
llvm::EnablePrettyStackTrace
void EnablePrettyStackTrace()
Enables dumping a "pretty" stack trace when the program crashes.
Definition: PrettyStackTrace.cpp:280
llvm::remarks::Format
Format
The format used for serializing/deserializing remarks.
Definition: RemarkFormat.h:25