diff options
author | Jason Molenda <jmolenda@apple.com> | 2013-04-16 06:24:42 +0000 |
---|---|---|
committer | Jason Molenda <jmolenda@apple.com> | 2013-04-16 06:24:42 +0000 |
commit | 0e0954c85af89a1bd68227d63ebfc43a3780f4a4 (patch) | |
tree | d580e7fdfd96797e0c40d0bfbf2c3b544016047f | |
parent | 73d1739bc4eb1eadeb0ca33495d80e11aa85cd63 (diff) | |
download | bcm5719-llvm-0e0954c85af89a1bd68227d63ebfc43a3780f4a4.tar.gz bcm5719-llvm-0e0954c85af89a1bd68227d63ebfc43a3780f4a4.zip |
The dyld_all_image_infos structure, at version 13 and higher, has
a UUID for the shared cache libraries that can be used to confirm
that one process' shared cache is the same as another, or that a
process' in-memory shared cache is a match for a given on-disk
dyld_shared_cache binary file. Use these UUIDs to catch some
uncommon problems when the shared caches are being changed for debug
purposes.
<rdar://problem/13524467>
llvm-svn: 179583
-rw-r--r-- | lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp | 123 | ||||
-rw-r--r-- | lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h | 17 |
2 files changed, 127 insertions, 13 deletions
diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp index 05350230bcc..42f21f7bb36 100644 --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -38,6 +38,11 @@ #include "Plugins/Process/Utility/RegisterContextDarwin_i386.h" #include "Plugins/Process/Utility/RegisterContextDarwin_x86_64.h" +#if defined (__APPLE__) && defined (__arm__) +// GetLLDBSharedCacheUUID() needs to call dlsym() +#include <dlfcn.h> +#endif + using namespace lldb; using namespace lldb_private; using namespace llvm::MachO; @@ -1372,8 +1377,17 @@ ObjectFileMachO::ParseSymtab (bool minimize) // symbol and string table. Reading all of this symbol and string table // data across can slow down debug launch times, so we optimize this by // reading the memory for the __LINKEDIT section from this process. + + UUID lldb_shared_cache(GetLLDBSharedCacheUUID()); + UUID process_shared_cache(GetProcessSharedCacheUUID(process)); + bool use_lldb_cache = true; + if (lldb_shared_cache.IsValid() && process_shared_cache.IsValid() && lldb_shared_cache != process_shared_cache) + { + use_lldb_cache = false; + } + PlatformSP platform_sp (target.GetPlatform()); - if (platform_sp && platform_sp->IsHost()) + if (platform_sp && platform_sp->IsHost() && use_lldb_cache) { data_was_read = true; nlist_data.SetData((void *)symoff_addr, nlist_data_byte_size, eByteOrderLittle); @@ -1571,16 +1585,6 @@ ObjectFileMachO::ParseSymtab (bool minimize) // Before we can start mapping the DSC, we need to make certain the target process is actually // using the cache we can find. - /* - * TODO (FIXME!) - * - * Consider the case of testing with a separate DSC file. - * If we go through the normal code paths, we will give symbols for the wrong DSC, and - * that is bad. We need to read the target process' all_image_infos struct, and look - * at the values of the processDetachedFromSharedRegion field. If that is set, we should skip - * this code section. - */ - // Next we need to determine the correct path for the dyld shared cache. ArchSpec header_arch(eArchTypeMachO, m_header.cputype, m_header.cpusubtype); @@ -1688,14 +1692,35 @@ ObjectFileMachO::ParseSymtab (bool minimize) } } + UUID dsc_uuid; + if (version >= 1) + { + offset = offsetof (struct lldb_copy_dyld_cache_header_v1, uuid); + uint8_t uuid_bytes[sizeof (uuid_t)]; + memcpy (uuid_bytes, dsc_header_data.GetData (&offset, sizeof (uuid_t)), sizeof (uuid_t)); + dsc_uuid.SetBytes (uuid_bytes); + } + + bool uuid_match = true; + if (dsc_uuid.IsValid() && process) + { + UUID shared_cache_uuid(GetProcessSharedCacheUUID(process)); + + if (shared_cache_uuid.IsValid() && dsc_uuid != shared_cache_uuid) + { + // The on-disk dyld_shared_cache file is not the same as the one in this + // process' memory, don't use it. + uuid_match = false; + } + } + offset = offsetof (struct lldb_copy_dyld_cache_header_v1, mappingOffset); uint32_t mappingOffset = dsc_header_data.GetU32(&offset); // If the mappingOffset points to a location inside the header, we've // opened an old dyld shared cache, and should not proceed further. - if ((version == 0 && mappingOffset >= sizeof(struct lldb_copy_dyld_cache_header_v0)) - || (version >= 1 && mappingOffset >= sizeof(struct lldb_copy_dyld_cache_header_v1))) + if (uuid_match && mappingOffset >= sizeof(struct lldb_copy_dyld_cache_header_v0)) { DataBufferSP dsc_mapping_info_data_sp = dsc_filespec.MemoryMapFileContents(mappingOffset, sizeof (struct lldb_copy_dyld_cache_mapping_info)); @@ -3942,6 +3967,78 @@ ObjectFileMachO::GetArchitecture (ArchSpec &arch) } +UUID +ObjectFileMachO::GetProcessSharedCacheUUID (Process *process) +{ + UUID uuid; + if (process) + { + addr_t all_image_infos = process->GetImageInfoAddress(); + + // The address returned by GetImageInfoAddress may be the address of dyld (don't want) + // or it may be the address of the dyld_all_image_infos structure (want). The first four + // bytes will be either the version field (all_image_infos) or a Mach-O file magic constant. + // Version 13 and higher of dyld_all_image_infos is required to get the sharedCacheUUID field. + + Error err; + uint32_t version_or_magic = process->ReadUnsignedIntegerFromMemory (all_image_infos, 4, -1, err); + if (version_or_magic != -1 + && version_or_magic != HeaderMagic32 + && version_or_magic != HeaderMagic32Swapped + && version_or_magic != HeaderMagic64 + && version_or_magic != HeaderMagic64Swapped + && version_or_magic >= 13) + { + addr_t sharedCacheUUID_address = LLDB_INVALID_ADDRESS; + int wordsize = process->GetAddressByteSize(); + if (wordsize == 8) + { + sharedCacheUUID_address = all_image_infos + 160; // sharedCacheUUID <mach-o/dyld_images.h> + } + if (wordsize == 4) + { + sharedCacheUUID_address = all_image_infos + 84; // sharedCacheUUID <mach-o/dyld_images.h> + } + if (sharedCacheUUID_address != LLDB_INVALID_ADDRESS) + { + uuid_t shared_cache_uuid; + if (process->ReadMemory (sharedCacheUUID_address, shared_cache_uuid, sizeof (uuid_t), err) == sizeof (uuid_t)) + { + uuid.SetBytes (shared_cache_uuid); + } + } + } + } + return uuid; +} + +UUID +ObjectFileMachO::GetLLDBSharedCacheUUID () +{ + UUID uuid; +#if defined (__APPLE__) && defined (__arm__) + uint8_t *(*dyld_get_all_image_infos)(void); + dyld_get_all_image_infos = (uint8_t*(*)()) dlsym (RTLD_DEFAULT, "_dyld_get_all_image_infos"); + if (dyld_get_all_image_infos) + { + uint8_t *dyld_all_image_infos_address = dyld_get_all_image_infos(); + if (dyld_all_image_infos_address) + { + uint32_t version; + memcpy (&version, dyld_all_image_infos_address, 4); + if (version >= 13) + { + uint8_t *sharedCacheUUID_address = 0; + sharedCacheUUID_address = dyld_all_image_infos_address + 84; // sharedCacheUUID <mach-o/dyld_images.h> + uuid.SetBytes (sharedCacheUUID_address); + } + } + } +#endif + return uuid; +} + + //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h index c4a15407c4e..dcba2c5a6d6 100644 --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h @@ -145,6 +145,23 @@ public: GetVersion (uint32_t *versions, uint32_t num_versions); protected: + + // Intended for same-host arm device debugging where lldb needs to + // detect libraries in the shared cache and augment the nlist entries + // 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 + // correctly. + lldb_private::UUID + GetProcessSharedCacheUUID (lldb_private::Process *); + + // Intended for same-host arm device debugging where lldb will read + // shared cache libraries out of its own memory instead of the remote + // process' memory as an optimization. If lldb's shared cache UUID + // does not match the process' shared cache UUID, this optimization + // should not be used. + lldb_private::UUID + GetLLDBSharedCacheUUID (); + llvm::MachO::mach_header m_header; static const lldb_private::ConstString &GetSegmentNameTEXT(); static const lldb_private::ConstString &GetSegmentNameDATA(); |