Skip to content

Commit 270051b

Browse files
jasonmolendakcloudy0717
authored andcommitted
[lldb][debugserver] Return shared cache filepath in jGetSharedCacheInfo (llvm#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
1 parent f4cb4fa commit 270051b

File tree

3 files changed

+135
-6
lines changed

3 files changed

+135
-6
lines changed

lldb/tools/debugserver/source/DNB.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1101,7 +1101,7 @@ DNBGetLibrariesInfoForAddresses(nub_process_t pid,
11011101
JSONGenerator::ObjectSP DNBGetSharedCacheInfo(nub_process_t pid) {
11021102
MachProcessSP procSP;
11031103
if (GetProcessSP(pid, procSP)) {
1104-
return procSP->GetSharedCacheInfo(pid);
1104+
return procSP->GetInferiorSharedCacheInfo(pid);
11051105
}
11061106
return JSONGenerator::ObjectSP();
11071107
}

lldb/tools/debugserver/source/MacOSX/MachProcess.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,10 @@ class MachProcess {
283283
JSONGenerator::ObjectSP
284284
GetAllLoadedLibrariesInfos(nub_process_t pid,
285285
bool fetch_report_load_commands);
286-
JSONGenerator::ObjectSP GetSharedCacheInfo(nub_process_t pid);
286+
bool GetDebugserverSharedCacheInfo(uuid_t &uuid,
287+
std::string &shared_cache_path);
288+
bool GetInferiorSharedCacheFilepath(std::string &inferior_sc_path);
289+
JSONGenerator::ObjectSP GetInferiorSharedCacheInfo(nub_process_t pid);
287290

288291
nub_size_t GetNumThreads() const;
289292
nub_thread_t GetThreadAtIndex(nub_size_t thread_idx) const;
@@ -474,13 +477,22 @@ class MachProcess {
474477

475478
void *(*m_dyld_process_info_create)(task_t task, uint64_t timestamp,
476479
kern_return_t *kernelError);
480+
void *(*m_dyld_process_create_for_task)(task_read_t task, kern_return_t *kr);
481+
void *(*m_dyld_process_snapshot_create_for_process)(void *process,
482+
kern_return_t *kr);
483+
void *(*m_dyld_process_snapshot_get_shared_cache)(void *snapshot);
484+
void (*m_dyld_shared_cache_for_each_file)(
485+
void *cache, void (^block)(const char *file_path));
486+
void (*m_dyld_process_snapshot_dispose)(void *snapshot);
487+
void (*m_dyld_process_dispose)(void *process);
477488
void (*m_dyld_process_info_for_each_image)(
478489
void *info, void (^callback)(uint64_t machHeaderAddress,
479490
const uuid_t uuid, const char *path));
480491
void (*m_dyld_process_info_release)(void *info);
481492
void (*m_dyld_process_info_get_cache)(void *info, void *cacheInfo);
482493
uint32_t (*m_dyld_process_info_get_platform)(void *info);
483494
void (*m_dyld_process_info_get_state)(void *info, void *stateInfo);
495+
const char *(*m_dyld_shared_cache_file_path)();
484496
};
485497

486498
#endif // LLDB_TOOLS_DEBUGSERVER_SOURCE_MACOSX_MACHPROCESS_H

lldb/tools/debugserver/source/MacOSX/MachProcess.mm

Lines changed: 121 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)