diff options
author | Aaron Smith <aaron.smith@microsoft.com> | 2018-12-06 21:36:39 +0000 |
---|---|---|
committer | Aaron Smith <aaron.smith@microsoft.com> | 2018-12-06 21:36:39 +0000 |
commit | 037ed1befd3ae2677cb09af72214420e80344f0a (patch) | |
tree | 11fa0dbf9aca81c081071db809437055fe6ee5d1 /lldb/source/Plugins/ObjectFile | |
parent | 488214fe847885b081cbcbee361d8f52c600d85e (diff) | |
download | bcm5719-llvm-037ed1befd3ae2677cb09af72214420e80344f0a.tar.gz bcm5719-llvm-037ed1befd3ae2677cb09af72214420e80344f0a.zip |
[pecoff] Implement ObjectFilePECOFF::GetDependedModules()
Summary:
This parses entries in pecoff import tables for imported DLLs and
is intended as the first step to allow LLDB to load a PE's shared
modules when creating a target on the LLDB console.
Reviewers: rnk, zturner, aleksandr.urakov, lldb-commits, labath, asmith
Reviewed By: labath, asmith
Subscribers: labath, lemo, clayborg, Hui, mgorny, mgrang, teemperor
Differential Revision: https://reviews.llvm.org/D53094
llvm-svn: 348527
Diffstat (limited to 'lldb/source/Plugins/ObjectFile')
-rw-r--r-- | lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp | 137 | ||||
-rw-r--r-- | lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h | 11 |
2 files changed, 141 insertions, 7 deletions
diff --git a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp index e792165734f..1883abe054c 100644 --- a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp +++ b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp @@ -23,11 +23,14 @@ #include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/DataBufferHeap.h" #include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/Log.h" #include "lldb/Utility/StreamString.h" #include "lldb/Utility/Timer.h" #include "lldb/Utility/UUID.h" #include "llvm/BinaryFormat/COFF.h" +#include "llvm/Object/COFFImportFile.h" +#include "llvm/Support/Error.h" #include "llvm/Support/MemoryBuffer.h" #define IMAGE_DOS_SIGNATURE 0x5A4D // MZ @@ -86,6 +89,10 @@ ObjectFile *ObjectFilePECOFF::CreateInstance(const lldb::ModuleSP &module_sp, if (!objfile_ap || !objfile_ap->ParseHeader()) return nullptr; + // Cache coff binary. + if (!objfile_ap->CreateBinary()) + return nullptr; + return objfile_ap.release(); } @@ -131,9 +138,7 @@ size_t ObjectFilePECOFF::GetModuleSpecifications( specs.Append(ModuleSpec(file, spec)); spec.SetTriple("i686-pc-windows"); specs.Append(ModuleSpec(file, spec)); - } - else if (coff_header.machine == MachineArmNt) - { + } else if (coff_header.machine == MachineArmNt) { spec.SetTriple("arm-pc-windows"); specs.Append(ModuleSpec(file, spec)); } @@ -168,6 +173,40 @@ lldb::SymbolType ObjectFilePECOFF::MapSymbolType(uint16_t coff_symbol_type) { return lldb::eSymbolTypeInvalid; } +bool ObjectFilePECOFF::CreateBinary() { + if (m_owningbin) + return true; + + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); + + auto binary = llvm::object::createBinary(m_file.GetPath()); + if (!binary) { + if (log) + log->Printf("ObjectFilePECOFF::CreateBinary() - failed to create binary " + "for file (%s): %s", + m_file ? m_file.GetPath().c_str() : "<NULL>", + errorToErrorCode(binary.takeError()).message().c_str()); + return false; + } + + // Make sure we only handle COFF format. + if (!binary->getBinary()->isCOFF() && + !binary->getBinary()->isCOFFImportFile()) + return false; + + m_owningbin = OWNBINType(std::move(*binary)); + if (log) + log->Printf("%p ObjectFilePECOFF::CreateBinary() module = %p (%s), file = " + "%s, binary = %p (Bin = %p)", + static_cast<void *>(this), + static_cast<void *>(GetModule().get()), + GetModule()->GetSpecificationDescription().c_str(), + m_file ? m_file.GetPath().c_str() : "<NULL>", + static_cast<void *>(m_owningbin.getPointer()), + static_cast<void *>(m_owningbin->getBinary())); + return true; +} + ObjectFilePECOFF::ObjectFilePECOFF(const lldb::ModuleSP &module_sp, DataBufferSP &data_sp, lldb::offset_t data_offset, @@ -176,7 +215,7 @@ ObjectFilePECOFF::ObjectFilePECOFF(const lldb::ModuleSP &module_sp, lldb::offset_t length) : ObjectFile(module_sp, file, file_offset, length, data_sp, data_offset), m_dos_header(), m_coff_header(), m_coff_header_opt(), m_sect_headers(), - m_entry_point_address() { + m_entry_point_address(), m_deps_filespec(), m_owningbin() { ::memset(&m_dos_header, 0, sizeof(m_dos_header)); ::memset(&m_coff_header, 0, sizeof(m_coff_header)); ::memset(&m_coff_header_opt, 0, sizeof(m_coff_header_opt)); @@ -188,7 +227,7 @@ ObjectFilePECOFF::ObjectFilePECOFF(const lldb::ModuleSP &module_sp, addr_t header_addr) : ObjectFile(module_sp, process_sp, header_addr, header_data_sp), m_dos_header(), m_coff_header(), m_coff_header_opt(), m_sect_headers(), - m_entry_point_address() { + m_entry_point_address(), m_deps_filespec(), m_owningbin() { ::memset(&m_dos_header, 0, sizeof(m_dos_header)); ::memset(&m_coff_header, 0, sizeof(m_coff_header)); ::memset(&m_coff_header_opt, 0, sizeof(m_coff_header_opt)); @@ -431,7 +470,7 @@ bool ObjectFilePECOFF::ParseCOFFOptionalHeader(lldb::offset_t *offset_ptr) { DataExtractor ObjectFilePECOFF::ReadImageData(uint32_t offset, size_t size) { if (m_file) { - // A bit of a hack, but we intend to write to this buffer, so we can't + // A bit of a hack, but we intend to write to this buffer, so we can't // mmap it. auto buffer_sp = MapFileData(m_file, size, offset); return DataExtractor(buffer_sp, GetByteOrder(), GetAddressByteSize()); @@ -805,8 +844,73 @@ void ObjectFilePECOFF::CreateSections(SectionList &unified_section_list) { bool ObjectFilePECOFF::GetUUID(UUID *uuid) { return false; } +uint32_t ObjectFilePECOFF::ParseDependentModules() { + ModuleSP module_sp(GetModule()); + if (!module_sp) + return 0; + + std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); + if (m_deps_filespec) + return m_deps_filespec->GetSize(); + + // Cache coff binary if it is not done yet. + if (!CreateBinary()) + return 0; + + Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); + if (log) + log->Printf("%p ObjectFilePECOFF::ParseDependentModules() module = %p " + "(%s), binary = %p (Bin = %p)", + static_cast<void *>(this), static_cast<void *>(module_sp.get()), + module_sp->GetSpecificationDescription().c_str(), + static_cast<void *>(m_owningbin.getPointer()), + m_owningbin ? static_cast<void *>(m_owningbin->getBinary()) + : nullptr); + + auto COFFObj = + llvm::dyn_cast<llvm::object::COFFObjectFile>(m_owningbin->getBinary()); + if (!COFFObj) + return 0; + + m_deps_filespec = FileSpecList(); + + for (const auto &entry : COFFObj->import_directories()) { + llvm::StringRef dll_name; + auto ec = entry.getName(dll_name); + // Report a bogus entry. + if (ec != std::error_code()) { + if (log) + log->Printf("ObjectFilePECOFF::ParseDependentModules() - failed to get " + "import directory entry name: %s", + ec.message().c_str()); + continue; + } + + // At this moment we only have the base name of the DLL. The full path can + // only be seen after the dynamic loading. Our best guess is Try to get it + // with the help of the object file's directory. + llvm::SmallString<MAX_PATH> dll_fullpath; + FileSpec dll_specs(dll_name); + dll_specs.GetDirectory().SetString(m_file.GetDirectory().GetCString()); + + if (!llvm::sys::fs::real_path(dll_specs.GetPath(), dll_fullpath)) + m_deps_filespec->Append(FileSpec(dll_fullpath)); + else { + // Known DLLs or DLL not found in the object file directory. + m_deps_filespec->Append(FileSpec(dll_name)); + } + } + return m_deps_filespec->GetSize(); +} + uint32_t ObjectFilePECOFF::GetDependentModules(FileSpecList &files) { - return 0; + auto num_modules = ParseDependentModules(); + auto original_size = files.GetSize(); + + for (unsigned i = 0; i < num_modules; ++i) + files.AppendIfUnique(m_deps_filespec->GetFileSpecAtIndex(i)); + + return files.GetSize() - original_size; } lldb_private::Address ObjectFilePECOFF::GetEntryPointAddress() { @@ -863,6 +967,9 @@ void ObjectFilePECOFF::Dump(Stream *s) { s->EOL(); DumpSectionHeaders(s); s->EOL(); + + DumpDependentModules(s); + s->EOL(); } } @@ -1010,6 +1117,22 @@ void ObjectFilePECOFF::DumpSectionHeaders(Stream *s) { } } +//---------------------------------------------------------------------- +// DumpDependentModules +// +// Dump all of the dependent modules to the specified output stream +//---------------------------------------------------------------------- +void ObjectFilePECOFF::DumpDependentModules(lldb_private::Stream *s) { + auto num_modules = ParseDependentModules(); + if (num_modules > 0) { + s->PutCString("Dependent Modules\n"); + for (unsigned i = 0; i < num_modules; ++i) { + auto spec = m_deps_filespec->GetFileSpecAtIndex(i); + s->Printf(" %s\n", spec.GetFilename().GetCString()); + } + } +} + bool ObjectFilePECOFF::IsWindowsSubsystem() { switch (m_coff_header_opt.subsystem) { case llvm::COFF::IMAGE_SUBSYSTEM_NATIVE: diff --git a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h index ec2487b4533..f93b83144b3 100644 --- a/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h +++ b/lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h @@ -13,6 +13,7 @@ #include <vector> #include "lldb/Symbol/ObjectFile.h" +#include "llvm/Object/Binary.h" class ObjectFilePECOFF : public lldb_private::ObjectFile { public: @@ -257,6 +258,8 @@ protected: bool ParseCOFFOptionalHeader(lldb::offset_t *offset_ptr); bool ParseSectionHeaders(uint32_t offset); + uint32_t ParseDependentModules(); + static void DumpDOSHeader(lldb_private::Stream *s, const dos_header_t &header); static void DumpCOFFHeader(lldb_private::Stream *s, @@ -265,6 +268,8 @@ protected: const coff_opt_header_t &header); void DumpSectionHeaders(lldb_private::Stream *s); void DumpSectionHeader(lldb_private::Stream *s, const section_header_t &sh); + void DumpDependentModules(lldb_private::Stream *s); + bool GetSectionName(std::string §_name, const section_header_t §); typedef std::vector<section_header_t> SectionHeaderColl; @@ -272,12 +277,18 @@ protected: typedef SectionHeaderColl::const_iterator SectionHeaderCollConstIter; private: + bool CreateBinary(); + +private: dos_header_t m_dos_header; coff_header_t m_coff_header; coff_opt_header_t m_coff_header_opt; SectionHeaderColl m_sect_headers; lldb::addr_t m_image_base; lldb_private::Address m_entry_point_address; + llvm::Optional<lldb_private::FileSpecList> m_deps_filespec; + typedef llvm::object::OwningBinary<llvm::object::Binary> OWNBINType; + llvm::Optional<OWNBINType> m_owningbin; }; #endif // liblldb_ObjectFilePECOFF_h_ |