@@ -534,13 +534,35 @@ static bool FBSAddEventDataToOptions(NSMutableDictionary *options,
534534 m_image_infos_baton (NULL ), m_sent_interrupt_signo (0 ),
535535 m_auto_resume_signo (0 ), m_did_exec (false ),
536536 m_dyld_process_info_create (nullptr ),
537+ m_dyld_process_create_for_task (nullptr ),
538+ m_dyld_process_snapshot_create_for_process (nullptr ),
539+ m_dyld_process_snapshot_get_shared_cache (nullptr ),
540+ m_dyld_shared_cache_for_each_file (nullptr ),
541+ m_dyld_process_snapshot_dispose (nullptr ), m_dyld_process_dispose (nullptr ),
537542 m_dyld_process_info_for_each_image (nullptr ),
538543 m_dyld_process_info_release (nullptr ),
539544 m_dyld_process_info_get_cache (nullptr ),
540- m_dyld_process_info_get_state (nullptr ) {
545+ m_dyld_process_info_get_state (nullptr ),
546+ m_dyld_shared_cache_file_path (nullptr ) {
541547 m_dyld_process_info_create =
542548 (void *(*)(task_t task, uint64_t timestamp, kern_return_t * kernelError))
543549 dlsym (RTLD_DEFAULT, " _dyld_process_info_create" );
550+
551+ m_dyld_process_create_for_task =
552+ (void *(*)(task_read_t , kern_return_t *))dlsym (
553+ RTLD_DEFAULT, " dyld_process_create_for_task" );
554+ m_dyld_process_snapshot_create_for_process =
555+ (void *(*)(void *, kern_return_t *))dlsym (
556+ RTLD_DEFAULT, " dyld_process_snapshot_create_for_process" );
557+ m_dyld_process_snapshot_get_shared_cache = (void *(*)(void *))dlsym (
558+ RTLD_DEFAULT, " dyld_process_snapshot_get_shared_cache" );
559+ m_dyld_shared_cache_for_each_file =
560+ (void (*)(void *, void (^)(const char *)))dlsym (
561+ RTLD_DEFAULT, " dyld_shared_cache_for_each_file" );
562+ m_dyld_process_snapshot_dispose =
563+ (void (*)(void *))dlsym (RTLD_DEFAULT, " dyld_process_snapshot_dispose" );
564+ m_dyld_process_dispose =
565+ (void (*)(void *))dlsym (RTLD_DEFAULT, " dyld_process_dispose" );
544566 m_dyld_process_info_for_each_image =
545567 (void (*)(void *info, void (^)(uint64_t machHeaderAddress,
546568 const uuid_t uuid, const char *path)))
@@ -553,6 +575,8 @@ static bool FBSAddEventDataToOptions(NSMutableDictionary *options,
553575 RTLD_DEFAULT, " _dyld_process_info_get_platform" );
554576 m_dyld_process_info_get_state = (void (*)(void *info, void *stateInfo))dlsym (
555577 RTLD_DEFAULT, " _dyld_process_info_get_state" );
578+ m_dyld_shared_cache_file_path =
579+ (const char *(*)())dlsym (RTLD_DEFAULT, " dyld_shared_cache_file_path" );
556580
557581 DNBLogThreadedIf (LOG_PROCESS | LOG_VERBOSE, " %s" , __PRETTY_FUNCTION__);
558582}
@@ -1179,13 +1203,82 @@ static bool mach_header_validity_test(uint32_t magic, uint32_t cputype) {
11791203 /* report_load_commands = */ true );
11801204}
11811205
1182- // From dyld's internal podyld_process_info.h:
1206+ bool MachProcess::GetDebugserverSharedCacheInfo (
1207+ uuid_t &uuid, std::string &shared_cache_path) {
1208+ uuid_clear (uuid);
1209+ shared_cache_path.clear ();
1210+
1211+ if (m_dyld_process_info_create && m_dyld_process_info_get_cache) {
1212+ kern_return_t kern_ret;
1213+ dyld_process_info info =
1214+ m_dyld_process_info_create (mach_task_self (), 0 , &kern_ret);
1215+ if (info) {
1216+ struct dyld_process_cache_info shared_cache_info;
1217+ m_dyld_process_info_get_cache (info, &shared_cache_info);
1218+ uuid_copy (uuid, shared_cache_info.cacheUUID );
1219+ m_dyld_process_info_release (info);
1220+ }
1221+ }
1222+ if (m_dyld_shared_cache_file_path) {
1223+ const char *cache_path = m_dyld_shared_cache_file_path ();
1224+ if (cache_path)
1225+ shared_cache_path = cache_path;
1226+ }
1227+ if (!uuid_is_null (uuid))
1228+ return true ;
1229+ return false ;
1230+ }
1231+
1232+ bool MachProcess::GetInferiorSharedCacheFilepath (
1233+ std::string &inferior_sc_path) {
1234+ inferior_sc_path.clear ();
1235+
1236+ if (!m_dyld_process_create_for_task ||
1237+ !m_dyld_process_snapshot_create_for_process ||
1238+ !m_dyld_process_snapshot_get_shared_cache ||
1239+ !m_dyld_shared_cache_for_each_file || !m_dyld_process_snapshot_dispose ||
1240+ !m_dyld_process_dispose)
1241+ return false ;
1242+
1243+ __block std::string sc_path;
1244+ kern_return_t kr;
1245+ void *process = m_dyld_process_create_for_task (m_task.TaskPort (), &kr);
1246+ if (kr != KERN_SUCCESS)
1247+ return false ;
1248+ void *snapshot = m_dyld_process_snapshot_create_for_process (process, &kr);
1249+ if (kr != KERN_SUCCESS)
1250+ return false ;
1251+ void *cache = m_dyld_process_snapshot_get_shared_cache (snapshot);
1252+
1253+ // The shared cache is a collection of files on disk, this callback
1254+ // will iterate over all of them.
1255+ // The first filepath provided is the base filename of the cache.
1256+ __block bool done = false ;
1257+ m_dyld_shared_cache_for_each_file (cache, ^(const char *path) {
1258+ if (done) {
1259+ return ;
1260+ }
1261+ done = true ;
1262+ sc_path = path;
1263+ });
1264+ m_dyld_process_snapshot_dispose (snapshot);
1265+ m_dyld_process_dispose (process);
1266+
1267+ inferior_sc_path = sc_path;
1268+ if (!sc_path.empty ())
1269+ return true ;
1270+ return false ;
1271+ }
1272+
1273+ // From dyld's internal dyld_process_info.h:
11831274
1184- JSONGenerator::ObjectSP MachProcess::GetSharedCacheInfo (nub_process_t pid) {
1275+ JSONGenerator::ObjectSP
1276+ MachProcess::GetInferiorSharedCacheInfo (nub_process_t pid) {
11851277 JSONGenerator::DictionarySP reply_sp (new JSONGenerator::Dictionary ());
11861278
1187- kern_return_t kern_ret ;
1279+ uuid_t inferior_sc_uuid ;
11881280 if (m_dyld_process_info_create && m_dyld_process_info_get_cache) {
1281+ kern_return_t kern_ret;
11891282 dyld_process_info info =
11901283 m_dyld_process_info_create (m_task.TaskPort (), 0 , &kern_ret);
11911284 if (info) {
@@ -1197,6 +1290,7 @@ static bool mach_header_validity_test(uint32_t magic, uint32_t cputype) {
11971290
11981291 uuid_string_t uuidstr;
11991292 uuid_unparse_upper (shared_cache_info.cacheUUID , uuidstr);
1293+ uuid_copy (inferior_sc_uuid, shared_cache_info.cacheUUID );
12001294 reply_sp->AddStringItem (" shared_cache_uuid" , uuidstr);
12011295
12021296 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) {
12061300 m_dyld_process_info_release (info);
12071301 }
12081302 }
1303+
1304+ // If debugserver and the inferior are have the same cache UUID,
1305+ // use the simple call to get the filepath to debugserver's shared
1306+ // cache, return that.
1307+ uuid_t debugserver_sc_uuid;
1308+ std::string debugserver_sc_path;
1309+ bool found_sc_filepath = false ;
1310+ if (GetDebugserverSharedCacheInfo (debugserver_sc_uuid, debugserver_sc_path)) {
1311+ if (uuid_compare (inferior_sc_uuid, debugserver_sc_uuid) == 0 &&
1312+ !debugserver_sc_path.empty ()) {
1313+ reply_sp->AddStringItem (" shared_cache_path" , debugserver_sc_path);
1314+ found_sc_filepath = true ;
1315+ }
1316+ }
1317+
1318+ // Use SPI that are only available on newer OSes to fetch the
1319+ // filepath of the shared cache of the inferior, if available.
1320+ if (!found_sc_filepath) {
1321+ std::string inferior_sc_path;
1322+ if (GetInferiorSharedCacheFilepath (inferior_sc_path))
1323+ reply_sp->AddStringItem (" shared_cache_path" , inferior_sc_path);
1324+ }
1325+
12091326 return reply_sp;
12101327}
12111328
0 commit comments