summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/ObjectFile
diff options
context:
space:
mode:
authorAaron Smith <aaron.smith@microsoft.com>2018-12-06 21:36:39 +0000
committerAaron Smith <aaron.smith@microsoft.com>2018-12-06 21:36:39 +0000
commit037ed1befd3ae2677cb09af72214420e80344f0a (patch)
tree11fa0dbf9aca81c081071db809437055fe6ee5d1 /lldb/source/Plugins/ObjectFile
parent488214fe847885b081cbcbee361d8f52c600d85e (diff)
downloadbcm5719-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.cpp137
-rw-r--r--lldb/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h11
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 &sect_name, const section_header_t &sect);
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_
OpenPOWER on IntegriCloud