[Lldb-commits] [lldb] 4cbe760 - [LLDB][ELF] Fix section unification to not just use names. (#90099)
via lldb-commits
lldb-commits at lists.llvm.org
Wed May 1 09:17:08 PDT 2024
Author: Alastair Houghton
Date: 2024-05-01T09:17:03-07:00
New Revision: 4cbe7607c75486dd17a048a45dd8c72c3dbf7e62
URL: https://github.com/llvm/llvm-project/commit/4cbe7607c75486dd17a048a45dd8c72c3dbf7e62
DIFF: https://github.com/llvm/llvm-project/commit/4cbe7607c75486dd17a048a45dd8c72c3dbf7e62.diff
LOG: [LLDB][ELF] Fix section unification to not just use names. (#90099)
Section unification cannot just use names, because it's valid for ELF
binaries to have multiple sections with the same name. We should check
other section properties too.
Fixes #88001.
rdar://124467787
Added:
lldb/test/Shell/ObjectFile/ELF/two-text-sections.yaml
Modified:
lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
Removed:
################################################################################
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 0d95a1c12bde35d..16f6d2e884b5771 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -1854,6 +1854,39 @@ class VMAddressProvider {
};
}
+// We have to do this because ELF doesn't have section IDs, and also
+// doesn't require section names to be unique. (We use the section index
+// for section IDs, but that isn't guaranteed to be the same in separate
+// debug images.)
+static SectionSP FindMatchingSection(const SectionList §ion_list,
+ SectionSP section) {
+ SectionSP sect_sp;
+
+ addr_t vm_addr = section->GetFileAddress();
+ ConstString name = section->GetName();
+ offset_t byte_size = section->GetByteSize();
+ bool thread_specific = section->IsThreadSpecific();
+ uint32_t permissions = section->GetPermissions();
+ uint32_t alignment = section->GetLog2Align();
+
+ for (auto sect : section_list) {
+ if (sect->GetName() == name &&
+ sect->IsThreadSpecific() == thread_specific &&
+ sect->GetPermissions() == permissions &&
+ sect->GetByteSize() == byte_size && sect->GetFileAddress() == vm_addr &&
+ sect->GetLog2Align() == alignment) {
+ sect_sp = sect;
+ break;
+ } else {
+ sect_sp = FindMatchingSection(sect->GetChildren(), section);
+ if (sect_sp)
+ break;
+ }
+ }
+
+ return sect_sp;
+}
+
void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
if (m_sections_up)
return;
@@ -2067,10 +2100,12 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
SectionList *module_section_list =
module_sp ? module_sp->GetSectionList() : nullptr;
- // Local cache to avoid doing a FindSectionByName for each symbol. The "const
- // char*" key must came from a ConstString object so they can be compared by
- // pointer
- std::unordered_map<const char *, lldb::SectionSP> section_name_to_section;
+ // We might have debug information in a separate object, in which case
+ // we need to map the sections from that object to the sections in the
+ // main object during symbol lookup. If we had to compare the sections
+ // for every single symbol, that would be expensive, so this map is
+ // used to accelerate the process.
+ std::unordered_map<lldb::SectionSP, lldb::SectionSP> section_map;
unsigned i;
for (i = 0; i < num_symbols; ++i) {
@@ -2275,14 +2310,14 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
if (symbol_section_sp && module_section_list &&
module_section_list != section_list) {
- ConstString sect_name = symbol_section_sp->GetName();
- auto section_it = section_name_to_section.find(sect_name.GetCString());
- if (section_it == section_name_to_section.end())
- section_it =
- section_name_to_section
- .emplace(sect_name.GetCString(),
- module_section_list->FindSectionByName(sect_name))
- .first;
+ auto section_it = section_map.find(symbol_section_sp);
+ if (section_it == section_map.end()) {
+ section_it = section_map
+ .emplace(symbol_section_sp,
+ FindMatchingSection(*module_section_list,
+ symbol_section_sp))
+ .first;
+ }
if (section_it->second)
symbol_section_sp = section_it->second;
}
diff --git a/lldb/test/Shell/ObjectFile/ELF/two-text-sections.yaml b/lldb/test/Shell/ObjectFile/ELF/two-text-sections.yaml
new file mode 100644
index 000000000000000..8b2fd47df1a1faf
--- /dev/null
+++ b/lldb/test/Shell/ObjectFile/ELF/two-text-sections.yaml
@@ -0,0 +1,48 @@
+# Test handling of object files that have duplicate sections. This is legal,
+# according to the System V ABI (Edition 4.1); see 4-20 where it says:
+#
+# Section names with a dot (.) prefix are reserved for the system,
+# although applications may use these sections if their existing
+# meanings are satisfactory. ... **An object file may have more than
+# one section with the same name.**
+#
+# (See https://github.com/llvm/llvm-project/issues/88001)
+
+# RUN: yaml2obj %s -o %t
+# RUN: lldb-test symbols %t | FileCheck %s
+
+# CHECK: 0x0000000000400010 {{.*}} my_function
+# CHECK: 0x0000000000401020 {{.*}} my_other_function
+
+!ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+ProgramHeaders:
+ - Type: PT_LOAD
+ Flags: [ PF_X, PF_R ]
+ FirstSec: .text
+ LastSec: '.text (1)'
+ VAddr: 0x400000
+ Align: 0x1000
+ Offset: 0x0
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x400010
+ AddressAlign: 0x10
+ - Name: '.text (1)'
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GNU_RETAIN ]
+ Address: 0x401000
+ AddressAlign: 0x10
+Symbols:
+ - Name: my_function
+ Section: .text
+ Value: 0x400010
+ - Name: my_other_function
+ Section: '.text (1)'
+ Value: 0x401020
More information about the lldb-commits
mailing list