| 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/Config/config.h" |
| 17 | #include "llvm/Support/Compiler.h" |
| 18 | #include "llvm/Support/SaveAndRestore.h" |
| 19 | #include "llvm/Support/Signals.h" |
| 20 | #include "llvm/Support/Watchdog.h" |
| 21 | #include "llvm/Support/raw_ostream.h" |
| 22 | |
| 23 | #ifdef __APPLE__ |
| 24 | #include "llvm/ADT/SmallString.h" |
| 25 | #endif |
| 26 | |
| 27 | #include <atomic> |
| 28 | #include <cassert> |
| 29 | #include <cstdarg> |
| 30 | #include <cstdio> |
| 31 | #include <cstring> |
| 32 | #include <tuple> |
| 33 | |
| 34 | #ifdef HAVE_CRASHREPORTERCLIENT_H |
| 35 | #include <CrashReporterClient.h> |
| 36 | #endif |
| 37 | |
| 38 | using namespace llvm; |
| 39 | |
| 40 | static const char *BugReportMsg = |
| 41 | "PLEASE submit a bug report to " BUG_REPORT_URL |
| 42 | " and include the crash backtrace.\n" ; |
| 43 | |
| 44 | // If backtrace support is not enabled, compile out support for pretty stack |
| 45 | // traces. This has the secondary effect of not requiring thread local storage |
| 46 | // when backtrace support is disabled. |
| 47 | #if ENABLE_BACKTRACES |
| 48 | |
| 49 | // We need a thread local pointer to manage the stack of our stack trace |
| 50 | // objects, but we *really* cannot tolerate destructors running and do not want |
| 51 | // to pay any overhead of synchronizing. As a consequence, we use a raw |
| 52 | // thread-local variable. |
| 53 | static LLVM_THREAD_LOCAL PrettyStackTraceEntry *PrettyStackTraceHead = nullptr; |
| 54 | |
| 55 | // The use of 'volatile' here is to ensure that any particular thread always |
| 56 | // reloads the value of the counter. The 'std::atomic' allows us to specify that |
| 57 | // this variable is accessed in an unsychronized way (it's not actually |
| 58 | // synchronizing). This does technically mean that the value may not appear to |
| 59 | // be the same across threads running simultaneously on different CPUs, but in |
| 60 | // practice the worst that will happen is that we won't print a stack trace when |
| 61 | // we could have. |
| 62 | // |
| 63 | // This is initialized to 1 because 0 is used as a sentinel for "not enabled on |
| 64 | // the current thread". If the user happens to overflow an 'unsigned' with |
| 65 | // SIGINFO requests, it's possible that some threads will stop responding to it, |
| 66 | // but the program won't crash. |
| 67 | static volatile std::atomic<unsigned> GlobalSigInfoGenerationCounter = 1; |
| 68 | static LLVM_THREAD_LOCAL unsigned ThreadLocalSigInfoGenerationCounter = 0; |
| 69 | |
| 70 | namespace llvm { |
| 71 | PrettyStackTraceEntry *ReverseStackTrace(PrettyStackTraceEntry *Head) { |
| 72 | PrettyStackTraceEntry *Prev = nullptr; |
| 73 | while (Head) |
| 74 | std::tie(args&: Prev, args&: Head, args&: Head->NextEntry) = |
| 75 | std::make_tuple(args&: Head, args&: Head->NextEntry, args&: Prev); |
| 76 | return Prev; |
| 77 | } |
| 78 | } // namespace llvm |
| 79 | |
| 80 | static void PrintStack(raw_ostream &OS) { |
| 81 | // Print out the stack in reverse order. To avoid recursion (which is likely |
| 82 | // to fail if we crashed due to stack overflow), we do an up-front pass to |
| 83 | // reverse the stack, then print it, then reverse it again. |
| 84 | unsigned ID = 0; |
| 85 | SaveAndRestore<PrettyStackTraceEntry *> SavedStack{PrettyStackTraceHead, |
| 86 | nullptr}; |
| 87 | PrettyStackTraceEntry *ReversedStack = ReverseStackTrace(Head: SavedStack.get()); |
| 88 | for (const PrettyStackTraceEntry *Entry = ReversedStack; Entry; |
| 89 | Entry = Entry->getNextEntry()) { |
| 90 | OS << ID++ << ".\t" ; |
| 91 | sys::Watchdog W(5); |
| 92 | Entry->print(OS); |
| 93 | } |
| 94 | llvm::ReverseStackTrace(Head: ReversedStack); |
| 95 | } |
| 96 | |
| 97 | /// Print the current stack trace to the specified stream. |
| 98 | /// |
| 99 | /// Marked NOINLINE so it can be called from debuggers. |
| 100 | LLVM_ATTRIBUTE_NOINLINE |
| 101 | static void PrintCurStackTrace(raw_ostream &OS) { |
| 102 | // Don't print an empty trace. |
| 103 | if (!PrettyStackTraceHead) return; |
| 104 | |
| 105 | // If there are pretty stack frames registered, walk and emit them. |
| 106 | OS << "Stack dump:\n" ; |
| 107 | |
| 108 | PrintStack(OS); |
| 109 | OS.flush(); |
| 110 | } |
| 111 | |
| 112 | // Integrate with crash reporter libraries. |
| 113 | #if defined (__APPLE__) && defined(HAVE_CRASHREPORTERCLIENT_H) |
| 114 | // If any clients of llvm try to link to libCrashReporterClient.a themselves, |
| 115 | // only one crash info struct will be used. |
| 116 | extern "C" { |
| 117 | CRASH_REPORTER_CLIENT_HIDDEN |
| 118 | struct crashreporter_annotations_t gCRAnnotations |
| 119 | __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION))) |
| 120 | #if CRASHREPORTER_ANNOTATIONS_VERSION < 5 |
| 121 | = { CRASHREPORTER_ANNOTATIONS_VERSION, 0, 0, 0, 0, 0, 0 }; |
| 122 | #else |
| 123 | = { CRASHREPORTER_ANNOTATIONS_VERSION, 0, 0, 0, 0, 0, 0, 0 }; |
| 124 | #endif |
| 125 | } |
| 126 | #elif defined(__APPLE__) && HAVE_CRASHREPORTER_INFO |
| 127 | extern "C" const char *__crashreporter_info__ |
| 128 | __attribute__((visibility("hidden" ))) = 0; |
| 129 | asm(".desc ___crashreporter_info__, 0x10" ); |
| 130 | #endif |
| 131 | |
| 132 | static void setCrashLogMessage(const char *msg) LLVM_ATTRIBUTE_UNUSED; |
| 133 | static void setCrashLogMessage(const char *msg) { |
| 134 | #ifdef HAVE_CRASHREPORTERCLIENT_H |
| 135 | (void)CRSetCrashLogMessage(msg); |
| 136 | #elif HAVE_CRASHREPORTER_INFO |
| 137 | __crashreporter_info__ = msg; |
| 138 | #endif |
| 139 | // Don't reorder subsequent operations: whatever comes after might crash and |
| 140 | // we want the system crash handling to see the message we just set. |
| 141 | std::atomic_signal_fence(m: std::memory_order_seq_cst); |
| 142 | } |
| 143 | |
| 144 | #ifdef __APPLE__ |
| 145 | using CrashHandlerString = SmallString<2048>; |
| 146 | using CrashHandlerStringStorage = std::byte[sizeof(CrashHandlerString)]; |
| 147 | alignas(CrashHandlerString) static CrashHandlerStringStorage |
| 148 | crashHandlerStringStorage; |
| 149 | #endif |
| 150 | |
| 151 | /// This callback is run if a fatal signal is delivered to the process, it |
| 152 | /// prints the pretty stack trace. |
| 153 | static void CrashHandler(void *) { |
| 154 | errs() << BugReportMsg ; |
| 155 | |
| 156 | #ifndef __APPLE__ |
| 157 | // On non-apple systems, just emit the crash stack trace to stderr. |
| 158 | PrintCurStackTrace(OS&: errs()); |
| 159 | #else |
| 160 | // Emit the crash stack trace to a SmallString, put it where the system crash |
| 161 | // handling will find it, and also send it to stderr. |
| 162 | // |
| 163 | // The SmallString is fairly large in the hope that we don't allocate (we're |
| 164 | // handling a fatal signal, something is already pretty wrong, allocation |
| 165 | // might not work). Further, we don't use a magic static in case that's also |
| 166 | // borked. We leak any allocation that does occur because the program is about |
| 167 | // to die anyways. This is technically racy if we were handling two fatal |
| 168 | // signals, however if we're in that situation a race is the least of our |
| 169 | // worries. |
| 170 | auto &crashHandlerString = |
| 171 | *new (&crashHandlerStringStorage) CrashHandlerString; |
| 172 | |
| 173 | // If we crash while trying to print the stack trace, we still want the system |
| 174 | // crash handling to have some partial information. That'll work out as long |
| 175 | // as the SmallString doesn't allocate. If it does allocate then the system |
| 176 | // crash handling will see some garbage because the inline buffer now contains |
| 177 | // a pointer. |
| 178 | setCrashLogMessage(crashHandlerString.c_str()); |
| 179 | |
| 180 | { |
| 181 | raw_svector_ostream Stream(crashHandlerString); |
| 182 | PrintCurStackTrace(Stream); |
| 183 | } |
| 184 | |
| 185 | if (!crashHandlerString.empty()) { |
| 186 | setCrashLogMessage(crashHandlerString.c_str()); |
| 187 | errs() << crashHandlerString.str(); |
| 188 | } else { |
| 189 | setCrashLogMessage("No crash information." ); |
| 190 | } |
| 191 | #endif |
| 192 | } |
| 193 | |
| 194 | static void printForSigInfoIfNeeded() { |
| 195 | unsigned CurrentSigInfoGeneration = |
| 196 | GlobalSigInfoGenerationCounter.load(m: std::memory_order_relaxed); |
| 197 | if (ThreadLocalSigInfoGenerationCounter == 0 || |
| 198 | ThreadLocalSigInfoGenerationCounter == CurrentSigInfoGeneration) { |
| 199 | return; |
| 200 | } |
| 201 | |
| 202 | PrintCurStackTrace(OS&: errs()); |
| 203 | ThreadLocalSigInfoGenerationCounter = CurrentSigInfoGeneration; |
| 204 | } |
| 205 | |
| 206 | #endif // ENABLE_BACKTRACES |
| 207 | |
| 208 | void llvm::setBugReportMsg(const char *Msg) { |
| 209 | BugReportMsg = Msg; |
| 210 | } |
| 211 | |
| 212 | const char *llvm::getBugReportMsg() { |
| 213 | return BugReportMsg; |
| 214 | } |
| 215 | |
| 216 | PrettyStackTraceEntry::PrettyStackTraceEntry() { |
| 217 | #if ENABLE_BACKTRACES |
| 218 | // Handle SIGINFO first, because we haven't finished constructing yet. |
| 219 | printForSigInfoIfNeeded(); |
| 220 | // Link ourselves. |
| 221 | NextEntry = PrettyStackTraceHead; |
| 222 | PrettyStackTraceHead = this; |
| 223 | #endif |
| 224 | } |
| 225 | |
| 226 | PrettyStackTraceEntry::~PrettyStackTraceEntry() { |
| 227 | #if ENABLE_BACKTRACES |
| 228 | assert(PrettyStackTraceHead == this && |
| 229 | "Pretty stack trace entry destruction is out of order" ); |
| 230 | PrettyStackTraceHead = NextEntry; |
| 231 | // Handle SIGINFO first, because we already started destructing. |
| 232 | printForSigInfoIfNeeded(); |
| 233 | #endif |
| 234 | } |
| 235 | |
| 236 | void PrettyStackTraceString::print(raw_ostream &OS) const { OS << Str << "\n" ; } |
| 237 | |
| 238 | PrettyStackTraceFormat::PrettyStackTraceFormat(const char *Format, ...) { |
| 239 | va_list AP; |
| 240 | va_start(AP, Format); |
| 241 | const int SizeOrError = vsnprintf(s: nullptr, maxlen: 0, format: Format, arg: AP); |
| 242 | va_end(AP); |
| 243 | if (SizeOrError < 0) { |
| 244 | return; |
| 245 | } |
| 246 | |
| 247 | const int Size = SizeOrError + 1; // '\0' |
| 248 | Str.resize(N: Size); |
| 249 | va_start(AP, Format); |
| 250 | vsnprintf(s: Str.data(), maxlen: Size, format: Format, arg: AP); |
| 251 | va_end(AP); |
| 252 | } |
| 253 | |
| 254 | void PrettyStackTraceFormat::print(raw_ostream &OS) const { OS << Str << "\n" ; } |
| 255 | |
| 256 | void PrettyStackTraceProgram::print(raw_ostream &OS) const { |
| 257 | OS << "Program arguments: " ; |
| 258 | // Print the argument list. |
| 259 | for (int I = 0; I < ArgC; ++I) { |
| 260 | const bool HaveSpace = ::strchr(s: ArgV[I], c: ' '); |
| 261 | if (I) |
| 262 | OS << ' '; |
| 263 | if (HaveSpace) |
| 264 | OS << '"'; |
| 265 | OS.write_escaped(Str: ArgV[I]); |
| 266 | if (HaveSpace) |
| 267 | OS << '"'; |
| 268 | } |
| 269 | OS << '\n'; |
| 270 | } |
| 271 | |
| 272 | #if ENABLE_BACKTRACES |
| 273 | static bool RegisterCrashPrinter() { |
| 274 | sys::AddSignalHandler(FnPtr: CrashHandler, Cookie: nullptr); |
| 275 | return false; |
| 276 | } |
| 277 | #endif |
| 278 | |
| 279 | void llvm::EnablePrettyStackTrace() { |
| 280 | #if ENABLE_BACKTRACES |
| 281 | // The first time this is called, we register the crash printer. |
| 282 | static bool HandlerRegistered = RegisterCrashPrinter(); |
| 283 | (void)HandlerRegistered; |
| 284 | #endif |
| 285 | } |
| 286 | |
| 287 | void llvm::EnablePrettyStackTraceOnSigInfoForThisThread(bool ShouldEnable) { |
| 288 | #if ENABLE_BACKTRACES |
| 289 | if (!ShouldEnable) { |
| 290 | ThreadLocalSigInfoGenerationCounter = 0; |
| 291 | return; |
| 292 | } |
| 293 | |
| 294 | // The first time this is called, we register the SIGINFO handler. |
| 295 | static bool HandlerRegistered = []{ |
| 296 | sys::SetInfoSignalFunction([]{ |
| 297 | GlobalSigInfoGenerationCounter.fetch_add(i: 1, m: std::memory_order_relaxed); |
| 298 | }); |
| 299 | return false; |
| 300 | }(); |
| 301 | (void)HandlerRegistered; |
| 302 | |
| 303 | // Next, enable it for the current thread. |
| 304 | ThreadLocalSigInfoGenerationCounter = |
| 305 | GlobalSigInfoGenerationCounter.load(m: std::memory_order_relaxed); |
| 306 | #endif |
| 307 | } |
| 308 | |
| 309 | const void *llvm::SavePrettyStackState() { |
| 310 | #if ENABLE_BACKTRACES |
| 311 | return PrettyStackTraceHead; |
| 312 | #else |
| 313 | return nullptr; |
| 314 | #endif |
| 315 | } |
| 316 | |
| 317 | void llvm::RestorePrettyStackState(const void *Top) { |
| 318 | #if ENABLE_BACKTRACES |
| 319 | PrettyStackTraceHead = |
| 320 | static_cast<PrettyStackTraceEntry *>(const_cast<void *>(Top)); |
| 321 | #endif |
| 322 | } |
| 323 | |
| 324 | void LLVMEnablePrettyStackTrace() { |
| 325 | EnablePrettyStackTrace(); |
| 326 | } |
| 327 | |