summaryrefslogtreecommitdiff
path: root/gnu
diff options
context:
space:
mode:
authorPatrick Wildt <patrick@cvs.openbsd.org>2017-10-04 20:27:40 +0000
committerPatrick Wildt <patrick@cvs.openbsd.org>2017-10-04 20:27:40 +0000
commit05276a939599b1c2eaf9b68e1c2c3830c2291991 (patch)
tree8ff3a0ab306cd5d8bf56892b05029f7e5a0fa780 /gnu
parentea30ef648a92850407f8b33b67c78a4948cd9eb9 (diff)
Import LLVM 5.0.0 release including clang, lld and lldb.
Diffstat (limited to 'gnu')
-rw-r--r--gnu/llvm/tools/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp1288
1 files changed, 607 insertions, 681 deletions
diff --git a/gnu/llvm/tools/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/gnu/llvm/tools/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 9a6563afa0a..3b33cf1601f 100644
--- a/gnu/llvm/tools/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/gnu/llvm/tools/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -13,28 +13,24 @@
#include <cassert>
#include <unordered_map>
+#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/FileSpecList.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
-#include "lldb/Core/RangeMap.h"
#include "lldb/Core/Section.h"
-#include "lldb/Host/FileSystem.h"
#include "lldb/Symbol/DWARFCallFrameInfo.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
-#include "lldb/Utility/ArchSpec.h"
-#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/DataBufferLLVM.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/Status.h"
#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"
#include "llvm/Support/ARMBuildAttributes.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -116,7 +112,7 @@ const elf_word LLDB_NT_GNU_ABI_OS_SOLARIS = 0x02;
//===----------------------------------------------------------------------===//
/// @class ELFRelocation
-/// Generic wrapper for ELFRel and ELFRela.
+/// @brief Generic wrapper for ELFRel and ELFRela.
///
/// This helper class allows us to parse both ELFRel and ELFRela relocation
/// entries in a generic manner.
@@ -238,17 +234,16 @@ 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)
return false;
- // The name field is required to be nul-terminated, and n_namesz includes the
- // terminating nul in observed implementations (contrary to the ELF-64 spec).
- // A special case is needed for cores generated by some older Linux versions,
- // which write a note named "CORE" without a nul terminator and n_namesz = 4.
+ // The name field is required to be nul-terminated, and n_namesz
+ // includes the terminating nul in observed implementations (contrary
+ // to the ELF-64 spec). A special case is needed for cores generated
+ // by some older Linux versions, which write a note named "CORE"
+ // without a nul terminator and n_namesz = 4.
if (n_namesz == 4) {
char buf[4];
if (data.ExtractBytes(*offset, 4, data.GetByteOrder(), buf) != 4)
@@ -299,8 +294,7 @@ static uint32_t mipsVariantFromElfFlags (const elf::ELFHeader &header) {
uint32_t arch_variant = ArchSpec::eMIPSSubType_unknown;
uint32_t fileclass = header.e_ident[EI_CLASS];
- // If there aren't any elf flags available (e.g core elf file) then return
- // default
+ // If there aren't any elf flags available (e.g core elf file) then return default
// 32 or 64 bit arch (without any architecture revision) based on object file's class.
if (header.e_type == ET_CORE) {
switch (fileclass) {
@@ -410,7 +404,8 @@ ObjectFile *ObjectFileELF::CreateInstance(const lldb::ModuleSP &module_sp,
lldb::offset_t file_offset,
lldb::offset_t length) {
if (!data_sp) {
- data_sp = MapFileData(*file, length, file_offset);
+ data_sp =
+ DataBufferLLVM::CreateSliceFromPath(file->GetPath(), length, file_offset);
if (!data_sp)
return nullptr;
data_offset = 0;
@@ -427,7 +422,8 @@ ObjectFile *ObjectFileELF::CreateInstance(const lldb::ModuleSP &module_sp,
// 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);
+ data_sp =
+ DataBufferLLVM::CreateSliceFromPath(file->GetPath(), length, file_offset);
if (!data_sp)
return nullptr;
data_offset = 0;
@@ -438,8 +434,9 @@ 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 = objfile_ap->GetArchitecture();
- if (spec && objfile_ap->SetModulesArchitecture(spec))
+ ArchSpec spec;
+ if (objfile_ap->GetArchitecture(spec) &&
+ objfile_ap->SetModulesArchitecture(spec))
return objfile_ap.release();
}
@@ -454,10 +451,11 @@ ObjectFile *ObjectFileELF::CreateMemoryInstance(
if (ELFHeader::MagicBytesMatch(magic)) {
unsigned address_size = ELFHeader::AddressSizeInBytes(magic);
if (address_size == 4 || address_size == 8) {
- std::unique_ptr<ObjectFileELF> objfile_ap(
+ std::auto_ptr<ObjectFileELF> objfile_ap(
new ObjectFileELF(module_sp, data_sp, process_sp, header_addr));
- ArchSpec spec = objfile_ap->GetArchitecture();
- if (spec && objfile_ap->SetModulesArchitecture(spec))
+ ArchSpec spec;
+ if (objfile_ap->GetArchitecture(spec) &&
+ objfile_ap->SetModulesArchitecture(spec))
return objfile_ap.release();
}
}
@@ -541,18 +539,19 @@ 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 (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;
+ 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;
DataExtractor segment_data;
if (segment_data.SetData(object_data, ph_offset, ph_size) != ph_size) {
- // The ELF program header contained incorrect data, probably corefile
- // is incomplete or corrupted.
+ // The ELF program header contained incorrect data,
+ // probably corefile is incomplete or corrupted.
break;
}
@@ -597,8 +596,8 @@ static const char *OSABIAsCString(unsigned char osabi_byte) {
//
// WARNING : This function is being deprecated
-// It's functionality has moved to ArchSpec::SetArchitecture This function is
-// only being kept to validate the move.
+// It's functionality has moved to ArchSpec::SetArchitecture
+// This function is only being kept to validate the move.
//
// TODO : Remove this function
static bool GetOsFromOSABI(unsigned char osabi_byte,
@@ -676,16 +675,31 @@ size_t ObjectFileELF::GetModuleSpecifications(
__FUNCTION__, file.GetPath().c_str());
}
- data_sp = MapFileData(file, -1, file_offset);
- if (data_sp)
- data.SetData(data_sp);
- // In case there is header extension in the section #0, the header we
- // parsed above could have sentinel values for e_phnum, e_shnum, and
- // e_shstrndx. In this case we need to reparse the header with a
- // bigger data source to get the actual values.
- if (header.HasHeaderExtension()) {
- lldb::offset_t header_offset = data_offset;
- header.Parse(data, &header_offset);
+ // In case there is header extension in the section #0, the header
+ // we parsed above could have sentinel values for e_phnum, e_shnum,
+ // and e_shstrndx. In this case we need to reparse the header
+ // with a bigger data source to get the actual values.
+ size_t section_header_end = header.e_shoff + header.e_shentsize;
+ if (header.HasHeaderExtension() &&
+ section_header_end > data_sp->GetByteSize()) {
+ data_sp = DataBufferLLVM::CreateSliceFromPath(
+ file.GetPath(), section_header_end, file_offset);
+ if (data_sp) {
+ data.SetData(data_sp);
+ lldb::offset_t header_offset = data_offset;
+ header.Parse(data, &header_offset);
+ }
+ }
+
+ // Try to get the UUID from the section list. Usually that's at the
+ // end, so map the file in if we don't have it already.
+ section_header_end =
+ header.e_shoff + header.e_shnum * header.e_shentsize;
+ if (section_header_end > data_sp->GetByteSize()) {
+ data_sp = DataBufferLLVM::CreateSliceFromPath(
+ file.GetPath(), section_header_end, file_offset);
+ if (data_sp)
+ data.SetData(data_sp);
}
uint32_t gnu_debuglink_crc = 0;
@@ -715,35 +729,61 @@ size_t ObjectFileELF::GetModuleSpecifications(
func_cat,
"Calculating module crc32 %s with size %" PRIu64 " KiB",
file.GetLastPathComponent().AsCString(),
- (FileSystem::Instance().GetByteSize(file) - file_offset) /
- 1024);
+ (file.GetByteSize() - file_offset) / 1024);
// For core files - which usually don't happen to have a
// gnu_debuglink, and are pretty bulky - calculating whole
// contents crc32 would be too much of luxury. Thus we will need
// to fallback to something simpler.
if (header.e_type == llvm::ELF::ET_CORE) {
+ size_t program_headers_end =
+ header.e_phoff + header.e_phnum * header.e_phentsize;
+ if (program_headers_end > data_sp->GetByteSize()) {
+ data_sp = DataBufferLLVM::CreateSliceFromPath(
+ file.GetPath(), program_headers_end, file_offset);
+ if (data_sp)
+ data.SetData(data_sp);
+ }
ProgramHeaderColl program_headers;
GetProgramHeaderInfo(program_headers, data, header);
+ size_t segment_data_end = 0;
+ for (ProgramHeaderCollConstIter I = program_headers.begin();
+ I != program_headers.end(); ++I) {
+ segment_data_end = std::max<unsigned long long>(
+ I->p_offset + I->p_filesz, segment_data_end);
+ }
+
+ if (segment_data_end > data_sp->GetByteSize()) {
+ data_sp = DataBufferLLVM::CreateSliceFromPath(
+ file.GetPath(), segment_data_end, file_offset);
+ if (data_sp)
+ data.SetData(data_sp);
+ }
+
core_notes_crc =
CalculateELFNotesSegmentsCRC32(program_headers, data);
} else {
- gnu_debuglink_crc = calc_gnu_debuglink_crc32(
- data.GetDataStart(), data.GetByteSize());
+ // Need to map entire file into memory to calculate the crc.
+ data_sp = DataBufferLLVM::CreateSliceFromPath(file.GetPath(), -1,
+ file_offset);
+ if (data_sp) {
+ data.SetData(data_sp);
+ gnu_debuglink_crc = calc_gnu_debuglink_crc32(
+ data.GetDataStart(), data.GetByteSize());
+ }
}
}
- using u32le = llvm::support::ulittle32_t;
if (gnu_debuglink_crc) {
// Use 4 bytes of crc from the .gnu_debuglink section.
- u32le data(gnu_debuglink_crc);
- uuid = UUID::fromData(&data, sizeof(data));
+ uint32_t uuidt[4] = {gnu_debuglink_crc, 0, 0, 0};
+ uuid.SetBytes(uuidt, sizeof(uuidt));
} else if (core_notes_crc) {
// Use 8 bytes - first 4 bytes for *magic* prefix, mainly to make
- // it look different form .gnu_debuglink crc followed by 4 bytes
- // of note segments crc.
- u32le data[] = {u32le(g_core_uuid_magic), u32le(core_notes_crc)};
- uuid = UUID::fromData(data, sizeof(data));
+ // it look different form
+ // .gnu_debuglink crc followed by 4 bytes of note segments crc.
+ uint32_t uuidt[4] = {g_core_uuid_magic, core_notes_crc, 0, 0};
+ uuid.SetBytes(uuidt, sizeof(uuidt));
}
}
@@ -806,30 +846,42 @@ bool ObjectFileELF::SetLoadAddress(Target &target, lldb::addr_t value,
SectionList *section_list = GetSectionList();
if (section_list) {
if (!value_is_offset) {
- addr_t base = GetBaseAddress().GetFileAddress();
- if (base == LLDB_INVALID_ADDRESS)
+ 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)
return false;
- value -= base;
}
const size_t num_sections = section_list->GetSize();
size_t sect_idx = 0;
for (sect_idx = 0; sect_idx < num_sections; ++sect_idx) {
- // Iterate through the object file sections to find all of the sections
- // that have SHF_ALLOC in their flag bits.
+ // 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->Test(SHF_ALLOC) ||
- section_sp->GetType() == eSectionTypeContainer) {
+ if (section_sp && section_sp->Test(SHF_ALLOC)) {
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
- // address already specified
+ // address
+ // already specified
if (section_sp->GetType() != eSectionTypeAbsoluteAddress)
load_addr += value;
// On 32-bit systems the load address have to fit into 4 bytes. The
- // rest of the bytes are the overflow from the addition.
+ // rest of
+ // the bytes are the overflow from the addition.
if (GetAddressByteSize() == 4)
load_addr &= 0xFFFFFFFF;
@@ -859,23 +911,24 @@ uint32_t ObjectFileELF::GetAddressByteSize() const {
AddressClass ObjectFileELF::GetAddressClass(addr_t file_addr) {
Symtab *symtab = GetSymtab();
if (!symtab)
- return AddressClass::eUnknown;
+ return eAddressClassUnknown;
- // The address class is determined based on the symtab. Ask it from the
- // object file what contains the symtab information.
+ // The address class is determined based on the symtab. Ask it from the object
+ // file what
+ // contains the symtab information.
ObjectFile *symtab_objfile = symtab->GetObjectFile();
if (symtab_objfile != nullptr && symtab_objfile != this)
return symtab_objfile->GetAddressClass(file_addr);
auto res = ObjectFile::GetAddressClass(file_addr);
- if (res != AddressClass::eCode)
+ if (res != eAddressClassCode)
return res;
auto ub = m_address_class_map.upper_bound(file_addr);
if (ub == m_address_class_map.begin()) {
- // No entry in the address class map before the address. Return default
- // address class for an address in a code section.
- return AddressClass::eCode;
+ // No entry in the address class map before the address. Return
+ // default address class for an address in a code section.
+ return eAddressClassCode;
}
// Move iterator to the address class entry preceding address
@@ -885,11 +938,11 @@ AddressClass ObjectFileELF::GetAddressClass(addr_t file_addr) {
}
size_t ObjectFileELF::SectionIndex(const SectionHeaderCollIter &I) {
- return std::distance(m_section_headers.begin(), I);
+ return std::distance(m_section_headers.begin(), I) + 1u;
}
size_t ObjectFileELF::SectionIndex(const SectionHeaderCollConstIter &I) const {
- return std::distance(m_section_headers.begin(), I);
+ return std::distance(m_section_headers.begin(), I) + 1u;
}
bool ObjectFileELF::ParseHeader() {
@@ -903,7 +956,6 @@ bool ObjectFileELF::GetUUID(lldb_private::UUID *uuid) {
if (!ParseSectionHeaders() && GetType() != ObjectFile::eTypeCoreFile)
return false;
- using u32le = llvm::support::ulittle32_t;
if (m_uuid.IsValid()) {
// We have the full build id uuid.
*uuid = m_uuid;
@@ -917,11 +969,11 @@ bool ObjectFileELF::GetUUID(lldb_private::UUID *uuid) {
core_notes_crc = CalculateELFNotesSegmentsCRC32(m_program_headers, m_data);
if (core_notes_crc) {
- // Use 8 bytes - first 4 bytes for *magic* prefix, mainly to make it look
- // different form .gnu_debuglink crc - followed by 4 bytes of note
+ // Use 8 bytes - first 4 bytes for *magic* prefix, mainly to make it
+ // look different form .gnu_debuglink crc - followed by 4 bytes of note
// segments crc.
- u32le data[] = {u32le(g_core_uuid_magic), u32le(core_notes_crc)};
- m_uuid = UUID::fromData(data, sizeof(data));
+ uint32_t uuidt[4] = {g_core_uuid_magic, core_notes_crc, 0, 0};
+ m_uuid.SetBytes(uuidt, sizeof(uuidt));
}
} else {
if (!m_gnu_debuglink_crc)
@@ -929,8 +981,8 @@ bool ObjectFileELF::GetUUID(lldb_private::UUID *uuid) {
calc_gnu_debuglink_crc32(m_data.GetDataStart(), m_data.GetByteSize());
if (m_gnu_debuglink_crc) {
// Use 4 bytes of crc from the .gnu_debuglink section.
- u32le data(m_gnu_debuglink_crc);
- m_uuid = UUID::fromData(&data, sizeof(data));
+ uint32_t uuidt[4] = {m_gnu_debuglink_crc, 0, 0, 0};
+ m_uuid.SetBytes(uuidt, sizeof(uuidt));
}
}
@@ -946,7 +998,7 @@ lldb_private::FileSpecList ObjectFileELF::GetDebugSymbolFilePaths() {
FileSpecList file_spec_list;
if (!m_gnu_debuglink_file.empty()) {
- FileSpec file_spec(m_gnu_debuglink_file);
+ FileSpec file_spec(m_gnu_debuglink_file, false);
file_spec_list.Append(file_spec);
}
return file_spec_list;
@@ -988,8 +1040,8 @@ Address ObjectFileELF::GetImageInfoAddress(Target *target) {
ELFDynamic &symbol = m_dynamic_symbols[i];
if (symbol.d_tag == DT_DEBUG) {
- // Compute the offset as the number of previous entries plus the size of
- // d_tag.
+ // Compute the offset as the number of previous entries plus the
+ // size of d_tag.
addr_t offset = i * dynsym_hdr->sh_entsize + GetAddressByteSize();
return Address(dynsym_section_sp, offset);
}
@@ -1048,18 +1100,6 @@ 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
//----------------------------------------------------------------------
@@ -1089,7 +1129,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).get();
+ Section *dynstr = section_list->FindSectionByID(header->sh_link + 1).get();
if (!dynstr)
return 0;
@@ -1112,9 +1152,7 @@ size_t ObjectFileELF::ParseDependentModules() {
uint32_t str_index = static_cast<uint32_t>(symbol.d_val);
const char *lib_name = dynstr_data.PeekCStr(str_index);
- FileSpec file_spec(lib_name);
- FileSystem::Instance().Resolve(file_spec);
- m_filespec_ap->Append(file_spec);
+ m_filespec_ap->Append(FileSpec(lib_name, true));
}
}
@@ -1148,7 +1186,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))
+ if (program_headers[idx].Parse(data, &offset) == false)
break;
}
@@ -1161,8 +1199,8 @@ size_t ObjectFileELF::GetProgramHeaderInfo(ProgramHeaderColl &program_headers,
//----------------------------------------------------------------------
// ParseProgramHeaders
//----------------------------------------------------------------------
-bool ObjectFileELF::ParseProgramHeaders() {
- return GetProgramHeaderInfo(m_program_headers, m_data, m_header) != 0;
+size_t ObjectFileELF::ParseProgramHeaders() {
+ return GetProgramHeaderInfo(m_program_headers, m_data, m_header);
}
lldb_private::Status
@@ -1282,16 +1320,18 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,
// Only bother processing this if we don't already have the uuid set.
if (!uuid.IsValid()) {
// 16 bytes is UUID|MD5, 20 bytes is SHA1. Other linkers may produce a
- // build-id of a different length. Accept it as long as it's at least
- // 4 bytes as it will be better than our own crc32.
- if (note.n_descsz >= 4) {
- if (const uint8_t *buf = data.PeekData(offset, note.n_descsz)) {
- // Save the build id as the UUID for the module.
- uuid = UUID::fromData(buf, note.n_descsz);
- } else {
+ // build-id of a different
+ // length. Accept it as long as it's at least 4 bytes as it will be
+ // better than our own crc32.
+ if (note.n_descsz >= 4 && note.n_descsz <= 20) {
+ uint8_t uuidbuf[20];
+ if (data.GetU8(&offset, &uuidbuf, note.n_descsz) == nullptr) {
error.SetErrorString("failed to read GNU_BUILD_ID note payload");
return error;
}
+
+ // Save the build id as the UUID for the module.
+ uuid.SetBytes(uuidbuf, note.n_descsz);
}
}
break;
@@ -1334,8 +1374,8 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,
arch_spec.GetTriple().setVendor(llvm::Triple::VendorType::CSR);
// TODO At some point the description string could be processed.
- // It could provide a steer towards the kalimba variant which this ELF
- // targets.
+ // It could provide a steer towards the kalimba variant which
+ // this ELF targets.
if (note.n_descsz) {
const char *cstr =
data.GetCStr(&offset, llvm::alignTo(note.n_descsz, 4));
@@ -1350,28 +1390,36 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,
// register info
arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);
} else if (note.n_name == LLDB_NT_OWNER_CORE) {
- // Parse the NT_FILE to look for stuff in paths to shared libraries As
- // the contents look like this in a 64 bit ELF core file: count =
- // 0x000000000000000a (10) page_size = 0x0000000000001000 (4096) Index
- // start end file_ofs path =====
- // ------------------ ------------------ ------------------
- // ------------------------------------- [ 0] 0x0000000000400000
- // 0x0000000000401000 0x0000000000000000 /tmp/a.out [ 1]
- // 0x0000000000600000 0x0000000000601000 0x0000000000000000 /tmp/a.out [
- // 2] 0x0000000000601000 0x0000000000602000 0x0000000000000001 /tmp/a.out
+ // Parse the NT_FILE to look for stuff in paths to shared libraries
+ // As the contents look like this in a 64 bit ELF core file:
+ // count = 0x000000000000000a (10)
+ // page_size = 0x0000000000001000 (4096)
+ // Index start end file_ofs path
+ // ===== ------------------ ------------------ ------------------
+ // -------------------------------------
+ // [ 0] 0x0000000000400000 0x0000000000401000 0x0000000000000000
+ // /tmp/a.out
+ // [ 1] 0x0000000000600000 0x0000000000601000 0x0000000000000000
+ // /tmp/a.out
+ // [ 2] 0x0000000000601000 0x0000000000602000 0x0000000000000001
+ // /tmp/a.out
// [ 3] 0x00007fa79c9ed000 0x00007fa79cba8000 0x0000000000000000
- // /lib/x86_64-linux-gnu/libc-2.19.so [ 4] 0x00007fa79cba8000
- // 0x00007fa79cda7000 0x00000000000001bb /lib/x86_64-linux-
- // gnu/libc-2.19.so [ 5] 0x00007fa79cda7000 0x00007fa79cdab000
- // 0x00000000000001ba /lib/x86_64-linux-gnu/libc-2.19.so [ 6]
- // 0x00007fa79cdab000 0x00007fa79cdad000 0x00000000000001be /lib/x86_64
- // -linux-gnu/libc-2.19.so [ 7] 0x00007fa79cdb2000 0x00007fa79cdd5000
- // 0x0000000000000000 /lib/x86_64-linux-gnu/ld-2.19.so [ 8]
- // 0x00007fa79cfd4000 0x00007fa79cfd5000 0x0000000000000022 /lib/x86_64
- // -linux-gnu/ld-2.19.so [ 9] 0x00007fa79cfd5000 0x00007fa79cfd6000
- // 0x0000000000000023 /lib/x86_64-linux-gnu/ld-2.19.so In the 32 bit ELFs
- // the count, page_size, start, end, file_ofs are uint32_t For reference:
- // see readelf source code (in binutils).
+ // /lib/x86_64-linux-gnu/libc-2.19.so
+ // [ 4] 0x00007fa79cba8000 0x00007fa79cda7000 0x00000000000001bb
+ // /lib/x86_64-linux-gnu/libc-2.19.so
+ // [ 5] 0x00007fa79cda7000 0x00007fa79cdab000 0x00000000000001ba
+ // /lib/x86_64-linux-gnu/libc-2.19.so
+ // [ 6] 0x00007fa79cdab000 0x00007fa79cdad000 0x00000000000001be
+ // /lib/x86_64-linux-gnu/libc-2.19.so
+ // [ 7] 0x00007fa79cdb2000 0x00007fa79cdd5000 0x0000000000000000
+ // /lib/x86_64-linux-gnu/ld-2.19.so
+ // [ 8] 0x00007fa79cfd4000 0x00007fa79cfd5000 0x0000000000000022
+ // /lib/x86_64-linux-gnu/ld-2.19.so
+ // [ 9] 0x00007fa79cfd5000 0x00007fa79cfd6000 0x0000000000000023
+ // /lib/x86_64-linux-gnu/ld-2.19.so
+ // In the 32 bit ELFs the count, page_size, start, end, file_ofs are
+ // uint32_t
+ // For reference: see readelf source code (in binutils).
if (note.n_type == NT_FILE) {
uint64_t count = data.GetAddress(&offset);
const char *cstr;
@@ -1395,14 +1443,15 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,
}
if (arch_spec.IsMIPS() &&
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);
+ // 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);
}
}
- // Calculate the offset of the next note just in case "offset" has been
- // used to poke at the contents of the note data
+ // Calculate the offset of the next note just in case "offset" has been used
+ // to poke at the contents of the note data
offset = note_offset + note.GetByteSize();
}
@@ -1501,13 +1550,14 @@ 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
- // might be not enough: for example a shared library might not have any
- // notes at all and have EI_OSABI flag set to System V, as result the OS
- // will be set to UnknownOS.
+
+ // 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 might be not enough: for example
+ // a shared library might not have any notes at all
+ // and have EI_OSABI flag set to System V,
+ // as result the OS will be set to UnknownOS.
GetOsFromOSABI(header.e_ident[EI_OSABI], ostype);
spec_ostype = arch_spec.GetTriple().getOS();
assert(spec_ostype == ostype);
@@ -1560,7 +1610,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))
+ if (section_headers[idx].Parse(sh_data, &offset) == false)
break;
}
if (idx < section_headers.size())
@@ -1708,6 +1758,27 @@ 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('@');
@@ -1725,10 +1796,10 @@ size_t ObjectFileELF::ParseSectionHeaders() {
const ObjectFileELF::ELFSectionHeaderInfo *
ObjectFileELF::GetSectionHeaderByIndex(lldb::user_id_t id) {
- if (!ParseSectionHeaders())
+ if (!id || !ParseSectionHeaders())
return NULL;
- if (id < m_section_headers.size())
+ if (--id < m_section_headers.size())
return &m_section_headers[id];
return NULL;
@@ -1743,285 +1814,243 @@ lldb::user_id_t ObjectFileELF::GetSectionIndexByName(const char *name) {
return 0;
}
-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;
- }
-}
-
-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;
-}
-
-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;
-}
-
-namespace {
-
-using VMRange = lldb_private::Range<addr_t, addr_t>;
-
-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) {}
+void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
+ if (!m_sections_ap.get() && ParseSectionHeaders()) {
+ m_sections_ap.reset(new SectionList());
+
+ 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_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_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_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");
+
+ 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_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_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_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;
+
+ 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;
+ }
- 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 (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);
+ }
- 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;
+ 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);
+ 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.
+ header.sh_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);
}
- 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 (m_sections_ap.get()) {
+ if (GetType() == eTypeDebugInfo) {
+ static const SectionType g_sections[] = {
+ eSectionTypeDWARFDebugAbbrev, eSectionTypeDWARFDebugAddr,
+ eSectionTypeDWARFDebugAranges, eSectionTypeDWARFDebugFrame,
+ eSectionTypeDWARFDebugInfo, eSectionTypeDWARFDebugLine,
+ eSectionTypeDWARFDebugLoc, eSectionTypeDWARFDebugMacInfo,
+ eSectionTypeDWARFDebugPubNames, eSectionTypeDWARFDebugPubTypes,
+ eSectionTypeDWARFDebugRanges, eSectionTypeDWARFDebugStr,
+ eSectionTypeDWARFDebugStrOffsets, eSectionTypeELFSymbolTable,
+ };
+ SectionList *elf_section_list = m_sections_ap.get();
+ for (size_t idx = 0; idx < sizeof(g_sections) / sizeof(g_sections[0]);
+ ++idx) {
+ SectionType section_type = g_sections[idx];
+ SectionSP section_sp(
+ elf_section_list->FindSectionByType(section_type, true));
+ if (section_sp) {
+ SectionSP module_section_sp(
+ unified_section_list.FindSectionByType(section_type, true));
+ if (module_section_sp)
+ unified_section_list.ReplaceSection(module_section_sp->GetID(),
+ section_sp);
+ else
+ unified_section_list.AddSection(section_sp);
+ }
}
+ } else {
+ unified_section_list = *m_sections_ap;
}
- 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
- // unified section list.
- if (GetType() != eTypeDebugInfo)
- unified_section_list = *m_sections_ap;
}
// Find the arm/aarch64 mapping symbol character in the given symbol name.
-// Mapping symbols have the form of "$<char>[.<any>]*". Additionally we
-// recognize cases when the mapping symbol prefixed by an arbitrary string
-// because if a symbol prefix added to each symbol in the object file with
+// Mapping symbols have the
+// form of "$<char>[.<any>]*". Additionally we recognize cases when the mapping
+// symbol prefixed by
+// an arbitrary string because if a symbol prefix added to each symbol in the
+// object file with
// objcopy then the mapping symbols are also prefixed.
static char FindArmAarch64MappingSymbol(const char *symbol_name) {
if (!symbol_name)
@@ -2063,32 +2092,37 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
static ConstString opd_section_name(".opd"); // For ppc64
// On Android the oatdata and the oatexec symbols in the oat and odex files
- // covers the full .text section what causes issues with displaying unusable
- // symbol name to the user and very slow unwinding speed because the
- // instruction emulation based unwind plans try to emulate all instructions
- // in these symbols. Don't add these symbols to the symbol list as they have
- // no use for the debugger and they are causing a lot of trouble. Filtering
- // can't be restricted to Android because this special object file don't
- // contain the note section specifying the environment to Android but the
- // custom extension and file name makes it highly unlikely that this will
- // collide with anything else.
+ // covers the full
+ // .text section what causes issues with displaying unusable symbol name to
+ // the user and very
+ // slow unwinding speed because the instruction emulation based unwind plans
+ // try to emulate all
+ // instructions in these symbols. Don't add these symbols to the symbol list
+ // as they have no
+ // use for the debugger and they are causing a lot of trouble.
+ // Filtering can't be restricted to Android because this special object file
+ // don't contain the
+ // note section specifying the environment to Android but the custom extension
+ // and file name
+ // makes it highly unlikely that this will collide with anything else.
ConstString file_extension = m_file.GetFileNameExtension();
- bool skip_oatdata_oatexec = file_extension == ConstString(".oat") ||
- file_extension == ConstString(".odex");
+ bool skip_oatdata_oatexec = file_extension == ConstString("oat") ||
+ file_extension == ConstString("odex");
- ArchSpec arch = GetArchitecture();
+ ArchSpec arch;
+ GetArchitecture(arch);
ModuleSP module_sp(GetModule());
SectionList *module_section_list =
module_sp ? module_sp->GetSectionList() : nullptr;
// Local cache to avoid doing a FindSectionByName for each symbol. The "const
- // char*" key must came from a ConstString object so they can be compared by
- // pointer
+ // char*" key must
+ // came from a ConstString object so they can be compared by pointer
std::unordered_map<const char *, lldb::SectionSP> section_name_to_section;
unsigned i;
for (i = 0; i < num_symbols; ++i) {
- if (!symbol.Parse(symtab_data, &offset))
+ if (symbol.Parse(symtab_data, &offset) == false)
break;
const char *symbol_name = strtab_data.PeekCStr(symbol.st_name);
@@ -2101,16 +2135,17 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
continue;
// Skipping oatdata and oatexec sections if it is requested. See details
- // above the definition of skip_oatdata_oatexec for the reasons.
+ // above the
+ // definition of skip_oatdata_oatexec for the reasons.
if (skip_oatdata_oatexec && (::strcmp(symbol_name, "oatdata") == 0 ||
::strcmp(symbol_name, "oatexec") == 0))
continue;
SectionSP symbol_section_sp;
SymbolType symbol_type = eSymbolTypeInvalid;
- Elf64_Half shndx = symbol.st_shndx;
+ Elf64_Half section_idx = symbol.st_shndx;
- switch (shndx) {
+ switch (section_idx) {
case SHN_ABS:
symbol_type = eSymbolTypeAbsolute;
break;
@@ -2118,7 +2153,7 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
symbol_type = eSymbolTypeUndefined;
break;
default:
- symbol_section_sp = section_list->FindSectionByID(shndx);
+ symbol_section_sp = section_list->GetSectionAtIndex(section_idx);
break;
}
@@ -2132,8 +2167,8 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
break;
case STT_OBJECT:
- // The symbol is associated with a data object, such as a variable, an
- // array, etc.
+ // The symbol is associated with a data object, such as a variable,
+ // an array, etc.
symbol_type = eSymbolTypeData;
break;
@@ -2144,13 +2179,13 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
case STT_SECTION:
// The symbol is associated with a section. Symbol table entries of
- // this type exist primarily for relocation and normally have STB_LOCAL
- // binding.
+ // this type exist primarily for relocation and normally have
+ // STB_LOCAL binding.
break;
case STT_FILE:
- // Conventionally, the symbol's name gives the name of the source file
- // associated with the object file. A file symbol has STB_LOCAL
+ // Conventionally, the symbol's name gives the name of the source
+ // file associated with the object file. A file symbol has STB_LOCAL
// binding, its section index is SHN_ABS, and it precedes the other
// STB_LOCAL symbols for the file, if it is present.
symbol_type = eSymbolTypeSourceFile;
@@ -2192,18 +2227,18 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
switch (mapping_symbol) {
case 'a':
// $a[.<any>]* - marks an ARM instruction sequence
- m_address_class_map[symbol.st_value] = AddressClass::eCode;
+ m_address_class_map[symbol.st_value] = eAddressClassCode;
break;
case 'b':
case 't':
// $b[.<any>]* - marks a THUMB BL instruction sequence
// $t[.<any>]* - marks a THUMB instruction sequence
m_address_class_map[symbol.st_value] =
- AddressClass::eCodeAlternateISA;
+ eAddressClassCodeAlternateISA;
break;
case 'd':
// $d[.<any>]* - marks a data item sequence (e.g. lit pool)
- m_address_class_map[symbol.st_value] = AddressClass::eData;
+ m_address_class_map[symbol.st_value] = eAddressClassData;
break;
}
}
@@ -2217,11 +2252,11 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
switch (mapping_symbol) {
case 'x':
// $x[.<any>]* - marks an A64 instruction sequence
- m_address_class_map[symbol.st_value] = AddressClass::eCode;
+ m_address_class_map[symbol.st_value] = eAddressClassCode;
break;
case 'd':
// $d[.<any>]* - marks a data item sequence (e.g. lit pool)
- m_address_class_map[symbol.st_value] = AddressClass::eData;
+ m_address_class_map[symbol.st_value] = eAddressClassData;
break;
}
}
@@ -2233,17 +2268,18 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
if (arch.GetMachine() == llvm::Triple::arm) {
if (symbol_type == eSymbolTypeCode) {
if (symbol.st_value & 1) {
- // Subtracting 1 from the address effectively unsets the low order
- // bit, which results in the address actually pointing to the
- // beginning of the symbol. This delta will be used below in
- // conjunction with symbol.st_value to produce the final
- // symbol_value that we store in the symtab.
+ // Subtracting 1 from the address effectively unsets
+ // the low order bit, which results in the address
+ // actually pointing to the beginning of the symbol.
+ // This delta will be used below in conjunction with
+ // symbol.st_value to produce the final symbol_value
+ // that we store in the symtab.
symbol_value_offset = -1;
m_address_class_map[symbol.st_value ^ 1] =
- AddressClass::eCodeAlternateISA;
+ eAddressClassCodeAlternateISA;
} else {
// This address is ARM
- m_address_class_map[symbol.st_value] = AddressClass::eCode;
+ m_address_class_map[symbol.st_value] = eAddressClassCode;
}
}
}
@@ -2268,32 +2304,36 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
llvm_arch == llvm::Triple::mips64 ||
llvm_arch == llvm::Triple::mips64el) {
if (IS_MICROMIPS(symbol.st_other))
- m_address_class_map[symbol.st_value] = AddressClass::eCodeAlternateISA;
+ m_address_class_map[symbol.st_value] = eAddressClassCodeAlternateISA;
else if ((symbol.st_value & 1) && (symbol_type == eSymbolTypeCode)) {
symbol.st_value = symbol.st_value & (~1ull);
- m_address_class_map[symbol.st_value] = AddressClass::eCodeAlternateISA;
+ m_address_class_map[symbol.st_value] = eAddressClassCodeAlternateISA;
} else {
if (symbol_type == eSymbolTypeCode)
- m_address_class_map[symbol.st_value] = AddressClass::eCode;
+ m_address_class_map[symbol.st_value] = eAddressClassCode;
else if (symbol_type == eSymbolTypeData)
- m_address_class_map[symbol.st_value] = AddressClass::eData;
+ m_address_class_map[symbol.st_value] = eAddressClassData;
else
- m_address_class_map[symbol.st_value] = AddressClass::eUnknown;
+ m_address_class_map[symbol.st_value] = eAddressClassUnknown;
}
}
}
// symbol_value_offset may contain 0 for ARM symbols or -1 for THUMB
- // symbols. See above for more details.
+ // symbols. See above for
+ // more details.
uint64_t symbol_value = symbol.st_value + symbol_value_offset;
- if (symbol_section_sp == nullptr && shndx == SHN_ABS &&
+ if (symbol_section_sp == nullptr && section_idx == 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
- // covered by the module (represented through the section list). It is
- // needed so module lookup for the addresses covered by this symbol will
- // be successfull. This case happens for absolute symbols.
+ // section for it
+ // so the address range covered by the symbol is also covered by the
+ // module (represented
+ // through the section list). It is needed so module lookup for the
+ // addresses covered
+ // by this symbol will be successfull. This case happens for absolute
+ // symbols.
ConstString fake_section_name(std::string(".absolute.") + symbol_name);
symbol_section_sp =
std::make_shared<Section>(module_sp, this, SHN_ABS, fake_section_name,
@@ -2336,7 +2376,8 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
Mangled mangled(ConstString(symbol_bare), is_mangled);
// Now append the suffix back to mangled and unmangled names. Only do it if
- // the demangling was successful (string is not empty).
+ // the
+ // demangling was successful (string is not empty).
if (has_suffix) {
llvm::StringRef suffix = symbol_ref.substr(version_pos);
@@ -2352,10 +2393,12 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
}
// In ELF all symbol should have a valid size but it is not true for some
- // function symbols coming from hand written assembly. As none of the
- // function symbol should have 0 size we try to calculate the size for
- // these symbols in the symtab with saying that their original size is not
- // valid.
+ // function symbols
+ // coming from hand written assembly. As none of the function symbol should
+ // have 0 size we
+ // try to calculate the size for these symbols in the symtab with saying
+ // that their original
+ // size is not valid.
bool symbol_size_valid =
symbol.st_size != 0 || symbol.getType() != STT_FUNC;
@@ -2384,7 +2427,8 @@ unsigned ObjectFileELF::ParseSymbolTable(Symtab *symbol_table,
lldb_private::Section *symtab) {
if (symtab->GetObjectFile() != this) {
// If the symbol table section is owned by a different object file, have it
- // do the parsing.
+ // do the
+ // parsing.
ObjectFileELF *obj_file_elf =
static_cast<ObjectFileELF *>(symtab->GetObjectFile());
return obj_file_elf->ParseSymbolTable(symbol_table, start_id, symtab);
@@ -2401,7 +2445,8 @@ unsigned ObjectFileELF::ParseSymbolTable(Symtab *symbol_table,
symtab_hdr->sh_type == SHT_DYNSYM);
// sh_link: section header index of associated string table.
- user_id_t strtab_id = symtab_hdr->sh_link;
+ // Section ID's are ones based.
+ user_id_t strtab_id = symtab_hdr->sh_link + 1;
Section *strtab = section_list->FindSectionByID(strtab_id).get();
if (symtab && strtab) {
@@ -2485,17 +2530,19 @@ unsigned ObjectFileELF::PLTRelocationType() {
return 0;
}
-// Returns the size of the normal plt entries and the offset of the first
-// normal plt entry. The 0th entry in the plt table is usually a resolution
-// entry which have different size in some architectures then the rest of the
-// plt entries.
+// Returns the size of the normal plt entries and the offset of the first normal
+// plt entry. The
+// 0th entry in the plt table is usually a resolution entry which have different
+// size in some
+// architectures then the rest of the plt entries.
static std::pair<uint64_t, uint64_t>
GetPltEntrySizeAndOffset(const ELFSectionHeader *rel_hdr,
const ELFSectionHeader *plt_hdr) {
const elf_xword num_relocations = rel_hdr->sh_size / rel_hdr->sh_entsize;
- // Clang 3.3 sets entsize to 4 for 32-bit binaries, but the plt entries are
- // 16 bytes. So round the entsize up by the alignment if addralign is set.
+ // Clang 3.3 sets entsize to 4 for 32-bit binaries, but the plt entries are 16
+ // bytes.
+ // So round the entsize up by the alignment if addralign is set.
elf_xword plt_entsize =
plt_hdr->sh_addralign
? llvm::alignTo(plt_hdr->sh_entsize, plt_hdr->sh_addralign)
@@ -2507,10 +2554,12 @@ GetPltEntrySizeAndOffset(const ELFSectionHeader *rel_hdr,
// just in case.
if (plt_entsize <= 4) {
// The linker haven't set the plt_hdr->sh_entsize field. Try to guess the
- // size of the plt entries based on the number of entries and the size of
- // the plt section with the assumption that the size of the 0th entry is at
- // least as big as the size of the normal entries and it isn't much bigger
- // then that.
+ // size of the plt
+ // entries based on the number of entries and the size of the plt section
+ // with the
+ // assumption that the size of the 0th entry is at least as big as the size
+ // of the normal
+ // entries and it isn't much bigger then that.
if (plt_hdr->sh_addralign)
plt_entsize = plt_hdr->sh_size / plt_hdr->sh_addralign /
(num_relocations + 1) * plt_hdr->sh_addralign;
@@ -2553,7 +2602,7 @@ static unsigned ParsePLTRelocations(
unsigned slot_type = hdr->GetRelocationJumpSlotType();
unsigned i;
for (i = 0; i < num_relocations; ++i) {
- if (!rel.Parse(rel_data, &offset))
+ if (rel.Parse(rel_data, &offset) == false)
break;
if (reloc_type(rel) != slot_type)
@@ -2611,6 +2660,10 @@ 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;
@@ -2636,7 +2689,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).get();
+ Section *strtab = section_list->FindSectionByID(sym_hdr->sh_link + 1).get();
if (!strtab)
return 0;
@@ -2661,7 +2714,7 @@ ObjectFileELF::ParseTrampolineSymbols(Symtab *symbol_table, user_id_t start_id,
rel_data, symtab_data, strtab_data);
}
-unsigned ObjectFileELF::ApplyRelocations(
+unsigned ObjectFileELF::RelocateSection(
Symtab *symtab, const ELFHeader *hdr, const ELFSectionHeader *rel_hdr,
const ELFSectionHeader *symtab_hdr, const ELFSectionHeader *debug_hdr,
DataExtractor &rel_data, DataExtractor &symtab_data,
@@ -2682,7 +2735,7 @@ unsigned ObjectFileELF::ApplyRelocations(
}
for (unsigned i = 0; i < num_relocations; ++i) {
- if (!rel.Parse(rel_data, &offset))
+ if (rel.Parse(rel_data, &offset) == false)
break;
Symbol *symbol = NULL;
@@ -2692,19 +2745,10 @@ unsigned ObjectFileELF::ApplyRelocations(
case R_386_32:
case R_386_PC32:
default:
- // FIXME: This asserts with this input:
- //
- // foo.cpp
- // int main(int argc, char **argv) { return 0; }
- //
- // clang++.exe --target=i686-unknown-linux-gnu -g -c foo.cpp -o foo.o
- //
- // and running this on the foo.o module.
assert(false && "unexpected relocation type");
}
} else {
switch (reloc_type(rel)) {
- case R_AARCH64_ABS64:
case R_X86_64_64: {
symbol = symtab->FindSymbolByID(reloc_symbol(rel));
if (symbol) {
@@ -2713,34 +2757,26 @@ unsigned ObjectFileELF::ApplyRelocations(
uint64_t *dst = reinterpret_cast<uint64_t *>(
data_buffer_sp->GetBytes() + rel_section->GetFileOffset() +
ELFRelocation::RelocOffset64(rel));
- uint64_t val_offset = value + ELFRelocation::RelocAddend64(rel);
- memcpy(dst, &val_offset, sizeof(uint64_t));
+ *dst = value + ELFRelocation::RelocAddend64(rel);
}
break;
}
case R_X86_64_32:
- case R_X86_64_32S:
- case R_AARCH64_ABS32: {
+ case R_X86_64_32S: {
symbol = symtab->FindSymbolByID(reloc_symbol(rel));
if (symbol) {
addr_t value = symbol->GetAddressRef().GetFileAddress();
value += ELFRelocation::RelocAddend32(rel);
- if ((reloc_type(rel) == R_X86_64_32 && (value > UINT32_MAX)) ||
+ assert(
+ (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)) ||
- (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;
- }
+ ((int64_t)value <= INT32_MAX && (int64_t)value >= INT32_MIN)));
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));
- memcpy(dst, &truncated_addr, sizeof(uint32_t));
+ *dst = truncated_addr;
}
break;
}
@@ -2755,8 +2791,7 @@ unsigned ObjectFileELF::ApplyRelocations(
}
unsigned ObjectFileELF::RelocateDebugSections(const ELFSectionHeader *rel_hdr,
- user_id_t rel_id,
- lldb_private::Symtab *thetab) {
+ user_id_t rel_id) {
assert(rel_hdr->sh_type == SHT_RELA || rel_hdr->sh_type == SHT_REL);
// Parse in the section list if needed.
@@ -2764,8 +2799,9 @@ unsigned ObjectFileELF::RelocateDebugSections(const ELFSectionHeader *rel_hdr,
if (!section_list)
return 0;
- user_id_t symtab_id = rel_hdr->sh_link;
- user_id_t debug_id = rel_hdr->sh_info;
+ // 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;
const ELFSectionHeader *symtab_hdr = GetSectionHeaderByIndex(symtab_id);
if (!symtab_hdr)
@@ -2791,11 +2827,10 @@ unsigned ObjectFileELF::RelocateDebugSections(const ELFSectionHeader *rel_hdr,
DataExtractor symtab_data;
DataExtractor debug_data;
- if (GetData(rel->GetFileOffset(), rel->GetFileSize(), rel_data) &&
- GetData(symtab->GetFileOffset(), symtab->GetFileSize(), symtab_data) &&
- GetData(debug->GetFileOffset(), debug->GetFileSize(), debug_data)) {
- ApplyRelocations(thetab, &m_header, rel_hdr, symtab_hdr, debug_hdr,
- rel_data, symtab_data, debug_data, debug);
+ if (ReadSectionData(rel, rel_data) && ReadSectionData(symtab, symtab_data) &&
+ ReadSectionData(debug, debug_data)) {
+ RelocateSection(m_symtab_ap.get(), &m_header, rel_hdr, symtab_hdr,
+ debug_hdr, rel_data, symtab_data, debug_data, debug);
}
return 0;
@@ -2807,7 +2842,8 @@ Symtab *ObjectFileELF::GetSymtab() {
return NULL;
// We always want to use the main object file so we (hopefully) only have one
- // cached copy of our symtab, dynamic sections, etc.
+ // cached copy
+ // of our symtab, dynamic sections, etc.
ObjectFile *module_obj_file = module_sp->GetObjectFile();
if (module_obj_file && module_obj_file != this)
return module_obj_file->GetSymtab();
@@ -2822,15 +2858,18 @@ Symtab *ObjectFileELF::GetSymtab() {
// Sharable objects and dynamic executables usually have 2 distinct symbol
// tables, one named ".symtab", and the other ".dynsym". The dynsym is a
- // smaller version of the symtab that only contains global symbols. The
- // information found in the dynsym is therefore also found in the symtab,
- // while the reverse is not necessarily true.
+ // smaller
+ // version of the symtab that only contains global symbols. The information
+ // found
+ // in the dynsym is therefore also found in the symtab, while the reverse is
+ // not
+ // necessarily true.
Section *symtab =
section_list->FindSectionByType(eSectionTypeELFSymbolTable, true).get();
if (!symtab) {
// The symtab section is non-allocable and can be stripped, so if it
- // doesn't exist then use the dynsym section which should always be
- // there.
+ // doesn't exist
+ // then use the dynsym section which should always be there.
symtab =
section_list->FindSectionByType(eSectionTypeELFDynamicSymbols, true)
.get();
@@ -2877,55 +2916,29 @@ Symtab *ObjectFileELF::GetSymtab() {
}
// If we still don't have any symtab then create an empty instance to avoid
- // do the section lookup next time.
+ // do the section
+ // lookup next time.
if (m_symtab_ap == nullptr)
m_symtab_ap.reset(new Symtab(this));
m_symtab_ap->CalculateSymbolSizes();
}
- return m_symtab_ap.get();
-}
-
-void ObjectFileELF::RelocateSection(lldb_private::Section *section)
-{
- static const char *debug_prefix = ".debug";
-
- // Set relocated bit so we stop getting called, regardless of whether we
- // actually relocate.
- section->SetIsRelocated(true);
-
- // We only relocate in ELF relocatable files
- if (CalculateType() != eTypeObjectFile)
- return;
-
- const char *section_name = section->GetName().GetCString();
- // Can't relocate that which can't be named
- if (section_name == nullptr)
- return;
-
- // We don't relocate non-debug sections at the moment
- if (strncmp(section_name, debug_prefix, strlen(debug_prefix)))
- return;
-
- // Relocation section names to look for
- std::string needle = std::string(".rel") + section_name;
- std::string needlea = std::string(".rela") + section_name;
-
for (SectionHeaderCollIter I = m_section_headers.begin();
I != m_section_headers.end(); ++I) {
if (I->sh_type == SHT_RELA || I->sh_type == SHT_REL) {
- const char *hay_name = I->section_name.GetCString();
- if (hay_name == nullptr)
- continue;
- if (needle == hay_name || needlea == hay_name) {
- const ELFSectionHeader &reloc_header = *I;
- user_id_t reloc_id = SectionIndex(I);
- RelocateDebugSections(&reloc_header, reloc_id, GetSymtab());
- break;
+ if (CalculateType() == eTypeObjectFile) {
+ const char *section_name = I->section_name.AsCString("");
+ if (strstr(section_name, ".rela.debug") ||
+ strstr(section_name, ".rel.debug")) {
+ const ELFSectionHeader &reloc_header = *I;
+ user_id_t reloc_id = SectionIndex(I);
+ RelocateDebugSections(&reloc_header, reloc_id);
+ }
}
}
}
+ return m_symtab_ap.get();
}
void ObjectFileELF::ParseUnwindSymbols(Symtab *symbol_table,
@@ -2935,10 +2948,12 @@ void ObjectFileELF::ParseUnwindSymbols(Symtab *symbol_table,
return;
// First we save the new symbols into a separate list and add them to the
- // symbol table after we colleced all symbols we want to add. This is
- // neccessary because adding a new symbol invalidates the internal index of
- // the symtab what causing the next lookup to be slow because it have to
- // recalculate the index first.
+ // symbol table after
+ // we colleced all symbols we want to add. This is neccessary because adding a
+ // new symbol
+ // invalidates the internal index of the symtab what causing the next lookup
+ // to be slow because
+ // it have to recalculate the index first.
std::vector<Symbol> new_symbols;
eh_frame->ForEachFDEEntries([this, symbol_table, section_list, &new_symbols](
@@ -3003,7 +3018,8 @@ void ObjectFileELF::Dump(Stream *s) {
s->Indent();
s->PutCString("ObjectFileELF");
- ArchSpec header_arch = GetArchitecture();
+ ArchSpec header_arch;
+ GetArchitecture(header_arch);
*s << ", file = '" << m_file
<< "', arch = " << header_arch.GetArchitectureName() << "\n";
@@ -3131,8 +3147,8 @@ void ObjectFileELF::DumpELFProgramHeader(Stream *s,
//----------------------------------------------------------------------
// DumpELFProgramHeader_p_type
//
-// Dump an token value for the ELF program header member p_type which describes
-// the type of the program header
+// Dump an token value for the ELF program header member p_type which
+// describes the type of the program header
// ----------------------------------------------------------------------
void ObjectFileELF::DumpELFProgramHeader_p_type(Stream *s, elf_word p_type) {
const int kStrWidth = 15;
@@ -3180,9 +3196,11 @@ void ObjectFileELF::DumpELFProgramHeaders(Stream *s) {
s->PutCString("==== --------------- -------- -------- -------- "
"-------- -------- ------------------------- --------\n");
- for (const auto &H : llvm::enumerate(m_program_headers)) {
- s->Format("[{0,2}] ", H.index());
- ObjectFileELF::DumpELFProgramHeader(s, H.value());
+ 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);
s->EOL();
}
}
@@ -3289,9 +3307,9 @@ void ObjectFileELF::DumpDependentModules(lldb_private::Stream *s) {
}
}
-ArchSpec ObjectFileELF::GetArchitecture() {
+bool ObjectFileELF::GetArchitecture(ArchSpec &arch) {
if (!ParseHeader())
- return ArchSpec();
+ return false;
if (m_section_headers.empty()) {
// Allow elf notes to be parsed which may affect the detected architecture.
@@ -3301,18 +3319,25 @@ ArchSpec ObjectFileELF::GetArchitecture() {
if (CalculateType() == eTypeCoreFile &&
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
- 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);
+ // 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);
+ }
+ }
}
}
}
- return m_arch_spec;
+ arch = m_arch_spec;
+ return true;
}
ObjectFile::Type ObjectFileELF::CalculateType() {
@@ -3356,22 +3381,22 @@ ObjectFile::Strata ObjectFileELF::CalculateStrata() {
case llvm::ELF::ET_EXEC:
// 2 - Executable file
// TODO: is there any way to detect that an executable is a kernel
- // related executable by inspecting the program headers, section headers,
- // symbols, or any other flag bits???
+ // related executable by inspecting the program headers, section
+ // headers, symbols, or any other flag bits???
return eStrataUser;
case llvm::ELF::ET_DYN:
// 3 - Shared object file
// TODO: is there any way to detect that an shared library is a kernel
- // related executable by inspecting the program headers, section headers,
- // symbols, or any other flag bits???
+ // related executable by inspecting the program headers, section
+ // headers, symbols, or any other flag bits???
return eStrataUnknown;
case ET_CORE:
// 4 - Core file
// TODO: is there any way to detect that an core file is a kernel
- // related executable by inspecting the program headers, section headers,
- // symbols, or any other flag bits???
+ // related executable by inspecting the program headers, section
+ // headers, symbols, or any other flag bits???
return eStrataUnknown;
default:
@@ -3379,102 +3404,3 @@ ObjectFile::Strata ObjectFileELF::CalculateStrata() {
}
return eStrataUnknown;
}
-
-size_t ObjectFileELF::ReadSectionData(Section *section,
- lldb::offset_t section_offset, void *dst,
- size_t dst_len) {
- // If some other objectfile owns this data, pass this to them.
- if (section->GetObjectFile() != this)
- return section->GetObjectFile()->ReadSectionData(section, section_offset,
- dst, dst_len);
-
- if (!section->Test(SHF_COMPRESSED))
- return ObjectFile::ReadSectionData(section, section_offset, dst, dst_len);
-
- // For compressed sections we need to read to full data to be able to
- // decompress.
- DataExtractor data;
- ReadSectionData(section, data);
- return data.CopyData(section_offset, dst_len, dst);
-}
-
-size_t ObjectFileELF::ReadSectionData(Section *section,
- DataExtractor &section_data) {
- // If some other objectfile owns this data, pass this to them.
- if (section->GetObjectFile() != this)
- return section->GetObjectFile()->ReadSectionData(section, section_data);
-
- size_t result = ObjectFile::ReadSectionData(section, section_data);
- if (result == 0 || !section->Test(SHF_COMPRESSED))
- return result;
-
- auto Decompressor = llvm::object::Decompressor::create(
- section->GetName().GetStringRef(),
- {reinterpret_cast<const char *>(section_data.GetDataStart()),
- size_t(section_data.GetByteSize())},
- GetByteOrder() == eByteOrderLittle, GetAddressByteSize() == 8);
- if (!Decompressor) {
- 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(
- {reinterpret_cast<char *>(buffer_sp->GetBytes()),
- size_t(buffer_sp->GetByteSize())})) {
- 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() {
- for (const ELFProgramHeader &H : ProgramHeaders()) {
- if (H.p_paddr != 0)
- return true;
- }
- return false;
-}
-
-std::vector<ObjectFile::LoadableData>
-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;
- bool should_use_paddr = AnySegmentHasPhysicalAddress();
- for (const ELFProgramHeader &H : ProgramHeaders()) {
- LoadableData loadable;
- if (H.p_type != llvm::ELF::PT_LOAD)
- continue;
- loadable.Dest = should_use_paddr ? H.p_paddr : H.p_vaddr;
- if (loadable.Dest == LLDB_INVALID_ADDRESS)
- continue;
- if (H.p_filesz == 0)
- continue;
- auto segment_data = GetSegmentData(H);
- loadable.Contents = llvm::ArrayRef<uint8_t>(segment_data.GetDataStart(),
- segment_data.GetByteSize());
- loadables.push_back(loadable);
- }
- return loadables;
-}