浏览代码

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.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@270903 91177308-0d34-0410-b5e6-96231b3b80d8

Richard Smith 9 年之前
父节点
当前提交
60364032ef
共有 2 个文件被更改,包括 36 次插入20 次删除
  1. 6 4
      include/llvm/Support/PrettyStackTrace.h
  2. 30 16
      lib/Support/PrettyStackTrace.cpp

+ 6 - 4
include/llvm/Support/PrettyStackTrace.h

@@ -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
 
 

+ 30 - 16
lib/Support/PrettyStackTrace.cpp

@@ -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 =
-    nullptr;
-
-static unsigned PrintStack(const PrettyStackTraceEntry *Entry, raw_ostream &OS){
-  unsigned NextID = 0;
-  if (Entry->getNextEntry())
-    NextID = PrintStack(Entry->getNextEntry(), OS);
-  OS << NextID << ".\t";
-  {
+static LLVM_THREAD_LOCAL PrettyStackTraceEntry *PrettyStackTraceHead = nullptr;
+
+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);
     sys::Watchdog W(5);
     Entry->print(OS);
     Entry->print(OS);
   }
   }
-  
-  return NextID+1;
+  llvm::ReverseStackTrace(ReversedStack);
 }
 }
 
 
 /// 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
 }
 }