[Lldb-commits] [lldb] 6a5fe4b - [lldb] Confine host shared cache reads to mapped segments (#205454)
via lldb-commits
lldb-commits at lists.llvm.org
Fri Jun 26 08:54:15 PDT 2026
Author: Jonas Devlieghere
Date: 2026-06-26T08:54:09-07:00
New Revision: 6a5fe4bf112d2d60f7e03a233d486ff502ce1b8c
URL: https://github.com/llvm/llvm-project/commit/6a5fe4bf112d2d60f7e03a233d486ff502ce1b8c
DIFF: https://github.com/llvm/llvm-project/commit/6a5fe4bf112d2d60f7e03a233d486ff502ce1b8c.diff
LOG: [lldb] Confine host shared cache reads to mapped segments (#205454)
When reading shared cache libraries out of lldb's own memory (the
default, eSymbolSharedCacheUseHostAndInferiorSharedCache), the dyld
introspection path built a plain DataExtractor spanning an image's
[minVmAddr, maxVmAddr). A shared cache image's segments may not be
contiguous: other images' data and unmapped guard pages may lie between
them.
Take advantage of the VirtualDataExtractor with a per-segment lookup
table instead, matching the map_shared_cache_binary_segments path, so
reads are confined to mapped segments.
Added:
lldb/test/API/macosx/shared-cache-host-memory/Makefile
lldb/test/API/macosx/shared-cache-host-memory/TestSharedCacheHostMemory.py
lldb/test/API/macosx/shared-cache-host-memory/main.c
Modified:
lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm
Removed:
################################################################################
diff --git a/lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm b/lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm
index 75a584d90121a..69f8bbdce91f6 100644
--- a/lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm
+++ b/lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm
@@ -32,6 +32,8 @@
// C++ Includes
#include <optional>
#include <string>
+#include <utility>
+#include <vector>
// C inclues
#include <cstdlib>
@@ -1023,6 +1025,10 @@ static DataExtractorSP map_shared_cache_binary_segments(void *image) {
__block uint64_t maxVmAddr = 0;
uuid_t uuidStore;
__block uuid_t *uuid = &uuidStore;
+ // A shared cache image's segments can occupy non-adjacent regions of the
+ // cache. Keep track of the segment's start and end so we can build a
+ // VirtualDataExtractor that prevents reads between segments.
+ __block std::vector<std::pair<uint64_t, uint64_t>> segments;
dyld_image_for_each_segment_info(
image,
@@ -1030,12 +1036,22 @@ static DataExtractorSP map_shared_cache_binary_segments(void *image) {
minVmAddr = std::min(minVmAddr, vmAddr);
maxVmAddr = std::max(maxVmAddr, vmAddr + vmSize);
dyld_image_copy_uuid(image, uuid);
+ if (vmSize > 0)
+ segments.emplace_back(vmAddr, vmSize);
});
assert(minVmAddr != UINT_MAX);
assert(maxVmAddr != 0);
lldb::DataBufferSP data_sp = std::make_shared<DataBufferUnowned>(
(uint8_t *)minVmAddr, maxVmAddr - minVmAddr);
- lldb::DataExtractorSP extractor_sp = std::make_shared<DataExtractor>(data_sp);
+ // Data is read in place from lldb's own shared cache, so each segment's
+ // virtual offset (image base at 0) equals its physical offset in the
+ // buffer.
+ VirtualDataExtractor::LookupTable table;
+ for (const std::pair<uint64_t, uint64_t> &seg : segments)
+ table.Append(VirtualDataExtractor::LookupTable::Entry(
+ seg.first - minVmAddr, seg.second, seg.first - minVmAddr));
+ lldb::DataExtractorSP extractor_sp =
+ std::make_shared<VirtualDataExtractor>(data_sp, table);
// Copy the filename into the const string pool to
// ensure lifetime.
ConstString installname(dyld_image_get_installname(image));
diff --git a/lldb/test/API/macosx/shared-cache-host-memory/Makefile b/lldb/test/API/macosx/shared-cache-host-memory/Makefile
new file mode 100644
index 0000000000000..4774d1d781b3c
--- /dev/null
+++ b/lldb/test/API/macosx/shared-cache-host-memory/Makefile
@@ -0,0 +1,4 @@
+C_SOURCES := main.c
+MAKE_DSYM := NO
+
+include Makefile.rules
diff --git a/lldb/test/API/macosx/shared-cache-host-memory/TestSharedCacheHostMemory.py b/lldb/test/API/macosx/shared-cache-host-memory/TestSharedCacheHostMemory.py
new file mode 100644
index 0000000000000..f45bf89b99444
--- /dev/null
+++ b/lldb/test/API/macosx/shared-cache-host-memory/TestSharedCacheHostMemory.py
@@ -0,0 +1,48 @@
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class SharedCacheHostMemoryTestCase(TestBase):
+ NO_DEBUG_INFO_TESTCASE = True
+
+ @skipUnlessDarwin
+ @skipIfRemote
+ def test_host_lldb_memory(self):
+ """Stop in a shared cache binary loaded from lldb's own memory and
+ backtrace through it."""
+ self.build()
+
+ self.runCmd("settings set symbols.shared-cache-binary-loading host-lldb-memory")
+ self.addTearDownHook(
+ lambda: self.runCmd("settings clear symbols.shared-cache-binary-loading")
+ )
+
+ target = self.createTestTarget()
+
+ # Breaking on puts forces lldb to load and symbolicate the shared cache
+ # binary it lives in. The breakpoint resolves once that library is
+ # loaded as the process launches.
+ breakpoint = target.BreakpointCreateByName("puts")
+
+ process = target.LaunchSimple(None, None, self.get_process_working_directory())
+ self.assertState(process.GetState(), lldb.eStateStopped, PROCESS_STOPPED)
+ self.assertGreater(
+ breakpoint.GetNumLocations(),
+ 0,
+ "puts breakpoint should resolve in the shared cache binary",
+ )
+
+ thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)
+ self.assertIsNotNone(thread, "Expected to stop at the puts breakpoint")
+
+ # We should be able to walk the stack out of the shared cache binary
+ # and back to main without crashing.
+ self.assertEqual(thread.GetFrameAtIndex(0).GetFunctionName(), "puts")
+ self.assertGreater(thread.GetNumFrames(), 1)
+ frame_names = [
+ thread.GetFrameAtIndex(i).GetFunctionName()
+ for i in range(thread.GetNumFrames())
+ ]
+ self.assertIn("main", frame_names)
diff --git a/lldb/test/API/macosx/shared-cache-host-memory/main.c b/lldb/test/API/macosx/shared-cache-host-memory/main.c
new file mode 100644
index 0000000000000..9d2a89dc43140
--- /dev/null
+++ b/lldb/test/API/macosx/shared-cache-host-memory/main.c
@@ -0,0 +1,4 @@
+#include <stdio.h>
+int main() {
+ puts("HI"); // break here
+}
More information about the lldb-commits
mailing list