1e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner//===- PrettyStackTrace.cpp - Pretty Crash Handling -----------------------===// 2e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner// 3e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner// The LLVM Compiler Infrastructure 4e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner// 5e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner// This file is distributed under the University of Illinois Open Source 6e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner// License. See LICENSE.TXT for details. 7e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner// 8e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner//===----------------------------------------------------------------------===// 9e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner// 10e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner// This file defines some helpful functions for dealing with the possibility of 117a2bdde0a0eebcd2125055e0eacaca040f0b766cChris Lattner// Unix signals occurring while your program is running. 12e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner// 13e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner//===----------------------------------------------------------------------===// 14e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner 15e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner#include "llvm/Support/PrettyStackTrace.h" 16d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/ADT/SmallString.h" 17d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Config/config.h" // Get autoconf configuration settings 181f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/Signals.h" 191f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/ThreadLocal.h" 20d5e1be03eda2e8036f136fdf12a5f5d9e1e684d8Nick Lewycky#include "llvm/Support/Watchdog.h" 21d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Support/raw_ostream.h" 22654dee487555a3cf21bcbca38ef5a2687fd18ea7Eric Christopher 23654dee487555a3cf21bcbca38ef5a2687fd18ea7Eric Christopher#ifdef HAVE_CRASHREPORTERCLIENT_H 24654dee487555a3cf21bcbca38ef5a2687fd18ea7Eric Christopher#include <CrashReporterClient.h> 25654dee487555a3cf21bcbca38ef5a2687fd18ea7Eric Christopher#endif 26654dee487555a3cf21bcbca38ef5a2687fd18ea7Eric Christopher 27e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattnerusing namespace llvm; 28e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner 2990bb3f3706cdf4e26df5e2c977d9232ba7b89c4eChris Lattnernamespace llvm { 3090bb3f3706cdf4e26df5e2c977d9232ba7b89c4eChris Lattner bool DisablePrettyStackTrace = false; 3190bb3f3706cdf4e26df5e2c977d9232ba7b89c4eChris Lattner} 3290bb3f3706cdf4e26df5e2c977d9232ba7b89c4eChris Lattner 33e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner// FIXME: This should be thread local when llvm supports threads. 340b49c32c56443a41f76c415bddc226488217da2fOwen Andersonstatic sys::ThreadLocal<const PrettyStackTraceEntry> PrettyStackTraceHead; 35e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner 36d56786f79a00fd47a805a17276853ffd9dc4e921Chris Lattnerstatic unsigned PrintStack(const PrettyStackTraceEntry *Entry, raw_ostream &OS){ 37d56786f79a00fd47a805a17276853ffd9dc4e921Chris Lattner unsigned NextID = 0; 38d56786f79a00fd47a805a17276853ffd9dc4e921Chris Lattner if (Entry->getNextEntry()) 39d56786f79a00fd47a805a17276853ffd9dc4e921Chris Lattner NextID = PrintStack(Entry->getNextEntry(), OS); 40d56786f79a00fd47a805a17276853ffd9dc4e921Chris Lattner OS << NextID << ".\t"; 41d5e1be03eda2e8036f136fdf12a5f5d9e1e684d8Nick Lewycky { 42d5e1be03eda2e8036f136fdf12a5f5d9e1e684d8Nick Lewycky sys::Watchdog W(5); 43d5e1be03eda2e8036f136fdf12a5f5d9e1e684d8Nick Lewycky Entry->print(OS); 44d5e1be03eda2e8036f136fdf12a5f5d9e1e684d8Nick Lewycky } 45d56786f79a00fd47a805a17276853ffd9dc4e921Chris Lattner 46d56786f79a00fd47a805a17276853ffd9dc4e921Chris Lattner return NextID+1; 47d56786f79a00fd47a805a17276853ffd9dc4e921Chris Lattner} 48d56786f79a00fd47a805a17276853ffd9dc4e921Chris Lattner 4949155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner/// PrintCurStackTrace - Print the current stack trace to the specified stream. 5049155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattnerstatic void PrintCurStackTrace(raw_ostream &OS) { 51d56786f79a00fd47a805a17276853ffd9dc4e921Chris Lattner // Don't print an empty trace. 520b49c32c56443a41f76c415bddc226488217da2fOwen Anderson if (PrettyStackTraceHead.get() == 0) return; 53d56786f79a00fd47a805a17276853ffd9dc4e921Chris Lattner 54e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner // If there are pretty stack frames registered, walk and emit them. 55e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner OS << "Stack dump:\n"; 56e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner 570b49c32c56443a41f76c415bddc226488217da2fOwen Anderson PrintStack(PrettyStackTraceHead.get(), OS); 58e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner OS.flush(); 59e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner} 60e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner 614411fbe25e9625ca4dd7c94aebc7ffd70b0e5bebEric Christopher// Integrate with crash reporter libraries. 62481d402ab03e163e180d2650fae13704858f8d81Eric Christopher#if defined (__APPLE__) && HAVE_CRASHREPORTERCLIENT_H 634411fbe25e9625ca4dd7c94aebc7ffd70b0e5bebEric Christopher// If any clients of llvm try to link to libCrashReporterClient.a themselves, 644411fbe25e9625ca4dd7c94aebc7ffd70b0e5bebEric Christopher// only one crash info struct will be used. 657d59a9766c1a48ea359e8014f9e7e7d01a57b593Eric Christopherextern "C" { 664411fbe25e9625ca4dd7c94aebc7ffd70b0e5bebEric ChristopherCRASH_REPORTER_CLIENT_HIDDEN 674411fbe25e9625ca4dd7c94aebc7ffd70b0e5bebEric Christopherstruct crashreporter_annotations_t gCRAnnotations 684411fbe25e9625ca4dd7c94aebc7ffd70b0e5bebEric Christopher __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION))) 69ce4984f86e910575e2bc7045189218466e00c93aEric Christopher = { CRASHREPORTER_ANNOTATIONS_VERSION, 0, 0, 0, 0, 0, 0 }; 707d59a9766c1a48ea359e8014f9e7e7d01a57b593Eric Christopher} 71481d402ab03e163e180d2650fae13704858f8d81Eric Christopher#elif defined (__APPLE__) && HAVE_CRASHREPORTER_INFO 724ef6730632f5e9e5958173b707230ff57b3c5dacDaniel Dunbarstatic const char *__crashreporter_info__ = 0; 734ef6730632f5e9e5958173b707230ff57b3c5dacDaniel Dunbarasm(".desc ___crashreporter_info__, 0x10"); 7449155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner#endif 7549155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner 7649155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner 7749155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner/// CrashHandler - This callback is run if a fatal signal is delivered to the 7849155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner/// process, it prints the pretty stack trace. 79371e5774c7cc4e78338d9da9dbcdcd9bb8785c1cEric Christopherstatic void CrashHandler(void *) { 8049155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner#ifndef __APPLE__ 8149155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner // On non-apple systems, just emit the crash stack trace to stderr. 8249155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner PrintCurStackTrace(errs()); 8349155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner#else 8449155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner // Otherwise, emit to a smallvector of chars, send *that* to stderr, but also 8549155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner // put it into __crashreporter_info__. 8649155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner SmallString<2048> TmpStr; 8749155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner { 8849155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner raw_svector_ostream Stream(TmpStr); 8949155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner PrintCurStackTrace(Stream); 9049155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner } 9149155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner 9249155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner if (!TmpStr.empty()) { 93481d402ab03e163e180d2650fae13704858f8d81Eric Christopher#ifdef HAVE_CRASHREPORTERCLIENT_H 94371e5774c7cc4e78338d9da9dbcdcd9bb8785c1cEric Christopher // Cast to void to avoid warning. 95371e5774c7cc4e78338d9da9dbcdcd9bb8785c1cEric Christopher (void)CRSetCrashLogMessage(std::string(TmpStr.str()).c_str()); 96481d402ab03e163e180d2650fae13704858f8d81Eric Christopher#elif HAVE_CRASHREPORTER_INFO 97481d402ab03e163e180d2650fae13704858f8d81Eric Christopher __crashreporter_info__ = strdup(std::string(TmpStr.str()).c_str()); 98654dee487555a3cf21bcbca38ef5a2687fd18ea7Eric Christopher#endif 99dddfd34e32ff081409e5a1c95b991a898d63dff2Daniel Dunbar errs() << TmpStr.str(); 10049155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner } 10149155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner 10249155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner#endif 10349155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner} 10449155ffababdc2102852fd3cd3988d800d12a5c6Chris Lattner 105e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattnerstatic bool RegisterCrashPrinter() { 10690bb3f3706cdf4e26df5e2c977d9232ba7b89c4eChris Lattner if (!DisablePrettyStackTrace) 10790bb3f3706cdf4e26df5e2c977d9232ba7b89c4eChris Lattner sys::AddSignalHandler(CrashHandler, 0); 108e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner return false; 109e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner} 110e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner 111e97c73354101507af0bc804c5c049a084c0c0c86Chris LattnerPrettyStackTraceEntry::PrettyStackTraceEntry() { 112e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner // The first time this is called, we register the crash printer. 113e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner static bool HandlerRegistered = RegisterCrashPrinter(); 1148e68c3873549ca31533e2e3e40dda3a43cb79566Jeffrey Yasskin (void)HandlerRegistered; 115e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner 116e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner // Link ourselves. 1170b49c32c56443a41f76c415bddc226488217da2fOwen Anderson NextEntry = PrettyStackTraceHead.get(); 1180b49c32c56443a41f76c415bddc226488217da2fOwen Anderson PrettyStackTraceHead.set(this); 119e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner} 120e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner 121e97c73354101507af0bc804c5c049a084c0c0c86Chris LattnerPrettyStackTraceEntry::~PrettyStackTraceEntry() { 1220b49c32c56443a41f76c415bddc226488217da2fOwen Anderson assert(PrettyStackTraceHead.get() == this && 123e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner "Pretty stack trace entry destruction is out of order"); 1240b49c32c56443a41f76c415bddc226488217da2fOwen Anderson PrettyStackTraceHead.set(getNextEntry()); 125e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner} 126e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner 127e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattnervoid PrettyStackTraceString::print(raw_ostream &OS) const { 128e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner OS << Str << "\n"; 129e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner} 130e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner 131e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattnervoid PrettyStackTraceProgram::print(raw_ostream &OS) const { 132fcba7cd630f0d974ae5ade4c1e74d6fc55e8764eChris Lattner OS << "Program arguments: "; 133e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner // Print the argument list. 134e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner for (unsigned i = 0, e = ArgC; i != e; ++i) 135e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner OS << ArgV[i] << ' '; 136e97c73354101507af0bc804c5c049a084c0c0c86Chris Lattner OS << '\n'; 137fcba7cd630f0d974ae5ade4c1e74d6fc55e8764eChris Lattner} 138