LCOV - code coverage report
Current view: top level - lib/Support - PrettyStackTrace.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 26 60 43.3 %
Date: 2017-09-14 15:23:50 Functions: 6 15 40.0 %
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           0 :   unsigned ID = 0;
      60             :   PrettyStackTraceEntry *ReversedStack =
      61           0 :       llvm::ReverseStackTrace(PrettyStackTraceHead);
      62           0 :   for (const PrettyStackTraceEntry *Entry = ReversedStack; Entry;
      63             :        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             :         = { CRASHREPORTER_ANNOTATIONS_VERSION, 0, 0, 0, 0, 0, 0 };
      92             : }
      93             : #elif defined(__APPLE__) && HAVE_CRASHREPORTER_INFO
      94             : extern "C" const char *__crashreporter_info__
      95             :     __attribute__((visibility("hidden"))) = 0;
      96             : asm(".desc ___crashreporter_info__, 0x10");
      97             : #endif
      98             : 
      99             : /// CrashHandler - This callback is run if a fatal signal is delivered to the
     100             : /// process, it prints the pretty stack trace.
     101           0 : static void CrashHandler(void *) {
     102             : #ifndef __APPLE__
     103             :   // On non-apple systems, just emit the crash stack trace to stderr.
     104           0 :   PrintCurStackTrace(errs());
     105             : #else
     106             :   // Otherwise, emit to a smallvector of chars, send *that* to stderr, but also
     107             :   // put it into __crashreporter_info__.
     108             :   SmallString<2048> TmpStr;
     109             :   {
     110             :     raw_svector_ostream Stream(TmpStr);
     111             :     PrintCurStackTrace(Stream);
     112             :   }
     113             :   
     114             :   if (!TmpStr.empty()) {
     115             : #ifdef HAVE_CRASHREPORTERCLIENT_H
     116             :     // Cast to void to avoid warning.
     117             :     (void)CRSetCrashLogMessage(std::string(TmpStr.str()).c_str());
     118             : #elif HAVE_CRASHREPORTER_INFO 
     119             :     __crashreporter_info__ = strdup(std::string(TmpStr.str()).c_str());
     120             : #endif
     121             :     errs() << TmpStr.str();
     122             :   }
     123             :   
     124             : #endif
     125           0 : }
     126             : 
     127             : // defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES
     128             : #endif
     129             : 
     130    58060460 : PrettyStackTraceEntry::PrettyStackTraceEntry() {
     131             : #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES
     132             :   // Link ourselves.
     133    58060460 :   NextEntry = PrettyStackTraceHead;
     134    58060460 :   PrettyStackTraceHead = this;
     135             : #endif
     136    58060460 : }
     137             : 
     138   116117844 : PrettyStackTraceEntry::~PrettyStackTraceEntry() {
     139             : #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES
     140             :   assert(PrettyStackTraceHead == this &&
     141             :          "Pretty stack trace entry destruction is out of order");
     142    58058922 :   PrettyStackTraceHead = NextEntry;
     143             : #endif
     144    58058922 : }
     145             : 
     146           0 : void PrettyStackTraceString::print(raw_ostream &OS) const { OS << Str << "\n"; }
     147             : 
     148        9542 : PrettyStackTraceFormat::PrettyStackTraceFormat(const char *Format, ...) {
     149             :   va_list AP;
     150        4771 :   va_start(AP, Format);
     151        4771 :   const int SizeOrError = vsnprintf(nullptr, 0, Format, AP);
     152        4771 :   va_end(AP);
     153        4771 :   if (SizeOrError < 0) {
     154           0 :     return;
     155             :   }
     156             : 
     157        4771 :   const int Size = SizeOrError + 1; // '\0'
     158        4771 :   Str.resize(Size);
     159        4771 :   va_start(AP, Format);
     160        9542 :   vsnprintf(Str.data(), Size, Format, AP);
     161        4771 :   va_end(AP);
     162             : }
     163             : 
     164           0 : void PrettyStackTraceFormat::print(raw_ostream &OS) const { OS << Str << "\n"; }
     165             : 
     166           0 : void PrettyStackTraceProgram::print(raw_ostream &OS) const {
     167           0 :   OS << "Program arguments: ";
     168             :   // Print the argument list.
     169           0 :   for (unsigned i = 0, e = ArgC; i != e; ++i)
     170           0 :     OS << ArgV[i] << ' ';
     171           0 :   OS << '\n';
     172           0 : }
     173             : 
     174             : #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES
     175             : static bool RegisterCrashPrinter() {
     176      109989 :   sys::AddSignalHandler(CrashHandler, nullptr);
     177             :   return false;
     178             : }
     179             : #endif
     180             : 
     181      109989 : void llvm::EnablePrettyStackTrace() {
     182             : #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES
     183             :   // The first time this is called, we register the crash printer.
     184      219978 :   static bool HandlerRegistered = RegisterCrashPrinter();
     185             :   (void)HandlerRegistered;
     186             : #endif
     187      109989 : }
     188             : 
     189       21335 : const void *llvm::SavePrettyStackState() {
     190             : #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES
     191       21335 :   return PrettyStackTraceHead;
     192             : #else
     193             :   return nullptr;
     194             : #endif
     195             : }
     196             : 
     197           0 : void llvm::RestorePrettyStackState(const void *Top) {
     198             : #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES
     199           0 :   PrettyStackTraceHead =
     200             :       static_cast<PrettyStackTraceEntry *>(const_cast<void *>(Top));
     201             : #endif
     202           0 : }
     203             : 
     204           7 : void LLVMEnablePrettyStackTrace() {
     205           7 :   EnablePrettyStackTrace();
     206           7 : }

Generated by: LCOV version 1.13