#include <folly/debugging/symbolizer/StackTrace.h>
#include <folly/tracing/AsyncStack.h>
#include <memory>
#include <folly/CppAttributes.h>
#include <folly/Portability.h>
#include <folly/portability/Config.h>
#include <folly/tracing/AsyncStack.h>
#if FOLLY_HAVE_LIBUNWIND
#define UNW_LOCAL_ONLY …
#include <folly/portability/Libunwind.h>
#endif
#if FOLLY_HAVE_BACKTRACE
#include <execinfo.h>
#endif
namespace folly {
namespace symbolizer {
namespace {
static uintptr_t sAddr = …;
static ssize_t sInit = …;
}
ssize_t getStackTrace(
[[maybe_unused]] uintptr_t* addresses,
[[maybe_unused]] size_t maxAddresses) { … }
namespace {
constexpr size_t kMaxExpectedStackFrameSizeLg2 = …
;
constexpr size_t kMaxExpectedStackFrameSize
= …;
#if FOLLY_HAVE_LIBUNWIND
inline bool getFrameInfo(unw_cursor_t* cursor, uintptr_t& ip) {
unw_word_t uip;
if (unw_get_reg(cursor, UNW_REG_IP, &uip) < 0) {
return false;
}
int r = unw_is_signal_frame(cursor);
if (r < 0) {
return false;
}
ip = uip - (r == 0);
return true;
}
#if FOLLY_PPC64 == 0
FOLLY_ALWAYS_INLINE
#endif
ssize_t getStackTraceInPlace(
unw_context_t& context,
unw_cursor_t& cursor,
uintptr_t* addresses,
size_t maxAddresses) {
if (maxAddresses == 0) {
return 0;
}
if (unw_getcontext(&context) < 0) {
return -1;
}
if (unw_init_local(&cursor, &context) < 0) {
return -1;
}
if (!getFrameInfo(&cursor, *addresses)) {
return -1;
}
++addresses;
size_t count = 1;
for (; count != maxAddresses; ++count, ++addresses) {
int r = unw_step(&cursor);
if (r < 0) {
return -1;
}
if (r == 0) {
break;
}
if (!getFrameInfo(&cursor, *addresses)) {
return -1;
}
}
return count;
}
#endif
}
ssize_t getStackTraceSafe(
[[maybe_unused]] uintptr_t* addresses,
[[maybe_unused]] size_t maxAddresses) { … }
ssize_t getStackTraceHeap(
[[maybe_unused]] uintptr_t* addresses,
[[maybe_unused]] size_t maxAddresses) { … }
namespace {
struct StackFrame { … };
FOLLY_DISABLE_THREAD_SANITIZER size_t walkNormalStack(
uintptr_t* addresses,
size_t maxAddresses,
StackFrame* normalStackFrame,
StackFrame* normalStackFrameStop) { … }
struct WalkAsyncStackResult { … };
WalkAsyncStackResult walkAsyncStack(
uintptr_t* addresses,
size_t maxAddresses,
AsyncStackFrame* asyncStackFrame) { … }
}
ssize_t getAsyncStackTraceSafe(uintptr_t* addresses, size_t maxAddresses) { … }
}
}