[Lldb-commits] [lldb] [lldb] Introduce Process::FixAnyAddressPreservingAuthentication (PR #159785)
Felipe de Azevedo Piovezan via lldb-commits
lldb-commits at lists.llvm.org
Fri Sep 19 08:06:27 PDT 2025
https://github.com/felipepiovezan updated https://github.com/llvm/llvm-project/pull/159785
>From cba7da1439a4d574906422856739dbdbb9590248 Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <fpiovezan at apple.com>
Date: Thu, 18 Sep 2025 14:45:00 -0700
Subject: [PATCH] [lldb] Introduce
Process::FixAnyAddressPreservingAuthentication
This is yet another variant of the Fix{Code,Data}Address methods, but
tailored for pointers that both:
1. Are going to be used in-process,
2. Require authentication metadata.
Currently, the callsite inside IRMemoryMap::WritePointerToMemory is an
example of 1; the pointer written to memory will be used by JITed code
during expression evaluation.
An example of (2) can be found in the MTE extension on arm processors.
An MTE-tagged pointer must preserve its normal bits in order for load
instructions to complete without faulting. However, PAC bits must be
stripped, as codegen for some expressions may generate regular load
instructions for accesses to those (instead of the special PAC
instructions).
---
lldb/include/lldb/Target/ABI.h | 4 ++++
lldb/include/lldb/Target/Process.h | 5 +++++
lldb/source/Expression/IRMemoryMap.cpp | 2 +-
lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp | 9 +++++++++
lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h | 1 +
lldb/source/Target/Process.cpp | 6 ++++++
.../TestArmPointerMetadataStripping.py | 9 ++++++++-
7 files changed, 34 insertions(+), 2 deletions(-)
diff --git a/lldb/include/lldb/Target/ABI.h b/lldb/include/lldb/Target/ABI.h
index 1a1f1724222e3..0839df5ac7cf3 100644
--- a/lldb/include/lldb/Target/ABI.h
+++ b/lldb/include/lldb/Target/ABI.h
@@ -141,6 +141,10 @@ class ABI : public PluginInterface {
return FixDataAddress(pc);
}
+ virtual lldb::addr_t FixAnyAddressPreservingAuthentication(lldb::addr_t pc) {
+ return FixAnyAddress(pc);
+ }
+
llvm::MCRegisterInfo &GetMCRegisterInfo() { return *m_mc_register_info_up; }
virtual void
diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index dc75d98acea70..0ad891955cfd1 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -1464,6 +1464,11 @@ class Process : public std::enable_shared_from_this<Process>,
/// platforms where there is a difference (only Arm Thumb at this time).
lldb::addr_t FixAnyAddress(lldb::addr_t pc);
+ /// Strip pointer metadata except for the bits necessary to authenticate a
+ /// memory access. This is useful, for example, if `address` requires
+ /// authentication and it is going to be consumed in JITed code.
+ lldb::addr_t FixAnyAddressPreservingAuthentication(lldb::addr_t address);
+
/// Get the Modification ID of the process.
///
/// \return
diff --git a/lldb/source/Expression/IRMemoryMap.cpp b/lldb/source/Expression/IRMemoryMap.cpp
index f978217fa8f2b..3df2fc072f227 100644
--- a/lldb/source/Expression/IRMemoryMap.cpp
+++ b/lldb/source/Expression/IRMemoryMap.cpp
@@ -647,7 +647,7 @@ void IRMemoryMap::WritePointerToMemory(lldb::addr_t process_address,
if (it == m_allocations.end() ||
it->second.m_policy != AllocationPolicy::eAllocationPolicyHostOnly)
if (auto process_sp = GetProcessWP().lock())
- pointer = process_sp->FixAnyAddress(pointer);
+ pointer = process_sp->FixAnyAddressPreservingAuthentication(pointer);
Scalar scalar(pointer);
diff --git a/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp b/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp
index c595564f6fb8e..700413ed6d26a 100644
--- a/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp
+++ b/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.cpp
@@ -792,6 +792,15 @@ addr_t ABIMacOSX_arm64::FixDataAddress(addr_t addr) {
return DoFixAddr(addr, false /*is_code*/, GetProcessSP());
}
+addr_t ABIMacOSX_arm64::FixAnyAddressPreservingAuthentication(addr_t addr) {
+ // Save the old MTE tag and restore it later.
+ constexpr addr_t mte_mask = 0x0f00000000000000ULL;
+ addr_t old_mte_tag = addr & mte_mask;
+
+ addr_t fixed_addr = FixDataAddress(addr);
+ return old_mte_tag | (fixed_addr & (~mte_mask));
+}
+
void ABIMacOSX_arm64::Initialize() {
PluginManager::RegisterPlugin(GetPluginNameStatic(), pluginDesc,
CreateInstance);
diff --git a/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h b/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h
index c8851709f50ad..b7eb695bdc9c9 100644
--- a/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h
+++ b/lldb/source/Plugins/ABI/AArch64/ABIMacOSX_arm64.h
@@ -59,6 +59,7 @@ class ABIMacOSX_arm64 : public ABIAArch64 {
lldb::addr_t FixCodeAddress(lldb::addr_t pc) override;
lldb::addr_t FixDataAddress(lldb::addr_t pc) override;
+ lldb::addr_t FixAnyAddressPreservingAuthentication(lldb::addr_t pc) override;
// Static Functions
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 3176852f0b724..562c8544af72b 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -5971,6 +5971,12 @@ addr_t Process::FixAnyAddress(addr_t addr) {
return addr;
}
+addr_t Process::FixAnyAddressPreservingAuthentication(addr_t addr) {
+ if (ABISP abi_sp = GetABI())
+ addr = abi_sp->FixAnyAddressPreservingAuthentication(addr);
+ return addr;
+}
+
void Process::DidExec() {
Log *log = GetLog(LLDBLog::Process);
LLDB_LOGF(log, "Process::%s()", __FUNCTION__);
diff --git a/lldb/test/API/pointer-nonaddressable-bits/TestArmPointerMetadataStripping.py b/lldb/test/API/pointer-nonaddressable-bits/TestArmPointerMetadataStripping.py
index 059fd9cf4ba7f..68ba61c8bbfb2 100644
--- a/lldb/test/API/pointer-nonaddressable-bits/TestArmPointerMetadataStripping.py
+++ b/lldb/test/API/pointer-nonaddressable-bits/TestArmPointerMetadataStripping.py
@@ -41,8 +41,15 @@ def test(self):
symbols_file = self.create_symbols_file()
self.runCmd(f"target module add {symbols_file}")
+ # The address of myglobal_json is: 0x1200AAAAAAAB1014
# The high order bits should be stripped.
- self.expect_expr("get_high_bits(&myglobal_json)", result_value="0")
+ # On Darwin platforms, the lower nibble of the most significant byte is preserved.
+ if platform.system() == "Darwin":
+ expected_value = str(0x200000000000000)
+ else:
+ expected_value = "0"
+
+ self.expect_expr("get_high_bits(&myglobal_json)", result_value=expected_value)
# Mark all bits as used for addresses and ensure bits are no longer stripped.
self.runCmd("settings set target.process.virtual-addressable-bits 64")
More information about the lldb-commits
mailing list