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 = std::byte[sizeof(CrashHandlerString)]; |
147 | alignas(CrashHandlerString) static CrashHandlerStringStorage |
148 | crashHandlerStringStorage; |
149 | #endif |
150 | |
151 | /// This callback is run if a fatal signal is delivered to the process, it |
152 | /// prints the pretty stack trace. |
153 | static void CrashHandler(void *) { |
154 | errs() << BugReportMsg ; |
155 | |
156 | #ifndef __APPLE__ |
157 | // On non-apple systems, just emit the crash stack trace to stderr. |
158 | PrintCurStackTrace(OS&: errs()); |
159 | #else |
160 | // Emit the crash stack trace to a SmallString, put it where the system crash |
161 | // handling will find it, and also send it to stderr. |
162 | // |
163 | // The SmallString is fairly large in the hope that we don't allocate (we're |
164 | // handling a fatal signal, something is already pretty wrong, allocation |
165 | // might not work). Further, we don't use a magic static in case that's also |
166 | // borked. We leak any allocation that does occur because the program is about |
167 | // to die anyways. This is technically racy if we were handling two fatal |
168 | // signals, however if we're in that situation a race is the least of our |
169 | // worries. |
170 | auto &crashHandlerString = |
171 | *new (&crashHandlerStringStorage) CrashHandlerString; |
172 | |
173 | // If we crash while trying to print the stack trace, we still want the system |
174 | // crash handling to have some partial information. That'll work out as long |
175 | // as the SmallString doesn't allocate. If it does allocate then the system |
176 | // crash handling will see some garbage because the inline buffer now contains |
177 | // a pointer. |
178 | setCrashLogMessage(crashHandlerString.c_str()); |
179 | |
180 | { |
181 | raw_svector_ostream Stream(crashHandlerString); |
182 | PrintCurStackTrace(Stream); |
183 | } |
184 | |
185 | if (!crashHandlerString.empty()) { |
186 | setCrashLogMessage(crashHandlerString.c_str()); |
187 | errs() << crashHandlerString.str(); |
188 | } else |
189 | setCrashLogMessage("No crash information." ); |
190 | #endif |
191 | } |
192 | |
193 | static void printForSigInfoIfNeeded() { |
194 | unsigned CurrentSigInfoGeneration = |
195 | GlobalSigInfoGenerationCounter.load(m: std::memory_order_relaxed); |
196 | if (ThreadLocalSigInfoGenerationCounter == 0 || |
197 | ThreadLocalSigInfoGenerationCounter == CurrentSigInfoGeneration) { |
198 | return; |
199 | } |
200 | |
201 | PrintCurStackTrace(OS&: errs()); |
202 | ThreadLocalSigInfoGenerationCounter = CurrentSigInfoGeneration; |
203 | } |
204 | |
205 | #endif // ENABLE_BACKTRACES |
206 | |
207 | void llvm::setBugReportMsg(const char *Msg) { |
208 | BugReportMsg = Msg; |
209 | } |
210 | |
211 | const char *llvm::getBugReportMsg() { |
212 | return BugReportMsg; |
213 | } |
214 | |
215 | PrettyStackTraceEntry::PrettyStackTraceEntry() { |
216 | #if ENABLE_BACKTRACES |
217 | // Handle SIGINFO first, because we haven't finished constructing yet. |
218 | printForSigInfoIfNeeded(); |
219 | // Link ourselves. |
220 | NextEntry = PrettyStackTraceHead; |
221 | PrettyStackTraceHead = this; |
222 | #endif |
223 | } |
224 | |
225 | PrettyStackTraceEntry::~PrettyStackTraceEntry() { |
226 | #if ENABLE_BACKTRACES |
227 | assert(PrettyStackTraceHead == this && |
228 | "Pretty stack trace entry destruction is out of order" ); |
229 | PrettyStackTraceHead = NextEntry; |
230 | // Handle SIGINFO first, because we already started destructing. |
231 | printForSigInfoIfNeeded(); |
232 | #endif |
233 | } |
234 | |
235 | void PrettyStackTraceString::print(raw_ostream &OS) const { OS << Str << "\n" ; } |
236 | |
237 | PrettyStackTraceFormat::PrettyStackTraceFormat(const char *Format, ...) { |
238 | va_list AP; |
239 | va_start(AP, Format); |
240 | const int SizeOrError = vsnprintf(s: nullptr, maxlen: 0, format: Format, arg: AP); |
241 | va_end(AP); |
242 | if (SizeOrError < 0) { |
243 | return; |
244 | } |
245 | |
246 | const int Size = SizeOrError + 1; // '\0' |
247 | Str.resize(N: Size); |
248 | va_start(AP, Format); |
249 | vsnprintf(s: Str.data(), maxlen: Size, format: Format, arg: AP); |
250 | va_end(AP); |
251 | } |
252 | |
253 | void PrettyStackTraceFormat::print(raw_ostream &OS) const { OS << Str << "\n" ; } |
254 | |
255 | void PrettyStackTraceProgram::print(raw_ostream &OS) const { |
256 | OS << "Program arguments: " ; |
257 | // Print the argument list. |
258 | for (int I = 0; I < ArgC; ++I) { |
259 | const bool HaveSpace = ::strchr(s: ArgV[I], c: ' '); |
260 | if (I) |
261 | OS << ' '; |
262 | if (HaveSpace) |
263 | OS << '"'; |
264 | OS.write_escaped(Str: ArgV[I]); |
265 | if (HaveSpace) |
266 | OS << '"'; |
267 | } |
268 | OS << '\n'; |
269 | } |
270 | |
271 | #if ENABLE_BACKTRACES |
272 | static bool RegisterCrashPrinter() { |
273 | sys::AddSignalHandler(FnPtr: CrashHandler, Cookie: nullptr); |
274 | return false; |
275 | } |
276 | #endif |
277 | |
278 | void llvm::EnablePrettyStackTrace() { |
279 | #if ENABLE_BACKTRACES |
280 | // The first time this is called, we register the crash printer. |
281 | static bool HandlerRegistered = RegisterCrashPrinter(); |
282 | (void)HandlerRegistered; |
283 | #endif |
284 | } |
285 | |
286 | void llvm::EnablePrettyStackTraceOnSigInfoForThisThread(bool ShouldEnable) { |
287 | #if ENABLE_BACKTRACES |
288 | if (!ShouldEnable) { |
289 | ThreadLocalSigInfoGenerationCounter = 0; |
290 | return; |
291 | } |
292 | |
293 | // The first time this is called, we register the SIGINFO handler. |
294 | static bool HandlerRegistered = []{ |
295 | sys::SetInfoSignalFunction([]{ |
296 | GlobalSigInfoGenerationCounter.fetch_add(i: 1, m: std::memory_order_relaxed); |
297 | }); |
298 | return false; |
299 | }(); |
300 | (void)HandlerRegistered; |
301 | |
302 | // Next, enable it for the current thread. |
303 | ThreadLocalSigInfoGenerationCounter = |
304 | GlobalSigInfoGenerationCounter.load(m: std::memory_order_relaxed); |
305 | #endif |
306 | } |
307 | |
308 | const void *llvm::SavePrettyStackState() { |
309 | #if ENABLE_BACKTRACES |
310 | return PrettyStackTraceHead; |
311 | #else |
312 | return nullptr; |
313 | #endif |
314 | } |
315 | |
316 | void llvm::RestorePrettyStackState(const void *Top) { |
317 | #if ENABLE_BACKTRACES |
318 | PrettyStackTraceHead = |
319 | static_cast<PrettyStackTraceEntry *>(const_cast<void *>(Top)); |
320 | #endif |
321 | } |
322 | |
323 | void LLVMEnablePrettyStackTrace() { |
324 | EnablePrettyStackTrace(); |
325 | } |
326 | |