diff --git a/absl/debugging/internal/stacktrace_riscv-inl.inc b/absl/debugging/internal/stacktrace_riscv-inl.inc index a0f23739..a9e2c323 100644 --- a/absl/debugging/internal/stacktrace_riscv-inl.inc +++ b/absl/debugging/internal/stacktrace_riscv-inl.inc @@ -32,54 +32,10 @@ #include #include "absl/base/attributes.h" -#include "absl/debugging/internal/address_is_readable.h" -#include "absl/debugging/internal/vdso_support.h" #include "absl/debugging/stacktrace.h" static const uintptr_t kUnknownFrameSize = 0; -#if defined(__linux__) -// Returns the address of the VDSO __kernel_rt_sigreturn function, if present. -static const unsigned char *GetKernelRtSigreturnAddress() { - constexpr uintptr_t kImpossibleAddress = 0; - ABSL_CONST_INIT static std::atomic memoized(kImpossibleAddress); - uintptr_t address = memoized.load(std::memory_order_relaxed); - if (address != kImpossibleAddress) { - return reinterpret_cast(address); - } - - address = reinterpret_cast(nullptr); - -#if ABSL_HAVE_VDSO_SUPPORT - absl::debugging_internal::VDSOSupport vdso; - if (vdso.IsPresent()) { - absl::debugging_internal::VDSOSupport::SymbolInfo symbol_info; - // Symbol versioning pulled from arch/riscv/kernel/vdso/vdso.lds at v5.10. - auto lookup = [&](int type) { - return vdso.LookupSymbol("__vdso_rt_sigreturn", "LINUX_4.15", type, - &symbol_info); - }; - if ((!lookup(STT_FUNC) && !lookup(STT_NOTYPE)) || - symbol_info.address == nullptr) { - // Unexpected: VDSO is present, yet the expected symbol is missing or - // null. - assert(false && "VDSO is present, but doesn't have expected symbol"); - } else { - if (reinterpret_cast(symbol_info.address) != - kImpossibleAddress) { - address = reinterpret_cast(symbol_info.address); - } else { - assert(false && "VDSO returned invalid address"); - } - } - } -#endif - - memoized.store(address, std::memory_order_relaxed); - return reinterpret_cast(address); -} -#endif // __linux__ - // Compute the size of a stack frame in [low..high). We assume that low < high. // Return size of kUnknownFrameSize. template @@ -115,40 +71,23 @@ static void ** NextStackFrame(void **old_frame_pointer, const void *uc, // $sp ->| ... | // +----------------+ void **new_frame_pointer = reinterpret_cast(old_frame_pointer[-2]); + uintptr_t frame_pointer = reinterpret_cast(new_frame_pointer); // The RISCV ELF psABI mandates that the stack pointer is always 16-byte // aligned. // TODO(#1236) this doesn't hold for ILP32E which only mandates a 4-byte // alignment. - if ((reinterpret_cast(new_frame_pointer) & 15) != 0) + if (frame_pointer & 15) return nullptr; -#if defined(__linux__) - if (WITH_CONTEXT && uc != nullptr) { - // Check to see if next frame's return address is __kernel_rt_sigreturn. - if (old_frame_pointer[-1] == GetKernelRtSigreturnAddress()) { - const ucontext_t *ucv = static_cast(uc); - // old_frame_pointer is not suitable for unwinding, look at ucontext to - // discover frame pointer before signal. - // + // If the new frame pointer matches the signal context, avoid terminating + // early to deal with alternate signal stacks. + if (WITH_CONTEXT) + if (const ucontext_t *ucv = static_cast(uc)) // RISCV ELF psABI has the frame pointer at x8/fp/s0. // -- RISCV psABI Table 18.2 - void **const pre_signal_frame_pointer = - reinterpret_cast(ucv->uc_mcontext.__gregs[8]); - - // Check the alleged frame pointer is actually readable. This is to - // prevent "double fault" in case we hit the first fault due to stack - // corruption. - if (!absl::debugging_internal::AddressIsReadable( - pre_signal_frame_pointer)) - return nullptr; - - // Alleged frame pointer is readable, use it for further unwinding. - new_frame_pointer = pre_signal_frame_pointer; - } - return new_frame_pointer; - } -#endif + if (ucv->uc_mcontext.__gregs[8] == frame_pointer) + return new_frame_pointer; // Check frame size. In strict mode, we assume frames to be under 100,000 // bytes. In non-strict mode, we relax the limit to 1MB. @@ -165,6 +104,7 @@ static void ** NextStackFrame(void **old_frame_pointer, const void *uc, reinterpret_cast(new_frame_pointer) > range.second) return nullptr; } + if (frame_size > max_size) return nullptr;