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/Core.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#ifdef HAVE_CRASHREPORTERCLIENT_H 25#include <CrashReporterClient.h> 26#endif 27 28using namespace llvm; 29 30// If backtrace support is not enabled, compile out support for pretty stack 31// traces. This has the secondary effect of not requiring thread local storage 32// when backtrace support is disabled. 33#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) 34 35// We need a thread local pointer to manage the stack of our stack trace 36// objects, but we *really* cannot tolerate destructors running and do not want 37// to pay any overhead of synchronizing. As a consequence, we use a raw 38// thread-local variable. 39static LLVM_THREAD_LOCAL const PrettyStackTraceEntry *PrettyStackTraceHead = 40 nullptr; 41 42static unsigned PrintStack(const PrettyStackTraceEntry *Entry, raw_ostream &OS){ 43 unsigned NextID = 0; 44 if (Entry->getNextEntry()) 45 NextID = PrintStack(Entry->getNextEntry(), OS); 46 OS << NextID << ".\t"; 47 { 48 sys::Watchdog W(5); 49 Entry->print(OS); 50 } 51 52 return NextID+1; 53} 54 55/// PrintCurStackTrace - Print the current stack trace to the specified stream. 56static void PrintCurStackTrace(raw_ostream &OS) { 57 // Don't print an empty trace. 58 if (!PrettyStackTraceHead) return; 59 60 // If there are pretty stack frames registered, walk and emit them. 61 OS << "Stack dump:\n"; 62 63 PrintStack(PrettyStackTraceHead, OS); 64 OS.flush(); 65} 66 67// Integrate with crash reporter libraries. 68#if defined (__APPLE__) && HAVE_CRASHREPORTERCLIENT_H 69// If any clients of llvm try to link to libCrashReporterClient.a themselves, 70// only one crash info struct will be used. 71extern "C" { 72CRASH_REPORTER_CLIENT_HIDDEN 73struct crashreporter_annotations_t gCRAnnotations 74 __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION))) 75 = { CRASHREPORTER_ANNOTATIONS_VERSION, 0, 0, 0, 0, 0, 0 }; 76} 77#elif defined (__APPLE__) && HAVE_CRASHREPORTER_INFO 78static const char *__crashreporter_info__ = 0; 79asm(".desc ___crashreporter_info__, 0x10"); 80#endif 81 82 83/// CrashHandler - This callback is run if a fatal signal is delivered to the 84/// process, it prints the pretty stack trace. 85static void CrashHandler(void *) { 86#ifndef __APPLE__ 87 // On non-apple systems, just emit the crash stack trace to stderr. 88 PrintCurStackTrace(errs()); 89#else 90 // Otherwise, emit to a smallvector of chars, send *that* to stderr, but also 91 // put it into __crashreporter_info__. 92 SmallString<2048> TmpStr; 93 { 94 raw_svector_ostream Stream(TmpStr); 95 PrintCurStackTrace(Stream); 96 } 97 98 if (!TmpStr.empty()) { 99#ifdef HAVE_CRASHREPORTERCLIENT_H 100 // Cast to void to avoid warning. 101 (void)CRSetCrashLogMessage(std::string(TmpStr.str()).c_str()); 102#elif HAVE_CRASHREPORTER_INFO 103 __crashreporter_info__ = strdup(std::string(TmpStr.str()).c_str()); 104#endif 105 errs() << TmpStr.str(); 106 } 107 108#endif 109} 110 111// defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) 112#endif 113 114PrettyStackTraceEntry::PrettyStackTraceEntry() { 115#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) 116 // Link ourselves. 117 NextEntry = PrettyStackTraceHead; 118 PrettyStackTraceHead = this; 119#endif 120} 121 122PrettyStackTraceEntry::~PrettyStackTraceEntry() { 123#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) 124 assert(PrettyStackTraceHead == this && 125 "Pretty stack trace entry destruction is out of order"); 126 PrettyStackTraceHead = getNextEntry(); 127#endif 128} 129 130void PrettyStackTraceString::print(raw_ostream &OS) const { 131 OS << Str << "\n"; 132} 133 134void PrettyStackTraceProgram::print(raw_ostream &OS) const { 135 OS << "Program arguments: "; 136 // Print the argument list. 137 for (unsigned i = 0, e = ArgC; i != e; ++i) 138 OS << ArgV[i] << ' '; 139 OS << '\n'; 140} 141 142#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) 143static bool RegisterCrashPrinter() { 144 sys::AddSignalHandler(CrashHandler, nullptr); 145 return false; 146} 147#endif 148 149void llvm::EnablePrettyStackTrace() { 150#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) 151 // The first time this is called, we register the crash printer. 152 static bool HandlerRegistered = RegisterCrashPrinter(); 153 (void)HandlerRegistered; 154#endif 155} 156 157void LLVMEnablePrettyStackTrace() { 158 EnablePrettyStackTrace(); 159} 160