diff --git a/lldb/include/lldb/Core/PluginManager.h b/lldb/include/lldb/Core/PluginManager.h --- a/lldb/include/lldb/Core/PluginManager.h +++ b/lldb/include/lldb/Core/PluginManager.h @@ -197,16 +197,20 @@ llvm::StringRef plugin_name); // ObjectContainer - static bool - RegisterPlugin(llvm::StringRef name, llvm::StringRef description, - ObjectContainerCreateInstance create_callback, - ObjectFileGetModuleSpecifications get_module_specifications); + static bool RegisterPlugin( + llvm::StringRef name, llvm::StringRef description, + ObjectContainerCreateInstance create_callback, + ObjectFileGetModuleSpecifications get_module_specifications, + ObjectContainerCreateMemoryInstance create_memory_callback = nullptr); static bool UnregisterPlugin(ObjectContainerCreateInstance create_callback); static ObjectContainerCreateInstance GetObjectContainerCreateCallbackAtIndex(uint32_t idx); + static ObjectContainerCreateMemoryInstance + GetObjectContainerCreateMemoryCallbackAtIndex(uint32_t idx); + static ObjectFileGetModuleSpecifications GetObjectContainerGetModuleSpecificationsCallbackAtIndex(uint32_t idx); diff --git a/lldb/include/lldb/Symbol/ObjectContainer.h b/lldb/include/lldb/Symbol/ObjectContainer.h --- a/lldb/include/lldb/Symbol/ObjectContainer.h +++ b/lldb/include/lldb/Symbol/ObjectContainer.h @@ -36,15 +36,7 @@ /// more than one architecture or object. ObjectContainer(const lldb::ModuleSP &module_sp, const FileSpec *file, lldb::offset_t file_offset, lldb::offset_t length, - lldb::DataBufferSP &data_sp, lldb::offset_t data_offset) - : ModuleChild(module_sp), - m_file(), // This file can be different than the module's file spec - m_offset(file_offset), m_length(length) { - if (file) - m_file = *file; - if (data_sp) - m_data.SetData(data_sp, data_offset, length); - } + lldb::DataBufferSP data_sp, lldb::offset_t data_offset); /// Destructor. /// @@ -132,15 +124,23 @@ /// file exists in the container. virtual lldb::ObjectFileSP GetObjectFile(const FileSpec *file) = 0; + static lldb::ObjectContainerSP + FindPlugin(const lldb::ModuleSP &module_sp, const lldb::ProcessSP &process_sp, + lldb::addr_t header_addr, lldb::WritableDataBufferSP file_data_sp); + protected: - // Member variables. - FileSpec m_file; ///< The file that represents this container objects (which - ///can be different from the module's file). - lldb::addr_t - m_offset; ///< The offset in bytes into the file, or the address in memory - lldb::addr_t m_length; ///< The size in bytes if known (can be zero). - DataExtractor - m_data; ///< The data for this object file so things can be parsed lazily. + /// The file that represents this container objects (which can be different + /// from the module's file). + FileSpec m_file; + + /// The offset in bytes into the file, or the address in memory + lldb::addr_t m_offset; + + /// The size in bytes if known (can be zero). + lldb::addr_t m_length; + + /// The data for this object file so things can be parsed lazily. + DataExtractor m_data; private: ObjectContainer(const ObjectContainer &) = delete; diff --git a/lldb/include/lldb/Symbol/ObjectFile.h b/lldb/include/lldb/Symbol/ObjectFile.h --- a/lldb/include/lldb/Symbol/ObjectFile.h +++ b/lldb/include/lldb/Symbol/ObjectFile.h @@ -723,6 +723,8 @@ /// file when storing cached data. uint32_t GetCacheHash(); + static lldb::DataBufferSP MapFileData(const FileSpec &file, uint64_t Size, + uint64_t Offset); protected: // Member variables. @@ -764,9 +766,6 @@ /// The number of bytes to read when going through the plugins. static size_t g_initial_bytes_to_read; - static lldb::DataBufferSP MapFileData(const FileSpec &file, uint64_t Size, - uint64_t Offset); - private: ObjectFile(const ObjectFile &) = delete; const ObjectFile &operator=(const ObjectFile &) = delete; diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h --- a/lldb/include/lldb/lldb-forward.h +++ b/lldb/include/lldb/lldb-forward.h @@ -349,6 +349,7 @@ typedef std::shared_ptr ModuleSP; typedef std::weak_ptr ModuleWP; typedef std::shared_ptr ObjectFileSP; +typedef std::shared_ptr ObjectContainerSP; typedef std::shared_ptr ObjectFileJITDelegateSP; typedef std::weak_ptr diff --git a/lldb/include/lldb/lldb-private-interfaces.h b/lldb/include/lldb/lldb-private-interfaces.h --- a/lldb/include/lldb/lldb-private-interfaces.h +++ b/lldb/include/lldb/lldb-private-interfaces.h @@ -40,6 +40,9 @@ 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 ObjectContainer *(*ObjectContainerCreateMemoryInstance)( + const lldb::ModuleSP &module_sp, lldb::WritableDataBufferSP data_sp, + const lldb::ProcessSP &process_sp, lldb::addr_t offset); typedef size_t (*ObjectFileGetModuleSpecifications)( const FileSpec &file, lldb::DataBufferSP &data_sp, lldb::offset_t data_offset, lldb::offset_t file_offset, diff --git a/lldb/source/Core/PluginManager.cpp b/lldb/source/Core/PluginManager.cpp --- a/lldb/source/Core/PluginManager.cpp +++ b/lldb/source/Core/PluginManager.cpp @@ -724,11 +724,14 @@ ObjectContainerInstance( llvm::StringRef name, llvm::StringRef description, CallbackType create_callback, + ObjectContainerCreateMemoryInstance create_memory_callback, ObjectFileGetModuleSpecifications get_module_specifications) : PluginInstance(name, description, create_callback), + create_memory_callback(create_memory_callback), get_module_specifications(get_module_specifications) {} + ObjectContainerCreateMemoryInstance create_memory_callback; ObjectFileGetModuleSpecifications get_module_specifications; }; typedef PluginInstances ObjectContainerInstances; @@ -741,9 +744,11 @@ bool PluginManager::RegisterPlugin( llvm::StringRef name, llvm::StringRef description, ObjectContainerCreateInstance create_callback, - ObjectFileGetModuleSpecifications get_module_specifications) { + ObjectFileGetModuleSpecifications get_module_specifications, + ObjectContainerCreateMemoryInstance create_memory_callback) { return GetObjectContainerInstances().RegisterPlugin( - name, description, create_callback, get_module_specifications); + name, description, create_callback, create_memory_callback, + get_module_specifications); } bool PluginManager::UnregisterPlugin( @@ -756,6 +761,14 @@ return GetObjectContainerInstances().GetCallbackAtIndex(idx); } +ObjectContainerCreateMemoryInstance +PluginManager::GetObjectContainerCreateMemoryCallbackAtIndex(uint32_t idx) { + const auto &instances = GetObjectContainerInstances().GetInstances(); + if (idx < instances.size()) + return instances[idx].create_memory_callback; + return nullptr; +} + ObjectFileGetModuleSpecifications PluginManager::GetObjectContainerGetModuleSpecificationsCallbackAtIndex( uint32_t idx) { diff --git a/lldb/source/Plugins/ObjectContainer/CMakeLists.txt b/lldb/source/Plugins/ObjectContainer/CMakeLists.txt --- a/lldb/source/Plugins/ObjectContainer/CMakeLists.txt +++ b/lldb/source/Plugins/ObjectContainer/CMakeLists.txt @@ -1,2 +1,3 @@ add_subdirectory(BSD-Archive) add_subdirectory(Universal-Mach-O) +add_subdirectory(Mach-O-Fileset) diff --git a/lldb/source/Plugins/ObjectContainer/Mach-O-Fileset/CMakeLists.txt b/lldb/source/Plugins/ObjectContainer/Mach-O-Fileset/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/lldb/source/Plugins/ObjectContainer/Mach-O-Fileset/CMakeLists.txt @@ -0,0 +1,10 @@ +add_lldb_library(lldbPluginObjectContainerMachOFileset PLUGIN + ObjectContainerMachOFileset.cpp + + LINK_LIBS + lldbCore + lldbHost + lldbSymbol + lldbTarget + lldbUtility + ) diff --git a/lldb/source/Plugins/ObjectContainer/Mach-O-Fileset/ObjectContainerMachOFileset.h b/lldb/source/Plugins/ObjectContainer/Mach-O-Fileset/ObjectContainerMachOFileset.h new file mode 100644 --- /dev/null +++ b/lldb/source/Plugins/ObjectContainer/Mach-O-Fileset/ObjectContainerMachOFileset.h @@ -0,0 +1,95 @@ +//===-- ObjectContainerMachOFileset.h ---------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SOURCE_PLUGINS_OBJECTCONTAINER_MACH_O_FILESET_OBJECTCONTAINERMADCHOFILESET_H +#define LLDB_SOURCE_PLUGINS_OBJECTCONTAINER_MACH_O_FILESET_OBJECTCONTAINERMADCHOFILESET_H + +#include "lldb/Host/SafeMachO.h" +#include "lldb/Symbol/ObjectContainer.h" +#include "lldb/Utility/FileSpec.h" + +namespace lldb_private { + +class ObjectContainerMachOFileset : public lldb_private::ObjectContainer { +public: + ObjectContainerMachOFileset(const lldb::ModuleSP &module_sp, + lldb::DataBufferSP &data_sp, + lldb::offset_t data_offset, + const lldb_private::FileSpec *file, + lldb::offset_t offset, lldb::offset_t length); + + ObjectContainerMachOFileset(const lldb::ModuleSP &module_sp, + lldb::WritableDataBufferSP data_sp, + const lldb::ProcessSP &process_sp, + lldb::addr_t header_addr); + + ~ObjectContainerMachOFileset() override; + + static void Initialize(); + static void Terminate(); + + static llvm::StringRef GetPluginNameStatic() { return "mach-o-fileset"; } + + static llvm::StringRef GetPluginDescriptionStatic() { + return "Mach-O Fileset container reader."; + } + + static lldb_private::ObjectContainer * + CreateInstance(const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp, + lldb::offset_t data_offset, const lldb_private::FileSpec *file, + lldb::offset_t offset, lldb::offset_t length); + + static lldb_private::ObjectContainer *CreateMemoryInstance( + const lldb::ModuleSP &module_sp, lldb::WritableDataBufferSP 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(const lldb_private::DataExtractor &data); + static bool MagicBytesMatch(lldb::DataBufferSP data_sp, + lldb::addr_t data_offset, + lldb::addr_t data_length); + + bool ParseHeader() override; + + size_t GetNumObjects() const override { return m_entries.size(); } + + lldb::ObjectFileSP GetObjectFile(const lldb_private::FileSpec *file) override; + + llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } + + struct Entry { + Entry(uint64_t vmaddr, uint64_t fileoff, std::string id) + : vmaddr(vmaddr), fileoff(fileoff), id(id) {} + uint64_t vmaddr; + uint64_t fileoff; + uint64_t slide; + std::string id; + }; + + Entry *FindEntry(llvm::StringRef id); + +private: + static bool ParseHeader(lldb_private::DataExtractor &data, + const lldb_private::FileSpec &file, + lldb::offset_t file_offset, + std::vector &entries); + + std::vector m_entries; + lldb::ProcessWP m_process_wp; + const lldb::addr_t m_memory_addr; +}; + +} // namespace lldb_private + +#endif // LLDB_SOURCE_PLUGINS_OBJECTCONTAINER_MACH_O_FILESET_OBJECTCONTAINERMADCHOFILESET_H diff --git a/lldb/source/Plugins/ObjectContainer/Mach-O-Fileset/ObjectContainerMachOFileset.cpp b/lldb/source/Plugins/ObjectContainer/Mach-O-Fileset/ObjectContainerMachOFileset.cpp new file mode 100644 --- /dev/null +++ b/lldb/source/Plugins/ObjectContainer/Mach-O-Fileset/ObjectContainerMachOFileset.cpp @@ -0,0 +1,283 @@ +//===-- ObjectContainerMachOFileset.cpp -----------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "ObjectContainerMachOFileset.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Target/Target.h" +#include "lldb/Utility/ArchSpec.h" +#include "lldb/Utility/DataBuffer.h" +#include "lldb/Utility/Stream.h" + +using namespace lldb; +using namespace lldb_private; +using namespace llvm::MachO; + +LLDB_PLUGIN_DEFINE(ObjectContainerMachOFileset) + +void ObjectContainerMachOFileset::Initialize() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), CreateInstance, + GetModuleSpecifications, CreateMemoryInstance); +} + +void ObjectContainerMachOFileset::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); +} + +ObjectContainerMachOFileset::ObjectContainerMachOFileset( + const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp, + lldb::offset_t data_offset, const lldb_private::FileSpec *file, + lldb::offset_t offset, lldb::offset_t length) + : ObjectContainer(module_sp, file, offset, length, data_sp, data_offset), + m_memory_addr(LLDB_INVALID_ADDRESS) {} + +ObjectContainerMachOFileset::ObjectContainerMachOFileset( + const lldb::ModuleSP &module_sp, lldb::WritableDataBufferSP data_sp, + const lldb::ProcessSP &process_sp, lldb::addr_t header_addr) + : ObjectContainer(module_sp, nullptr, 0, 0, data_sp, 0), + m_memory_addr(header_addr) {} + +ObjectContainer *ObjectContainerMachOFileset::CreateInstance( + const lldb::ModuleSP &module_sp, DataBufferSP &data_sp, + lldb::offset_t data_offset, const FileSpec *file, + lldb::offset_t file_offset, lldb::offset_t length) { + if (!data_sp) + return {}; + + DataExtractor data; + data.SetData(data_sp, data_offset, length); + if (!MagicBytesMatch(data)) + return {}; + + auto container_up = std::make_unique( + module_sp, data_sp, data_offset, file, file_offset, length); + if (!container_up->ParseHeader()) + return {}; + + return container_up.release(); +} + +ObjectContainer *ObjectContainerMachOFileset::CreateMemoryInstance( + const lldb::ModuleSP &module_sp, lldb::WritableDataBufferSP data_sp, + const lldb::ProcessSP &process_sp, lldb::addr_t header_addr) { + if (!MagicBytesMatch(data_sp, 0, data_sp->GetByteSize())) + return {}; + + auto container_up = std::make_unique( + module_sp, data_sp, process_sp, header_addr); + if (!container_up->ParseHeader()) + return {}; + + return container_up.release(); +} + +ObjectContainerMachOFileset::~ObjectContainerMachOFileset() = default; + +static uint32_t MachHeaderSizeFromMagic(uint32_t magic) { + switch (magic) { + case MH_MAGIC: + case MH_CIGAM: + return sizeof(struct mach_header); + case MH_MAGIC_64: + case MH_CIGAM_64: + return sizeof(struct mach_header_64); + default: + return 0; + } +} + +static llvm::Optional ParseMachOHeader(DataExtractor &data) { + lldb::offset_t offset = 0; + mach_header header; + header.magic = data.GetU32(&offset); + switch (header.magic) { + case MH_MAGIC: + data.SetByteOrder(endian::InlHostByteOrder()); + data.SetAddressByteSize(4); + break; + case MH_MAGIC_64: + data.SetByteOrder(endian::InlHostByteOrder()); + data.SetAddressByteSize(8); + break; + case MH_CIGAM: + data.SetByteOrder(endian::InlHostByteOrder() == eByteOrderBig + ? eByteOrderLittle + : eByteOrderBig); + data.SetAddressByteSize(4); + break; + case MH_CIGAM_64: + data.SetByteOrder(endian::InlHostByteOrder() == eByteOrderBig + ? eByteOrderLittle + : eByteOrderBig); + data.SetAddressByteSize(8); + break; + default: + return {}; + } + + header.cputype = data.GetU32(&offset); + header.cpusubtype = data.GetU32(&offset); + header.filetype = data.GetU32(&offset); + header.ncmds = data.GetU32(&offset); + header.sizeofcmds = data.GetU32(&offset); + return header; +} + +static bool +ParseFileset(DataExtractor &data, mach_header header, + std::vector &entries) { + lldb::offset_t offset = MachHeaderSizeFromMagic(header.magic); + for (uint32_t i = 0; i < header.ncmds; ++i) { + const lldb::offset_t load_cmd_offset = offset; + load_command lc = {}; + if (data.GetU32(&offset, &lc.cmd, 2) == nullptr) + break; + + if (lc.cmd == LC_FILESET_ENTRY) { + fileset_entry_command entry; + data.CopyData(load_cmd_offset, sizeof(fileset_entry_command), &entry); + lldb::offset_t entry_id_offset = load_cmd_offset + entry.entry_id; + const char *id = data.GetCStr(&entry_id_offset); + entries.emplace_back(entry.vmaddr, entry.fileoff, std::string(id)); + } + offset = load_cmd_offset + lc.cmdsize; + } + + return true; +} + +bool ObjectContainerMachOFileset::ParseHeader( + DataExtractor &data, const lldb_private::FileSpec &file, + lldb::offset_t file_offset, std::vector &entries) { + llvm::Optional header = ParseMachOHeader(data); + + if (!header) + return false; + + const size_t header_size = MachHeaderSizeFromMagic(header->magic); + const size_t header_and_lc_size = header_size + header->sizeofcmds; + + if (data.GetByteSize() < header_and_lc_size) { + DataBufferSP data_sp = + ObjectFile::MapFileData(file, header_and_lc_size, file_offset); + data.SetData(data_sp); + } + + return ParseFileset(data, *header, entries); +} + +bool ObjectContainerMachOFileset::ParseHeader() { + ModuleSP module_sp(GetModule()); + if (!module_sp) + return false; + + std::lock_guard guard(module_sp->GetMutex()); + + llvm::Optional header = ParseMachOHeader(m_data); + if (!header) + return false; + + const size_t header_size = MachHeaderSizeFromMagic(header->magic); + const size_t header_and_lc_size = header_size + header->sizeofcmds; + + if (m_data.GetByteSize() < header_and_lc_size) { + ProcessSP process_sp(m_process_wp.lock()); + DataBufferSP data_sp = + process_sp + ? ObjectFile::ReadMemory(process_sp, m_memory_addr, + header_and_lc_size) + : ObjectFile::MapFileData(m_file, header_and_lc_size, m_offset); + m_data.SetData(data_sp); + } + + return ParseFileset(m_data, *header, m_entries); +} + +size_t ObjectContainerMachOFileset::GetModuleSpecifications( + const lldb_private::FileSpec &file, lldb::DataBufferSP &data_sp, + lldb::offset_t data_offset, lldb::offset_t file_offset, + lldb::offset_t file_size, lldb_private::ModuleSpecList &specs) { + const size_t initial_count = specs.GetSize(); + + DataExtractor data; + data.SetData(data_sp, data_offset, data_sp->GetByteSize()); + + if (MagicBytesMatch(data)) { + std::vector entries; + if (ParseHeader(data, file, file_offset, entries)) { + for (const Entry &entry : entries) { + const lldb::offset_t entry_offset = entry.fileoff + file_offset; + if (ObjectFile::GetModuleSpecifications( + file, entry_offset, file_size - entry_offset, specs)) { + ModuleSpec &spec = specs.GetModuleSpecRefAtIndex(specs.GetSize() - 1); + spec.GetObjectName() = ConstString(entry.id); + } + } + } + } + return specs.GetSize() - initial_count; +} + +bool ObjectContainerMachOFileset::MagicBytesMatch(DataBufferSP data_sp, + lldb::addr_t data_offset, + lldb::addr_t data_length) { + DataExtractor data; + data.SetData(data_sp, data_offset, data_length); + return MagicBytesMatch(data); +} + +bool ObjectContainerMachOFileset::MagicBytesMatch(const DataExtractor &data) { + lldb::offset_t offset = 0; + uint32_t magic = data.GetU32(&offset); + switch (magic) { + case MH_MAGIC: + case MH_CIGAM: + case MH_MAGIC_64: + case MH_CIGAM_64: + break; + default: + return false; + } + offset += 4; // cputype + offset += 4; // cpusubtype + uint32_t filetype = data.GetU32(&offset); + return filetype == MH_FILESET; +} + +ObjectFileSP +ObjectContainerMachOFileset::GetObjectFile(const lldb_private::FileSpec *file) { + ModuleSP module_sp(GetModule()); + if (!module_sp) + return {}; + + ConstString object_name = module_sp->GetObjectName(); + if (!object_name) + return {}; + + Entry *entry = FindEntry(object_name.GetCString()); + if (!entry) + return {}; + + DataBufferSP data_sp; + lldb::offset_t data_offset = 0; + return ObjectFile::FindPlugin(module_sp, file, m_offset + entry->fileoff, + m_data.GetByteSize() - entry->fileoff, data_sp, + data_offset); +} + +ObjectContainerMachOFileset::Entry * +ObjectContainerMachOFileset::FindEntry(llvm::StringRef id) { + for (Entry &entry : m_entries) { + if (entry.id == id) + return &entry; + } + return nullptr; +} diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -941,6 +941,17 @@ data.SetData(data_sp, data_offset, data_length); lldb::offset_t offset = 0; uint32_t magic = data.GetU32(&offset); + + offset += 4; // cputype + offset += 4; // cpusubtype + uint32_t filetype = data.GetU32(&offset); + + // A fileset has a Mach-O header but is not an + // individual file and must be handled via an + // ObjectContainer plugin. + if (filetype == llvm::MachO::MH_FILESET) + return false; + return MachHeaderSizeFromMagic(magic) != 0; } diff --git a/lldb/source/Symbol/CMakeLists.txt b/lldb/source/Symbol/CMakeLists.txt --- a/lldb/source/Symbol/CMakeLists.txt +++ b/lldb/source/Symbol/CMakeLists.txt @@ -22,6 +22,7 @@ LineEntry.cpp LineTable.cpp LocateSymbolFile.cpp + ObjectContainer.cpp ObjectFile.cpp PostfixExpression.cpp Symbol.cpp diff --git a/lldb/source/Symbol/ObjectContainer.cpp b/lldb/source/Symbol/ObjectContainer.cpp new file mode 100644 --- /dev/null +++ b/lldb/source/Symbol/ObjectContainer.cpp @@ -0,0 +1,59 @@ +//===-- ObjectContainer.cpp -----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Symbol/ObjectContainer.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Target/Process.h" +#include "lldb/Utility/Timer.h" + +using namespace lldb; +using namespace lldb_private; + +ObjectContainer::ObjectContainer(const lldb::ModuleSP &module_sp, + const FileSpec *file, + lldb::offset_t file_offset, + lldb::offset_t length, + lldb::DataBufferSP data_sp, + lldb::offset_t data_offset) + : ModuleChild(module_sp), + m_file(), // This file can be different than the module's file spec + m_offset(file_offset), m_length(length) { + if (file) + m_file = *file; + if (data_sp) + m_data.SetData(data_sp, data_offset, length); +} + +ObjectContainerSP ObjectContainer::FindPlugin(const lldb::ModuleSP &module_sp, + const ProcessSP &process_sp, + lldb::addr_t header_addr, + WritableDataBufferSP data_sp) { + if (!module_sp) + return {}; + + LLDB_SCOPED_TIMERF("ObjectContainer::FindPlugin (module = " + "%s, process = %p, header_addr = " + "0x%" PRIx64 ")", + module_sp->GetFileSpec().GetPath().c_str(), + static_cast(process_sp.get()), header_addr); + + ObjectContainerCreateMemoryInstance create_callback; + for (size_t idx = 0; + (create_callback = + PluginManager::GetObjectContainerCreateMemoryCallbackAtIndex( + idx)) != nullptr; + ++idx) { + ObjectContainerSP object_container_sp( + create_callback(module_sp, data_sp, process_sp, header_addr)); + if (object_container_sp) + return object_container_sp; + } + + return {}; +}