Author: Jason Molenda Date: 2025-11-30T21:40:13-08:00 New Revision: 036279addf48cc5a5d7596f4abd06d33242f4f19
URL: https://github.com/llvm/llvm-project/commit/036279addf48cc5a5d7596f4abd06d33242f4f19 DIFF: https://github.com/llvm/llvm-project/commit/036279addf48cc5a5d7596f4abd06d33242f4f19.diff LOG: [lldb][debugserver] Return shared cache filepath in jGetSharedCacheInfo (#168474) Add a "shared_cache_path" key-value to the jGetSharedCacheInfo response, if we can fetch the shared cache path. If debugserver and the inferior process are running with the same shared cache UUID, there is a simple SPI to get debugserver's own shared cache filepath and we will return that. On newer OSes, there are SPI we can use to get the inferior process' shared cache filepath, use that if necessary and the SPI are available. The response for the jGetSharedCacheInfo packet will now look like {"shared_cache_base_address":6609256448,"shared_cache_uuid":"B69FF43C-DBFD-3FB1-B4FE-A8FE32EA1062","no_shared_cache":false,"shared_cache_private_cache":false,"shared_cache_path":"/System/Volumes/Preboot/Cryptexes/OS/System/Library/dyld/dyld_shared_cache_arm64e"} when we have the full information about the shared cache in the inferior. There are three possible types of responses: 1. inferior has not yet mapped in a shared cache (read: when stopped at dyld_start and dyld hasn't started executing yet). In this case, no "shared_cache_path" is listed. ("shared_cache_base_address" will be 0, "shared_cache_uuid" will be all-zeroes uuid) 2. inferior has a shared cache, but it is different than debugserver's and we do not have the new SPI to query the shared cache filepath. No "shared_cache_path" is listed. 3. We were able to find the shared cache filepath, and it is included in the response, as above. I'm not using this information in lldb yet, but changes that build on this will be forthcoming. rdar://148939795 Added: Modified: lldb/tools/debugserver/source/DNB.cpp lldb/tools/debugserver/source/MacOSX/MachProcess.h lldb/tools/debugserver/source/MacOSX/MachProcess.mm Removed: ################################################################################ diff --git a/lldb/tools/debugserver/source/DNB.cpp b/lldb/tools/debugserver/source/DNB.cpp index 0cd48d91a682a..4d5afcf93a44b 100644 --- a/lldb/tools/debugserver/source/DNB.cpp +++ b/lldb/tools/debugserver/source/DNB.cpp @@ -1101,7 +1101,7 @@ DNBGetLibrariesInfoForAddresses(nub_process_t pid, JSONGenerator::ObjectSP DNBGetSharedCacheInfo(nub_process_t pid) { MachProcessSP procSP; if (GetProcessSP(pid, procSP)) { - return procSP->GetSharedCacheInfo(pid); + return procSP->GetInferiorSharedCacheInfo(pid); } return JSONGenerator::ObjectSP(); } diff --git a/lldb/tools/debugserver/source/MacOSX/MachProcess.h b/lldb/tools/debugserver/source/MacOSX/MachProcess.h index 56bc9d6c7461e..67b27b9902999 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachProcess.h +++ b/lldb/tools/debugserver/source/MacOSX/MachProcess.h @@ -283,7 +283,10 @@ class MachProcess { JSONGenerator::ObjectSP GetAllLoadedLibrariesInfos(nub_process_t pid, bool fetch_report_load_commands); - JSONGenerator::ObjectSP GetSharedCacheInfo(nub_process_t pid); + bool GetDebugserverSharedCacheInfo(uuid_t &uuid, + std::string &shared_cache_path); + bool GetInferiorSharedCacheFilepath(std::string &inferior_sc_path); + JSONGenerator::ObjectSP GetInferiorSharedCacheInfo(nub_process_t pid); nub_size_t GetNumThreads() const; nub_thread_t GetThreadAtIndex(nub_size_t thread_idx) const; @@ -474,6 +477,14 @@ class MachProcess { void *(*m_dyld_process_info_create)(task_t task, uint64_t timestamp, kern_return_t *kernelError); + void *(*m_dyld_process_create_for_task)(task_read_t task, kern_return_t *kr); + void *(*m_dyld_process_snapshot_create_for_process)(void *process, + kern_return_t *kr); + void *(*m_dyld_process_snapshot_get_shared_cache)(void *snapshot); + void (*m_dyld_shared_cache_for_each_file)( + void *cache, void (^block)(const char *file_path)); + void (*m_dyld_process_snapshot_dispose)(void *snapshot); + void (*m_dyld_process_dispose)(void *process); void (*m_dyld_process_info_for_each_image)( void *info, void (^callback)(uint64_t machHeaderAddress, const uuid_t uuid, const char *path)); @@ -481,6 +492,7 @@ class MachProcess { void (*m_dyld_process_info_get_cache)(void *info, void *cacheInfo); uint32_t (*m_dyld_process_info_get_platform)(void *info); void (*m_dyld_process_info_get_state)(void *info, void *stateInfo); + const char *(*m_dyld_shared_cache_file_path)(); }; #endif // LLDB_TOOLS_DEBUGSERVER_SOURCE_MACOSX_MACHPROCESS_H diff --git a/lldb/tools/debugserver/source/MacOSX/MachProcess.mm b/lldb/tools/debugserver/source/MacOSX/MachProcess.mm index 3b875e61a268d..10ed8045a9211 100644 --- a/lldb/tools/debugserver/source/MacOSX/MachProcess.mm +++ b/lldb/tools/debugserver/source/MacOSX/MachProcess.mm @@ -534,13 +534,35 @@ static bool FBSAddEventDataToOptions(NSMutableDictionary *options, m_image_infos_baton(NULL), m_sent_interrupt_signo(0), m_auto_resume_signo(0), m_did_exec(false), m_dyld_process_info_create(nullptr), + m_dyld_process_create_for_task(nullptr), + m_dyld_process_snapshot_create_for_process(nullptr), + m_dyld_process_snapshot_get_shared_cache(nullptr), + m_dyld_shared_cache_for_each_file(nullptr), + m_dyld_process_snapshot_dispose(nullptr), m_dyld_process_dispose(nullptr), m_dyld_process_info_for_each_image(nullptr), m_dyld_process_info_release(nullptr), m_dyld_process_info_get_cache(nullptr), - m_dyld_process_info_get_state(nullptr) { + m_dyld_process_info_get_state(nullptr), + m_dyld_shared_cache_file_path(nullptr) { m_dyld_process_info_create = (void *(*)(task_t task, uint64_t timestamp, kern_return_t * kernelError)) dlsym(RTLD_DEFAULT, "_dyld_process_info_create"); + + m_dyld_process_create_for_task = + (void *(*)(task_read_t, kern_return_t *))dlsym( + RTLD_DEFAULT, "dyld_process_create_for_task"); + m_dyld_process_snapshot_create_for_process = + (void *(*)(void *, kern_return_t *))dlsym( + RTLD_DEFAULT, "dyld_process_snapshot_create_for_process"); + m_dyld_process_snapshot_get_shared_cache = (void *(*)(void *))dlsym( + RTLD_DEFAULT, "dyld_process_snapshot_get_shared_cache"); + m_dyld_shared_cache_for_each_file = + (void (*)(void *, void (^)(const char *)))dlsym( + RTLD_DEFAULT, "dyld_shared_cache_for_each_file"); + m_dyld_process_snapshot_dispose = + (void (*)(void *))dlsym(RTLD_DEFAULT, "dyld_process_snapshot_dispose"); + m_dyld_process_dispose = + (void (*)(void *))dlsym(RTLD_DEFAULT, "dyld_process_dispose"); m_dyld_process_info_for_each_image = (void (*)(void *info, void (^)(uint64_t machHeaderAddress, const uuid_t uuid, const char *path))) @@ -553,6 +575,8 @@ static bool FBSAddEventDataToOptions(NSMutableDictionary *options, RTLD_DEFAULT, "_dyld_process_info_get_platform"); m_dyld_process_info_get_state = (void (*)(void *info, void *stateInfo))dlsym( RTLD_DEFAULT, "_dyld_process_info_get_state"); + m_dyld_shared_cache_file_path = + (const char *(*)())dlsym(RTLD_DEFAULT, "dyld_shared_cache_file_path"); DNBLogThreadedIf(LOG_PROCESS | LOG_VERBOSE, "%s", __PRETTY_FUNCTION__); } @@ -1179,13 +1203,82 @@ static bool mach_header_validity_test(uint32_t magic, uint32_t cputype) { /* report_load_commands = */ true); } -// From dyld's internal podyld_process_info.h: +bool MachProcess::GetDebugserverSharedCacheInfo( + uuid_t &uuid, std::string &shared_cache_path) { + uuid_clear(uuid); + shared_cache_path.clear(); + + if (m_dyld_process_info_create && m_dyld_process_info_get_cache) { + kern_return_t kern_ret; + dyld_process_info info = + m_dyld_process_info_create(mach_task_self(), 0, &kern_ret); + if (info) { + struct dyld_process_cache_info shared_cache_info; + m_dyld_process_info_get_cache(info, &shared_cache_info); + uuid_copy(uuid, shared_cache_info.cacheUUID); + m_dyld_process_info_release(info); + } + } + if (m_dyld_shared_cache_file_path) { + const char *cache_path = m_dyld_shared_cache_file_path(); + if (cache_path) + shared_cache_path = cache_path; + } + if (!uuid_is_null(uuid)) + return true; + return false; +} + +bool MachProcess::GetInferiorSharedCacheFilepath( + std::string &inferior_sc_path) { + inferior_sc_path.clear(); + + if (!m_dyld_process_create_for_task || + !m_dyld_process_snapshot_create_for_process || + !m_dyld_process_snapshot_get_shared_cache || + !m_dyld_shared_cache_for_each_file || !m_dyld_process_snapshot_dispose || + !m_dyld_process_dispose) + return false; + + __block std::string sc_path; + kern_return_t kr; + void *process = m_dyld_process_create_for_task(m_task.TaskPort(), &kr); + if (kr != KERN_SUCCESS) + return false; + void *snapshot = m_dyld_process_snapshot_create_for_process(process, &kr); + if (kr != KERN_SUCCESS) + return false; + void *cache = m_dyld_process_snapshot_get_shared_cache(snapshot); + + // The shared cache is a collection of files on disk, this callback + // will iterate over all of them. + // The first filepath provided is the base filename of the cache. + __block bool done = false; + m_dyld_shared_cache_for_each_file(cache, ^(const char *path) { + if (done) { + return; + } + done = true; + sc_path = path; + }); + m_dyld_process_snapshot_dispose(snapshot); + m_dyld_process_dispose(process); + + inferior_sc_path = sc_path; + if (!sc_path.empty()) + return true; + return false; +} + +// From dyld's internal dyld_process_info.h: -JSONGenerator::ObjectSP MachProcess::GetSharedCacheInfo(nub_process_t pid) { +JSONGenerator::ObjectSP +MachProcess::GetInferiorSharedCacheInfo(nub_process_t pid) { JSONGenerator::DictionarySP reply_sp(new JSONGenerator::Dictionary()); - kern_return_t kern_ret; + uuid_t inferior_sc_uuid; if (m_dyld_process_info_create && m_dyld_process_info_get_cache) { + kern_return_t kern_ret; dyld_process_info info = m_dyld_process_info_create(m_task.TaskPort(), 0, &kern_ret); if (info) { @@ -1197,6 +1290,7 @@ static bool mach_header_validity_test(uint32_t magic, uint32_t cputype) { uuid_string_t uuidstr; uuid_unparse_upper(shared_cache_info.cacheUUID, uuidstr); + uuid_copy(inferior_sc_uuid, shared_cache_info.cacheUUID); reply_sp->AddStringItem("shared_cache_uuid", uuidstr); reply_sp->AddBooleanItem("no_shared_cache", shared_cache_info.noCache); @@ -1206,6 +1300,29 @@ static bool mach_header_validity_test(uint32_t magic, uint32_t cputype) { m_dyld_process_info_release(info); } } + + // If debugserver and the inferior are have the same cache UUID, + // use the simple call to get the filepath to debugserver's shared + // cache, return that. + uuid_t debugserver_sc_uuid; + std::string debugserver_sc_path; + bool found_sc_filepath = false; + if (GetDebugserverSharedCacheInfo(debugserver_sc_uuid, debugserver_sc_path)) { + if (uuid_compare(inferior_sc_uuid, debugserver_sc_uuid) == 0 && + !debugserver_sc_path.empty()) { + reply_sp->AddStringItem("shared_cache_path", debugserver_sc_path); + found_sc_filepath = true; + } + } + + // Use SPI that are only available on newer OSes to fetch the + // filepath of the shared cache of the inferior, if available. + if (!found_sc_filepath) { + std::string inferior_sc_path; + if (GetInferiorSharedCacheFilepath(inferior_sc_path)) + reply_sp->AddStringItem("shared_cache_path", inferior_sc_path); + } + return reply_sp; } _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
