From ce9c2cc6748c22ce4b0f5178b66668f5e877d430 Mon Sep 17 00:00:00 2001 From: Felipe de Azevedo Piovezan Date: Wed, 13 Aug 2025 18:38:23 -0700 Subject: [PATCH 1/8] [lldb] Call FixUpPointer in WritePointerToMemory (try 2) In architectures where pointers may contain metadata, such as arm64e, the metadata may need to be cleaned prior to sending this pointer to be used in expression evaluation generated code. This patch is a step towards allowing consumers of pointers to decide whether they want to keep or remove metadata, as opposed to discarding metadata at the moment pointers are created. See #150537. This was tested running the LLDB test suite on arm64e. (The first attempt at this patch caused a failure in TestScriptedProcessEmptyMemoryRegion.py. This test exercises a case where IRMemoryMap uses host memory in its allocations; pointers to such allocations should not be fixed, which is what the original patch failed to account for). --- lldb/source/Expression/IRMemoryMap.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lldb/source/Expression/IRMemoryMap.cpp b/lldb/source/Expression/IRMemoryMap.cpp index 150699352a2e3..3ac42649d0834 100644 --- a/lldb/source/Expression/IRMemoryMap.cpp +++ b/lldb/source/Expression/IRMemoryMap.cpp @@ -640,6 +640,13 @@ void IRMemoryMap::WritePointerToMemory(lldb::addr_t process_address, lldb::addr_t address, Status &error) { error.Clear(); + /// Only ask the Process to fix the address if this address belongs to the + /// process (host allocations are stored in m_data). + if (auto it = FindAllocation(process_address, 1); + it != m_allocations.end() && it->second.m_data.GetByteSize() == 0) + if (auto process_sp = GetProcessWP().lock()) + address = process_sp->FixAnyAddress(address); + Scalar scalar(address); WriteScalarToMemory(process_address, scalar, GetAddressByteSize(), error); From 36dcebb09eecd46f649feb4073c4f10b75423699 Mon Sep 17 00:00:00 2001 From: Felipe de Azevedo Piovezan Date: Thu, 14 Aug 2025 08:22:44 -0700 Subject: [PATCH 2/8] fixup! Improve comment --- lldb/source/Expression/IRMemoryMap.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lldb/source/Expression/IRMemoryMap.cpp b/lldb/source/Expression/IRMemoryMap.cpp index 3ac42649d0834..7faf6809383eb 100644 --- a/lldb/source/Expression/IRMemoryMap.cpp +++ b/lldb/source/Expression/IRMemoryMap.cpp @@ -641,7 +641,8 @@ void IRMemoryMap::WritePointerToMemory(lldb::addr_t process_address, error.Clear(); /// Only ask the Process to fix the address if this address belongs to the - /// process (host allocations are stored in m_data). + /// process. An address belongs to the process if the Allocation contains a + /// non-empty m_data member. if (auto it = FindAllocation(process_address, 1); it != m_allocations.end() && it->second.m_data.GetByteSize() == 0) if (auto process_sp = GetProcessWP().lock()) From 579c985eb3bbce4d10e86de7ff87238541936232 Mon Sep 17 00:00:00 2001 From: Felipe de Azevedo Piovezan Date: Thu, 14 Aug 2025 08:22:58 -0700 Subject: [PATCH 3/8] fixup! Add {} to if statement --- lldb/source/Expression/IRMemoryMap.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lldb/source/Expression/IRMemoryMap.cpp b/lldb/source/Expression/IRMemoryMap.cpp index 7faf6809383eb..8b6d87b589c1b 100644 --- a/lldb/source/Expression/IRMemoryMap.cpp +++ b/lldb/source/Expression/IRMemoryMap.cpp @@ -644,9 +644,10 @@ void IRMemoryMap::WritePointerToMemory(lldb::addr_t process_address, /// process. An address belongs to the process if the Allocation contains a /// non-empty m_data member. if (auto it = FindAllocation(process_address, 1); - it != m_allocations.end() && it->second.m_data.GetByteSize() == 0) + it != m_allocations.end() && it->second.m_data.GetByteSize() == 0) { if (auto process_sp = GetProcessWP().lock()) address = process_sp->FixAnyAddress(address); + } Scalar scalar(address); From d098df34532dfc20a2e6b1f566082ce5b9af24d9 Mon Sep 17 00:00:00 2001 From: Felipe de Azevedo Piovezan Date: Wed, 27 Aug 2025 14:26:29 -0700 Subject: [PATCH 4/8] fixup! Fix address confusion --- lldb/source/Expression/IRMemoryMap.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lldb/source/Expression/IRMemoryMap.cpp b/lldb/source/Expression/IRMemoryMap.cpp index 8b6d87b589c1b..26e59b76a4dac 100644 --- a/lldb/source/Expression/IRMemoryMap.cpp +++ b/lldb/source/Expression/IRMemoryMap.cpp @@ -641,13 +641,13 @@ void IRMemoryMap::WritePointerToMemory(lldb::addr_t process_address, error.Clear(); /// Only ask the Process to fix the address if this address belongs to the - /// process. An address belongs to the process if the Allocation contains a - /// non-empty m_data member. - if (auto it = FindAllocation(process_address, 1); - it != m_allocations.end() && it->second.m_data.GetByteSize() == 0) { + /// process. An address belongs to the process if the Allocation policy is not + /// eAllocationPolicyHostOnly. + auto it = FindAllocation(address, 1); + if (it == m_allocations.end() || + it->second.m_policy != AllocationPolicy::eAllocationPolicyHostOnly) if (auto process_sp = GetProcessWP().lock()) address = process_sp->FixAnyAddress(address); - } Scalar scalar(address); From e96470ae39d16a1ebd0f94595b65e22cace5d829 Mon Sep 17 00:00:00 2001 From: Felipe de Azevedo Piovezan Date: Tue, 2 Sep 2025 11:23:40 -0700 Subject: [PATCH 5/8] fixup! Add test --- .../arm-pointer-metadata-stripping/Makefile | 2 + .../TestArmPointerMetadataStripping.py | 50 +++++++++++++++++++ .../extra_symbols.json | 21 ++++++++ .../arm-pointer-metadata-stripping/main.c | 20 ++++++++ 4 files changed, 93 insertions(+) create mode 100644 lldb/test/API/macosx/arm-pointer-metadata-stripping/Makefile create mode 100644 lldb/test/API/macosx/arm-pointer-metadata-stripping/TestArmPointerMetadataStripping.py create mode 100644 lldb/test/API/macosx/arm-pointer-metadata-stripping/extra_symbols.json create mode 100644 lldb/test/API/macosx/arm-pointer-metadata-stripping/main.c diff --git a/lldb/test/API/macosx/arm-pointer-metadata-stripping/Makefile b/lldb/test/API/macosx/arm-pointer-metadata-stripping/Makefile new file mode 100644 index 0000000000000..c9319d6e6888a --- /dev/null +++ b/lldb/test/API/macosx/arm-pointer-metadata-stripping/Makefile @@ -0,0 +1,2 @@ +C_SOURCES := main.c +include Makefile.rules diff --git a/lldb/test/API/macosx/arm-pointer-metadata-stripping/TestArmPointerMetadataStripping.py b/lldb/test/API/macosx/arm-pointer-metadata-stripping/TestArmPointerMetadataStripping.py new file mode 100644 index 0000000000000..e62f714b402a9 --- /dev/null +++ b/lldb/test/API/macosx/arm-pointer-metadata-stripping/TestArmPointerMetadataStripping.py @@ -0,0 +1,50 @@ +import lldb +import json +import os +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +@skipIf(archs=no_match(["arm64", "arm64e"])) +class TestArmPointerMetadataStripping(TestBase): + # Use extra_symbols.json as a template to add a new symbol whose address + # contains non-zero high order bits set. + def create_symbols_file(self): + template_path = os.path.join(self.getSourceDir(), "extra_symbols.json") + with open(template_path, "r") as f: + symbols_data = json.load(f) + + target = self.dbg.GetSelectedTarget() + symbols_data["triple"] = target.GetTriple() + + module = target.GetModuleAtIndex(0) + symbols_data["uuid"] = module.GetUUIDString() + + json_filename = self.getBuildArtifact("extra_symbols.json") + with open(json_filename, "w") as file: + json.dump(symbols_data, file, indent=4) + + return json_filename + + def test(self): + self.build() + src = lldb.SBFileSpec("main.c") + target, process, thread, bkpt = lldbutil.run_to_source_breakpoint( + self, "break here", src + ) + + self.expect_expr("get_high_bits(&x)", result_value="0") + self.expect_expr("get_high_bits(&myglobal)", result_value="0") + + symbols_file = self.create_symbols_file() + + # The high order bits should be stripped. + self.runCmd(f"target module add {symbols_file}") + self.expect_expr("get_high_bits(&myglobal_json)", result_value="0") + + # Mark all bits as used for addresses and ensure bits are no longer stripped. + self.runCmd("settings set target.process.virtual-addressable-bits 64") + self.expect_expr( + "get_high_bits(&myglobal_json)", result_value=str(0x1200000000000000) + ) diff --git a/lldb/test/API/macosx/arm-pointer-metadata-stripping/extra_symbols.json b/lldb/test/API/macosx/arm-pointer-metadata-stripping/extra_symbols.json new file mode 100644 index 0000000000000..eadd9f2d8c391 --- /dev/null +++ b/lldb/test/API/macosx/arm-pointer-metadata-stripping/extra_symbols.json @@ -0,0 +1,21 @@ +{ + "triple": "replace me", + "uuid": "replace me", + "type": "executable", + "sections": [ + { + "name": "__DATA", + "type": "data", + "address": 1297224342667202580, + "size": 16 + } + ], + "symbols": [ + { + "name": "myglobal_json", + "size": 8, + "type": "data", + "address": 1297224342667202580 + } + ] +} diff --git a/lldb/test/API/macosx/arm-pointer-metadata-stripping/main.c b/lldb/test/API/macosx/arm-pointer-metadata-stripping/main.c new file mode 100644 index 0000000000000..cad88495e6fa7 --- /dev/null +++ b/lldb/test/API/macosx/arm-pointer-metadata-stripping/main.c @@ -0,0 +1,20 @@ +#include +#include +#include + + +int myglobal = 41; + +uint64_t get_high_bits(void *ptr) { + uint64_t mask = ~((1ULL << 48) - 1); + uint64_t ptrtoint = (uint64_t)ptr; + uint64_t high_bits = ptrtoint & mask; + printf("Higher bits are = %llx\n", high_bits); + return high_bits; +} + +int main (){ + int x = 42; + assert(0 == get_high_bits(&x)); + return 0; //break here +} From 293e1ddb21351b5d62776baaaea18868896f3aca Mon Sep 17 00:00:00 2001 From: Felipe de Azevedo Piovezan Date: Tue, 2 Sep 2025 13:05:31 -0700 Subject: [PATCH 6/8] fixup! Clang-format test --- .../arm-pointer-metadata-stripping/extra_symbols.json | 10 +++++----- .../API/macosx/arm-pointer-metadata-stripping/main.c | 5 ++--- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/lldb/test/API/macosx/arm-pointer-metadata-stripping/extra_symbols.json b/lldb/test/API/macosx/arm-pointer-metadata-stripping/extra_symbols.json index eadd9f2d8c391..5c2503d508b42 100644 --- a/lldb/test/API/macosx/arm-pointer-metadata-stripping/extra_symbols.json +++ b/lldb/test/API/macosx/arm-pointer-metadata-stripping/extra_symbols.json @@ -3,19 +3,19 @@ "uuid": "replace me", "type": "executable", "sections": [ - { + { "name": "__DATA", "type": "data", "address": 1297224342667202580, "size": 16 - } - ], + } + ], "symbols": [ { "name": "myglobal_json", "size": 8, "type": "data", "address": 1297224342667202580 - } - ] + } + ] } diff --git a/lldb/test/API/macosx/arm-pointer-metadata-stripping/main.c b/lldb/test/API/macosx/arm-pointer-metadata-stripping/main.c index cad88495e6fa7..71d22bd2d8e11 100644 --- a/lldb/test/API/macosx/arm-pointer-metadata-stripping/main.c +++ b/lldb/test/API/macosx/arm-pointer-metadata-stripping/main.c @@ -2,7 +2,6 @@ #include #include - int myglobal = 41; uint64_t get_high_bits(void *ptr) { @@ -13,8 +12,8 @@ uint64_t get_high_bits(void *ptr) { return high_bits; } -int main (){ +int main() { int x = 42; assert(0 == get_high_bits(&x)); - return 0; //break here + return 0; // break here } From 7f02dbd5df68d22e2fae3a09f1b082070d985d5b Mon Sep 17 00:00:00 2001 From: Felipe de Azevedo Piovezan Date: Wed, 3 Sep 2025 07:20:00 -0700 Subject: [PATCH 7/8] fixup! Address test feedback --- .../TestArmPointerMetadataStripping.py | 7 ++----- .../macosx/arm-pointer-metadata-stripping/main.c | 16 +++++----------- 2 files changed, 7 insertions(+), 16 deletions(-) diff --git a/lldb/test/API/macosx/arm-pointer-metadata-stripping/TestArmPointerMetadataStripping.py b/lldb/test/API/macosx/arm-pointer-metadata-stripping/TestArmPointerMetadataStripping.py index e62f714b402a9..4f064cf662be9 100644 --- a/lldb/test/API/macosx/arm-pointer-metadata-stripping/TestArmPointerMetadataStripping.py +++ b/lldb/test/API/macosx/arm-pointer-metadata-stripping/TestArmPointerMetadataStripping.py @@ -5,7 +5,7 @@ from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil - +@skipUnlessDarwin @skipIf(archs=no_match(["arm64", "arm64e"])) class TestArmPointerMetadataStripping(TestBase): # Use extra_symbols.json as a template to add a new symbol whose address @@ -34,13 +34,10 @@ def test(self): self, "break here", src ) - self.expect_expr("get_high_bits(&x)", result_value="0") - self.expect_expr("get_high_bits(&myglobal)", result_value="0") - symbols_file = self.create_symbols_file() + self.runCmd(f"target module add {symbols_file}") # The high order bits should be stripped. - self.runCmd(f"target module add {symbols_file}") self.expect_expr("get_high_bits(&myglobal_json)", result_value="0") # Mark all bits as used for addresses and ensure bits are no longer stripped. diff --git a/lldb/test/API/macosx/arm-pointer-metadata-stripping/main.c b/lldb/test/API/macosx/arm-pointer-metadata-stripping/main.c index 71d22bd2d8e11..05a85133caf72 100644 --- a/lldb/test/API/macosx/arm-pointer-metadata-stripping/main.c +++ b/lldb/test/API/macosx/arm-pointer-metadata-stripping/main.c @@ -1,19 +1,13 @@ -#include #include -#include -int myglobal = 41; - -uint64_t get_high_bits(void *ptr) { - uint64_t mask = ~((1ULL << 48) - 1); - uint64_t ptrtoint = (uint64_t)ptr; - uint64_t high_bits = ptrtoint & mask; - printf("Higher bits are = %llx\n", high_bits); +uintptr_t get_high_bits(void *ptr) { + uintptr_t address_bits = 56; + uintptr_t mask = ~((1ULL << address_bits) - 1); + uintptr_t ptrtoint = (uintptr_t)ptr; + uintptr_t high_bits = ptrtoint & mask; return high_bits; } int main() { - int x = 42; - assert(0 == get_high_bits(&x)); return 0; // break here } From 1431f5ea456fc1b2128e1175d4fa9e1bc2313fbb Mon Sep 17 00:00:00 2001 From: Felipe de Azevedo Piovezan Date: Wed, 3 Sep 2025 07:35:24 -0700 Subject: [PATCH 8/8] fixup! Fix python formatting --- .../TestArmPointerMetadataStripping.py | 1 + 1 file changed, 1 insertion(+) diff --git a/lldb/test/API/macosx/arm-pointer-metadata-stripping/TestArmPointerMetadataStripping.py b/lldb/test/API/macosx/arm-pointer-metadata-stripping/TestArmPointerMetadataStripping.py index 4f064cf662be9..f61945b3eb4c9 100644 --- a/lldb/test/API/macosx/arm-pointer-metadata-stripping/TestArmPointerMetadataStripping.py +++ b/lldb/test/API/macosx/arm-pointer-metadata-stripping/TestArmPointerMetadataStripping.py @@ -5,6 +5,7 @@ from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil + @skipUnlessDarwin @skipIf(archs=no_match(["arm64", "arm64e"])) class TestArmPointerMetadataStripping(TestBase):