[Lldb-commits] [lldb] Add support for reading the dynamic symbol table from PT_DYNAMIC (PR #112596)
Greg Clayton via lldb-commits
lldb-commits at lists.llvm.org
Wed Oct 30 11:20:17 PDT 2024
https://github.com/clayborg updated https://github.com/llvm/llvm-project/pull/112596
>From 0ff6ba499bcb04581cf5b77780f769bee05e4aef Mon Sep 17 00:00:00 2001
From: Greg Clayton <clayborg at gmail.com>
Date: Sat, 28 Sep 2024 15:05:37 -0700
Subject: [PATCH 1/3] Add support for reading the dynamic symbol table from
program headers and PT_DYNAMIC.
Allow LLDB to parse the dynamic symbol table from an ELF file or memory image in an ELF file that has no section headers. This patch uses the ability to parse the PT_DYNAMIC segment and find the DT_SYMTAB, DT_SYMENT, DT_HASH or DT_GNU_HASH to find and parse the dynamic symbol table if the section headers are not present. It also adds a helper function to read data from a .dynamic key/value pair entry correctly from the file or from memory.
---
.../Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 163 ++++-
.../Plugins/ObjectFile/ELF/ObjectFileELF.h | 34 +
.../test/Shell/ObjectFile/ELF/elf-dynsym.yaml | 631 ++++++++++++++++++
3 files changed, 811 insertions(+), 17 deletions(-)
create mode 100644 lldb/test/Shell/ObjectFile/ELF/elf-dynsym.yaml
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 10d09662c0a47a..7374ac10a1e27a 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -44,6 +44,8 @@
#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: \
@@ -2990,18 +2992,34 @@ 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.
+ bool found_dynsym = false;
if (!symtab ||
GetSectionList()->FindSectionByName(ConstString(".gnu_debugdata"))) {
Section *dynsym =
section_list->FindSectionByType(eSectionTypeELFDynamicSymbols, true)
.get();
if (dynsym) {
+ found_dynsym = true;
auto [num_symbols, address_class_map] =
ParseSymbolTable(&lldb_symtab, symbol_id, dynsym);
symbol_id += num_symbols;
m_address_class_map.merge(address_class_map);
}
}
+ if (!found_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
@@ -3811,6 +3829,33 @@ 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.
@@ -3846,23 +3891,7 @@ std::optional<DataExtractor> ObjectFileELF::GetDynstrData() {
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;
+ return ReadDataFromDynamic(strtab, strsz->d_val, /*offset=*/0);
}
std::optional<lldb_private::DataExtractor> ObjectFileELF::GetDynamicData() {
@@ -3895,3 +3924,103 @@ std::optional<lldb_private::DataExtractor> ObjectFileELF::GetDynamicData() {
}
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);
+ const ELFDynamic *hash = FindDynamicSymbol(DT_HASH);
+ const ELFDynamic *gnu_hash = FindDynamicSymbol(DT_GNU_HASH);
+ // DT_SYMTAB and DT_SYMENT are mandatory.
+ if (symtab == nullptr || syment == nullptr)
+ return std::nullopt;
+ // We must have either a DT_HASH or a DT_GNU_HASH.
+ if (hash == nullptr && gnu_hash == nullptr)
+ return std::nullopt;
+ // The number of symbols in the symbol table is the number of entries in the
+ // symbol table divided by the size of each symbol table entry.
+ // We must figure out the number of symbols in the symbol table using the
+ // DT_HASH or the DT_GNU_HASH as the number of symbols isn't stored anywhere
+ // in the .dynamic section.
+
+ lldb::offset_t offset;
+ if (hash) {
+ // The DT_HASH header contains the number of symbols in the "nchain"
+ // member. The header looks like this:
+ // struct DT_HASH_HEADER {
+ // uint32_t nbucket;
+ // uint32_t nchain;
+ // };
+ if (auto data = ReadDataFromDynamic(hash, 8)) {
+ offset = 4;
+ num_symbols = data->GetU32(&offset);
+ }
+ }
+ if (num_symbols == 0 && gnu_hash) {
+ struct DT_GNU_HASH_HEADER {
+ uint32_t nbuckets = 0;
+ uint32_t symoffset = 0;
+ uint32_t bloom_size = 0;
+ uint32_t bloom_shift = 0;
+ };
+ if (auto data = ReadDataFromDynamic(gnu_hash, sizeof(DT_GNU_HASH_HEADER))) {
+ offset = 0;
+ DT_GNU_HASH_HEADER 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(DT_GNU_HASH_HEADER) + 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)
+ ++num_symbols; // First symbol is always all zeros
+ }
+ 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 aba3a5bfcbf5b6..34d9ae74fbb23f 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
@@ -435,6 +435,40 @@ 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);
};
#endif // LLDB_SOURCE_PLUGINS_OBJECTFILE_ELF_OBJECTFILEELF_H
diff --git a/lldb/test/Shell/ObjectFile/ELF/elf-dynsym.yaml b/lldb/test/Shell/ObjectFile/ELF/elf-dynsym.yaml
new file mode 100644
index 00000000000000..2763aac1df4893
--- /dev/null
+++ b/lldb/test/Shell/ObjectFile/ELF/elf-dynsym.yaml
@@ -0,0 +1,631 @@
+## 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.
+##
+## This test will convert a shared library from yaml, strip its section headers,
+## and varify that LLDB can load the dynamic symbol table. We must manually
+## strip the section headers from a full shared library because our ELF YAML
+## support in obj2yaml/yaml2obj doesn't support ELF files with program headers
+## only, they must have sections or the file doesn't get recreated correctlty.
+
+# RUN: yaml2obj %s -o %t
+# RUN: llvm-strip --strip-sections %t -o %t.noshdrs
+
+# RUN: %lldb -b \
+# RUN: -o "target create -d '%t.noshdrs'" \
+# RUN: -o "image dump objfile" \
+# RUN: | FileCheck %s --dump-input=always
+# CHECK: (lldb) image dump objfile
+# CHECK: Dumping headers for 1 module(s).
+# CHECK: ObjectFileELF, file =
+# CHECK: ELF Header
+# Make sure there are no section headers
+# CHECK: e_shnum = 0x00000000
+# Make sure we were able to load the symbols
+# CHECK: elf-dynsym.yaml.tmp.noshdrs, num_symbols = 9:
+# CHECK: [ 0] 1 Undefined 0x0000000000000000 0x0000000000000000 0x00000022 __cxa_finalize
+# CHECK: [ 1] 2 X Undefined 0x0000000000000000 0x0000000000000000 0x00000012 puts
+# CHECK: [ 2] 3 Undefined 0x0000000000000000 0x0000000000000000 0x00000020 _ITM_deregisterTMCloneTable
+# CHECK: [ 3] 4 Undefined 0x0000000000000000 0x0000000000000000 0x00000020 __gmon_start__
+# CHECK: [ 4] 5 Undefined 0x0000000000000000 0x0000000000000000 0x00000020 _ITM_registerTMCloneTable
+# CHECK: [ 5] 6 X Code 0x0000000000001135 0x0000000000000016 0x00000012 baz()
+# CHECK: [ 6] 7 X Code 0x000000000000111f 0x0000000000000016 0x00000012 bar()
+# CHECK: [ 7] 8 X Code 0x000000000000114b 0x0000000000000016 0x00000012 biz()
+# CHECK: [ 8] 9 X Code 0x0000000000001109 0x0000000000000016 0x00000012 foo()
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_DYN
+ Machine: EM_X86_64
+ Entry: 0x1050
+ProgramHeaders:
+ - Type: PT_LOAD
+ Flags: [ PF_R ]
+ FirstSec: .note.gnu.build-id
+ LastSec: .rela.plt
+ Align: 0x1000
+ Offset: 0x0
+ - Type: PT_LOAD
+ Flags: [ PF_X, PF_R ]
+ FirstSec: .init
+ LastSec: .fini
+ VAddr: 0x1000
+ Align: 0x1000
+ Offset: 0x1000
+ - Type: PT_LOAD
+ Flags: [ PF_R ]
+ FirstSec: .rodata
+ LastSec: .eh_frame
+ VAddr: 0x2000
+ Align: 0x1000
+ Offset: 0x2000
+ - Type: PT_LOAD
+ Flags: [ PF_W, PF_R ]
+ FirstSec: .init_array
+ LastSec: .bss
+ VAddr: 0x3DC8
+ Align: 0x1000
+ Offset: 0x2DC8
+ - Type: PT_DYNAMIC
+ Flags: [ PF_W, PF_R ]
+ FirstSec: .dynamic
+ LastSec: .dynamic
+ VAddr: 0x3DE0
+ Align: 0x8
+ Offset: 0x2DE0
+ - Type: PT_NOTE
+ Flags: [ PF_R ]
+ FirstSec: .note.gnu.build-id
+ LastSec: .note.gnu.build-id
+ VAddr: 0x238
+ Align: 0x4
+ Offset: 0x238
+ - Type: PT_GNU_EH_FRAME
+ Flags: [ PF_R ]
+ FirstSec: .eh_frame_hdr
+ LastSec: .eh_frame_hdr
+ VAddr: 0x202C
+ Align: 0x4
+ Offset: 0x202C
+ - Type: PT_GNU_STACK
+ Flags: [ PF_W, PF_R ]
+ Align: 0x10
+ Offset: 0x0
+ - Type: PT_GNU_RELRO
+ Flags: [ PF_R ]
+ FirstSec: .init_array
+ LastSec: .got
+ VAddr: 0x3DC8
+ Offset: 0x2DC8
+Sections:
+ - Name: .note.gnu.build-id
+ Type: SHT_NOTE
+ Flags: [ SHF_ALLOC ]
+ Address: 0x238
+ AddressAlign: 0x4
+ Notes:
+ - Name: GNU
+ Desc: E98A07D11FFBEC0C57492B71EEE529C65D183408
+ Type: NT_PRPSINFO
+ - Name: .gnu.hash
+ Type: SHT_GNU_HASH
+ Flags: [ SHF_ALLOC ]
+ Address: 0x260
+ Link: .dynsym
+ AddressAlign: 0x8
+ Header:
+ SymNdx: 0x6
+ Shift2: 0x6
+ BloomFilter: [ 0x3021080800001010 ]
+ HashBuckets: [ 0x0, 0x6, 0x0 ]
+ HashValues: [ 0x6A5EBD44, 0x6A5EBC3C, 0x6A5EDF4C, 0x6A6128EB ]
+ - Name: .dynsym
+ Type: SHT_DYNSYM
+ Flags: [ SHF_ALLOC ]
+ Address: 0x298
+ Link: .dynstr
+ AddressAlign: 0x8
+ - Name: .dynstr
+ Type: SHT_STRTAB
+ Flags: [ SHF_ALLOC ]
+ Address: 0x388
+ AddressAlign: 0x1
+ - Name: .gnu.version
+ Type: SHT_GNU_versym
+ Flags: [ SHF_ALLOC ]
+ Address: 0x44E
+ Link: .dynsym
+ AddressAlign: 0x2
+ Entries: [ 0, 2, 2, 0, 0, 0, 1, 1, 1, 1 ]
+ - Name: .gnu.version_r
+ Type: SHT_GNU_verneed
+ Flags: [ SHF_ALLOC ]
+ Address: 0x468
+ Link: .dynstr
+ AddressAlign: 0x8
+ Dependencies:
+ - Version: 1
+ File: libc.so.6
+ Entries:
+ - Name: GLIBC_2.2.5
+ Hash: 157882997
+ Flags: 0
+ Other: 2
+ - Name: .rela.dyn
+ Type: SHT_RELA
+ Flags: [ SHF_ALLOC ]
+ Address: 0x488
+ Link: .dynsym
+ AddressAlign: 0x8
+ Relocations:
+ - Offset: 0x3DC8
+ Type: R_X86_64_RELATIVE
+ Addend: 4352
+ - Offset: 0x3DD0
+ Type: R_X86_64_RELATIVE
+ Addend: 4288
+ - Offset: 0x3DD8
+ Type: R_X86_64_RELATIVE
+ Addend: 15832
+ - Offset: 0x3FE0
+ Symbol: __cxa_finalize
+ Type: R_X86_64_GLOB_DAT
+ - Offset: 0x3FE8
+ Symbol: _ITM_deregisterTMCloneTable
+ Type: R_X86_64_GLOB_DAT
+ - Offset: 0x3FF0
+ Symbol: __gmon_start__
+ Type: R_X86_64_GLOB_DAT
+ - Offset: 0x3FF8
+ Symbol: _ITM_registerTMCloneTable
+ Type: R_X86_64_GLOB_DAT
+ - Name: .rela.plt
+ Type: SHT_RELA
+ Flags: [ SHF_ALLOC, SHF_INFO_LINK ]
+ Address: 0x530
+ Link: .dynsym
+ AddressAlign: 0x8
+ Info: .got.plt
+ Relocations:
+ - Offset: 0x4018
+ Symbol: __cxa_finalize
+ Type: R_X86_64_JUMP_SLOT
+ - Offset: 0x4020
+ Symbol: puts
+ Type: R_X86_64_JUMP_SLOT
+ - Name: .init
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x1000
+ AddressAlign: 0x4
+ Offset: 0x1000
+ Content: F30F1EFA4883EC08488B05E12F00004885C07402FFD04883C408C3
+ - Name: .plt
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x1020
+ AddressAlign: 0x10
+ EntSize: 0x10
+ Content: FF35E22F0000FF25E42F00000F1F4000FF25E22F00006800000000E9E0FFFFFFFF25DA2F00006801000000E9D0FFFFFF
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x1050
+ AddressAlign: 0x10
+ Content: 488D3DD12F0000488D05CA2F00004839F87415488B057E2F00004885C07409FFE00F1F8000000000C30F1F8000000000488D3DA12F0000488D359A2F00004829FE4889F048C1EE3F48C1F8034801C648D1FE7414488B054D2F00004885C07408FFE0660F1F440000C30F1F8000000000F30F1EFA803D5D2F000000752B5548833D0A2F0000004889E5740C488D3DF62C0000E849FFFFFFE864FFFFFFC605352F0000015DC30F1F00C30F1F8000000000F30F1EFAE977FFFFFF554889E5488D05EC0E00004889C7E824FFFFFF905DC3554889E5488D05E10E00004889C7E80EFFFFFF905DC3554889E5488D05D60E00004889C7E8F8FEFFFF905DC3554889E5488D05CB0E00004889C7E8E2FEFFFF905DC3
+ - Name: .fini
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x1164
+ AddressAlign: 0x4
+ Content: F30F1EFA4883EC084883C408C3
+ - Name: .rodata
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC ]
+ Address: 0x2000
+ AddressAlign: 0x1
+ Offset: 0x2000
+ Content: 766F696420666F6F282900766F696420626172282900766F69642062617A282900766F69642062697A282900
+ - Name: .eh_frame_hdr
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC ]
+ Address: 0x202C
+ AddressAlign: 0x4
+ Content: 011B033B3000000005000000F4EFFFFF4C000000DDF0FFFF74000000F3F0FFFF9400000009F1FFFFB40000001FF1FFFFD4000000
+ - Name: .eh_frame
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC ]
+ Address: 0x2060
+ AddressAlign: 0x8
+ Content: 1400000000000000017A5200017810011B0C070890010000240000001C000000A0EFFFFF30000000000E10460E184A0F0B770880003F1A3B2A332422000000001C0000004400000061F0FFFF1600000000410E108602430D06510C07080000001C0000006400000057F0FFFF1600000000410E108602430D06510C07080000001C000000840000004DF0FFFF1600000000410E108602430D06510C07080000001C000000A400000043F0FFFF1600000000410E108602430D06510C070800000000000000
+ - Name: .init_array
+ Type: SHT_INIT_ARRAY
+ Flags: [ SHF_WRITE, SHF_ALLOC ]
+ Address: 0x3DC8
+ AddressAlign: 0x8
+ EntSize: 0x8
+ Offset: 0x2DC8
+ Content: '0011000000000000'
+ - Name: .fini_array
+ Type: SHT_FINI_ARRAY
+ Flags: [ SHF_WRITE, SHF_ALLOC ]
+ Address: 0x3DD0
+ AddressAlign: 0x8
+ EntSize: 0x8
+ Content: C010000000000000
+ - Name: .data.rel.ro
+ Type: SHT_PROGBITS
+ Flags: [ SHF_WRITE, SHF_ALLOC ]
+ Address: 0x3DD8
+ AddressAlign: 0x8
+ Content: D83D000000000000
+ - Name: .dynamic
+ Type: SHT_DYNAMIC
+ Flags: [ SHF_WRITE, SHF_ALLOC ]
+ Address: 0x3DE0
+ Link: .dynstr
+ AddressAlign: 0x8
+ Entries:
+ - Tag: DT_NEEDED
+ Value: 0x7A
+ - Tag: DT_NEEDED
+ Value: 0x89
+ - Tag: DT_NEEDED
+ Value: 0x93
+ - Tag: DT_NEEDED
+ Value: 0xA1
+ - Tag: DT_SONAME
+ Value: 0xAB
+ - Tag: DT_INIT
+ Value: 0x1000
+ - Tag: DT_FINI
+ Value: 0x1164
+ - Tag: DT_INIT_ARRAY
+ Value: 0x3DC8
+ - Tag: DT_INIT_ARRAYSZ
+ Value: 0x8
+ - Tag: DT_FINI_ARRAY
+ Value: 0x3DD0
+ - Tag: DT_FINI_ARRAYSZ
+ Value: 0x8
+ - Tag: DT_GNU_HASH
+ Value: 0x260
+ - Tag: DT_STRTAB
+ Value: 0x388
+ - Tag: DT_SYMTAB
+ Value: 0x298
+ - Tag: DT_STRSZ
+ Value: 0xC5
+ - Tag: DT_SYMENT
+ Value: 0x18
+ - Tag: DT_PLTGOT
+ Value: 0x4000
+ - Tag: DT_PLTRELSZ
+ Value: 0x30
+ - Tag: DT_PLTREL
+ Value: 0x7
+ - Tag: DT_JMPREL
+ Value: 0x530
+ - Tag: DT_RELA
+ Value: 0x488
+ - Tag: DT_RELASZ
+ Value: 0xA8
+ - Tag: DT_RELAENT
+ Value: 0x18
+ - Tag: DT_VERNEED
+ Value: 0x468
+ - Tag: DT_VERNEEDNUM
+ Value: 0x1
+ - Tag: DT_VERSYM
+ Value: 0x44E
+ - Tag: DT_RELACOUNT
+ Value: 0x3
+ - Tag: DT_NULL
+ Value: 0x0
+ - Tag: DT_NULL
+ Value: 0x0
+ - Tag: DT_NULL
+ Value: 0x0
+ - Tag: DT_NULL
+ Value: 0x0
+ - Tag: DT_NULL
+ Value: 0x0
+ - Name: .got
+ Type: SHT_PROGBITS
+ Flags: [ SHF_WRITE, SHF_ALLOC ]
+ Address: 0x3FE0
+ AddressAlign: 0x8
+ EntSize: 0x8
+ Content: '0000000000000000000000000000000000000000000000000000000000000000'
+ - Name: .got.plt
+ Type: SHT_PROGBITS
+ Flags: [ SHF_WRITE, SHF_ALLOC ]
+ Address: 0x4000
+ AddressAlign: 0x8
+ EntSize: 0x8
+ Content: E03D0000000000000000000000000000000000000000000036100000000000004610000000000000
+ - Name: .bss
+ Type: SHT_NOBITS
+ Flags: [ SHF_WRITE, SHF_ALLOC ]
+ Address: 0x4028
+ AddressAlign: 0x1
+ Size: 0x8
+ - Name: .comment
+ Type: SHT_PROGBITS
+ Flags: [ SHF_MERGE, SHF_STRINGS ]
+ AddressAlign: 0x1
+ EntSize: 0x1
+ Content: 4743433A2028474E55292031312E352E302032303234303731392028526564204861742031312E352E302D322900
+ - Name: .gnu.build.attributes
+ Type: SHT_NOTE
+ Address: 0x6030
+ AddressAlign: 0x4
+ Notes:
+ - Name: "GA$\x013a1"
+ Desc: '50100000000000005010000000000000'
+ Type: NT_GNU_BUILD_ATTRIBUTE_OPEN
+ - Name: "GA$\x013a1"
+ Desc: '00100000000000001610000000000000'
+ Type: NT_GNU_BUILD_ATTRIBUTE_OPEN
+ - Name: "GA$\x013a1"
+ Desc: 64110000000000006C11000000000000
+ Type: NT_GNU_BUILD_ATTRIBUTE_OPEN
+ - Name: "GA$\x013a1"
+ Desc: '50100000000000000911000000000000'
+ Type: NT_GNU_BUILD_ATTRIBUTE_OPEN
+ - Name: "GA$\x013a1"
+ Desc: '61110000000000006111000000000000'
+ Type: NT_GNU_BUILD_ATTRIBUTE_OPEN
+ - Name: "GA$\x013a1"
+ Desc: '61110000000000006111000000000000'
+ Type: NT_GNU_BUILD_ATTRIBUTE_OPEN
+ - Name: "GA$\x013a1"
+ Desc: 16100000000000001B10000000000000
+ Type: NT_GNU_BUILD_ATTRIBUTE_OPEN
+ - Name: "GA$\x013a1"
+ Desc: 6C110000000000007111000000000000
+ Type: NT_GNU_BUILD_ATTRIBUTE_OPEN
+Symbols:
+ - Name: .note.gnu.build-id
+ Type: STT_SECTION
+ Section: .note.gnu.build-id
+ Value: 0x238
+ - Name: .gnu.hash
+ Type: STT_SECTION
+ Section: .gnu.hash
+ Value: 0x260
+ - Name: .dynsym
+ Type: STT_SECTION
+ Section: .dynsym
+ Value: 0x298
+ - Name: .dynstr
+ Type: STT_SECTION
+ Section: .dynstr
+ Value: 0x388
+ - Name: .gnu.version
+ Type: STT_SECTION
+ Section: .gnu.version
+ Value: 0x44E
+ - Name: .gnu.version_r
+ Type: STT_SECTION
+ Section: .gnu.version_r
+ Value: 0x468
+ - Name: .rela.dyn
+ Type: STT_SECTION
+ Section: .rela.dyn
+ Value: 0x488
+ - Name: .rela.plt
+ Type: STT_SECTION
+ Section: .rela.plt
+ Value: 0x530
+ - Name: .init
+ Type: STT_SECTION
+ Section: .init
+ Value: 0x1000
+ - Name: .plt
+ Type: STT_SECTION
+ Section: .plt
+ Value: 0x1020
+ - Name: .text
+ Type: STT_SECTION
+ Section: .text
+ Value: 0x1050
+ - Name: .fini
+ Type: STT_SECTION
+ Section: .fini
+ Value: 0x1164
+ - Name: .rodata
+ Type: STT_SECTION
+ Section: .rodata
+ Value: 0x2000
+ - Name: .eh_frame_hdr
+ Type: STT_SECTION
+ Section: .eh_frame_hdr
+ Value: 0x202C
+ - Name: .eh_frame
+ Type: STT_SECTION
+ Section: .eh_frame
+ Value: 0x2060
+ - Name: .init_array
+ Type: STT_SECTION
+ Section: .init_array
+ Value: 0x3DC8
+ - Name: .fini_array
+ Type: STT_SECTION
+ Section: .fini_array
+ Value: 0x3DD0
+ - Name: .data.rel.ro
+ Type: STT_SECTION
+ Section: .data.rel.ro
+ Value: 0x3DD8
+ - Name: .dynamic
+ Type: STT_SECTION
+ Section: .dynamic
+ Value: 0x3DE0
+ - Name: .got
+ Type: STT_SECTION
+ Section: .got
+ Value: 0x3FE0
+ - Name: .got.plt
+ Type: STT_SECTION
+ Section: .got.plt
+ Value: 0x4000
+ - Name: .bss
+ Type: STT_SECTION
+ Section: .bss
+ Value: 0x4028
+ - Name: .comment
+ Type: STT_SECTION
+ Section: .comment
+ - Name: .gnu.build.attributes
+ Type: STT_SECTION
+ Section: .gnu.build.attributes
+ Value: 0x6030
+ - Name: crtstuff.c
+ Type: STT_FILE
+ Index: SHN_ABS
+ - Name: deregister_tm_clones
+ Type: STT_FUNC
+ Section: .text
+ Value: 0x1050
+ - Name: register_tm_clones
+ Type: STT_FUNC
+ Section: .text
+ Value: 0x1080
+ - Name: __do_global_dtors_aux
+ Type: STT_FUNC
+ Section: .text
+ Value: 0x10C0
+ - Name: completed.0
+ Type: STT_OBJECT
+ Section: .bss
+ Value: 0x4028
+ Size: 0x1
+ - Name: __do_global_dtors_aux_fini_array_entry
+ Type: STT_OBJECT
+ Section: .fini_array
+ Value: 0x3DD0
+ - Name: frame_dummy
+ Type: STT_FUNC
+ Section: .text
+ Value: 0x1100
+ - Name: __frame_dummy_init_array_entry
+ Type: STT_OBJECT
+ Section: .init_array
+ Value: 0x3DC8
+ - Name: foo.cpp
+ Type: STT_FILE
+ Index: SHN_ABS
+ - Name: 'crtstuff.c (1)'
+ Type: STT_FILE
+ Index: SHN_ABS
+ - Name: __FRAME_END__
+ Type: STT_OBJECT
+ Section: .eh_frame
+ Value: 0x2120
+ - Type: STT_FILE
+ Index: SHN_ABS
+ - Name: __GNU_EH_FRAME_HDR
+ Section: .eh_frame_hdr
+ Value: 0x202C
+ - Name: __dso_handle
+ Type: STT_OBJECT
+ Section: .data.rel.ro
+ Value: 0x3DD8
+ - Name: _fini
+ Type: STT_FUNC
+ Section: .fini
+ Value: 0x1164
+ - Name: _init
+ Type: STT_FUNC
+ Section: .init
+ Value: 0x1000
+ - Name: _DYNAMIC
+ Type: STT_OBJECT
+ Section: .dynamic
+ Value: 0x3DE0
+ - Name: __TMC_END__
+ Type: STT_OBJECT
+ Section: .got.plt
+ Value: 0x4028
+ - Name: _GLOBAL_OFFSET_TABLE_
+ Type: STT_OBJECT
+ Section: .got.plt
+ Value: 0x4000
+ - Name: _Z3bazv
+ Type: STT_FUNC
+ Section: .text
+ Binding: STB_GLOBAL
+ Value: 0x1135
+ Size: 0x16
+ - Name: '__cxa_finalize at GLIBC_2.2.5'
+ Type: STT_FUNC
+ Binding: STB_WEAK
+ - Name: _Z3barv
+ Type: STT_FUNC
+ Section: .text
+ Binding: STB_GLOBAL
+ Value: 0x111F
+ Size: 0x16
+ - Name: _Z3bizv
+ Type: STT_FUNC
+ Section: .text
+ Binding: STB_GLOBAL
+ Value: 0x114B
+ Size: 0x16
+ - Name: _Z3foov
+ Type: STT_FUNC
+ Section: .text
+ Binding: STB_GLOBAL
+ Value: 0x1109
+ Size: 0x16
+ - Name: 'puts at GLIBC_2.2.5'
+ Type: STT_FUNC
+ Binding: STB_GLOBAL
+ - Name: _ITM_deregisterTMCloneTable
+ Binding: STB_WEAK
+ - Name: __gmon_start__
+ Binding: STB_WEAK
+ - Name: _ITM_registerTMCloneTable
+ Binding: STB_WEAK
+DynamicSymbols:
+ - Name: __cxa_finalize
+ Type: STT_FUNC
+ Binding: STB_WEAK
+ - Name: puts
+ Type: STT_FUNC
+ Binding: STB_GLOBAL
+ - Name: _ITM_deregisterTMCloneTable
+ Binding: STB_WEAK
+ - Name: __gmon_start__
+ Binding: STB_WEAK
+ - Name: _ITM_registerTMCloneTable
+ Binding: STB_WEAK
+ - Name: _Z3bazv
+ Type: STT_FUNC
+ Section: .text
+ Binding: STB_GLOBAL
+ Value: 0x1135
+ Size: 0x16
+ - Name: _Z3barv
+ Type: STT_FUNC
+ Section: .text
+ Binding: STB_GLOBAL
+ Value: 0x111F
+ Size: 0x16
+ - Name: _Z3bizv
+ Type: STT_FUNC
+ Section: .text
+ Binding: STB_GLOBAL
+ Value: 0x114B
+ Size: 0x16
+ - Name: _Z3foov
+ Type: STT_FUNC
+ Section: .text
+ Binding: STB_GLOBAL
+ Value: 0x1109
+ Size: 0x16
+...
>From c9ff87a1b23b94b07db8a158c7a0665a23100d14 Mon Sep 17 00:00:00 2001
From: Greg Clayton <clayborg at gmail.com>
Date: Thu, 17 Oct 2024 15:40:57 -0700
Subject: [PATCH 2/3] Respond to user feedback.
---
.../Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 173 ++++++++++--------
.../Plugins/ObjectFile/ELF/ObjectFileELF.h | 21 ++-
2 files changed, 106 insertions(+), 88 deletions(-)
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 7374ac10a1e27a..67341fb027615b 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -46,7 +46,6 @@
#include "llvm/Support/MipsABIFlags.h"
#include "lldb/Target/Process.h"
-
#define CASE_AND_STREAM(s, def, width) \
case def: \
s->Printf("%-*s", width, #def); \
@@ -2992,21 +2991,20 @@ 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.
- bool found_dynsym = false;
+ Section *dynsym = nullptr;
if (!symtab ||
GetSectionList()->FindSectionByName(ConstString(".gnu_debugdata"))) {
- Section *dynsym =
+ dynsym =
section_list->FindSectionByType(eSectionTypeELFDynamicSymbols, true)
.get();
if (dynsym) {
- found_dynsym = true;
auto [num_symbols, address_class_map] =
ParseSymbolTable(&lldb_symtab, symbol_id, dynsym);
symbol_id += num_symbols;
m_address_class_map.merge(address_class_map);
}
}
- if (!found_dynsym) {
+ if (!dynsym) {
// Try and read the dynamic symbol table from the .dynamic section.
uint32_t num_symbols = 0;
std::optional<DataExtractor> symtab_data =
@@ -3883,9 +3881,9 @@ 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 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 are
+ // guaranteed 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)
@@ -3925,6 +3923,86 @@ 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; // First symbol is always all zeros
+
+ return std::nullopt;
+}
std::optional<DataExtractor>
ObjectFileELF::GetDynsymDataFromDynamic(uint32_t &num_symbols) {
@@ -3943,83 +4021,16 @@ ObjectFileELF::GetDynsymDataFromDynamic(uint32_t &num_symbols) {
ProcessSP process_sp(m_process_wp.lock());
const ELFDynamic *symtab = FindDynamicSymbol(DT_SYMTAB);
const ELFDynamic *syment = FindDynamicSymbol(DT_SYMENT);
- const ELFDynamic *hash = FindDynamicSymbol(DT_HASH);
- const ELFDynamic *gnu_hash = FindDynamicSymbol(DT_GNU_HASH);
// DT_SYMTAB and DT_SYMENT are mandatory.
if (symtab == nullptr || syment == nullptr)
return std::nullopt;
- // We must have either a DT_HASH or a DT_GNU_HASH.
- if (hash == nullptr && gnu_hash == nullptr)
- return std::nullopt;
- // The number of symbols in the symbol table is the number of entries in the
- // symbol table divided by the size of each symbol table entry.
- // We must figure out the number of symbols in the symbol table using the
- // DT_HASH or the DT_GNU_HASH as the number of symbols isn't stored anywhere
- // in the .dynamic section.
- lldb::offset_t offset;
- if (hash) {
- // The DT_HASH header contains the number of symbols in the "nchain"
- // member. The header looks like this:
- // struct DT_HASH_HEADER {
- // uint32_t nbucket;
- // uint32_t nchain;
- // };
- if (auto data = ReadDataFromDynamic(hash, 8)) {
- offset = 4;
- num_symbols = data->GetU32(&offset);
- }
- }
- if (num_symbols == 0 && gnu_hash) {
- struct DT_GNU_HASH_HEADER {
- uint32_t nbuckets = 0;
- uint32_t symoffset = 0;
- uint32_t bloom_size = 0;
- uint32_t bloom_shift = 0;
- };
- if (auto data = ReadDataFromDynamic(gnu_hash, sizeof(DT_GNU_HASH_HEADER))) {
- offset = 0;
- DT_GNU_HASH_HEADER 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(DT_GNU_HASH_HEADER) + 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)
- ++num_symbols; // First symbol is always all zeros
- }
+ 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 34d9ae74fbb23f..16c216eb81e729 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
@@ -447,13 +447,13 @@ class ObjectFileELF : public lldb_private::ObjectFile {
///
/// \param[in] length The number of bytes to read.
///
- /// \param[in] offset The number of bytes to skip after the d_ptr value
+ /// \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
+ /// \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,
+ 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
@@ -461,14 +461,21 @@ class ObjectFileELF : public lldb_private::ObjectFile {
///
/// 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
+ /// 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
+ /// 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>
+ 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
>From a174d9bb6bdd99d33d12f179e5c60de9a3258f64 Mon Sep 17 00:00:00 2001
From: Greg Clayton <clayborg at gmail.com>
Date: Tue, 22 Oct 2024 00:06:27 -0700
Subject: [PATCH 3/3] Switch testing over to using llvm-mv + lld.
---
.../Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 2 +-
.../test/Shell/ObjectFile/ELF/elf-dynsym.test | 42 ++
.../test/Shell/ObjectFile/ELF/elf-dynsym.yaml | 631 ------------------
3 files changed, 43 insertions(+), 632 deletions(-)
create mode 100644 lldb/test/Shell/ObjectFile/ELF/elf-dynsym.test
delete mode 100644 lldb/test/Shell/ObjectFile/ELF/elf-dynsym.yaml
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 67341fb027615b..c5c37aafe505e3 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -3999,7 +3999,7 @@ std::optional<uint32_t> ObjectFileELF::GetNumSymbolsFromDynamicGnuHash() {
}
}
if (num_symbols > 0)
- return ++num_symbols; // First symbol is always all zeros
+ return num_symbols;
return std::nullopt;
}
diff --git a/lldb/test/Shell/ObjectFile/ELF/elf-dynsym.test b/lldb/test/Shell/ObjectFile/ELF/elf-dynsym.test
new file mode 100644
index 00000000000000..7d948e2cd225c6
--- /dev/null
+++ b/lldb/test/Shell/ObjectFile/ELF/elf-dynsym.test
@@ -0,0 +1,42 @@
+// 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
diff --git a/lldb/test/Shell/ObjectFile/ELF/elf-dynsym.yaml b/lldb/test/Shell/ObjectFile/ELF/elf-dynsym.yaml
deleted file mode 100644
index 2763aac1df4893..00000000000000
--- a/lldb/test/Shell/ObjectFile/ELF/elf-dynsym.yaml
+++ /dev/null
@@ -1,631 +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.
-##
-## This test will convert a shared library from yaml, strip its section headers,
-## and varify that LLDB can load the dynamic symbol table. We must manually
-## strip the section headers from a full shared library because our ELF YAML
-## support in obj2yaml/yaml2obj doesn't support ELF files with program headers
-## only, they must have sections or the file doesn't get recreated correctlty.
-
-# RUN: yaml2obj %s -o %t
-# RUN: llvm-strip --strip-sections %t -o %t.noshdrs
-
-# RUN: %lldb -b \
-# RUN: -o "target create -d '%t.noshdrs'" \
-# RUN: -o "image dump objfile" \
-# RUN: | FileCheck %s --dump-input=always
-# CHECK: (lldb) image dump objfile
-# CHECK: Dumping headers for 1 module(s).
-# CHECK: ObjectFileELF, file =
-# CHECK: ELF Header
-# Make sure there are no section headers
-# CHECK: e_shnum = 0x00000000
-# Make sure we were able to load the symbols
-# CHECK: elf-dynsym.yaml.tmp.noshdrs, num_symbols = 9:
-# CHECK: [ 0] 1 Undefined 0x0000000000000000 0x0000000000000000 0x00000022 __cxa_finalize
-# CHECK: [ 1] 2 X Undefined 0x0000000000000000 0x0000000000000000 0x00000012 puts
-# CHECK: [ 2] 3 Undefined 0x0000000000000000 0x0000000000000000 0x00000020 _ITM_deregisterTMCloneTable
-# CHECK: [ 3] 4 Undefined 0x0000000000000000 0x0000000000000000 0x00000020 __gmon_start__
-# CHECK: [ 4] 5 Undefined 0x0000000000000000 0x0000000000000000 0x00000020 _ITM_registerTMCloneTable
-# CHECK: [ 5] 6 X Code 0x0000000000001135 0x0000000000000016 0x00000012 baz()
-# CHECK: [ 6] 7 X Code 0x000000000000111f 0x0000000000000016 0x00000012 bar()
-# CHECK: [ 7] 8 X Code 0x000000000000114b 0x0000000000000016 0x00000012 biz()
-# CHECK: [ 8] 9 X Code 0x0000000000001109 0x0000000000000016 0x00000012 foo()
-
---- !ELF
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- Type: ET_DYN
- Machine: EM_X86_64
- Entry: 0x1050
-ProgramHeaders:
- - Type: PT_LOAD
- Flags: [ PF_R ]
- FirstSec: .note.gnu.build-id
- LastSec: .rela.plt
- Align: 0x1000
- Offset: 0x0
- - Type: PT_LOAD
- Flags: [ PF_X, PF_R ]
- FirstSec: .init
- LastSec: .fini
- VAddr: 0x1000
- Align: 0x1000
- Offset: 0x1000
- - Type: PT_LOAD
- Flags: [ PF_R ]
- FirstSec: .rodata
- LastSec: .eh_frame
- VAddr: 0x2000
- Align: 0x1000
- Offset: 0x2000
- - Type: PT_LOAD
- Flags: [ PF_W, PF_R ]
- FirstSec: .init_array
- LastSec: .bss
- VAddr: 0x3DC8
- Align: 0x1000
- Offset: 0x2DC8
- - Type: PT_DYNAMIC
- Flags: [ PF_W, PF_R ]
- FirstSec: .dynamic
- LastSec: .dynamic
- VAddr: 0x3DE0
- Align: 0x8
- Offset: 0x2DE0
- - Type: PT_NOTE
- Flags: [ PF_R ]
- FirstSec: .note.gnu.build-id
- LastSec: .note.gnu.build-id
- VAddr: 0x238
- Align: 0x4
- Offset: 0x238
- - Type: PT_GNU_EH_FRAME
- Flags: [ PF_R ]
- FirstSec: .eh_frame_hdr
- LastSec: .eh_frame_hdr
- VAddr: 0x202C
- Align: 0x4
- Offset: 0x202C
- - Type: PT_GNU_STACK
- Flags: [ PF_W, PF_R ]
- Align: 0x10
- Offset: 0x0
- - Type: PT_GNU_RELRO
- Flags: [ PF_R ]
- FirstSec: .init_array
- LastSec: .got
- VAddr: 0x3DC8
- Offset: 0x2DC8
-Sections:
- - Name: .note.gnu.build-id
- Type: SHT_NOTE
- Flags: [ SHF_ALLOC ]
- Address: 0x238
- AddressAlign: 0x4
- Notes:
- - Name: GNU
- Desc: E98A07D11FFBEC0C57492B71EEE529C65D183408
- Type: NT_PRPSINFO
- - Name: .gnu.hash
- Type: SHT_GNU_HASH
- Flags: [ SHF_ALLOC ]
- Address: 0x260
- Link: .dynsym
- AddressAlign: 0x8
- Header:
- SymNdx: 0x6
- Shift2: 0x6
- BloomFilter: [ 0x3021080800001010 ]
- HashBuckets: [ 0x0, 0x6, 0x0 ]
- HashValues: [ 0x6A5EBD44, 0x6A5EBC3C, 0x6A5EDF4C, 0x6A6128EB ]
- - Name: .dynsym
- Type: SHT_DYNSYM
- Flags: [ SHF_ALLOC ]
- Address: 0x298
- Link: .dynstr
- AddressAlign: 0x8
- - Name: .dynstr
- Type: SHT_STRTAB
- Flags: [ SHF_ALLOC ]
- Address: 0x388
- AddressAlign: 0x1
- - Name: .gnu.version
- Type: SHT_GNU_versym
- Flags: [ SHF_ALLOC ]
- Address: 0x44E
- Link: .dynsym
- AddressAlign: 0x2
- Entries: [ 0, 2, 2, 0, 0, 0, 1, 1, 1, 1 ]
- - Name: .gnu.version_r
- Type: SHT_GNU_verneed
- Flags: [ SHF_ALLOC ]
- Address: 0x468
- Link: .dynstr
- AddressAlign: 0x8
- Dependencies:
- - Version: 1
- File: libc.so.6
- Entries:
- - Name: GLIBC_2.2.5
- Hash: 157882997
- Flags: 0
- Other: 2
- - Name: .rela.dyn
- Type: SHT_RELA
- Flags: [ SHF_ALLOC ]
- Address: 0x488
- Link: .dynsym
- AddressAlign: 0x8
- Relocations:
- - Offset: 0x3DC8
- Type: R_X86_64_RELATIVE
- Addend: 4352
- - Offset: 0x3DD0
- Type: R_X86_64_RELATIVE
- Addend: 4288
- - Offset: 0x3DD8
- Type: R_X86_64_RELATIVE
- Addend: 15832
- - Offset: 0x3FE0
- Symbol: __cxa_finalize
- Type: R_X86_64_GLOB_DAT
- - Offset: 0x3FE8
- Symbol: _ITM_deregisterTMCloneTable
- Type: R_X86_64_GLOB_DAT
- - Offset: 0x3FF0
- Symbol: __gmon_start__
- Type: R_X86_64_GLOB_DAT
- - Offset: 0x3FF8
- Symbol: _ITM_registerTMCloneTable
- Type: R_X86_64_GLOB_DAT
- - Name: .rela.plt
- Type: SHT_RELA
- Flags: [ SHF_ALLOC, SHF_INFO_LINK ]
- Address: 0x530
- Link: .dynsym
- AddressAlign: 0x8
- Info: .got.plt
- Relocations:
- - Offset: 0x4018
- Symbol: __cxa_finalize
- Type: R_X86_64_JUMP_SLOT
- - Offset: 0x4020
- Symbol: puts
- Type: R_X86_64_JUMP_SLOT
- - Name: .init
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- Address: 0x1000
- AddressAlign: 0x4
- Offset: 0x1000
- Content: F30F1EFA4883EC08488B05E12F00004885C07402FFD04883C408C3
- - Name: .plt
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- Address: 0x1020
- AddressAlign: 0x10
- EntSize: 0x10
- Content: FF35E22F0000FF25E42F00000F1F4000FF25E22F00006800000000E9E0FFFFFFFF25DA2F00006801000000E9D0FFFFFF
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- Address: 0x1050
- AddressAlign: 0x10
- Content: 488D3DD12F0000488D05CA2F00004839F87415488B057E2F00004885C07409FFE00F1F8000000000C30F1F8000000000488D3DA12F0000488D359A2F00004829FE4889F048C1EE3F48C1F8034801C648D1FE7414488B054D2F00004885C07408FFE0660F1F440000C30F1F8000000000F30F1EFA803D5D2F000000752B5548833D0A2F0000004889E5740C488D3DF62C0000E849FFFFFFE864FFFFFFC605352F0000015DC30F1F00C30F1F8000000000F30F1EFAE977FFFFFF554889E5488D05EC0E00004889C7E824FFFFFF905DC3554889E5488D05E10E00004889C7E80EFFFFFF905DC3554889E5488D05D60E00004889C7E8F8FEFFFF905DC3554889E5488D05CB0E00004889C7E8E2FEFFFF905DC3
- - Name: .fini
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- Address: 0x1164
- AddressAlign: 0x4
- Content: F30F1EFA4883EC084883C408C3
- - Name: .rodata
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC ]
- Address: 0x2000
- AddressAlign: 0x1
- Offset: 0x2000
- Content: 766F696420666F6F282900766F696420626172282900766F69642062617A282900766F69642062697A282900
- - Name: .eh_frame_hdr
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC ]
- Address: 0x202C
- AddressAlign: 0x4
- Content: 011B033B3000000005000000F4EFFFFF4C000000DDF0FFFF74000000F3F0FFFF9400000009F1FFFFB40000001FF1FFFFD4000000
- - Name: .eh_frame
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC ]
- Address: 0x2060
- AddressAlign: 0x8
- Content: 1400000000000000017A5200017810011B0C070890010000240000001C000000A0EFFFFF30000000000E10460E184A0F0B770880003F1A3B2A332422000000001C0000004400000061F0FFFF1600000000410E108602430D06510C07080000001C0000006400000057F0FFFF1600000000410E108602430D06510C07080000001C000000840000004DF0FFFF1600000000410E108602430D06510C07080000001C000000A400000043F0FFFF1600000000410E108602430D06510C070800000000000000
- - Name: .init_array
- Type: SHT_INIT_ARRAY
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- Address: 0x3DC8
- AddressAlign: 0x8
- EntSize: 0x8
- Offset: 0x2DC8
- Content: '0011000000000000'
- - Name: .fini_array
- Type: SHT_FINI_ARRAY
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- Address: 0x3DD0
- AddressAlign: 0x8
- EntSize: 0x8
- Content: C010000000000000
- - Name: .data.rel.ro
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- Address: 0x3DD8
- AddressAlign: 0x8
- Content: D83D000000000000
- - Name: .dynamic
- Type: SHT_DYNAMIC
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- Address: 0x3DE0
- Link: .dynstr
- AddressAlign: 0x8
- Entries:
- - Tag: DT_NEEDED
- Value: 0x7A
- - Tag: DT_NEEDED
- Value: 0x89
- - Tag: DT_NEEDED
- Value: 0x93
- - Tag: DT_NEEDED
- Value: 0xA1
- - Tag: DT_SONAME
- Value: 0xAB
- - Tag: DT_INIT
- Value: 0x1000
- - Tag: DT_FINI
- Value: 0x1164
- - Tag: DT_INIT_ARRAY
- Value: 0x3DC8
- - Tag: DT_INIT_ARRAYSZ
- Value: 0x8
- - Tag: DT_FINI_ARRAY
- Value: 0x3DD0
- - Tag: DT_FINI_ARRAYSZ
- Value: 0x8
- - Tag: DT_GNU_HASH
- Value: 0x260
- - Tag: DT_STRTAB
- Value: 0x388
- - Tag: DT_SYMTAB
- Value: 0x298
- - Tag: DT_STRSZ
- Value: 0xC5
- - Tag: DT_SYMENT
- Value: 0x18
- - Tag: DT_PLTGOT
- Value: 0x4000
- - Tag: DT_PLTRELSZ
- Value: 0x30
- - Tag: DT_PLTREL
- Value: 0x7
- - Tag: DT_JMPREL
- Value: 0x530
- - Tag: DT_RELA
- Value: 0x488
- - Tag: DT_RELASZ
- Value: 0xA8
- - Tag: DT_RELAENT
- Value: 0x18
- - Tag: DT_VERNEED
- Value: 0x468
- - Tag: DT_VERNEEDNUM
- Value: 0x1
- - Tag: DT_VERSYM
- Value: 0x44E
- - Tag: DT_RELACOUNT
- Value: 0x3
- - Tag: DT_NULL
- Value: 0x0
- - Tag: DT_NULL
- Value: 0x0
- - Tag: DT_NULL
- Value: 0x0
- - Tag: DT_NULL
- Value: 0x0
- - Tag: DT_NULL
- Value: 0x0
- - Name: .got
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- Address: 0x3FE0
- AddressAlign: 0x8
- EntSize: 0x8
- Content: '0000000000000000000000000000000000000000000000000000000000000000'
- - Name: .got.plt
- Type: SHT_PROGBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- Address: 0x4000
- AddressAlign: 0x8
- EntSize: 0x8
- Content: E03D0000000000000000000000000000000000000000000036100000000000004610000000000000
- - Name: .bss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC ]
- Address: 0x4028
- AddressAlign: 0x1
- Size: 0x8
- - Name: .comment
- Type: SHT_PROGBITS
- Flags: [ SHF_MERGE, SHF_STRINGS ]
- AddressAlign: 0x1
- EntSize: 0x1
- Content: 4743433A2028474E55292031312E352E302032303234303731392028526564204861742031312E352E302D322900
- - Name: .gnu.build.attributes
- Type: SHT_NOTE
- Address: 0x6030
- AddressAlign: 0x4
- Notes:
- - Name: "GA$\x013a1"
- Desc: '50100000000000005010000000000000'
- Type: NT_GNU_BUILD_ATTRIBUTE_OPEN
- - Name: "GA$\x013a1"
- Desc: '00100000000000001610000000000000'
- Type: NT_GNU_BUILD_ATTRIBUTE_OPEN
- - Name: "GA$\x013a1"
- Desc: 64110000000000006C11000000000000
- Type: NT_GNU_BUILD_ATTRIBUTE_OPEN
- - Name: "GA$\x013a1"
- Desc: '50100000000000000911000000000000'
- Type: NT_GNU_BUILD_ATTRIBUTE_OPEN
- - Name: "GA$\x013a1"
- Desc: '61110000000000006111000000000000'
- Type: NT_GNU_BUILD_ATTRIBUTE_OPEN
- - Name: "GA$\x013a1"
- Desc: '61110000000000006111000000000000'
- Type: NT_GNU_BUILD_ATTRIBUTE_OPEN
- - Name: "GA$\x013a1"
- Desc: 16100000000000001B10000000000000
- Type: NT_GNU_BUILD_ATTRIBUTE_OPEN
- - Name: "GA$\x013a1"
- Desc: 6C110000000000007111000000000000
- Type: NT_GNU_BUILD_ATTRIBUTE_OPEN
-Symbols:
- - Name: .note.gnu.build-id
- Type: STT_SECTION
- Section: .note.gnu.build-id
- Value: 0x238
- - Name: .gnu.hash
- Type: STT_SECTION
- Section: .gnu.hash
- Value: 0x260
- - Name: .dynsym
- Type: STT_SECTION
- Section: .dynsym
- Value: 0x298
- - Name: .dynstr
- Type: STT_SECTION
- Section: .dynstr
- Value: 0x388
- - Name: .gnu.version
- Type: STT_SECTION
- Section: .gnu.version
- Value: 0x44E
- - Name: .gnu.version_r
- Type: STT_SECTION
- Section: .gnu.version_r
- Value: 0x468
- - Name: .rela.dyn
- Type: STT_SECTION
- Section: .rela.dyn
- Value: 0x488
- - Name: .rela.plt
- Type: STT_SECTION
- Section: .rela.plt
- Value: 0x530
- - Name: .init
- Type: STT_SECTION
- Section: .init
- Value: 0x1000
- - Name: .plt
- Type: STT_SECTION
- Section: .plt
- Value: 0x1020
- - Name: .text
- Type: STT_SECTION
- Section: .text
- Value: 0x1050
- - Name: .fini
- Type: STT_SECTION
- Section: .fini
- Value: 0x1164
- - Name: .rodata
- Type: STT_SECTION
- Section: .rodata
- Value: 0x2000
- - Name: .eh_frame_hdr
- Type: STT_SECTION
- Section: .eh_frame_hdr
- Value: 0x202C
- - Name: .eh_frame
- Type: STT_SECTION
- Section: .eh_frame
- Value: 0x2060
- - Name: .init_array
- Type: STT_SECTION
- Section: .init_array
- Value: 0x3DC8
- - Name: .fini_array
- Type: STT_SECTION
- Section: .fini_array
- Value: 0x3DD0
- - Name: .data.rel.ro
- Type: STT_SECTION
- Section: .data.rel.ro
- Value: 0x3DD8
- - Name: .dynamic
- Type: STT_SECTION
- Section: .dynamic
- Value: 0x3DE0
- - Name: .got
- Type: STT_SECTION
- Section: .got
- Value: 0x3FE0
- - Name: .got.plt
- Type: STT_SECTION
- Section: .got.plt
- Value: 0x4000
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- Value: 0x4028
- - Name: .comment
- Type: STT_SECTION
- Section: .comment
- - Name: .gnu.build.attributes
- Type: STT_SECTION
- Section: .gnu.build.attributes
- Value: 0x6030
- - Name: crtstuff.c
- Type: STT_FILE
- Index: SHN_ABS
- - Name: deregister_tm_clones
- Type: STT_FUNC
- Section: .text
- Value: 0x1050
- - Name: register_tm_clones
- Type: STT_FUNC
- Section: .text
- Value: 0x1080
- - Name: __do_global_dtors_aux
- Type: STT_FUNC
- Section: .text
- Value: 0x10C0
- - Name: completed.0
- Type: STT_OBJECT
- Section: .bss
- Value: 0x4028
- Size: 0x1
- - Name: __do_global_dtors_aux_fini_array_entry
- Type: STT_OBJECT
- Section: .fini_array
- Value: 0x3DD0
- - Name: frame_dummy
- Type: STT_FUNC
- Section: .text
- Value: 0x1100
- - Name: __frame_dummy_init_array_entry
- Type: STT_OBJECT
- Section: .init_array
- Value: 0x3DC8
- - Name: foo.cpp
- Type: STT_FILE
- Index: SHN_ABS
- - Name: 'crtstuff.c (1)'
- Type: STT_FILE
- Index: SHN_ABS
- - Name: __FRAME_END__
- Type: STT_OBJECT
- Section: .eh_frame
- Value: 0x2120
- - Type: STT_FILE
- Index: SHN_ABS
- - Name: __GNU_EH_FRAME_HDR
- Section: .eh_frame_hdr
- Value: 0x202C
- - Name: __dso_handle
- Type: STT_OBJECT
- Section: .data.rel.ro
- Value: 0x3DD8
- - Name: _fini
- Type: STT_FUNC
- Section: .fini
- Value: 0x1164
- - Name: _init
- Type: STT_FUNC
- Section: .init
- Value: 0x1000
- - Name: _DYNAMIC
- Type: STT_OBJECT
- Section: .dynamic
- Value: 0x3DE0
- - Name: __TMC_END__
- Type: STT_OBJECT
- Section: .got.plt
- Value: 0x4028
- - Name: _GLOBAL_OFFSET_TABLE_
- Type: STT_OBJECT
- Section: .got.plt
- Value: 0x4000
- - Name: _Z3bazv
- Type: STT_FUNC
- Section: .text
- Binding: STB_GLOBAL
- Value: 0x1135
- Size: 0x16
- - Name: '__cxa_finalize at GLIBC_2.2.5'
- Type: STT_FUNC
- Binding: STB_WEAK
- - Name: _Z3barv
- Type: STT_FUNC
- Section: .text
- Binding: STB_GLOBAL
- Value: 0x111F
- Size: 0x16
- - Name: _Z3bizv
- Type: STT_FUNC
- Section: .text
- Binding: STB_GLOBAL
- Value: 0x114B
- Size: 0x16
- - Name: _Z3foov
- Type: STT_FUNC
- Section: .text
- Binding: STB_GLOBAL
- Value: 0x1109
- Size: 0x16
- - Name: 'puts at GLIBC_2.2.5'
- Type: STT_FUNC
- Binding: STB_GLOBAL
- - Name: _ITM_deregisterTMCloneTable
- Binding: STB_WEAK
- - Name: __gmon_start__
- Binding: STB_WEAK
- - Name: _ITM_registerTMCloneTable
- Binding: STB_WEAK
-DynamicSymbols:
- - Name: __cxa_finalize
- Type: STT_FUNC
- Binding: STB_WEAK
- - Name: puts
- Type: STT_FUNC
- Binding: STB_GLOBAL
- - Name: _ITM_deregisterTMCloneTable
- Binding: STB_WEAK
- - Name: __gmon_start__
- Binding: STB_WEAK
- - Name: _ITM_registerTMCloneTable
- Binding: STB_WEAK
- - Name: _Z3bazv
- Type: STT_FUNC
- Section: .text
- Binding: STB_GLOBAL
- Value: 0x1135
- Size: 0x16
- - Name: _Z3barv
- Type: STT_FUNC
- Section: .text
- Binding: STB_GLOBAL
- Value: 0x111F
- Size: 0x16
- - Name: _Z3bizv
- Type: STT_FUNC
- Section: .text
- Binding: STB_GLOBAL
- Value: 0x114B
- Size: 0x16
- - Name: _Z3foov
- Type: STT_FUNC
- Section: .text
- Binding: STB_GLOBAL
- Value: 0x1109
- Size: 0x16
-...
More information about the lldb-commits
mailing list