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 15 #include "llvm/Support/PrettyStackTrace.h" 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" 22 #include "llvm/Support/raw_ostream.h" 23 24 #include <cstdarg> 25 #include <cstdio> 26 #include <tuple> 27 28 #ifdef HAVE_CRASHREPORTERCLIENT_H 29 #include <CrashReporterClient.h> 30 #endif 31 32 using namespace llvm; 33 34 // If backtrace support is not enabled, compile out support for pretty stack 35 // traces. This has the secondary effect of not requiring thread local storage 36 // when backtrace support is disabled. 37 #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES 38 39 // We need a thread local pointer to manage the stack of our stack trace 40 // objects, but we *really* cannot tolerate destructors running and do not want 41 // to pay any overhead of synchronizing. As a consequence, we use a raw 42 // thread-local variable. 43 static LLVM_THREAD_LOCAL PrettyStackTraceEntry *PrettyStackTraceHead = nullptr; 44 45 namespace llvm { 46 PrettyStackTraceEntry *ReverseStackTrace(PrettyStackTraceEntry *Head) { 47 PrettyStackTraceEntry *Prev = nullptr; 48 while (Head) 49 std::tie(Prev, Head, Head->NextEntry) = 50 std::make_tuple(Head, Head->NextEntry, Prev); 51 return Prev; 52 } 53 } 54 55 static void PrintStack(raw_ostream &OS) { 56 // Print out the stack in reverse order. To avoid recursion (which is likely 57 // to fail if we crashed due to stack overflow), we do an up-front pass to 58 // reverse the stack, then print it, then reverse it again. 59 unsigned ID = 0; 60 PrettyStackTraceEntry *ReversedStack = 61 llvm::ReverseStackTrace(PrettyStackTraceHead); 62 for (const PrettyStackTraceEntry *Entry = ReversedStack; Entry; 63 Entry = Entry->getNextEntry()) { 64 OS << ID++ << ".\t"; 65 sys::Watchdog W(5); 66 Entry->print(OS); 67 } 68 llvm::ReverseStackTrace(ReversedStack); 69 } 70 71 /// PrintCurStackTrace - Print the current stack trace to the specified stream. 72 static void PrintCurStackTrace(raw_ostream &OS) { 73 // Don't print an empty trace. 74 if (!PrettyStackTraceHead) return; 75 76 // If there are pretty stack frames registered, walk and emit them. 77 OS << "Stack dump:\n"; 78 79 PrintStack(OS); 80 OS.flush(); 81 } 82 83 // Integrate with crash reporter libraries. 84 #if defined (__APPLE__) && defined(HAVE_CRASHREPORTERCLIENT_H) 85 // If any clients of llvm try to link to libCrashReporterClient.a themselves, 86 // only one crash info struct will be used. 87 extern "C" { 88 CRASH_REPORTER_CLIENT_HIDDEN 89 struct crashreporter_annotations_t gCRAnnotations 90 __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION))) 91 #if CRASHREPORTER_ANNOTATIONS_VERSION < 5 92 = { CRASHREPORTER_ANNOTATIONS_VERSION, 0, 0, 0, 0, 0, 0 }; 93 #else 94 = { CRASHREPORTER_ANNOTATIONS_VERSION, 0, 0, 0, 0, 0, 0, 0 }; 95 #endif 96 } 97 #elif defined(__APPLE__) && HAVE_CRASHREPORTER_INFO 98 extern "C" const char *__crashreporter_info__ 99 __attribute__((visibility("hidden"))) = 0; 100 asm(".desc ___crashreporter_info__, 0x10"); 101 #endif 102 103 /// CrashHandler - This callback is run if a fatal signal is delivered to the 104 /// process, it prints the pretty stack trace. 105 static void CrashHandler(void *) { 106 #ifndef __APPLE__ 107 // On non-apple systems, just emit the crash stack trace to stderr. 108 PrintCurStackTrace(errs()); 109 #else 110 // Otherwise, emit to a smallvector of chars, send *that* to stderr, but also 111 // put it into __crashreporter_info__. 112 SmallString<2048> TmpStr; 113 { 114 raw_svector_ostream Stream(TmpStr); 115 PrintCurStackTrace(Stream); 116 } 117 118 if (!TmpStr.empty()) { 119 #ifdef HAVE_CRASHREPORTERCLIENT_H 120 // Cast to void to avoid warning. 121 (void)CRSetCrashLogMessage(TmpStr.c_str()); 122 #elif HAVE_CRASHREPORTER_INFO 123 __crashreporter_info__ = strdup(TmpStr.c_str()); 124 #endif 125 errs() << TmpStr.str(); 126 } 127 128 #endif 129 } 130 131 // defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES 132 #endif 133 134 PrettyStackTraceEntry::PrettyStackTraceEntry() { 135 #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES 136 // Link ourselves. 137 NextEntry = PrettyStackTraceHead; 138 PrettyStackTraceHead = this; 139 #endif 140 } 141 142 PrettyStackTraceEntry::~PrettyStackTraceEntry() { 143 #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES 144 assert(PrettyStackTraceHead == this && 145 "Pretty stack trace entry destruction is out of order"); 146 PrettyStackTraceHead = NextEntry; 147 #endif 148 } 149 150 void PrettyStackTraceString::print(raw_ostream &OS) const { OS << Str << "\n"; } 151 152 PrettyStackTraceFormat::PrettyStackTraceFormat(const char *Format, ...) { 153 va_list AP; 154 va_start(AP, Format); 155 const int SizeOrError = vsnprintf(nullptr, 0, Format, AP); 156 va_end(AP); 157 if (SizeOrError < 0) { 158 return; 159 } 160 161 const int Size = SizeOrError + 1; // '\0' 162 Str.resize(Size); 163 va_start(AP, Format); 164 vsnprintf(Str.data(), Size, Format, AP); 165 va_end(AP); 166 } 167 168 void PrettyStackTraceFormat::print(raw_ostream &OS) const { OS << Str << "\n"; } 169 170 void PrettyStackTraceProgram::print(raw_ostream &OS) const { 171 OS << "Program arguments: "; 172 // Print the argument list. 173 for (unsigned i = 0, e = ArgC; i != e; ++i) 174 OS << ArgV[i] << ' '; 175 OS << '\n'; 176 } 177 178 #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES 179 static bool RegisterCrashPrinter() { 180 sys::AddSignalHandler(CrashHandler, nullptr); 181 return false; 182 } 183 #endif 184 185 void llvm::EnablePrettyStackTrace() { 186 #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES 187 // The first time this is called, we register the crash printer. 188 static bool HandlerRegistered = RegisterCrashPrinter(); 189 (void)HandlerRegistered; 190 #endif 191 } 192 193 const void *llvm::SavePrettyStackState() { 194 #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES 195 return PrettyStackTraceHead; 196 #else 197 return nullptr; 198 #endif 199 } 200 201 void llvm::RestorePrettyStackState(const void *Top) { 202 #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES 203 PrettyStackTraceHead = 204 static_cast<PrettyStackTraceEntry *>(const_cast<void *>(Top)); 205 #endif 206 } 207 208 void LLVMEnablePrettyStackTrace() { 209 EnablePrettyStackTrace(); 210 } 211