PrettyStackTrace.cpp revision 208599
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 11193323Sed// Unix signals occuring while your program is running. 12193323Sed// 13193323Sed//===----------------------------------------------------------------------===// 14193323Sed 15193323Sed#include "llvm/Support/PrettyStackTrace.h" 16193323Sed#include "llvm/Support/raw_ostream.h" 17193323Sed#include "llvm/System/Signals.h" 18195098Sed#include "llvm/System/ThreadLocal.h" 19193323Sed#include "llvm/ADT/SmallString.h" 20193323Sedusing namespace llvm; 21193323Sed 22198090Srdivackynamespace llvm { 23198090Srdivacky bool DisablePrettyStackTrace = false; 24198090Srdivacky} 25198090Srdivacky 26193323Sed// FIXME: This should be thread local when llvm supports threads. 27195098Sedstatic sys::ThreadLocal<const PrettyStackTraceEntry> PrettyStackTraceHead; 28193323Sed 29193323Sedstatic unsigned PrintStack(const PrettyStackTraceEntry *Entry, raw_ostream &OS){ 30193323Sed unsigned NextID = 0; 31193323Sed if (Entry->getNextEntry()) 32193323Sed NextID = PrintStack(Entry->getNextEntry(), OS); 33193323Sed OS << NextID << ".\t"; 34193323Sed Entry->print(OS); 35193323Sed 36193323Sed return NextID+1; 37193323Sed} 38193323Sed 39193323Sed/// PrintCurStackTrace - Print the current stack trace to the specified stream. 40193323Sedstatic void PrintCurStackTrace(raw_ostream &OS) { 41193323Sed // Don't print an empty trace. 42195098Sed if (PrettyStackTraceHead.get() == 0) return; 43193323Sed 44193323Sed // If there are pretty stack frames registered, walk and emit them. 45193323Sed OS << "Stack dump:\n"; 46193323Sed 47195098Sed PrintStack(PrettyStackTraceHead.get(), OS); 48193323Sed OS.flush(); 49193323Sed} 50193323Sed 51193323Sed// Integrate with crash reporter. 52193323Sed#ifdef __APPLE__ 53208599Srdivackystatic const char *__crashreporter_info__ = 0; 54208599Srdivackyasm(".desc ___crashreporter_info__, 0x10"); 55193323Sed#endif 56193323Sed 57193323Sed 58193323Sed/// CrashHandler - This callback is run if a fatal signal is delivered to the 59193323Sed/// process, it prints the pretty stack trace. 60193323Sedstatic void CrashHandler(void *Cookie) { 61193323Sed#ifndef __APPLE__ 62193323Sed // On non-apple systems, just emit the crash stack trace to stderr. 63193323Sed PrintCurStackTrace(errs()); 64193323Sed#else 65193323Sed // Otherwise, emit to a smallvector of chars, send *that* to stderr, but also 66193323Sed // put it into __crashreporter_info__. 67193323Sed SmallString<2048> TmpStr; 68193323Sed { 69193323Sed raw_svector_ostream Stream(TmpStr); 70193323Sed PrintCurStackTrace(Stream); 71193323Sed } 72193323Sed 73193323Sed if (!TmpStr.empty()) { 74198090Srdivacky __crashreporter_info__ = strdup(std::string(TmpStr.str()).c_str()); 75198090Srdivacky errs() << TmpStr.str(); 76193323Sed } 77193323Sed 78193323Sed#endif 79193323Sed} 80193323Sed 81193323Sedstatic bool RegisterCrashPrinter() { 82198090Srdivacky if (!DisablePrettyStackTrace) 83198090Srdivacky sys::AddSignalHandler(CrashHandler, 0); 84193323Sed return false; 85193323Sed} 86193323Sed 87193323SedPrettyStackTraceEntry::PrettyStackTraceEntry() { 88193323Sed // The first time this is called, we register the crash printer. 89193323Sed static bool HandlerRegistered = RegisterCrashPrinter(); 90193323Sed HandlerRegistered = HandlerRegistered; 91193323Sed 92193323Sed // Link ourselves. 93195098Sed NextEntry = PrettyStackTraceHead.get(); 94195098Sed PrettyStackTraceHead.set(this); 95193323Sed} 96193323Sed 97193323SedPrettyStackTraceEntry::~PrettyStackTraceEntry() { 98195098Sed assert(PrettyStackTraceHead.get() == this && 99193323Sed "Pretty stack trace entry destruction is out of order"); 100195098Sed PrettyStackTraceHead.set(getNextEntry()); 101193323Sed} 102193323Sed 103193323Sedvoid PrettyStackTraceString::print(raw_ostream &OS) const { 104193323Sed OS << Str << "\n"; 105193323Sed} 106193323Sed 107193323Sedvoid PrettyStackTraceProgram::print(raw_ostream &OS) const { 108193323Sed OS << "Program arguments: "; 109193323Sed // Print the argument list. 110193323Sed for (unsigned i = 0, e = ArgC; i != e; ++i) 111193323Sed OS << ArgV[i] << ' '; 112193323Sed OS << '\n'; 113193323Sed} 114193323Sed 115