/home/arjun/llvm-project/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 <cassert> |
26 | | #include <cstdarg> |
27 | | #include <cstdio> |
28 | | #include <tuple> |
29 | | |
30 | | #ifdef HAVE_CRASHREPORTERCLIENT_H |
31 | | #include <CrashReporterClient.h> |
32 | | #endif |
33 | | |
34 | | using namespace llvm; |
35 | | |
36 | | // If backtrace support is not enabled, compile out support for pretty stack |
37 | | // traces. This has the secondary effect of not requiring thread local storage |
38 | | // when backtrace support is disabled. |
39 | | #if ENABLE_BACKTRACES |
40 | | |
41 | | // We need a thread local pointer to manage the stack of our stack trace |
42 | | // objects, but we *really* cannot tolerate destructors running and do not want |
43 | | // to pay any overhead of synchronizing. As a consequence, we use a raw |
44 | | // thread-local variable. |
45 | | static LLVM_THREAD_LOCAL PrettyStackTraceEntry *PrettyStackTraceHead = nullptr; |
46 | | |
47 | | // The use of 'volatile' here is to ensure that any particular thread always |
48 | | // reloads the value of the counter. The 'std::atomic' allows us to specify that |
49 | | // this variable is accessed in an unsychronized way (it's not actually |
50 | | // synchronizing). This does technically mean that the value may not appear to |
51 | | // be the same across threads running simultaneously on different CPUs, but in |
52 | | // practice the worst that will happen is that we won't print a stack trace when |
53 | | // we could have. |
54 | | // |
55 | | // This is initialized to 1 because 0 is used as a sentinel for "not enabled on |
56 | | // the current thread". If the user happens to overflow an 'unsigned' with |
57 | | // SIGINFO requests, it's possible that some threads will stop responding to it, |
58 | | // but the program won't crash. |
59 | | static volatile std::atomic<unsigned> GlobalSigInfoGenerationCounter = |
60 | | ATOMIC_VAR_INIT(1); |
61 | | static LLVM_THREAD_LOCAL unsigned ThreadLocalSigInfoGenerationCounter = 0; |
62 | | |
63 | | namespace llvm { |
64 | 0 | PrettyStackTraceEntry *ReverseStackTrace(PrettyStackTraceEntry *Head) { |
65 | 0 | PrettyStackTraceEntry *Prev = nullptr; |
66 | 0 | while (Head) |
67 | 0 | std::tie(Prev, Head, Head->NextEntry) = |
68 | 0 | std::make_tuple(Head, Head->NextEntry, Prev); |
69 | 0 | return Prev; |
70 | 0 | } |
71 | | } |
72 | | |
73 | 0 | static void PrintStack(raw_ostream &OS) { |
74 | 0 | // Print out the stack in reverse order. To avoid recursion (which is likely |
75 | 0 | // to fail if we crashed due to stack overflow), we do an up-front pass to |
76 | 0 | // reverse the stack, then print it, then reverse it again. |
77 | 0 | unsigned ID = 0; |
78 | 0 | SaveAndRestore<PrettyStackTraceEntry *> SavedStack{PrettyStackTraceHead, |
79 | 0 | nullptr}; |
80 | 0 | PrettyStackTraceEntry *ReversedStack = ReverseStackTrace(SavedStack.get()); |
81 | 0 | for (const PrettyStackTraceEntry *Entry = ReversedStack; Entry; |
82 | 0 | Entry = Entry->getNextEntry()) { |
83 | 0 | OS << ID++ << ".\t"; |
84 | 0 | sys::Watchdog W(5); |
85 | 0 | Entry->print(OS); |
86 | 0 | } |
87 | 0 | llvm::ReverseStackTrace(ReversedStack); |
88 | 0 | } |
89 | | |
90 | | /// Print the current stack trace to the specified stream. |
91 | | /// |
92 | | /// Marked NOINLINE so it can be called from debuggers. |
93 | | LLVM_ATTRIBUTE_NOINLINE |
94 | 0 | static void PrintCurStackTrace(raw_ostream &OS) { |
95 | 0 | // Don't print an empty trace. |
96 | 0 | if (!PrettyStackTraceHead) return; |
97 | 0 | |
98 | 0 | // If there are pretty stack frames registered, walk and emit them. |
99 | 0 | OS << "Stack dump:\n"; |
100 | 0 |
|
101 | 0 | PrintStack(OS); |
102 | 0 | OS.flush(); |
103 | 0 | } |
104 | | |
105 | | // Integrate with crash reporter libraries. |
106 | | #if defined (__APPLE__) && defined(HAVE_CRASHREPORTERCLIENT_H) |
107 | | // If any clients of llvm try to link to libCrashReporterClient.a themselves, |
108 | | // only one crash info struct will be used. |
109 | | extern "C" { |
110 | | CRASH_REPORTER_CLIENT_HIDDEN |
111 | | struct crashreporter_annotations_t gCRAnnotations |
112 | | __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION))) |
113 | | #if CRASHREPORTER_ANNOTATIONS_VERSION < 5 |
114 | | = { CRASHREPORTER_ANNOTATIONS_VERSION, 0, 0, 0, 0, 0, 0 }; |
115 | | #else |
116 | | = { CRASHREPORTER_ANNOTATIONS_VERSION, 0, 0, 0, 0, 0, 0, 0 }; |
117 | | #endif |
118 | | } |
119 | | #elif defined(__APPLE__) && HAVE_CRASHREPORTER_INFO |
120 | | extern "C" const char *__crashreporter_info__ |
121 | | __attribute__((visibility("hidden"))) = 0; |
122 | | asm(".desc ___crashreporter_info__, 0x10"); |
123 | | #endif |
124 | | |
125 | | static void setCrashLogMessage(const char *msg) LLVM_ATTRIBUTE_UNUSED; |
126 | 0 | static void setCrashLogMessage(const char *msg) { |
127 | 0 | #ifdef HAVE_CRASHREPORTERCLIENT_H |
128 | 0 | (void)CRSetCrashLogMessage(msg); |
129 | 0 | #elif HAVE_CRASHREPORTER_INFO |
130 | 0 | __crashreporter_info__ = msg; |
131 | 0 | #endif |
132 | 0 | // Don't reorder subsequent operations: whatever comes after might crash and |
133 | 0 | // we want the system crash handling to see the message we just set. |
134 | 0 | std::atomic_signal_fence(std::memory_order_seq_cst); |
135 | 0 | } |
136 | | |
137 | | #ifdef __APPLE__ |
138 | | using CrashHandlerString = SmallString<2048>; |
139 | | using CrashHandlerStringStorage = |
140 | | std::aligned_storage<sizeof(CrashHandlerString), |
141 | | alignof(CrashHandlerString)>::type; |
142 | | static CrashHandlerStringStorage crashHandlerStringStorage; |
143 | | #endif |
144 | | |
145 | | static const char *BugReportMsg = |
146 | | "PLEASE submit a bug report to " BUG_REPORT_URL |
147 | | " and include the crash backtrace.\n"; |
148 | | |
149 | | /// This callback is run if a fatal signal is delivered to the process, it |
150 | | /// prints the pretty stack trace. |
151 | 0 | static void CrashHandler(void *) { |
152 | 0 | errs() << BugReportMsg ; |
153 | 0 |
|
154 | 0 | #ifndef __APPLE__ |
155 | 0 | // On non-apple systems, just emit the crash stack trace to stderr. |
156 | 0 | PrintCurStackTrace(errs()); |
157 | | #else |
158 | | // Emit the crash stack trace to a SmallString, put it where the system crash |
159 | | // handling will find it, and also send it to stderr. |
160 | | // |
161 | | // The SmallString is fairly large in the hope that we don't allocate (we're |
162 | | // handling a fatal signal, something is already pretty wrong, allocation |
163 | | // might not work). Further, we don't use a magic static in case that's also |
164 | | // borked. We leak any allocation that does occur because the program is about |
165 | | // to die anyways. This is technically racy if we were handling two fatal |
166 | | // signals, however if we're in that situation a race is the least of our |
167 | | // worries. |
168 | | auto &crashHandlerString = |
169 | | *new (&crashHandlerStringStorage) CrashHandlerString; |
170 | | |
171 | | // If we crash while trying to print the stack trace, we still want the system |
172 | | // crash handling to have some partial information. That'll work out as long |
173 | | // as the SmallString doesn't allocate. If it does allocate then the system |
174 | | // crash handling will see some garbage because the inline buffer now contains |
175 | | // a pointer. |
176 | | setCrashLogMessage(crashHandlerString.c_str()); |
177 | | |
178 | | { |
179 | | raw_svector_ostream Stream(crashHandlerString); |
180 | | PrintCurStackTrace(Stream); |
181 | | } |
182 | | |
183 | | if (!crashHandlerString.empty()) { |
184 | | setCrashLogMessage(crashHandlerString.c_str()); |
185 | | errs() << crashHandlerString.str(); |
186 | | } else |
187 | | setCrashLogMessage("No crash information."); |
188 | | #endif |
189 | | } |
190 | | |
191 | 0 | static void printForSigInfoIfNeeded() { |
192 | 0 | unsigned CurrentSigInfoGeneration = |
193 | 0 | GlobalSigInfoGenerationCounter.load(std::memory_order_relaxed); |
194 | 0 | if (ThreadLocalSigInfoGenerationCounter == 0 || |
195 | 0 | ThreadLocalSigInfoGenerationCounter == CurrentSigInfoGeneration) { |
196 | 0 | return; |
197 | 0 | } |
198 | 0 | |
199 | 0 | PrintCurStackTrace(errs()); |
200 | 0 | ThreadLocalSigInfoGenerationCounter = CurrentSigInfoGeneration; |
201 | 0 | } |
202 | | |
203 | | #endif // ENABLE_BACKTRACES |
204 | | |
205 | 0 | void llvm::setBugReportMsg(const char *Msg) { |
206 | 0 | #if ENABLE_BACKTRACES |
207 | 0 | BugReportMsg = Msg; |
208 | 0 | #endif |
209 | 0 | } |
210 | | |
211 | 0 | PrettyStackTraceEntry::PrettyStackTraceEntry() { |
212 | 0 | #if ENABLE_BACKTRACES |
213 | 0 | // Handle SIGINFO first, because we haven't finished constructing yet. |
214 | 0 | printForSigInfoIfNeeded(); |
215 | 0 | // Link ourselves. |
216 | 0 | NextEntry = PrettyStackTraceHead; |
217 | 0 | PrettyStackTraceHead = this; |
218 | 0 | #endif |
219 | 0 | } |
220 | | |
221 | 0 | PrettyStackTraceEntry::~PrettyStackTraceEntry() { |
222 | 0 | #if ENABLE_BACKTRACES |
223 | 0 | assert(PrettyStackTraceHead == this && |
224 | 0 | "Pretty stack trace entry destruction is out of order"); |
225 | 0 | PrettyStackTraceHead = NextEntry; |
226 | 0 | // Handle SIGINFO first, because we already started destructing. |
227 | 0 | printForSigInfoIfNeeded(); |
228 | 0 | #endif |
229 | 0 | } |
230 | | |
231 | 0 | void PrettyStackTraceString::print(raw_ostream &OS) const { OS << Str << "\n"; } |
232 | | |
233 | 0 | PrettyStackTraceFormat::PrettyStackTraceFormat(const char *Format, ...) { |
234 | 0 | va_list AP; |
235 | 0 | va_start(AP, Format); |
236 | 0 | const int SizeOrError = vsnprintf(nullptr, 0, Format, AP); |
237 | 0 | va_end(AP); |
238 | 0 | if (SizeOrError < 0) { |
239 | 0 | return; |
240 | 0 | } |
241 | 0 | |
242 | 0 | const int Size = SizeOrError + 1; // '\0' |
243 | 0 | Str.resize(Size); |
244 | 0 | va_start(AP, Format); |
245 | 0 | vsnprintf(Str.data(), Size, Format, AP); |
246 | 0 | va_end(AP); |
247 | 0 | } |
248 | | |
249 | 0 | void PrettyStackTraceFormat::print(raw_ostream &OS) const { OS << Str << "\n"; } |
250 | | |
251 | 0 | void PrettyStackTraceProgram::print(raw_ostream &OS) const { |
252 | 0 | OS << "Program arguments: "; |
253 | 0 | // Print the argument list. |
254 | 0 | for (unsigned i = 0, e = ArgC; i != e; ++i) |
255 | 0 | OS << ArgV[i] << ' '; |
256 | 0 | OS << '\n'; |
257 | 0 | } |
258 | | |
259 | | #if ENABLE_BACKTRACES |
260 | 0 | static bool RegisterCrashPrinter() { |
261 | 0 | sys::AddSignalHandler(CrashHandler, nullptr); |
262 | 0 | return false; |
263 | 0 | } |
264 | | #endif |
265 | | |
266 | 0 | void llvm::EnablePrettyStackTrace() { |
267 | 0 | #if ENABLE_BACKTRACES |
268 | 0 | // The first time this is called, we register the crash printer. |
269 | 0 | static bool HandlerRegistered = RegisterCrashPrinter(); |
270 | 0 | (void)HandlerRegistered; |
271 | 0 | #endif |
272 | 0 | } |
273 | | |
274 | 0 | void llvm::EnablePrettyStackTraceOnSigInfoForThisThread(bool ShouldEnable) { |
275 | 0 | #if ENABLE_BACKTRACES |
276 | 0 | if (!ShouldEnable) { |
277 | 0 | ThreadLocalSigInfoGenerationCounter = 0; |
278 | 0 | return; |
279 | 0 | } |
280 | 0 | |
281 | 0 | // The first time this is called, we register the SIGINFO handler. |
282 | 0 | static bool HandlerRegistered = []{ |
283 | 0 | sys::SetInfoSignalFunction([]{ |
284 | 0 | GlobalSigInfoGenerationCounter.fetch_add(1, std::memory_order_relaxed); |
285 | 0 | }); |
286 | 0 | return false; |
287 | 0 | }(); |
288 | 0 | (void)HandlerRegistered; |
289 | 0 |
|
290 | 0 | // Next, enable it for the current thread. |
291 | 0 | ThreadLocalSigInfoGenerationCounter = |
292 | 0 | GlobalSigInfoGenerationCounter.load(std::memory_order_relaxed); |
293 | 0 | #endif |
294 | 0 | } |
295 | | |
296 | 0 | const void *llvm::SavePrettyStackState() { |
297 | 0 | #if ENABLE_BACKTRACES |
298 | 0 | return PrettyStackTraceHead; |
299 | | #else |
300 | | return nullptr; |
301 | | #endif |
302 | | } |
303 | | |
304 | 0 | void llvm::RestorePrettyStackState(const void *Top) { |
305 | 0 | #if ENABLE_BACKTRACES |
306 | 0 | PrettyStackTraceHead = |
307 | 0 | static_cast<PrettyStackTraceEntry *>(const_cast<void *>(Top)); |
308 | 0 | #endif |
309 | 0 | } |
310 | | |
311 | 0 | void LLVMEnablePrettyStackTrace() { |
312 | 0 | EnablePrettyStackTrace(); |
313 | 0 | } |