PrettyStackTrace.cpp revision 226633
1193323Sed//===- PrettyStackTrace.cpp - Pretty Crash Handling -----------------------===// 2193323Sed// 3193323Sed// The LLVM Compiler Infrastructure 4193323Sed// 5193323Sed// This file is distributed under the University of Illinois Open Source 6193323Sed// License. See LICENSE.TXT for details. 7193323Sed// 8193323Sed//===----------------------------------------------------------------------===// 9193323Sed// 10193323Sed// This file defines some helpful functions for dealing with the possibility of 11221345Sdim// Unix signals occurring while your program is running. 12193323Sed// 13193323Sed//===----------------------------------------------------------------------===// 14193323Sed 15210299Sed#include "llvm/Config/config.h" // Get autoconf configuration settings 16193323Sed#include "llvm/Support/PrettyStackTrace.h" 17193323Sed#include "llvm/Support/raw_ostream.h" 18218893Sdim#include "llvm/Support/Signals.h" 19218893Sdim#include "llvm/Support/ThreadLocal.h" 20193323Sed#include "llvm/ADT/SmallString.h" 21210299Sed 22210299Sed#ifdef HAVE_CRASHREPORTERCLIENT_H 23210299Sed#include <CrashReporterClient.h> 24210299Sed#endif 25210299Sed 26193323Sedusing namespace llvm; 27193323Sed 28198090Srdivackynamespace llvm { 29198090Srdivacky bool DisablePrettyStackTrace = false; 30198090Srdivacky} 31198090Srdivacky 32193323Sed// FIXME: This should be thread local when llvm supports threads. 33195098Sedstatic sys::ThreadLocal<const PrettyStackTraceEntry> PrettyStackTraceHead; 34193323Sed 35193323Sedstatic unsigned PrintStack(const PrettyStackTraceEntry *Entry, raw_ostream &OS){ 36193323Sed unsigned NextID = 0; 37193323Sed if (Entry->getNextEntry()) 38193323Sed NextID = PrintStack(Entry->getNextEntry(), OS); 39193323Sed OS << NextID << ".\t"; 40193323Sed Entry->print(OS); 41193323Sed 42193323Sed return NextID+1; 43193323Sed} 44193323Sed 45193323Sed/// PrintCurStackTrace - Print the current stack trace to the specified stream. 46193323Sedstatic void PrintCurStackTrace(raw_ostream &OS) { 47193323Sed // Don't print an empty trace. 48195098Sed if (PrettyStackTraceHead.get() == 0) return; 49193323Sed 50193323Sed // If there are pretty stack frames registered, walk and emit them. 51193323Sed OS << "Stack dump:\n"; 52193323Sed 53195098Sed PrintStack(PrettyStackTraceHead.get(), OS); 54193323Sed OS.flush(); 55193323Sed} 56193323Sed 57210299Sed// Integrate with crash reporter libraries. 58218893Sdim#if defined (__APPLE__) && HAVE_CRASHREPORTERCLIENT_H 59210299Sed// If any clients of llvm try to link to libCrashReporterClient.a themselves, 60210299Sed// only one crash info struct will be used. 61210299Sedextern "C" { 62210299SedCRASH_REPORTER_CLIENT_HIDDEN 63210299Sedstruct crashreporter_annotations_t gCRAnnotations 64210299Sed __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION))) 65226633Sdim = { CRASHREPORTER_ANNOTATIONS_VERSION, 0, 0, 0, 0, 0, 0 }; 66210299Sed} 67218893Sdim#elif defined (__APPLE__) && HAVE_CRASHREPORTER_INFO 68208599Srdivackystatic const char *__crashreporter_info__ = 0; 69208599Srdivackyasm(".desc ___crashreporter_info__, 0x10"); 70193323Sed#endif 71193323Sed 72193323Sed 73193323Sed/// CrashHandler - This callback is run if a fatal signal is delivered to the 74193323Sed/// process, it prints the pretty stack trace. 75212904Sdimstatic void CrashHandler(void *) { 76193323Sed#ifndef __APPLE__ 77193323Sed // On non-apple systems, just emit the crash stack trace to stderr. 78193323Sed PrintCurStackTrace(errs()); 79193323Sed#else 80193323Sed // Otherwise, emit to a smallvector of chars, send *that* to stderr, but also 81193323Sed // put it into __crashreporter_info__. 82193323Sed SmallString<2048> TmpStr; 83193323Sed { 84193323Sed raw_svector_ostream Stream(TmpStr); 85193323Sed PrintCurStackTrace(Stream); 86193323Sed } 87193323Sed 88193323Sed if (!TmpStr.empty()) { 89218893Sdim#ifdef HAVE_CRASHREPORTERCLIENT_H 90212904Sdim // Cast to void to avoid warning. 91212904Sdim (void)CRSetCrashLogMessage(std::string(TmpStr.str()).c_str()); 92218893Sdim#elif HAVE_CRASHREPORTER_INFO 93218893Sdim __crashreporter_info__ = strdup(std::string(TmpStr.str()).c_str()); 94210299Sed#endif 95198090Srdivacky errs() << TmpStr.str(); 96193323Sed } 97193323Sed 98193323Sed#endif 99193323Sed} 100193323Sed 101193323Sedstatic bool RegisterCrashPrinter() { 102198090Srdivacky if (!DisablePrettyStackTrace) 103198090Srdivacky sys::AddSignalHandler(CrashHandler, 0); 104193323Sed return false; 105193323Sed} 106193323Sed 107193323SedPrettyStackTraceEntry::PrettyStackTraceEntry() { 108193323Sed // The first time this is called, we register the crash printer. 109193323Sed static bool HandlerRegistered = RegisterCrashPrinter(); 110218893Sdim (void)HandlerRegistered; 111193323Sed 112193323Sed // Link ourselves. 113195098Sed NextEntry = PrettyStackTraceHead.get(); 114195098Sed PrettyStackTraceHead.set(this); 115193323Sed} 116193323Sed 117193323SedPrettyStackTraceEntry::~PrettyStackTraceEntry() { 118195098Sed assert(PrettyStackTraceHead.get() == this && 119193323Sed "Pretty stack trace entry destruction is out of order"); 120195098Sed PrettyStackTraceHead.set(getNextEntry()); 121193323Sed} 122193323Sed 123193323Sedvoid PrettyStackTraceString::print(raw_ostream &OS) const { 124193323Sed OS << Str << "\n"; 125193323Sed} 126193323Sed 127193323Sedvoid PrettyStackTraceProgram::print(raw_ostream &OS) const { 128193323Sed OS << "Program arguments: "; 129193323Sed // Print the argument list. 130193323Sed for (unsigned i = 0, e = ArgC; i != e; ++i) 131193323Sed OS << ArgV[i] << ' '; 132193323Sed OS << '\n'; 133193323Sed} 134