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