diff --git a/include/llvm/Support/PrettyStackTrace.h b/include/llvm/Support/PrettyStackTrace.h index 027f9433969..62e3bbc0ddb 100644 --- a/include/llvm/Support/PrettyStackTrace.h +++ b/include/llvm/Support/PrettyStackTrace.h @@ -29,9 +29,11 @@ namespace llvm { /// constructed and destructed, they will add their symbolic frames to a /// virtual stack trace. This gets dumped out if the program crashes. class PrettyStackTraceEntry { - const PrettyStackTraceEntry *NextEntry; + friend PrettyStackTraceEntry *ReverseStackTrace(PrettyStackTraceEntry *); + + PrettyStackTraceEntry *NextEntry; PrettyStackTraceEntry(const PrettyStackTraceEntry &) = delete; - void operator=(const PrettyStackTraceEntry&) = delete; + void operator=(const PrettyStackTraceEntry &) = delete; public: PrettyStackTraceEntry(); virtual ~PrettyStackTraceEntry(); @@ -67,7 +69,7 @@ namespace llvm { }; /// Returns the topmost element of the "pretty" stack state. - const void* SavePrettyStackState(); + const void *SavePrettyStackState(); /// Restores the topmost element of the "pretty" stack state to State, which /// should come from a previous call to SavePrettyStackState(). This is @@ -76,7 +78,7 @@ namespace llvm { /// happens after a crash that's been recovered by CrashRecoveryContext /// doesn't have frames on it that were added in code unwound by the /// CrashRecoveryContext. - void RestorePrettyStackState(const void* State); + void RestorePrettyStackState(const void *State); } // end namespace llvm diff --git a/lib/Support/PrettyStackTrace.cpp b/lib/Support/PrettyStackTrace.cpp index 05b3e31644b..613416a7f0f 100644 --- a/lib/Support/PrettyStackTrace.cpp +++ b/lib/Support/PrettyStackTrace.cpp @@ -21,6 +21,8 @@ #include "llvm/Support/Watchdog.h" #include "llvm/Support/raw_ostream.h" +#include + #ifdef HAVE_CRASHREPORTERCLIENT_H #include #endif @@ -36,20 +38,32 @@ using namespace llvm; // objects, but we *really* cannot tolerate destructors running and do not want // to pay any overhead of synchronizing. As a consequence, we use a raw // thread-local variable. -static LLVM_THREAD_LOCAL const PrettyStackTraceEntry *PrettyStackTraceHead = - nullptr; +static LLVM_THREAD_LOCAL PrettyStackTraceEntry *PrettyStackTraceHead = nullptr; -static unsigned PrintStack(const PrettyStackTraceEntry *Entry, raw_ostream &OS){ - unsigned NextID = 0; - if (Entry->getNextEntry()) - NextID = PrintStack(Entry->getNextEntry(), OS); - OS << NextID << ".\t"; - { +namespace llvm { +PrettyStackTraceEntry *ReverseStackTrace(PrettyStackTraceEntry *Head) { + PrettyStackTraceEntry *Prev = nullptr; + while (Head) + std::tie(Prev, Head, Head->NextEntry) = + std::make_tuple(Head, Head->NextEntry, Prev); + return Prev; +} +} + +static void PrintStack(raw_ostream &OS) { + // Print out the stack in reverse order. To avoid recursion (which is likely + // to fail if we crashed due to stack overflow), we do an up-front pass to + // reverse the stack, then print it, then reverse it again. + unsigned ID = 0; + PrettyStackTraceEntry *ReversedStack = + llvm::ReverseStackTrace(PrettyStackTraceHead); + for (const PrettyStackTraceEntry *Entry = ReversedStack; Entry; + Entry = Entry->getNextEntry()) { + OS << ID++ << ".\t"; sys::Watchdog W(5); Entry->print(OS); } - - return NextID+1; + llvm::ReverseStackTrace(ReversedStack); } /// PrintCurStackTrace - Print the current stack trace to the specified stream. @@ -60,7 +74,7 @@ static void PrintCurStackTrace(raw_ostream &OS) { // If there are pretty stack frames registered, walk and emit them. OS << "Stack dump:\n"; - PrintStack(PrettyStackTraceHead, OS); + PrintStack(OS); OS.flush(); } @@ -123,7 +137,7 @@ PrettyStackTraceEntry::~PrettyStackTraceEntry() { #if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) assert(PrettyStackTraceHead == this && "Pretty stack trace entry destruction is out of order"); - PrettyStackTraceHead = getNextEntry(); + PrettyStackTraceHead = NextEntry; #endif } @@ -154,7 +168,7 @@ void llvm::EnablePrettyStackTrace() { #endif } -const void* llvm::SavePrettyStackState() { +const void *llvm::SavePrettyStackState() { #if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) return PrettyStackTraceHead; #else @@ -162,9 +176,9 @@ const void* llvm::SavePrettyStackState() { #endif } -void llvm::RestorePrettyStackState(const void* Top) { +void llvm::RestorePrettyStackState(const void *Top) { #if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) - PrettyStackTraceHead = (const PrettyStackTraceEntry*)Top; + PrettyStackTraceHead = (PrettyStackTraceEntry*)Top; #endif }