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