~ubuntu-branches/ubuntu/feisty/clamav/feisty

« back to all changes in this revision

Viewing changes to libclamav/c++/llvm/lib/Support/PrettyStackTrace.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Kees Cook
  • Date: 2007-02-20 10:33:44 UTC
  • mto: This revision was merged to the branch mainline in revision 16.
  • Revision ID: james.westby@ubuntu.com-20070220103344-zgcu2psnx9d98fpa
Tags: upstream-0.90
ImportĀ upstreamĀ versionĀ 0.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
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 occuring while your program is running.
12
 
//
13
 
//===----------------------------------------------------------------------===//
14
 
 
15
 
#include "llvm/Config/config.h"     // Get autoconf configuration settings
16
 
#include "llvm/Support/PrettyStackTrace.h"
17
 
#include "llvm/Support/raw_ostream.h"
18
 
#include "llvm/System/Signals.h"
19
 
#include "llvm/System/ThreadLocal.h"
20
 
#include "llvm/ADT/SmallString.h"
21
 
 
22
 
#ifdef HAVE_CRASHREPORTERCLIENT_H
23
 
#include <CrashReporterClient.h>
24
 
#endif
25
 
 
26
 
using namespace llvm;
27
 
 
28
 
namespace llvm {
29
 
  bool DisablePrettyStackTrace = false;
30
 
}
31
 
 
32
 
// FIXME: This should be thread local when llvm supports threads.
33
 
static sys::ThreadLocal<const PrettyStackTraceEntry> PrettyStackTraceHead;
34
 
 
35
 
static unsigned PrintStack(const PrettyStackTraceEntry *Entry, raw_ostream &OS){
36
 
  unsigned NextID = 0;
37
 
  if (Entry->getNextEntry())
38
 
    NextID = PrintStack(Entry->getNextEntry(), OS);
39
 
  OS << NextID << ".\t";
40
 
  Entry->print(OS);
41
 
  
42
 
  return NextID+1;
43
 
}
44
 
 
45
 
/// PrintCurStackTrace - Print the current stack trace to the specified stream.
46
 
static void PrintCurStackTrace(raw_ostream &OS) {
47
 
  // Don't print an empty trace.
48
 
  if (PrettyStackTraceHead.get() == 0) return;
49
 
  
50
 
  // If there are pretty stack frames registered, walk and emit them.
51
 
  OS << "Stack dump:\n";
52
 
  
53
 
  PrintStack(PrettyStackTraceHead.get(), OS);
54
 
  OS.flush();
55
 
}
56
 
 
57
 
// Integrate with crash reporter libraries.
58
 
#if defined (__APPLE__) && HAVE_CRASHREPORTERCLIENT_H
59
 
//  If any clients of llvm try to link to libCrashReporterClient.a themselves,
60
 
//  only one crash info struct will be used.
61
 
extern "C" {
62
 
CRASH_REPORTER_CLIENT_HIDDEN 
63
 
struct crashreporter_annotations_t gCRAnnotations 
64
 
        __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION))) 
65
 
        = { CRASHREPORTER_ANNOTATIONS_VERSION, 0, 0, 0, 0 };
66
 
}
67
 
#elif defined (__APPLE__) && HAVE_CRASHREPORTER_INFO
68
 
static const char *__crashreporter_info__ = 0;
69
 
asm(".desc ___crashreporter_info__, 0x10");
70
 
#endif
71
 
 
72
 
 
73
 
/// CrashHandler - This callback is run if a fatal signal is delivered to the
74
 
/// process, it prints the pretty stack trace.
75
 
static void CrashHandler(void *) {
76
 
#ifndef __APPLE__
77
 
  // On non-apple systems, just emit the crash stack trace to stderr.
78
 
  PrintCurStackTrace(errs());
79
 
#else
80
 
  // Otherwise, emit to a smallvector of chars, send *that* to stderr, but also
81
 
  // put it into __crashreporter_info__.
82
 
  SmallString<2048> TmpStr;
83
 
  {
84
 
    raw_svector_ostream Stream(TmpStr);
85
 
    PrintCurStackTrace(Stream);
86
 
  }
87
 
  
88
 
  if (!TmpStr.empty()) {
89
 
#ifdef HAVE_CRASHREPORTERCLIENT_H
90
 
    // Cast to void to avoid warning.
91
 
    (void)CRSetCrashLogMessage(std::string(TmpStr.str()).c_str());
92
 
#elif HAVE_CRASHREPORTER_INFO 
93
 
    __crashreporter_info__ = strdup(std::string(TmpStr.str()).c_str());
94
 
#endif
95
 
    errs() << TmpStr.str();
96
 
  }
97
 
  
98
 
#endif
99
 
}
100
 
 
101
 
static bool RegisterCrashPrinter() {
102
 
  if (!DisablePrettyStackTrace)
103
 
    sys::AddSignalHandler(CrashHandler, 0);
104
 
  return false;
105
 
}
106
 
 
107
 
PrettyStackTraceEntry::PrettyStackTraceEntry() {
108
 
  // The first time this is called, we register the crash printer.
109
 
  static bool HandlerRegistered = RegisterCrashPrinter();
110
 
  HandlerRegistered = HandlerRegistered;
111
 
    
112
 
  // Link ourselves.
113
 
  NextEntry = PrettyStackTraceHead.get();
114
 
  PrettyStackTraceHead.set(this);
115
 
}
116
 
 
117
 
PrettyStackTraceEntry::~PrettyStackTraceEntry() {
118
 
  assert(PrettyStackTraceHead.get() == this &&
119
 
         "Pretty stack trace entry destruction is out of order");
120
 
  PrettyStackTraceHead.set(getNextEntry());
121
 
}
122
 
 
123
 
void PrettyStackTraceString::print(raw_ostream &OS) const {
124
 
  OS << Str << "\n";
125
 
}
126
 
 
127
 
void PrettyStackTraceProgram::print(raw_ostream &OS) const {
128
 
  OS << "Program arguments: ";
129
 
  // Print the argument list.
130
 
  for (unsigned i = 0, e = ArgC; i != e; ++i)
131
 
    OS << ArgV[i] << ' ';
132
 
  OS << '\n';
133
 
}
134