mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-12 22:17:47 +00:00
Don't use recursion to print out the PrettyStackTrace after a crash. If the
crash was due to a stack overflow, chances are good that this would also cause a stack overflow. llvm-svn: 270903
This commit is contained in:
parent
f05c00c198
commit
978cfd3135
@ -29,9 +29,11 @@ namespace llvm {
|
|||||||
/// constructed and destructed, they will add their symbolic frames to a
|
/// constructed and destructed, they will add their symbolic frames to a
|
||||||
/// virtual stack trace. This gets dumped out if the program crashes.
|
/// virtual stack trace. This gets dumped out if the program crashes.
|
||||||
class PrettyStackTraceEntry {
|
class PrettyStackTraceEntry {
|
||||||
const PrettyStackTraceEntry *NextEntry;
|
friend PrettyStackTraceEntry *ReverseStackTrace(PrettyStackTraceEntry *);
|
||||||
|
|
||||||
|
PrettyStackTraceEntry *NextEntry;
|
||||||
PrettyStackTraceEntry(const PrettyStackTraceEntry &) = delete;
|
PrettyStackTraceEntry(const PrettyStackTraceEntry &) = delete;
|
||||||
void operator=(const PrettyStackTraceEntry&) = delete;
|
void operator=(const PrettyStackTraceEntry &) = delete;
|
||||||
public:
|
public:
|
||||||
PrettyStackTraceEntry();
|
PrettyStackTraceEntry();
|
||||||
virtual ~PrettyStackTraceEntry();
|
virtual ~PrettyStackTraceEntry();
|
||||||
@ -67,7 +69,7 @@ namespace llvm {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Returns the topmost element of the "pretty" stack state.
|
/// 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
|
/// Restores the topmost element of the "pretty" stack state to State, which
|
||||||
/// should come from a previous call to SavePrettyStackState(). This is
|
/// 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
|
/// happens after a crash that's been recovered by CrashRecoveryContext
|
||||||
/// doesn't have frames on it that were added in code unwound by the
|
/// doesn't have frames on it that were added in code unwound by the
|
||||||
/// CrashRecoveryContext.
|
/// CrashRecoveryContext.
|
||||||
void RestorePrettyStackState(const void* State);
|
void RestorePrettyStackState(const void *State);
|
||||||
|
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
|
||||||
|
@ -21,6 +21,8 @@
|
|||||||
#include "llvm/Support/Watchdog.h"
|
#include "llvm/Support/Watchdog.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
|
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
#ifdef HAVE_CRASHREPORTERCLIENT_H
|
#ifdef HAVE_CRASHREPORTERCLIENT_H
|
||||||
#include <CrashReporterClient.h>
|
#include <CrashReporterClient.h>
|
||||||
#endif
|
#endif
|
||||||
@ -36,20 +38,32 @@ using namespace llvm;
|
|||||||
// objects, but we *really* cannot tolerate destructors running and do not want
|
// 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
|
// to pay any overhead of synchronizing. As a consequence, we use a raw
|
||||||
// thread-local variable.
|
// thread-local variable.
|
||||||
static LLVM_THREAD_LOCAL const PrettyStackTraceEntry *PrettyStackTraceHead =
|
static LLVM_THREAD_LOCAL PrettyStackTraceEntry *PrettyStackTraceHead = nullptr;
|
||||||
nullptr;
|
|
||||||
|
|
||||||
static unsigned PrintStack(const PrettyStackTraceEntry *Entry, raw_ostream &OS){
|
namespace llvm {
|
||||||
unsigned NextID = 0;
|
PrettyStackTraceEntry *ReverseStackTrace(PrettyStackTraceEntry *Head) {
|
||||||
if (Entry->getNextEntry())
|
PrettyStackTraceEntry *Prev = nullptr;
|
||||||
NextID = PrintStack(Entry->getNextEntry(), OS);
|
while (Head)
|
||||||
OS << NextID << ".\t";
|
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);
|
sys::Watchdog W(5);
|
||||||
Entry->print(OS);
|
Entry->print(OS);
|
||||||
}
|
}
|
||||||
|
llvm::ReverseStackTrace(ReversedStack);
|
||||||
return NextID+1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// PrintCurStackTrace - Print the current stack trace to the specified stream.
|
/// 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.
|
// If there are pretty stack frames registered, walk and emit them.
|
||||||
OS << "Stack dump:\n";
|
OS << "Stack dump:\n";
|
||||||
|
|
||||||
PrintStack(PrettyStackTraceHead, OS);
|
PrintStack(OS);
|
||||||
OS.flush();
|
OS.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,7 +137,7 @@ PrettyStackTraceEntry::~PrettyStackTraceEntry() {
|
|||||||
#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES)
|
#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES)
|
||||||
assert(PrettyStackTraceHead == this &&
|
assert(PrettyStackTraceHead == this &&
|
||||||
"Pretty stack trace entry destruction is out of order");
|
"Pretty stack trace entry destruction is out of order");
|
||||||
PrettyStackTraceHead = getNextEntry();
|
PrettyStackTraceHead = NextEntry;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,7 +168,7 @@ void llvm::EnablePrettyStackTrace() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
const void* llvm::SavePrettyStackState() {
|
const void *llvm::SavePrettyStackState() {
|
||||||
#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES)
|
#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES)
|
||||||
return PrettyStackTraceHead;
|
return PrettyStackTraceHead;
|
||||||
#else
|
#else
|
||||||
@ -162,9 +176,9 @@ const void* llvm::SavePrettyStackState() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void llvm::RestorePrettyStackState(const void* Top) {
|
void llvm::RestorePrettyStackState(const void *Top) {
|
||||||
#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES)
|
#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES)
|
||||||
PrettyStackTraceHead = (const PrettyStackTraceEntry*)Top;
|
PrettyStackTraceHead = (PrettyStackTraceEntry*)Top;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user