From 802fc1139742bf29ea43cecb0eb508bd2e7564fe Mon Sep 17 00:00:00 2001 From: Katarzyna Kubaj Date: Sun, 30 Aug 2026 21:41:56 +0200 Subject: [PATCH 1/2] Fix saved-LR slot for 32-bit ELF PowerPC in the stacktrace unwinder StacktracePowerPCGetLRPtr() falls back to OS checks when the compiler does not provide the _CALL_* ABI macros. Clang defines neither _CALL_SYSV nor _CALL_AIX on any FreeBSD PowerPC target (64-bit gets only _CALL_ELF=2), so 32-bit powerpc-*-freebsd hits the __FreeBSD__ fallback and reads the LR from sp[2]. The 32-bit SVR4 ABI saves the LR in the second word of the frame, sp[1]; sp[2] is correct only for the 64-bit ELF ABIs and Darwin/AIX. Verified against clang codegen: powerpc-unknown-freebsd emits "stwu 1,-16(1); stw 0,20(1)" (old SP + 4) while powerpc64-unknown-freebsd emits "stdu 1,-48(1); std 0,64(1)" (old SP + 16). Key the fallback on the word size instead of the OS: any __PPC64__ target uses sp[2], and 32-bit ELF targets (Linux, FreeBSD) use sp[1]. This is behavior-preserving for Linux and for 64-bit FreeBSD, and fixes the 32-bit FreeBSD case (currently latent, since stacktrace_config.h does not select this unwinder on FreeBSD). --- absl/debugging/internal/stacktrace_powerpc-inl.inc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/absl/debugging/internal/stacktrace_powerpc-inl.inc b/absl/debugging/internal/stacktrace_powerpc-inl.inc index f23c29cb0a0..b2082157017 100644 --- a/absl/debugging/internal/stacktrace_powerpc-inl.inc +++ b/absl/debugging/internal/stacktrace_powerpc-inl.inc @@ -51,11 +51,10 @@ static inline void **StacktracePowerPCGetLRPtr(void **sp) { return (sp + 2); #elif defined(_CALL_SYSV) return (sp + 1); -#elif defined(__APPLE__) || defined(__FreeBSD__) || \ - (defined(__linux__) && defined(__PPC64__)) +#elif defined(__APPLE__) || defined(__PPC64__) // This check is in case the compiler doesn't define _CALL_AIX/etc. return (sp + 2); -#elif defined(__linux) +#elif defined(__linux) || defined(__FreeBSD__) // This check is in case the compiler doesn't define _CALL_SYSV. return (sp + 1); #else From 8f4431186a50594b7dced86835d4b0a5be708dd6 Mon Sep 17 00:00:00 2001 From: Katarzyna Kubaj Date: Sun, 30 Aug 2026 20:54:20 +0200 Subject: [PATCH 2/2] Fix UnscaledCycleClock::Frequency() on FreeBSD/PowerPC The FreeBSD branch reads the kern.timecounter.tc.timebase.frequency sysctl straight into a double. The kernel registers that OID as CTLTYPE_U64 (sys/kern/kern_tc.c, tc_init()), so sysctlbyname() fills the 8-byte buffer with the integer 512000000 and the bits are then interpreted as an IEEE double: Frequency() returns ~2.5e-315 instead of 5.12e+08. The size check cannot catch this because uint64_t and double are both 8 bytes. Observed on FreeBSD 15.1 powerpc64le and powerpc64 (POWER9): - LOG_EVERY_N_SEC / VLOG_EVERY_N_SEC never rate-limit, because LogEveryNSecState::ShouldLog() computes the next log time as now + seconds * Frequency() ~= now (1000 of 1000 iterations logged with a 3600 s period). - Mutex waiters refresh their pthread_getschedparam() cache on every block instead of once per second. Read the sysctl into a uint64_t and convert to double; keep 0.0 if the sysctl fails. --- absl/base/internal/unscaledcycleclock.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/absl/base/internal/unscaledcycleclock.cc b/absl/base/internal/unscaledcycleclock.cc index 9e931808412..28fe66e0fdd 100644 --- a/absl/base/internal/unscaledcycleclock.cc +++ b/absl/base/internal/unscaledcycleclock.cc @@ -99,9 +99,12 @@ double UnscaledCycleClock::Frequency() { static once_flag init_timebase_frequency_once; static double timebase_frequency = 0.0; base_internal::LowLevelCallOnce(&init_timebase_frequency_once, [&]() { - size_t length = sizeof(timebase_frequency); - sysctlbyname("kern.timecounter.tc.timebase.frequency", &timebase_frequency, - &length, nullptr, 0); + uint64_t freq = 0; + size_t length = sizeof(freq); + if (sysctlbyname("kern.timecounter.tc.timebase.frequency", &freq, &length, + nullptr, 0) == 0) { + timebase_frequency = static_cast(freq); + } }); return timebase_frequency; #else