LCOV - code coverage report
Current view: top level - lib/Support - PrettyStackTrace.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 19 64 29.7 %
Date: 2018-10-20 13:21:21 Functions: 5 15 33.3 %
Legend: Lines: hit not hit

          Line data    Source code
       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           0 : PrettyStackTraceEntry *ReverseStackTrace(PrettyStackTraceEntry *Head) {
      47           0 :   PrettyStackTraceEntry *Prev = nullptr;
      48           0 :   while (Head)
      49           0 :     std::tie(Prev, Head, Head->NextEntry) =
      50           0 :         std::make_tuple(Head, Head->NextEntry, Prev);
      51           0 :   return Prev;
      52             : }
      53             : }
      54             : 
      55           0 : 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           0 :       llvm::ReverseStackTrace(PrettyStackTraceHead);
      62           0 :   for (const PrettyStackTraceEntry *Entry = ReversedStack; Entry;
      63           0 :        Entry = Entry->getNextEntry()) {
      64           0 :     OS << ID++ << ".\t";
      65           0 :     sys::Watchdog W(5);
      66           0 :     Entry->print(OS);
      67             :   }
      68           0 :   llvm::ReverseStackTrace(ReversedStack);
      69           0 : }
      70             : 
      71             : /// PrintCurStackTrace - Print the current stack trace to the specified stream.
      72           0 : static void PrintCurStackTrace(raw_ostream &OS) {
      73             :   // Don't print an empty trace.
      74           0 :   if (!PrettyStackTraceHead) return;
      75             : 
      76             :   // If there are pretty stack frames registered, walk and emit them.
      77           0 :   OS << "Stack dump:\n";
      78             : 
      79           0 :   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           0 : static void CrashHandler(void *) {
     106             : #ifndef __APPLE__
     107             :   // On non-apple systems, just emit the crash stack trace to stderr.
     108           0 :   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           0 : }
     130             : 
     131             : // defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES
     132             : #endif
     133             : 
     134   176351781 : PrettyStackTraceEntry::PrettyStackTraceEntry() {
     135             : #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES
     136             :   // Link ourselves.
     137   176351781 :   NextEntry = PrettyStackTraceHead;
     138   176351781 :   PrettyStackTraceHead = this;
     139             : #endif
     140   176351781 : }
     141             : 
     142   352700410 : PrettyStackTraceEntry::~PrettyStackTraceEntry() {
     143             : #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES
     144             :   assert(PrettyStackTraceHead == this &&
     145             :          "Pretty stack trace entry destruction is out of order");
     146   176350205 :   PrettyStackTraceHead = NextEntry;
     147             : #endif
     148   176350205 : }
     149           0 : 
     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           0 :   const int SizeOrError = vsnprintf(nullptr, 0, Format, AP);
     156   352700410 :   va_end(AP);
     157             :   if (SizeOrError < 0) {
     158             :     return;
     159             :   }
     160   176350205 : 
     161             :   const int Size = SizeOrError + 1; // '\0'
     162   176350205 :   Str.resize(Size);
     163             :   va_start(AP, Format);
     164           0 :   vsnprintf(Str.data(), Size, Format, AP);
     165             :   va_end(AP);
     166           0 : }
     167             : 
     168           0 : void PrettyStackTraceFormat::print(raw_ostream &OS) const { OS << Str << "\n"; }
     169           0 : 
     170           0 : void PrettyStackTraceProgram::print(raw_ostream &OS) const {
     171           0 :   OS << "Program arguments: ";
     172           0 :   // Print the argument list.
     173             :   for (unsigned i = 0, e = ArgC; i != e; ++i)
     174             :     OS << ArgV[i] << ' ';
     175           0 :   OS << '\n';
     176           0 : }
     177           0 : 
     178           0 : #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES
     179           0 : static bool RegisterCrashPrinter() {
     180             :   sys::AddSignalHandler(CrashHandler, nullptr);
     181             :   return false;
     182           0 : }
     183             : #endif
     184           0 : 
     185           0 : void llvm::EnablePrettyStackTrace() {
     186             : #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES
     187           0 :   // The first time this is called, we register the crash printer.
     188           0 :   static bool HandlerRegistered = RegisterCrashPrinter();
     189             :   (void)HandlerRegistered;
     190           0 : #endif
     191             : }
     192             : 
     193             : const void *llvm::SavePrettyStackState() {
     194      166312 : #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES
     195             :   return PrettyStackTraceHead;
     196             : #else
     197             :   return nullptr;
     198             : #endif
     199      166312 : }
     200             : 
     201             : void llvm::RestorePrettyStackState(const void *Top) {
     202      332624 : #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES
     203             :   PrettyStackTraceHead =
     204             :       static_cast<PrettyStackTraceEntry *>(const_cast<void *>(Top));
     205      166312 : #endif
     206             : }
     207       36870 : 
     208             : void LLVMEnablePrettyStackTrace() {
     209       36870 :   EnablePrettyStackTrace();
     210             : }

Generated by: LCOV version 1.13