summaryrefslogtreecommitdiff
path: root/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2018-07-28 11:09:23 +0000
committerDimitry Andric <dim@FreeBSD.org>2018-07-28 11:09:23 +0000
commitf73363f1dd94996356cefbf24388f561891acf0b (patch)
treee3c31248bdb36eaec5fd833490d4278162dba2a0 /source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
parent160ee69dd7ae18978f4068116777639ea98dc951 (diff)
Notes
Diffstat (limited to 'source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp')
-rw-r--r--source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp560
1 files changed, 251 insertions, 309 deletions
diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 36027dde0432..8701908378f1 100644
--- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -113,7 +113,7 @@ const elf_word LLDB_NT_GNU_ABI_OS_SOLARIS = 0x02;
//===----------------------------------------------------------------------===//
/// @class ELFRelocation
-/// @brief Generic wrapper for ELFRel and ELFRela.
+/// Generic wrapper for ELFRel and ELFRela.
///
/// This helper class allows us to parse both ELFRel and ELFRela relocation
/// entries in a generic manner.
@@ -240,11 +240,10 @@ bool ELFNote::Parse(const DataExtractor &data, lldb::offset_t *offset) {
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)
@@ -295,7 +294,8 @@ 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) {
@@ -549,8 +549,8 @@ uint32_t ObjectFileELF::CalculateELFNotesSegmentsCRC32(
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;
}
@@ -595,8 +595,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,
@@ -674,29 +674,16 @@ size_t ObjectFileELF::GetModuleSpecifications(
__FUNCTION__, file.GetPath().c_str());
}
- // 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 = MapFileData(file, 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 = MapFileData(file, section_header_end, file_offset);
- if (data_sp)
- data.SetData(data_sp);
+ 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);
}
uint32_t gnu_debuglink_crc = 0;
@@ -733,51 +720,27 @@ size_t ObjectFileELF::GetModuleSpecifications(
// 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 = MapFileData(file, 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 = MapFileData(file, segment_data_end, file_offset);
- if (data_sp)
- data.SetData(data_sp);
- }
-
core_notes_crc =
CalculateELFNotesSegmentsCRC32(program_headers, data);
} else {
- // Need to map entire file into memory to calculate the crc.
- data_sp = MapFileData(file, -1, file_offset);
- if (data_sp) {
- data.SetData(data_sp);
- gnu_debuglink_crc = calc_gnu_debuglink_crc32(
- data.GetDataStart(), data.GetByteSize());
- }
+ 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.
- uint32_t uuidt[4] = {gnu_debuglink_crc, 0, 0, 0};
- uuid.SetBytes(uuidt, sizeof(uuidt));
+ u32le data(gnu_debuglink_crc);
+ uuid = UUID::fromData(&data, sizeof(data));
} 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.
- uint32_t uuidt[4] = {g_core_uuid_magic, core_notes_crc, 0, 0};
- uuid.SetBytes(uuidt, sizeof(uuidt));
+ // 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));
}
}
@@ -861,21 +824,19 @@ bool ObjectFileELF::SetLoadAddress(Target &target, lldb::addr_t value,
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 && 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;
@@ -905,24 +866,23 @@ uint32_t ObjectFileELF::GetAddressByteSize() const {
AddressClass ObjectFileELF::GetAddressClass(addr_t file_addr) {
Symtab *symtab = GetSymtab();
if (!symtab)
- return eAddressClassUnknown;
+ return AddressClass::eUnknown;
- // 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 != eAddressClassCode)
+ if (res != AddressClass::eCode)
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 eAddressClassCode;
+ // No entry in the address class map before the address. Return default
+ // address class for an address in a code section.
+ return AddressClass::eCode;
}
// Move iterator to the address class entry preceding address
@@ -950,6 +910,7 @@ 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;
@@ -963,11 +924,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.
- uint32_t uuidt[4] = {g_core_uuid_magic, core_notes_crc, 0, 0};
- m_uuid.SetBytes(uuidt, sizeof(uuidt));
+ u32le data[] = {u32le(g_core_uuid_magic), u32le(core_notes_crc)};
+ m_uuid = UUID::fromData(data, sizeof(data));
}
} else {
if (!m_gnu_debuglink_crc)
@@ -975,8 +936,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.
- uint32_t uuidt[4] = {m_gnu_debuglink_crc, 0, 0, 0};
- m_uuid.SetBytes(uuidt, sizeof(uuidt));
+ u32le data(m_gnu_debuglink_crc);
+ m_uuid = UUID::fromData(&data, sizeof(data));
}
}
@@ -1034,8 +995,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);
}
@@ -1314,18 +1275,16 @@ 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 && note.n_descsz <= 20) {
- uint8_t uuidbuf[20];
- if (data.GetU8(&offset, &uuidbuf, note.n_descsz) == nullptr) {
+ // 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 {
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;
@@ -1368,8 +1327,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));
@@ -1384,36 +1343,28 @@ 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;
@@ -1437,15 +1388,14 @@ 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
+ // 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();
}
@@ -1545,13 +1495,12 @@ size_t ObjectFileELF::GetSectionHeaderInfo(SectionHeaderColl &section_headers,
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);
@@ -1842,6 +1791,7 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
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");
@@ -1857,10 +1807,12 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
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;
@@ -1881,23 +1833,19 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
}
// .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
+ // 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_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
+ // 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;
@@ -1919,6 +1867,8 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
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)
@@ -1927,6 +1877,8 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
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)
@@ -1951,6 +1903,8 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
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) |
@@ -1978,13 +1932,21 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
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".
+ // It does support linkscripts which (can) give rise to various
+ // arbitrarily named sections being "Code" or "Data".
sect_type = kalimbaSectionType(m_header, header);
}
+ // 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;
+ }
+
const uint32_t target_bytes_size =
(eSectionTypeData == sect_type || eSectionTypeZeroFill == sect_type)
? m_arch_spec.GetDataByteSize()
@@ -2024,46 +1986,16 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
}
}
- if (m_sections_ap.get()) {
- if (GetType() == eTypeDebugInfo) {
- static const SectionType g_sections[] = {
- eSectionTypeDWARFDebugAbbrev, eSectionTypeDWARFDebugAddr,
- eSectionTypeDWARFDebugAranges, eSectionTypeDWARFDebugCuIndex,
- 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;
- }
- }
+ // 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)
@@ -2105,22 +2037,18 @@ 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(arch);
@@ -2129,8 +2057,8 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
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;
@@ -2148,8 +2076,7 @@ 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;
@@ -2180,8 +2107,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;
@@ -2192,13 +2119,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;
@@ -2240,18 +2167,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] = eAddressClassCode;
+ m_address_class_map[symbol.st_value] = AddressClass::eCode;
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] =
- eAddressClassCodeAlternateISA;
+ AddressClass::eCodeAlternateISA;
break;
case 'd':
// $d[.<any>]* - marks a data item sequence (e.g. lit pool)
- m_address_class_map[symbol.st_value] = eAddressClassData;
+ m_address_class_map[symbol.st_value] = AddressClass::eData;
break;
}
}
@@ -2265,11 +2192,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] = eAddressClassCode;
+ m_address_class_map[symbol.st_value] = AddressClass::eCode;
break;
case 'd':
// $d[.<any>]* - marks a data item sequence (e.g. lit pool)
- m_address_class_map[symbol.st_value] = eAddressClassData;
+ m_address_class_map[symbol.st_value] = AddressClass::eData;
break;
}
}
@@ -2281,18 +2208,17 @@ 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] =
- eAddressClassCodeAlternateISA;
+ AddressClass::eCodeAlternateISA;
} else {
// This address is ARM
- m_address_class_map[symbol.st_value] = eAddressClassCode;
+ m_address_class_map[symbol.st_value] = AddressClass::eCode;
}
}
}
@@ -2317,36 +2243,32 @@ 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] = eAddressClassCodeAlternateISA;
+ m_address_class_map[symbol.st_value] = AddressClass::eCodeAlternateISA;
else if ((symbol.st_value & 1) && (symbol_type == eSymbolTypeCode)) {
symbol.st_value = symbol.st_value & (~1ull);
- m_address_class_map[symbol.st_value] = eAddressClassCodeAlternateISA;
+ m_address_class_map[symbol.st_value] = AddressClass::eCodeAlternateISA;
} else {
if (symbol_type == eSymbolTypeCode)
- m_address_class_map[symbol.st_value] = eAddressClassCode;
+ m_address_class_map[symbol.st_value] = AddressClass::eCode;
else if (symbol_type == eSymbolTypeData)
- m_address_class_map[symbol.st_value] = eAddressClassData;
+ m_address_class_map[symbol.st_value] = AddressClass::eData;
else
- m_address_class_map[symbol.st_value] = eAddressClassUnknown;
+ m_address_class_map[symbol.st_value] = AddressClass::eUnknown;
}
}
}
// 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 && 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,
@@ -2389,8 +2311,7 @@ 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);
@@ -2406,12 +2327,10 @@ 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;
@@ -2440,8 +2359,7 @@ 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);
@@ -2457,8 +2375,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.
+ // 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;
Section *strtab = section_list->FindSectionByID(strtab_id).get();
@@ -2543,19 +2461,17 @@ 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)
@@ -2567,12 +2483,10 @@ 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;
@@ -2865,8 +2779,7 @@ 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();
@@ -2881,18 +2794,15 @@ 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();
@@ -2939,8 +2849,7 @@ 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));
@@ -2954,8 +2863,8 @@ 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.
+ // Set relocated bit so we stop getting called, regardless of whether we
+ // actually relocate.
section->SetIsRelocated(true);
// We only relocate in ELF relocatable files
@@ -2998,12 +2907,10 @@ 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](
@@ -3197,8 +3104,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;
@@ -3369,8 +3276,7 @@ bool ObjectFileELF::GetArchitecture(ArchSpec &arch) {
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
+ // 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);
@@ -3431,22 +3337,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:
@@ -3491,8 +3397,9 @@ size_t ObjectFileELF::ReadSectionData(Section *section,
size_t(section_data.GetByteSize())},
GetByteOrder() == eByteOrderLittle, GetAddressByteSize() == 8);
if (!Decompressor) {
- LLDB_LOG(log, "Unable to initialize decompressor for section {0}: {1}",
- section->GetName(), llvm::toString(Decompressor.takeError()));
+ LLDB_LOG_ERROR(log, Decompressor.takeError(),
+ "Unable to initialize decompressor for section {0}",
+ section->GetName());
return result;
}
auto buffer_sp =
@@ -3500,10 +3407,45 @@ size_t ObjectFileELF::ReadSectionData(Section *section,
if (auto Error = Decompressor->decompress(
{reinterpret_cast<char *>(buffer_sp->GetBytes()),
size_t(buffer_sp->GetByteSize())})) {
- LLDB_LOG(log, "Decompression of section {0} failed: {1}",
- section->GetName(), llvm::toString(std::move(Error)));
+ LLDB_LOG_ERROR(log, std::move(Error), "Decompression of section {0} failed",
+ section->GetName());
return result;
}
section_data.SetData(buffer_sp);
return buffer_sp->GetByteSize();
}
+
+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)
+ 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;
+ size_t header_count = ParseProgramHeaders();
+ bool should_use_paddr = AnySegmentHasPhysicalAddress();
+ for (size_t i = 1; i <= header_count; ++i) {
+ LoadableData loadable;
+ auto header = GetProgramHeaderByIndex(i);
+ if (header->p_type != llvm::ELF::PT_LOAD)
+ continue;
+ loadable.Dest = should_use_paddr ? header->p_paddr : header->p_vaddr;
+ if (loadable.Dest == LLDB_INVALID_ADDRESS)
+ continue;
+ if (header->p_filesz == 0)
+ continue;
+ auto segment_data = GetSegmentDataByIndex(i);
+ loadable.Contents = llvm::ArrayRef<uint8_t>(segment_data.GetDataStart(),
+ segment_data.GetByteSize());
+ loadables.push_back(loadable);
+ }
+ return loadables;
+}