diff options
author | Leonard Chan <leonardchan@google.com> | 2024-08-08 23:05:23 +0000 |
---|---|---|
committer | Leonard Chan <leonardchan@google.com> | 2024-08-08 23:05:23 +0000 |
commit | 1d9e1c6644a03530efbb09d419013ec0bfe0c823 (patch) | |
tree | b80e812d7159bac7779044ba0d3142dc70fa94d4 /lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp | |
parent | 046524e8fe425cbc86c3371f2bf29fbb39d98435 (diff) | |
download | llvm-1d9e1c6644a03530efbb09d419013ec0bfe0c823.zip llvm-1d9e1c6644a03530efbb09d419013ec0bfe0c823.tar.gz llvm-1d9e1c6644a03530efbb09d419013ec0bfe0c823.tar.bz2 |
Revert "[LLDB] Impove ObjectFileELF's .dynamic parsing and usage. (#101237)"
This reverts commit 28ba8a56b6fb9ec61897fa84369f46e43be94c03.
Reverting since this broke the buildbot at
https://green.lab.llvm.org/job/llvm.org/view/LLDB/job/as-lldb-cmake/9352/.
Diffstat (limited to 'lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp')
-rw-r--r-- | lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 422 |
1 files changed, 120 insertions, 302 deletions
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index 414ac61..890db5c 100644 --- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -419,35 +419,19 @@ ObjectFile *ObjectFileELF::CreateInstance(const lldb::ModuleSP &module_sp, ObjectFile *ObjectFileELF::CreateMemoryInstance( const lldb::ModuleSP &module_sp, WritableDataBufferSP data_sp, const lldb::ProcessSP &process_sp, lldb::addr_t header_addr) { - if (!data_sp || data_sp->GetByteSize() < (llvm::ELF::EI_NIDENT)) - return nullptr; - const uint8_t *magic = data_sp->GetBytes(); - if (!ELFHeader::MagicBytesMatch(magic)) - return nullptr; - // Read the ELF header first so we can figure out how many bytes we need - // to read to get as least the ELF header + program headers. - DataExtractor data; - data.SetData(data_sp); - elf::ELFHeader hdr; - lldb::offset_t offset = 0; - if (!hdr.Parse(data, &offset)) - return nullptr; - - // Make sure the address size is set correctly in the ELF header. - if (!hdr.Is32Bit() && !hdr.Is64Bit()) - return nullptr; - // Figure out where the program headers end and read enough bytes to get the - // program headers in their entirety. - lldb::offset_t end_phdrs = hdr.e_phoff + (hdr.e_phentsize * hdr.e_phnum); - if (end_phdrs > data_sp->GetByteSize()) - data_sp = ReadMemory(process_sp, header_addr, end_phdrs); - - std::unique_ptr<ObjectFileELF> objfile_up( - new ObjectFileELF(module_sp, data_sp, process_sp, header_addr)); - ArchSpec spec = objfile_up->GetArchitecture(); - if (spec && objfile_up->SetModulesArchitecture(spec)) - return objfile_up.release(); - + if (data_sp && data_sp->GetByteSize() > (llvm::ELF::EI_NIDENT)) { + const uint8_t *magic = data_sp->GetBytes(); + if (ELFHeader::MagicBytesMatch(magic)) { + unsigned address_size = ELFHeader::AddressSizeInBytes(magic); + if (address_size == 4 || address_size == 8) { + std::unique_ptr<ObjectFileELF> objfile_up( + new ObjectFileELF(module_sp, data_sp, process_sp, header_addr)); + ArchSpec spec = objfile_up->GetArchitecture(); + if (spec && objfile_up->SetModulesArchitecture(spec)) + return objfile_up.release(); + } + } + } return nullptr; } @@ -889,37 +873,42 @@ Address ObjectFileELF::GetImageInfoAddress(Target *target) { if (!section_list) return Address(); - for (size_t i = 0; i < m_dynamic_symbols.size(); ++i) { - const ELFDynamic &symbol = m_dynamic_symbols[i].symbol; + // Find the SHT_DYNAMIC (.dynamic) section. + SectionSP dynsym_section_sp( + section_list->FindSectionByType(eSectionTypeELFDynamicLinkInfo, true)); + if (!dynsym_section_sp) + return Address(); + assert(dynsym_section_sp->GetObjectFile() == this); - if (symbol.d_tag != DT_DEBUG && symbol.d_tag != DT_MIPS_RLD_MAP && - symbol.d_tag != DT_MIPS_RLD_MAP_REL) - continue; + user_id_t dynsym_id = dynsym_section_sp->GetID(); + const ELFSectionHeaderInfo *dynsym_hdr = GetSectionHeaderByIndex(dynsym_id); + if (!dynsym_hdr) + return Address(); - // Compute the offset as the number of previous entries plus the size of - // d_tag. - const addr_t offset = (i * 2 + 1) * GetAddressByteSize(); - const addr_t d_file_addr = m_dynamic_base_addr + offset; - Address d_addr; - if (d_addr.ResolveAddressUsingFileSections(d_file_addr, GetSectionList())) - return Address(); - if (symbol.d_tag == DT_DEBUG) - return d_addr; + for (size_t i = 0; i < m_dynamic_symbols.size(); ++i) { + 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. + addr_t offset = i * dynsym_hdr->sh_entsize + GetAddressByteSize(); + return Address(dynsym_section_sp, offset); + } // MIPS executables uses DT_MIPS_RLD_MAP_REL to support PIE. DT_MIPS_RLD_MAP // exists in non-PIE. - if ((symbol.d_tag == DT_MIPS_RLD_MAP || - symbol.d_tag == DT_MIPS_RLD_MAP_REL) && - target) { - const addr_t d_load_addr = d_addr.GetLoadAddress(target); - if (d_load_addr == LLDB_INVALID_ADDRESS) + else if ((symbol.d_tag == DT_MIPS_RLD_MAP || + symbol.d_tag == DT_MIPS_RLD_MAP_REL) && + target) { + addr_t offset = i * dynsym_hdr->sh_entsize + GetAddressByteSize(); + addr_t dyn_base = dynsym_section_sp->GetLoadBaseAddress(target); + if (dyn_base == LLDB_INVALID_ADDRESS) return Address(); Status error; if (symbol.d_tag == DT_MIPS_RLD_MAP) { // DT_MIPS_RLD_MAP tag stores an absolute address of the debug pointer. Address addr; - if (target->ReadPointerFromMemory(d_load_addr, error, addr, true)) + if (target->ReadPointerFromMemory(dyn_base + offset, error, addr, true)) return addr; } if (symbol.d_tag == DT_MIPS_RLD_MAP_REL) { @@ -927,17 +916,18 @@ Address ObjectFileELF::GetImageInfoAddress(Target *target) { // relative to the address of the tag. uint64_t rel_offset; rel_offset = target->ReadUnsignedIntegerFromMemory( - d_load_addr, GetAddressByteSize(), UINT64_MAX, error, true); + dyn_base + offset, GetAddressByteSize(), UINT64_MAX, error, true); if (error.Success() && rel_offset != UINT64_MAX) { Address addr; addr_t debug_ptr_address = - d_load_addr - GetAddressByteSize() + rel_offset; + dyn_base + (offset - GetAddressByteSize()) + rel_offset; addr.SetOffset(debug_ptr_address); return addr; } } } } + return Address(); } @@ -980,23 +970,62 @@ Address ObjectFileELF::GetBaseAddress() { return LLDB_INVALID_ADDRESS; } +// ParseDependentModules size_t ObjectFileELF::ParseDependentModules() { if (m_filespec_up) return m_filespec_up->GetSize(); m_filespec_up = std::make_unique<FileSpecList>(); - if (ParseDynamicSymbols()) { - for (const auto &entry : m_dynamic_symbols) { - if (entry.symbol.d_tag != DT_NEEDED) + if (!ParseSectionHeaders()) + return 0; + + SectionList *section_list = GetSectionList(); + if (!section_list) + return 0; + + // Find the SHT_DYNAMIC section. + Section *dynsym = + section_list->FindSectionByType(eSectionTypeELFDynamicLinkInfo, true) + .get(); + if (!dynsym) + return 0; + assert(dynsym->GetObjectFile() == this); + + const ELFSectionHeaderInfo *header = GetSectionHeaderByIndex(dynsym->GetID()); + if (!header) + 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(); + if (!dynstr) + return 0; + + DataExtractor dynsym_data; + DataExtractor dynstr_data; + if (ReadSectionData(dynsym, dynsym_data) && + ReadSectionData(dynstr, dynstr_data)) { + ELFDynamic symbol; + const lldb::offset_t section_size = dynsym_data.GetByteSize(); + lldb::offset_t offset = 0; + + // The only type of entries we are concerned with are tagged DT_NEEDED, + // yielding the name of a required library. + while (offset < section_size) { + if (!symbol.Parse(dynsym_data, &offset)) + break; + + if (symbol.d_tag != DT_NEEDED) continue; - if (!entry.name.empty()) { - FileSpec file_spec(entry.name); - FileSystem::Instance().Resolve(file_spec); - m_filespec_up->Append(file_spec); - } + + 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_up->Append(file_spec); } } + return m_filespec_up->GetSize(); } @@ -2443,47 +2472,48 @@ size_t ObjectFileELF::ParseDynamicSymbols() { if (m_dynamic_symbols.size()) return m_dynamic_symbols.size(); - std::optional<DataExtractor> dynamic_data = GetDynamicData(); - if (!dynamic_data) + SectionList *section_list = GetSectionList(); + if (!section_list) return 0; - ELFDynamicWithName e; - lldb::offset_t cursor = 0; - while (e.symbol.Parse(*dynamic_data, &cursor)) { - m_dynamic_symbols.push_back(e); - if (e.symbol.d_tag == DT_NULL) - break; - } - if (std::optional<DataExtractor> dynstr_data = GetDynstrData()) { - for (ELFDynamicWithName &entry : m_dynamic_symbols) { - switch (entry.symbol.d_tag) { - case DT_NEEDED: - case DT_SONAME: - case DT_RPATH: - case DT_RUNPATH: - case DT_AUXILIARY: - case DT_FILTER: { - lldb::offset_t cursor = entry.symbol.d_val; - const char *name = dynstr_data->GetCStr(&cursor); - if (name) - entry.name = std::string(name); - break; - } - default: + // Find the SHT_DYNAMIC section. + Section *dynsym = + section_list->FindSectionByType(eSectionTypeELFDynamicLinkInfo, true) + .get(); + if (!dynsym) + return 0; + assert(dynsym->GetObjectFile() == this); + + ELFDynamic symbol; + DataExtractor dynsym_data; + if (ReadSectionData(dynsym, dynsym_data)) { + const lldb::offset_t section_size = dynsym_data.GetByteSize(); + lldb::offset_t cursor = 0; + + while (cursor < section_size) { + if (!symbol.Parse(dynsym_data, &cursor)) break; - } + + m_dynamic_symbols.push_back(symbol); } } + return m_dynamic_symbols.size(); } const ELFDynamic *ObjectFileELF::FindDynamicSymbol(unsigned tag) { if (!ParseDynamicSymbols()) return nullptr; - for (const auto &entry : m_dynamic_symbols) { - if (entry.symbol.d_tag == tag) - return &entry.symbol; + + DynamicSymbolCollIter I = m_dynamic_symbols.begin(); + DynamicSymbolCollIter E = m_dynamic_symbols.end(); + for (; I != E; ++I) { + ELFDynamic *symbol = &*I; + + if (symbol->d_tag == tag) + return symbol; } + return nullptr; } @@ -3200,10 +3230,7 @@ void ObjectFileELF::Dump(Stream *s) { ArchSpec header_arch = GetArchitecture(); *s << ", file = '" << m_file - << "', arch = " << header_arch.GetArchitectureName(); - if (m_memory_addr != LLDB_INVALID_ADDRESS) - s->Printf(", addr = %#16.16" PRIx64, m_memory_addr); - s->EOL(); + << "', arch = " << header_arch.GetArchitectureName() << "\n"; DumpELFHeader(s, m_header); s->EOL(); @@ -3221,8 +3248,6 @@ void ObjectFileELF::Dump(Stream *s) { s->EOL(); DumpDependentModules(s); s->EOL(); - DumpELFDynamic(s); - s->EOL(); } // DumpELFHeader @@ -3467,111 +3492,6 @@ void ObjectFileELF::DumpDependentModules(lldb_private::Stream *s) { } } -std::string static getDynamicTagAsString(uint16_t Arch, uint64_t Type) { -#define DYNAMIC_STRINGIFY_ENUM(tag, value) \ - case value: \ - return #tag; - -#define DYNAMIC_TAG(n, v) - switch (Arch) { - case llvm::ELF::EM_AARCH64: - switch (Type) { -#define AARCH64_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value) -#include "llvm/BinaryFormat/DynamicTags.def" -#undef AARCH64_DYNAMIC_TAG - } - break; - - case llvm::ELF::EM_HEXAGON: - switch (Type) { -#define HEXAGON_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value) -#include "llvm/BinaryFormat/DynamicTags.def" -#undef HEXAGON_DYNAMIC_TAG - } - break; - - case llvm::ELF::EM_MIPS: - switch (Type) { -#define MIPS_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value) -#include "llvm/BinaryFormat/DynamicTags.def" -#undef MIPS_DYNAMIC_TAG - } - break; - - case llvm::ELF::EM_PPC: - switch (Type) { -#define PPC_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value) -#include "llvm/BinaryFormat/DynamicTags.def" -#undef PPC_DYNAMIC_TAG - } - break; - - case llvm::ELF::EM_PPC64: - switch (Type) { -#define PPC64_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value) -#include "llvm/BinaryFormat/DynamicTags.def" -#undef PPC64_DYNAMIC_TAG - } - break; - - case llvm::ELF::EM_RISCV: - switch (Type) { -#define RISCV_DYNAMIC_TAG(name, value) DYNAMIC_STRINGIFY_ENUM(name, value) -#include "llvm/BinaryFormat/DynamicTags.def" -#undef RISCV_DYNAMIC_TAG - } - break; - } -#undef DYNAMIC_TAG - switch (Type) { -// Now handle all dynamic tags except the architecture specific ones -#define AARCH64_DYNAMIC_TAG(name, value) -#define MIPS_DYNAMIC_TAG(name, value) -#define HEXAGON_DYNAMIC_TAG(name, value) -#define PPC_DYNAMIC_TAG(name, value) -#define PPC64_DYNAMIC_TAG(name, value) -#define RISCV_DYNAMIC_TAG(name, value) -// Also ignore marker tags such as DT_HIOS (maps to DT_VERNEEDNUM), etc. -#define DYNAMIC_TAG_MARKER(name, value) -#define DYNAMIC_TAG(name, value) \ - case value: \ - return #name; -#include "llvm/BinaryFormat/DynamicTags.def" -#undef DYNAMIC_TAG -#undef AARCH64_DYNAMIC_TAG -#undef MIPS_DYNAMIC_TAG -#undef HEXAGON_DYNAMIC_TAG -#undef PPC_DYNAMIC_TAG -#undef PPC64_DYNAMIC_TAG -#undef RISCV_DYNAMIC_TAG -#undef DYNAMIC_TAG_MARKER -#undef DYNAMIC_STRINGIFY_ENUM - default: - return "<unknown:>0x" + llvm::utohexstr(Type, true); - } -} - -void ObjectFileELF::DumpELFDynamic(lldb_private::Stream *s) { - ParseDynamicSymbols(); - if (m_dynamic_symbols.empty()) - return; - - s->PutCString(".dynamic:\n"); - s->PutCString("IDX d_tag d_val/d_ptr\n"); - s->PutCString("==== ---------------- ------------------\n"); - uint32_t idx = 0; - for (const auto &entry : m_dynamic_symbols) { - s->Printf("[%2u] ", idx++); - s->Printf( - "%-16s 0x%16.16" PRIx64, - getDynamicTagAsString(m_header.e_machine, entry.symbol.d_tag).c_str(), - entry.symbol.d_ptr); - if (!entry.name.empty()) - s->Printf(" \"%s\"", entry.name.c_str()); - s->EOL(); - } -} - ArchSpec ObjectFileELF::GetArchitecture() { if (!ParseHeader()) return ArchSpec(); @@ -3744,24 +3664,7 @@ llvm::ArrayRef<ELFProgramHeader> ObjectFileELF::ProgramHeaders() { } DataExtractor ObjectFileELF::GetSegmentData(const ELFProgramHeader &H) { - // Try and read the program header from our cached m_data which can come from - // the file on disk being mmap'ed or from the initial part of the ELF file we - // read from memory and cached. - DataExtractor data = DataExtractor(m_data, H.p_offset, H.p_filesz); - if (data.GetByteSize() == H.p_filesz) - return data; - if (IsInMemory()) { - // We have a ELF file in process memory, read the program header data from - // the process. - if (ProcessSP process_sp = m_process_wp.lock()) { - const lldb::offset_t base_file_addr = GetBaseAddress().GetFileAddress(); - const addr_t load_bias = m_memory_addr - base_file_addr; - const addr_t data_addr = H.p_vaddr + load_bias; - if (DataBufferSP data_sp = ReadMemory(process_sp, data_addr, H.p_memsz)) - return DataExtractor(data_sp, GetByteOrder(), GetAddressByteSize()); - } - } - return DataExtractor(); + return DataExtractor(m_data, H.p_offset, H.p_filesz); } bool ObjectFileELF::AnySegmentHasPhysicalAddress() { @@ -3801,88 +3704,3 @@ ObjectFileELF::MapFileDataWritable(const FileSpec &file, uint64_t Size, return FileSystem::Instance().CreateWritableDataBuffer(file.GetPath(), Size, Offset); } - -std::optional<DataExtractor> ObjectFileELF::GetDynstrData() { - if (SectionList *section_list = GetSectionList()) { - // Find the SHT_DYNAMIC section. - if (Section *dynamic = - section_list - ->FindSectionByType(eSectionTypeELFDynamicLinkInfo, true) - .get()) { - assert(dynamic->GetObjectFile() == this); - if (const ELFSectionHeaderInfo *header = - GetSectionHeaderByIndex(dynamic->GetID())) { - // sh_link: section header index of string table used by entries in - // the section. - if (Section *dynstr = - section_list->FindSectionByID(header->sh_link).get()) { - DataExtractor data; - if (ReadSectionData(dynstr, data)) - return data; - } - } - } - } - - // Every ELF file which represents an executable or shared library has - // mandatory .dynamic entries. Two of these values are DT_STRTAB and DT_STRSZ - // and represent the dynamic symbol tables's string table. These are needed - // by the dynamic loader and we can read them from a process' address space. - // - // When loading and ELF file from memory, only the program headers end up - // being mapped into memory, and we can find these values in the PT_DYNAMIC - // segment. - const ELFDynamic *strtab = FindDynamicSymbol(DT_STRTAB); - const ELFDynamic *strsz = FindDynamicSymbol(DT_STRSZ); - if (strtab == nullptr || strsz == nullptr) - return std::nullopt; - - if (ProcessSP process_sp = m_process_wp.lock()) { - if (DataBufferSP data_sp = - ReadMemory(process_sp, strtab->d_ptr, strsz->d_val)) - return DataExtractor(data_sp, GetByteOrder(), GetAddressByteSize()); - } else { - // We have an ELF file with no section headers or we didn't find the - // .dynamic section. Try and find the .dynstr section. - Address addr; - if (addr.ResolveAddressUsingFileSections(strtab->d_ptr, GetSectionList())) { - DataExtractor data; - addr.GetSection()->GetSectionData(data); - return DataExtractor(data, - strtab->d_ptr - addr.GetSection()->GetFileAddress(), - strsz->d_val); - } - } - return std::nullopt; -} - -std::optional<lldb_private::DataExtractor> ObjectFileELF::GetDynamicData() { - DataExtractor data; - // The PT_DYNAMIC program header describes where the .dynamic section is and - // doesn't require parsing section headers. The PT_DYNAMIC is required by - // executables and shared libraries so it will always be available. - for (const ELFProgramHeader &H : ProgramHeaders()) { - if (H.p_type == llvm::ELF::PT_DYNAMIC) { - data = GetSegmentData(H); - if (data.GetByteSize() > 0) { - m_dynamic_base_addr = H.p_vaddr; - return data; - } - } - } - // Fall back to using section headers. - if (SectionList *section_list = GetSectionList()) { - // Find the SHT_DYNAMIC section. - if (Section *dynamic = - section_list - ->FindSectionByType(eSectionTypeELFDynamicLinkInfo, true) - .get()) { - assert(dynamic->GetObjectFile() == this); - if (ReadSectionData(dynamic, data)) { - m_dynamic_base_addr = dynamic->GetFileAddress(); - return data; - } - } - } - return std::nullopt; -} |