summaryrefslogtreecommitdiff
path: root/source/Plugins/ObjectFile
diff options
context:
space:
mode:
Diffstat (limited to 'source/Plugins/ObjectFile')
-rw-r--r--source/Plugins/ObjectFile/Breakpad/CMakeLists.txt11
-rw-r--r--source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp315
-rw-r--r--source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h109
-rw-r--r--source/Plugins/ObjectFile/CMakeLists.txt3
-rw-r--r--source/Plugins/ObjectFile/ELF/ELFHeader.cpp29
-rw-r--r--source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp735
-rw-r--r--source/Plugins/ObjectFile/ELF/ObjectFileELF.h28
-rw-r--r--source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp16
-rw-r--r--source/Plugins/ObjectFile/JIT/ObjectFileJIT.h8
-rw-r--r--source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp435
-rw-r--r--source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h21
-rw-r--r--source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp441
-rw-r--r--source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h19
-rw-r--r--source/Plugins/ObjectFile/PECOFF/WindowsMiniDump.cpp2
14 files changed, 1455 insertions, 717 deletions
diff --git a/source/Plugins/ObjectFile/Breakpad/CMakeLists.txt b/source/Plugins/ObjectFile/Breakpad/CMakeLists.txt
new file mode 100644
index 000000000000..2f51b2c8719a
--- /dev/null
+++ b/source/Plugins/ObjectFile/Breakpad/CMakeLists.txt
@@ -0,0 +1,11 @@
+add_lldb_library(lldbPluginObjectFileBreakpad PLUGIN
+ ObjectFileBreakpad.cpp
+
+ LINK_LIBS
+ lldbCore
+ lldbHost
+ lldbSymbol
+ lldbUtility
+ LINK_COMPONENTS
+ Support
+ )
diff --git a/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp b/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp
new file mode 100644
index 000000000000..917025030ada
--- /dev/null
+++ b/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.cpp
@@ -0,0 +1,315 @@
+//===-- ObjectFileBreakpad.cpp -------------------------------- -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Utility/DataBuffer.h"
+#include "llvm/ADT/StringExtras.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::breakpad;
+
+namespace {
+struct Header {
+ ArchSpec arch;
+ UUID uuid;
+ static llvm::Optional<Header> parse(llvm::StringRef text);
+};
+
+enum class Token { Unknown, Module, Info, File, Func, Public, Stack };
+} // namespace
+
+static Token toToken(llvm::StringRef str) {
+ return llvm::StringSwitch<Token>(str)
+ .Case("MODULE", Token::Module)
+ .Case("INFO", Token::Info)
+ .Case("FILE", Token::File)
+ .Case("FUNC", Token::Func)
+ .Case("PUBLIC", Token::Public)
+ .Case("STACK", Token::Stack)
+ .Default(Token::Unknown);
+}
+
+static llvm::StringRef toString(Token t) {
+ switch (t) {
+ case Token::Unknown:
+ return "";
+ case Token::Module:
+ return "MODULE";
+ case Token::Info:
+ return "INFO";
+ case Token::File:
+ return "FILE";
+ case Token::Func:
+ return "FUNC";
+ case Token::Public:
+ return "PUBLIC";
+ case Token::Stack:
+ return "STACK";
+ }
+ llvm_unreachable("Unknown token!");
+}
+
+static llvm::Triple::OSType toOS(llvm::StringRef str) {
+ using llvm::Triple;
+ return llvm::StringSwitch<Triple::OSType>(str)
+ .Case("Linux", Triple::Linux)
+ .Case("mac", Triple::MacOSX)
+ .Case("windows", Triple::Win32)
+ .Default(Triple::UnknownOS);
+}
+
+static llvm::Triple::ArchType toArch(llvm::StringRef str) {
+ using llvm::Triple;
+ return llvm::StringSwitch<Triple::ArchType>(str)
+ .Case("arm", Triple::arm)
+ .Case("arm64", Triple::aarch64)
+ .Case("mips", Triple::mips)
+ .Case("ppc", Triple::ppc)
+ .Case("ppc64", Triple::ppc64)
+ .Case("s390", Triple::systemz)
+ .Case("sparc", Triple::sparc)
+ .Case("sparcv9", Triple::sparcv9)
+ .Case("x86", Triple::x86)
+ .Case("x86_64", Triple::x86_64)
+ .Default(Triple::UnknownArch);
+}
+
+static llvm::StringRef consume_front(llvm::StringRef &str, size_t n) {
+ llvm::StringRef result = str.take_front(n);
+ str = str.drop_front(n);
+ return result;
+}
+
+static UUID parseModuleId(llvm::Triple::OSType os, llvm::StringRef str) {
+ struct uuid_data {
+ llvm::support::ulittle32_t uuid1;
+ llvm::support::ulittle16_t uuid2[2];
+ uint8_t uuid3[8];
+ llvm::support::ulittle32_t age;
+ } data;
+ static_assert(sizeof(data) == 20, "");
+ // The textual module id encoding should be between 33 and 40 bytes long,
+ // depending on the size of the age field, which is of variable length.
+ // The first three chunks of the id are encoded in big endian, so we need to
+ // byte-swap those.
+ if (str.size() < 33 || str.size() > 40)
+ return UUID();
+ uint32_t t;
+ if (to_integer(consume_front(str, 8), t, 16))
+ data.uuid1 = t;
+ else
+ return UUID();
+ for (int i = 0; i < 2; ++i) {
+ if (to_integer(consume_front(str, 4), t, 16))
+ data.uuid2[i] = t;
+ else
+ return UUID();
+ }
+ for (int i = 0; i < 8; ++i) {
+ if (!to_integer(consume_front(str, 2), data.uuid3[i], 16))
+ return UUID();
+ }
+ if (to_integer(str, t, 16))
+ data.age = t;
+ else
+ return UUID();
+
+ // On non-windows, the age field should always be zero, so we don't include to
+ // match the native uuid format of these platforms.
+ return UUID::fromData(&data, os == llvm::Triple::Win32 ? 20 : 16);
+}
+
+llvm::Optional<Header> Header::parse(llvm::StringRef text) {
+ // A valid module should start with something like:
+ // MODULE Linux x86_64 E5894855C35DCCCCCCCCCCCCCCCCCCCC0 a.out
+ // optionally followed by
+ // INFO CODE_ID 554889E55DC3CCCCCCCCCCCCCCCCCCCC [a.exe]
+ llvm::StringRef token, line;
+ std::tie(line, text) = text.split('\n');
+ std::tie(token, line) = getToken(line);
+ if (toToken(token) != Token::Module)
+ return llvm::None;
+
+ std::tie(token, line) = getToken(line);
+ llvm::Triple triple;
+ triple.setOS(toOS(token));
+ if (triple.getOS() == llvm::Triple::UnknownOS)
+ return llvm::None;
+
+ std::tie(token, line) = getToken(line);
+ triple.setArch(toArch(token));
+ if (triple.getArch() == llvm::Triple::UnknownArch)
+ return llvm::None;
+
+ llvm::StringRef module_id;
+ std::tie(module_id, line) = getToken(line);
+
+ std::tie(line, text) = text.split('\n');
+ std::tie(token, line) = getToken(line);
+ if (token == "INFO") {
+ std::tie(token, line) = getToken(line);
+ if (token != "CODE_ID")
+ return llvm::None;
+
+ std::tie(token, line) = getToken(line);
+ // If we don't have any text following the code id (e.g. on linux), we
+ // should use the module id as UUID. Otherwise, we revert back to the module
+ // id.
+ if (line.trim().empty()) {
+ UUID uuid;
+ if (uuid.SetFromStringRef(token, token.size() / 2) != token.size())
+ return llvm::None;
+
+ return Header{ArchSpec(triple), uuid};
+ }
+ }
+
+ // We reach here if we don't have a INFO CODE_ID section, or we chose not to
+ // use it. In either case, we need to properly decode the module id, whose
+ // fields are encoded in big-endian.
+ UUID uuid = parseModuleId(triple.getOS(), module_id);
+ if (!uuid)
+ return llvm::None;
+
+ return Header{ArchSpec(triple), uuid};
+}
+
+void ObjectFileBreakpad::Initialize() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(), CreateInstance,
+ CreateMemoryInstance, GetModuleSpecifications);
+}
+
+void ObjectFileBreakpad::Terminate() {
+ PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+ConstString ObjectFileBreakpad::GetPluginNameStatic() {
+ static ConstString g_name("breakpad");
+ return g_name;
+}
+
+ObjectFile *ObjectFileBreakpad::CreateInstance(
+ const ModuleSP &module_sp, DataBufferSP &data_sp, offset_t data_offset,
+ const FileSpec *file, offset_t file_offset, offset_t length) {
+ if (!data_sp) {
+ data_sp = MapFileData(*file, length, file_offset);
+ if (!data_sp)
+ return nullptr;
+ data_offset = 0;
+ }
+ auto text = toStringRef(data_sp->GetData());
+ llvm::Optional<Header> header = Header::parse(text);
+ if (!header)
+ return nullptr;
+
+ // Update the data to contain the entire file if it doesn't already
+ if (data_sp->GetByteSize() < length) {
+ data_sp = MapFileData(*file, length, file_offset);
+ if (!data_sp)
+ return nullptr;
+ data_offset = 0;
+ }
+
+ return new ObjectFileBreakpad(module_sp, data_sp, data_offset, file,
+ file_offset, length, std::move(header->arch),
+ std::move(header->uuid));
+}
+
+ObjectFile *ObjectFileBreakpad::CreateMemoryInstance(
+ const ModuleSP &module_sp, DataBufferSP &data_sp,
+ const ProcessSP &process_sp, addr_t header_addr) {
+ return nullptr;
+}
+
+size_t ObjectFileBreakpad::GetModuleSpecifications(
+ const FileSpec &file, DataBufferSP &data_sp, offset_t data_offset,
+ offset_t file_offset, offset_t length, ModuleSpecList &specs) {
+ auto text = toStringRef(data_sp->GetData());
+ llvm::Optional<Header> header = Header::parse(text);
+ if (!header)
+ return 0;
+ ModuleSpec spec(file, std::move(header->arch));
+ spec.GetUUID() = std::move(header->uuid);
+ specs.Append(spec);
+ return 1;
+}
+
+ObjectFileBreakpad::ObjectFileBreakpad(const ModuleSP &module_sp,
+ DataBufferSP &data_sp,
+ offset_t data_offset,
+ const FileSpec *file, offset_t offset,
+ offset_t length, ArchSpec arch,
+ UUID uuid)
+ : ObjectFile(module_sp, file, offset, length, data_sp, data_offset),
+ m_arch(std::move(arch)), m_uuid(std::move(uuid)) {}
+
+bool ObjectFileBreakpad::ParseHeader() {
+ // We already parsed the header during initialization.
+ return true;
+}
+
+Symtab *ObjectFileBreakpad::GetSymtab() {
+ // TODO
+ return nullptr;
+}
+
+bool ObjectFileBreakpad::GetUUID(UUID *uuid) {
+ *uuid = m_uuid;
+ return true;
+}
+
+void ObjectFileBreakpad::CreateSections(SectionList &unified_section_list) {
+ if (m_sections_ap)
+ return;
+ m_sections_ap = llvm::make_unique<SectionList>();
+
+ Token current_section = Token::Unknown;
+ offset_t section_start;
+ llvm::StringRef text = toStringRef(m_data.GetData());
+ uint32_t next_section_id = 1;
+ auto maybe_add_section = [&](const uint8_t *end_ptr) {
+ if (current_section == Token::Unknown)
+ return; // We have been called before parsing the first line.
+
+ offset_t end_offset = end_ptr - m_data.GetDataStart();
+ auto section_sp = std::make_shared<Section>(
+ GetModule(), this, next_section_id++,
+ ConstString(toString(current_section)), eSectionTypeOther,
+ /*file_vm_addr*/ 0, /*vm_size*/ 0, section_start,
+ end_offset - section_start, /*log2align*/ 0, /*flags*/ 0);
+ m_sections_ap->AddSection(section_sp);
+ unified_section_list.AddSection(section_sp);
+ };
+ while (!text.empty()) {
+ llvm::StringRef line;
+ std::tie(line, text) = text.split('\n');
+
+ Token token = toToken(getToken(line).first);
+ if (token == Token::Unknown) {
+ // We assume this is a line record, which logically belongs to the Func
+ // section. Errors will be handled when parsing the Func section.
+ token = Token::Func;
+ }
+ if (token == current_section)
+ continue;
+
+ // Changing sections, finish off the previous one, if there was any.
+ maybe_add_section(line.bytes_begin());
+ // And start a new one.
+ current_section = token;
+ section_start = line.bytes_begin() - m_data.GetDataStart();
+ }
+ // Finally, add the last section.
+ maybe_add_section(m_data.GetDataEnd());
+}
diff --git a/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h b/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h
new file mode 100644
index 000000000000..ba2a3ad30e5f
--- /dev/null
+++ b/source/Plugins/ObjectFile/Breakpad/ObjectFileBreakpad.h
@@ -0,0 +1,109 @@
+//===-- ObjectFileBreakpad.h ---------------------------------- -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_PLUGINS_OBJECTFILE_BREAKPAD_OBJECTFILEBREAKPAD_H
+#define LLDB_PLUGINS_OBJECTFILE_BREAKPAD_OBJECTFILEBREAKPAD_H
+
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Utility/ArchSpec.h"
+#include "llvm/ADT/Triple.h"
+
+namespace lldb_private {
+namespace breakpad {
+
+class ObjectFileBreakpad : public ObjectFile {
+public:
+ //------------------------------------------------------------------
+ // Static Functions
+ //------------------------------------------------------------------
+ static void Initialize();
+ static void Terminate();
+
+ static ConstString GetPluginNameStatic();
+ static const char *GetPluginDescriptionStatic() {
+ return "Breakpad object file reader.";
+ }
+
+ static ObjectFile *
+ CreateInstance(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);
+
+ static ObjectFile *CreateMemoryInstance(const lldb::ModuleSP &module_sp,
+ lldb::DataBufferSP &data_sp,
+ const lldb::ProcessSP &process_sp,
+ lldb::addr_t header_addr);
+
+ static size_t GetModuleSpecifications(const FileSpec &file,
+ lldb::DataBufferSP &data_sp,
+ lldb::offset_t data_offset,
+ lldb::offset_t file_offset,
+ lldb::offset_t length,
+ ModuleSpecList &specs);
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ ConstString GetPluginName() override { return GetPluginNameStatic(); }
+
+ uint32_t GetPluginVersion() override { return 1; }
+
+ //------------------------------------------------------------------
+ // ObjectFile Protocol.
+ //------------------------------------------------------------------
+
+ bool ParseHeader() override;
+
+ lldb::ByteOrder GetByteOrder() const override {
+ return m_arch.GetByteOrder();
+ }
+
+ bool IsExecutable() const override { return false; }
+
+ uint32_t GetAddressByteSize() const override {
+ return m_arch.GetAddressByteSize();
+ }
+
+ AddressClass GetAddressClass(lldb::addr_t file_addr) override {
+ return AddressClass::eInvalid;
+ }
+
+ Symtab *GetSymtab() override;
+
+ bool IsStripped() override { return false; }
+
+ void CreateSections(SectionList &unified_section_list) override;
+
+ void Dump(Stream *s) override {}
+
+ ArchSpec GetArchitecture() override { return m_arch; }
+
+ bool GetUUID(UUID *uuid) override;
+
+ FileSpecList GetDebugSymbolFilePaths() override { return FileSpecList(); }
+
+ uint32_t GetDependentModules(FileSpecList &files) override { return 0; }
+
+ Type CalculateType() override { return eTypeDebugInfo; }
+
+ Strata CalculateStrata() override { return eStrataUser; }
+
+private:
+ ArchSpec m_arch;
+ UUID m_uuid;
+
+ ObjectFileBreakpad(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, ArchSpec arch, UUID uuid);
+};
+
+} // namespace breakpad
+} // namespace lldb_private
+#endif // LLDB_PLUGINS_OBJECTFILE_BREAKPAD_OBJECTFILEBREAKPAD_H
diff --git a/source/Plugins/ObjectFile/CMakeLists.txt b/source/Plugins/ObjectFile/CMakeLists.txt
index 06aa01c4f004..4edd667b9723 100644
--- a/source/Plugins/ObjectFile/CMakeLists.txt
+++ b/source/Plugins/ObjectFile/CMakeLists.txt
@@ -1,4 +1,5 @@
+add_subdirectory(Breakpad)
add_subdirectory(ELF)
add_subdirectory(Mach-O)
add_subdirectory(PECOFF)
-add_subdirectory(JIT) \ No newline at end of file
+add_subdirectory(JIT)
diff --git a/source/Plugins/ObjectFile/ELF/ELFHeader.cpp b/source/Plugins/ObjectFile/ELF/ELFHeader.cpp
index 16cbb6e5753b..3d4735286bf2 100644
--- a/source/Plugins/ObjectFile/ELF/ELFHeader.cpp
+++ b/source/Plugins/ObjectFile/ELF/ELFHeader.cpp
@@ -38,7 +38,7 @@ static bool GetMaxU64(const lldb_private::DataExtractor &data,
lldb::offset_t saved_offset = *offset;
for (uint32_t i = 0; i < count; ++i, ++value) {
- if (GetMaxU64(data, offset, value, byte_size) == false) {
+ if (!GetMaxU64(data, offset, value, byte_size)) {
*offset = saved_offset;
return false;
}
@@ -60,7 +60,7 @@ static bool GetMaxS64(const lldb_private::DataExtractor &data,
lldb::offset_t saved_offset = *offset;
for (uint32_t i = 0; i < count; ++i, ++value) {
- if (GetMaxS64(data, offset, value, byte_size) == false) {
+ if (!GetMaxS64(data, offset, value, byte_size)) {
*offset = saved_offset;
return false;
}
@@ -133,7 +133,7 @@ bool ELFHeader::Parse(lldb_private::DataExtractor &data,
return false;
// Read e_entry, e_phoff and e_shoff.
- if (GetMaxU64(data, offset, &e_entry, byte_size, 3) == false)
+ if (!GetMaxU64(data, offset, &e_entry, byte_size, 3))
return false;
// Read e_flags.
@@ -232,11 +232,11 @@ bool ELFSectionHeader::Parse(const lldb_private::DataExtractor &data,
return false;
// Read sh_flags.
- if (GetMaxU64(data, offset, &sh_flags, byte_size) == false)
+ if (!GetMaxU64(data, offset, &sh_flags, byte_size))
return false;
// Read sh_addr, sh_off and sh_size.
- if (GetMaxU64(data, offset, &sh_addr, byte_size, 3) == false)
+ if (!GetMaxU64(data, offset, &sh_addr, byte_size, 3))
return false;
// Read sh_link and sh_info.
@@ -244,7 +244,7 @@ bool ELFSectionHeader::Parse(const lldb_private::DataExtractor &data,
return false;
// Read sh_addralign and sh_entsize.
- if (GetMaxU64(data, offset, &sh_addralign, byte_size, 2) == false)
+ if (!GetMaxU64(data, offset, &sh_addralign, byte_size, 2))
return false;
return true;
@@ -332,7 +332,7 @@ bool ELFSymbol::Parse(const lldb_private::DataExtractor &data,
if (parsing_32) {
// Read st_value and st_size.
- if (GetMaxU64(data, offset, &st_value, byte_size, 2) == false)
+ if (!GetMaxU64(data, offset, &st_value, byte_size, 2))
return false;
// Read st_info and st_other.
@@ -376,7 +376,7 @@ bool ELFProgramHeader::Parse(const lldb_private::DataExtractor &data,
if (parsing_32) {
// Read p_offset, p_vaddr, p_paddr, p_filesz and p_memsz.
- if (GetMaxU64(data, offset, &p_offset, byte_size, 5) == false)
+ if (!GetMaxU64(data, offset, &p_offset, byte_size, 5))
return false;
// Read p_flags.
@@ -384,7 +384,7 @@ bool ELFProgramHeader::Parse(const lldb_private::DataExtractor &data,
return false;
// Read p_align.
- if (GetMaxU64(data, offset, &p_align, byte_size) == false)
+ if (!GetMaxU64(data, offset, &p_align, byte_size))
return false;
} else {
// Read p_flags.
@@ -392,7 +392,7 @@ bool ELFProgramHeader::Parse(const lldb_private::DataExtractor &data,
return false;
// Read p_offset, p_vaddr, p_paddr, p_filesz, p_memsz and p_align.
- if (GetMaxU64(data, offset, &p_offset, byte_size, 6) == false)
+ if (!GetMaxU64(data, offset, &p_offset, byte_size, 6))
return false;
}
@@ -420,10 +420,7 @@ bool ELFRel::Parse(const lldb_private::DataExtractor &data,
const unsigned byte_size = data.GetAddressByteSize();
// Read r_offset and r_info.
- if (GetMaxU64(data, offset, &r_offset, byte_size, 2) == false)
- return false;
-
- return true;
+ return GetMaxU64(data, offset, &r_offset, byte_size, 2) != false;
}
//------------------------------------------------------------------------------
@@ -436,11 +433,11 @@ bool ELFRela::Parse(const lldb_private::DataExtractor &data,
const unsigned byte_size = data.GetAddressByteSize();
// Read r_offset and r_info.
- if (GetMaxU64(data, offset, &r_offset, byte_size, 2) == false)
+ if (!GetMaxU64(data, offset, &r_offset, byte_size, 2))
return false;
// Read r_addend;
- if (GetMaxS64(data, offset, &r_addend, byte_size) == false)
+ if (!GetMaxS64(data, offset, &r_addend, byte_size))
return false;
return true;
diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 8701908378f1..9a6563afa0a0 100644
--- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -17,7 +17,9 @@
#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"
+#include "lldb/Host/FileSystem.h"
#include "lldb/Symbol/DWARFCallFrameInfo.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Target/SectionLoadList.h"
@@ -29,6 +31,7 @@
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/Timer.h"
+#include "llvm/ADT/IntervalMap.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Object/Decompressor.h"
@@ -235,6 +238,8 @@ unsigned ELFRelocation::RelocAddend64(const ELFRelocation &rel) {
} // end anonymous namespace
+static user_id_t SegmentID(size_t PHdrIndex) { return ~PHdrIndex; }
+
bool ELFNote::Parse(const DataExtractor &data, lldb::offset_t *offset) {
// Read all fields.
if (data.GetU32(offset, &n_namesz, 3) == NULL)
@@ -433,9 +438,8 @@ ObjectFile *ObjectFileELF::CreateInstance(const lldb::ModuleSP &module_sp,
if (address_size == 4 || address_size == 8) {
std::unique_ptr<ObjectFileELF> objfile_ap(new ObjectFileELF(
module_sp, data_sp, data_offset, file, file_offset, length));
- ArchSpec spec;
- if (objfile_ap->GetArchitecture(spec) &&
- objfile_ap->SetModulesArchitecture(spec))
+ ArchSpec spec = objfile_ap->GetArchitecture();
+ if (spec && objfile_ap->SetModulesArchitecture(spec))
return objfile_ap.release();
}
@@ -452,9 +456,8 @@ ObjectFile *ObjectFileELF::CreateMemoryInstance(
if (address_size == 4 || address_size == 8) {
std::unique_ptr<ObjectFileELF> objfile_ap(
new ObjectFileELF(module_sp, data_sp, process_sp, header_addr));
- ArchSpec spec;
- if (objfile_ap->GetArchitecture(spec) &&
- objfile_ap->SetModulesArchitecture(spec))
+ ArchSpec spec = objfile_ap->GetArchitecture();
+ if (spec && objfile_ap->SetModulesArchitecture(spec))
return objfile_ap.release();
}
}
@@ -538,14 +541,13 @@ static uint32_t calc_gnu_debuglink_crc32(const void *buf, size_t size) {
uint32_t ObjectFileELF::CalculateELFNotesSegmentsCRC32(
const ProgramHeaderColl &program_headers, DataExtractor &object_data) {
- typedef ProgramHeaderCollConstIter Iter;
uint32_t core_notes_crc = 0;
- for (Iter I = program_headers.begin(); I != program_headers.end(); ++I) {
- if (I->p_type == llvm::ELF::PT_NOTE) {
- const elf_off ph_offset = I->p_offset;
- const size_t ph_size = I->p_filesz;
+ for (const ELFProgramHeader &H : program_headers) {
+ if (H.p_type == llvm::ELF::PT_NOTE) {
+ const elf_off ph_offset = H.p_offset;
+ const size_t ph_size = H.p_filesz;
DataExtractor segment_data;
if (segment_data.SetData(object_data, ph_offset, ph_size) != ph_size) {
@@ -713,7 +715,8 @@ size_t ObjectFileELF::GetModuleSpecifications(
func_cat,
"Calculating module crc32 %s with size %" PRIu64 " KiB",
file.GetLastPathComponent().AsCString(),
- (file.GetByteSize() - file_offset) / 1024);
+ (FileSystem::Instance().GetByteSize(file) - file_offset) /
+ 1024);
// For core files - which usually don't happen to have a
// gnu_debuglink, and are pretty bulky - calculating whole
@@ -803,21 +806,10 @@ bool ObjectFileELF::SetLoadAddress(Target &target, lldb::addr_t value,
SectionList *section_list = GetSectionList();
if (section_list) {
if (!value_is_offset) {
- bool found_offset = false;
- for (size_t i = 1, count = GetProgramHeaderCount(); i <= count; ++i) {
- const elf::ELFProgramHeader *header = GetProgramHeaderByIndex(i);
- if (header == nullptr)
- continue;
-
- if (header->p_type != PT_LOAD || header->p_offset != 0)
- continue;
-
- value = value - header->p_vaddr;
- found_offset = true;
- break;
- }
- if (!found_offset)
+ addr_t base = GetBaseAddress().GetFileAddress();
+ if (base == LLDB_INVALID_ADDRESS)
return false;
+ value -= base;
}
const size_t num_sections = section_list->GetSize();
@@ -827,7 +819,8 @@ bool ObjectFileELF::SetLoadAddress(Target &target, lldb::addr_t value,
// Iterate through the object file sections to find all of the sections
// that have SHF_ALLOC in their flag bits.
SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx));
- if (section_sp && section_sp->Test(SHF_ALLOC)) {
+ if (section_sp->Test(SHF_ALLOC) ||
+ section_sp->GetType() == eSectionTypeContainer) {
lldb::addr_t load_addr = section_sp->GetFileAddress();
// We don't want to update the load address of a section with type
// eSectionTypeAbsoluteAddress as they already have the absolute load
@@ -892,11 +885,11 @@ AddressClass ObjectFileELF::GetAddressClass(addr_t file_addr) {
}
size_t ObjectFileELF::SectionIndex(const SectionHeaderCollIter &I) {
- return std::distance(m_section_headers.begin(), I) + 1u;
+ return std::distance(m_section_headers.begin(), I);
}
size_t ObjectFileELF::SectionIndex(const SectionHeaderCollConstIter &I) const {
- return std::distance(m_section_headers.begin(), I) + 1u;
+ return std::distance(m_section_headers.begin(), I);
}
bool ObjectFileELF::ParseHeader() {
@@ -953,7 +946,7 @@ lldb_private::FileSpecList ObjectFileELF::GetDebugSymbolFilePaths() {
FileSpecList file_spec_list;
if (!m_gnu_debuglink_file.empty()) {
- FileSpec file_spec(m_gnu_debuglink_file, false);
+ FileSpec file_spec(m_gnu_debuglink_file);
file_spec_list.Append(file_spec);
}
return file_spec_list;
@@ -1055,6 +1048,18 @@ lldb_private::Address ObjectFileELF::GetEntryPointAddress() {
return m_entry_point_address;
}
+Address ObjectFileELF::GetBaseAddress() {
+ for (const auto &EnumPHdr : llvm::enumerate(ProgramHeaders())) {
+ const ELFProgramHeader &H = EnumPHdr.value();
+ if (H.p_type != PT_LOAD)
+ continue;
+
+ return Address(
+ GetSectionList()->FindSectionByID(SegmentID(EnumPHdr.index())), 0);
+ }
+ return LLDB_INVALID_ADDRESS;
+}
+
//----------------------------------------------------------------------
// ParseDependentModules
//----------------------------------------------------------------------
@@ -1084,7 +1089,7 @@ size_t ObjectFileELF::ParseDependentModules() {
return 0;
// sh_link: section header index of string table used by entries in the
// section.
- Section *dynstr = section_list->FindSectionByID(header->sh_link + 1).get();
+ Section *dynstr = section_list->FindSectionByID(header->sh_link).get();
if (!dynstr)
return 0;
@@ -1107,7 +1112,9 @@ size_t ObjectFileELF::ParseDependentModules() {
uint32_t str_index = static_cast<uint32_t>(symbol.d_val);
const char *lib_name = dynstr_data.PeekCStr(str_index);
- m_filespec_ap->Append(FileSpec(lib_name, true));
+ FileSpec file_spec(lib_name);
+ FileSystem::Instance().Resolve(file_spec);
+ m_filespec_ap->Append(file_spec);
}
}
@@ -1141,7 +1148,7 @@ size_t ObjectFileELF::GetProgramHeaderInfo(ProgramHeaderColl &program_headers,
uint32_t idx;
lldb::offset_t offset;
for (idx = 0, offset = 0; idx < header.e_phnum; ++idx) {
- if (program_headers[idx].Parse(data, &offset) == false)
+ if (!program_headers[idx].Parse(data, &offset))
break;
}
@@ -1154,8 +1161,8 @@ size_t ObjectFileELF::GetProgramHeaderInfo(ProgramHeaderColl &program_headers,
//----------------------------------------------------------------------
// ParseProgramHeaders
//----------------------------------------------------------------------
-size_t ObjectFileELF::ParseProgramHeaders() {
- return GetProgramHeaderInfo(m_program_headers, m_data, m_header);
+bool ObjectFileELF::ParseProgramHeaders() {
+ return GetProgramHeaderInfo(m_program_headers, m_data, m_header) != 0;
}
lldb_private::Status
@@ -1390,7 +1397,7 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,
arch_spec.GetTriple().getOS() == llvm::Triple::OSType::UnknownOS)
// In case of MIPSR6, the LLDB_NT_OWNER_GNU note is missing for some
// cases (e.g. compile with -nostdlib) Hence set OS to Linux
- arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);
+ arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);
}
}
@@ -1494,7 +1501,7 @@ size_t ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl &section_headers,
const uint32_t sub_type = subTypeFromElfHeader(header);
arch_spec.SetArchitecture(eArchTypeELF, header.e_machine, sub_type,
header.e_ident[EI_OSABI]);
-
+
// Validate if it is ok to remove GetOsFromOSABI. Note, that now the OS is
// determined based on EI_OSABI flag and the info extracted from ELF notes
// (see RefineModuleDetailsFromNote). However in some cases that still
@@ -1553,7 +1560,7 @@ size_t ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl &section_headers,
uint32_t idx;
lldb::offset_t offset;
for (idx = 0, offset = 0; idx < header.e_shnum; ++idx) {
- if (section_headers[idx].Parse(sh_data, &offset) == false)
+ if (!section_headers[idx].Parse(sh_data, &offset))
break;
}
if (idx < section_headers.size())
@@ -1701,27 +1708,6 @@ size_t ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl &section_headers,
return 0;
}
-size_t ObjectFileELF::GetProgramHeaderCount() { return ParseProgramHeaders(); }
-
-const elf::ELFProgramHeader *
-ObjectFileELF::GetProgramHeaderByIndex(lldb::user_id_t id) {
- if (!id || !ParseProgramHeaders())
- return NULL;
-
- if (--id < m_program_headers.size())
- return &m_program_headers[id];
-
- return NULL;
-}
-
-DataExtractor ObjectFileELF::GetSegmentDataByIndex(lldb::user_id_t id) {
- const elf::ELFProgramHeader *segment_header = GetProgramHeaderByIndex(id);
- if (segment_header == NULL)
- return DataExtractor();
- return DataExtractor(m_data, segment_header->p_offset,
- segment_header->p_filesz);
-}
-
llvm::StringRef
ObjectFileELF::StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const {
size_t pos = symbol_name.find('@');
@@ -1739,10 +1725,10 @@ size_t ObjectFileELF::ParseSectionHeaders() {
const ObjectFileELF::ELFSectionHeaderInfo *
ObjectFileELF::GetSectionHeaderByIndex(lldb::user_id_t id) {
- if (!id || !ParseSectionHeaders())
+ if (!ParseSectionHeaders())
return NULL;
- if (--id < m_section_headers.size())
+ if (id < m_section_headers.size())
return &m_section_headers[id];
return NULL;
@@ -1757,233 +1743,273 @@ lldb::user_id_t ObjectFileELF::GetSectionIndexByName(const char *name) {
return 0;
}
-void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
- if (!m_sections_ap.get() && ParseSectionHeaders()) {
- m_sections_ap.reset(new SectionList());
-
- // Object files frequently have 0 for every section address, meaning we
- // need to compute synthetic addresses in order for "file addresses" from
- // different sections to not overlap
- bool synthaddrs = (CalculateType() == ObjectFile::Type::eTypeObjectFile);
- uint64_t nextaddr = 0;
-
- for (SectionHeaderCollIter I = m_section_headers.begin();
- I != m_section_headers.end(); ++I) {
- const ELFSectionHeaderInfo &header = *I;
-
- ConstString &name = I->section_name;
- const uint64_t file_size =
- header.sh_type == SHT_NOBITS ? 0 : header.sh_size;
- const uint64_t vm_size = header.sh_flags & SHF_ALLOC ? header.sh_size : 0;
-
- static ConstString g_sect_name_text(".text");
- static ConstString g_sect_name_data(".data");
- static ConstString g_sect_name_bss(".bss");
- static ConstString g_sect_name_tdata(".tdata");
- static ConstString g_sect_name_tbss(".tbss");
- static ConstString g_sect_name_dwarf_debug_abbrev(".debug_abbrev");
- static ConstString g_sect_name_dwarf_debug_addr(".debug_addr");
- static ConstString g_sect_name_dwarf_debug_aranges(".debug_aranges");
- static ConstString g_sect_name_dwarf_debug_cu_index(".debug_cu_index");
- static ConstString g_sect_name_dwarf_debug_frame(".debug_frame");
- static ConstString g_sect_name_dwarf_debug_info(".debug_info");
- static ConstString g_sect_name_dwarf_debug_line(".debug_line");
- static ConstString g_sect_name_dwarf_debug_loc(".debug_loc");
- static ConstString g_sect_name_dwarf_debug_macinfo(".debug_macinfo");
- static ConstString g_sect_name_dwarf_debug_macro(".debug_macro");
- static ConstString g_sect_name_dwarf_debug_names(".debug_names");
- static ConstString g_sect_name_dwarf_debug_pubnames(".debug_pubnames");
- static ConstString g_sect_name_dwarf_debug_pubtypes(".debug_pubtypes");
- static ConstString g_sect_name_dwarf_debug_ranges(".debug_ranges");
- static ConstString g_sect_name_dwarf_debug_str(".debug_str");
- static ConstString g_sect_name_dwarf_debug_str_offsets(
- ".debug_str_offsets");
- static ConstString g_sect_name_dwarf_debug_abbrev_dwo(
- ".debug_abbrev.dwo");
- static ConstString g_sect_name_dwarf_debug_info_dwo(".debug_info.dwo");
- static ConstString g_sect_name_dwarf_debug_line_dwo(".debug_line.dwo");
- static ConstString g_sect_name_dwarf_debug_macro_dwo(".debug_macro.dwo");
- static ConstString g_sect_name_dwarf_debug_loc_dwo(".debug_loc.dwo");
- static ConstString g_sect_name_dwarf_debug_str_dwo(".debug_str.dwo");
- static ConstString g_sect_name_dwarf_debug_str_offsets_dwo(
- ".debug_str_offsets.dwo");
- static ConstString g_sect_name_dwarf_debug_types(".debug_types");
- static ConstString g_sect_name_eh_frame(".eh_frame");
- static ConstString g_sect_name_arm_exidx(".ARM.exidx");
- static ConstString g_sect_name_arm_extab(".ARM.extab");
- static ConstString g_sect_name_go_symtab(".gosymtab");
- static ConstString g_sect_name_dwarf_gnu_debugaltlink(".gnu_debugaltlink");
-
- SectionType sect_type = eSectionTypeOther;
-
- bool is_thread_specific = false;
-
- if (name == g_sect_name_text)
- sect_type = eSectionTypeCode;
- else if (name == g_sect_name_data)
- sect_type = eSectionTypeData;
- else if (name == g_sect_name_bss)
- sect_type = eSectionTypeZeroFill;
- else if (name == g_sect_name_tdata) {
- sect_type = eSectionTypeData;
- is_thread_specific = true;
- } else if (name == g_sect_name_tbss) {
- sect_type = eSectionTypeZeroFill;
- is_thread_specific = true;
- }
- // .debug_abbrev – Abbreviations used in the .debug_info section
- // .debug_aranges – Lookup table for mapping addresses to compilation
- // units .debug_frame – Call frame information .debug_info – The core
- // DWARF information section .debug_line – Line number information
- // .debug_loc – Location lists used in DW_AT_location attributes
- // .debug_macinfo – Macro information .debug_pubnames – Lookup table
- // for mapping object and function names to compilation units
- // .debug_pubtypes – Lookup table for mapping type names to compilation
- // units .debug_ranges – Address ranges used in DW_AT_ranges attributes
- // .debug_str – String table used in .debug_info MISSING?
- // .gnu_debugdata - "mini debuginfo / MiniDebugInfo" section,
- // http://sourceware.org/gdb/onlinedocs/gdb/MiniDebugInfo.html MISSING?
- // .debug-index - http://src.chromium.org/viewvc/chrome/trunk/src/build
- // /gdb-add-index?pathrev=144644 MISSING? .debug_types - Type
- // descriptions from DWARF 4? See
- // http://gcc.gnu.org/wiki/DwarfSeparateTypeInfo
- else if (name == g_sect_name_dwarf_debug_abbrev)
- sect_type = eSectionTypeDWARFDebugAbbrev;
- else if (name == g_sect_name_dwarf_debug_addr)
- sect_type = eSectionTypeDWARFDebugAddr;
- else if (name == g_sect_name_dwarf_debug_aranges)
- sect_type = eSectionTypeDWARFDebugAranges;
- else if (name == g_sect_name_dwarf_debug_cu_index)
- sect_type = eSectionTypeDWARFDebugCuIndex;
- else if (name == g_sect_name_dwarf_debug_frame)
- sect_type = eSectionTypeDWARFDebugFrame;
- else if (name == g_sect_name_dwarf_debug_info)
- sect_type = eSectionTypeDWARFDebugInfo;
- else if (name == g_sect_name_dwarf_debug_line)
- sect_type = eSectionTypeDWARFDebugLine;
- else if (name == g_sect_name_dwarf_debug_loc)
- sect_type = eSectionTypeDWARFDebugLoc;
- else if (name == g_sect_name_dwarf_debug_macinfo)
- sect_type = eSectionTypeDWARFDebugMacInfo;
- else if (name == g_sect_name_dwarf_debug_macro)
- sect_type = eSectionTypeDWARFDebugMacro;
- else if (name == g_sect_name_dwarf_debug_names)
- sect_type = eSectionTypeDWARFDebugNames;
- else if (name == g_sect_name_dwarf_debug_pubnames)
- sect_type = eSectionTypeDWARFDebugPubNames;
- else if (name == g_sect_name_dwarf_debug_pubtypes)
- sect_type = eSectionTypeDWARFDebugPubTypes;
- else if (name == g_sect_name_dwarf_debug_ranges)
- sect_type = eSectionTypeDWARFDebugRanges;
- else if (name == g_sect_name_dwarf_debug_str)
- sect_type = eSectionTypeDWARFDebugStr;
- else if (name == g_sect_name_dwarf_debug_types)
- sect_type = eSectionTypeDWARFDebugTypes;
- else if (name == g_sect_name_dwarf_debug_str_offsets)
- sect_type = eSectionTypeDWARFDebugStrOffsets;
- else if (name == g_sect_name_dwarf_debug_abbrev_dwo)
- sect_type = eSectionTypeDWARFDebugAbbrev;
- else if (name == g_sect_name_dwarf_debug_info_dwo)
- sect_type = eSectionTypeDWARFDebugInfo;
- else if (name == g_sect_name_dwarf_debug_line_dwo)
- sect_type = eSectionTypeDWARFDebugLine;
- else if (name == g_sect_name_dwarf_debug_macro_dwo)
- sect_type = eSectionTypeDWARFDebugMacro;
- else if (name == g_sect_name_dwarf_debug_loc_dwo)
- sect_type = eSectionTypeDWARFDebugLoc;
- else if (name == g_sect_name_dwarf_debug_str_dwo)
- sect_type = eSectionTypeDWARFDebugStr;
- else if (name == g_sect_name_dwarf_debug_str_offsets_dwo)
- sect_type = eSectionTypeDWARFDebugStrOffsets;
- else if (name == g_sect_name_eh_frame)
- sect_type = eSectionTypeEHFrame;
- else if (name == g_sect_name_arm_exidx)
- sect_type = eSectionTypeARMexidx;
- else if (name == g_sect_name_arm_extab)
- sect_type = eSectionTypeARMextab;
- else if (name == g_sect_name_go_symtab)
- sect_type = eSectionTypeGoSymtab;
- else if (name == g_sect_name_dwarf_gnu_debugaltlink)
- sect_type = eSectionTypeDWARFGNUDebugAltLink;
-
- const uint32_t permissions =
- ((header.sh_flags & SHF_ALLOC) ? ePermissionsReadable : 0u) |
- ((header.sh_flags & SHF_WRITE) ? ePermissionsWritable : 0u) |
- ((header.sh_flags & SHF_EXECINSTR) ? ePermissionsExecutable : 0u);
- switch (header.sh_type) {
- case SHT_SYMTAB:
- assert(sect_type == eSectionTypeOther);
- sect_type = eSectionTypeELFSymbolTable;
- break;
- case SHT_DYNSYM:
- assert(sect_type == eSectionTypeOther);
- sect_type = eSectionTypeELFDynamicSymbols;
- break;
- case SHT_RELA:
- case SHT_REL:
- assert(sect_type == eSectionTypeOther);
- sect_type = eSectionTypeELFRelocationEntries;
- break;
- case SHT_DYNAMIC:
- assert(sect_type == eSectionTypeOther);
- sect_type = eSectionTypeELFDynamicLinkInfo;
- break;
- }
+static SectionType GetSectionTypeFromName(llvm::StringRef Name) {
+ return llvm::StringSwitch<SectionType>(Name)
+ .Case(".ARM.exidx", eSectionTypeARMexidx)
+ .Case(".ARM.extab", eSectionTypeARMextab)
+ .Cases(".bss", ".tbss", eSectionTypeZeroFill)
+ .Cases(".data", ".tdata", eSectionTypeData)
+ .Case(".debug_abbrev", eSectionTypeDWARFDebugAbbrev)
+ .Case(".debug_abbrev.dwo", eSectionTypeDWARFDebugAbbrevDwo)
+ .Case(".debug_addr", eSectionTypeDWARFDebugAddr)
+ .Case(".debug_aranges", eSectionTypeDWARFDebugAranges)
+ .Case(".debug_cu_index", eSectionTypeDWARFDebugCuIndex)
+ .Case(".debug_frame", eSectionTypeDWARFDebugFrame)
+ .Case(".debug_info", eSectionTypeDWARFDebugInfo)
+ .Case(".debug_info.dwo", eSectionTypeDWARFDebugInfoDwo)
+ .Cases(".debug_line", ".debug_line.dwo", eSectionTypeDWARFDebugLine)
+ .Cases(".debug_line_str", ".debug_line_str.dwo",
+ eSectionTypeDWARFDebugLineStr)
+ .Cases(".debug_loc", ".debug_loc.dwo", eSectionTypeDWARFDebugLoc)
+ .Cases(".debug_loclists", ".debug_loclists.dwo",
+ eSectionTypeDWARFDebugLocLists)
+ .Case(".debug_macinfo", eSectionTypeDWARFDebugMacInfo)
+ .Cases(".debug_macro", ".debug_macro.dwo", eSectionTypeDWARFDebugMacro)
+ .Case(".debug_names", eSectionTypeDWARFDebugNames)
+ .Case(".debug_pubnames", eSectionTypeDWARFDebugPubNames)
+ .Case(".debug_pubtypes", eSectionTypeDWARFDebugPubTypes)
+ .Case(".debug_ranges", eSectionTypeDWARFDebugRanges)
+ .Case(".debug_rnglists", eSectionTypeDWARFDebugRngLists)
+ .Case(".debug_str", eSectionTypeDWARFDebugStr)
+ .Case(".debug_str.dwo", eSectionTypeDWARFDebugStrDwo)
+ .Case(".debug_str_offsets", eSectionTypeDWARFDebugStrOffsets)
+ .Case(".debug_str_offsets.dwo", eSectionTypeDWARFDebugStrOffsetsDwo)
+ .Case(".debug_types", eSectionTypeDWARFDebugTypes)
+ .Case(".eh_frame", eSectionTypeEHFrame)
+ .Case(".gnu_debugaltlink", eSectionTypeDWARFGNUDebugAltLink)
+ .Case(".gosymtab", eSectionTypeGoSymtab)
+ .Case(".text", eSectionTypeCode)
+ .Default(eSectionTypeOther);
+}
+
+SectionType ObjectFileELF::GetSectionType(const ELFSectionHeaderInfo &H) const {
+ switch (H.sh_type) {
+ case SHT_PROGBITS:
+ if (H.sh_flags & SHF_EXECINSTR)
+ return eSectionTypeCode;
+ break;
+ case SHT_SYMTAB:
+ return eSectionTypeELFSymbolTable;
+ case SHT_DYNSYM:
+ return eSectionTypeELFDynamicSymbols;
+ case SHT_RELA:
+ case SHT_REL:
+ return eSectionTypeELFRelocationEntries;
+ case SHT_DYNAMIC:
+ return eSectionTypeELFDynamicLinkInfo;
+ }
+ SectionType Type = GetSectionTypeFromName(H.section_name.GetStringRef());
+ if (Type == eSectionTypeOther) {
+ // the kalimba toolchain assumes that ELF section names are free-form.
+ // It does support linkscripts which (can) give rise to various
+ // arbitrarily named sections being "Code" or "Data".
+ Type = kalimbaSectionType(m_header, H);
+ }
+ return Type;
+}
+
+static uint32_t GetTargetByteSize(SectionType Type, const ArchSpec &arch) {
+ switch (Type) {
+ case eSectionTypeData:
+ case eSectionTypeZeroFill:
+ return arch.GetDataByteSize();
+ case eSectionTypeCode:
+ return arch.GetCodeByteSize();
+ default:
+ return 1;
+ }
+}
- if (eSectionTypeOther == sect_type) {
- // the kalimba toolchain assumes that ELF section names are free-form.
- // It does support linkscripts which (can) give rise to various
- // arbitrarily named sections being "Code" or "Data".
- sect_type = kalimbaSectionType(m_header, header);
- }
+static Permissions GetPermissions(const ELFSectionHeader &H) {
+ Permissions Perm = Permissions(0);
+ if (H.sh_flags & SHF_ALLOC)
+ Perm |= ePermissionsReadable;
+ if (H.sh_flags & SHF_WRITE)
+ Perm |= ePermissionsWritable;
+ if (H.sh_flags & SHF_EXECINSTR)
+ Perm |= ePermissionsExecutable;
+ return Perm;
+}
- // In common case ELF code section can have arbitrary name (for example,
- // we can specify it using section attribute for particular function) so
- // assume that section is a code section if it has SHF_EXECINSTR flag set
- // and has SHT_PROGBITS type.
- if (eSectionTypeOther == sect_type &&
- llvm::ELF::SHT_PROGBITS == header.sh_type &&
- (header.sh_flags & SHF_EXECINSTR)) {
- sect_type = eSectionTypeCode;
- }
+static Permissions GetPermissions(const ELFProgramHeader &H) {
+ Permissions Perm = Permissions(0);
+ if (H.p_flags & PF_R)
+ Perm |= ePermissionsReadable;
+ if (H.p_flags & PF_W)
+ Perm |= ePermissionsWritable;
+ if (H.p_flags & PF_X)
+ Perm |= ePermissionsExecutable;
+ return Perm;
+}
- const uint32_t target_bytes_size =
- (eSectionTypeData == sect_type || eSectionTypeZeroFill == sect_type)
- ? m_arch_spec.GetDataByteSize()
- : eSectionTypeCode == sect_type ? m_arch_spec.GetCodeByteSize()
- : 1;
- elf::elf_xword log2align =
- (header.sh_addralign == 0) ? 0 : llvm::Log2_64(header.sh_addralign);
-
- uint64_t addr = header.sh_addr;
-
- if ((header.sh_flags & SHF_ALLOC) && synthaddrs) {
- nextaddr =
- (nextaddr + header.sh_addralign - 1) & ~(header.sh_addralign - 1);
- addr = nextaddr;
- nextaddr += vm_size;
- }
+namespace {
+
+using VMRange = lldb_private::Range<addr_t, addr_t>;
- SectionSP section_sp(new Section(
- GetModule(), // Module to which this section belongs.
- this, // ObjectFile to which this section belongs and should read
- // section data from.
- SectionIndex(I), // Section ID.
- name, // Section name.
- sect_type, // Section type.
- addr, // VM address.
- vm_size, // VM size in bytes of this section.
- header.sh_offset, // Offset of this section in the file.
- file_size, // Size of the section as found in the file.
- log2align, // Alignment of the section
- header.sh_flags, // Flags for this section.
- target_bytes_size)); // Number of host bytes per target byte
-
- section_sp->SetPermissions(permissions);
- if (is_thread_specific)
- section_sp->SetIsThreadSpecific(is_thread_specific);
- m_sections_ap->AddSection(section_sp);
+struct SectionAddressInfo {
+ SectionSP Segment;
+ VMRange Range;
+};
+
+// (Unlinked) ELF object files usually have 0 for every section address, meaning
+// we need to compute synthetic addresses in order for "file addresses" from
+// different sections to not overlap. This class handles that logic.
+class VMAddressProvider {
+ using VMMap = llvm::IntervalMap<addr_t, SectionSP, 4,
+ llvm::IntervalMapHalfOpenInfo<addr_t>>;
+
+ ObjectFile::Type ObjectType;
+ addr_t NextVMAddress = 0;
+ VMMap::Allocator Alloc;
+ VMMap Segments = VMMap(Alloc);
+ VMMap Sections = VMMap(Alloc);
+ lldb_private::Log *Log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_MODULES);
+
+ VMRange GetVMRange(const ELFSectionHeader &H) {
+ addr_t Address = H.sh_addr;
+ addr_t Size = H.sh_flags & SHF_ALLOC ? H.sh_size : 0;
+ if (ObjectType == ObjectFile::Type::eTypeObjectFile && Segments.empty() && (H.sh_flags & SHF_ALLOC)) {
+ NextVMAddress =
+ llvm::alignTo(NextVMAddress, std::max<addr_t>(H.sh_addralign, 1));
+ Address = NextVMAddress;
+ NextVMAddress += Size;
}
+ return VMRange(Address, Size);
+ }
+
+public:
+ VMAddressProvider(ObjectFile::Type Type) : ObjectType(Type) {}
+
+ llvm::Optional<VMRange> GetAddressInfo(const ELFProgramHeader &H) {
+ if (H.p_memsz == 0) {
+ LLDB_LOG(Log,
+ "Ignoring zero-sized PT_LOAD segment. Corrupt object file?");
+ return llvm::None;
+ }
+
+ if (Segments.overlaps(H.p_vaddr, H.p_vaddr + H.p_memsz)) {
+ LLDB_LOG(Log,
+ "Ignoring overlapping PT_LOAD segment. Corrupt object file?");
+ return llvm::None;
+ }
+ return VMRange(H.p_vaddr, H.p_memsz);
+ }
+
+ llvm::Optional<SectionAddressInfo> GetAddressInfo(const ELFSectionHeader &H) {
+ VMRange Range = GetVMRange(H);
+ SectionSP Segment;
+ auto It = Segments.find(Range.GetRangeBase());
+ if ((H.sh_flags & SHF_ALLOC) && It.valid()) {
+ addr_t MaxSize;
+ if (It.start() <= Range.GetRangeBase()) {
+ MaxSize = It.stop() - Range.GetRangeBase();
+ Segment = *It;
+ } else
+ MaxSize = It.start() - Range.GetRangeBase();
+ if (Range.GetByteSize() > MaxSize) {
+ LLDB_LOG(Log, "Shortening section crossing segment boundaries. "
+ "Corrupt object file?");
+ Range.SetByteSize(MaxSize);
+ }
+ }
+ if (Range.GetByteSize() > 0 &&
+ Sections.overlaps(Range.GetRangeBase(), Range.GetRangeEnd())) {
+ LLDB_LOG(Log, "Ignoring overlapping section. Corrupt object file?");
+ return llvm::None;
+ }
+ if (Segment)
+ Range.Slide(-Segment->GetFileAddress());
+ return SectionAddressInfo{Segment, Range};
+ }
+
+ void AddSegment(const VMRange &Range, SectionSP Seg) {
+ Segments.insert(Range.GetRangeBase(), Range.GetRangeEnd(), std::move(Seg));
+ }
+
+ void AddSection(SectionAddressInfo Info, SectionSP Sect) {
+ if (Info.Range.GetByteSize() == 0)
+ return;
+ if (Info.Segment)
+ Info.Range.Slide(Info.Segment->GetFileAddress());
+ Sections.insert(Info.Range.GetRangeBase(), Info.Range.GetRangeEnd(),
+ std::move(Sect));
+ }
+};
+}
+
+void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
+ if (m_sections_ap)
+ return;
+
+ m_sections_ap = llvm::make_unique<SectionList>();
+ VMAddressProvider address_provider(CalculateType());
+
+ size_t LoadID = 0;
+ for (const auto &EnumPHdr : llvm::enumerate(ProgramHeaders())) {
+ const ELFProgramHeader &PHdr = EnumPHdr.value();
+ if (PHdr.p_type != PT_LOAD)
+ continue;
+
+ auto InfoOr = address_provider.GetAddressInfo(PHdr);
+ if (!InfoOr)
+ continue;
+
+ ConstString Name(("PT_LOAD[" + llvm::Twine(LoadID++) + "]").str());
+ uint32_t Log2Align = llvm::Log2_64(std::max<elf_xword>(PHdr.p_align, 1));
+ SectionSP Segment = std::make_shared<Section>(
+ GetModule(), this, SegmentID(EnumPHdr.index()), Name,
+ eSectionTypeContainer, InfoOr->GetRangeBase(), InfoOr->GetByteSize(),
+ PHdr.p_offset, PHdr.p_filesz, Log2Align, /*flags*/ 0);
+ Segment->SetPermissions(GetPermissions(PHdr));
+ m_sections_ap->AddSection(Segment);
+
+ address_provider.AddSegment(*InfoOr, std::move(Segment));
+ }
+
+ ParseSectionHeaders();
+ if (m_section_headers.empty())
+ return;
+
+ for (SectionHeaderCollIter I = std::next(m_section_headers.begin());
+ I != m_section_headers.end(); ++I) {
+ const ELFSectionHeaderInfo &header = *I;
+
+ ConstString &name = I->section_name;
+ const uint64_t file_size =
+ header.sh_type == SHT_NOBITS ? 0 : header.sh_size;
+
+ auto InfoOr = address_provider.GetAddressInfo(header);
+ if (!InfoOr)
+ continue;
+
+ SectionType sect_type = GetSectionType(header);
+
+ const uint32_t target_bytes_size =
+ GetTargetByteSize(sect_type, m_arch_spec);
+
+ elf::elf_xword log2align =
+ (header.sh_addralign == 0) ? 0 : llvm::Log2_64(header.sh_addralign);
+
+ SectionSP section_sp(new Section(
+ InfoOr->Segment, GetModule(), // Module to which this section belongs.
+ this, // ObjectFile to which this section belongs and should
+ // read section data from.
+ SectionIndex(I), // Section ID.
+ name, // Section name.
+ sect_type, // Section type.
+ InfoOr->Range.GetRangeBase(), // VM address.
+ InfoOr->Range.GetByteSize(), // VM size in bytes of this section.
+ header.sh_offset, // Offset of this section in the file.
+ file_size, // Size of the section as found in the file.
+ log2align, // Alignment of the section
+ header.sh_flags, // Flags for this section.
+ target_bytes_size)); // Number of host bytes per target byte
+
+ section_sp->SetPermissions(GetPermissions(header));
+ section_sp->SetIsThreadSpecific(header.sh_flags & SHF_TLS);
+ (InfoOr->Segment ? InfoOr->Segment->GetChildren() : *m_sections_ap)
+ .AddSection(section_sp);
+ address_provider.AddSection(std::move(*InfoOr), std::move(section_sp));
}
// For eTypeDebugInfo files, the Symbol Vendor will take care of updating the
@@ -2050,8 +2076,7 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
bool skip_oatdata_oatexec = file_extension == ConstString(".oat") ||
file_extension == ConstString(".odex");
- ArchSpec arch;
- GetArchitecture(arch);
+ ArchSpec arch = GetArchitecture();
ModuleSP module_sp(GetModule());
SectionList *module_section_list =
module_sp ? module_sp->GetSectionList() : nullptr;
@@ -2063,7 +2088,7 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
unsigned i;
for (i = 0; i < num_symbols; ++i) {
- if (symbol.Parse(symtab_data, &offset) == false)
+ if (!symbol.Parse(symtab_data, &offset))
break;
const char *symbol_name = strtab_data.PeekCStr(symbol.st_name);
@@ -2083,9 +2108,9 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
SectionSP symbol_section_sp;
SymbolType symbol_type = eSymbolTypeInvalid;
- Elf64_Half section_idx = symbol.st_shndx;
+ Elf64_Half shndx = symbol.st_shndx;
- switch (section_idx) {
+ switch (shndx) {
case SHN_ABS:
symbol_type = eSymbolTypeAbsolute;
break;
@@ -2093,7 +2118,7 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
symbol_type = eSymbolTypeUndefined;
break;
default:
- symbol_section_sp = section_list->GetSectionAtIndex(section_idx);
+ symbol_section_sp = section_list->FindSectionByID(shndx);
break;
}
@@ -2262,7 +2287,7 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
// symbols. See above for more details.
uint64_t symbol_value = symbol.st_value + symbol_value_offset;
- if (symbol_section_sp == nullptr && section_idx == SHN_ABS &&
+ if (symbol_section_sp == nullptr && shndx == SHN_ABS &&
symbol.st_size != 0) {
// We don't have a section for a symbol with non-zero size. Create a new
// section for it so the address range covered by the symbol is also
@@ -2375,9 +2400,8 @@ unsigned ObjectFileELF::ParseSymbolTable(Symtab *symbol_table,
assert(symtab_hdr->sh_type == SHT_SYMTAB ||
symtab_hdr->sh_type == SHT_DYNSYM);
- // sh_link: section header index of associated string table. Section ID's are
- // ones based.
- user_id_t strtab_id = symtab_hdr->sh_link + 1;
+ // sh_link: section header index of associated string table.
+ user_id_t strtab_id = symtab_hdr->sh_link;
Section *strtab = section_list->FindSectionByID(strtab_id).get();
if (symtab && strtab) {
@@ -2529,7 +2553,7 @@ static unsigned ParsePLTRelocations(
unsigned slot_type = hdr->GetRelocationJumpSlotType();
unsigned i;
for (i = 0; i < num_relocations; ++i) {
- if (rel.Parse(rel_data, &offset) == false)
+ if (!rel.Parse(rel_data, &offset))
break;
if (reloc_type(rel) != slot_type)
@@ -2587,10 +2611,6 @@ ObjectFileELF::ParseTrampolineSymbols(Symtab *symbol_table, user_id_t start_id,
if (!symtab_id || !plt_id)
return 0;
- // Section ID's are ones based;
- symtab_id++;
- plt_id++;
-
const ELFSectionHeaderInfo *plt_hdr = GetSectionHeaderByIndex(plt_id);
if (!plt_hdr)
return 0;
@@ -2616,7 +2636,7 @@ ObjectFileELF::ParseTrampolineSymbols(Symtab *symbol_table, user_id_t start_id,
return 0;
// sh_link points to associated string table.
- Section *strtab = section_list->FindSectionByID(sym_hdr->sh_link + 1).get();
+ Section *strtab = section_list->FindSectionByID(sym_hdr->sh_link).get();
if (!strtab)
return 0;
@@ -2662,7 +2682,7 @@ unsigned ObjectFileELF::ApplyRelocations(
}
for (unsigned i = 0; i < num_relocations; ++i) {
- if (rel.Parse(rel_data, &offset) == false)
+ if (!rel.Parse(rel_data, &offset))
break;
Symbol *symbol = NULL;
@@ -2684,6 +2704,7 @@ unsigned ObjectFileELF::ApplyRelocations(
}
} else {
switch (reloc_type(rel)) {
+ case R_AARCH64_ABS64:
case R_X86_64_64: {
symbol = symtab->FindSymbolByID(reloc_symbol(rel));
if (symbol) {
@@ -2692,26 +2713,34 @@ unsigned ObjectFileELF::ApplyRelocations(
uint64_t *dst = reinterpret_cast<uint64_t *>(
data_buffer_sp->GetBytes() + rel_section->GetFileOffset() +
ELFRelocation::RelocOffset64(rel));
- *dst = value + ELFRelocation::RelocAddend64(rel);
+ uint64_t val_offset = value + ELFRelocation::RelocAddend64(rel);
+ memcpy(dst, &val_offset, sizeof(uint64_t));
}
break;
}
case R_X86_64_32:
- case R_X86_64_32S: {
+ case R_X86_64_32S:
+ case R_AARCH64_ABS32: {
symbol = symtab->FindSymbolByID(reloc_symbol(rel));
if (symbol) {
addr_t value = symbol->GetAddressRef().GetFileAddress();
value += ELFRelocation::RelocAddend32(rel);
- assert(
- (reloc_type(rel) == R_X86_64_32 && (value <= UINT32_MAX)) ||
+ if ((reloc_type(rel) == R_X86_64_32 && (value > UINT32_MAX)) ||
(reloc_type(rel) == R_X86_64_32S &&
- ((int64_t)value <= INT32_MAX && (int64_t)value >= INT32_MIN)));
+ ((int64_t)value > INT32_MAX && (int64_t)value < INT32_MIN)) ||
+ (reloc_type(rel) == R_AARCH64_ABS32 &&
+ ((int64_t)value > INT32_MAX && (int64_t)value < INT32_MIN))) {
+ Log *log =
+ lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_MODULES);
+ log->Printf("Failed to apply debug info relocations");
+ break;
+ }
uint32_t truncated_addr = (value & 0xFFFFFFFF);
DataBufferSP &data_buffer_sp = debug_data.GetSharedDataBuffer();
uint32_t *dst = reinterpret_cast<uint32_t *>(
data_buffer_sp->GetBytes() + rel_section->GetFileOffset() +
ELFRelocation::RelocOffset32(rel));
- *dst = truncated_addr;
+ memcpy(dst, &truncated_addr, sizeof(uint32_t));
}
break;
}
@@ -2735,9 +2764,8 @@ unsigned ObjectFileELF::RelocateDebugSections(const ELFSectionHeader *rel_hdr,
if (!section_list)
return 0;
- // Section ID's are ones based.
- user_id_t symtab_id = rel_hdr->sh_link + 1;
- user_id_t debug_id = rel_hdr->sh_info + 1;
+ user_id_t symtab_id = rel_hdr->sh_link;
+ user_id_t debug_id = rel_hdr->sh_info;
const ELFSectionHeader *symtab_hdr = GetSectionHeaderByIndex(symtab_id);
if (!symtab_hdr)
@@ -2975,8 +3003,7 @@ void ObjectFileELF::Dump(Stream *s) {
s->Indent();
s->PutCString("ObjectFileELF");
- ArchSpec header_arch;
- GetArchitecture(header_arch);
+ ArchSpec header_arch = GetArchitecture();
*s << ", file = '" << m_file
<< "', arch = " << header_arch.GetArchitectureName() << "\n";
@@ -3153,11 +3180,9 @@ void ObjectFileELF::DumpELFProgramHeaders(Stream *s) {
s->PutCString("==== --------------- -------- -------- -------- "
"-------- -------- ------------------------- --------\n");
- uint32_t idx = 0;
- for (ProgramHeaderCollConstIter I = m_program_headers.begin();
- I != m_program_headers.end(); ++I, ++idx) {
- s->Printf("[%2u] ", idx);
- ObjectFileELF::DumpELFProgramHeader(s, *I);
+ for (const auto &H : llvm::enumerate(m_program_headers)) {
+ s->Format("[{0,2}] ", H.index());
+ ObjectFileELF::DumpELFProgramHeader(s, H.value());
s->EOL();
}
}
@@ -3264,9 +3289,9 @@ void ObjectFileELF::DumpDependentModules(lldb_private::Stream *s) {
}
}
-bool ObjectFileELF::GetArchitecture(ArchSpec &arch) {
+ArchSpec ObjectFileELF::GetArchitecture() {
if (!ParseHeader())
- return false;
+ return ArchSpec();
if (m_section_headers.empty()) {
// Allow elf notes to be parsed which may affect the detected architecture.
@@ -3277,23 +3302,17 @@ bool ObjectFileELF::GetArchitecture(ArchSpec &arch) {
m_arch_spec.TripleOSIsUnspecifiedUnknown()) {
// Core files don't have section headers yet they have PT_NOTE program
// headers that might shed more light on the architecture
- if (ParseProgramHeaders()) {
- for (size_t i = 1, count = GetProgramHeaderCount(); i <= count; ++i) {
- const elf::ELFProgramHeader *header = GetProgramHeaderByIndex(i);
- if (header && header->p_type == PT_NOTE && header->p_offset != 0 &&
- header->p_filesz > 0) {
- DataExtractor data;
- if (data.SetData(m_data, header->p_offset, header->p_filesz) ==
- header->p_filesz) {
- lldb_private::UUID uuid;
- RefineModuleDetailsFromNote(data, m_arch_spec, uuid);
- }
- }
+ for (const elf::ELFProgramHeader &H : ProgramHeaders()) {
+ if (H.p_type != PT_NOTE || H.p_offset == 0 || H.p_filesz == 0)
+ continue;
+ DataExtractor data;
+ if (data.SetData(m_data, H.p_offset, H.p_filesz) == H.p_filesz) {
+ UUID uuid;
+ RefineModuleDetailsFromNote(data, m_arch_spec, uuid);
}
}
}
- arch = m_arch_spec;
- return true;
+ return m_arch_spec;
}
ObjectFile::Type ObjectFileELF::CalculateType() {
@@ -3385,8 +3404,6 @@ size_t ObjectFileELF::ReadSectionData(Section *section,
if (section->GetObjectFile() != this)
return section->GetObjectFile()->ReadSectionData(section, section_data);
- Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_MODULES);
-
size_t result = ObjectFile::ReadSectionData(section, section_data);
if (result == 0 || !section->Test(SHF_COMPRESSED))
return result;
@@ -3397,29 +3414,43 @@ size_t ObjectFileELF::ReadSectionData(Section *section,
size_t(section_data.GetByteSize())},
GetByteOrder() == eByteOrderLittle, GetAddressByteSize() == 8);
if (!Decompressor) {
- LLDB_LOG_ERROR(log, Decompressor.takeError(),
- "Unable to initialize decompressor for section {0}",
- section->GetName());
- return result;
+ GetModule()->ReportWarning(
+ "Unable to initialize decompressor for section '%s': %s",
+ section->GetName().GetCString(),
+ llvm::toString(Decompressor.takeError()).c_str());
+ section_data.Clear();
+ return 0;
}
+
auto buffer_sp =
std::make_shared<DataBufferHeap>(Decompressor->getDecompressedSize(), 0);
- if (auto Error = Decompressor->decompress(
+ if (auto error = Decompressor->decompress(
{reinterpret_cast<char *>(buffer_sp->GetBytes()),
size_t(buffer_sp->GetByteSize())})) {
- LLDB_LOG_ERROR(log, std::move(Error), "Decompression of section {0} failed",
- section->GetName());
- return result;
+ GetModule()->ReportWarning(
+ "Decompression of section '%s' failed: %s",
+ section->GetName().GetCString(),
+ llvm::toString(std::move(error)).c_str());
+ section_data.Clear();
+ return 0;
}
+
section_data.SetData(buffer_sp);
return buffer_sp->GetByteSize();
}
+llvm::ArrayRef<ELFProgramHeader> ObjectFileELF::ProgramHeaders() {
+ ParseProgramHeaders();
+ return m_program_headers;
+}
+
+DataExtractor ObjectFileELF::GetSegmentData(const ELFProgramHeader &H) {
+ return DataExtractor(m_data, H.p_offset, H.p_filesz);
+}
+
bool ObjectFileELF::AnySegmentHasPhysicalAddress() {
- size_t header_count = ParseProgramHeaders();
- for (size_t i = 1; i <= header_count; ++i) {
- auto header = GetProgramHeaderByIndex(i);
- if (header->p_paddr != 0)
+ for (const ELFProgramHeader &H : ProgramHeaders()) {
+ if (H.p_paddr != 0)
return true;
}
return false;
@@ -3430,19 +3461,17 @@ ObjectFileELF::GetLoadableData(Target &target) {
// Create a list of loadable data from loadable segments, using physical
// addresses if they aren't all null
std::vector<LoadableData> loadables;
- size_t header_count = ParseProgramHeaders();
bool should_use_paddr = AnySegmentHasPhysicalAddress();
- for (size_t i = 1; i <= header_count; ++i) {
+ for (const ELFProgramHeader &H : ProgramHeaders()) {
LoadableData loadable;
- auto header = GetProgramHeaderByIndex(i);
- if (header->p_type != llvm::ELF::PT_LOAD)
+ if (H.p_type != llvm::ELF::PT_LOAD)
continue;
- loadable.Dest = should_use_paddr ? header->p_paddr : header->p_vaddr;
+ loadable.Dest = should_use_paddr ? H.p_paddr : H.p_vaddr;
if (loadable.Dest == LLDB_INVALID_ADDRESS)
continue;
- if (header->p_filesz == 0)
+ if (H.p_filesz == 0)
continue;
- auto segment_data = GetSegmentDataByIndex(i);
+ auto segment_data = GetSegmentData(H);
loadable.Contents = llvm::ArrayRef<uint8_t>(segment_data.GetDataStart(),
segment_data.GetByteSize());
loadables.push_back(loadable);
diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
index 2664595fd81d..08fd5bdc60a9 100644
--- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
+++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
@@ -10,10 +10,8 @@
#ifndef liblldb_ObjectFileELF_h_
#define liblldb_ObjectFileELF_h_
-// C Includes
#include <stdint.h>
-// C++ Includes
#include <vector>
#include "lldb/Symbol/ObjectFile.h"
@@ -123,7 +121,7 @@ public:
void Dump(lldb_private::Stream *s) override;
- bool GetArchitecture(lldb_private::ArchSpec &arch) override;
+ lldb_private::ArchSpec GetArchitecture() override;
bool GetUUID(lldb_private::UUID *uuid) override;
@@ -136,6 +134,8 @@ public:
lldb_private::Address GetEntryPointAddress() override;
+ lldb_private::Address GetBaseAddress() override;
+
ObjectFile::Type CalculateType() override;
ObjectFile::Strata CalculateStrata() override;
@@ -147,14 +147,8 @@ public:
size_t ReadSectionData(lldb_private::Section *section,
lldb_private::DataExtractor &section_data) override;
- // Returns number of program headers found in the ELF file.
- size_t GetProgramHeaderCount();
-
- // Returns the program header with the given index.
- const elf::ELFProgramHeader *GetProgramHeaderByIndex(lldb::user_id_t id);
-
- // Returns segment data for the given index.
- lldb_private::DataExtractor GetSegmentDataByIndex(lldb::user_id_t id);
+ llvm::ArrayRef<elf::ELFProgramHeader> ProgramHeaders();
+ lldb_private::DataExtractor GetSegmentData(const elf::ELFProgramHeader &H);
llvm::StringRef
StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const override;
@@ -176,8 +170,6 @@ private:
const lldb::ProcessSP &process_sp, lldb::addr_t header_addr);
typedef std::vector<elf::ELFProgramHeader> ProgramHeaderColl;
- typedef ProgramHeaderColl::iterator ProgramHeaderCollIter;
- typedef ProgramHeaderColl::const_iterator ProgramHeaderCollConstIter;
struct ELFSectionHeaderInfo : public elf::ELFSectionHeader {
lldb_private::ConstString section_name;
@@ -230,10 +222,10 @@ private:
/// The address class for each symbol in the elf file
FileAddressToAddressClassMap m_address_class_map;
- /// Returns a 1 based index of the given section header.
+ /// Returns the index of the given section header.
size_t SectionIndex(const SectionHeaderCollIter &I);
- /// Returns a 1 based index of the given section header.
+ /// Returns the index of the given section header.
size_t SectionIndex(const SectionHeaderCollConstIter &I) const;
// Parses the ELF program headers.
@@ -248,14 +240,16 @@ private:
/// Parses all section headers present in this object file and populates
/// m_program_headers. This method will compute the header list only once.
- /// Returns the number of headers parsed.
- size_t ParseProgramHeaders();
+ /// Returns true iff the headers have been successfully parsed.
+ bool ParseProgramHeaders();
/// Parses all section headers present in this object file and populates
/// m_section_headers. This method will compute the header list only once.
/// Returns the number of headers parsed.
size_t ParseSectionHeaders();
+ lldb::SectionType GetSectionType(const ELFSectionHeaderInfo &H) const;
+
static void ParseARMAttributes(lldb_private::DataExtractor &data,
uint64_t length,
lldb_private::ArchSpec &arch_spec);
diff --git a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp
index af040322ec52..cfe61992be0d 100644
--- a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp
+++ b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp
@@ -153,8 +153,7 @@ void ObjectFileJIT::Dump(Stream *s) {
s->Indent();
s->PutCString("ObjectFileJIT");
- ArchSpec arch;
- if (GetArchitecture(arch))
+ if (ArchSpec arch = GetArchitecture())
*s << ", arch = " << arch.GetArchitectureName();
s->EOL();
@@ -184,17 +183,16 @@ lldb_private::Address ObjectFileJIT::GetEntryPointAddress() {
return Address();
}
-lldb_private::Address ObjectFileJIT::GetHeaderAddress() { return Address(); }
+lldb_private::Address ObjectFileJIT::GetBaseAddress() { return Address(); }
ObjectFile::Type ObjectFileJIT::CalculateType() { return eTypeJIT; }
ObjectFile::Strata ObjectFileJIT::CalculateStrata() { return eStrataJIT; }
-bool ObjectFileJIT::GetArchitecture(ArchSpec &arch) {
- ObjectFileJITDelegateSP delegate_sp(m_delegate_wp.lock());
- if (delegate_sp)
- return delegate_sp->GetArchitecture(arch);
- return false;
+ArchSpec ObjectFileJIT::GetArchitecture() {
+ if (ObjectFileJITDelegateSP delegate_sp = m_delegate_wp.lock())
+ return delegate_sp->GetArchitecture();
+ return ArchSpec();
}
//------------------------------------------------------------------
@@ -218,7 +216,7 @@ bool ObjectFileJIT::SetLoadAddress(Target &target, lldb::addr_t value,
// that size on disk (to avoid __PAGEZERO) and load them
SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx));
if (section_sp && section_sp->GetFileSize() > 0 &&
- section_sp->IsThreadSpecific() == false) {
+ !section_sp->IsThreadSpecific()) {
if (target.GetSectionLoadList().SetSectionLoadAddress(
section_sp, section_sp->GetFileAddress() + value))
++num_loaded_sections;
diff --git a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h
index c964906a5e8e..3d9e4748d3df 100644
--- a/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h
+++ b/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h
@@ -10,10 +10,6 @@
#ifndef liblldb_ObjectFileJIT_h_
#define liblldb_ObjectFileJIT_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/Address.h"
#include "lldb/Symbol/ObjectFile.h"
@@ -77,7 +73,7 @@ public:
void Dump(lldb_private::Stream *s) override;
- bool GetArchitecture(lldb_private::ArchSpec &arch) override;
+ lldb_private::ArchSpec GetArchitecture() override;
bool GetUUID(lldb_private::UUID *uuid) override;
@@ -93,7 +89,7 @@ public:
lldb_private::Address GetEntryPointAddress() override;
- lldb_private::Address GetHeaderAddress() override;
+ lldb_private::Address GetBaseAddress() override;
ObjectFile::Type CalculateType() override;
diff --git a/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
index 91e7f3353270..06908fecf984 100644
--- a/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
+++ b/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
@@ -7,12 +7,8 @@
//
//===----------------------------------------------------------------------===//
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
#include "llvm/ADT/StringRef.h"
-// Project includes
#include "Plugins/Process/Utility/RegisterContextDarwin_arm.h"
#include "Plugins/Process/Utility/RegisterContextDarwin_arm64.h"
#include "Plugins/Process/Utility/RegisterContextDarwin_i386.h"
@@ -23,7 +19,6 @@
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/RangeMap.h"
-#include "lldb/Core/RegisterValue.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Host/Host.h"
@@ -41,12 +36,13 @@
#include "lldb/Utility/DataBuffer.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/Timer.h"
#include "lldb/Utility/UUID.h"
-#include "lldb/Utility/SafeMachO.h"
+#include "lldb/Host/SafeMachO.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -919,12 +915,10 @@ size_t ObjectFileMachO::GetModuleSpecifications(
spec.SetObjectOffset(file_offset);
spec.SetObjectSize(length);
- if (GetArchitecture(header, data, data_offset,
- spec.GetArchitecture())) {
- if (spec.GetArchitecture().IsValid()) {
- GetUUID(header, data, data_offset, spec.GetUUID());
- specs.Append(spec);
- }
+ spec.GetArchitecture() = GetArchitecture(header, data, data_offset);
+ if (spec.GetArchitecture().IsValid()) {
+ GetUUID(header, data, data_offset, spec.GetUUID());
+ specs.Append(spec);
}
}
}
@@ -962,6 +956,11 @@ const ConstString &ObjectFileMachO::GetSegmentNameLINKEDIT() {
return g_section_name_LINKEDIT;
}
+const ConstString &ObjectFileMachO::GetSegmentNameDWARF() {
+ static ConstString g_section_name("__DWARF");
+ return g_section_name;
+}
+
const ConstString &ObjectFileMachO::GetSectionNameEHFrame() {
static ConstString g_section_name_eh_frame("__eh_frame");
return g_section_name_eh_frame;
@@ -1102,9 +1101,7 @@ bool ObjectFileMachO::ParseHeader() {
if (can_parse) {
m_data.GetU32(&offset, &m_header.cputype, 6);
- ArchSpec mach_arch;
-
- if (GetArchitecture(mach_arch)) {
+ if (ArchSpec mach_arch = GetArchitecture()) {
// Check if the module has a required architecture
const ArchSpec &module_arch = module_sp->GetArchitecture();
if (module_arch.IsValid() && !module_arch.IsCompatibleMatch(mach_arch))
@@ -1191,21 +1188,28 @@ AddressClass ObjectFileMachO::GetAddressClass(lldb::addr_t file_addr) {
case eSectionTypeDebug:
case eSectionTypeDWARFDebugAbbrev:
+ case eSectionTypeDWARFDebugAbbrevDwo:
case eSectionTypeDWARFDebugAddr:
case eSectionTypeDWARFDebugAranges:
case eSectionTypeDWARFDebugCuIndex:
case eSectionTypeDWARFDebugFrame:
case eSectionTypeDWARFDebugInfo:
+ case eSectionTypeDWARFDebugInfoDwo:
case eSectionTypeDWARFDebugLine:
+ case eSectionTypeDWARFDebugLineStr:
case eSectionTypeDWARFDebugLoc:
+ case eSectionTypeDWARFDebugLocLists:
case eSectionTypeDWARFDebugMacInfo:
case eSectionTypeDWARFDebugMacro:
case eSectionTypeDWARFDebugNames:
case eSectionTypeDWARFDebugPubNames:
case eSectionTypeDWARFDebugPubTypes:
case eSectionTypeDWARFDebugRanges:
+ case eSectionTypeDWARFDebugRngLists:
case eSectionTypeDWARFDebugStr:
+ case eSectionTypeDWARFDebugStrDwo:
case eSectionTypeDWARFDebugStrOffsets:
+ case eSectionTypeDWARFDebugStrOffsetsDwo:
case eSectionTypeDWARFDebugTypes:
case eSectionTypeDWARFAppleNames:
case eSectionTypeDWARFAppleTypes:
@@ -1455,6 +1459,7 @@ static lldb::SectionType GetSectionType(uint32_t flags,
static ConstString g_sect_name_dwarf_debug_info("__debug_info");
static ConstString g_sect_name_dwarf_debug_line("__debug_line");
static ConstString g_sect_name_dwarf_debug_loc("__debug_loc");
+ static ConstString g_sect_name_dwarf_debug_loclists("__debug_loclists");
static ConstString g_sect_name_dwarf_debug_macinfo("__debug_macinfo");
static ConstString g_sect_name_dwarf_debug_names("__debug_names");
static ConstString g_sect_name_dwarf_debug_pubnames("__debug_pubnames");
@@ -1484,6 +1489,8 @@ static lldb::SectionType GetSectionType(uint32_t flags,
return eSectionTypeDWARFDebugLine;
if (section_name == g_sect_name_dwarf_debug_loc)
return eSectionTypeDWARFDebugLoc;
+ if (section_name == g_sect_name_dwarf_debug_loclists)
+ return eSectionTypeDWARFDebugLocLists;
if (section_name == g_sect_name_dwarf_debug_macinfo)
return eSectionTypeDWARFDebugMacInfo;
if (section_name == g_sect_name_dwarf_debug_names)
@@ -1493,7 +1500,7 @@ static lldb::SectionType GetSectionType(uint32_t flags,
if (section_name == g_sect_name_dwarf_debug_pubtypes)
return eSectionTypeDWARFDebugPubTypes;
if (section_name == g_sect_name_dwarf_debug_ranges)
- return eSectionTypeDWARFDebugRanges;
+ return eSectionTypeDWARFDebugRanges;
if (section_name == g_sect_name_dwarf_debug_str)
return eSectionTypeDWARFDebugStr;
if (section_name == g_sect_name_dwarf_debug_types)
@@ -1668,7 +1675,7 @@ void ObjectFileMachO::ProcessSegmentCommand(const load_command &load_cmd_,
} else if (unified_section_sp) {
if (is_dsym && unified_section_sp->GetFileAddress() != load_cmd.vmaddr) {
// Check to see if the module was read from memory?
- if (module_sp->GetObjectFile()->GetHeaderAddress().IsValid()) {
+ if (module_sp->GetObjectFile()->GetBaseAddress().IsValid()) {
// We have a module that is in memory and needs to have its file
// address adjusted. We need to do this because when we load a file
// from memory, its addresses will be slid already, yet the addresses
@@ -2177,7 +2184,7 @@ size_t ObjectFileMachO::ParseSymtab() {
uint32_t name_offset = cmd_offset + m_data.GetU32(&offset);
const char *path = m_data.PeekCStr(name_offset);
if (path) {
- FileSpec file_spec(path, false);
+ FileSpec file_spec(path);
// Strip the path if there is @rpath, @executable, etc so we just use
// the basename
if (path[0] == '@')
@@ -2331,14 +2338,6 @@ size_t ObjectFileMachO::ParseSymtab() {
if (nlist_data_sp)
nlist_data.SetData(nlist_data_sp, 0,
nlist_data_sp->GetByteSize());
- // Load strings individually from memory when loading from memory
- // since shared cache string tables contain strings for all symbols
- // from all shared cached libraries DataBufferSP strtab_data_sp
- // (ReadMemory (process_sp, strtab_addr,
- // strtab_data_byte_size));
- // if (strtab_data_sp)
- // strtab_data.SetData (strtab_data_sp, 0,
- // strtab_data_sp->GetByteSize());
if (m_dysymtab.nindirectsyms != 0) {
const addr_t indirect_syms_addr = linkedit_load_addr +
m_dysymtab.indirectsymoff -
@@ -2350,8 +2349,25 @@ size_t ObjectFileMachO::ParseSymtab() {
indirect_symbol_index_data.SetData(
indirect_syms_data_sp, 0,
indirect_syms_data_sp->GetByteSize());
+ // If this binary is outside the shared cache,
+ // cache the string table.
+ // Binaries in the shared cache all share a giant string table, and
+ // we can't share the string tables across multiple ObjectFileMachO's,
+ // so we'd end up re-reading this mega-strtab for every binary
+ // in the shared cache - it would be a big perf problem.
+ // For binaries outside the shared cache, it's faster to read the
+ // entire strtab at once instead of piece-by-piece as we process
+ // the nlist records.
+ if ((m_header.flags & 0x80000000u) == 0) {
+ DataBufferSP strtab_data_sp (ReadMemory (process_sp, strtab_addr,
+ strtab_data_byte_size));
+ if (strtab_data_sp) {
+ strtab_data.SetData (strtab_data_sp, 0, strtab_data_sp->GetByteSize());
+ }
+ }
}
- } else if (memory_module_load_level >=
+ }
+ if (memory_module_load_level >=
eMemoryModuleLoadLevelPartial) {
if (function_starts_load_command.cmd) {
const addr_t func_start_addr =
@@ -2621,7 +2637,7 @@ size_t ObjectFileMachO::ParseSymtab() {
// shared cache UUID in the development or non-development shared caches
// on disk.
if (process_shared_cache_uuid.IsValid()) {
- if (dsc_development_filespec.Exists()) {
+ if (FileSystem::Instance().Exists(dsc_development_filespec)) {
UUID dsc_development_uuid = GetSharedCacheUUID(
dsc_development_filespec, byte_order, addr_byte_size);
if (dsc_development_uuid.IsValid() &&
@@ -2630,7 +2646,8 @@ size_t ObjectFileMachO::ParseSymtab() {
dsc_uuid = dsc_development_uuid;
}
}
- if (!dsc_uuid.IsValid() && dsc_nondevelopment_filespec.Exists()) {
+ if (!dsc_uuid.IsValid() &&
+ FileSystem::Instance().Exists(dsc_nondevelopment_filespec)) {
UUID dsc_nondevelopment_uuid = GetSharedCacheUUID(
dsc_nondevelopment_filespec, byte_order, addr_byte_size);
if (dsc_nondevelopment_uuid.IsValid() &&
@@ -2643,8 +2660,8 @@ size_t ObjectFileMachO::ParseSymtab() {
// Failing a UUID match, prefer the development dyld_shared cache if both
// are present.
- if (!dsc_filespec.Exists()) {
- if (dsc_development_filespec.Exists()) {
+ if (!FileSystem::Instance().Exists(dsc_filespec)) {
+ if (FileSystem::Instance().Exists(dsc_development_filespec)) {
dsc_filespec = dsc_development_filespec;
} else {
dsc_filespec = dsc_nondevelopment_filespec;
@@ -3052,11 +3069,11 @@ size_t ObjectFileMachO::ParseSymtab() {
// file so you end up with a path that looks
// like "/tmp/src//tmp/src/"
FileSpec so_dir(so_path, false);
- if (!so_dir.Exists()) {
+ if (!FileSystem::Instance().Exists(so_dir)) {
so_dir.SetFile(
&full_so_path[double_slash_pos + 1],
false);
- if (so_dir.Exists()) {
+ if (FileSystem::Instance().Exists(so_dir)) {
// Trim off the incorrect path
full_so_path.erase(0,
double_slash_pos + 1);
@@ -4001,11 +4018,11 @@ size_t ObjectFileMachO::ParseSymtab() {
// string in the DW_AT_comp_dir, and the second is the
// directory for the source file so you end up with a path
// that looks like "/tmp/src//tmp/src/"
- FileSpec so_dir(so_path, false);
- if (!so_dir.Exists()) {
- so_dir.SetFile(&full_so_path[double_slash_pos + 1], false,
+ FileSpec so_dir(so_path);
+ if (!FileSystem::Instance().Exists(so_dir)) {
+ so_dir.SetFile(&full_so_path[double_slash_pos + 1],
FileSpec::Style::native);
- if (so_dir.Exists()) {
+ if (FileSystem::Instance().Exists(so_dir)) {
// Trim off the incorrect path
full_so_path.erase(0, double_slash_pos + 1);
}
@@ -4453,7 +4470,7 @@ size_t ObjectFileMachO::ParseSymtab() {
symbol_value -= section_file_addr;
}
- if (is_debug == false) {
+ if (!is_debug) {
if (type == eSymbolTypeCode) {
// See if we can find a N_FUN entry for any code symbols. If we
// do find a match, and the name matches, then we can merge the
@@ -4600,7 +4617,7 @@ size_t ObjectFileMachO::ParseSymtab() {
if (function_starts_count > 0) {
uint32_t num_synthetic_function_symbols = 0;
for (i = 0; i < function_starts_count; ++i) {
- if (function_starts.GetEntryRef(i).data == false)
+ if (!function_starts.GetEntryRef(i).data)
++num_synthetic_function_symbols;
}
@@ -4612,7 +4629,7 @@ size_t ObjectFileMachO::ParseSymtab() {
for (i = 0; i < function_starts_count; ++i) {
const FunctionStarts::Entry *func_start_entry =
function_starts.GetEntryAtIndex(i);
- if (func_start_entry->data == false) {
+ if (!func_start_entry->data) {
addr_t symbol_file_addr = func_start_entry->addr;
uint32_t symbol_flags = 0;
if (is_arm) {
@@ -4817,8 +4834,7 @@ void ObjectFileMachO::Dump(Stream *s) {
else
s->PutCString("ObjectFileMachO32");
- ArchSpec header_arch;
- GetArchitecture(header_arch);
+ ArchSpec header_arch = GetArchitecture();
*s << ", file = '" << m_file
<< "', triple = " << header_arch.GetTriple().getTriple() << "\n";
@@ -4869,25 +4885,83 @@ bool ObjectFileMachO::GetUUID(const llvm::MachO::mach_header &header,
return false;
}
-static const char *GetOSName(uint32_t cmd) {
+static llvm::StringRef GetOSName(uint32_t cmd) {
switch (cmd) {
case llvm::MachO::LC_VERSION_MIN_IPHONEOS:
- return "ios";
+ return llvm::Triple::getOSTypeName(llvm::Triple::IOS);
case llvm::MachO::LC_VERSION_MIN_MACOSX:
- return "macosx";
+ return llvm::Triple::getOSTypeName(llvm::Triple::MacOSX);
case llvm::MachO::LC_VERSION_MIN_TVOS:
- return "tvos";
+ return llvm::Triple::getOSTypeName(llvm::Triple::TvOS);
case llvm::MachO::LC_VERSION_MIN_WATCHOS:
- return "watchos";
+ return llvm::Triple::getOSTypeName(llvm::Triple::WatchOS);
default:
llvm_unreachable("unexpected LC_VERSION load command");
}
}
-bool ObjectFileMachO::GetArchitecture(const llvm::MachO::mach_header &header,
- const lldb_private::DataExtractor &data,
- lldb::offset_t lc_offset,
- ArchSpec &arch) {
+namespace {
+ struct OSEnv {
+ llvm::StringRef os_type;
+ llvm::StringRef environment;
+ OSEnv(uint32_t cmd) {
+ switch (cmd) {
+ case PLATFORM_MACOS:
+ os_type = llvm::Triple::getOSTypeName(llvm::Triple::MacOSX);
+ return;
+ case PLATFORM_IOS:
+ os_type = llvm::Triple::getOSTypeName(llvm::Triple::IOS);
+ return;
+ case PLATFORM_TVOS:
+ os_type = llvm::Triple::getOSTypeName(llvm::Triple::TvOS);
+ return;
+ case PLATFORM_WATCHOS:
+ os_type = llvm::Triple::getOSTypeName(llvm::Triple::WatchOS);
+ return;
+// NEED_BRIDGEOS_TRIPLE case PLATFORM_BRIDGEOS:
+// NEED_BRIDGEOS_TRIPLE os_type = llvm::Triple::getOSTypeName(llvm::Triple::BridgeOS);
+// NEED_BRIDGEOS_TRIPLE return;
+#if defined (PLATFORM_IOSSIMULATOR) && defined (PLATFORM_TVOSSIMULATOR) && defined (PLATFORM_WATCHOSSIMULATOR)
+ case PLATFORM_IOSSIMULATOR:
+ os_type = llvm::Triple::getOSTypeName(llvm::Triple::IOS);
+ environment =
+ llvm::Triple::getEnvironmentTypeName(llvm::Triple::Simulator);
+ return;
+ case PLATFORM_TVOSSIMULATOR:
+ os_type = llvm::Triple::getOSTypeName(llvm::Triple::TvOS);
+ environment =
+ llvm::Triple::getEnvironmentTypeName(llvm::Triple::Simulator);
+ return;
+ case PLATFORM_WATCHOSSIMULATOR:
+ os_type = llvm::Triple::getOSTypeName(llvm::Triple::WatchOS);
+ environment =
+ llvm::Triple::getEnvironmentTypeName(llvm::Triple::Simulator);
+ return;
+#endif
+ default: {
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_SYMBOLS |
+ LIBLLDB_LOG_PROCESS));
+ if (log)
+ log->Printf("unsupported platform in LC_BUILD_VERSION");
+ }
+ }
+ }
+ };
+
+ struct MinOS {
+ uint32_t major_version, minor_version, patch_version;
+ MinOS(uint32_t version)
+ : major_version(version >> 16),
+ minor_version((version >> 8) & 0xffu),
+ patch_version(version & 0xffu) {}
+ };
+} // namespace
+
+ArchSpec
+ObjectFileMachO::GetArchitecture(const llvm::MachO::mach_header &header,
+ const lldb_private::DataExtractor &data,
+ lldb::offset_t lc_offset) {
+ ArchSpec arch;
arch.SetArchitecture(eArchTypeMachO, header.cputype, header.cpusubtype);
if (arch.IsValid()) {
@@ -4912,39 +4986,37 @@ bool ObjectFileMachO::GetArchitecture(const llvm::MachO::mach_header &header,
triple.setVendor(llvm::Triple::UnknownVendor);
triple.setVendorName(llvm::StringRef());
}
- return true;
+ return arch;
} else {
struct load_command load_cmd;
+ llvm::SmallString<16> os_name;
+ llvm::raw_svector_ostream os(os_name);
+ // See if there is an LC_VERSION_MIN_* load command that can give
+ // us the OS type.
lldb::offset_t offset = lc_offset;
for (uint32_t i = 0; i < header.ncmds; ++i) {
const lldb::offset_t cmd_offset = offset;
if (data.GetU32(&offset, &load_cmd, 2) == NULL)
break;
- uint32_t major, minor, patch;
struct version_min_command version_min;
-
- llvm::SmallString<16> os_name;
- llvm::raw_svector_ostream os(os_name);
-
switch (load_cmd.cmd) {
case llvm::MachO::LC_VERSION_MIN_IPHONEOS:
case llvm::MachO::LC_VERSION_MIN_MACOSX:
case llvm::MachO::LC_VERSION_MIN_TVOS:
- case llvm::MachO::LC_VERSION_MIN_WATCHOS:
+ case llvm::MachO::LC_VERSION_MIN_WATCHOS: {
if (load_cmd.cmdsize != sizeof(version_min))
break;
- data.ExtractBytes(cmd_offset,
- sizeof(version_min), data.GetByteOrder(),
- &version_min);
- major = version_min.version >> 16;
- minor = (version_min.version >> 8) & 0xffu;
- patch = version_min.version & 0xffu;
- os << GetOSName(load_cmd.cmd) << major << '.' << minor << '.'
- << patch;
+ if (data.ExtractBytes(cmd_offset, sizeof(version_min),
+ data.GetByteOrder(), &version_min) == 0)
+ break;
+ MinOS min_os(version_min.version);
+ os << GetOSName(load_cmd.cmd) << min_os.major_version << '.'
+ << min_os.minor_version << '.' << min_os.patch_version;
triple.setOSName(os.str());
- return true;
+ return arch;
+ }
default:
break;
}
@@ -4952,6 +5024,39 @@ bool ObjectFileMachO::GetArchitecture(const llvm::MachO::mach_header &header,
offset = cmd_offset + load_cmd.cmdsize;
}
+ // See if there is an LC_BUILD_VERSION load command that can give
+ // us the OS type.
+
+ offset = lc_offset;
+ for (uint32_t i = 0; i < header.ncmds; ++i) {
+ const lldb::offset_t cmd_offset = offset;
+ if (data.GetU32(&offset, &load_cmd, 2) == NULL)
+ break;
+ do {
+ if (load_cmd.cmd == llvm::MachO::LC_BUILD_VERSION) {
+ struct build_version_command build_version;
+ if (load_cmd.cmdsize < sizeof(build_version)) {
+ // Malformed load command.
+ break;
+ }
+ if (data.ExtractBytes(cmd_offset, sizeof(build_version),
+ data.GetByteOrder(), &build_version) == 0)
+ break;
+ MinOS min_os(build_version.minos);
+ OSEnv os_env(build_version.platform);
+ if (os_env.os_type.empty())
+ break;
+ os << os_env.os_type << min_os.major_version << '.'
+ << min_os.minor_version << '.' << min_os.patch_version;
+ triple.setOSName(os.str());
+ if (!os_env.environment.empty())
+ triple.setEnvironmentName(os_env.environment);
+ return arch;
+ }
+ } while (0);
+ offset = cmd_offset + load_cmd.cmdsize;
+ }
+
if (header.filetype != MH_KEXT_BUNDLE) {
// We didn't find a LC_VERSION_MIN load command and this isn't a KEXT
// so lets not say our Vendor is Apple, leave it as an unspecified
@@ -4961,7 +5066,7 @@ bool ObjectFileMachO::GetArchitecture(const llvm::MachO::mach_header &header,
}
}
}
- return arch.IsValid();
+ return arch;
}
bool ObjectFileMachO::GetUUID(lldb_private::UUID *uuid) {
@@ -4984,9 +5089,6 @@ uint32_t ObjectFileMachO::GetDependentModules(FileSpecList &files) {
std::vector<std::string> rpath_paths;
std::vector<std::string> rpath_relative_paths;
std::vector<std::string> at_exec_relative_paths;
- const bool resolve_path = false; // Don't resolve the dependent file paths
- // since they may not reside on this
- // system
uint32_t i;
for (i = 0; i < m_header.ncmds; ++i) {
const uint32_t cmd_offset = offset;
@@ -5015,7 +5117,7 @@ uint32_t ObjectFileMachO::GetDependentModules(FileSpecList &files) {
at_exec_relative_paths.push_back(path
+ strlen("@executable_path"));
} else {
- FileSpec file_spec(path, resolve_path);
+ FileSpec file_spec(path);
if (files.AppendIfUnique(file_spec))
count++;
}
@@ -5030,8 +5132,8 @@ uint32_t ObjectFileMachO::GetDependentModules(FileSpecList &files) {
}
FileSpec this_file_spec(m_file);
- this_file_spec.ResolvePath();
-
+ FileSystem::Instance().Resolve(this_file_spec);
+
if (!rpath_paths.empty()) {
// Fixup all LC_RPATH values to be absolute paths
std::string loader_path("@loader_path");
@@ -5052,8 +5154,10 @@ uint32_t ObjectFileMachO::GetDependentModules(FileSpecList &files) {
path += rpath_relative_path;
// It is OK to resolve this path because we must find a file on disk
// for us to accept it anyway if it is rpath relative.
- FileSpec file_spec(path, true);
- if (file_spec.Exists() && files.AppendIfUnique(file_spec)) {
+ FileSpec file_spec(path);
+ FileSystem::Instance().Resolve(file_spec);
+ if (FileSystem::Instance().Exists(file_spec) &&
+ files.AppendIfUnique(file_spec)) {
count++;
break;
}
@@ -5070,7 +5174,8 @@ uint32_t ObjectFileMachO::GetDependentModules(FileSpecList &files) {
for (const auto &at_exec_relative_path : at_exec_relative_paths) {
FileSpec file_spec =
exec_dir.CopyByAppendingPathComponent(at_exec_relative_path);
- if (file_spec.Exists() && files.AppendIfUnique(file_spec))
+ if (FileSystem::Instance().Exists(file_spec) &&
+ files.AppendIfUnique(file_spec))
count++;
}
}
@@ -5235,7 +5340,7 @@ lldb_private::Address ObjectFileMachO::GetEntryPointAddress() {
return m_entry_point_address;
}
-lldb_private::Address ObjectFileMachO::GetHeaderAddress() {
+lldb_private::Address ObjectFileMachO::GetBaseAddress() {
lldb_private::Address header_addr;
SectionList *section_list = GetSectionList();
if (section_list) {
@@ -5583,14 +5688,16 @@ llvm::VersionTuple ObjectFileMachO::GetVersion() {
return llvm::VersionTuple();
}
-bool ObjectFileMachO::GetArchitecture(ArchSpec &arch) {
+ArchSpec ObjectFileMachO::GetArchitecture() {
ModuleSP module_sp(GetModule());
+ ArchSpec arch;
if (module_sp) {
std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
+
return GetArchitecture(m_header, m_data,
- MachHeaderSizeFromMagic(m_header.magic), arch);
+ MachHeaderSizeFromMagic(m_header.magic));
}
- return false;
+ return arch;
}
void ObjectFileMachO::GetProcessSharedCacheUUID(Process *process, addr_t &base_addr, UUID &uuid) {
@@ -5716,8 +5823,30 @@ llvm::VersionTuple ObjectFileMachO::GetMinimumOSVersion() {
m_min_os_version = llvm::VersionTuple(xxxx, yy, zz);
break;
}
+ }
+ } else if (lc.cmd == llvm::MachO::LC_BUILD_VERSION) {
+ // struct build_version_command {
+ // uint32_t cmd; /* LC_BUILD_VERSION */
+ // uint32_t cmdsize; /* sizeof(struct build_version_command) plus */
+ // /* ntools * sizeof(struct build_tool_version) */
+ // uint32_t platform; /* platform */
+ // uint32_t minos; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
+ // uint32_t sdk; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
+ // uint32_t ntools; /* number of tool entries following this */
+ // };
+
+ offset += 4; // skip platform
+ uint32_t minos = m_data.GetU32(&offset);
+
+ const uint32_t xxxx = minos >> 16;
+ const uint32_t yy = (minos >> 8) & 0xffu;
+ const uint32_t zz = minos & 0xffu;
+ if (xxxx) {
+ m_min_os_version = llvm::VersionTuple(xxxx, yy, zz);
+ break;
}
}
+
offset = load_cmd_offset + lc.cmdsize;
}
@@ -5735,7 +5864,7 @@ uint32_t ObjectFileMachO::GetSDKVersion(uint32_t *versions,
if (m_sdk_versions.empty()) {
lldb::offset_t offset = MachHeaderSizeFromMagic(m_header.magic);
bool success = false;
- for (uint32_t i = 0; success == false && i < m_header.ncmds; ++i) {
+ for (uint32_t i = 0; !success && i < m_header.ncmds; ++i) {
const lldb::offset_t load_cmd_offset = offset;
version_min_command lc;
@@ -5764,7 +5893,46 @@ uint32_t ObjectFileMachO::GetSDKVersion(uint32_t *versions,
offset = load_cmd_offset + lc.cmdsize;
}
- if (success == false) {
+ if (!success) {
+ offset = MachHeaderSizeFromMagic(m_header.magic);
+ for (uint32_t i = 0; !success && i < m_header.ncmds; ++i) {
+ const lldb::offset_t load_cmd_offset = offset;
+
+ version_min_command lc;
+ if (m_data.GetU32(&offset, &lc.cmd, 2) == NULL)
+ break;
+ if (lc.cmd == llvm::MachO::LC_BUILD_VERSION) {
+ // struct build_version_command {
+ // uint32_t cmd; /* LC_BUILD_VERSION */
+ // uint32_t cmdsize; /* sizeof(struct
+ // build_version_command) plus */
+ // /* ntools * sizeof(struct
+ // build_tool_version) */
+ // uint32_t platform; /* platform */
+ // uint32_t minos; /* X.Y.Z is encoded in nibbles
+ // xxxx.yy.zz */ uint32_t sdk; /* X.Y.Z is encoded
+ // in nibbles xxxx.yy.zz */ uint32_t ntools; /* number
+ // of tool entries following this */
+ // };
+
+ offset += 4; // skip platform
+ uint32_t minos = m_data.GetU32(&offset);
+
+ const uint32_t xxxx = minos >> 16;
+ const uint32_t yy = (minos >> 8) & 0xffu;
+ const uint32_t zz = minos & 0xffu;
+ if (xxxx) {
+ m_sdk_versions.push_back(xxxx);
+ m_sdk_versions.push_back(yy);
+ m_sdk_versions.push_back(zz);
+ success = true;
+ }
+ }
+ offset = load_cmd_offset + lc.cmdsize;
+ }
+ }
+
+ if (!success) {
// Push an invalid value so we don't try to find
// the version # again on the next call to this
// method.
@@ -5814,52 +5982,52 @@ Section *ObjectFileMachO::GetMachHeaderSection() {
// the mach-o file which can be subtracted from the vmaddr of the other
// segments found in memory and added to the load address
ModuleSP module_sp = GetModule();
- if (module_sp) {
- SectionList *section_list = GetSectionList();
- if (section_list) {
- lldb::addr_t mach_base_file_addr = LLDB_INVALID_ADDRESS;
- const size_t num_sections = section_list->GetSize();
-
- for (size_t sect_idx = 0; sect_idx < num_sections &&
- mach_base_file_addr == LLDB_INVALID_ADDRESS;
- ++sect_idx) {
- Section *section = section_list->GetSectionAtIndex(sect_idx).get();
- if (section && section->GetFileSize() > 0 &&
- section->GetFileOffset() == 0 &&
- section->IsThreadSpecific() == false &&
- module_sp.get() == section->GetModule().get()) {
- return section;
- }
- }
- }
+ if (!module_sp)
+ return nullptr;
+ SectionList *section_list = GetSectionList();
+ if (!section_list)
+ return nullptr;
+ const size_t num_sections = section_list->GetSize();
+ for (size_t sect_idx = 0; sect_idx < num_sections; ++sect_idx) {
+ Section *section = section_list->GetSectionAtIndex(sect_idx).get();
+ if (section->GetFileOffset() == 0 && SectionIsLoadable(section))
+ return section;
}
return nullptr;
}
+bool ObjectFileMachO::SectionIsLoadable(const Section *section) {
+ if (!section)
+ return false;
+ const bool is_dsym = (m_header.filetype == MH_DSYM);
+ if (section->GetFileSize() == 0 && !is_dsym)
+ return false;
+ if (section->IsThreadSpecific())
+ return false;
+ if (GetModule().get() != section->GetModule().get())
+ return false;
+ // Be careful with __LINKEDIT and __DWARF segments
+ if (section->GetName() == GetSegmentNameLINKEDIT() ||
+ section->GetName() == GetSegmentNameDWARF()) {
+ // Only map __LINKEDIT and __DWARF if we have an in memory image and
+ // this isn't a kernel binary like a kext or mach_kernel.
+ const bool is_memory_image = (bool)m_process_wp.lock();
+ const Strata strata = GetStrata();
+ if (is_memory_image == false || strata == eStrataKernel)
+ return false;
+ }
+ return true;
+}
+
lldb::addr_t ObjectFileMachO::CalculateSectionLoadAddressForMemoryImage(
- lldb::addr_t mach_header_load_address, const Section *mach_header_section,
+ lldb::addr_t header_load_address, const Section *header_section,
const Section *section) {
ModuleSP module_sp = GetModule();
- if (module_sp && mach_header_section && section &&
- mach_header_load_address != LLDB_INVALID_ADDRESS) {
- lldb::addr_t mach_header_file_addr = mach_header_section->GetFileAddress();
- if (mach_header_file_addr != LLDB_INVALID_ADDRESS) {
- if (section && section->GetFileSize() > 0 &&
- section->IsThreadSpecific() == false &&
- module_sp.get() == section->GetModule().get()) {
- // Ignore __LINKEDIT and __DWARF segments
- if (section->GetName() == GetSegmentNameLINKEDIT()) {
- // Only map __LINKEDIT if we have an in memory image and this isn't a
- // kernel binary like a kext or mach_kernel.
- const bool is_memory_image = (bool)m_process_wp.lock();
- const Strata strata = GetStrata();
- if (is_memory_image == false || strata == eStrataKernel)
- return LLDB_INVALID_ADDRESS;
- }
- return section->GetFileAddress() - mach_header_file_addr +
- mach_header_load_address;
- }
- }
+ if (module_sp && header_section && section &&
+ header_load_address != LLDB_INVALID_ADDRESS) {
+ lldb::addr_t file_addr = header_section->GetFileAddress();
+ if (file_addr != LLDB_INVALID_ADDRESS && SectionIsLoadable(section))
+ return section->GetFileAddress() - file_addr + header_load_address;
}
return LLDB_INVALID_ADDRESS;
}
@@ -5879,22 +6047,10 @@ bool ObjectFileMachO::SetLoadAddress(Target &target, lldb::addr_t value,
// Iterate through the object file sections to find all of the
// sections that size on disk (to avoid __PAGEZERO) and load them
SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx));
- if (section_sp && section_sp->GetFileSize() > 0 &&
- section_sp->IsThreadSpecific() == false &&
- module_sp.get() == section_sp->GetModule().get()) {
- // Ignore __LINKEDIT and __DWARF segments
- if (section_sp->GetName() == GetSegmentNameLINKEDIT()) {
- // Only map __LINKEDIT if we have an in memory image and this
- // isn't a kernel binary like a kext or mach_kernel.
- const bool is_memory_image = (bool)m_process_wp.lock();
- const Strata strata = GetStrata();
- if (is_memory_image == false || strata == eStrataKernel)
- continue;
- }
+ if (SectionIsLoadable(section_sp.get()))
if (target.GetSectionLoadList().SetSectionLoadAddress(
section_sp, section_sp->GetFileAddress() + value))
++num_loaded_sections;
- }
}
} else {
// "value" is the new base address of the mach_header, adjust each
@@ -5933,6 +6089,7 @@ bool ObjectFileMachO::SaveCore(const lldb::ProcessSP &process_sp,
target_triple.getOS() == llvm::Triple::IOS ||
target_triple.getOS() == llvm::Triple::WatchOS ||
target_triple.getOS() == llvm::Triple::TvOS)) {
+ // NEED_BRIDGEOS_TRIPLE target_triple.getOS() == llvm::Triple::BridgeOS)) {
bool make_core = false;
switch (target_arch.GetMachine()) {
case llvm::Triple::aarch64:
@@ -6161,10 +6318,10 @@ bool ObjectFileMachO::SaveCore(const lldb::ProcessSP &process_sp,
File core_file;
std::string core_file_path(outfile.GetPath());
- error = core_file.Open(core_file_path.c_str(),
- File::eOpenOptionWrite |
- File::eOpenOptionTruncate |
- File::eOpenOptionCanCreate);
+ error = FileSystem::Instance().Open(core_file, outfile,
+ File::eOpenOptionWrite |
+ File::eOpenOptionTruncate |
+ File::eOpenOptionCanCreate);
if (error.Success()) {
// Read 1 page at a time
uint8_t bytes[0x1000];
diff --git a/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h b/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
index be64518064b5..196abae807e9 100644
--- a/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
+++ b/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h
@@ -10,16 +10,12 @@
#ifndef liblldb_ObjectFileMachO_h_
#define liblldb_ObjectFileMachO_h_
-// C Includes
-// C++ Includes
-// Other libraries and framework includes
-// Project includes
#include "lldb/Core/Address.h"
#include "lldb/Core/FileSpecList.h"
#include "lldb/Core/RangeMap.h"
+#include "lldb/Host/SafeMachO.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Utility/FileSpec.h"
-#include "lldb/Utility/SafeMachO.h"
#include "lldb/Utility/UUID.h"
//----------------------------------------------------------------------
@@ -96,7 +92,7 @@ public:
void Dump(lldb_private::Stream *s) override;
- bool GetArchitecture(lldb_private::ArchSpec &arch) override;
+ lldb_private::ArchSpec GetArchitecture() override;
bool GetUUID(lldb_private::UUID *uuid) override;
@@ -108,7 +104,7 @@ public:
lldb_private::Address GetEntryPointAddress() override;
- lldb_private::Address GetHeaderAddress() override;
+ lldb_private::Address GetBaseAddress() override;
uint32_t GetNumThreadContexts() override;
@@ -151,10 +147,10 @@ protected:
lldb::offset_t lc_offset, // Offset to the first load command
lldb_private::UUID &uuid);
- static bool GetArchitecture(const llvm::MachO::mach_header &header,
- const lldb_private::DataExtractor &data,
- lldb::offset_t lc_offset,
- lldb_private::ArchSpec &arch);
+ static lldb_private::ArchSpec
+ GetArchitecture(const llvm::MachO::mach_header &header,
+ const lldb_private::DataExtractor &data,
+ lldb::offset_t lc_offset);
// Intended for same-host arm device debugging where lldb needs to
// detect libraries in the shared cache and augment the nlist entries
@@ -196,6 +192,8 @@ protected:
void SanitizeSegmentCommand(llvm::MachO::segment_command_64 &seg_cmd,
uint32_t cmd_idx);
+ bool SectionIsLoadable(const lldb_private::Section *section);
+
llvm::MachO::mach_header m_header;
static const lldb_private::ConstString &GetSegmentNameTEXT();
static const lldb_private::ConstString &GetSegmentNameDATA();
@@ -203,6 +201,7 @@ protected:
static const lldb_private::ConstString &GetSegmentNameDATA_CONST();
static const lldb_private::ConstString &GetSegmentNameOBJC();
static const lldb_private::ConstString &GetSegmentNameLINKEDIT();
+ static const lldb_private::ConstString &GetSegmentNameDWARF();
static const lldb_private::ConstString &GetSectionNameEHFrame();
llvm::MachO::dysymtab_command m_dysymtab;
diff --git a/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp b/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
index b2967f1532ab..d18ff617521f 100644
--- a/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.cpp
+++ b/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());
@@ -488,25 +527,23 @@ bool ObjectFilePECOFF::ParseSectionHeaders(
}
}
- return m_sect_headers.empty() == false;
+ return !m_sect_headers.empty();
}
-bool ObjectFilePECOFF::GetSectionName(std::string &sect_name,
- const section_header_t &sect) {
- if (sect.name[0] == '/') {
- lldb::offset_t stroff = strtoul(&sect.name[1], NULL, 10);
+llvm::StringRef ObjectFilePECOFF::GetSectionName(const section_header_t &sect) {
+ llvm::StringRef hdr_name(sect.name, llvm::array_lengthof(sect.name));
+ hdr_name = hdr_name.split('\0').first;
+ if (hdr_name.consume_front("/")) {
+ lldb::offset_t stroff;
+ if (!to_integer(hdr_name, stroff, 10))
+ return "";
lldb::offset_t string_file_offset =
m_coff_header.symoff + (m_coff_header.nsyms * 18) + stroff;
- const char *name = m_data.GetCStr(&string_file_offset);
- if (name) {
- sect_name = name;
- return true;
- }
-
- return false;
+ if (const char *name = m_data.GetCStr(&string_file_offset))
+ return name;
+ return "";
}
- sect_name = sect.name;
- return true;
+ return hdr_name;
}
//----------------------------------------------------------------------
@@ -663,144 +700,213 @@ bool ObjectFilePECOFF::IsStripped() {
}
void ObjectFilePECOFF::CreateSections(SectionList &unified_section_list) {
- if (!m_sections_ap.get()) {
- m_sections_ap.reset(new SectionList());
+ if (m_sections_ap)
+ return;
+ m_sections_ap.reset(new SectionList());
+ ModuleSP module_sp(GetModule());
+ if (module_sp) {
+ std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
+ const uint32_t nsects = m_sect_headers.size();
ModuleSP module_sp(GetModule());
- if (module_sp) {
- std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex());
- const uint32_t nsects = m_sect_headers.size();
- ModuleSP module_sp(GetModule());
- for (uint32_t idx = 0; idx < nsects; ++idx) {
- std::string sect_name;
- GetSectionName(sect_name, m_sect_headers[idx]);
- ConstString const_sect_name(sect_name.c_str());
- static ConstString g_code_sect_name(".code");
- static ConstString g_CODE_sect_name("CODE");
- static ConstString g_data_sect_name(".data");
- static ConstString g_DATA_sect_name("DATA");
- static ConstString g_bss_sect_name(".bss");
- static ConstString g_BSS_sect_name("BSS");
- static ConstString g_debug_sect_name(".debug");
- static ConstString g_reloc_sect_name(".reloc");
- static ConstString g_stab_sect_name(".stab");
- static ConstString g_stabstr_sect_name(".stabstr");
- static ConstString g_sect_name_dwarf_debug_abbrev(".debug_abbrev");
- static ConstString g_sect_name_dwarf_debug_aranges(".debug_aranges");
- static ConstString g_sect_name_dwarf_debug_frame(".debug_frame");
- static ConstString g_sect_name_dwarf_debug_info(".debug_info");
- static ConstString g_sect_name_dwarf_debug_line(".debug_line");
- static ConstString g_sect_name_dwarf_debug_loc(".debug_loc");
- static ConstString g_sect_name_dwarf_debug_macinfo(".debug_macinfo");
- static ConstString g_sect_name_dwarf_debug_names(".debug_names");
- static ConstString g_sect_name_dwarf_debug_pubnames(".debug_pubnames");
- static ConstString g_sect_name_dwarf_debug_pubtypes(".debug_pubtypes");
- static ConstString g_sect_name_dwarf_debug_ranges(".debug_ranges");
- static ConstString g_sect_name_dwarf_debug_str(".debug_str");
- static ConstString g_sect_name_dwarf_debug_types(".debug_types");
- static ConstString g_sect_name_eh_frame(".eh_frame");
- static ConstString g_sect_name_go_symtab(".gosymtab");
- SectionType section_type = eSectionTypeOther;
- if (m_sect_headers[idx].flags & llvm::COFF::IMAGE_SCN_CNT_CODE &&
- ((const_sect_name == g_code_sect_name) ||
- (const_sect_name == g_CODE_sect_name))) {
- section_type = eSectionTypeCode;
- } else if (m_sect_headers[idx].flags &
- llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA &&
- ((const_sect_name == g_data_sect_name) ||
- (const_sect_name == g_DATA_sect_name))) {
+ for (uint32_t idx = 0; idx < nsects; ++idx) {
+ ConstString const_sect_name(GetSectionName(m_sect_headers[idx]));
+ static ConstString g_code_sect_name(".code");
+ static ConstString g_CODE_sect_name("CODE");
+ static ConstString g_data_sect_name(".data");
+ static ConstString g_DATA_sect_name("DATA");
+ static ConstString g_bss_sect_name(".bss");
+ static ConstString g_BSS_sect_name("BSS");
+ static ConstString g_debug_sect_name(".debug");
+ static ConstString g_reloc_sect_name(".reloc");
+ static ConstString g_stab_sect_name(".stab");
+ static ConstString g_stabstr_sect_name(".stabstr");
+ static ConstString g_sect_name_dwarf_debug_abbrev(".debug_abbrev");
+ static ConstString g_sect_name_dwarf_debug_aranges(".debug_aranges");
+ static ConstString g_sect_name_dwarf_debug_frame(".debug_frame");
+ static ConstString g_sect_name_dwarf_debug_info(".debug_info");
+ static ConstString g_sect_name_dwarf_debug_line(".debug_line");
+ static ConstString g_sect_name_dwarf_debug_loc(".debug_loc");
+ static ConstString g_sect_name_dwarf_debug_loclists(".debug_loclists");
+ static ConstString g_sect_name_dwarf_debug_macinfo(".debug_macinfo");
+ static ConstString g_sect_name_dwarf_debug_names(".debug_names");
+ static ConstString g_sect_name_dwarf_debug_pubnames(".debug_pubnames");
+ static ConstString g_sect_name_dwarf_debug_pubtypes(".debug_pubtypes");
+ static ConstString g_sect_name_dwarf_debug_ranges(".debug_ranges");
+ static ConstString g_sect_name_dwarf_debug_str(".debug_str");
+ static ConstString g_sect_name_dwarf_debug_types(".debug_types");
+ static ConstString g_sect_name_eh_frame(".eh_frame");
+ static ConstString g_sect_name_go_symtab(".gosymtab");
+ SectionType section_type = eSectionTypeOther;
+ if (m_sect_headers[idx].flags & llvm::COFF::IMAGE_SCN_CNT_CODE &&
+ ((const_sect_name == g_code_sect_name) ||
+ (const_sect_name == g_CODE_sect_name))) {
+ section_type = eSectionTypeCode;
+ } else if (m_sect_headers[idx].flags &
+ llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA &&
+ ((const_sect_name == g_data_sect_name) ||
+ (const_sect_name == g_DATA_sect_name))) {
+ if (m_sect_headers[idx].size == 0 && m_sect_headers[idx].offset == 0)
+ section_type = eSectionTypeZeroFill;
+ else
section_type = eSectionTypeData;
- } else if (m_sect_headers[idx].flags &
- llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA &&
- ((const_sect_name == g_bss_sect_name) ||
- (const_sect_name == g_BSS_sect_name))) {
- if (m_sect_headers[idx].size == 0)
- section_type = eSectionTypeZeroFill;
- else
- section_type = eSectionTypeData;
- } else if (const_sect_name == g_debug_sect_name) {
- section_type = eSectionTypeDebug;
- } else if (const_sect_name == g_stabstr_sect_name) {
- section_type = eSectionTypeDataCString;
- } else if (const_sect_name == g_reloc_sect_name) {
- section_type = eSectionTypeOther;
- } else if (const_sect_name == g_sect_name_dwarf_debug_abbrev)
- section_type = eSectionTypeDWARFDebugAbbrev;
- else if (const_sect_name == g_sect_name_dwarf_debug_aranges)
- section_type = eSectionTypeDWARFDebugAranges;
- else if (const_sect_name == g_sect_name_dwarf_debug_frame)
- section_type = eSectionTypeDWARFDebugFrame;
- else if (const_sect_name == g_sect_name_dwarf_debug_info)
- section_type = eSectionTypeDWARFDebugInfo;
- else if (const_sect_name == g_sect_name_dwarf_debug_line)
- section_type = eSectionTypeDWARFDebugLine;
- else if (const_sect_name == g_sect_name_dwarf_debug_loc)
- section_type = eSectionTypeDWARFDebugLoc;
- else if (const_sect_name == g_sect_name_dwarf_debug_macinfo)
- section_type = eSectionTypeDWARFDebugMacInfo;
- else if (const_sect_name == g_sect_name_dwarf_debug_names)
- section_type = eSectionTypeDWARFDebugNames;
- else if (const_sect_name == g_sect_name_dwarf_debug_pubnames)
- section_type = eSectionTypeDWARFDebugPubNames;
- else if (const_sect_name == g_sect_name_dwarf_debug_pubtypes)
- section_type = eSectionTypeDWARFDebugPubTypes;
- else if (const_sect_name == g_sect_name_dwarf_debug_ranges)
- section_type = eSectionTypeDWARFDebugRanges;
- else if (const_sect_name == g_sect_name_dwarf_debug_str)
- section_type = eSectionTypeDWARFDebugStr;
- else if (const_sect_name == g_sect_name_dwarf_debug_types)
- section_type = eSectionTypeDWARFDebugTypes;
- else if (const_sect_name == g_sect_name_eh_frame)
- section_type = eSectionTypeEHFrame;
- else if (const_sect_name == g_sect_name_go_symtab)
- section_type = eSectionTypeGoSymtab;
- else if (m_sect_headers[idx].flags & llvm::COFF::IMAGE_SCN_CNT_CODE) {
- section_type = eSectionTypeCode;
- } else if (m_sect_headers[idx].flags &
- llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA) {
+ } else if (m_sect_headers[idx].flags &
+ llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA &&
+ ((const_sect_name == g_bss_sect_name) ||
+ (const_sect_name == g_BSS_sect_name))) {
+ if (m_sect_headers[idx].size == 0)
+ section_type = eSectionTypeZeroFill;
+ else
+ section_type = eSectionTypeData;
+ } else if (const_sect_name == g_debug_sect_name) {
+ section_type = eSectionTypeDebug;
+ } else if (const_sect_name == g_stabstr_sect_name) {
+ section_type = eSectionTypeDataCString;
+ } else if (const_sect_name == g_reloc_sect_name) {
+ section_type = eSectionTypeOther;
+ } else if (const_sect_name == g_sect_name_dwarf_debug_abbrev)
+ section_type = eSectionTypeDWARFDebugAbbrev;
+ else if (const_sect_name == g_sect_name_dwarf_debug_aranges)
+ section_type = eSectionTypeDWARFDebugAranges;
+ else if (const_sect_name == g_sect_name_dwarf_debug_frame)
+ section_type = eSectionTypeDWARFDebugFrame;
+ else if (const_sect_name == g_sect_name_dwarf_debug_info)
+ section_type = eSectionTypeDWARFDebugInfo;
+ else if (const_sect_name == g_sect_name_dwarf_debug_line)
+ section_type = eSectionTypeDWARFDebugLine;
+ else if (const_sect_name == g_sect_name_dwarf_debug_loc)
+ section_type = eSectionTypeDWARFDebugLoc;
+ else if (const_sect_name == g_sect_name_dwarf_debug_loclists)
+ section_type = eSectionTypeDWARFDebugLocLists;
+ else if (const_sect_name == g_sect_name_dwarf_debug_macinfo)
+ section_type = eSectionTypeDWARFDebugMacInfo;
+ else if (const_sect_name == g_sect_name_dwarf_debug_names)
+ section_type = eSectionTypeDWARFDebugNames;
+ else if (const_sect_name == g_sect_name_dwarf_debug_pubnames)
+ section_type = eSectionTypeDWARFDebugPubNames;
+ else if (const_sect_name == g_sect_name_dwarf_debug_pubtypes)
+ section_type = eSectionTypeDWARFDebugPubTypes;
+ else if (const_sect_name == g_sect_name_dwarf_debug_ranges)
+ section_type = eSectionTypeDWARFDebugRanges;
+ else if (const_sect_name == g_sect_name_dwarf_debug_str)
+ section_type = eSectionTypeDWARFDebugStr;
+ else if (const_sect_name == g_sect_name_dwarf_debug_types)
+ section_type = eSectionTypeDWARFDebugTypes;
+ else if (const_sect_name == g_sect_name_eh_frame)
+ section_type = eSectionTypeEHFrame;
+ else if (const_sect_name == g_sect_name_go_symtab)
+ section_type = eSectionTypeGoSymtab;
+ else if (m_sect_headers[idx].flags & llvm::COFF::IMAGE_SCN_CNT_CODE) {
+ section_type = eSectionTypeCode;
+ } else if (m_sect_headers[idx].flags &
+ llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA) {
+ section_type = eSectionTypeData;
+ } else if (m_sect_headers[idx].flags &
+ llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) {
+ if (m_sect_headers[idx].size == 0)
+ section_type = eSectionTypeZeroFill;
+ else
section_type = eSectionTypeData;
- } else if (m_sect_headers[idx].flags &
- llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) {
- if (m_sect_headers[idx].size == 0)
- section_type = eSectionTypeZeroFill;
- else
- section_type = eSectionTypeData;
- }
-
- // Use a segment ID of the segment index shifted left by 8 so they
- // never conflict with any of the sections.
- SectionSP section_sp(new Section(
- module_sp, // Module to which this section belongs
- this, // Object file to which this section belongs
- idx + 1, // Section ID is the 1 based segment index shifted right by
- // 8 bits as not to collide with any of the 256 section IDs
- // that are possible
- const_sect_name, // Name of this section
- section_type, // This section is a container of other sections.
- m_coff_header_opt.image_base +
- m_sect_headers[idx].vmaddr, // File VM address == addresses as
- // they are found in the object file
- m_sect_headers[idx].vmsize, // VM size in bytes of this section
- m_sect_headers[idx]
- .offset, // Offset to the data for this section in the file
- m_sect_headers[idx]
- .size, // Size in bytes of this section as found in the file
- m_coff_header_opt.sect_alignment, // Section alignment
- m_sect_headers[idx].flags)); // Flags for this section
-
- // section_sp->SetIsEncrypted (segment_is_encrypted);
-
- unified_section_list.AddSection(section_sp);
- m_sections_ap->AddSection(section_sp);
}
+
+ // Use a segment ID of the segment index shifted left by 8 so they
+ // never conflict with any of the sections.
+ SectionSP section_sp(new Section(
+ module_sp, // Module to which this section belongs
+ this, // Object file to which this section belongs
+ idx + 1, // Section ID is the 1 based segment index shifted right by
+ // 8 bits as not to collide with any of the 256 section IDs
+ // that are possible
+ const_sect_name, // Name of this section
+ section_type, // This section is a container of other sections.
+ m_coff_header_opt.image_base +
+ m_sect_headers[idx].vmaddr, // File VM address == addresses as
+ // they are found in the object file
+ m_sect_headers[idx].vmsize, // VM size in bytes of this section
+ m_sect_headers[idx]
+ .offset, // Offset to the data for this section in the file
+ m_sect_headers[idx]
+ .size, // Size in bytes of this section as found in the file
+ m_coff_header_opt.sect_alignment, // Section alignment
+ m_sect_headers[idx].flags)); // Flags for this section
+
+ // section_sp->SetIsEncrypted (segment_is_encrypted);
+
+ unified_section_list.AddSection(section_sp);
+ m_sections_ap->AddSection(section_sp);
}
}
}
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<128> 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() {
@@ -811,12 +917,12 @@ lldb_private::Address ObjectFilePECOFF::GetEntryPointAddress() {
return m_entry_point_address;
SectionList *section_list = GetSectionList();
- addr_t offset = m_coff_header_opt.entry;
+ addr_t file_addr = m_coff_header_opt.entry + m_coff_header_opt.image_base;
if (!section_list)
- m_entry_point_address.SetOffset(offset);
+ m_entry_point_address.SetOffset(file_addr);
else
- m_entry_point_address.ResolveAddressUsingFileSections(offset, section_list);
+ m_entry_point_address.ResolveAddressUsingFileSections(file_addr, section_list);
return m_entry_point_address;
}
@@ -834,8 +940,7 @@ void ObjectFilePECOFF::Dump(Stream *s) {
s->Indent();
s->PutCString("ObjectFilePECOFF");
- ArchSpec header_arch;
- GetArchitecture(header_arch);
+ ArchSpec header_arch = GetArchitecture();
*s << ", file = '" << m_file
<< "', arch = " << header_arch.GetArchitectureName() << "\n";
@@ -857,6 +962,9 @@ void ObjectFilePECOFF::Dump(Stream *s) {
s->EOL();
DumpSectionHeaders(s);
s->EOL();
+
+ DumpDependentModules(s);
+ s->EOL();
}
}
@@ -974,8 +1082,7 @@ void ObjectFilePECOFF::DumpOptCOFFHeader(Stream *s,
//----------------------------------------------------------------------
void ObjectFilePECOFF::DumpSectionHeader(Stream *s,
const section_header_t &sh) {
- std::string name;
- GetSectionName(name, sh);
+ std::string name = GetSectionName(sh);
s->Printf("%-16s 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x 0x%4.4x "
"0x%4.4x 0x%8.8x\n",
name.c_str(), sh.vmaddr, sh.vmsize, sh.offset, sh.size, sh.reloff,
@@ -1004,6 +1111,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:
@@ -1019,9 +1142,11 @@ bool ObjectFilePECOFF::IsWindowsSubsystem() {
}
}
-bool ObjectFilePECOFF::GetArchitecture(ArchSpec &arch) {
+ArchSpec ObjectFilePECOFF::GetArchitecture() {
uint16_t machine = m_coff_header.machine;
switch (machine) {
+ default:
+ break;
case llvm::COFF::IMAGE_FILE_MACHINE_AMD64:
case llvm::COFF::IMAGE_FILE_MACHINE_I386:
case llvm::COFF::IMAGE_FILE_MACHINE_POWERPC:
@@ -1029,14 +1154,13 @@ bool ObjectFilePECOFF::GetArchitecture(ArchSpec &arch) {
case llvm::COFF::IMAGE_FILE_MACHINE_ARM:
case llvm::COFF::IMAGE_FILE_MACHINE_ARMNT:
case llvm::COFF::IMAGE_FILE_MACHINE_THUMB:
+ ArchSpec arch;
arch.SetArchitecture(eArchTypeCOFF, machine, LLDB_INVALID_CPUTYPE,
IsWindowsSubsystem() ? llvm::Triple::Win32
: llvm::Triple::UnknownOS);
- return true;
- default:
- break;
+ return arch;
}
- return false;
+ return ArchSpec();
}
ObjectFile::Type ObjectFilePECOFF::CalculateType() {
@@ -1050,6 +1174,7 @@ ObjectFile::Type ObjectFilePECOFF::CalculateType() {
}
ObjectFile::Strata ObjectFilePECOFF::CalculateStrata() { return eStrataUser; }
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
diff --git a/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h b/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
index d8a94e19d34f..9fd313f26a0a 100644
--- a/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
+++ b/source/Plugins/ObjectFile/PECOFF/ObjectFilePECOFF.h
@@ -10,13 +10,10 @@
#ifndef liblldb_ObjectFilePECOFF_h_
#define liblldb_ObjectFilePECOFF_h_
-// C Includes
-// C++ Includes
#include <vector>
-// Other libraries and framework includes
-// Project includes
#include "lldb/Symbol/ObjectFile.h"
+#include "llvm/Object/Binary.h"
class ObjectFilePECOFF : public lldb_private::ObjectFile {
public:
@@ -113,7 +110,7 @@ public:
void Dump(lldb_private::Stream *s) override;
- bool GetArchitecture(lldb_private::ArchSpec &arch) override;
+ lldb_private::ArchSpec GetArchitecture() override;
bool GetUUID(lldb_private::UUID *uuid) override;
@@ -261,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,
@@ -269,19 +268,27 @@ protected:
const coff_opt_header_t &header);
void DumpSectionHeaders(lldb_private::Stream *s);
void DumpSectionHeader(lldb_private::Stream *s, const section_header_t &sh);
- bool GetSectionName(std::string &sect_name, const section_header_t &sect);
+ void DumpDependentModules(lldb_private::Stream *s);
+
+ llvm::StringRef GetSectionName(const section_header_t &sect);
typedef std::vector<section_header_t> SectionHeaderColl;
typedef SectionHeaderColl::iterator SectionHeaderCollIter;
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_
diff --git a/source/Plugins/ObjectFile/PECOFF/WindowsMiniDump.cpp b/source/Plugins/ObjectFile/PECOFF/WindowsMiniDump.cpp
index d6553f6e5142..e77888c871b5 100644
--- a/source/Plugins/ObjectFile/PECOFF/WindowsMiniDump.cpp
+++ b/source/Plugins/ObjectFile/PECOFF/WindowsMiniDump.cpp
@@ -16,7 +16,7 @@
#ifdef _WIN32
#include "lldb/Host/windows/windows.h"
-#include <dbghelp.h> // for MiniDumpWriteDump
+#include <dbghelp.h>
#endif
namespace lldb_private {