/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Support/PrettyStackTrace.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- PrettyStackTrace.cpp - Pretty Crash Handling -----------------------===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | // |
9 | | // This file defines some helpful functions for dealing with the possibility of |
10 | | // Unix signals occurring while your program is running. |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #include "llvm/Support/PrettyStackTrace.h" |
15 | | #include "llvm-c/ErrorHandling.h" |
16 | | #include "llvm/ADT/SmallString.h" |
17 | | #include "llvm/Config/config.h" |
18 | | #include "llvm/Support/Compiler.h" |
19 | | #include "llvm/Support/SaveAndRestore.h" |
20 | | #include "llvm/Support/Signals.h" |
21 | | #include "llvm/Support/Watchdog.h" |
22 | | #include "llvm/Support/raw_ostream.h" |
23 | | |
24 | | #include <atomic> |
25 | | #include <cstdarg> |
26 | | #include <cstdio> |
27 | | #include <tuple> |
28 | | |
29 | | #ifdef HAVE_CRASHREPORTERCLIENT_H |
30 | | #include <CrashReporterClient.h> |
31 | | #endif |
32 | | |
33 | | using namespace llvm; |
34 | | |
35 | | // If backtrace support is not enabled, compile out support for pretty stack |
36 | | // traces. This has the secondary effect of not requiring thread local storage |
37 | | // when backtrace support is disabled. |
38 | | #if ENABLE_BACKTRACES |
39 | | |
40 | | // We need a thread local pointer to manage the stack of our stack trace |
41 | | // objects, but we *really* cannot tolerate destructors running and do not want |
42 | | // to pay any overhead of synchronizing. As a consequence, we use a raw |
43 | | // thread-local variable. |
44 | | static LLVM_THREAD_LOCAL PrettyStackTraceEntry *PrettyStackTraceHead = nullptr; |
45 | | |
46 | | // The use of 'volatile' here is to ensure that any particular thread always |
47 | | // reloads the value of the counter. The 'std::atomic' allows us to specify that |
48 | | // this variable is accessed in an unsychronized way (it's not actually |
49 | | // synchronizing). This does technically mean that the value may not appear to |
50 | | // be the same across threads running simultaneously on different CPUs, but in |
51 | | // practice the worst that will happen is that we won't print a stack trace when |
52 | | // we could have. |
53 | | // |
54 | | // This is initialized to 1 because 0 is used as a sentinel for "not enabled on |
55 | | // the current thread". If the user happens to overflow an 'unsigned' with |
56 | | // SIGINFO requests, it's possible that some threads will stop responding to it, |
57 | | // but the program won't crash. |
58 | | static volatile std::atomic<unsigned> GlobalSigInfoGenerationCounter = |
59 | | ATOMIC_VAR_INIT(1); |
60 | | static LLVM_THREAD_LOCAL unsigned ThreadLocalSigInfoGenerationCounter = 0; |
61 | | |
62 | | namespace llvm { |
63 | 0 | PrettyStackTraceEntry *ReverseStackTrace(PrettyStackTraceEntry *Head) { |
64 | 0 | PrettyStackTraceEntry *Prev = nullptr; |
65 | 0 | while (Head) |
66 | 0 | std::tie(Prev, Head, Head->NextEntry) = |
67 | 0 | std::make_tuple(Head, Head->NextEntry, Prev); |
68 | 0 | return Prev; |
69 | 0 | } |
70 | | } |
71 | | |
72 | 0 | static void PrintStack(raw_ostream &OS) { |
73 | 0 | // Print out the stack in reverse order. To avoid recursion (which is likely |
74 | 0 | // to fail if we crashed due to stack overflow), we do an up-front pass to |
75 | 0 | // reverse the stack, then print it, then reverse it again. |
76 | 0 | unsigned ID = 0; |
77 | 0 | SaveAndRestore<PrettyStackTraceEntry *> SavedStack{PrettyStackTraceHead, |
78 | 0 | nullptr}; |
79 | 0 | PrettyStackTraceEntry *ReversedStack = ReverseStackTrace(SavedStack.get()); |
80 | 0 | for (const PrettyStackTraceEntry *Entry = ReversedStack; Entry; |
81 | 0 | Entry = Entry->getNextEntry()) { |
82 | 0 | OS << ID++ << ".\t"; |
83 | 0 | sys::Watchdog W(5); |
84 | 0 | Entry->print(OS); |
85 | 0 | } |
86 | 0 | llvm::ReverseStackTrace(ReversedStack); |
87 | 0 | } |
88 | | |
89 | | /// Print the current stack trace to the specified stream. |
90 | | /// |
91 | | /// Marked NOINLINE so it can be called from debuggers. |
92 | | LLVM_ATTRIBUTE_NOINLINE |
93 | 0 | static void PrintCurStackTrace(raw_ostream &OS) { |
94 | 0 | // Don't print an empty trace. |
95 | 0 | if (!PrettyStackTraceHead) return; |
96 | 0 | |
97 | 0 | // If there are pretty stack frames registered, walk and emit them. |
98 | 0 | OS << "Stack dump:\n"; |
99 | 0 |
|
100 | 0 | PrintStack(OS); |
101 | 0 | OS.flush(); |
102 | 0 | } |
103 | | |
104 | | // Integrate with crash reporter libraries. |
105 | | #if defined (__APPLE__) && defined(HAVE_CRASHREPORTERCLIENT_H) |
106 | | // If any clients of llvm try to link to libCrashReporterClient.a themselves, |
107 | | // only one crash info struct will be used. |
108 | | extern "C" { |
109 | | CRASH_REPORTER_CLIENT_HIDDEN |
110 | | struct crashreporter_annotations_t gCRAnnotations |
111 | | __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION))) |
112 | | #if CRASHREPORTER_ANNOTATIONS_VERSION < 5 |
113 | | = { CRASHREPORTER_ANNOTATIONS_VERSION, 0, 0, 0, 0, 0, 0 }; |
114 | | #else |
115 | | = { CRASHREPORTER_ANNOTATIONS_VERSION, 0, 0, 0, 0, 0, 0, 0 }; |
116 | | #endif |
117 | | } |
118 | | #elif defined(__APPLE__) && HAVE_CRASHREPORTER_INFO |
119 | | extern "C" const char *__crashreporter_info__ |
120 | | __attribute__((visibility("hidden"))) = 0; |
121 | | asm(".desc ___crashreporter_info__, 0x10"); |
122 | | #endif |
123 | | |
124 | | /// CrashHandler - This callback is run if a fatal signal is delivered to the |
125 | | /// process, it prints the pretty stack trace. |
126 | 0 | static void CrashHandler(void *) { |
127 | | #ifndef __APPLE__ |
128 | | // On non-apple systems, just emit the crash stack trace to stderr. |
129 | | PrintCurStackTrace(errs()); |
130 | | #else |
131 | | // Otherwise, emit to a smallvector of chars, send *that* to stderr, but also |
132 | 0 | // put it into __crashreporter_info__. |
133 | 0 | SmallString<2048> TmpStr; |
134 | 0 | { |
135 | 0 | raw_svector_ostream Stream(TmpStr); |
136 | 0 | PrintCurStackTrace(Stream); |
137 | 0 | } |
138 | 0 |
|
139 | 0 | if (!TmpStr.empty()) { |
140 | | #ifdef HAVE_CRASHREPORTERCLIENT_H |
141 | | // Cast to void to avoid warning. |
142 | | (void)CRSetCrashLogMessage(TmpStr.c_str()); |
143 | | #elif HAVE_CRASHREPORTER_INFO |
144 | | __crashreporter_info__ = strdup(TmpStr.c_str()); |
145 | 0 | #endif |
146 | 0 | errs() << TmpStr.str(); |
147 | 0 | } |
148 | 0 |
|
149 | 0 | #endif |
150 | 0 | } |
151 | | |
152 | 725M | static void printForSigInfoIfNeeded() { |
153 | 725M | unsigned CurrentSigInfoGeneration = |
154 | 725M | GlobalSigInfoGenerationCounter.load(std::memory_order_relaxed); |
155 | 725M | if (ThreadLocalSigInfoGenerationCounter == 0 || |
156 | 725M | ThreadLocalSigInfoGenerationCounter == CurrentSigInfoGeneration0 ) { |
157 | 725M | return; |
158 | 725M | } |
159 | 18.4E | |
160 | 18.4E | PrintCurStackTrace(errs()); |
161 | 18.4E | ThreadLocalSigInfoGenerationCounter = CurrentSigInfoGeneration; |
162 | 18.4E | } |
163 | | |
164 | | #endif // ENABLE_BACKTRACES |
165 | | |
166 | 362M | PrettyStackTraceEntry::PrettyStackTraceEntry() { |
167 | 362M | #if ENABLE_BACKTRACES |
168 | 362M | // Handle SIGINFO first, because we haven't finished constructing yet. |
169 | 362M | printForSigInfoIfNeeded(); |
170 | 362M | // Link ourselves. |
171 | 362M | NextEntry = PrettyStackTraceHead; |
172 | 362M | PrettyStackTraceHead = this; |
173 | 362M | #endif |
174 | 362M | } |
175 | | |
176 | 362M | PrettyStackTraceEntry::~PrettyStackTraceEntry() { |
177 | 362M | #if ENABLE_BACKTRACES |
178 | 362M | assert(PrettyStackTraceHead == this && |
179 | 362M | "Pretty stack trace entry destruction is out of order"); |
180 | 362M | PrettyStackTraceHead = NextEntry; |
181 | 362M | // Handle SIGINFO first, because we already started destructing. |
182 | 362M | printForSigInfoIfNeeded(); |
183 | 362M | #endif |
184 | 362M | } |
185 | | |
186 | 0 | void PrettyStackTraceString::print(raw_ostream &OS) const { OS << Str << "\n"; } |
187 | | |
188 | 0 | PrettyStackTraceFormat::PrettyStackTraceFormat(const char *Format, ...) { |
189 | 0 | va_list AP; |
190 | 0 | va_start(AP, Format); |
191 | 0 | const int SizeOrError = vsnprintf(nullptr, 0, Format, AP); |
192 | 0 | va_end(AP); |
193 | 0 | if (SizeOrError < 0) { |
194 | 0 | return; |
195 | 0 | } |
196 | 0 | |
197 | 0 | const int Size = SizeOrError + 1; // '\0' |
198 | 0 | Str.resize(Size); |
199 | 0 | va_start(AP, Format); |
200 | 0 | vsnprintf(Str.data(), Size, Format, AP); |
201 | 0 | va_end(AP); |
202 | 0 | } Unexecuted instantiation: llvm::PrettyStackTraceFormat::PrettyStackTraceFormat(char const*, ...) Unexecuted instantiation: llvm::PrettyStackTraceFormat::PrettyStackTraceFormat(char const*, ...) |
203 | | |
204 | 0 | void PrettyStackTraceFormat::print(raw_ostream &OS) const { OS << Str << "\n"; } |
205 | | |
206 | 0 | void PrettyStackTraceProgram::print(raw_ostream &OS) const { |
207 | 0 | OS << "Program arguments: "; |
208 | 0 | // Print the argument list. |
209 | 0 | for (unsigned i = 0, e = ArgC; i != e; ++i) |
210 | 0 | OS << ArgV[i] << ' '; |
211 | 0 | OS << '\n'; |
212 | 0 | } |
213 | | |
214 | | #if ENABLE_BACKTRACES |
215 | 128k | static bool RegisterCrashPrinter() { |
216 | 128k | sys::AddSignalHandler(CrashHandler, nullptr); |
217 | 128k | return false; |
218 | 128k | } |
219 | | #endif |
220 | | |
221 | 128k | void llvm::EnablePrettyStackTrace() { |
222 | 128k | #if ENABLE_BACKTRACES |
223 | 128k | // The first time this is called, we register the crash printer. |
224 | 128k | static bool HandlerRegistered = RegisterCrashPrinter(); |
225 | 128k | (void)HandlerRegistered; |
226 | 128k | #endif |
227 | 128k | } |
228 | | |
229 | 0 | void llvm::EnablePrettyStackTraceOnSigInfoForThisThread(bool ShouldEnable) { |
230 | 0 | #if ENABLE_BACKTRACES |
231 | 0 | if (!ShouldEnable) { |
232 | 0 | ThreadLocalSigInfoGenerationCounter = 0; |
233 | 0 | return; |
234 | 0 | } |
235 | 0 | |
236 | 0 | // The first time this is called, we register the SIGINFO handler. |
237 | 0 | static bool HandlerRegistered = []{ |
238 | 0 | sys::SetInfoSignalFunction([]{ |
239 | 0 | GlobalSigInfoGenerationCounter.fetch_add(1, std::memory_order_relaxed); |
240 | 0 | }); |
241 | 0 | return false; |
242 | 0 | }(); |
243 | 0 | (void)HandlerRegistered; |
244 | 0 |
|
245 | 0 | // Next, enable it for the current thread. |
246 | 0 | ThreadLocalSigInfoGenerationCounter = |
247 | 0 | GlobalSigInfoGenerationCounter.load(std::memory_order_relaxed); |
248 | 0 | #endif |
249 | 0 | } |
250 | | |
251 | 41.4k | const void *llvm::SavePrettyStackState() { |
252 | 41.4k | #if ENABLE_BACKTRACES |
253 | 41.4k | return PrettyStackTraceHead; |
254 | | #else |
255 | | return nullptr; |
256 | | #endif |
257 | | } |
258 | | |
259 | 0 | void llvm::RestorePrettyStackState(const void *Top) { |
260 | 0 | #if ENABLE_BACKTRACES |
261 | 0 | PrettyStackTraceHead = |
262 | 0 | static_cast<PrettyStackTraceEntry *>(const_cast<void *>(Top)); |
263 | 0 | #endif |
264 | 0 | } |
265 | | |
266 | 7 | void LLVMEnablePrettyStackTrace() { |
267 | 7 | EnablePrettyStackTrace(); |
268 | 7 | } |