diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index 0d95a1c12bde3..16f6d2e884b57 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 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 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 0000000000000..8b2fd47df1a1f --- /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