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 124*0b57cec5SDimitry Andric /// CrashHandler - This callback is run if a fatal signal is delivered to the 125*0b57cec5SDimitry Andric /// process, it prints the pretty stack trace. 126*0b57cec5SDimitry Andric static void CrashHandler(void *) { 127*0b57cec5SDimitry Andric #ifndef __APPLE__ 128*0b57cec5SDimitry Andric // On non-apple systems, just emit the crash stack trace to stderr. 129*0b57cec5SDimitry Andric PrintCurStackTrace(errs()); 130*0b57cec5SDimitry Andric #else 131*0b57cec5SDimitry Andric // Otherwise, emit to a smallvector of chars, send *that* to stderr, but also 132*0b57cec5SDimitry Andric // put it into __crashreporter_info__. 133*0b57cec5SDimitry Andric SmallString<2048> TmpStr; 134*0b57cec5SDimitry Andric { 135*0b57cec5SDimitry Andric raw_svector_ostream Stream(TmpStr); 136*0b57cec5SDimitry Andric PrintCurStackTrace(Stream); 137*0b57cec5SDimitry Andric } 138*0b57cec5SDimitry Andric 139*0b57cec5SDimitry Andric if (!TmpStr.empty()) { 140*0b57cec5SDimitry Andric #ifdef HAVE_CRASHREPORTERCLIENT_H 141*0b57cec5SDimitry Andric // Cast to void to avoid warning. 142*0b57cec5SDimitry Andric (void)CRSetCrashLogMessage(TmpStr.c_str()); 143*0b57cec5SDimitry Andric #elif HAVE_CRASHREPORTER_INFO 144*0b57cec5SDimitry Andric __crashreporter_info__ = strdup(TmpStr.c_str()); 145*0b57cec5SDimitry Andric #endif 146*0b57cec5SDimitry Andric errs() << TmpStr.str(); 147*0b57cec5SDimitry Andric } 148*0b57cec5SDimitry Andric 149*0b57cec5SDimitry Andric #endif 150*0b57cec5SDimitry Andric } 151*0b57cec5SDimitry Andric 152*0b57cec5SDimitry Andric static void printForSigInfoIfNeeded() { 153*0b57cec5SDimitry Andric unsigned CurrentSigInfoGeneration = 154*0b57cec5SDimitry Andric GlobalSigInfoGenerationCounter.load(std::memory_order_relaxed); 155*0b57cec5SDimitry Andric if (ThreadLocalSigInfoGenerationCounter == 0 || 156*0b57cec5SDimitry Andric ThreadLocalSigInfoGenerationCounter == CurrentSigInfoGeneration) { 157*0b57cec5SDimitry Andric return; 158*0b57cec5SDimitry Andric } 159*0b57cec5SDimitry Andric 160*0b57cec5SDimitry Andric PrintCurStackTrace(errs()); 161*0b57cec5SDimitry Andric ThreadLocalSigInfoGenerationCounter = CurrentSigInfoGeneration; 162*0b57cec5SDimitry Andric } 163*0b57cec5SDimitry Andric 164*0b57cec5SDimitry Andric #endif // ENABLE_BACKTRACES 165*0b57cec5SDimitry Andric 166*0b57cec5SDimitry Andric PrettyStackTraceEntry::PrettyStackTraceEntry() { 167*0b57cec5SDimitry Andric #if ENABLE_BACKTRACES 168*0b57cec5SDimitry Andric // Handle SIGINFO first, because we haven't finished constructing yet. 169*0b57cec5SDimitry Andric printForSigInfoIfNeeded(); 170*0b57cec5SDimitry Andric // Link ourselves. 171*0b57cec5SDimitry Andric NextEntry = PrettyStackTraceHead; 172*0b57cec5SDimitry Andric PrettyStackTraceHead = this; 173*0b57cec5SDimitry Andric #endif 174*0b57cec5SDimitry Andric } 175*0b57cec5SDimitry Andric 176*0b57cec5SDimitry Andric PrettyStackTraceEntry::~PrettyStackTraceEntry() { 177*0b57cec5SDimitry Andric #if ENABLE_BACKTRACES 178*0b57cec5SDimitry Andric assert(PrettyStackTraceHead == this && 179*0b57cec5SDimitry Andric "Pretty stack trace entry destruction is out of order"); 180*0b57cec5SDimitry Andric PrettyStackTraceHead = NextEntry; 181*0b57cec5SDimitry Andric // Handle SIGINFO first, because we already started destructing. 182*0b57cec5SDimitry Andric printForSigInfoIfNeeded(); 183*0b57cec5SDimitry Andric #endif 184*0b57cec5SDimitry Andric } 185*0b57cec5SDimitry Andric 186*0b57cec5SDimitry Andric void PrettyStackTraceString::print(raw_ostream &OS) const { OS << Str << "\n"; } 187*0b57cec5SDimitry Andric 188*0b57cec5SDimitry Andric PrettyStackTraceFormat::PrettyStackTraceFormat(const char *Format, ...) { 189*0b57cec5SDimitry Andric va_list AP; 190*0b57cec5SDimitry Andric va_start(AP, Format); 191*0b57cec5SDimitry Andric const int SizeOrError = vsnprintf(nullptr, 0, Format, AP); 192*0b57cec5SDimitry Andric va_end(AP); 193*0b57cec5SDimitry Andric if (SizeOrError < 0) { 194*0b57cec5SDimitry Andric return; 195*0b57cec5SDimitry Andric } 196*0b57cec5SDimitry Andric 197*0b57cec5SDimitry Andric const int Size = SizeOrError + 1; // '\0' 198*0b57cec5SDimitry Andric Str.resize(Size); 199*0b57cec5SDimitry Andric va_start(AP, Format); 200*0b57cec5SDimitry Andric vsnprintf(Str.data(), Size, Format, AP); 201*0b57cec5SDimitry Andric va_end(AP); 202*0b57cec5SDimitry Andric } 203*0b57cec5SDimitry Andric 204*0b57cec5SDimitry Andric void PrettyStackTraceFormat::print(raw_ostream &OS) const { OS << Str << "\n"; } 205*0b57cec5SDimitry Andric 206*0b57cec5SDimitry Andric void PrettyStackTraceProgram::print(raw_ostream &OS) const { 207*0b57cec5SDimitry Andric OS << "Program arguments: "; 208*0b57cec5SDimitry Andric // Print the argument list. 209*0b57cec5SDimitry Andric for (unsigned i = 0, e = ArgC; i != e; ++i) 210*0b57cec5SDimitry Andric OS << ArgV[i] << ' '; 211*0b57cec5SDimitry Andric OS << '\n'; 212*0b57cec5SDimitry Andric } 213*0b57cec5SDimitry Andric 214*0b57cec5SDimitry Andric #if ENABLE_BACKTRACES 215*0b57cec5SDimitry Andric static bool RegisterCrashPrinter() { 216*0b57cec5SDimitry Andric sys::AddSignalHandler(CrashHandler, nullptr); 217*0b57cec5SDimitry Andric return false; 218*0b57cec5SDimitry Andric } 219*0b57cec5SDimitry Andric #endif 220*0b57cec5SDimitry Andric 221*0b57cec5SDimitry Andric void llvm::EnablePrettyStackTrace() { 222*0b57cec5SDimitry Andric #if ENABLE_BACKTRACES 223*0b57cec5SDimitry Andric // The first time this is called, we register the crash printer. 224*0b57cec5SDimitry Andric static bool HandlerRegistered = RegisterCrashPrinter(); 225*0b57cec5SDimitry Andric (void)HandlerRegistered; 226*0b57cec5SDimitry Andric #endif 227*0b57cec5SDimitry Andric } 228*0b57cec5SDimitry Andric 229*0b57cec5SDimitry Andric void llvm::EnablePrettyStackTraceOnSigInfoForThisThread(bool ShouldEnable) { 230*0b57cec5SDimitry Andric #if ENABLE_BACKTRACES 231*0b57cec5SDimitry Andric if (!ShouldEnable) { 232*0b57cec5SDimitry Andric ThreadLocalSigInfoGenerationCounter = 0; 233*0b57cec5SDimitry Andric return; 234*0b57cec5SDimitry Andric } 235*0b57cec5SDimitry Andric 236*0b57cec5SDimitry Andric // The first time this is called, we register the SIGINFO handler. 237*0b57cec5SDimitry Andric static bool HandlerRegistered = []{ 238*0b57cec5SDimitry Andric sys::SetInfoSignalFunction([]{ 239*0b57cec5SDimitry Andric GlobalSigInfoGenerationCounter.fetch_add(1, std::memory_order_relaxed); 240*0b57cec5SDimitry Andric }); 241*0b57cec5SDimitry Andric return false; 242*0b57cec5SDimitry Andric }(); 243*0b57cec5SDimitry Andric (void)HandlerRegistered; 244*0b57cec5SDimitry Andric 245*0b57cec5SDimitry Andric // Next, enable it for the current thread. 246*0b57cec5SDimitry Andric ThreadLocalSigInfoGenerationCounter = 247*0b57cec5SDimitry Andric GlobalSigInfoGenerationCounter.load(std::memory_order_relaxed); 248*0b57cec5SDimitry Andric #endif 249*0b57cec5SDimitry Andric } 250*0b57cec5SDimitry Andric 251*0b57cec5SDimitry Andric const void *llvm::SavePrettyStackState() { 252*0b57cec5SDimitry Andric #if ENABLE_BACKTRACES 253*0b57cec5SDimitry Andric return PrettyStackTraceHead; 254*0b57cec5SDimitry Andric #else 255*0b57cec5SDimitry Andric return nullptr; 256*0b57cec5SDimitry Andric #endif 257*0b57cec5SDimitry Andric } 258*0b57cec5SDimitry Andric 259*0b57cec5SDimitry Andric void llvm::RestorePrettyStackState(const void *Top) { 260*0b57cec5SDimitry Andric #if ENABLE_BACKTRACES 261*0b57cec5SDimitry Andric PrettyStackTraceHead = 262*0b57cec5SDimitry Andric static_cast<PrettyStackTraceEntry *>(const_cast<void *>(Top)); 263*0b57cec5SDimitry Andric #endif 264*0b57cec5SDimitry Andric } 265*0b57cec5SDimitry Andric 266*0b57cec5SDimitry Andric void LLVMEnablePrettyStackTrace() { 267*0b57cec5SDimitry Andric EnablePrettyStackTrace(); 268*0b57cec5SDimitry Andric } 269