1*0b57cec5SDimitry Andric //===- PrettyStackTrace.cpp - Pretty Crash Handling -----------------------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric //
9*0b57cec5SDimitry Andric // This file defines some helpful functions for dealing with the possibility of
10*0b57cec5SDimitry Andric // Unix signals occurring while your program is running.
11*0b57cec5SDimitry Andric //
12*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
13*0b57cec5SDimitry Andric 
14*0b57cec5SDimitry Andric #include "llvm/Support/PrettyStackTrace.h"
15*0b57cec5SDimitry Andric #include "llvm-c/ErrorHandling.h"
16*0b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
17*0b57cec5SDimitry Andric #include "llvm/Config/config.h"
18*0b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
19*0b57cec5SDimitry Andric #include "llvm/Support/SaveAndRestore.h"
20*0b57cec5SDimitry Andric #include "llvm/Support/Signals.h"
21*0b57cec5SDimitry Andric #include "llvm/Support/Watchdog.h"
22*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
23*0b57cec5SDimitry Andric 
24*0b57cec5SDimitry Andric #include <atomic>
25*0b57cec5SDimitry Andric #include <cstdarg>
26*0b57cec5SDimitry Andric #include <cstdio>
27*0b57cec5SDimitry Andric #include <tuple>
28*0b57cec5SDimitry Andric 
29*0b57cec5SDimitry Andric #ifdef HAVE_CRASHREPORTERCLIENT_H
30*0b57cec5SDimitry Andric #include <CrashReporterClient.h>
31*0b57cec5SDimitry Andric #endif
32*0b57cec5SDimitry Andric 
33*0b57cec5SDimitry Andric using namespace llvm;
34*0b57cec5SDimitry Andric 
35*0b57cec5SDimitry Andric // If backtrace support is not enabled, compile out support for pretty stack
36*0b57cec5SDimitry Andric // traces.  This has the secondary effect of not requiring thread local storage
37*0b57cec5SDimitry Andric // when backtrace support is disabled.
38*0b57cec5SDimitry Andric #if ENABLE_BACKTRACES
39*0b57cec5SDimitry Andric 
40*0b57cec5SDimitry Andric // We need a thread local pointer to manage the stack of our stack trace
41*0b57cec5SDimitry Andric // objects, but we *really* cannot tolerate destructors running and do not want
42*0b57cec5SDimitry Andric // to pay any overhead of synchronizing. As a consequence, we use a raw
43*0b57cec5SDimitry Andric // thread-local variable.
44*0b57cec5SDimitry Andric static LLVM_THREAD_LOCAL PrettyStackTraceEntry *PrettyStackTraceHead = nullptr;
45*0b57cec5SDimitry Andric 
46*0b57cec5SDimitry Andric // The use of 'volatile' here is to ensure that any particular thread always
47*0b57cec5SDimitry Andric // reloads the value of the counter. The 'std::atomic' allows us to specify that
48*0b57cec5SDimitry Andric // this variable is accessed in an unsychronized way (it's not actually
49*0b57cec5SDimitry Andric // synchronizing). This does technically mean that the value may not appear to
50*0b57cec5SDimitry Andric // be the same across threads running simultaneously on different CPUs, but in
51*0b57cec5SDimitry Andric // practice the worst that will happen is that we won't print a stack trace when
52*0b57cec5SDimitry Andric // we could have.
53*0b57cec5SDimitry Andric //
54*0b57cec5SDimitry Andric // This is initialized to 1 because 0 is used as a sentinel for "not enabled on
55*0b57cec5SDimitry Andric // the current thread". If the user happens to overflow an 'unsigned' with
56*0b57cec5SDimitry Andric // SIGINFO requests, it's possible that some threads will stop responding to it,
57*0b57cec5SDimitry Andric // but the program won't crash.
58*0b57cec5SDimitry Andric static volatile std::atomic<unsigned> GlobalSigInfoGenerationCounter =
59*0b57cec5SDimitry Andric     ATOMIC_VAR_INIT(1);
60*0b57cec5SDimitry Andric static LLVM_THREAD_LOCAL unsigned ThreadLocalSigInfoGenerationCounter = 0;
61*0b57cec5SDimitry Andric 
62*0b57cec5SDimitry Andric namespace llvm {
63*0b57cec5SDimitry Andric PrettyStackTraceEntry *ReverseStackTrace(PrettyStackTraceEntry *Head) {
64*0b57cec5SDimitry Andric   PrettyStackTraceEntry *Prev = nullptr;
65*0b57cec5SDimitry Andric   while (Head)
66*0b57cec5SDimitry Andric     std::tie(Prev, Head, Head->NextEntry) =
67*0b57cec5SDimitry Andric         std::make_tuple(Head, Head->NextEntry, Prev);
68*0b57cec5SDimitry Andric   return Prev;
69*0b57cec5SDimitry Andric }
70*0b57cec5SDimitry Andric }
71*0b57cec5SDimitry Andric 
72*0b57cec5SDimitry Andric static void PrintStack(raw_ostream &OS) {
73*0b57cec5SDimitry Andric   // Print out the stack in reverse order. To avoid recursion (which is likely
74*0b57cec5SDimitry Andric   // to fail if we crashed due to stack overflow), we do an up-front pass to
75*0b57cec5SDimitry Andric   // reverse the stack, then print it, then reverse it again.
76*0b57cec5SDimitry Andric   unsigned ID = 0;
77*0b57cec5SDimitry Andric   SaveAndRestore<PrettyStackTraceEntry *> SavedStack{PrettyStackTraceHead,
78*0b57cec5SDimitry Andric                                                      nullptr};
79*0b57cec5SDimitry Andric   PrettyStackTraceEntry *ReversedStack = ReverseStackTrace(SavedStack.get());
80*0b57cec5SDimitry Andric   for (const PrettyStackTraceEntry *Entry = ReversedStack; Entry;
81*0b57cec5SDimitry Andric        Entry = Entry->getNextEntry()) {
82*0b57cec5SDimitry Andric     OS << ID++ << ".\t";
83*0b57cec5SDimitry Andric     sys::Watchdog W(5);
84*0b57cec5SDimitry Andric     Entry->print(OS);
85*0b57cec5SDimitry Andric   }
86*0b57cec5SDimitry Andric   llvm::ReverseStackTrace(ReversedStack);
87*0b57cec5SDimitry Andric }
88*0b57cec5SDimitry Andric 
89*0b57cec5SDimitry Andric /// Print the current stack trace to the specified stream.
90*0b57cec5SDimitry Andric ///
91*0b57cec5SDimitry Andric /// Marked NOINLINE so it can be called from debuggers.
92*0b57cec5SDimitry Andric LLVM_ATTRIBUTE_NOINLINE
93*0b57cec5SDimitry Andric static void PrintCurStackTrace(raw_ostream &OS) {
94*0b57cec5SDimitry Andric   // Don't print an empty trace.
95*0b57cec5SDimitry Andric   if (!PrettyStackTraceHead) return;
96*0b57cec5SDimitry Andric 
97*0b57cec5SDimitry Andric   // If there are pretty stack frames registered, walk and emit them.
98*0b57cec5SDimitry Andric   OS << "Stack dump:\n";
99*0b57cec5SDimitry Andric 
100*0b57cec5SDimitry Andric   PrintStack(OS);
101*0b57cec5SDimitry Andric   OS.flush();
102*0b57cec5SDimitry Andric }
103*0b57cec5SDimitry Andric 
104*0b57cec5SDimitry Andric // Integrate with crash reporter libraries.
105*0b57cec5SDimitry Andric #if defined (__APPLE__) && defined(HAVE_CRASHREPORTERCLIENT_H)
106*0b57cec5SDimitry Andric //  If any clients of llvm try to link to libCrashReporterClient.a themselves,
107*0b57cec5SDimitry Andric //  only one crash info struct will be used.
108*0b57cec5SDimitry Andric extern "C" {
109*0b57cec5SDimitry Andric CRASH_REPORTER_CLIENT_HIDDEN
110*0b57cec5SDimitry Andric struct crashreporter_annotations_t gCRAnnotations
111*0b57cec5SDimitry Andric         __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION)))
112*0b57cec5SDimitry Andric #if CRASHREPORTER_ANNOTATIONS_VERSION < 5
113*0b57cec5SDimitry Andric         = { CRASHREPORTER_ANNOTATIONS_VERSION, 0, 0, 0, 0, 0, 0 };
114*0b57cec5SDimitry Andric #else
115*0b57cec5SDimitry Andric         = { CRASHREPORTER_ANNOTATIONS_VERSION, 0, 0, 0, 0, 0, 0, 0 };
116*0b57cec5SDimitry Andric #endif
117*0b57cec5SDimitry Andric }
118*0b57cec5SDimitry Andric #elif defined(__APPLE__) && HAVE_CRASHREPORTER_INFO
119*0b57cec5SDimitry Andric extern "C" const char *__crashreporter_info__
120*0b57cec5SDimitry Andric     __attribute__((visibility("hidden"))) = 0;
121*0b57cec5SDimitry Andric asm(".desc ___crashreporter_info__, 0x10");
122*0b57cec5SDimitry Andric #endif
123*0b57cec5SDimitry Andric 
1248bcb0991SDimitry Andric static void setCrashLogMessage(const char *msg) LLVM_ATTRIBUTE_UNUSED;
1258bcb0991SDimitry Andric static void setCrashLogMessage(const char *msg) {
1268bcb0991SDimitry Andric #ifdef HAVE_CRASHREPORTERCLIENT_H
1278bcb0991SDimitry Andric   (void)CRSetCrashLogMessage(msg);
1288bcb0991SDimitry Andric #elif HAVE_CRASHREPORTER_INFO
1298bcb0991SDimitry Andric   __crashreporter_info__ = msg;
1308bcb0991SDimitry Andric #endif
1318bcb0991SDimitry Andric   // Don't reorder subsequent operations: whatever comes after might crash and
1328bcb0991SDimitry Andric   // we want the system crash handling to see the message we just set.
1338bcb0991SDimitry Andric   std::atomic_signal_fence(std::memory_order_seq_cst);
1348bcb0991SDimitry Andric }
1358bcb0991SDimitry Andric 
1368bcb0991SDimitry Andric #ifdef __APPLE__
1378bcb0991SDimitry Andric using CrashHandlerString = SmallString<2048>;
1388bcb0991SDimitry Andric using CrashHandlerStringStorage =
1398bcb0991SDimitry Andric     std::aligned_storage<sizeof(CrashHandlerString),
1408bcb0991SDimitry Andric                          alignof(CrashHandlerString)>::type;
1418bcb0991SDimitry Andric static CrashHandlerStringStorage crashHandlerStringStorage;
1428bcb0991SDimitry Andric #endif
1438bcb0991SDimitry Andric 
1448bcb0991SDimitry Andric /// This callback is run if a fatal signal is delivered to the process, it
1458bcb0991SDimitry Andric /// prints the pretty stack trace.
146*0b57cec5SDimitry Andric static void CrashHandler(void *) {
147*0b57cec5SDimitry Andric #ifndef __APPLE__
148*0b57cec5SDimitry Andric   // On non-apple systems, just emit the crash stack trace to stderr.
149*0b57cec5SDimitry Andric   PrintCurStackTrace(errs());
150*0b57cec5SDimitry Andric #else
1518bcb0991SDimitry Andric   // Emit the crash stack trace to a SmallString, put it where the system crash
1528bcb0991SDimitry Andric   // handling will find it, and also send it to stderr.
1538bcb0991SDimitry Andric   //
1548bcb0991SDimitry Andric   // The SmallString is fairly large in the hope that we don't allocate (we're
1558bcb0991SDimitry Andric   // handling a fatal signal, something is already pretty wrong, allocation
1568bcb0991SDimitry Andric   // might not work). Further, we don't use a magic static in case that's also
1578bcb0991SDimitry Andric   // borked. We leak any allocation that does occur because the program is about
1588bcb0991SDimitry Andric   // to die anyways. This is technically racy if we were handling two fatal
1598bcb0991SDimitry Andric   // signals, however if we're in that situation a race is the least of our
1608bcb0991SDimitry Andric   // worries.
1618bcb0991SDimitry Andric   auto &crashHandlerString =
1628bcb0991SDimitry Andric       *new (&crashHandlerStringStorage) CrashHandlerString;
1638bcb0991SDimitry Andric 
1648bcb0991SDimitry Andric   // If we crash while trying to print the stack trace, we still want the system
1658bcb0991SDimitry Andric   // crash handling to have some partial information. That'll work out as long
1668bcb0991SDimitry Andric   // as the SmallString doesn't allocate. If it does allocate then the system
1678bcb0991SDimitry Andric   // crash handling will see some garbage because the inline buffer now contains
1688bcb0991SDimitry Andric   // a pointer.
1698bcb0991SDimitry Andric   setCrashLogMessage(crashHandlerString.c_str());
1708bcb0991SDimitry Andric 
171*0b57cec5SDimitry Andric   {
1728bcb0991SDimitry Andric     raw_svector_ostream Stream(crashHandlerString);
173*0b57cec5SDimitry Andric     PrintCurStackTrace(Stream);
174*0b57cec5SDimitry Andric   }
175*0b57cec5SDimitry Andric 
1768bcb0991SDimitry Andric   if (!crashHandlerString.empty()) {
1778bcb0991SDimitry Andric     setCrashLogMessage(crashHandlerString.c_str());
1788bcb0991SDimitry Andric     errs() << crashHandlerString.str();
1798bcb0991SDimitry Andric   } else
1808bcb0991SDimitry Andric     setCrashLogMessage("No crash information.");
181*0b57cec5SDimitry Andric #endif
182*0b57cec5SDimitry Andric }
183*0b57cec5SDimitry Andric 
184*0b57cec5SDimitry Andric static void printForSigInfoIfNeeded() {
185*0b57cec5SDimitry Andric   unsigned CurrentSigInfoGeneration =
186*0b57cec5SDimitry Andric       GlobalSigInfoGenerationCounter.load(std::memory_order_relaxed);
187*0b57cec5SDimitry Andric   if (ThreadLocalSigInfoGenerationCounter == 0 ||
188*0b57cec5SDimitry Andric       ThreadLocalSigInfoGenerationCounter == CurrentSigInfoGeneration) {
189*0b57cec5SDimitry Andric     return;
190*0b57cec5SDimitry Andric   }
191*0b57cec5SDimitry Andric 
192*0b57cec5SDimitry Andric   PrintCurStackTrace(errs());
193*0b57cec5SDimitry Andric   ThreadLocalSigInfoGenerationCounter = CurrentSigInfoGeneration;
194*0b57cec5SDimitry Andric }
195*0b57cec5SDimitry Andric 
196*0b57cec5SDimitry Andric #endif // ENABLE_BACKTRACES
197*0b57cec5SDimitry Andric 
198*0b57cec5SDimitry Andric PrettyStackTraceEntry::PrettyStackTraceEntry() {
199*0b57cec5SDimitry Andric #if ENABLE_BACKTRACES
200*0b57cec5SDimitry Andric   // Handle SIGINFO first, because we haven't finished constructing yet.
201*0b57cec5SDimitry Andric   printForSigInfoIfNeeded();
202*0b57cec5SDimitry Andric   // Link ourselves.
203*0b57cec5SDimitry Andric   NextEntry = PrettyStackTraceHead;
204*0b57cec5SDimitry Andric   PrettyStackTraceHead = this;
205*0b57cec5SDimitry Andric #endif
206*0b57cec5SDimitry Andric }
207*0b57cec5SDimitry Andric 
208*0b57cec5SDimitry Andric PrettyStackTraceEntry::~PrettyStackTraceEntry() {
209*0b57cec5SDimitry Andric #if ENABLE_BACKTRACES
210*0b57cec5SDimitry Andric   assert(PrettyStackTraceHead == this &&
211*0b57cec5SDimitry Andric          "Pretty stack trace entry destruction is out of order");
212*0b57cec5SDimitry Andric   PrettyStackTraceHead = NextEntry;
213*0b57cec5SDimitry Andric   // Handle SIGINFO first, because we already started destructing.
214*0b57cec5SDimitry Andric   printForSigInfoIfNeeded();
215*0b57cec5SDimitry Andric #endif
216*0b57cec5SDimitry Andric }
217*0b57cec5SDimitry Andric 
218*0b57cec5SDimitry Andric void PrettyStackTraceString::print(raw_ostream &OS) const { OS << Str << "\n"; }
219*0b57cec5SDimitry Andric 
220*0b57cec5SDimitry Andric PrettyStackTraceFormat::PrettyStackTraceFormat(const char *Format, ...) {
221*0b57cec5SDimitry Andric   va_list AP;
222*0b57cec5SDimitry Andric   va_start(AP, Format);
223*0b57cec5SDimitry Andric   const int SizeOrError = vsnprintf(nullptr, 0, Format, AP);
224*0b57cec5SDimitry Andric   va_end(AP);
225*0b57cec5SDimitry Andric   if (SizeOrError < 0) {
226*0b57cec5SDimitry Andric     return;
227*0b57cec5SDimitry Andric   }
228*0b57cec5SDimitry Andric 
229*0b57cec5SDimitry Andric   const int Size = SizeOrError + 1; // '\0'
230*0b57cec5SDimitry Andric   Str.resize(Size);
231*0b57cec5SDimitry Andric   va_start(AP, Format);
232*0b57cec5SDimitry Andric   vsnprintf(Str.data(), Size, Format, AP);
233*0b57cec5SDimitry Andric   va_end(AP);
234*0b57cec5SDimitry Andric }
235*0b57cec5SDimitry Andric 
236*0b57cec5SDimitry Andric void PrettyStackTraceFormat::print(raw_ostream &OS) const { OS << Str << "\n"; }
237*0b57cec5SDimitry Andric 
238*0b57cec5SDimitry Andric void PrettyStackTraceProgram::print(raw_ostream &OS) const {
239*0b57cec5SDimitry Andric   OS << "Program arguments: ";
240*0b57cec5SDimitry Andric   // Print the argument list.
241*0b57cec5SDimitry Andric   for (unsigned i = 0, e = ArgC; i != e; ++i)
242*0b57cec5SDimitry Andric     OS << ArgV[i] << ' ';
243*0b57cec5SDimitry Andric   OS << '\n';
244*0b57cec5SDimitry Andric }
245*0b57cec5SDimitry Andric 
246*0b57cec5SDimitry Andric #if ENABLE_BACKTRACES
247*0b57cec5SDimitry Andric static bool RegisterCrashPrinter() {
248*0b57cec5SDimitry Andric   sys::AddSignalHandler(CrashHandler, nullptr);
249*0b57cec5SDimitry Andric   return false;
250*0b57cec5SDimitry Andric }
251*0b57cec5SDimitry Andric #endif
252*0b57cec5SDimitry Andric 
253*0b57cec5SDimitry Andric void llvm::EnablePrettyStackTrace() {
254*0b57cec5SDimitry Andric #if ENABLE_BACKTRACES
255*0b57cec5SDimitry Andric   // The first time this is called, we register the crash printer.
256*0b57cec5SDimitry Andric   static bool HandlerRegistered = RegisterCrashPrinter();
257*0b57cec5SDimitry Andric   (void)HandlerRegistered;
258*0b57cec5SDimitry Andric #endif
259*0b57cec5SDimitry Andric }
260*0b57cec5SDimitry Andric 
261*0b57cec5SDimitry Andric void llvm::EnablePrettyStackTraceOnSigInfoForThisThread(bool ShouldEnable) {
262*0b57cec5SDimitry Andric #if ENABLE_BACKTRACES
263*0b57cec5SDimitry Andric   if (!ShouldEnable) {
264*0b57cec5SDimitry Andric     ThreadLocalSigInfoGenerationCounter = 0;
265*0b57cec5SDimitry Andric     return;
266*0b57cec5SDimitry Andric   }
267*0b57cec5SDimitry Andric 
268*0b57cec5SDimitry Andric   // The first time this is called, we register the SIGINFO handler.
269*0b57cec5SDimitry Andric   static bool HandlerRegistered = []{
270*0b57cec5SDimitry Andric     sys::SetInfoSignalFunction([]{
271*0b57cec5SDimitry Andric       GlobalSigInfoGenerationCounter.fetch_add(1, std::memory_order_relaxed);
272*0b57cec5SDimitry Andric     });
273*0b57cec5SDimitry Andric     return false;
274*0b57cec5SDimitry Andric   }();
275*0b57cec5SDimitry Andric   (void)HandlerRegistered;
276*0b57cec5SDimitry Andric 
277*0b57cec5SDimitry Andric   // Next, enable it for the current thread.
278*0b57cec5SDimitry Andric   ThreadLocalSigInfoGenerationCounter =
279*0b57cec5SDimitry Andric       GlobalSigInfoGenerationCounter.load(std::memory_order_relaxed);
280*0b57cec5SDimitry Andric #endif
281*0b57cec5SDimitry Andric }
282*0b57cec5SDimitry Andric 
283*0b57cec5SDimitry Andric const void *llvm::SavePrettyStackState() {
284*0b57cec5SDimitry Andric #if ENABLE_BACKTRACES
285*0b57cec5SDimitry Andric   return PrettyStackTraceHead;
286*0b57cec5SDimitry Andric #else
287*0b57cec5SDimitry Andric   return nullptr;
288*0b57cec5SDimitry Andric #endif
289*0b57cec5SDimitry Andric }
290*0b57cec5SDimitry Andric 
291*0b57cec5SDimitry Andric void llvm::RestorePrettyStackState(const void *Top) {
292*0b57cec5SDimitry Andric #if ENABLE_BACKTRACES
293*0b57cec5SDimitry Andric   PrettyStackTraceHead =
294*0b57cec5SDimitry Andric       static_cast<PrettyStackTraceEntry *>(const_cast<void *>(Top));
295*0b57cec5SDimitry Andric #endif
296*0b57cec5SDimitry Andric }
297*0b57cec5SDimitry Andric 
298*0b57cec5SDimitry Andric void LLVMEnablePrettyStackTrace() {
299*0b57cec5SDimitry Andric   EnablePrettyStackTrace();
300*0b57cec5SDimitry Andric }
301