blob: 8863dea67ddc58180b951cd2e514f599b6db7989 [file] [log] [blame]
Chris Lattner68061d52009-03-04 21:40:23 +00001//===- PrettyStackTrace.cpp - Pretty Crash Handling -----------------------===//
Fangrui Songf78650a2018-07-30 19:41:25 +00002//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Fangrui Songf78650a2018-07-30 19:41:25 +00006//
Chris Lattner68061d52009-03-04 21:40:23 +00007//===----------------------------------------------------------------------===//
8//
9// This file defines some helpful functions for dealing with the possibility of
Chris Lattner0ab5e2c2011-04-15 05:18:47 +000010// Unix signals occurring while your program is running.
Chris Lattner68061d52009-03-04 21:40:23 +000011//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/Support/PrettyStackTrace.h"
Eric Christophera6b96002015-12-18 01:46:52 +000015#include "llvm-c/ErrorHandling.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000016#include "llvm/ADT/SmallString.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000017#include "llvm/Config/config.h" // Get autoconf configuration settings
Chandler Carruthfb3139a2015-01-29 01:23:04 +000018#include "llvm/Support/Compiler.h"
Michael J. Spencer447762d2010-11-29 18:16:10 +000019#include "llvm/Support/Signals.h"
Nick Lewycky4e06def2013-03-26 01:27:52 +000020#include "llvm/Support/Watchdog.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000021#include "llvm/Support/raw_ostream.h"
Eric Christophere9c1bb62010-06-22 21:01:04 +000022
Sean Callanan62204ad2016-12-14 19:19:53 +000023#include <cstdarg>
Dimitry Andricc12f10f2017-04-29 23:45:30 +000024#include <cstdio>
Richard Smith3de58a52016-05-26 20:21:55 +000025#include <tuple>
26
Eric Christophere9c1bb62010-06-22 21:01:04 +000027#ifdef HAVE_CRASHREPORTERCLIENT_H
28#include <CrashReporterClient.h>
29#endif
30
Chris Lattner68061d52009-03-04 21:40:23 +000031using namespace llvm;
32
Owen Anderson9253bb92015-01-29 07:35:31 +000033// If backtrace support is not enabled, compile out support for pretty stack
34// traces. This has the secondary effect of not requiring thread local storage
35// when backtrace support is disabled.
Saleem Abdulrasoolb67342e2019-02-27 03:21:50 +000036#if ENABLE_BACKTRACES
Owen Anderson9253bb92015-01-29 07:35:31 +000037
Chandler Carruth16b670e2015-01-28 09:52:14 +000038// We need a thread local pointer to manage the stack of our stack trace
39// objects, but we *really* cannot tolerate destructors running and do not want
40// to pay any overhead of synchronizing. As a consequence, we use a raw
Chandler Carruthfb3139a2015-01-29 01:23:04 +000041// thread-local variable.
Richard Smith3de58a52016-05-26 20:21:55 +000042static LLVM_THREAD_LOCAL PrettyStackTraceEntry *PrettyStackTraceHead = nullptr;
Chris Lattner68061d52009-03-04 21:40:23 +000043
Richard Smith3de58a52016-05-26 20:21:55 +000044namespace llvm {
45PrettyStackTraceEntry *ReverseStackTrace(PrettyStackTraceEntry *Head) {
46 PrettyStackTraceEntry *Prev = nullptr;
47 while (Head)
48 std::tie(Prev, Head, Head->NextEntry) =
49 std::make_tuple(Head, Head->NextEntry, Prev);
50 return Prev;
51}
52}
53
54static void PrintStack(raw_ostream &OS) {
55 // Print out the stack in reverse order. To avoid recursion (which is likely
56 // to fail if we crashed due to stack overflow), we do an up-front pass to
57 // reverse the stack, then print it, then reverse it again.
58 unsigned ID = 0;
59 PrettyStackTraceEntry *ReversedStack =
60 llvm::ReverseStackTrace(PrettyStackTraceHead);
61 for (const PrettyStackTraceEntry *Entry = ReversedStack; Entry;
62 Entry = Entry->getNextEntry()) {
63 OS << ID++ << ".\t";
Nick Lewycky4e06def2013-03-26 01:27:52 +000064 sys::Watchdog W(5);
65 Entry->print(OS);
66 }
Richard Smith3de58a52016-05-26 20:21:55 +000067 llvm::ReverseStackTrace(ReversedStack);
Chris Lattner8d0fe8c2009-03-05 07:03:49 +000068}
69
Chris Lattnere41a4342009-03-06 07:19:54 +000070/// PrintCurStackTrace - Print the current stack trace to the specified stream.
71static void PrintCurStackTrace(raw_ostream &OS) {
Chris Lattner8d0fe8c2009-03-05 07:03:49 +000072 // Don't print an empty trace.
Chandler Carruth16b670e2015-01-28 09:52:14 +000073 if (!PrettyStackTraceHead) return;
Fangrui Songf78650a2018-07-30 19:41:25 +000074
Chris Lattner68061d52009-03-04 21:40:23 +000075 // If there are pretty stack frames registered, walk and emit them.
Chris Lattner68061d52009-03-04 21:40:23 +000076 OS << "Stack dump:\n";
Fangrui Songf78650a2018-07-30 19:41:25 +000077
Richard Smith3de58a52016-05-26 20:21:55 +000078 PrintStack(OS);
Chris Lattner68061d52009-03-04 21:40:23 +000079 OS.flush();
80}
81
Eric Christopher51f290832010-06-28 18:25:51 +000082// Integrate with crash reporter libraries.
Chris Bienemanbfff2542016-12-07 19:28:22 +000083#if defined (__APPLE__) && defined(HAVE_CRASHREPORTERCLIENT_H)
Eric Christopher51f290832010-06-28 18:25:51 +000084// If any clients of llvm try to link to libCrashReporterClient.a themselves,
85// only one crash info struct will be used.
Eric Christopher7f103a22010-06-28 18:33:48 +000086extern "C" {
Fangrui Songf78650a2018-07-30 19:41:25 +000087CRASH_REPORTER_CLIENT_HIDDEN
88struct crashreporter_annotations_t gCRAnnotations
89 __attribute__((section("__DATA," CRASHREPORTER_ANNOTATIONS_SECTION)))
Daniel Sanders8c345dc2018-01-30 16:02:32 +000090#if CRASHREPORTER_ANNOTATIONS_VERSION < 5
Eric Christopherc4b9b522011-10-05 05:00:26 +000091 = { CRASHREPORTER_ANNOTATIONS_VERSION, 0, 0, 0, 0, 0, 0 };
Daniel Sanders8c345dc2018-01-30 16:02:32 +000092#else
93 = { CRASHREPORTER_ANNOTATIONS_VERSION, 0, 0, 0, 0, 0, 0, 0 };
94#endif
Eric Christopher7f103a22010-06-28 18:33:48 +000095}
Sean Callanan032dbf92016-12-14 19:09:43 +000096#elif defined(__APPLE__) && HAVE_CRASHREPORTER_INFO
97extern "C" const char *__crashreporter_info__
98 __attribute__((visibility("hidden"))) = 0;
Daniel Dunbarc120ffe2010-05-20 23:50:19 +000099asm(".desc ___crashreporter_info__, 0x10");
Chris Lattnere41a4342009-03-06 07:19:54 +0000100#endif
101
Chris Lattnere41a4342009-03-06 07:19:54 +0000102/// CrashHandler - This callback is run if a fatal signal is delivered to the
103/// process, it prints the pretty stack trace.
Eric Christopher87947f72010-08-08 00:00:34 +0000104static void CrashHandler(void *) {
Chris Lattnere41a4342009-03-06 07:19:54 +0000105#ifndef __APPLE__
106 // On non-apple systems, just emit the crash stack trace to stderr.
107 PrintCurStackTrace(errs());
108#else
109 // Otherwise, emit to a smallvector of chars, send *that* to stderr, but also
110 // put it into __crashreporter_info__.
111 SmallString<2048> TmpStr;
112 {
113 raw_svector_ostream Stream(TmpStr);
114 PrintCurStackTrace(Stream);
115 }
Fangrui Songf78650a2018-07-30 19:41:25 +0000116
Chris Lattnere41a4342009-03-06 07:19:54 +0000117 if (!TmpStr.empty()) {
Eric Christopherca466732010-12-03 07:45:22 +0000118#ifdef HAVE_CRASHREPORTERCLIENT_H
Eric Christopher87947f72010-08-08 00:00:34 +0000119 // Cast to void to avoid warning.
Jordan Rose7e535bc2018-06-15 16:35:31 +0000120 (void)CRSetCrashLogMessage(TmpStr.c_str());
Fangrui Songf78650a2018-07-30 19:41:25 +0000121#elif HAVE_CRASHREPORTER_INFO
Jordan Rose7e535bc2018-06-15 16:35:31 +0000122 __crashreporter_info__ = strdup(TmpStr.c_str());
Eric Christophere9c1bb62010-06-22 21:01:04 +0000123#endif
Daniel Dunbar8b0b1152009-08-19 20:07:03 +0000124 errs() << TmpStr.str();
Chris Lattnere41a4342009-03-06 07:19:54 +0000125 }
Fangrui Songf78650a2018-07-30 19:41:25 +0000126
Chris Lattnere41a4342009-03-06 07:19:54 +0000127#endif
128}
129
Saleem Abdulrasoolb67342e2019-02-27 03:21:50 +0000130#endif // ENABLE_BACKTRACES
Owen Anderson9253bb92015-01-29 07:35:31 +0000131
Chris Lattner68061d52009-03-04 21:40:23 +0000132PrettyStackTraceEntry::PrettyStackTraceEntry() {
Saleem Abdulrasoolb67342e2019-02-27 03:21:50 +0000133#if ENABLE_BACKTRACES
Chris Lattner68061d52009-03-04 21:40:23 +0000134 // Link ourselves.
Chandler Carruth16b670e2015-01-28 09:52:14 +0000135 NextEntry = PrettyStackTraceHead;
136 PrettyStackTraceHead = this;
Owen Anderson9253bb92015-01-29 07:35:31 +0000137#endif
Chris Lattner68061d52009-03-04 21:40:23 +0000138}
139
140PrettyStackTraceEntry::~PrettyStackTraceEntry() {
Saleem Abdulrasoolb67342e2019-02-27 03:21:50 +0000141#if ENABLE_BACKTRACES
Chandler Carruth16b670e2015-01-28 09:52:14 +0000142 assert(PrettyStackTraceHead == this &&
Chris Lattner68061d52009-03-04 21:40:23 +0000143 "Pretty stack trace entry destruction is out of order");
Richard Smith3de58a52016-05-26 20:21:55 +0000144 PrettyStackTraceHead = NextEntry;
Owen Anderson9253bb92015-01-29 07:35:31 +0000145#endif
Chris Lattner68061d52009-03-04 21:40:23 +0000146}
147
Sean Callanan032dbf92016-12-14 19:09:43 +0000148void PrettyStackTraceString::print(raw_ostream &OS) const { OS << Str << "\n"; }
149
150PrettyStackTraceFormat::PrettyStackTraceFormat(const char *Format, ...) {
151 va_list AP;
152 va_start(AP, Format);
153 const int SizeOrError = vsnprintf(nullptr, 0, Format, AP);
154 va_end(AP);
155 if (SizeOrError < 0) {
156 return;
157 }
158
159 const int Size = SizeOrError + 1; // '\0'
160 Str.resize(Size);
161 va_start(AP, Format);
162 vsnprintf(Str.data(), Size, Format, AP);
163 va_end(AP);
Chris Lattner68061d52009-03-04 21:40:23 +0000164}
165
Sean Callanan032dbf92016-12-14 19:09:43 +0000166void PrettyStackTraceFormat::print(raw_ostream &OS) const { OS << Str << "\n"; }
167
Chris Lattner68061d52009-03-04 21:40:23 +0000168void PrettyStackTraceProgram::print(raw_ostream &OS) const {
Chris Lattner2674eb42009-03-05 06:51:42 +0000169 OS << "Program arguments: ";
Chris Lattner68061d52009-03-04 21:40:23 +0000170 // Print the argument list.
171 for (unsigned i = 0, e = ArgC; i != e; ++i)
172 OS << ArgV[i] << ' ';
173 OS << '\n';
Chris Lattner2674eb42009-03-05 06:51:42 +0000174}
Filip Pizlo9f50ccd2013-11-03 00:29:47 +0000175
Saleem Abdulrasoolb67342e2019-02-27 03:21:50 +0000176#if ENABLE_BACKTRACES
Filip Pizloc10ca902013-11-04 02:22:25 +0000177static bool RegisterCrashPrinter() {
Craig Topperc10719f2014-04-07 04:17:22 +0000178 sys::AddSignalHandler(CrashHandler, nullptr);
Filip Pizloc10ca902013-11-04 02:22:25 +0000179 return false;
180}
Owen Anderson9253bb92015-01-29 07:35:31 +0000181#endif
Filip Pizloc10ca902013-11-04 02:22:25 +0000182
183void llvm::EnablePrettyStackTrace() {
Saleem Abdulrasoolb67342e2019-02-27 03:21:50 +0000184#if ENABLE_BACKTRACES
Filip Pizloc10ca902013-11-04 02:22:25 +0000185 // The first time this is called, we register the crash printer.
186 static bool HandlerRegistered = RegisterCrashPrinter();
187 (void)HandlerRegistered;
Owen Anderson9253bb92015-01-29 07:35:31 +0000188#endif
Filip Pizloc10ca902013-11-04 02:22:25 +0000189}
190
Richard Smith3de58a52016-05-26 20:21:55 +0000191const void *llvm::SavePrettyStackState() {
Saleem Abdulrasoolb67342e2019-02-27 03:21:50 +0000192#if ENABLE_BACKTRACES
Nico Weberaf3f2422015-08-07 17:47:03 +0000193 return PrettyStackTraceHead;
194#else
195 return nullptr;
196#endif
197}
198
Richard Smith3de58a52016-05-26 20:21:55 +0000199void llvm::RestorePrettyStackState(const void *Top) {
Saleem Abdulrasoolb67342e2019-02-27 03:21:50 +0000200#if ENABLE_BACKTRACES
Sanjoy Dasebeee962016-05-27 23:04:28 +0000201 PrettyStackTraceHead =
202 static_cast<PrettyStackTraceEntry *>(const_cast<void *>(Top));
Nico Weberaf3f2422015-08-07 17:47:03 +0000203#endif
204}
205
Filip Pizloc10ca902013-11-04 02:22:25 +0000206void LLVMEnablePrettyStackTrace() {
207 EnablePrettyStackTrace();
Filip Pizlo9f50ccd2013-11-03 00:29:47 +0000208}