1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 18:42:46 +02:00

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.

llvm-svn: 270276
This commit is contained in:
Richard Smith 2016-05-20 21:18:12 +00:00
parent 1ae48ee8c8
commit d86d870067
2 changed files with 60 additions and 4 deletions

View File

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

View File

@ -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 **StackTrace, int Depth,
}
#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_ostream &OS) {
}
OS << '\n';
}
#else
#elif defined(HAVE_BACKTRACE)
backtrace_symbols_fd(StackTrace, depth, STDERR_FILENO);
#endif
#endif