[Lldb-commits] [lldb] f14e1a8 - Revert "Add support for reading the dynamic symbol table from PT_DYNAMIC (#112596)"
Shubham Sandeep Rastogi via lldb-commits
lldb-commits at lists.llvm.org
Mon Nov 18 11:10:07 PST 2024
Author: Shubham Sandeep Rastogi
Date: 2024-11-18T11:09:58-08:00
New Revision: f14e1a8597f83fa5bbc78befcb7059144d58ff5c
URL: https://github.com/llvm/llvm-project/commit/f14e1a8597f83fa5bbc78befcb7059144d58ff5c
DIFF: https://github.com/llvm/llvm-project/commit/f14e1a8597f83fa5bbc78befcb7059144d58ff5c.diff
LOG: Revert "Add support for reading the dynamic symbol table from PT_DYNAMIC (#112596)"
This reverts commit a7b2e73bcaa91255a20f1f2e692bec9eb6c17022.
This patch broke the greendragon bot
Failed Tests (10):
lldb-api :: python_api/sbplatform/TestLocateModuleCallback.py
lldb-unit :: Target/./TargetTests/LocateModuleCallbackTest/GetOrCreateModuleCallbackSuccessWithModuleAndSymbol
lldb-unit :: Target/./TargetTests/LocateModuleCallbackTest/GetOrCreateModuleCallbackSuccessWithOnlySymbol
lldb-unit :: Target/./TargetTests/LocateModuleCallbackTest/GetOrCreateModuleCallbackSuccessWithSymbolAsModule
lldb-unit :: Target/./TargetTests/LocateModuleCallbackTest/GetOrCreateModuleCallbackSuccessWithSymbolAsModuleAndSymbol
lldb-unit :: Target/./TargetTests/LocateModuleCallbackTest/GetOrCreateModuleCallbackSuccessWithSymbolByPlatformUUID
lldb-unit :: Target/./TargetTests/LocateModuleCallbackTest/GetOrCreateModuleWithCachedModuleAndSymbol
lldb-unit :: Target/./TargetTests/ModuleCacheTest/GetAndPut
lldb-unit :: Target/./TargetTests/ModuleCacheTest/GetAndPutStrangeHostname
lldb-unit :: Target/./TargetTests/ModuleCacheTest/GetAndPutUuidExists
Added:
Modified:
lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
Removed:
lldb/test/Shell/ObjectFile/ELF/elf-dynsym.test
################################################################################
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 8df226817326dd..9c7dff8127f473 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -44,7 +44,6 @@
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/MipsABIFlags.h"
-#include "lldb/Target/Process.h"
#define CASE_AND_STREAM(s, def, width) \
case def: \
@@ -3008,10 +3007,9 @@ void ObjectFileELF::ParseSymtab(Symtab &lldb_symtab) {
// section, nomatter if .symtab was already parsed or not. This is because
// minidebuginfo normally removes the .symtab symbols which have their
// matching .dynsym counterparts.
- Section *dynsym = nullptr;
if (!symtab ||
GetSectionList()->FindSectionByName(ConstString(".gnu_debugdata"))) {
- dynsym =
+ Section *dynsym =
section_list->FindSectionByType(eSectionTypeELFDynamicSymbols, true)
.get();
if (dynsym) {
@@ -3021,20 +3019,6 @@ void ObjectFileELF::ParseSymtab(Symtab &lldb_symtab) {
m_address_class_map.merge(address_class_map);
}
}
- if (!dynsym) {
- // Try and read the dynamic symbol table from the .dynamic section.
- uint32_t num_symbols = 0;
- std::optional<DataExtractor> symtab_data =
- GetDynsymDataFromDynamic(num_symbols);
- std::optional<DataExtractor> strtab_data = GetDynstrData();
- if (symtab_data && strtab_data) {
- auto [num_symbols_parsed, address_class_map] =
- ParseSymbols(&lldb_symtab, symbol_id, section_list, num_symbols,
- symtab_data.value(), strtab_data.value());
- symbol_id += num_symbols_parsed;
- m_address_class_map.merge(address_class_map);
- }
- }
// DT_JMPREL
// If present, this entry's d_ptr member holds the address of
@@ -3844,33 +3828,6 @@ ObjectFileELF::MapFileDataWritable(const FileSpec &file, uint64_t Size,
Offset);
}
-std::optional<DataExtractor>
-ObjectFileELF::ReadDataFromDynamic(const ELFDynamic *dyn, uint64_t length,
- uint64_t offset) {
- // ELFDynamic values contain a "d_ptr" member that will be a load address if
- // we have an ELF file read from memory, or it will be a file address if it
- // was read from a ELF file. This function will correctly fetch data pointed
- // to by the ELFDynamic::d_ptr, or return std::nullopt if the data isn't
- // available.
- const lldb::addr_t d_ptr_addr = dyn->d_ptr + offset;
- if (ProcessSP process_sp = m_process_wp.lock()) {
- if (DataBufferSP data_sp = ReadMemory(process_sp, d_ptr_addr, length))
- 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(d_ptr_addr, GetSectionList()))
- return std::nullopt;
- DataExtractor data;
- addr.GetSection()->GetSectionData(data);
- return DataExtractor(data,
- d_ptr_addr - addr.GetSection()->GetFileAddress(),
- length);
- }
- return std::nullopt;
-}
-
std::optional<DataExtractor> ObjectFileELF::GetDynstrData() {
if (SectionList *section_list = GetSectionList()) {
// Find the SHT_DYNAMIC section.
@@ -3898,15 +3855,31 @@ std::optional<DataExtractor> ObjectFileELF::GetDynstrData() {
// 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 are
- // guaranteed end up being mapped into memory, and we can find these values in
- // the PT_DYNAMIC segment.
+ // 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;
- return ReadDataFromDynamic(strtab, strsz->d_val, /*offset=*/0);
+ 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() {
@@ -3939,116 +3912,3 @@ std::optional<lldb_private::DataExtractor> ObjectFileELF::GetDynamicData() {
}
return std::nullopt;
}
-
-std::optional<uint32_t> ObjectFileELF::GetNumSymbolsFromDynamicHash() {
- const ELFDynamic *hash = FindDynamicSymbol(DT_HASH);
- if (hash == nullptr)
- return std::nullopt;
-
- // The DT_HASH header looks like this:
- struct DtHashHeader {
- uint32_t nbucket;
- uint32_t nchain;
- };
- if (auto data = ReadDataFromDynamic(hash, 8)) {
- // We don't need the number of buckets value "nbucket", we just need the
- // "nchain" value which contains the number of symbols.
- offset_t offset = offsetof(DtHashHeader, nchain);
- return data->GetU32(&offset);
- }
-
- return std::nullopt;
-}
-
-std::optional<uint32_t> ObjectFileELF::GetNumSymbolsFromDynamicGnuHash() {
- const ELFDynamic *gnu_hash = FindDynamicSymbol(DT_GNU_HASH);
- if (gnu_hash == nullptr)
- return std::nullopt;
-
- // Create a DT_GNU_HASH header
- // https://flapenguin.me/elf-dt-gnu-hash
- struct DtGnuHashHeader {
- uint32_t nbuckets = 0;
- uint32_t symoffset = 0;
- uint32_t bloom_size = 0;
- uint32_t bloom_shift = 0;
- };
- uint32_t num_symbols = 0;
- // Read enogh data for the DT_GNU_HASH header so we can extract the values.
- if (auto data = ReadDataFromDynamic(gnu_hash, sizeof(DtGnuHashHeader))) {
- offset_t offset = 0;
- DtGnuHashHeader header;
- header.nbuckets = data->GetU32(&offset);
- header.symoffset = data->GetU32(&offset);
- header.bloom_size = data->GetU32(&offset);
- header.bloom_shift = data->GetU32(&offset);
- const size_t addr_size = GetAddressByteSize();
- const addr_t buckets_offset =
- sizeof(DtGnuHashHeader) + addr_size * header.bloom_size;
- std::vector<uint32_t> buckets;
- if (auto bucket_data = ReadDataFromDynamic(gnu_hash, header.nbuckets * 4, buckets_offset)) {
- offset = 0;
- for (uint32_t i = 0; i < header.nbuckets; ++i)
- buckets.push_back(bucket_data->GetU32(&offset));
- // Locate the chain that handles the largest index bucket.
- uint32_t last_symbol = 0;
- for (uint32_t bucket_value : buckets)
- last_symbol = std::max(bucket_value, last_symbol);
- if (last_symbol < header.symoffset) {
- num_symbols = header.symoffset;
- } else {
- // Walk the bucket's chain to add the chain length to the total.
- const addr_t chains_base_offset = buckets_offset + header.nbuckets * 4;
- for (;;) {
- if (auto chain_entry_data = ReadDataFromDynamic(gnu_hash, 4, chains_base_offset + (last_symbol - header.symoffset) * 4)) {
- offset = 0;
- uint32_t chain_entry = chain_entry_data->GetU32(&offset);
- ++last_symbol;
- // If the low bit is set, this entry is the end of the chain.
- if (chain_entry & 1)
- break;
- } else {
- break;
- }
- }
- num_symbols = last_symbol;
- }
- }
- }
- if (num_symbols > 0)
- return num_symbols;
-
- return std::nullopt;
-}
-
-std::optional<DataExtractor>
-ObjectFileELF::GetDynsymDataFromDynamic(uint32_t &num_symbols) {
- // Every ELF file which represents an executable or shared library has
- // mandatory .dynamic entries. The DT_SYMTAB value contains a pointer to the
- // symbol table, and DT_SYMENT contains the size of a symbol table entry.
- // We then can use either the DT_HASH or DT_GNU_HASH to find the number of
- // symbols in the symbol table as the symbol count is not stored in the
- // .dynamic section as a key/value pair.
- //
- // 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.
- num_symbols = 0;
- // Get the process in case this is an in memory ELF file.
- ProcessSP process_sp(m_process_wp.lock());
- const ELFDynamic *symtab = FindDynamicSymbol(DT_SYMTAB);
- const ELFDynamic *syment = FindDynamicSymbol(DT_SYMENT);
- // DT_SYMTAB and DT_SYMENT are mandatory.
- if (symtab == nullptr || syment == nullptr)
- return std::nullopt;
-
- if (std::optional<uint32_t> syms = GetNumSymbolsFromDynamicHash())
- num_symbols = *syms;
- else if (std::optional<uint32_t> syms = GetNumSymbolsFromDynamicGnuHash())
- num_symbols = *syms;
- else
- return std::nullopt;
- if (num_symbols == 0)
- return std::nullopt;
- return ReadDataFromDynamic(symtab, syment->d_val * num_symbols);
-}
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
index 16c216eb81e729..aba3a5bfcbf5b6 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
@@ -435,47 +435,6 @@ class ObjectFileELF : public lldb_private::ObjectFile {
/// \return The bytes that represent the string table data or \c std::nullopt
/// if an error occured.
std::optional<lldb_private::DataExtractor> GetDynstrData();
-
- /// Read the bytes pointed to by the \a dyn dynamic entry.
- ///
- /// ELFDynamic::d_ptr values contain file addresses if we load the ELF file
- /// form a file on disk, or they contain load addresses if they were read
- /// from memory. This function will correctly extract the data in both cases
- /// if it is available.
- ///
- /// \param[in] dyn The dynamic entry to use to fetch the data from.
- ///
- /// \param[in] length The number of bytes to read.
- ///
- /// \param[in] offset The number of bytes to skip after the d_ptr value
- /// before reading data.
- ///
- /// \return The bytes that represent the dynanic entries data or
- /// \c std::nullopt if an error occured or the data is not available.
- std::optional<lldb_private::DataExtractor>
- ReadDataFromDynamic(const elf::ELFDynamic *dyn, uint64_t length,
- uint64_t offset = 0);
-
- /// Get the bytes that represent the dynamic symbol table from the .dynamic
- /// section from process memory.
- ///
- /// This functon uses the DT_SYMTAB value from the .dynamic section to read
- /// the symbols table data from process memory. The number of symbols in the
- /// symbol table is calculated by looking at the DT_HASH or DT_GNU_HASH
- /// values as the symbol count isn't stored in the .dynamic section.
- ///
- /// \return The bytes that represent the symbol table data from the .dynamic
- /// section or section headers or \c std::nullopt if an error
- /// occured or if there is no dynamic symbol data available.
- std::optional<lldb_private::DataExtractor>
- GetDynsymDataFromDynamic(uint32_t &num_symbols);
-
- /// Get the number of symbols from the DT_HASH dynamic entry.
- std::optional<uint32_t> GetNumSymbolsFromDynamicHash();
-
- /// Get the number of symbols from the DT_GNU_HASH dynamic entry.
- std::optional<uint32_t> GetNumSymbolsFromDynamicGnuHash();
-
};
#endif // LLDB_SOURCE_PLUGINS_OBJECTFILE_ELF_OBJECTFILEELF_H
diff --git a/lldb/test/Shell/ObjectFile/ELF/elf-dynsym.test b/lldb/test/Shell/ObjectFile/ELF/elf-dynsym.test
deleted file mode 100644
index 7d948e2cd225c6..00000000000000
--- a/lldb/test/Shell/ObjectFile/ELF/elf-dynsym.test
+++ /dev/null
@@ -1,42 +0,0 @@
-// This test verifies that loading an ELF file that has no section headers can
-// load the dynamic symbol table using the DT_SYMTAB, DT_SYMENT, DT_HASH or
-// the DT_GNU_HASH .dynamic key/value pairs that are loaded via the PT_DYNAMIC
-// segment.
-
-// RUN: llvm-mc -triple=x86_64-pc-linux -filetype=obj \
-// RUN: -o - - <<<".globl defined, undefined; defined:" | \
-// RUN: ld.lld /dev/stdin -o - --hash-style=gnu -export-dynamic -shared \
-// RUN: -z nosectionheader -o %t.gnu
-// RUN: %lldb %t.gnu -b \
-// RUN: -o "image dump objfile" \
-// RUN: | FileCheck %s --dump-input=always --check-prefix=GNU
-// GNU: (lldb) image dump objfile
-// GNU: Dumping headers for 1 module(s).
-// GNU: ObjectFileELF, file =
-// GNU: ELF Header
-// GNU: e_type = 0x0003 ET_DYN
-// Make sure there are no section headers
-// GNU: e_shnum = 0x00000000
-// Make sure we were able to load the symbols
-// GNU: Symtab, file = {{.*}}elf-dynsym.test.tmp.gnu, num_symbols = 2:
-// GNU-DAG: undefined
-// GNU-DAG: defined
-
-// RUN: llvm-mc -triple=x86_64-pc-linux -filetype=obj \
-// RUN: -o - - <<<".globl defined, undefined; defined:" | \
-// RUN: ld.lld /dev/stdin -o - --hash-style=sysv -export-dynamic -shared \
-// RUN: -z nosectionheader -o %t.sysv
-// RUN: %lldb %t.sysv -b \
-// RUN: -o "image dump objfile" \
-// RUN: | FileCheck %s --dump-input=always --check-prefix=HASH
-// HASH: (lldb) image dump objfile
-// HASH: Dumping headers for 1 module(s).
-// HASH: ObjectFileELF, file =
-// HASH: ELF Header
-// HASH: e_type = 0x0003 ET_DYN
-// Make sure there are no section headers
-// HASH: e_shnum = 0x00000000
-// Make sure we were able to load the symbols
-// HASH: Symtab, file = {{.*}}elf-dynsym.test.tmp.sysv, num_symbols = 2:
-// HASH-DAG: undefined
-// HASH-DAG: defined
More information about the lldb-commits
mailing list