llvm.org GIT mirror llvm / e97c733
add some helper classes for building light-weight symbolic stack traces that get printed when a program crashes. This is the first step of many. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@66076 91177308-0d34-0410-b5e6-96231b3b80d8 Chris Lattner 11 years ago
2 changed file(s) with 134 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0 //===- llvm/Support/PrettyStackTrace.h - Pretty Crash Handling --*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the PrettyStackTraceEntry class, which is used to make
10 // crashes give more contextual information about what the program was doing
11 // when it crashed.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #ifndef LLVM_SUPPORT_PRETTYSTACKTRACE_H
16 #define LLVM_SUPPORT_PRETTYSTACKTRACE_H
17
18 namespace llvm {
19 class raw_ostream;
20
21 /// PrettyStackTraceEntry - This class is used to represent a frame of the
22 /// "pretty" stack trace that is dumped when a program crashes. You can define
23 /// subclasses of this and declare them on the program stack: when they are
24 /// constructed and destructed, they will add their symbolic frames to a
25 /// virtual stack trace. This gets dumped out if the program crashes.
26 class PrettyStackTraceEntry {
27 const PrettyStackTraceEntry *NextEntry;
28 PrettyStackTraceEntry(const PrettyStackTraceEntry &); // DO NOT IMPLEMENT
29 void operator=(const PrettyStackTraceEntry&); // DO NOT IMPLEMENT
30 public:
31 PrettyStackTraceEntry();
32 virtual ~PrettyStackTraceEntry();
33
34 /// print - Emit information about this stack frame to OS.
35 virtual void print(raw_ostream &OS) const = 0;
36
37 /// getNextEntry - Return the next entry in the list of frames.
38 const PrettyStackTraceEntry *getNextEntry() const { return NextEntry; }
39 };
40
41 /// PrettyStackTraceString - This object prints a specified string (which
42 /// should not contain newlines) to the stream as the stack trace when a crash
43 /// occurs.
44 class PrettyStackTraceString : public PrettyStackTraceEntry {
45 const char *Str;
46 public:
47 PrettyStackTraceString(const char *str) : Str(str) {}
48 virtual void print(raw_ostream &OS) const;
49 };
50
51 /// PrettyStackTraceProgram - This object prints a specified program arguments
52 /// to the stream as the stack trace when a crash occurs.
53 class PrettyStackTraceProgram : public PrettyStackTraceEntry {
54 int ArgC;
55 const char *const *ArgV;
56 public:
57 PrettyStackTraceProgram(int argc, const char * const*argv)
58 : ArgC(argc), ArgV(argv) {}
59 virtual void print(raw_ostream &OS) const;
60 };
61
62 } // end namespace llvm
63
64 #endif
0 //===- PrettyStackTrace.cpp - Pretty Crash Handling -----------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines some helpful functions for dealing with the possibility of
10 // Unix signals occuring while your program is running.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/Support/PrettyStackTrace.h"
15 #include "llvm/Support/raw_ostream.h"
16 #include "llvm/System/Signals.h"
17 using namespace llvm;
18
19 // FIXME: This should be thread local when llvm supports threads.
20 static const PrettyStackTraceEntry *PrettyStackTraceHead = 0;
21
22 /// CrashHandler - This callback is run if a fatal signal is delivered to the
23 /// process, it prints the pretty stack trace.
24 static void CrashHandler(void *Cookie) {
25 // If there are pretty stack frames registered, walk and emit them.
26 raw_ostream &OS = errs();
27 OS << "Stack dump:\n";
28
29 unsigned i = 0;
30 for (const PrettyStackTraceEntry *Entry = PrettyStackTraceHead; Entry;
31 Entry = Entry->getNextEntry(), ++i) {
32 OS << i << ".\t";
33 Entry->print(OS);
34 }
35 OS.flush();
36 }
37
38 static bool RegisterCrashPrinter() {
39 sys::AddSignalHandler(CrashHandler, 0);
40 return false;
41 }
42
43 PrettyStackTraceEntry::PrettyStackTraceEntry() {
44 // The first time this is called, we register the crash printer.
45 static bool HandlerRegistered = RegisterCrashPrinter();
46 HandlerRegistered = HandlerRegistered;
47
48 // Link ourselves.
49 NextEntry = PrettyStackTraceHead;
50 PrettyStackTraceHead = this;
51 }
52
53 PrettyStackTraceEntry::~PrettyStackTraceEntry() {
54 assert(PrettyStackTraceHead == this &&
55 "Pretty stack trace entry destruction is out of order");
56 PrettyStackTraceHead = getNextEntry();
57 }
58
59 void PrettyStackTraceString::print(raw_ostream &OS) const {
60 OS << Str << "\n";
61 }
62
63 void PrettyStackTraceProgram::print(raw_ostream &OS) const {
64 // Print the argument list.
65 for (unsigned i = 0, e = ArgC; i != e; ++i)
66 OS << ArgV[i] << ' ';
67 OS << '\n';
68 }