/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/Support/PrettyStackTrace.cpp
Line | Count | Source (jump to first uncovered line) |
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 occurring while your program is running. |
12 | | // |
13 | | //===----------------------------------------------------------------------===// |
14 | | |
15 | | #include "llvm/Support/PrettyStackTrace.h" |
16 | | #include "llvm-c/ErrorHandling.h" |
17 | | #include "llvm/ADT/SmallString.h" |
18 | | #include "llvm/Config/config.h" // Get autoconf configuration settings |
19 | | #include "llvm/Support/Compiler.h" |
20 | | #include "llvm/Support/Signals.h" |
21 | | #include "llvm/Support/Watchdog.h" |
22 | | #include "llvm/Support/raw_ostream.h" |
23 | | |
24 | | #include <cstdarg> |
25 | | #include <cstdio> |
26 | | #include <tuple> |
27 | | |
28 | | #ifdef HAVE_CRASHREPORTERCLIENT_H |
29 | | #include <CrashReporterClient.h> |
30 | | #endif |
31 | | |
32 | | using namespace llvm; |
33 | | |
34 | | // If backtrace support is not enabled, compile out support for pretty stack |
35 | | // traces. This has the secondary effect of not requiring thread local storage |
36 | | // when backtrace support is disabled. |
37 | | #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES |
38 | | |
39 | | // We need a thread local pointer to manage the stack of our stack trace |
40 | | // objects, but we *really* cannot tolerate destructors running and do not want |
41 | | // to pay any overhead of synchronizing. As a consequence, we use a raw |
42 | | // thread-local variable. |
43 | | static LLVM_THREAD_LOCAL PrettyStackTraceEntry *PrettyStackTraceHead = nullptr; |
44 | | |
45 | | namespace llvm { |
46 | 0 | PrettyStackTraceEntry *ReverseStackTrace(PrettyStackTraceEntry *Head) { |
47 | 0 | PrettyStackTraceEntry *Prev = nullptr; |
48 | 0 | while (Head) |
49 | 0 | std::tie(Prev, Head, Head->NextEntry) = |
50 | 0 | std::make_tuple(Head, Head->NextEntry, Prev); |
51 | 0 | return Prev; |
52 | 0 | } |
53 | | } |
54 | | |
55 | 0 | static void PrintStack(raw_ostream &OS) { |
56 | 0 | // Print out the stack in reverse order. To avoid recursion (which is likely |
57 | 0 | // to fail if we crashed due to stack overflow), we do an up-front pass to |
58 | 0 | // reverse the stack, then print it, then reverse it again. |
59 | 0 | unsigned ID = 0; |
60 | 0 | PrettyStackTraceEntry *ReversedStack = |
61 | 0 | llvm::ReverseStackTrace(PrettyStackTraceHead); |
62 | 0 | for (const PrettyStackTraceEntry *Entry = ReversedStack; Entry; |
63 | 0 | Entry = Entry->getNextEntry()0 ) { |
64 | 0 | OS << ID++ << ".\t"; |
65 | 0 | sys::Watchdog W(5); |
66 | 0 | Entry->print(OS); |
67 | 0 | } |
68 | 0 | llvm::ReverseStackTrace(ReversedStack); |
69 | 0 | } |
70 | | |
71 | | /// PrintCurStackTrace - Print the current stack trace to the specified stream. |
72 | 0 | static void PrintCurStackTrace(raw_ostream &OS) { |
73 | 0 | // Don't print an empty trace. |
74 | 0 | if (!PrettyStackTraceHead0 ) return0 ; |
75 | 0 | |
76 | 0 | // If there are pretty stack frames registered, walk and emit them. |
77 | 0 | OS << "Stack dump:\n"; |
78 | 0 | |
79 | 0 | PrintStack(OS); |
80 | 0 | OS.flush(); |
81 | 0 | } |
82 | | |
83 | | // Integrate with crash reporter libraries. |
84 | | #if defined (__APPLE__) && defined(HAVE_CRASHREPORTERCLIENT_H) |
85 | | // If any clients of llvm try to link to libCrashReporterClient.a themselves, |
86 | | // only one crash info struct will be used. |
87 | | extern "C" { |
88 | | CRASH_REPORTER_CLIENT_HIDDEN |
89 | | struct crashreporter_annotations_t gCRAnnotations |
90 | | __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION))) |
91 | | = { CRASHREPORTER_ANNOTATIONS_VERSION, 0, 0, 0, 0, 0, 0 }; |
92 | | } |
93 | | #elif defined(__APPLE__) && HAVE_CRASHREPORTER_INFO |
94 | | extern "C" const char *__crashreporter_info__ |
95 | | __attribute__((visibility("hidden"))) = 0; |
96 | | asm(".desc ___crashreporter_info__, 0x10"); |
97 | | #endif |
98 | | |
99 | | /// CrashHandler - This callback is run if a fatal signal is delivered to the |
100 | | /// process, it prints the pretty stack trace. |
101 | 0 | static void CrashHandler(void *) { |
102 | | #ifndef __APPLE__ |
103 | | // On non-apple systems, just emit the crash stack trace to stderr. |
104 | | PrintCurStackTrace(errs()); |
105 | | #else |
106 | | // Otherwise, emit to a smallvector of chars, send *that* to stderr, but also |
107 | 0 | // put it into __crashreporter_info__. |
108 | 0 | SmallString<2048> TmpStr; |
109 | 0 | { |
110 | 0 | raw_svector_ostream Stream(TmpStr); |
111 | 0 | PrintCurStackTrace(Stream); |
112 | 0 | } |
113 | 0 | |
114 | 0 | if (!TmpStr.empty()0 ) { |
115 | | #ifdef HAVE_CRASHREPORTERCLIENT_H |
116 | | // Cast to void to avoid warning. |
117 | | (void)CRSetCrashLogMessage(std::string(TmpStr.str()).c_str()); |
118 | | #elif HAVE_CRASHREPORTER_INFO |
119 | | __crashreporter_info__ = strdup(std::string(TmpStr.str()).c_str()); |
120 | 0 | #endif |
121 | 0 | errs() << TmpStr.str(); |
122 | 0 | } |
123 | 0 | |
124 | 0 | #endif |
125 | 0 | } |
126 | | |
127 | | // defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES |
128 | | #endif |
129 | | |
130 | 399M | PrettyStackTraceEntry::PrettyStackTraceEntry() { |
131 | 399M | #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES |
132 | 399M | // Link ourselves. |
133 | 399M | NextEntry = PrettyStackTraceHead; |
134 | 399M | PrettyStackTraceHead = this; |
135 | 399M | #endif |
136 | 399M | } |
137 | | |
138 | 399M | PrettyStackTraceEntry::~PrettyStackTraceEntry() { |
139 | 399M | #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES |
140 | 399M | assert(PrettyStackTraceHead == this && |
141 | 399M | "Pretty stack trace entry destruction is out of order"); |
142 | 399M | PrettyStackTraceHead = NextEntry; |
143 | 399M | #endif |
144 | 399M | } |
145 | | |
146 | 0 | void PrettyStackTraceString::print(raw_ostream &OS) const { OS << Str << "\n"; } |
147 | | |
148 | 0 | PrettyStackTraceFormat::PrettyStackTraceFormat(const char *Format, ...) { |
149 | 0 | va_list AP; |
150 | 0 | va_start(AP, Format); |
151 | 0 | const int SizeOrError = vsnprintf(nullptr, 0, Format, AP); |
152 | 0 | va_end(AP); |
153 | 0 | if (SizeOrError < 00 ) { |
154 | 0 | return; |
155 | 0 | } |
156 | 0 |
|
157 | 0 | const int Size = SizeOrError + 1; // '\0' |
158 | 0 | Str.resize(Size); |
159 | 0 | va_start(AP, Format); |
160 | 0 | vsnprintf(Str.data(), Size, Format, AP); |
161 | 0 | va_end(AP); |
162 | 0 | } Unexecuted instantiation: llvm::PrettyStackTraceFormat::PrettyStackTraceFormat(char const*, ...) Unexecuted instantiation: llvm::PrettyStackTraceFormat::PrettyStackTraceFormat(char const*, ...) |
163 | | |
164 | 0 | void PrettyStackTraceFormat::print(raw_ostream &OS) const { OS << Str << "\n"; } |
165 | | |
166 | 0 | void PrettyStackTraceProgram::print(raw_ostream &OS) const { |
167 | 0 | OS << "Program arguments: "; |
168 | 0 | // Print the argument list. |
169 | 0 | for (unsigned i = 0, e = ArgC; i != e0 ; ++i0 ) |
170 | 0 | OS << ArgV[i] << ' '; |
171 | 0 | OS << '\n'; |
172 | 0 | } |
173 | | |
174 | | #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES |
175 | 102k | static bool RegisterCrashPrinter() { |
176 | 102k | sys::AddSignalHandler(CrashHandler, nullptr); |
177 | 102k | return false; |
178 | 102k | } |
179 | | #endif |
180 | | |
181 | 102k | void llvm::EnablePrettyStackTrace() { |
182 | 102k | #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES |
183 | 102k | // The first time this is called, we register the crash printer. |
184 | 102k | static bool HandlerRegistered = RegisterCrashPrinter(); |
185 | 102k | (void)HandlerRegistered; |
186 | 102k | #endif |
187 | 102k | } |
188 | | |
189 | 29.4k | const void *llvm::SavePrettyStackState() { |
190 | 29.4k | #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES |
191 | 29.4k | return PrettyStackTraceHead; |
192 | | #else |
193 | | return nullptr; |
194 | | #endif |
195 | | } |
196 | | |
197 | 0 | void llvm::RestorePrettyStackState(const void *Top) { |
198 | 0 | #if defined(HAVE_BACKTRACE) && ENABLE_BACKTRACES |
199 | 0 | PrettyStackTraceHead = |
200 | 0 | static_cast<PrettyStackTraceEntry *>(const_cast<void *>(Top)); |
201 | 0 | #endif |
202 | 0 | } |
203 | | |
204 | 7 | void LLVMEnablePrettyStackTrace() { |
205 | 7 | EnablePrettyStackTrace(); |
206 | 7 | } |