[llvm] r270276 - Reinstate r269992 (reverting r270267), but restricted to cases where glibc is

Richard Smith via llvm-commits llvm-commits at lists.llvm.org
Fri May 20 14:18:12 PDT 2016


Author: rsmith
Date: Fri May 20 16:18:12 2016
New Revision: 270276

URL: http://llvm.org/viewvc/llvm-project?rev=270276&view=rev
Log:
Reinstate r269992 (reverting r270267), but restricted to cases where glibc is
the C standard library implementation in use.

This works around a glibc bug in the backtrace() function where it fails to
produce a backtrace on x86_64 if libgcc / libunwind is statically linked.

Modified:
    llvm/trunk/cmake/config-ix.cmake
    llvm/trunk/lib/Support/Unix/Signals.inc

Modified: llvm/trunk/cmake/config-ix.cmake
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/cmake/config-ix.cmake?rev=270276&r1=270275&r2=270276&view=diff
==============================================================================
--- llvm/trunk/cmake/config-ix.cmake (original)
+++ llvm/trunk/cmake/config-ix.cmake Fri May 20 16:18:12 2016
@@ -144,6 +144,7 @@ endif()
 # function checks
 check_symbol_exists(arc4random "stdlib.h" HAVE_DECL_ARC4RANDOM)
 check_symbol_exists(backtrace "execinfo.h" HAVE_BACKTRACE)
+check_symbol_exists(_Unwind_Backtrace "unwind.h" HAVE_UNWIND_BACKTRACE)
 check_symbol_exists(getpagesize unistd.h HAVE_GETPAGESIZE)
 check_symbol_exists(getrusage sys/resource.h HAVE_GETRUSAGE)
 check_symbol_exists(setrlimit sys/resource.h HAVE_SETRLIMIT)

Modified: llvm/trunk/lib/Support/Unix/Signals.inc
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Unix/Signals.inc?rev=270276&r1=270275&r2=270276&view=diff
==============================================================================
--- llvm/trunk/lib/Support/Unix/Signals.inc (original)
+++ llvm/trunk/lib/Support/Unix/Signals.inc Fri May 20 16:18:12 2016
@@ -47,6 +47,17 @@
 #if HAVE_LINK_H
 #include <link.h>
 #endif
+#if HAVE_UNWIND_BACKTRACE
+// FIXME: We should be able to use <unwind.h> for any target that has an
+// _Unwind_Backtrace function, but on FreeBSD the configure test passes
+// despite the function not existing, and on Android, <unwind.h> conflicts
+// with <link.h>.
+#ifdef __GLIBC__
+#include <unwind.h>
+#else
+#undef HAVE_UNWIND_BACKTRACE
+#endif
+#endif
 
 using namespace llvm;
 
@@ -340,17 +351,61 @@ static bool findModulesAndOffsets(void *
 }
 #endif // defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) && ...
 
+#if defined(ENABLE_BACKTRACES) && defined(HAVE_UNWIND_BACKTRACE)
+static int unwindBacktrace(void **StackTrace, int MaxEntries) {
+  if (MaxEntries < 0)
+    return 0;
+
+  // Skip the first frame ('unwindBacktrace' itself).
+  int Entries = -1;
+
+  auto HandleFrame = [&](_Unwind_Context *Context) -> _Unwind_Reason_Code {
+    // Apparently we need to detect reaching the end of the stack ourselves.
+    void *IP = (void *)_Unwind_GetIP(Context);
+    if (!IP)
+      return _URC_END_OF_STACK;
+
+    assert(Entries < MaxEntries && "recursively called after END_OF_STACK?");
+    if (Entries >= 0)
+      StackTrace[Entries] = IP;
+
+    if (++Entries == MaxEntries)
+      return _URC_END_OF_STACK;
+    return _URC_NO_REASON;
+  };
+
+  _Unwind_Backtrace(
+      [](_Unwind_Context *Context, void *Handler) {
+        return (*static_cast<decltype(HandleFrame) *>(Handler))(Context);
+      },
+      static_cast<void *>(&HandleFrame));
+  return std::max(Entries, 0);
+}
+#endif
+
 // PrintStackTrace - In the case of a program crash or fault, print out a stack
 // trace so that the user has an indication of why and where we died.
 //
 // On glibc systems we have the 'backtrace' function, which works nicely, but
 // doesn't demangle symbols.
 void llvm::sys::PrintStackTrace(raw_ostream &OS) {
-#if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES)
-  static void* StackTrace[256];
+#if defined(ENABLE_BACKTRACES)
+  static void *StackTrace[256];
+  int depth = 0;
+#if defined(HAVE_BACKTRACE)
   // Use backtrace() to output a backtrace on Linux systems with glibc.
-  int depth = backtrace(StackTrace,
+  if (!depth)
+    depth = backtrace(StackTrace, static_cast<int>(array_lengthof(StackTrace)));
+#endif
+#if defined(HAVE_UNWIND_BACKTRACE)
+  // Try _Unwind_Backtrace() if backtrace() failed.
+  if (!depth)
+    depth = unwindBacktrace(StackTrace,
                         static_cast<int>(array_lengthof(StackTrace)));
+#endif
+  if (!depth)
+    return;
+
   if (printSymbolizedStackTrace(StackTrace, depth, OS))
     return;
 #if HAVE_DLFCN_H && __GNUG__
@@ -400,7 +455,7 @@ void llvm::sys::PrintStackTrace(raw_ostr
     }
     OS << '\n';
   }
-#else
+#elif defined(HAVE_BACKTRACE)
   backtrace_symbols_fd(StackTrace, depth, STDERR_FILENO);
 #endif
 #endif




More information about the llvm-commits mailing list