Migrate ClearPacBits() to a more generic implementation and location

PiperOrigin-RevId: 736664098
Change-Id: Ic99ff4ebae02097b9f7691ebdcb2e10f7d255834
This commit is contained in:
Abseil Team
2025-03-13 15:44:00 -07:00
committed by Copybara-Service
parent 45acc96832
commit 4d6cb98f27
5 changed files with 59 additions and 17 deletions

View File

@@ -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"

View File

@@ -202,6 +202,7 @@ cc_library(
],
hdrs = [
"internal/address_is_readable.h",
"internal/addresses.h",
"internal/elf_mem_image.h",
"internal/vdso_support.h",
],

View File

@@ -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

View File

@@ -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_

View File

@@ -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 <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 @@ 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<void *>(
absl::debugging_internal::StripPointerMetadata(prev_return_address));
if (IS_STACK_FRAMES) {
sizes[n] = static_cast<int>(
ComputeStackFrameSize(prev_frame_pointer, frame_pointer));