[Lldb-commits] [lldb] [LLDB] Impove ObjectFileELF's .dynamic parsing and usage. (PR #102570)
via lldb-commits
lldb-commits at lists.llvm.org
Thu Aug 8 22:28:03 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lldb
Author: Greg Clayton (clayborg)
<details>
<summary>Changes</summary>
https://github.com/llvm/llvm-project/pull/101237 got reverted due to buildbot failures. Opening a new PR to submit this again with a fix.
This patch improves the ability of a ObjectFileELF instance to read the .dynamic section. It adds the ability to read the .dynamic section from the PT_DYNAMIC program header which is useful for ELF files that have no section headers and for ELF files that are read from memory. It cleans up the usage of the .dynamic entries so that ObjectFileELF::ParseDynamicSymbols() is the only code that parses .dynamic entries, teaches that function the read and store the string values for each .dynamic entry. We now dump the .dynamic entries in the output of "image dump objfile". It also cleans up the code that gets the dynamic string table so that it can grab it from the DT_STRTAB and DT_STRSZ .dynamic entries for when we have a ELF file with no section headers or we are reading it from memory.
---
Patch is 29.81 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/102570.diff
7 Files Affected:
- (modified) lldb/include/lldb/Symbol/ObjectFile.h (+3-2)
- (modified) lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp (+306-120)
- (modified) lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h (+34-1)
- (modified) lldb/source/Symbol/ObjectFile.cpp (+4-3)
- (added) lldb/test/Shell/ObjectFile/ELF/Inputs/memory-elf.cpp (+5)
- (added) lldb/test/Shell/ObjectFile/ELF/elf-dynamic-no-shdrs.yaml (+93)
- (added) lldb/test/Shell/ObjectFile/ELF/elf-memory.test (+55)
``````````diff
diff --git a/lldb/include/lldb/Symbol/ObjectFile.h b/lldb/include/lldb/Symbol/ObjectFile.h
index 8592323322e383..d89314d44bf671 100644
--- a/lldb/include/lldb/Symbol/ObjectFile.h
+++ b/lldb/include/lldb/Symbol/ObjectFile.h
@@ -656,8 +656,9 @@ class ObjectFile : public std::enable_shared_from_this<ObjectFile>,
// When an object file is in memory, subclasses should try and lock the
// process weak pointer. If the process weak pointer produces a valid
// ProcessSP, then subclasses can call this function to read memory.
- static lldb::DataBufferSP ReadMemory(const lldb::ProcessSP &process_sp,
- lldb::addr_t addr, size_t byte_size);
+ static lldb::WritableDataBufferSP
+ ReadMemory(const lldb::ProcessSP &process_sp, lldb::addr_t addr,
+ size_t byte_size);
// This function returns raw file contents. Do not use it if you want
// transparent decompression of section contents.
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 890db5c2748146..f348b94baad806 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -419,19 +419,35 @@ 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)) {
- 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();
- }
- }
- }
+ 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();
+
return nullptr;
}
@@ -873,42 +889,37 @@ Address ObjectFileELF::GetImageInfoAddress(Target *target) {
if (!section_list)
return Address();
- // 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);
+ for (size_t i = 0; i < m_dynamic_symbols.size(); ++i) {
+ const ELFDynamic &symbol = m_dynamic_symbols[i].symbol;
- user_id_t dynsym_id = dynsym_section_sp->GetID();
- const ELFSectionHeaderInfo *dynsym_hdr = GetSectionHeaderByIndex(dynsym_id);
- if (!dynsym_hdr)
- return Address();
+ if (symbol.d_tag != DT_DEBUG && symbol.d_tag != DT_MIPS_RLD_MAP &&
+ symbol.d_tag != DT_MIPS_RLD_MAP_REL)
+ continue;
- for (size_t i = 0; i < m_dynamic_symbols.size(); ++i) {
- ELFDynamic &symbol = m_dynamic_symbols[i];
+ // 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;
- 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.
- 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)
+ 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)
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(dyn_base + offset, error, addr, true))
+ if (target->ReadPointerFromMemory(d_load_addr, error, addr, true))
return addr;
}
if (symbol.d_tag == DT_MIPS_RLD_MAP_REL) {
@@ -916,18 +927,17 @@ Address ObjectFileELF::GetImageInfoAddress(Target *target) {
// relative to the address of the tag.
uint64_t rel_offset;
rel_offset = target->ReadUnsignedIntegerFromMemory(
- dyn_base + offset, GetAddressByteSize(), UINT64_MAX, error, true);
+ d_load_addr, GetAddressByteSize(), UINT64_MAX, error, true);
if (error.Success() && rel_offset != UINT64_MAX) {
Address addr;
addr_t debug_ptr_address =
- dyn_base + (offset - GetAddressByteSize()) + rel_offset;
+ d_load_addr - GetAddressByteSize() + rel_offset;
addr.SetOffset(debug_ptr_address);
return addr;
}
}
}
}
-
return Address();
}
@@ -970,62 +980,23 @@ 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 (!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)
+ if (ParseDynamicSymbols()) {
+ for (const auto &entry : m_dynamic_symbols) {
+ if (entry.symbol.d_tag != DT_NEEDED)
continue;
-
- 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);
+ if (!entry.name.empty()) {
+ FileSpec file_spec(entry.name);
+ FileSystem::Instance().Resolve(file_spec);
+ m_filespec_up->Append(file_spec);
+ }
}
}
-
return m_filespec_up->GetSize();
}
@@ -2472,48 +2443,47 @@ size_t ObjectFileELF::ParseDynamicSymbols() {
if (m_dynamic_symbols.size())
return m_dynamic_symbols.size();
- SectionList *section_list = GetSectionList();
- if (!section_list)
+ std::optional<DataExtractor> dynamic_data = GetDynamicData();
+ if (!dynamic_data)
return 0;
- // 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))
+ 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;
-
- m_dynamic_symbols.push_back(symbol);
+ }
+ default:
+ break;
+ }
}
}
-
return m_dynamic_symbols.size();
}
const ELFDynamic *ObjectFileELF::FindDynamicSymbol(unsigned tag) {
if (!ParseDynamicSymbols())
return nullptr;
-
- 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;
+ for (const auto &entry : m_dynamic_symbols) {
+ if (entry.symbol.d_tag == tag)
+ return &entry.symbol;
}
-
return nullptr;
}
@@ -3230,7 +3200,10 @@ void ObjectFileELF::Dump(Stream *s) {
ArchSpec header_arch = GetArchitecture();
*s << ", file = '" << m_file
- << "', arch = " << header_arch.GetArchitectureName() << "\n";
+ << "', arch = " << header_arch.GetArchitectureName();
+ if (m_memory_addr != LLDB_INVALID_ADDRESS)
+ s->Printf(", addr = %#16.16" PRIx64, m_memory_addr);
+ s->EOL();
DumpELFHeader(s, m_header);
s->EOL();
@@ -3248,6 +3221,12 @@ void ObjectFileELF::Dump(Stream *s) {
s->EOL();
DumpDependentModules(s);
s->EOL();
+ DumpELFDynamic(s);
+ s->EOL();
+ Address image_info_addr = GetImageInfoAddress(nullptr);
+ if (image_info_addr.IsValid())
+ s->Printf("image_info_address = %#16.16" PRIx64 "\n",
+ image_info_addr.GetFileAddress());
}
// DumpELFHeader
@@ -3492,6 +3471,111 @@ 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();
@@ -3664,7 +3748,24 @@ llvm::ArrayRef<ELFProgramHeader> ObjectFileELF::ProgramHeaders() {
}
DataExtractor ObjectFileELF::GetSegmentData(const ELFProgramHeader &H) {
- return DataExtractor(m_data, H.p_offset, H.p_filesz);
+ // 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();
}
bool ObjectFileELF::AnySegmentHasPhysicalAddress() {
@@ -3704,3 +3805,88 @@ 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;
+}
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
index 844e981b1d890a..aba3a5bfcbf5b6 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
@@ -183,7 +18...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/102570
More information about the lldb-commits
mailing list