Migrate ClearPacBits() to a more generic implementation and location PiperOrigin-RevId: 736664098 Change-Id: Ic99ff4ebae02097b9f7691ebdcb2e10f7d255834
diff --git a/CMake/AbseilDll.cmake b/CMake/AbseilDll.cmake index e318d72..df071af 100644 --- a/CMake/AbseilDll.cmake +++ b/CMake/AbseilDll.cmake
@@ -126,6 +126,7 @@ "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 6e61bb3..01d3230 100644 --- a/absl/debugging/BUILD.bazel +++ b/absl/debugging/BUILD.bazel
@@ -202,6 +202,7 @@ ], 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 a96b4f3..30eeb5b 100644 --- a/absl/debugging/CMakeLists.txt +++ b/absl/debugging/CMakeLists.txt
@@ -174,6 +174,7 @@ 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 0000000..e40c54e --- /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 <stdint.h> + +#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<uintptr_t>(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<uintptr_t>(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 dccadae..baea9a8 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 @@ 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 <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT> // We count on the bottom frame being this one. See the comment // at prev_return_address @@ -235,7 +220,8 @@ if (skip_count > 0) { skip_count--; } else { - result[n] = ClearPacBits(prev_return_address); + result[n] = reinterpret_cast<void *>( + absl::debugging_internal::StripPointerMetadata(prev_return_address)); if (IS_STACK_FRAMES) { sizes[n] = static_cast<int>( ComputeStackFrameSize(prev_frame_pointer, frame_pointer));