summaryrefslogtreecommitdiffstats
path: root/contrib/restricted/abseil-cpp-tstring/y_absl/debugging
diff options
context:
space:
mode:
authorthegeorg <[email protected]>2023-08-20 23:36:15 +0300
committerthegeorg <[email protected]>2023-08-21 00:54:32 +0300
commit4ffd2d398873ff2e3f1c28fbb1d647d26a9600d1 (patch)
treef023ac7871845812356d6ace5e07d059bdf270b4 /contrib/restricted/abseil-cpp-tstring/y_absl/debugging
parentd619e9fffe040fe2f8b4940b1a72cc1757538c8c (diff)
Update contrib/restricted/abseil-cpp-tstring to 20230802.0
Diffstat (limited to 'contrib/restricted/abseil-cpp-tstring/y_absl/debugging')
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/debugging/failure_signal_handler.cc48
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/debugging/failure_signal_handler.h2
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/debugging/internal/elf_mem_image.h3
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/debugging/internal/examine_stack.cc3
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/debugging/internal/stacktrace_aarch64-inl.inc82
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/debugging/internal/stacktrace_powerpc-inl.inc2
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/debugging/internal/stacktrace_x86-inl.inc2
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/debugging/internal/symbolize.h2
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/debugging/leak_check.cc4
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/debugging/symbolize_elf.inc62
-rw-r--r--contrib/restricted/abseil-cpp-tstring/y_absl/debugging/symbolize_emscripten.inc3
11 files changed, 148 insertions, 65 deletions
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/failure_signal_handler.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/failure_signal_handler.cc
index 25ed376e0f3..ab8b62dda2d 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/failure_signal_handler.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/failure_signal_handler.cc
@@ -31,6 +31,13 @@
#ifdef Y_ABSL_HAVE_MMAP
#include <sys/mman.h>
+#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+#endif
+
+#ifdef __linux__
+#include <sys/prctl.h>
#endif
#include <algorithm>
@@ -77,10 +84,10 @@ struct FailureSignalData {
struct sigaction previous_action;
// StructSigaction is used to silence -Wmissing-field-initializers.
using StructSigaction = struct sigaction;
- #define FSD_PREVIOUS_INIT FailureSignalData::StructSigaction()
+#define FSD_PREVIOUS_INIT FailureSignalData::StructSigaction()
#else
void (*previous_handler)(int);
- #define FSD_PREVIOUS_INIT SIG_DFL
+#define FSD_PREVIOUS_INIT SIG_DFL
#endif
};
@@ -132,7 +139,7 @@ const char* FailureSignalToString(int signo) {
#ifdef Y_ABSL_HAVE_SIGALTSTACK
static bool SetupAlternateStackOnce() {
-#if defined(__wasm__) || defined (__asjms__)
+#if defined(__wasm__) || defined(__asjms__)
const size_t page_mask = getpagesize() - 1;
#else
const size_t page_mask = static_cast<size_t>(sysconf(_SC_PAGESIZE)) - 1;
@@ -154,9 +161,6 @@ static bool SetupAlternateStackOnce() {
#ifndef MAP_STACK
#define MAP_STACK 0
#endif
-#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
-#define MAP_ANONYMOUS MAP_ANON
-#endif
sigstk.ss_sp = mmap(nullptr, sigstk.ss_size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
if (sigstk.ss_sp == MAP_FAILED) {
@@ -172,6 +176,20 @@ static bool SetupAlternateStackOnce() {
if (sigaltstack(&sigstk, nullptr) != 0) {
Y_ABSL_RAW_LOG(FATAL, "sigaltstack() failed with errno=%d", errno);
}
+
+#ifdef __linux__
+#if defined(PR_SET_VMA) && defined(PR_SET_VMA_ANON_NAME)
+ // Make a best-effort attempt to name the allocated region in
+ // /proc/$PID/smaps.
+ //
+ // The call to prctl() may fail if the kernel was not configured with the
+ // CONFIG_ANON_VMA_NAME kernel option. This is OK since the call is
+ // primarily a debugging aid.
+ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, sigstk.ss_sp, sigstk.ss_size,
+ "y_absl-signalstack");
+#endif
+#endif // __linux__
+
return true;
}
@@ -218,10 +236,6 @@ static void InstallOneFailureHandler(FailureSignalData* data,
#endif
-static void WriteToStderr(const char* data) {
- y_absl::raw_log_internal::AsyncSignalSafeWriteToStderr(data, strlen(data));
-}
-
static void WriteSignalMessage(int signo, int cpu,
void (*writerfn)(const char*)) {
char buf[96];
@@ -234,7 +248,7 @@ static void WriteSignalMessage(int signo, int cpu,
if (signal_string != nullptr && signal_string[0] != '\0') {
snprintf(buf, sizeof(buf), "*** %s received at time=%ld%s ***\n",
signal_string,
- static_cast<long>(time(nullptr)), // NOLINT(runtime/int)
+ static_cast<long>(time(nullptr)), // NOLINT(runtime/int)
on_cpu);
} else {
snprintf(buf, sizeof(buf), "*** Signal %d received at time=%ld%s ***\n",
@@ -297,7 +311,8 @@ static void PortableSleepForSeconds(int seconds) {
struct timespec sleep_time;
sleep_time.tv_sec = seconds;
sleep_time.tv_nsec = 0;
- while (nanosleep(&sleep_time, &sleep_time) != 0 && errno == EINTR) {}
+ while (nanosleep(&sleep_time, &sleep_time) != 0 && errno == EINTR) {
+ }
#endif
}
@@ -307,9 +322,7 @@ static void PortableSleepForSeconds(int seconds) {
// set amount of time. If AbslFailureSignalHandler() hangs for more than
// the alarm timeout, ImmediateAbortSignalHandler() will abort the
// program.
-static void ImmediateAbortSignalHandler(int) {
- RaiseToDefaultHandler(SIGABRT);
-}
+static void ImmediateAbortSignalHandler(int) { RaiseToDefaultHandler(SIGABRT); }
#endif
// y_absl::base_internal::GetTID() returns pid_t on most platforms, but
@@ -362,7 +375,10 @@ static void AbslFailureSignalHandler(int signo, siginfo_t*, void* ucontext) {
#endif
// First write to stderr.
- WriteFailureInfo(signo, ucontext, my_cpu, WriteToStderr);
+ WriteFailureInfo(
+ signo, ucontext, my_cpu, +[](const char* data) {
+ y_absl::raw_log_internal::AsyncSignalSafeWriteError(data, strlen(data));
+ });
// Riskier code (because it is less likely to be async-signal-safe)
// goes after this point.
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/failure_signal_handler.h b/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/failure_signal_handler.h
index b4262642761..03ce76be424 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/failure_signal_handler.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/failure_signal_handler.h
@@ -62,7 +62,7 @@ struct FailureSignalHandlerOptions {
// If true, try to run signal handlers on an alternate stack (if supported on
// the given platform). An alternate stack is useful for program crashes due
// to a stack overflow; by running on a alternate stack, the signal handler
- // may run even when normal stack space has been exausted. The downside of
+ // may run even when normal stack space has been exhausted. The downside of
// using an alternate stack is that extra memory for the alternate stack needs
// to be pre-allocated.
bool use_alternate_stack = true;
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/internal/elf_mem_image.h b/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/internal/elf_mem_image.h
index a7dde972061..9c5e588fbbc 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/internal/elf_mem_image.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/internal/elf_mem_image.h
@@ -33,7 +33,8 @@
#if defined(__ELF__) && !defined(__OpenBSD__) && !defined(__QNX__) && \
!defined(__native_client__) && !defined(__asmjs__) && \
- !defined(__wasm__) && !defined(__HAIKU__)
+ !defined(__wasm__) && !defined(__HAIKU__) && !defined(__sun) && \
+ !defined(__VXWORKS__) && !defined(__hexagon__)
#define Y_ABSL_HAVE_ELF_MEM_IMAGE 1
#endif
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/internal/examine_stack.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/internal/examine_stack.cc
index 62d600f5a8a..284610b5d7b 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/internal/examine_stack.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/internal/examine_stack.cc
@@ -24,6 +24,9 @@
#ifdef Y_ABSL_HAVE_MMAP
#include <sys/mman.h>
+#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
+#define MAP_ANONYMOUS MAP_ANON
+#endif
#endif
#if defined(__linux__) || defined(__APPLE__)
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/internal/stacktrace_aarch64-inl.inc b/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/internal/stacktrace_aarch64-inl.inc
index b9a79192225..04531613f8a 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/internal/stacktrace_aarch64-inl.inc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/internal/stacktrace_aarch64-inl.inc
@@ -13,6 +13,7 @@
#include <cassert>
#include <cstdint>
#include <iostream>
+#include <limits>
#include "y_absl/base/attributes.h"
#include "y_absl/debugging/internal/address_is_readable.h"
@@ -20,6 +21,10 @@
#include "y_absl/debugging/stacktrace.h"
static const size_t kUnknownFrameSize = 0;
+// Stack end to use when we don't know the actual stack end
+// (effectively just the end of address space).
+constexpr uintptr_t kUnknownStackEnd =
+ std::numeric_limits<size_t>::max() - sizeof(void *);
#if defined(__linux__)
// Returns the address of the VDSO __kernel_rt_sigreturn function, if present.
@@ -79,8 +84,9 @@ static inline size_t ComputeStackFrameSize(const T* low,
// "STRICT_UNWINDING") to reduce the chance that a bad pointer is returned.
template<bool STRICT_UNWINDING, bool WITH_CONTEXT>
Y_ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS // May read random elements from stack.
-Y_ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY // May read random elements from stack.
-static void **NextStackFrame(void **old_frame_pointer, const void *uc) {
+Y_ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY // May read random elements from stack.
+static void **NextStackFrame(void **old_frame_pointer, const void *uc,
+ size_t stack_low, size_t stack_high) {
void **new_frame_pointer = reinterpret_cast<void**>(*old_frame_pointer);
bool check_frame_size = true;
@@ -94,16 +100,21 @@ static void **NextStackFrame(void **old_frame_pointer, const void *uc) {
void **const pre_signal_frame_pointer =
reinterpret_cast<void **>(ucv->uc_mcontext.regs[29]);
+ // The most recent signal always needs special handling to find the frame
+ // pointer, but a nested signal does not. If pre_signal_frame_pointer is
+ // earlier in the stack than the old_frame_pointer, then use it. If it is
+ // later, then we have already unwound through it and it needs no special
+ // handling.
+ if (pre_signal_frame_pointer >= old_frame_pointer) {
+ new_frame_pointer = pre_signal_frame_pointer;
+ }
// Check that alleged frame pointer is actually readable. This is to
// prevent "double fault" in case we hit the first fault due to e.g.
// stack corruption.
if (!y_absl::debugging_internal::AddressIsReadable(
- pre_signal_frame_pointer))
+ new_frame_pointer))
return nullptr;
- // Alleged frame pointer is readable, use it for further unwinding.
- new_frame_pointer = pre_signal_frame_pointer;
-
// Skip frame size check if we return from a signal. We may be using a
// an alternate stack for signals.
check_frame_size = false;
@@ -121,8 +132,26 @@ static void **NextStackFrame(void **old_frame_pointer, const void *uc) {
const size_t max_size = STRICT_UNWINDING ? 100000 : 1000000;
const size_t frame_size =
ComputeStackFrameSize(old_frame_pointer, new_frame_pointer);
- if (frame_size == kUnknownFrameSize || frame_size > max_size)
- return nullptr;
+ if (frame_size == kUnknownFrameSize)
+ return nullptr;
+ // A very large frame may mean corrupt memory or an erroneous frame
+ // pointer. But also maybe just a plain-old large frame. Assume that if the
+ // frame is within the known stack, then it is valid.
+ if (frame_size > max_size) {
+ if (stack_high < kUnknownStackEnd &&
+ static_cast<size_t>(getpagesize()) < stack_low) {
+ const uintptr_t new_fp_u =
+ reinterpret_cast<uintptr_t>(new_frame_pointer);
+ // Stack bounds are known.
+ if (!(stack_low < new_fp_u && new_fp_u <= stack_high)) {
+ // new_frame_pointer is not within the known stack.
+ return nullptr;
+ }
+ } else {
+ // Stack bounds are unknown, prefer truncated stack to possible crash.
+ return nullptr;
+ }
+ }
}
return new_frame_pointer;
@@ -138,42 +167,49 @@ static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count,
#else
# error reading stack point not yet supported on this platform.
#endif
-
skip_count++; // Skip the frame for this function.
int n = 0;
+ // Assume that the first page is not stack.
+ size_t stack_low = static_cast<size_t>(getpagesize());
+ size_t stack_high = kUnknownStackEnd;
+
// The frame pointer points to low address of a frame. The first 64-bit
// word of a frame points to the next frame up the call chain, which normally
// is just after the high address of the current frame. The second word of
- // a frame contains return adress of to the caller. To find a pc value
+ // a frame contains return address of to the caller. To find a pc value
// associated with the current frame, we need to go down a level in the call
// chain. So we remember return the address of the last frame seen. This
// does not work for the first stack frame, which belongs to UnwindImp() but
// we skip the frame for UnwindImp() anyway.
void* prev_return_address = nullptr;
+ // The nth frame size is the difference between the nth frame pointer and the
+ // the frame pointer below it in the call chain. There is no frame below the
+ // leaf frame, but this function is the leaf anyway, and we skip it.
+ void** prev_frame_pointer = nullptr;
- while (frame_pointer && n < max_depth) {
- // The y_absl::GetStackFrames routine is called when we are in some
- // informational context (the failure signal handler for example).
- // Use the non-strict unwinding rules to produce a stack trace
- // that is as complete as possible (even if it contains a few bogus
- // entries in some rare cases).
- void **next_frame_pointer =
- NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(frame_pointer, ucp);
-
+ while (frame_pointer && n < max_depth) {
if (skip_count > 0) {
skip_count--;
} else {
result[n] = prev_return_address;
if (IS_STACK_FRAMES) {
sizes[n] = static_cast<int>(
- ComputeStackFrameSize(frame_pointer, next_frame_pointer));
+ ComputeStackFrameSize(prev_frame_pointer, frame_pointer));
}
n++;
}
prev_return_address = frame_pointer[1];
- frame_pointer = next_frame_pointer;
+ prev_frame_pointer = frame_pointer;
+ // The y_absl::GetStackFrames routine is called when we are in some
+ // informational context (the failure signal handler for example).
+ // Use the non-strict unwinding rules to produce a stack trace
+ // that is as complete as possible (even if it contains a few bogus
+ // entries in some rare cases).
+ frame_pointer = NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(
+ frame_pointer, ucp, stack_low, stack_high);
}
+
if (min_dropped_frames != nullptr) {
// Implementation detail: we clamp the max of frames we are willing to
// count, so as not to spend too much time in the loop below.
@@ -185,8 +221,8 @@ static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count,
} else {
num_dropped_frames++;
}
- frame_pointer =
- NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(frame_pointer, ucp);
+ frame_pointer = NextStackFrame<!IS_STACK_FRAMES, IS_WITH_CONTEXT>(
+ frame_pointer, ucp, stack_low, stack_high);
}
*min_dropped_frames = num_dropped_frames;
}
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/internal/stacktrace_powerpc-inl.inc b/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/internal/stacktrace_powerpc-inl.inc
index 56dcd40c670..9edbe28c843 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/internal/stacktrace_powerpc-inl.inc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/internal/stacktrace_powerpc-inl.inc
@@ -57,7 +57,7 @@ static inline void *StacktracePowerPCGetLR(void **sp) {
// This check is in case the compiler doesn't define _CALL_SYSV.
return *(sp+1);
#else
-#error Need to specify the PPC ABI for your archiecture.
+#error Need to specify the PPC ABI for your architecture.
#endif
}
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/internal/stacktrace_x86-inl.inc b/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/internal/stacktrace_x86-inl.inc
index 278a0b6da48..3ee3502b192 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/internal/stacktrace_x86-inl.inc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/internal/stacktrace_x86-inl.inc
@@ -40,7 +40,7 @@ using y_absl::debugging_internal::AddressIsReadable;
#if defined(__linux__) && defined(__i386__)
// Count "push %reg" instructions in VDSO __kernel_vsyscall(),
-// preceeding "syscall" or "sysenter".
+// preceding "syscall" or "sysenter".
// If __kernel_vsyscall uses frame pointer, answer 0.
//
// kMaxBytes tells how many instruction bytes of __kernel_vsyscall
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/internal/symbolize.h b/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/internal/symbolize.h
index c404b3cf91a..90a78d53174 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/internal/symbolize.h
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/internal/symbolize.h
@@ -115,7 +115,7 @@ bool RemoveSymbolDecorator(int ticket);
// Remove all installed decorators. Returns true if successful, false if
// symbolization is currently in progress.
-bool RemoveAllSymbolDecorators(void);
+bool RemoveAllSymbolDecorators();
// Registers an address range to a file mapping.
//
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/leak_check.cc b/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/leak_check.cc
index 1cddc78cc8a..323d50604cc 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/leak_check.cc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/leak_check.cc
@@ -65,8 +65,8 @@ bool LeakCheckerIsActive() { return false; }
void DoIgnoreLeak(const void*) { }
void RegisterLivePointers(const void*, size_t) { }
void UnRegisterLivePointers(const void*, size_t) { }
-LeakCheckDisabler::LeakCheckDisabler() { }
-LeakCheckDisabler::~LeakCheckDisabler() { }
+LeakCheckDisabler::LeakCheckDisabler() = default;
+LeakCheckDisabler::~LeakCheckDisabler() = default;
Y_ABSL_NAMESPACE_END
} // namespace y_absl
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/symbolize_elf.inc b/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/symbolize_elf.inc
index 33ad4a9b0c1..81e31e01c8e 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/symbolize_elf.inc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/symbolize_elf.inc
@@ -532,6 +532,11 @@ bool ForEachSection(int fd,
return false;
}
+ // Technically it can be larger, but in practice this never happens.
+ if (elf_header.e_shentsize != sizeof(ElfW(Shdr))) {
+ return false;
+ }
+
ElfW(Shdr) shstrtab;
off_t shstrtab_offset = static_cast<off_t>(elf_header.e_shoff) +
elf_header.e_shentsize * elf_header.e_shstrndx;
@@ -584,6 +589,11 @@ bool GetSectionHeaderByName(int fd, const char *name, size_t name_len,
return false;
}
+ // Technically it can be larger, but in practice this never happens.
+ if (elf_header.e_shentsize != sizeof(ElfW(Shdr))) {
+ return false;
+ }
+
ElfW(Shdr) shstrtab;
off_t shstrtab_offset = static_cast<off_t>(elf_header.e_shoff) +
elf_header.e_shentsize * elf_header.e_shstrndx;
@@ -648,8 +658,10 @@ static bool ShouldPickFirstSymbol(const ElfW(Sym) & symbol1,
}
// Return true if an address is inside a section.
-static bool InSection(const void *address, const ElfW(Shdr) * section) {
- const char *start = reinterpret_cast<const char *>(section->sh_addr);
+static bool InSection(const void *address, ptrdiff_t relocation,
+ const ElfW(Shdr) * section) {
+ const char *start = reinterpret_cast<const char *>(
+ section->sh_addr + static_cast<ElfW(Addr)>(relocation));
size_t size = static_cast<size_t>(section->sh_size);
return start <= address && address < (start + size);
}
@@ -689,8 +701,8 @@ static Y_ABSL_ATTRIBUTE_NOINLINE FindSymbolResult FindSymbol(
// starting address. However, we do not always want to use the real
// starting address because we sometimes want to symbolize a function
// pointer into the .opd section, e.g. FindSymbol(&foo,...).
- const bool pc_in_opd =
- kPlatformUsesOPDSections && opd != nullptr && InSection(pc, opd);
+ const bool pc_in_opd = kPlatformUsesOPDSections && opd != nullptr &&
+ InSection(pc, relocation, opd);
const bool deref_function_descriptor_pointer =
kPlatformUsesOPDSections && opd != nullptr && !pc_in_opd;
@@ -730,7 +742,7 @@ static Y_ABSL_ATTRIBUTE_NOINLINE FindSymbolResult FindSymbol(
#endif
if (deref_function_descriptor_pointer &&
- InSection(original_start_address, opd)) {
+ InSection(original_start_address, /*relocation=*/0, opd)) {
// The opd section is mapped into memory. Just dereference
// start_address to get the first double word, which points to the
// function entry.
@@ -1326,7 +1338,7 @@ static bool MaybeInitializeObjFile(ObjFile *obj) {
const int phnum = obj->elf_header.e_phnum;
const int phentsize = obj->elf_header.e_phentsize;
auto phoff = static_cast<off_t>(obj->elf_header.e_phoff);
- size_t num_executable_load_segments = 0;
+ size_t num_interesting_load_segments = 0;
for (int j = 0; j < phnum; j++) {
ElfW(Phdr) phdr;
if (!ReadFromOffsetExact(obj->fd, &phdr, sizeof(phdr), phoff)) {
@@ -1335,23 +1347,35 @@ static bool MaybeInitializeObjFile(ObjFile *obj) {
return false;
}
phoff += phentsize;
- constexpr int rx = PF_X | PF_R;
- if (phdr.p_type != PT_LOAD || (phdr.p_flags & rx) != rx) {
- // Not a LOAD segment, or not executable code.
+
+#if defined(__powerpc__) && !(_CALL_ELF > 1)
+ // On the PowerPC ELF v1 ABI, function pointers actually point to function
+ // descriptors. These descriptors are stored in an .opd section, which is
+ // mapped read-only. We thus need to look at all readable segments, not
+ // just the executable ones.
+ constexpr int interesting = PF_R;
+#else
+ constexpr int interesting = PF_X | PF_R;
+#endif
+
+ if (phdr.p_type != PT_LOAD
+ || (phdr.p_flags & interesting) != interesting) {
+ // Not a LOAD segment, not executable code, and not a function
+ // descriptor.
continue;
}
- if (num_executable_load_segments < obj->phdr.size()) {
- memcpy(&obj->phdr[num_executable_load_segments++], &phdr, sizeof(phdr));
+ if (num_interesting_load_segments < obj->phdr.size()) {
+ memcpy(&obj->phdr[num_interesting_load_segments++], &phdr, sizeof(phdr));
} else {
Y_ABSL_RAW_LOG(
- WARNING, "%s: too many executable LOAD segments: %zu >= %zu",
- obj->filename, num_executable_load_segments, obj->phdr.size());
+ WARNING, "%s: too many interesting LOAD segments: %zu >= %zu",
+ obj->filename, num_interesting_load_segments, obj->phdr.size());
break;
}
}
- if (num_executable_load_segments == 0) {
- // This object has no "r-x" LOAD segments. That's unexpected.
- Y_ABSL_RAW_LOG(WARNING, "%s: no executable LOAD segments", obj->filename);
+ if (num_interesting_load_segments == 0) {
+ // This object has no interesting LOAD segments. That's unexpected.
+ Y_ABSL_RAW_LOG(WARNING, "%s: no interesting LOAD segments", obj->filename);
return false;
}
}
@@ -1379,8 +1403,8 @@ const char *Symbolizer::GetUncachedSymbol(const void *pc) {
// X in the file will have a start address of [true relocation]+X.
relocation = static_cast<ptrdiff_t>(start_addr - obj->offset);
- // Note: some binaries have multiple "rx" LOAD segments. We must
- // find the right one.
+ // Note: some binaries have multiple LOAD segments that can contain
+ // function pointers. We must find the right one.
ElfW(Phdr) *phdr = nullptr;
for (size_t j = 0; j < obj->phdr.size(); j++) {
ElfW(Phdr) &p = obj->phdr[j];
@@ -1390,7 +1414,7 @@ const char *Symbolizer::GetUncachedSymbol(const void *pc) {
Y_ABSL_RAW_CHECK(p.p_type == PT_NULL, "unexpected p_type");
break;
}
- if (pc < reinterpret_cast<void *>(start_addr + p.p_memsz)) {
+ if (pc < reinterpret_cast<void *>(start_addr + p.p_vaddr + p.p_memsz)) {
phdr = &p;
break;
}
diff --git a/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/symbolize_emscripten.inc b/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/symbolize_emscripten.inc
index 5aa97cca46e..558160f9705 100644
--- a/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/symbolize_emscripten.inc
+++ b/contrib/restricted/abseil-cpp-tstring/y_absl/debugging/symbolize_emscripten.inc
@@ -50,6 +50,9 @@ bool Symbolize(const void* pc, char* out, int out_size) {
if (!HaveOffsetConverter()) {
return false;
}
+ if (pc == nullptr || out_size <= 0) {
+ return false;
+ }
const char* func_name = emscripten_pc_get_function(pc);
if (func_name == nullptr) {
return false;