From 4d6cb98f276c549acbf78e9749ebc8f4eaed899f Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Thu, 13 Mar 2025 15:44:00 -0700 Subject: [PATCH] Migrate ClearPacBits() to a more generic implementation and location PiperOrigin-RevId: 736664098 Change-Id: Ic99ff4ebae02097b9f7691ebdcb2e10f7d255834 --- CMake/AbseilDll.cmake | 1 + absl/debugging/BUILD.bazel | 1 + absl/debugging/CMakeLists.txt | 1 + absl/debugging/internal/addresses.h | 53 +++++++++++++++++++ .../internal/stacktrace_aarch64-inl.inc | 20 ++----- 5 files changed, 59 insertions(+), 17 deletions(-) create mode 100644 absl/debugging/internal/addresses.h diff --git a/CMake/AbseilDll.cmake b/CMake/AbseilDll.cmake index e318d721..df071afe 100644 --- a/CMake/AbseilDll.cmake +++ b/CMake/AbseilDll.cmake @@ -126,6 +126,7 @@ set(ABSL_INTERNAL_DLL_FILES "debugging/symbolize.h" "debugging/internal/address_is_readable.cc" "debugging/internal/address_is_readable.h" + "debugging/internal/addresses.h" "debugging/internal/bounded_utf8_length_sequence.h" "debugging/internal/decode_rust_punycode.cc" "debugging/internal/decode_rust_punycode.h" diff --git a/absl/debugging/BUILD.bazel b/absl/debugging/BUILD.bazel index 6e61bb36..01d3230a 100644 --- a/absl/debugging/BUILD.bazel +++ b/absl/debugging/BUILD.bazel @@ -202,6 +202,7 @@ cc_library( ], hdrs = [ "internal/address_is_readable.h", + "internal/addresses.h", "internal/elf_mem_image.h", "internal/vdso_support.h", ], diff --git a/absl/debugging/CMakeLists.txt b/absl/debugging/CMakeLists.txt index a96b4f39..30eeb5bf 100644 --- a/absl/debugging/CMakeLists.txt +++ b/absl/debugging/CMakeLists.txt @@ -174,6 +174,7 @@ absl_cc_library( debugging_internal HDRS "internal/address_is_readable.h" + "internal/addresses.h" "internal/elf_mem_image.h" "internal/vdso_support.h" SRCS diff --git a/absl/debugging/internal/addresses.h b/absl/debugging/internal/addresses.h new file mode 100644 index 00000000..e40c54e5 --- /dev/null +++ b/absl/debugging/internal/addresses.h @@ -0,0 +1,53 @@ +// Copyright 2025 The Abseil Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef ABSL_DEBUGGING_INTERNAL_ADDRESSES_H_ +#define ABSL_DEBUGGING_INTERNAL_ADDRESSES_H_ + +#include + +#include "absl/base/config.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace debugging_internal { + +// Removes any metadata (tag bits) from the given pointer, converting it into a +// user-readable address. +inline uintptr_t StripPointerMetadata(void* ptr) { +#if defined(__aarch64__) + // When PAC-RET (-mbranch-protection=pac-ret) is enabled, return addresses + // stored on the stack will be signed, which means that pointer bits outside + // of the virtual address range are potentially set. Since the stacktrace code + // is expected to return normal code pointers, this function clears those + // bits. + register uintptr_t x30 __asm__("x30") = reinterpret_cast(ptr); + // The normal instruction for clearing PAC bits is XPACI, but for + // compatibility with ARM platforms that do not support pointer + // authentication, we use the hint space instruction XPACLRI instead. Hint + // space instructions behave as NOPs on unsupported platforms. +#define ABSL_XPACLRI_HINT "hint #0x7;" + asm(ABSL_XPACLRI_HINT : "+r"(x30)); // asm("xpaclri" : "+r"(x30)); +#undef ABSL_XPACLRI_HINT + return x30; +#else + return reinterpret_cast(ptr); +#endif +} + +} // namespace debugging_internal +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_DEBUGGING_INTERNAL_ADDRESSES_H_ diff --git a/absl/debugging/internal/stacktrace_aarch64-inl.inc b/absl/debugging/internal/stacktrace_aarch64-inl.inc index dccadaeb..baea9a89 100644 --- a/absl/debugging/internal/stacktrace_aarch64-inl.inc +++ b/absl/debugging/internal/stacktrace_aarch64-inl.inc @@ -18,6 +18,7 @@ #include "absl/base/attributes.h" #include "absl/debugging/internal/address_is_readable.h" +#include "absl/debugging/internal/addresses.h" #include "absl/debugging/internal/vdso_support.h" // a no-op on non-elf or non-glibc systems #include "absl/debugging/stacktrace.h" @@ -178,22 +179,6 @@ static void **NextStackFrame(void **old_frame_pointer, const void *uc, return new_frame_pointer; } -// When PAC-RET (-mbranch-protection=pac-ret) is enabled, return addresses -// stored on the stack will be signed, which means that pointer bits outside of -// the VA range are potentially set. Since the stacktrace code is expected to -// return normal code pointers, this function clears those bits. -inline void* ClearPacBits(void* ptr) { - register void* x30 __asm__("x30") = ptr; - // The normal instruction for clearing PAC bits is XPACI, but for - // compatibility with ARM platforms that do not support pointer - // authentication, we use the hint space instruction XPACLRI instead. Hint - // space instructions behave as NOPs on unsupported platforms. -#define ABSL_XPACLRI_HINT "hint #0x7;" - asm(ABSL_XPACLRI_HINT : "+r"(x30)); // asm("xpaclri" : "+r"(x30)); -#undef ABSL_XPACLRI_HINT - return x30; -} - template // We count on the bottom frame being this one. See the comment // at prev_return_address @@ -235,7 +220,8 @@ static int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count, if (skip_count > 0) { skip_count--; } else { - result[n] = ClearPacBits(prev_return_address); + result[n] = reinterpret_cast( + absl::debugging_internal::StripPointerMetadata(prev_return_address)); if (IS_STACK_FRAMES) { sizes[n] = static_cast( ComputeStackFrameSize(prev_frame_pointer, frame_pointer));