diff options
author | Patrick Wildt <patrick@cvs.openbsd.org> | 2017-10-04 20:27:40 +0000 |
---|---|---|
committer | Patrick Wildt <patrick@cvs.openbsd.org> | 2017-10-04 20:27:40 +0000 |
commit | 05276a939599b1c2eaf9b68e1c2c3830c2291991 (patch) | |
tree | 8ff3a0ab306cd5d8bf56892b05029f7e5a0fa780 /gnu | |
parent | ea30ef648a92850407f8b33b67c78a4948cd9eb9 (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.cpp | 1288 |
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 §ion_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 §ion_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 §ion_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 §ion_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; -} |