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