[Lldb-commits] [lldb] [lldb] Look up shared cache images by UUID instead of iterating (PR #194998)
Jonas Devlieghere via lldb-commits
lldb-commits at lists.llvm.org
Wed Apr 29 21:02:09 PDT 2026
https://github.com/JDevlieghere created https://github.com/llvm/llvm-project/pull/194998
Add HostInfo::WithSharedCacheImage to look up a dyld shared cache image directly by UUID, replacing the expensive iteration through all installed shared caches and their images in ObjectFileMachO's symbol table parsing. The new API takes a callback that receives the retained image handle, ensuring it remains valid for the duration of the call.
>From 1d3a0fc35d5420450a6bda197478559428bf8e77 Mon Sep 17 00:00:00 2001
From: Jonas Devlieghere <jonas at devlieghere.com>
Date: Wed, 29 Apr 2026 21:00:57 -0700
Subject: [PATCH] [lldb] Look up shared cache images by UUID instead of
iterating
Add HostInfo::WithSharedCacheImage to look up a dyld shared cache
image directly by UUID, replacing the expensive iteration through
all installed shared caches and their images in ObjectFileMachO's
symbol table parsing. The new API takes a callback that receives
the retained image handle, ensuring it remains valid for the
duration of the call.
---
lldb/include/lldb/Host/HostInfoBase.h | 11 ++
.../include/lldb/Host/macosx/HostInfoMacOSX.h | 5 +
.../Host/macosx/objcxx/HostInfoMacOSX.mm | 26 +++++
.../ObjectFile/Mach-O/ObjectFileMachO.cpp | 105 +++++++-----------
4 files changed, 84 insertions(+), 63 deletions(-)
diff --git a/lldb/include/lldb/Host/HostInfoBase.h b/lldb/include/lldb/Host/HostInfoBase.h
index 3074a97a6fac1..a003b39276cf2 100644
--- a/lldb/include/lldb/Host/HostInfoBase.h
+++ b/lldb/include/lldb/Host/HostInfoBase.h
@@ -16,6 +16,7 @@
#include "lldb/Utility/UserIDResolver.h"
#include "lldb/Utility/XcodeSDK.h"
#include "lldb/lldb-enumerations.h"
+#include "llvm/ADT/STLFunctionalExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Errc.h"
@@ -266,6 +267,16 @@ class HostInfoBase {
return false;
}
+ /// Invoke \p callback with the retained dyld_image_t for a shared cache
+ /// image matching \p image_uuid. The image handle is only valid for the
+ /// duration of the callback. Returns true if the image was found.
+ static bool
+ WithSharedCacheImage(const UUID &image_uuid, const UUID &sc_uuid,
+ lldb::SymbolSharedCacheUse sc_mode,
+ llvm::function_ref<void(void *image)> callback) {
+ return false;
+ }
+
/// Returns the distribution id of the host
///
/// This will be something like "ubuntu", "fedora", etc. on Linux.
diff --git a/lldb/include/lldb/Host/macosx/HostInfoMacOSX.h b/lldb/include/lldb/Host/macosx/HostInfoMacOSX.h
index 6c2cabbf55c74..9ee4612591b0c 100644
--- a/lldb/include/lldb/Host/macosx/HostInfoMacOSX.h
+++ b/lldb/include/lldb/Host/macosx/HostInfoMacOSX.h
@@ -58,6 +58,11 @@ class HostInfoMacOSX : public HostInfoPosix {
static bool SharedCacheIndexFiles(FileSpec &filepath, UUID &uuid,
lldb::SymbolSharedCacheUse sc_mode);
+ static bool
+ WithSharedCacheImage(const UUID &image_uuid, const UUID &sc_uuid,
+ lldb::SymbolSharedCacheUse sc_mode,
+ llvm::function_ref<void(void *image)> callback);
+
/// Check whether a bundle at the given path has a valid code signature that
/// chains to a trusted anchor in the system trust store.
static bool IsBundleCodeSignTrusted(const FileSpec &bundle_path);
diff --git a/lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm b/lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm
index 9f1335ee2946d..5efe4fc74d145 100644
--- a/lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm
+++ b/lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm
@@ -717,6 +717,25 @@ SharedCacheImageInfo GetByUUID(UUID sc_uuid, UUID file_uuid) {
/// system, open it and add all of the binary images to m_caches.
bool CreateSharedCacheImageList(UUID uuid, std::string filepath);
+ /// Invoke \p callback with the retained dyld_image_t for the image matching
+ /// \p file_uuid in shared cache \p sc_uuid. Returns true if found.
+ bool WithImageBaton(UUID sc_uuid, UUID file_uuid,
+ llvm::function_ref<void(void *image)> callback) {
+ llvm::sys::ScopedReader guard(m_mutex);
+ if (!sc_uuid)
+ sc_uuid = m_host_uuid;
+ if (!m_uuid_map.contains(sc_uuid))
+ return false;
+ if (!m_uuid_map[sc_uuid].contains(file_uuid))
+ return false;
+ size_t idx = m_uuid_map[sc_uuid][file_uuid];
+ void *baton = m_file_infos[sc_uuid][idx].GetImageBaton();
+ if (!baton)
+ return false;
+ callback(baton);
+ return true;
+ }
+
SharedCacheInfo(SymbolSharedCacheUse sc_mode);
private:
@@ -1099,6 +1118,13 @@ static dispatch_data_t (*g_dyld_image_segment_data_4HWTrace)(
return false;
}
+bool HostInfoMacOSX::WithSharedCacheImage(
+ const UUID &image_uuid, const UUID &sc_uuid, SymbolSharedCacheUse sc_mode,
+ llvm::function_ref<void(void *image)> callback) {
+ return GetSharedCacheSingleton(sc_mode).WithImageBaton(sc_uuid, image_uuid,
+ callback);
+}
+
bool HostInfoMacOSX::IsBundleCodeSignTrusted(const FileSpec &bundle_path) {
std::string path = bundle_path.GetPath();
CFURLRef url = CFURLCreateFromFileSystemRepresentation(
diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
index 814eb58b7b9b8..692f3eb766fb9 100644
--- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
+++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
@@ -15,11 +15,13 @@
#include "Plugins/Process/Utility/RegisterContextDarwin_x86_64.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleList.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Progress.h"
#include "lldb/Core/Section.h"
#include "lldb/Host/Host.h"
+#include "lldb/Host/HostInfo.h"
#include "lldb/Symbol/DWARFCallFrameInfo.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/DynamicLoader.h"
@@ -2718,73 +2720,50 @@ void ObjectFileMachO::ParseSymtab(Symtab &symtab) {
UndefinedNameToDescMap undefined_name_to_desc;
SymbolIndexToName reexport_shlib_needs_fixup;
- dyld_for_each_installed_shared_cache(^(dyld_shared_cache_t shared_cache) {
- uuid_t cache_uuid;
- dyld_shared_cache_copy_uuid(shared_cache, &cache_uuid);
- if (found_image)
+ auto nlist_extraction_block = ^(const void *nlistStart, uint64_t nlistCount,
+ const char *stringTable) {
+ if (!nlistStart || !nlistCount)
return;
- if (process_shared_cache_uuid.IsValid() &&
- process_shared_cache_uuid != UUID(&cache_uuid, 16))
+ kern_return_t ret = vm_read(mach_task_self(), (vm_address_t)nlistStart,
+ nlist_byte_size * nlistCount,
+ &vm_nlist_memory, &vm_nlist_bytes_read);
+ if (ret != KERN_SUCCESS)
+ return;
+ assert(vm_nlist_bytes_read == nlist_byte_size * nlistCount);
+
+ vm_address_t string_address = (vm_address_t)stringTable;
+ vm_size_t region_size;
+ mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT_64;
+ vm_region_basic_info_data_t info;
+ memory_object_name_t object;
+ ret = vm_region_64(mach_task_self(), &string_address, ®ion_size,
+ VM_REGION_BASIC_INFO_64, (vm_region_info_t)&info,
+ &info_count, &object);
+ if (ret != KERN_SUCCESS)
return;
- dyld_shared_cache_for_each_image(shared_cache, ^(dyld_image_t image) {
- uuid_t dsc_image_uuid;
- if (found_image)
- return;
-
- dyld_image_copy_uuid(image, &dsc_image_uuid);
- if (image_uuid != UUID(dsc_image_uuid, 16))
- return;
-
- found_image = true;
-
- // Compute the size of the string table. We need to ask dyld for a
- // new SPI to avoid this step.
- dyld_image_local_nlist_content_4Symbolication(
- image, ^(const void *nlistStart, uint64_t nlistCount,
- const char *stringTable) {
- if (!nlistStart || !nlistCount)
- return;
-
- // The buffers passed here are valid only inside the block.
- // Use vm_read to make a cheap copy of them available for our
- // processing later.
- kern_return_t ret =
- vm_read(mach_task_self(), (vm_address_t)nlistStart,
- nlist_byte_size * nlistCount, &vm_nlist_memory,
- &vm_nlist_bytes_read);
- if (ret != KERN_SUCCESS)
- return;
- assert(vm_nlist_bytes_read == nlist_byte_size * nlistCount);
-
- // We don't know the size of the string table. It's cheaper
- // to map the whole VM region than to determine the size by
- // parsing all the nlist entries.
- vm_address_t string_address = (vm_address_t)stringTable;
- vm_size_t region_size;
- mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT_64;
- vm_region_basic_info_data_t info;
- memory_object_name_t object;
- ret = vm_region_64(mach_task_self(), &string_address,
- ®ion_size, VM_REGION_BASIC_INFO_64,
- (vm_region_info_t)&info, &info_count, &object);
- if (ret != KERN_SUCCESS)
- return;
-
- ret = vm_read(mach_task_self(), (vm_address_t)stringTable,
- region_size -
- ((vm_address_t)stringTable - string_address),
- &vm_string_memory, &vm_string_bytes_read);
- if (ret != KERN_SUCCESS)
- return;
-
- nlist_buffer = (void *)vm_nlist_memory;
- string_table = (char *)vm_string_memory;
- nlist_count = nlistCount;
- });
- });
- });
+ ret = vm_read(mach_task_self(), (vm_address_t)stringTable,
+ region_size - ((vm_address_t)stringTable - string_address),
+ &vm_string_memory, &vm_string_bytes_read);
+ if (ret != KERN_SUCCESS)
+ return;
+
+ nlist_buffer = (void *)vm_nlist_memory;
+ string_table = (char *)vm_string_memory;
+ nlist_count = nlistCount;
+ };
+
+ // Use the host shared cache to look up the image directly by UUID, avoiding
+ // the expensive iteration through all installed shared caches.
+ SymbolSharedCacheUse sc_mode = ModuleList::GetGlobalModuleListProperties()
+ .GetSharedCacheBinaryLoading();
+ found_image = HostInfo::WithSharedCacheImage(
+ image_uuid, process_shared_cache_uuid, sc_mode, [&](void *image) {
+ dyld_image_local_nlist_content_4Symbolication((dyld_image_t)image,
+ nlist_extraction_block);
+ });
+
if (nlist_buffer) {
DataExtractor dsc_local_symbols_data(nlist_buffer,
nlist_count * nlist_byte_size,
More information about the lldb-commits
mailing list