https://github.com/jasonmolenda updated https://github.com/llvm/llvm-project/pull/180323
>From dc41c1eb771c766e6213c55c1562b6af1f1220a1 Mon Sep 17 00:00:00 2001 From: Jason Molenda <[email protected]> Date: Fri, 6 Feb 2026 22:08:00 -0800 Subject: [PATCH 1/3] [lldb] Get shared cache path from inferior, open Get the shared cache filepath and uuid that the inferior process is using from debugserver, try to open that shared cache on the lldb host mac and if the UUID matches, index all of the binaries in that shared cache. When looking for binaries loaded in the process, get them from the already-indexed shared cache. Every time a binary is loaded, PlatformMacOSX may query the shared cache filepath and uuid from the Process, and pass that to HostInfo::GetSharedCacheImageInfo() if available (else fall back to the old HostInfo::GetSharedCacheImageInfo method which only looks at lldb's own shared cache), to get the file being requested. ProcessGDBRemote caches the shared cache filepath and uuid from the inferior, once it has a non-zero UUID. I added a lock for this ivar specifically, so I don't have 20 threads all asking for the shared cache information from debugserver and updating the cached answer. If we never get back a non-zero UUID shared cache reply, we will re-query at every library loaded notification. debugserver has been providing the shared cache UUID since 2013, although I only added the shared cache filepath field last November. Note that a process will not report its shared cache filepath or uuid at initial launch. As dyld gets a chance to execute a bit, it will start returning binaries -- it will be available at the point when libraries start loading. (it won't be available yet when the binary & dyld are the only two binaries loaded in the process) I tested this by disabling lldb's scan of its own shared cache pre-execution -- only loading the system shared cache when the inferior process reports that it is using that. I got 6-7 additional testsuite failures running lldb like that, because no system binaries were loaded before exeuction start, and the tests assumed they would be. rdar://148939795 --- lldb/include/lldb/Host/HostInfoBase.h | 16 ++++ .../include/lldb/Host/macosx/HostInfoMacOSX.h | 5 ++ lldb/include/lldb/Target/DynamicLoader.h | 12 ++- .../Host/macosx/objcxx/HostInfoMacOSX.mm | 52 +++++++++++-- .../MacOSX-DYLD/DynamicLoaderDarwin.cpp | 16 +++- .../MacOSX-DYLD/DynamicLoaderMacOS.cpp | 10 ++- .../MacOSX-DYLD/DynamicLoaderMacOS.h | 10 ++- .../MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp | 2 +- .../MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h | 3 +- .../ObjectFile/Mach-O/ObjectFileMachO.cpp | 3 +- .../Platform/MacOSX/PlatformDarwinDevice.cpp | 22 +++++- .../Platform/MacOSX/PlatformDarwinDevice.h | 3 +- .../Platform/MacOSX/PlatformMacOSX.cpp | 10 +-- .../MacOSX/PlatformRemoteDarwinDevice.cpp | 2 +- .../Process/gdb-remote/ProcessGDBRemote.cpp | 74 +++++++++++-------- .../Process/gdb-remote/ProcessGDBRemote.h | 2 + .../platform/basic/TestPlatformCommand.py | 4 +- 17 files changed, 184 insertions(+), 62 deletions(-) diff --git a/lldb/include/lldb/Host/HostInfoBase.h b/lldb/include/lldb/Host/HostInfoBase.h index 149810ff53924..fc9ab96676341 100644 --- a/lldb/include/lldb/Host/HostInfoBase.h +++ b/lldb/include/lldb/Host/HostInfoBase.h @@ -190,6 +190,22 @@ class HostInfoBase { return {}; } + /// Return information about module \p image_name if it is loaded in + /// the current process's address space using shared cache \p uuid. + /// The shared cache UUID must have been previously indexed. + static SharedCacheImageInfo + GetSharedCacheImageInfo(llvm::StringRef image_name, UUID &uuid) { + return {}; + } + + /// Scan the files in a shared cache, if the filepath and uuid match + /// on the debug host. + /// Returns false if the shared cache filepath did not exist, or uuid + /// did not match. + static bool SharedCacheIndexFiles(FileSpec &filepath, UUID &uuid) { + 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 734a394c18679..78f8344aefd13 100644 --- a/lldb/include/lldb/Host/macosx/HostInfoMacOSX.h +++ b/lldb/include/lldb/Host/macosx/HostInfoMacOSX.h @@ -45,6 +45,11 @@ class HostInfoMacOSX : public HostInfoPosix { static SharedCacheImageInfo GetSharedCacheImageInfo(llvm::StringRef image_name); + static SharedCacheImageInfo + GetSharedCacheImageInfo(llvm::StringRef image_name, UUID &uuid); + + static bool SharedCacheIndexFiles(FileSpec &filepath, UUID &uuid); + protected: static bool ComputeSupportExeDirectory(FileSpec &file_spec); static void ComputeHostArchitectureSupport(ArchSpec &arch_32, diff --git a/lldb/include/lldb/Target/DynamicLoader.h b/lldb/include/lldb/Target/DynamicLoader.h index 7f2652bb28727..04fd7556e1068 100644 --- a/lldb/include/lldb/Target/DynamicLoader.h +++ b/lldb/include/lldb/Target/DynamicLoader.h @@ -310,12 +310,18 @@ class DynamicLoader : public PluginInterface { /// private shared cache. /// If this information cannot be fetched, eLazyBoolCalculate. /// + /// \param[out] shared_cache_path + /// A FileSpec representing the shared cache path being run + /// in the inferior process. + /// /// \return /// Returns false if this DynamicLoader cannot gather information /// about the shared cache / has no concept of a shared cache. - virtual bool GetSharedCacheInformation(lldb::addr_t &base_address, UUID &uuid, - LazyBool &using_shared_cache, - LazyBool &private_shared_cache) { + virtual bool + GetSharedCacheInformation(lldb::addr_t &base_address, UUID &uuid, + LazyBool &using_shared_cache, + LazyBool &private_shared_cache, + lldb_private::FileSpec &shared_cache_path) { base_address = LLDB_INVALID_ADDRESS; uuid.Clear(); using_shared_cache = eLazyBoolCalculate; diff --git a/lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm b/lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm index e8f416270cdb8..6d1755f346df8 100644 --- a/lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm +++ b/lldb/source/Host/macosx/objcxx/HostInfoMacOSX.mm @@ -688,6 +688,18 @@ void dyld_shared_cache_for_each_image(dyld_shared_cache_t cache, return m_caches[m_host_uuid]; } + bool GetImages(llvm::StringMap<SharedCacheImageInfo> **images, UUID &uuid) { + if (m_caches.find(uuid) != m_caches.end()) { + *images = &m_caches[uuid]; + return true; + } + return false; + } + + // Given the UUID and filepath to a shared cache on the local debug host + // system, open it and add all of the binary images to m_caches. + bool CreateSharedCacheImageList(UUID uuid, std::string filepath); + SharedCacheInfo(); private: @@ -695,10 +707,6 @@ void dyld_shared_cache_for_each_image(dyld_shared_cache_t cache, void CreateSharedCacheInfoLLDBsVirtualMemory(); bool CreateHostSharedCacheImageList(); - // Given the UUID and filepath to a shared cache on the local debug host - // system, open it and add all of the binary images to m_caches. - bool CreateSharedCacheImageList(UUID uuid, std::string filepath); - std::map<UUID, llvm::StringMap<SharedCacheImageInfo>> m_caches; UUID m_host_uuid; @@ -829,6 +837,13 @@ static dispatch_data_t (*g_dyld_image_segment_data_4HWTrace)( !m_dyld_image_segment_data_4HWTrace) return false; + if (filepath.empty()) + return false; + + Log *log = GetLog(LLDBLog::Modules); + LLDB_LOGF(log, "Opening shared cache at %s to check for matching UUID %s", + filepath.c_str(), uuid.GetAsString().c_str()); + __block bool return_failed = false; dyld_shared_cache_for_file(filepath.c_str(), ^(dyld_shared_cache_t cache) { uuid_t sc_uuid; @@ -952,8 +967,33 @@ static dispatch_data_t (*g_dyld_image_segment_data_4HWTrace)( }); } +SharedCacheInfo &GetSharedCacheSingleton() { + static SharedCacheInfo g_shared_cache_info; + return g_shared_cache_info; +} + SharedCacheImageInfo HostInfoMacOSX::GetSharedCacheImageInfo(llvm::StringRef image_name) { - static SharedCacheInfo g_shared_cache_info; - return g_shared_cache_info.GetImages().lookup(image_name); + return GetSharedCacheSingleton().GetImages().lookup(image_name); +} + +SharedCacheImageInfo +HostInfoMacOSX::GetSharedCacheImageInfo(llvm::StringRef image_name, + UUID &uuid) { + llvm::StringMap<SharedCacheImageInfo> *shared_cache_info; + if (GetSharedCacheSingleton().GetImages(&shared_cache_info, uuid)) + return shared_cache_info->lookup(image_name); + else + return {}; +} + +bool HostInfoMacOSX::SharedCacheIndexFiles(FileSpec &filepath, UUID &uuid) { + // There is a libdyld SPI to iterate over all installed shared caches, + // but it can have performance problems if an older Simulator SDK shared + // cache is installed. So require that we are given a filepath of + // the shared cache. + if (FileSystem::Instance().Exists(filepath)) + return GetSharedCacheSingleton().CreateSharedCacheImageList( + uuid, filepath.GetPath()); + return false; } diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp index 00cae1c6cea1e..0a8aa51a1469c 100644 --- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp +++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderDarwin.cpp @@ -135,8 +135,20 @@ ModuleSP DynamicLoaderDarwin::FindTargetModuleForImageInfo( // exist on the filesystem, so let's use the images in our own memory // to create the modules. // Check if the requested image is in our shared cache. - SharedCacheImageInfo image_info = - HostInfo::GetSharedCacheImageInfo(module_spec.GetFileSpec().GetPath()); + SharedCacheImageInfo image_info; + addr_t sc_base_addr; + UUID sc_uuid; + LazyBool using_sc; + LazyBool private_sc; + FileSpec sc_path; + if (GetSharedCacheInformation(sc_base_addr, sc_uuid, using_sc, private_sc, + sc_path) && + sc_uuid) + image_info = HostInfo::GetSharedCacheImageInfo( + module_spec.GetFileSpec().GetPath(), sc_uuid); + else + image_info = HostInfo::GetSharedCacheImageInfo( + module_spec.GetFileSpec().GetPath()); // If we found it and it has the correct UUID, let's proceed with // creating a module from the memory contents. diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp index ce1a0975260c9..97a487bf79e4d 100644 --- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp +++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.cpp @@ -691,7 +691,7 @@ Status DynamicLoaderMacOS::CanLoadImage() { bool DynamicLoaderMacOS::GetSharedCacheInformation( lldb::addr_t &base_address, UUID &uuid, LazyBool &using_shared_cache, - LazyBool &private_shared_cache) { + LazyBool &private_shared_cache, FileSpec &shared_cache_path) { base_address = LLDB_INVALID_ADDRESS; uuid.Clear(); using_shared_cache = eLazyBoolCalculate; @@ -710,6 +710,7 @@ bool DynamicLoaderMacOS::GetSharedCacheInformation( if (info_dict && info_dict->HasKey("shared_cache_uuid") && info_dict->HasKey("no_shared_cache") && + info_dict->HasKey("shared_cache_private_cache") && info_dict->HasKey("shared_cache_base_address")) { base_address = info_dict->GetValueForKey("shared_cache_base_address") ->GetUnsignedIntegerValue(LLDB_INVALID_ADDRESS); @@ -726,7 +727,12 @@ bool DynamicLoaderMacOS::GetSharedCacheInformation( private_shared_cache = eLazyBoolYes; else private_shared_cache = eLazyBoolNo; - + if (info_dict->HasKey("shared_cache_path")) { + std::string filepath = info_dict->GetValueForKey("shared_cache_path") + ->GetStringValue() + .str(); + shared_cache_path.SetPath(filepath); + } return true; } } diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.h b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.h index bd2c2e0bac538..9bb50de3eadb3 100644 --- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.h +++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOS.h @@ -54,10 +54,12 @@ class DynamicLoaderMacOS : public lldb_private::DynamicLoaderDarwin { lldb_private::Status CanLoadImage() override; - bool GetSharedCacheInformation( - lldb::addr_t &base_address, lldb_private::UUID &uuid, - lldb_private::LazyBool &using_shared_cache, - lldb_private::LazyBool &private_shared_cache) override; + bool + GetSharedCacheInformation(lldb::addr_t &base_address, + lldb_private::UUID &uuid, + lldb_private::LazyBool &using_shared_cache, + lldb_private::LazyBool &private_shared_cache, + lldb_private::FileSpec &shared_cache_path) override; // PluginInterface protocol llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp index f839948660aa0..1ec91548a1866 100644 --- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp +++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.cpp @@ -1071,7 +1071,7 @@ Status DynamicLoaderMacOSXDYLD::CanLoadImage() { bool DynamicLoaderMacOSXDYLD::GetSharedCacheInformation( lldb::addr_t &base_address, UUID &uuid, LazyBool &using_shared_cache, - LazyBool &private_shared_cache) { + LazyBool &private_shared_cache, FileSpec &shared_cache_filepath) { base_address = LLDB_INVALID_ADDRESS; uuid.Clear(); using_shared_cache = eLazyBoolCalculate; diff --git a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h index ae7451722a8d7..e3f263a08d7df 100644 --- a/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h +++ b/lldb/source/Plugins/DynamicLoader/MacOSX-DYLD/DynamicLoaderMacOSXDYLD.h @@ -61,7 +61,8 @@ class DynamicLoaderMacOSXDYLD : public lldb_private::DynamicLoaderDarwin { bool GetSharedCacheInformation( lldb::addr_t &base_address, lldb_private::UUID &uuid, lldb_private::LazyBool &using_shared_cache, - lldb_private::LazyBool &private_shared_cache) override; + lldb_private::LazyBool &private_shared_cache, + lldb_private::FileSpec &shared_cache_filepath) override; // PluginInterface protocol llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp index c1729d7ef57ba..b188c3f6964b2 100644 --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -5737,8 +5737,9 @@ void ObjectFileMachO::GetProcessSharedCacheUUID(Process *process, DynamicLoader *dl = process->GetDynamicLoader(); LazyBool using_shared_cache; LazyBool private_shared_cache; + FileSpec sc_filepath; dl->GetSharedCacheInformation(base_addr, uuid, using_shared_cache, - private_shared_cache); + private_shared_cache, sc_filepath); } Log *log(GetLog(LLDBLog::Symbols | LLDBLog::Process)); LLDB_LOGF( diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinDevice.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinDevice.cpp index c1a04e801107e..59d2f9ed9d856 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinDevice.cpp +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinDevice.cpp @@ -11,6 +11,7 @@ #include "lldb/Core/ModuleList.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Host/HostInfo.h" +#include "lldb/Target/DynamicLoader.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Log.h" @@ -295,7 +296,8 @@ BringInRemoteFile(Platform *platform, lldb_private::Status PlatformDarwinDevice::GetSharedModuleWithLocalCache( const lldb_private::ModuleSpec &module_spec, lldb::ModuleSP &module_sp, - llvm::SmallVectorImpl<lldb::ModuleSP> *old_modules, bool *did_create_ptr) { + llvm::SmallVectorImpl<lldb::ModuleSP> *old_modules, bool *did_create_ptr, + Process *process) { Log *log = GetLog(LLDBLog::Platform); LLDB_LOGF(log, @@ -317,9 +319,21 @@ lldb_private::Status PlatformDarwinDevice::GetSharedModuleWithLocalCache( // exist on the filesystem, so let's use the images in our own memory // to create the modules. - // Check if the requested image is in our shared cache. - SharedCacheImageInfo image_info = - HostInfo::GetSharedCacheImageInfo(module_spec.GetFileSpec().GetPath()); + SharedCacheImageInfo image_info; + if (process && process->GetDynamicLoader()) { + addr_t sc_base_addr; + UUID sc_uuid; + LazyBool using_sc, private_sc; + FileSpec sc_path; + if (process->GetDynamicLoader()->GetSharedCacheInformation( + sc_base_addr, sc_uuid, using_sc, private_sc, sc_path)) + image_info = HostInfo::GetSharedCacheImageInfo( + module_spec.GetFileSpec().GetPath(), sc_uuid); + } + + if (!image_info.GetUUID()) + image_info = HostInfo::GetSharedCacheImageInfo( + module_spec.GetFileSpec().GetPath()); // If we found it and it has the correct UUID, let's proceed with // creating a module from the memory contents. diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinDevice.h b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinDevice.h index e0142ab7ca4cb..d8ea1807edf14 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinDevice.h +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinDevice.h @@ -26,7 +26,8 @@ class PlatformDarwinDevice : public PlatformDarwin { protected: virtual Status GetSharedModuleWithLocalCache( const ModuleSpec &module_spec, lldb::ModuleSP &module_sp, - llvm::SmallVectorImpl<lldb::ModuleSP> *old_modules, bool *did_create_ptr); + llvm::SmallVectorImpl<lldb::ModuleSP> *old_modules, bool *did_create_ptr, + lldb_private::Process *process); struct SDKDirectoryInfo { SDKDirectoryInfo(const FileSpec &sdk_dir_spec); diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp index e6ea75a35f921..bf653cd758295 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformMacOSX.cpp @@ -183,8 +183,8 @@ lldb_private::Status PlatformMacOSX::GetSharedModule( const lldb_private::ModuleSpec &module_spec, Process *process, lldb::ModuleSP &module_sp, llvm::SmallVectorImpl<lldb::ModuleSP> *old_modules, bool *did_create_ptr) { - Status error = GetSharedModuleWithLocalCache(module_spec, module_sp, - old_modules, did_create_ptr); + Status error = GetSharedModuleWithLocalCache( + module_spec, module_sp, old_modules, did_create_ptr, process); if (module_sp) { if (module_spec.GetArchitecture().GetCore() == @@ -197,9 +197,9 @@ lldb_private::Status PlatformMacOSX::GetSharedModule( lldb::ModuleSP x86_64_module_sp; llvm::SmallVector<lldb::ModuleSP, 1> old_x86_64_modules; bool did_create = false; - Status x86_64_error = - GetSharedModuleWithLocalCache(module_spec_x86_64, x86_64_module_sp, - &old_x86_64_modules, &did_create); + Status x86_64_error = GetSharedModuleWithLocalCache( + module_spec_x86_64, x86_64_module_sp, &old_x86_64_modules, + &did_create, process); if (x86_64_module_sp && x86_64_module_sp->GetObjectFile()) { module_sp = x86_64_module_sp; if (old_modules) diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp index 021a526bb623b..2babfa0517ab5 100644 --- a/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp +++ b/lldb/source/Plugins/Platform/MacOSX/PlatformRemoteDarwinDevice.cpp @@ -261,7 +261,7 @@ Status PlatformRemoteDarwinDevice::GetSharedModule( // This may not be an SDK-related module. Try whether we can bring in the // thing to our local cache. error = GetSharedModuleWithLocalCache(module_spec, module_sp, old_modules, - did_create_ptr); + did_create_ptr, process); if (error.Success()) return error; diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index e1f28674ae45c..eb85b9278c54b 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -269,13 +269,14 @@ ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp, m_async_listener_sp( Listener::MakeListener("lldb.process.gdb-remote.async-listener")), m_async_thread_state_mutex(), m_thread_ids(), m_thread_pcs(), - m_jstopinfo_sp(), m_jthreadsinfo_sp(), m_continue_c_tids(), - m_continue_C_tids(), m_continue_s_tids(), m_continue_S_tids(), - m_max_memory_size(0), m_remote_stub_max_memory_size(0), - m_addr_to_mmap_size(), m_thread_create_bp_sp(), - m_waiting_for_attach(false), m_command_sp(), m_breakpoint_pc_offset(0), - m_initial_tid(LLDB_INVALID_THREAD_ID), m_allow_flash_writes(false), - m_erased_flash_ranges(), m_vfork_in_progress_count(0) { + m_jstopinfo_sp(), m_jthreadsinfo_sp(), m_shared_cache_info_sp(), + m_shared_cache_info_mutex(), m_continue_c_tids(), m_continue_C_tids(), + m_continue_s_tids(), m_continue_S_tids(), m_max_memory_size(0), + m_remote_stub_max_memory_size(0), m_addr_to_mmap_size(), + m_thread_create_bp_sp(), m_waiting_for_attach(false), m_command_sp(), + m_breakpoint_pc_offset(0), m_initial_tid(LLDB_INVALID_THREAD_ID), + m_allow_flash_writes(false), m_erased_flash_ranges(), + m_vfork_in_progress_count(0) { m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit, "async thread should exit"); m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue, @@ -1248,6 +1249,7 @@ Status ProcessGDBRemote::WillResume() { m_continue_S_tids.clear(); m_jstopinfo_sp.reset(); m_jthreadsinfo_sp.reset(); + m_shared_cache_info_sp.reset(); return Status(); } @@ -4335,35 +4337,49 @@ StructuredData::ObjectSP ProcessGDBRemote::GetDynamicLoaderProcessState() { } StructuredData::ObjectSP ProcessGDBRemote::GetSharedCacheInfo() { - StructuredData::ObjectSP object_sp; + std::lock_guard<std::recursive_mutex> guard(m_shared_cache_info_mutex); StructuredData::ObjectSP args_dict(new StructuredData::Dictionary()); - if (m_gdb_comm.GetSharedCacheInfoSupported()) { - StreamString packet; - packet << "jGetSharedCacheInfo:"; - args_dict->Dump(packet, false); + if (m_shared_cache_info_sp || !m_gdb_comm.GetSharedCacheInfoSupported()) + return m_shared_cache_info_sp; - // FIXME the final character of a JSON dictionary, '}', is the escape - // character in gdb-remote binary mode. lldb currently doesn't escape - // these characters in its packet output -- so we add the quoted version of - // the } character here manually in case we talk to a debugserver which un- - // escapes the characters at packet read time. - packet << (char)(0x7d ^ 0x20); + StreamString packet; + packet << "jGetSharedCacheInfo:"; + args_dict->Dump(packet, false); - StringExtractorGDBRemote response; - response.SetResponseValidatorToJSON(); - if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) == - GDBRemoteCommunication::PacketResult::Success) { - StringExtractorGDBRemote::ResponseType response_type = - response.GetResponseType(); - if (response_type == StringExtractorGDBRemote::eResponse) { - if (!response.Empty()) { - object_sp = StructuredData::ParseJSON(response.GetStringRef()); - } + StringExtractorGDBRemote response; + response.SetResponseValidatorToJSON(); + if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) == + GDBRemoteCommunication::PacketResult::Success) { + StringExtractorGDBRemote::ResponseType response_type = + response.GetResponseType(); + if (response_type == StringExtractorGDBRemote::eResponse) { + if (response.Empty()) + return {}; + StructuredData::ObjectSP response_sp = + StructuredData::ParseJSON(response.GetStringRef()); + if (!response_sp) + return {}; + StructuredData::Dictionary *dict = response_sp->GetAsDictionary(); + if (!dict) + return {}; + if (!dict->HasKey("shared_cache_uuid")) + return {}; + llvm::StringRef uuid_str; + if (!dict->GetValueForKeyAsString("shared_cache_uuid", uuid_str, "") || + uuid_str == "00000000-0000-0000-0000-000000000000") + return {}; + if (dict->HasKey("shared_cache_path")) { + UUID uuid; + uuid.SetFromStringRef(uuid_str); + FileSpec sc_path( + dict->GetValueForKey("shared_cache_path")->GetStringValue()); + HostInfo::SharedCacheIndexFiles(sc_path, uuid); } + m_shared_cache_info_sp = response_sp; } } - return object_sp; + return m_shared_cache_info_sp; } Status ProcessGDBRemote::ConfigureStructuredData( diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index db3c43284587b..dfee3928bb0d1 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -297,6 +297,8 @@ class ProcessGDBRemote : public Process, // registers and memory for all // threads if "jThreadsInfo" // packet is supported + StructuredData::ObjectSP m_shared_cache_info_sp; + std::recursive_mutex m_shared_cache_info_mutex; tid_collection m_continue_c_tids; // 'c' for continue tid_sig_collection m_continue_C_tids; // 'C' for continue with signal tid_collection m_continue_s_tids; // 's' for step diff --git a/lldb/test/API/commands/platform/basic/TestPlatformCommand.py b/lldb/test/API/commands/platform/basic/TestPlatformCommand.py index 1e1a476c44a92..e9e1b8f9ce796 100644 --- a/lldb/test/API/commands/platform/basic/TestPlatformCommand.py +++ b/lldb/test/API/commands/platform/basic/TestPlatformCommand.py @@ -71,8 +71,8 @@ def test_shell(self): self.expect("platform shell ls /", substrs=["cache", "dev", "system"]) self.expect("shell ls /", substrs=["cache", "dev", "system"]) else: - self.expect("platform shell ls /", substrs=["dev", "tmp", "usr"]) - self.expect("shell ls /", substrs=["dev", "tmp", "usr"]) + self.expect("platform shell ls /", substrs=["dev", "tmp", "usr"], ordered=False) + self.expect("shell ls /", substrs=["dev", "tmp", "usr"], ordered=False) @no_debug_info_test def test_shell_builtin(self): >From 959b8d3712a79a940ed25b09ac6047544a550900 Mon Sep 17 00:00:00 2001 From: Jason Molenda <[email protected]> Date: Fri, 6 Feb 2026 22:21:44 -0800 Subject: [PATCH 2/3] Add comment about how we're forcing the scan of the newly-discovered shared cache in ProcessGDBRemote. --- lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index eb85b9278c54b..b43ba6cabd810 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -4374,6 +4374,9 @@ StructuredData::ObjectSP ProcessGDBRemote::GetSharedCacheInfo() { uuid.SetFromStringRef(uuid_str); FileSpec sc_path( dict->GetValueForKey("shared_cache_path")->GetStringValue()); + + // Attempt to open the shared cache at sc_path, and + // if the uuid matches, index all the files. HostInfo::SharedCacheIndexFiles(sc_path, uuid); } m_shared_cache_info_sp = response_sp; >From 39022e065913b254fe40ade8af8f7bd868e67da6 Mon Sep 17 00:00:00 2001 From: Jason Molenda <[email protected]> Date: Fri, 6 Feb 2026 22:29:16 -0800 Subject: [PATCH 3/3] ws fix --- lldb/test/API/commands/platform/basic/TestPlatformCommand.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lldb/test/API/commands/platform/basic/TestPlatformCommand.py b/lldb/test/API/commands/platform/basic/TestPlatformCommand.py index e9e1b8f9ce796..03a9c6f7a8eba 100644 --- a/lldb/test/API/commands/platform/basic/TestPlatformCommand.py +++ b/lldb/test/API/commands/platform/basic/TestPlatformCommand.py @@ -2,7 +2,6 @@ Test some lldb platform commands. """ - import lldb from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * @@ -71,7 +70,9 @@ def test_shell(self): self.expect("platform shell ls /", substrs=["cache", "dev", "system"]) self.expect("shell ls /", substrs=["cache", "dev", "system"]) else: - self.expect("platform shell ls /", substrs=["dev", "tmp", "usr"], ordered=False) + self.expect( + "platform shell ls /", substrs=["dev", "tmp", "usr"], ordered=False + ) self.expect("shell ls /", substrs=["dev", "tmp", "usr"], ordered=False) @no_debug_info_test _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
