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