diff --git a/lldb/include/lldb/Core/ModuleSpec.h b/lldb/include/lldb/Core/ModuleSpec.h index 9446c76e17ed..52e9499b464c 100644 --- a/lldb/include/lldb/Core/ModuleSpec.h +++ b/lldb/include/lldb/Core/ModuleSpec.h @@ -255,6 +255,19 @@ public: return m_source_mappings; } + void + Clear () + { + m_file.Clear(); + m_platform_file.Clear(); + m_symbol_file.Clear(); + m_arch.Clear(); + m_uuid.Clear(); + m_object_name.Clear(); + m_object_offset = 0; + m_source_mappings.Clear(false); + } + protected: FileSpec m_file; FileSpec m_platform_file; @@ -266,6 +279,121 @@ protected: mutable PathMappingList m_source_mappings; }; +class ModuleSpecList +{ +public: + ModuleSpecList () : + m_specs(), + m_mutex(Mutex::eMutexTypeRecursive) + { + } + + ModuleSpecList (const ModuleSpecList &rhs) : + m_specs(), + m_mutex(Mutex::eMutexTypeRecursive) + { + Mutex::Locker lhs_locker(m_mutex); + Mutex::Locker rhs_locker(rhs.m_mutex); + m_specs = rhs.m_specs; + } + + ~ModuleSpecList () + { + } + + size_t + GetSize() const + { + Mutex::Locker locker(m_mutex); + return m_specs.size(); + } + + void + Clear () + { + Mutex::Locker locker(m_mutex); + m_specs.clear(); + } + + void + Append (const ModuleSpec &spec) + { + Mutex::Locker locker(m_mutex); + m_specs.push_back (spec); + } + + bool + GetModuleSpecAtIndex (size_t i, ModuleSpec &module_spec) const + { + Mutex::Locker locker(m_mutex); + if (i < m_specs.size()) + { + module_spec = m_specs[i]; + return true; + } + module_spec.Clear(); + return false; + } + + bool + FindMatchingModuleSpec (const ModuleSpec &module_spec, ModuleSpec &match_module_spec) const + { + const FileSpec *file_ptr = module_spec.GetFileSpecPtr(); + const FileSpec *platform_file_ptr = module_spec.GetPlatformFileSpecPtr(); + const FileSpec *symbol_file_ptr = module_spec.GetSymbolFileSpecPtr(); + const ArchSpec *arch_ptr = module_spec.GetArchitecturePtr(); + const UUID *uuid_ptr = module_spec.GetUUIDPtr(); + const bool check_module_name = (bool)module_spec.GetObjectName(); + Mutex::Locker locker(m_mutex); + for (auto spec: m_specs) + { + if (uuid_ptr && spec.GetUUID() != *uuid_ptr) + continue; + if (check_module_name && module_spec.GetObjectName() != spec.GetObjectName()) + continue; + if (file_ptr && !FileSpec::Equal(*file_ptr, spec.GetFileSpec(), file_ptr->GetDirectory().IsEmpty() == false)) + continue; + if (platform_file_ptr && !FileSpec::Equal(*platform_file_ptr, spec.GetFileSpec(), platform_file_ptr->GetDirectory().IsEmpty() == false)) + continue; + if (symbol_file_ptr && !FileSpec::Equal(*symbol_file_ptr, spec.GetFileSpec(), symbol_file_ptr->GetDirectory().IsEmpty() == false)) + continue; + if (arch_ptr && !spec.GetArchitecture().IsExactMatch(*arch_ptr)) + continue; + match_module_spec = spec; + return true; + } + + // If there was an architecture, retry with a compatible arch + if (arch_ptr) + { + for (auto spec: m_specs) + { + if (uuid_ptr && spec.GetUUID() != *uuid_ptr) + continue; + if (check_module_name && module_spec.GetObjectName() != spec.GetObjectName()) + continue; + if (file_ptr && !FileSpec::Equal(*file_ptr, spec.GetFileSpec(), file_ptr->GetDirectory().IsEmpty() == false)) + continue; + if (platform_file_ptr && !FileSpec::Equal(*platform_file_ptr, spec.GetFileSpec(), platform_file_ptr->GetDirectory().IsEmpty() == false)) + continue; + if (symbol_file_ptr && !FileSpec::Equal(*symbol_file_ptr, spec.GetFileSpec(), symbol_file_ptr->GetDirectory().IsEmpty() == false)) + continue; + if (arch_ptr && !spec.GetArchitecture().IsCompatibleMatch(*arch_ptr)) + continue; + match_module_spec = spec; + return true; + } + } + match_module_spec.Clear(); + return false; + } + +protected: + typedef std::vector collection; ///< The module collection type. + collection m_specs; ///< The collection of modules. + mutable Mutex m_mutex; +}; + } // namespace lldb_private #endif // liblldb_ModuleSpec_h_ diff --git a/lldb/include/lldb/Core/PluginManager.h b/lldb/include/lldb/Core/PluginManager.h index 1033e93056a1..93f2c32a7aa7 100644 --- a/lldb/include/lldb/Core/PluginManager.h +++ b/lldb/include/lldb/Core/PluginManager.h @@ -138,7 +138,8 @@ public: RegisterPlugin (const char *name, const char *description, ObjectFileCreateInstance create_callback, - ObjectFileCreateMemoryInstance create_memory_callback); + ObjectFileCreateMemoryInstance create_memory_callback, + ObjectFileGetModuleSpecifications get_module_specifications); static bool UnregisterPlugin (ObjectFileCreateInstance create_callback); @@ -149,6 +150,9 @@ public: static ObjectFileCreateMemoryInstance GetObjectFileCreateMemoryCallbackAtIndex (uint32_t idx); + static ObjectFileGetModuleSpecifications + GetObjectFileGetModuleSpecificationsCallbackAtIndex (uint32_t idx); + static ObjectFileCreateInstance GetObjectFileCreateCallbackForPluginName (const char *name); @@ -162,7 +166,8 @@ public: static bool RegisterPlugin (const char *name, const char *description, - ObjectContainerCreateInstance create_callback); + ObjectContainerCreateInstance create_callback, + ObjectFileGetModuleSpecifications get_module_specifications); static bool UnregisterPlugin (ObjectContainerCreateInstance create_callback); @@ -173,6 +178,9 @@ public: static ObjectContainerCreateInstance GetObjectContainerCreateCallbackForPluginName (const char *name); + static ObjectFileGetModuleSpecifications + GetObjectContainerGetModuleSpecificationsCallbackAtIndex (uint32_t idx); + //------------------------------------------------------------------ // LogChannel //------------------------------------------------------------------ diff --git a/lldb/include/lldb/Symbol/ObjectFile.h b/lldb/include/lldb/Symbol/ObjectFile.h index 04fd1c644bc5..c8f3cd5254c9 100644 --- a/lldb/include/lldb/Symbol/ObjectFile.h +++ b/lldb/include/lldb/Symbol/ObjectFile.h @@ -178,6 +178,18 @@ public: lldb::DataBufferSP &file_data_sp); + static size_t + GetModuleSpecifications (const FileSpec &file, + lldb::offset_t file_offset, + ModuleSpecList &specs); + + static size_t + GetModuleSpecifications (const lldb_private::FileSpec& file, + lldb::DataBufferSP& data_sp, + lldb::offset_t data_offset, + lldb::offset_t file_offset, + lldb::offset_t length, + lldb_private::ModuleSpecList &specs); //------------------------------------------------------------------ /// Split a path into a file path with object name. /// diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h index 60575939379a..84af8b646901 100644 --- a/lldb/include/lldb/lldb-forward.h +++ b/lldb/include/lldb/lldb-forward.h @@ -113,6 +113,7 @@ class Materializer; class Module; class ModuleList; class ModuleSpec; +class ModuleSpecList; class Mutex; struct NameSearchContext; class ObjCLanguageRuntime; diff --git a/lldb/include/lldb/lldb-private-interfaces.h b/lldb/include/lldb/lldb-private-interfaces.h index 25b71e6efffc..492926e7a457 100644 --- a/lldb/include/lldb/lldb-private-interfaces.h +++ b/lldb/include/lldb/lldb-private-interfaces.h @@ -20,6 +20,7 @@ namespace lldb_private typedef Disassembler* (*DisassemblerCreateInstance) (const ArchSpec &arch, const char *flavor); typedef DynamicLoader* (*DynamicLoaderCreateInstance) (Process* process, bool force); typedef ObjectContainer* (*ObjectContainerCreateInstance) (const lldb::ModuleSP &module_sp, lldb::DataBufferSP& data_sp, lldb::offset_t data_offset, const FileSpec *file, lldb::offset_t offset, lldb::offset_t length); + typedef size_t (*ObjectFileGetModuleSpecifications) (const FileSpec &file, lldb::DataBufferSP& data_sp, lldb::offset_t data_offset, lldb::offset_t file_offset, lldb::offset_t length, ModuleSpecList &module_specs); typedef ObjectFile* (*ObjectFileCreateInstance) (const lldb::ModuleSP &module_sp, lldb::DataBufferSP& data_sp, lldb::offset_t data_offset, const FileSpec* file, lldb::offset_t file_offset, lldb::offset_t length); typedef ObjectFile* (*ObjectFileCreateMemoryInstance) (const lldb::ModuleSP &module_sp, lldb::DataBufferSP& data_sp, const lldb::ProcessSP &process_sp, lldb::addr_t offset); typedef LogChannel* (*LogChannelCreateInstance) (); diff --git a/lldb/source/Core/PluginManager.cpp b/lldb/source/Core/PluginManager.cpp index 4498182e7547..0cc916b115d8 100644 --- a/lldb/source/Core/PluginManager.cpp +++ b/lldb/source/Core/PluginManager.cpp @@ -870,7 +870,9 @@ struct ObjectFileInstance ObjectFileInstance() : name(), description(), - create_callback(NULL) + create_callback(NULL), + create_memory_callback (NULL), + get_module_specifications (NULL) { } @@ -878,7 +880,7 @@ struct ObjectFileInstance std::string description; ObjectFileCreateInstance create_callback; ObjectFileCreateMemoryInstance create_memory_callback; - + ObjectFileGetModuleSpecifications get_module_specifications; }; typedef std::vector ObjectFileInstances; @@ -899,13 +901,11 @@ GetObjectFileInstances () bool -PluginManager::RegisterPlugin -( - const char *name, - const char *description, - ObjectFileCreateInstance create_callback, - ObjectFileCreateMemoryInstance create_memory_callback -) +PluginManager::RegisterPlugin (const char *name, + const char *description, + ObjectFileCreateInstance create_callback, + ObjectFileCreateMemoryInstance create_memory_callback, + ObjectFileGetModuleSpecifications get_module_specifications) { if (create_callback) { @@ -916,6 +916,7 @@ PluginManager::RegisterPlugin instance.description = description; instance.create_callback = create_callback; instance.create_memory_callback = create_memory_callback; + instance.get_module_specifications = get_module_specifications; Mutex::Locker locker (GetObjectFileMutex ()); GetObjectFileInstances ().push_back (instance); } @@ -964,6 +965,16 @@ PluginManager::GetObjectFileCreateMemoryCallbackAtIndex (uint32_t idx) return NULL; } +ObjectFileGetModuleSpecifications +PluginManager::GetObjectFileGetModuleSpecificationsCallbackAtIndex (uint32_t idx) +{ + Mutex::Locker locker (GetObjectFileMutex ()); + ObjectFileInstances &instances = GetObjectFileInstances (); + if (idx < instances.size()) + return instances[idx].get_module_specifications; + return NULL; +} + ObjectFileCreateInstance PluginManager::GetObjectFileCreateCallbackForPluginName (const char *name) { @@ -1012,13 +1023,16 @@ struct ObjectContainerInstance ObjectContainerInstance() : name(), description(), - create_callback(NULL) + create_callback (NULL), + get_module_specifications (NULL) { } std::string name; std::string description; ObjectContainerCreateInstance create_callback; + ObjectFileGetModuleSpecifications get_module_specifications; + }; typedef std::vector ObjectContainerInstances; @@ -1038,12 +1052,10 @@ GetObjectContainerInstances () } bool -PluginManager::RegisterPlugin -( - const char *name, - const char *description, - ObjectContainerCreateInstance create_callback -) +PluginManager::RegisterPlugin (const char *name, + const char *description, + ObjectContainerCreateInstance create_callback, + ObjectFileGetModuleSpecifications get_module_specifications) { if (create_callback) { @@ -1053,6 +1065,7 @@ PluginManager::RegisterPlugin if (description && description[0]) instance.description = description; instance.create_callback = create_callback; + instance.get_module_specifications = get_module_specifications; Mutex::Locker locker (GetObjectContainerMutex ()); GetObjectContainerInstances ().push_back (instance); } @@ -1109,6 +1122,16 @@ PluginManager::GetObjectContainerCreateCallbackForPluginName (const char *name) return NULL; } +ObjectFileGetModuleSpecifications +PluginManager::GetObjectContainerGetModuleSpecificationsCallbackAtIndex (uint32_t idx) +{ + Mutex::Locker locker (GetObjectContainerMutex ()); + ObjectContainerInstances &instances = GetObjectContainerInstances (); + if (idx < instances.size()) + return instances[idx].get_module_specifications; + return NULL; +} + #pragma mark LogChannel struct LogInstance diff --git a/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp b/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp index 19d17f0033e3..2ca17e506be6 100644 --- a/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp +++ b/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.cpp @@ -239,7 +239,8 @@ ObjectContainerBSDArchive::Initialize() { PluginManager::RegisterPlugin (GetPluginNameStatic(), GetPluginDescriptionStatic(), - CreateInstance); + CreateInstance, + GetModuleSpecifications); } void @@ -472,3 +473,14 @@ ObjectContainerBSDArchive::GetPluginVersion() return 1; } + +size_t +ObjectContainerBSDArchive::GetModuleSpecifications (const lldb_private::FileSpec& file, + lldb::DataBufferSP& data_sp, + lldb::offset_t data_offset, + lldb::offset_t file_offset, + lldb::offset_t length, + lldb_private::ModuleSpecList &specs) +{ + return 0; +} diff --git a/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h b/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h index f4bd5d203620..7802eb152d56 100644 --- a/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h +++ b/lldb/source/Plugins/ObjectContainer/BSD-Archive/ObjectContainerBSDArchive.h @@ -46,6 +46,14 @@ public: lldb::offset_t offset, lldb::offset_t length); + static size_t + GetModuleSpecifications (const lldb_private::FileSpec& file, + lldb::DataBufferSP& data_sp, + lldb::offset_t data_offset, + lldb::offset_t file_offset, + lldb::offset_t length, + lldb_private::ModuleSpecList &specs); + static bool MagicBytesMatch (const lldb_private::DataExtractor &data); diff --git a/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp b/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp index 9a28736e3e68..d1f4434c987a 100644 --- a/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp +++ b/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.cpp @@ -11,6 +11,7 @@ #include "lldb/Core/ArchSpec.h" #include "lldb/Core/DataBuffer.h" #include "lldb/Core/Module.h" +#include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/Stream.h" #include "lldb/Symbol/ObjectFile.h" @@ -25,7 +26,8 @@ ObjectContainerUniversalMachO::Initialize() { PluginManager::RegisterPlugin (GetPluginNameStatic(), GetPluginDescriptionStatic(), - CreateInstance); + CreateInstance, + GetModuleSpecifications); } void @@ -108,45 +110,53 @@ ObjectContainerUniversalMachO::~ObjectContainerUniversalMachO() bool ObjectContainerUniversalMachO::ParseHeader () +{ + bool success = ParseHeader (m_data, m_header, m_fat_archs); + // We no longer need any data, we parsed all we needed to parse + // and cached it in m_header and m_fat_archs + m_data.Clear(); + return success; +} + +bool +ObjectContainerUniversalMachO::ParseHeader (lldb_private::DataExtractor &data, + llvm::MachO::fat_header &header, + std::vector &fat_archs) { bool success = false; // Store the file offset for this universal file as we could have a universal .o file // in a BSD archive, or be contained in another kind of object. - lldb::offset_t offset = 0; // Universal mach-o files always have their headers in big endian. - m_data.SetByteOrder (eByteOrderBig); - m_header.magic = m_data.GetU32(&offset); + lldb::offset_t offset = 0; + data.SetByteOrder (eByteOrderBig); + header.magic = data.GetU32(&offset); + fat_archs.clear(); - if (m_header.magic == UniversalMagic) + if (header.magic == UniversalMagic) { - m_data.SetAddressByteSize(4); - - m_header.nfat_arch = m_data.GetU32(&offset); + data.SetAddressByteSize(4); + + header.nfat_arch = data.GetU32(&offset); + // Now we should have enough data for all of the fat headers, so lets index // them so we know how many architectures that this universal binary contains. uint32_t arch_idx = 0; - for (arch_idx = 0; arch_idx < m_header.nfat_arch; ++arch_idx) + for (arch_idx = 0; arch_idx < header.nfat_arch; ++arch_idx) { - if (m_data.ValidOffsetForDataOfSize(offset, sizeof(fat_arch))) + if (data.ValidOffsetForDataOfSize(offset, sizeof(fat_arch))) { fat_arch arch; - if (m_data.GetU32(&offset, &arch, sizeof(fat_arch)/sizeof(uint32_t))) - { - m_fat_archs.push_back(arch); - } + if (data.GetU32(&offset, &arch, sizeof(fat_arch)/sizeof(uint32_t))) + fat_archs.push_back(arch); } } success = true; } else { - memset(&m_header, 0, sizeof(m_header)); + memset(&header, 0, sizeof(header)); } - - // We no longer need any data, we parsed all we needed to parse - // and cached it in m_header and m_fat_archs - m_data.Clear(); return success; } @@ -268,3 +278,33 @@ ObjectContainerUniversalMachO::GetPluginVersion() } +size_t +ObjectContainerUniversalMachO::GetModuleSpecifications (const lldb_private::FileSpec& file, + lldb::DataBufferSP& data_sp, + lldb::offset_t data_offset, + lldb::offset_t file_offset, + lldb::offset_t length, + lldb_private::ModuleSpecList &specs) +{ + const size_t initial_count = specs.GetSize(); + + DataExtractor data; + data.SetData (data_sp, data_offset, length); + + if (ObjectContainerUniversalMachO::MagicBytesMatch(data)) + { + llvm::MachO::fat_header header; + std::vector fat_archs; + if (ParseHeader (data, header, fat_archs)) + { + for (const llvm::MachO::fat_arch &fat_arch : fat_archs) + { + ObjectFile::GetModuleSpecifications (file, + fat_arch.offset + file_offset, + specs); + } + } + } + return specs.GetSize() - initial_count; +} + diff --git a/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h b/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h index 78945b0ef98e..1fe1a2d2165c 100644 --- a/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h +++ b/lldb/source/Plugins/ObjectContainer/Universal-Mach-O/ObjectContainerUniversalMachO.h @@ -42,6 +42,14 @@ public: lldb::offset_t offset, lldb::offset_t length); + static size_t + GetModuleSpecifications (const lldb_private::FileSpec& file, + lldb::DataBufferSP& data_sp, + lldb::offset_t data_offset, + lldb::offset_t file_offset, + lldb::offset_t length, + lldb_private::ModuleSpecList &specs); + static bool MagicBytesMatch (const lldb_private::DataExtractor &data); @@ -88,6 +96,12 @@ public: protected: llvm::MachO::fat_header m_header; std::vector m_fat_archs; + + static bool + ParseHeader (lldb_private::DataExtractor &data, + llvm::MachO::fat_header &header, + std::vector &fat_archs); + }; #endif // liblldb_ObjectContainerUniversalMachO_h_ diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index 0ce96b972d84..4ba081a7b7ca 100644 --- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -17,6 +17,7 @@ #include "lldb/Core/Error.h" #include "lldb/Core/FileSpecList.h" #include "lldb/Core/Module.h" +#include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/Section.h" #include "lldb/Core/Stream.h" @@ -149,7 +150,8 @@ ObjectFileELF::Initialize() PluginManager::RegisterPlugin(GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance, - CreateMemoryInstance); + CreateMemoryInstance, + GetModuleSpecifications); } void @@ -220,6 +222,17 @@ ObjectFileELF::CreateMemoryInstance (const lldb::ModuleSP &module_sp, } +size_t +ObjectFileELF::GetModuleSpecifications (const lldb_private::FileSpec& file, + lldb::DataBufferSP& data_sp, + lldb::offset_t data_offset, + lldb::offset_t file_offset, + lldb::offset_t length, + lldb_private::ModuleSpecList &specs) +{ + return 0; +} + //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h index 66b6f7110c22..78cfb3f5157c 100644 --- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h +++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h @@ -58,6 +58,13 @@ public: const lldb::ProcessSP &process_sp, lldb::addr_t header_addr); + static size_t + GetModuleSpecifications (const lldb_private::FileSpec& file, + lldb::DataBufferSP& data_sp, + lldb::offset_t data_offset, + lldb::offset_t file_offset, + lldb::offset_t length, + lldb_private::ModuleSpecList &specs); //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp index 90e56054a1fc..7bd6020f1e63 100644 --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -19,6 +19,7 @@ #include "lldb/Core/FileSpecList.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" +#include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/RangeMap.h" #include "lldb/Core/Section.h" @@ -367,7 +368,8 @@ ObjectFileMachO::Initialize() PluginManager::RegisterPlugin (GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance, - CreateMemoryInstance); + CreateMemoryInstance, + GetModuleSpecifications); } void @@ -433,6 +435,47 @@ ObjectFileMachO::CreateMemoryInstance (const lldb::ModuleSP &module_sp, return NULL; } +size_t +ObjectFileMachO::GetModuleSpecifications (const lldb_private::FileSpec& file, + lldb::DataBufferSP& data_sp, + lldb::offset_t data_offset, + lldb::offset_t file_offset, + lldb::offset_t length, + lldb_private::ModuleSpecList &specs) +{ + const size_t initial_count = specs.GetSize(); + + if (ObjectFileMachO::MagicBytesMatch(data_sp, 0, data_sp->GetByteSize())) + { + DataExtractor data; + data.SetData(data_sp); + llvm::MachO::mach_header header; + if (ParseHeader (data, &data_offset, header)) + { + if (header.sizeofcmds >= data_sp->GetByteSize()) + { + data_sp = file.ReadFileContents(file_offset, header.sizeofcmds); + data_offset = 0; + } + if (data_sp) + { + ModuleSpec spec; + spec.GetFileSpec() = file; + spec.GetArchitecture().SetArchitecture(eArchTypeMachO, + header.cputype, + header.cpusubtype); + if (spec.GetArchitecture().IsValid()) + { + GetUUID (header, data, data_offset, spec.GetUUID()); + specs.Append(spec); + } + } + } + } + return specs.GetSize() - initial_count; +} + + const ConstString & ObjectFileMachO::GetSegmentNameTEXT() @@ -541,6 +584,61 @@ ObjectFileMachO::~ObjectFileMachO() { } +bool +ObjectFileMachO::ParseHeader (DataExtractor &data, + lldb::offset_t *data_offset_ptr, + llvm::MachO::mach_header &header) +{ + data.SetByteOrder (lldb::endian::InlHostByteOrder()); + // Leave magic in the original byte order + header.magic = data.GetU32(data_offset_ptr); + bool can_parse = false; + bool is_64_bit = false; + switch (header.magic) + { + case HeaderMagic32: + data.SetByteOrder (lldb::endian::InlHostByteOrder()); + data.SetAddressByteSize(4); + can_parse = true; + break; + + case HeaderMagic64: + data.SetByteOrder (lldb::endian::InlHostByteOrder()); + data.SetAddressByteSize(8); + can_parse = true; + is_64_bit = true; + break; + + case HeaderMagic32Swapped: + data.SetByteOrder(lldb::endian::InlHostByteOrder() == eByteOrderBig ? eByteOrderLittle : eByteOrderBig); + data.SetAddressByteSize(4); + can_parse = true; + break; + + case HeaderMagic64Swapped: + data.SetByteOrder(lldb::endian::InlHostByteOrder() == eByteOrderBig ? eByteOrderLittle : eByteOrderBig); + data.SetAddressByteSize(8); + is_64_bit = true; + can_parse = true; + break; + + default: + break; + } + + if (can_parse) + { + data.GetU32(data_offset_ptr, &header.cputype, 6); + if (is_64_bit) + *data_offset_ptr += 4; + return true; + } + else + { + memset(&header, 0, sizeof(header)); + } + return false; +} bool ObjectFileMachO::ParseHeader () @@ -3481,6 +3579,49 @@ ObjectFileMachO::Dump (Stream *s) } } +bool +ObjectFileMachO::GetUUID (const llvm::MachO::mach_header &header, + const lldb_private::DataExtractor &data, + lldb::offset_t lc_offset, + lldb_private::UUID& uuid) +{ + uint32_t i; + struct uuid_command load_cmd; + + lldb::offset_t offset = lc_offset; + for (i=0; iGetMutex()); - struct uuid_command load_cmd; lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic); - uint32_t i; - for (i=0; iSetBytes (uuid_bytes); - return true; - } - return false; - } - offset = cmd_offset + load_cmd.cmdsize; - } + return GetUUID (m_header, m_data, offset, *uuid); } return false; } diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h index dcba2c5a6d64..2226e3dd6959 100644 --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h @@ -55,6 +55,14 @@ public: const lldb::ProcessSP &process_sp, lldb::addr_t header_addr); + static size_t + GetModuleSpecifications (const lldb_private::FileSpec& file, + lldb::DataBufferSP& data_sp, + lldb::offset_t data_offset, + lldb::offset_t file_offset, + lldb::offset_t length, + lldb_private::ModuleSpecList &specs); + static bool MagicBytesMatch (lldb::DataBufferSP& data_sp, lldb::addr_t offset, @@ -146,7 +154,19 @@ public: protected: - // Intended for same-host arm device debugging where lldb needs to + static bool + ParseHeader (lldb_private::DataExtractor &data, + lldb::offset_t *data_offset_ptr, + llvm::MachO::mach_header &header); + + + static bool + GetUUID (const llvm::MachO::mach_header &header, + const lldb_private::DataExtractor &data, + lldb::offset_t lc_offset, // Offset to the first load command + lldb_private::UUID& uuid); + + // 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 diff --git a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp index 4ce198b7ee2b..157b148ee5c9 100644 --- a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp +++ b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp @@ -16,6 +16,7 @@ #include "lldb/Host/FileSpec.h" #include "lldb/Core/FileSpecList.h" #include "lldb/Core/Module.h" +#include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/Section.h" #include "lldb/Core/StreamFile.h" @@ -121,7 +122,8 @@ ObjectFilePECOFF::Initialize() PluginManager::RegisterPlugin (GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance, - CreateMemoryInstance); + CreateMemoryInstance, + GetModuleSpecifications); } void @@ -179,6 +181,18 @@ ObjectFilePECOFF::CreateMemoryInstance (const lldb::ModuleSP &module_sp, return NULL; } +size_t +ObjectFilePECOFF::GetModuleSpecifications (const lldb_private::FileSpec& file, + lldb::DataBufferSP& data_sp, + lldb::offset_t data_offset, + lldb::offset_t file_offset, + lldb::offset_t length, + lldb_private::ModuleSpecList &specs) +{ + return 0; +} + + bool ObjectFilePECOFF::MagicBytesMatch (DataBufferSP& data_sp) { diff --git a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h index 814559f56387..33973abad02c 100644 --- a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h +++ b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h @@ -47,6 +47,15 @@ public: lldb::DataBufferSP& data_sp, const lldb::ProcessSP &process_sp, lldb::addr_t header_addr); + + static size_t + GetModuleSpecifications (const lldb_private::FileSpec& file, + lldb::DataBufferSP& data_sp, + lldb::offset_t data_offset, + lldb::offset_t file_offset, + lldb::offset_t length, + lldb_private::ModuleSpecList &specs); + static bool MagicBytesMatch (lldb::DataBufferSP& data_sp); diff --git a/lldb/source/Symbol/ObjectFile.cpp b/lldb/source/Symbol/ObjectFile.cpp index c12cdd6517f8..a713543b25d5 100644 --- a/lldb/source/Symbol/ObjectFile.cpp +++ b/lldb/source/Symbol/ObjectFile.cpp @@ -13,6 +13,7 @@ #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" +#include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/RegularExpression.h" #include "lldb/Core/Section.h" @@ -184,8 +185,51 @@ ObjectFile::FindPlugin (const lldb::ModuleSP &module_sp, return object_file_sp; } -ObjectFile::ObjectFile (const lldb::ModuleSP &module_sp, - const FileSpec *file_spec_ptr, +size_t +ObjectFile::GetModuleSpecifications (const FileSpec &file, + lldb::offset_t file_offset, + ModuleSpecList &specs) +{ + DataBufferSP data_sp (file.ReadFileContents(file_offset, 512)); + if (data_sp) + return ObjectFile::GetModuleSpecifications (file, // file spec + data_sp, // data bytes + 0, // data offset + file_offset, // file offset + data_sp->GetByteSize(), // data length + specs); + return 0; +} + +size_t +ObjectFile::GetModuleSpecifications (const lldb_private::FileSpec& file, + lldb::DataBufferSP& data_sp, + lldb::offset_t data_offset, + lldb::offset_t file_offset, + lldb::offset_t length, + lldb_private::ModuleSpecList &specs) +{ + const size_t initial_count = specs.GetSize(); + ObjectFileGetModuleSpecifications callback; + uint32_t i; + // Try the ObjectFile plug-ins + for (i = 0; (callback = PluginManager::GetObjectFileGetModuleSpecificationsCallbackAtIndex(i)) != NULL; ++i) + { + if (callback (file, data_sp, data_offset, file_offset, length, specs) > 0) + return specs.GetSize() - initial_count; + } + + // Try the ObjectContainer plug-ins + for (i = 0; (callback = PluginManager::GetObjectContainerGetModuleSpecificationsCallbackAtIndex(i)) != NULL; ++i) + { + if (callback (file, data_sp, data_offset, file_offset, length, specs) > 0) + return specs.GetSize() - initial_count; + } + return 0; +} + +ObjectFile::ObjectFile (const lldb::ModuleSP &module_sp, + const FileSpec *file_spec_ptr, lldb::offset_t file_offset, lldb::offset_t length, lldb::DataBufferSP& data_sp, diff --git a/lldb/source/Target/TargetList.cpp b/lldb/source/Target/TargetList.cpp index 3b13a0885de9..1bc32946ca5b 100644 --- a/lldb/source/Target/TargetList.cpp +++ b/lldb/source/Target/TargetList.cpp @@ -17,11 +17,13 @@ #include "lldb/Core/Debugger.h" #include "lldb/Core/Event.h" #include "lldb/Core/Module.h" +#include "lldb/Core/ModuleSpec.h" #include "lldb/Core/State.h" #include "lldb/Core/Timer.h" #include "lldb/Host/Host.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/OptionGroupPlatform.h" +#include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" #include "lldb/Target/TargetList.h" @@ -80,8 +82,67 @@ TargetList::CreateTarget (Debugger &debugger, return error; } } - + ArchSpec platform_arch(arch); + + + if (user_exe_path && user_exe_path[0]) + { + ModuleSpecList module_specs; + ModuleSpec module_spec; + module_spec.GetFileSpec().SetFile(user_exe_path, true); + lldb::offset_t file_offset = 0; + const size_t num_specs = ObjectFile::GetModuleSpecifications (module_spec.GetFileSpec(), file_offset, module_specs); + if (num_specs > 0) + { + ModuleSpec matching_module_spec; + + if (num_specs == 1) + { + if (module_specs.GetModuleSpecAtIndex(0, matching_module_spec)) + { + if (platform_arch.IsValid()) + { + if (!platform_arch.IsCompatibleMatch(matching_module_spec.GetArchitecture())) + { + error.SetErrorStringWithFormat("the specified architecture '%s' is not compatible with '%s' in '%s%s%s'", + platform_arch.GetTriple().str().c_str(), + matching_module_spec.GetArchitecture().GetTriple().str().c_str(), + module_spec.GetFileSpec().GetDirectory() ? module_spec.GetFileSpec().GetDirectory().GetCString() : "", + module_spec.GetFileSpec().GetDirectory() ? "/" : "", + module_spec.GetFileSpec().GetFilename().GetCString()); + return error; + } + } + else + { + // Only one arch and none was specified + platform_arch = matching_module_spec.GetArchitecture(); + } + } + } + else + { + if (arch.IsValid()) + { + module_spec.GetArchitecture() = arch; + if (module_specs.FindMatchingModuleSpec(module_spec, matching_module_spec)) + { + platform_arch = matching_module_spec.GetArchitecture(); + } + } + else + { + // No arch specified, select the first arch + if (module_specs.GetModuleSpecAtIndex(0, matching_module_spec)) + { + platform_arch = matching_module_spec.GetArchitecture(); + } + } + } + } + } + CommandInterpreter &interpreter = debugger.GetCommandInterpreter(); if (platform_options) {