forked from OSchip/llvm-project
The on-ios-device command line lldb has an optimization where
when it and the inferior process both have the same shared cache (a conglomeration of all libraries at the same fixed address for all processes), lldb will read data out of its own memory to speed things up. The shared cache has a UUID, so lldb currently checks that the UUID of its own shared cache matches that of the inferior. This change adds one refinement to that -- it checks that the UUID is the same and that the base address of the shared cache is the same. And only uses its local shared cache if they are both identical. This involved using a different style of SPI with dyld to get lldb's shared cache load address, but it's not especially difficult. One unattractive part of the change is that I'm using the real underlying types of task_t and kern_return_t instead of picking them up from mach/mach.h. The defines that get picked up there (a lot from machine.h but others too) conflict with llvm/Support/MachO.h even when I have mach.h included before our SafeMachO.h which undefines most of the defines before including llvm/Support/MachO.h. I'll need to augment the #undefs in SafeMachO.h to get this to compile cleanly, but that'll be another day. <rdar://problem/39868238> llvm-svn: 331497
This commit is contained in:
parent
4cc0d4e823
commit
07580ffe47
lldb/source/Plugins/ObjectFile/Mach-O
|
@ -2280,17 +2280,17 @@ size_t ObjectFileMachO::ParseSymtab() {
|
||||||
// this by reading the memory for the __LINKEDIT section from this
|
// this by reading the memory for the __LINKEDIT section from this
|
||||||
// process.
|
// process.
|
||||||
|
|
||||||
UUID lldb_shared_cache(GetLLDBSharedCacheUUID());
|
UUID lldb_shared_cache;
|
||||||
UUID process_shared_cache(GetProcessSharedCacheUUID(process));
|
addr_t lldb_shared_cache_addr;
|
||||||
|
GetLLDBSharedCacheUUID (lldb_shared_cache_addr, lldb_shared_cache);
|
||||||
|
UUID process_shared_cache;
|
||||||
|
addr_t process_shared_cache_addr;
|
||||||
|
GetProcessSharedCacheUUID(process, process_shared_cache_addr, process_shared_cache);
|
||||||
bool use_lldb_cache = true;
|
bool use_lldb_cache = true;
|
||||||
if (lldb_shared_cache.IsValid() && process_shared_cache.IsValid() &&
|
if (lldb_shared_cache.IsValid() && process_shared_cache.IsValid() &&
|
||||||
lldb_shared_cache != process_shared_cache) {
|
(lldb_shared_cache != process_shared_cache
|
||||||
|
|| process_shared_cache_addr != lldb_shared_cache_addr)) {
|
||||||
use_lldb_cache = false;
|
use_lldb_cache = false;
|
||||||
ModuleSP module_sp(GetModule());
|
|
||||||
if (module_sp)
|
|
||||||
module_sp->ReportWarning("shared cache in process does not match "
|
|
||||||
"lldb's own shared cache, startup will "
|
|
||||||
"be slow.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PlatformSP platform_sp(target.GetPlatform());
|
PlatformSP platform_sp(target.GetPlatform());
|
||||||
|
@ -2605,9 +2605,10 @@ size_t ObjectFileMachO::ParseSymtab() {
|
||||||
|
|
||||||
UUID dsc_uuid;
|
UUID dsc_uuid;
|
||||||
UUID process_shared_cache_uuid;
|
UUID process_shared_cache_uuid;
|
||||||
|
addr_t process_shared_cache_base_addr;
|
||||||
|
|
||||||
if (process) {
|
if (process) {
|
||||||
process_shared_cache_uuid = GetProcessSharedCacheUUID(process);
|
GetProcessSharedCacheUUID(process, process_shared_cache_base_addr, process_shared_cache_uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
// First see if we can find an exact match for the inferior process
|
// First see if we can find an exact match for the inferior process
|
||||||
|
@ -5577,24 +5578,40 @@ bool ObjectFileMachO::GetArchitecture(ArchSpec &arch) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
UUID ObjectFileMachO::GetProcessSharedCacheUUID(Process *process) {
|
void ObjectFileMachO::GetProcessSharedCacheUUID(Process *process, addr_t &base_addr, UUID &uuid) {
|
||||||
UUID uuid;
|
uuid.Clear();
|
||||||
|
base_addr = LLDB_INVALID_ADDRESS;
|
||||||
if (process && process->GetDynamicLoader()) {
|
if (process && process->GetDynamicLoader()) {
|
||||||
DynamicLoader *dl = process->GetDynamicLoader();
|
DynamicLoader *dl = process->GetDynamicLoader();
|
||||||
addr_t load_address;
|
|
||||||
LazyBool using_shared_cache;
|
LazyBool using_shared_cache;
|
||||||
LazyBool private_shared_cache;
|
LazyBool private_shared_cache;
|
||||||
dl->GetSharedCacheInformation(load_address, uuid, using_shared_cache,
|
dl->GetSharedCacheInformation(base_addr, uuid, using_shared_cache,
|
||||||
private_shared_cache);
|
private_shared_cache);
|
||||||
}
|
}
|
||||||
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS | LIBLLDB_LOG_PROCESS));
|
Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS | LIBLLDB_LOG_PROCESS));
|
||||||
if (log)
|
if (log)
|
||||||
log->Printf("inferior process shared cache has a UUID of %s", uuid.GetAsString().c_str());
|
log->Printf("inferior process shared cache has a UUID of %s, base address 0x%" PRIx64 , uuid.GetAsString().c_str(), base_addr);
|
||||||
return uuid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UUID ObjectFileMachO::GetLLDBSharedCacheUUID() {
|
// From dyld SPI header dyld_process_info.h
|
||||||
UUID uuid;
|
typedef void *dyld_process_info;
|
||||||
|
struct lldb_copy__dyld_process_cache_info {
|
||||||
|
uuid_t cacheUUID; // UUID of cache used by process
|
||||||
|
uint64_t cacheBaseAddress; // load address of dyld shared cache
|
||||||
|
bool noCache; // process is running without a dyld cache
|
||||||
|
bool privateCache; // process is using a private copy of its dyld cache
|
||||||
|
};
|
||||||
|
|
||||||
|
// #including mach/mach.h pulls in machine.h & CPU_TYPE_ARM etc conflicts with llvm
|
||||||
|
// enum definitions llvm::MachO::CPU_TYPE_ARM turning them into compile errors.
|
||||||
|
// So we need to use the actual underlying types of task_t and kern_return_t
|
||||||
|
// below.
|
||||||
|
extern "C" unsigned int /*task_t*/ mach_task_self();
|
||||||
|
|
||||||
|
void ObjectFileMachO::GetLLDBSharedCacheUUID(addr_t &base_addr, UUID &uuid) {
|
||||||
|
uuid.Clear();
|
||||||
|
base_addr = LLDB_INVALID_ADDRESS;
|
||||||
|
|
||||||
#if defined(__APPLE__) && \
|
#if defined(__APPLE__) && \
|
||||||
(defined(__arm__) || defined(__arm64__) || defined(__aarch64__))
|
(defined(__arm__) || defined(__arm64__) || defined(__aarch64__))
|
||||||
uint8_t *(*dyld_get_all_image_infos)(void);
|
uint8_t *(*dyld_get_all_image_infos)(void);
|
||||||
|
@ -5612,30 +5629,54 @@ UUID ObjectFileMachO::GetLLDBSharedCacheUUID() {
|
||||||
sharedCacheUUID_address =
|
sharedCacheUUID_address =
|
||||||
(uuid_t *)((uint8_t *)dyld_all_image_infos_address +
|
(uuid_t *)((uint8_t *)dyld_all_image_infos_address +
|
||||||
160); // sharedCacheUUID <mach-o/dyld_images.h>
|
160); // sharedCacheUUID <mach-o/dyld_images.h>
|
||||||
|
if (*version >= 15)
|
||||||
|
base_addr = *(uint64_t *) ((uint8_t *) dyld_all_image_infos_address
|
||||||
|
+ 176); // sharedCacheBaseAddress <mach-o/dyld_images.h>
|
||||||
} else {
|
} else {
|
||||||
sharedCacheUUID_address =
|
sharedCacheUUID_address =
|
||||||
(uuid_t *)((uint8_t *)dyld_all_image_infos_address +
|
(uuid_t *)((uint8_t *)dyld_all_image_infos_address +
|
||||||
84); // sharedCacheUUID <mach-o/dyld_images.h>
|
84); // sharedCacheUUID <mach-o/dyld_images.h>
|
||||||
|
if (*version >= 15) {
|
||||||
|
base_addr = 0;
|
||||||
|
base_addr = *(uint32_t *) ((uint8_t *) dyld_all_image_infos_address
|
||||||
|
+ 100); // sharedCacheBaseAddress <mach-o/dyld_images.h>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
uuid.SetBytes(sharedCacheUUID_address);
|
uuid.SetBytes(sharedCacheUUID_address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Exists in macOS 10.12 and later, iOS 10.0 and later - dyld SPI
|
// Exists in macOS 10.12 and later, iOS 10.0 and later - dyld SPI
|
||||||
bool *(*dyld_get_shared_cache_uuid)(uuid_t);
|
dyld_process_info (*dyld_process_info_create)(unsigned int /* task_t */ task, uint64_t timestamp, unsigned int /*kern_return_t*/ *kernelError);
|
||||||
dyld_get_shared_cache_uuid = (bool *(*)(uuid_t))
|
void (*dyld_process_info_get_cache)(void *info, void *cacheInfo);
|
||||||
dlsym(RTLD_DEFAULT, "_dyld_get_shared_cache_uuid");
|
void (*dyld_process_info_release)(dyld_process_info info);
|
||||||
if (dyld_get_shared_cache_uuid) {
|
|
||||||
uuid_t tmp_uuid;
|
dyld_process_info_create = (void *(*)(unsigned int /* task_t */, uint64_t, unsigned int /*kern_return_t*/ *))
|
||||||
if (dyld_get_shared_cache_uuid(tmp_uuid))
|
dlsym (RTLD_DEFAULT, "_dyld_process_info_create");
|
||||||
uuid.SetBytes(tmp_uuid);
|
dyld_process_info_get_cache = (void (*)(void *, void *))
|
||||||
|
dlsym (RTLD_DEFAULT, "_dyld_process_info_get_cache");
|
||||||
|
dyld_process_info_release = (void (*)(void *))
|
||||||
|
dlsym (RTLD_DEFAULT, "_dyld_process_info_release");
|
||||||
|
|
||||||
|
if (dyld_process_info_create && dyld_process_info_get_cache) {
|
||||||
|
unsigned int /*kern_return_t */ kern_ret;
|
||||||
|
dyld_process_info process_info = dyld_process_info_create(::mach_task_self(), 0, &kern_ret);
|
||||||
|
if (process_info) {
|
||||||
|
struct lldb_copy__dyld_process_cache_info sc_info;
|
||||||
|
memset (&sc_info, 0, sizeof (struct lldb_copy__dyld_process_cache_info));
|
||||||
|
dyld_process_info_get_cache (process_info, &sc_info);
|
||||||
|
if (sc_info.cacheBaseAddress != 0) {
|
||||||
|
base_addr = sc_info.cacheBaseAddress;
|
||||||
|
uuid.SetBytes (sc_info.cacheUUID);
|
||||||
|
}
|
||||||
|
dyld_process_info_release (process_info);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS | LIBLLDB_LOG_PROCESS));
|
Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS | LIBLLDB_LOG_PROCESS));
|
||||||
if (log && uuid.IsValid())
|
if (log && uuid.IsValid())
|
||||||
log->Printf("lldb's in-memory shared cache has a UUID of %s", uuid.GetAsString().c_str());
|
log->Printf("lldb's in-memory shared cache has a UUID of %s base address of 0x%" PRIx64, uuid.GetAsString().c_str(), base_addr);
|
||||||
#endif
|
#endif
|
||||||
return uuid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ObjectFileMachO::GetMinimumOSVersion(uint32_t *versions,
|
uint32_t ObjectFileMachO::GetMinimumOSVersion(uint32_t *versions,
|
||||||
|
|
|
@ -162,14 +162,14 @@ protected:
|
||||||
// with an on-disk dyld_shared_cache file. The process will record
|
// with an on-disk dyld_shared_cache file. The process will record
|
||||||
// the shared cache UUID so the on-disk cache can be matched or rejected
|
// the shared cache UUID so the on-disk cache can be matched or rejected
|
||||||
// correctly.
|
// correctly.
|
||||||
lldb_private::UUID GetProcessSharedCacheUUID(lldb_private::Process *);
|
void GetProcessSharedCacheUUID(lldb_private::Process *, lldb::addr_t &base_addr, lldb_private::UUID &uuid);
|
||||||
|
|
||||||
// Intended for same-host arm device debugging where lldb will read
|
// Intended for same-host arm device debugging where lldb will read
|
||||||
// shared cache libraries out of its own memory instead of the remote
|
// shared cache libraries out of its own memory instead of the remote
|
||||||
// process' memory as an optimization. If lldb's shared cache UUID
|
// process' memory as an optimization. If lldb's shared cache UUID
|
||||||
// does not match the process' shared cache UUID, this optimization
|
// does not match the process' shared cache UUID, this optimization
|
||||||
// should not be used.
|
// should not be used.
|
||||||
lldb_private::UUID GetLLDBSharedCacheUUID();
|
void GetLLDBSharedCacheUUID(lldb::addr_t &base_addir, lldb_private::UUID &uuid);
|
||||||
|
|
||||||
lldb_private::Section *GetMachHeaderSection();
|
lldb_private::Section *GetMachHeaderSection();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue