Skip to content

Commit 491ce66

Browse files
authored
Merge pull request #8669 from al45tair/eng/PR-124467787-6.0
[6.0][LLDB][ELF] Fix section unification to not just use names.
2 parents 8a82d83 + 6b39d19 commit 491ce66

File tree

2 files changed

+95
-12
lines changed

2 files changed

+95
-12
lines changed

lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1841,6 +1841,39 @@ class VMAddressProvider {
18411841
};
18421842
}
18431843

1844+
// We have to do this because ELF doesn't have section IDs, and also
1845+
// doesn't require section names to be unique. (We use the section index
1846+
// for section IDs, but that isn't guaranteed to be the same in separate
1847+
// debug images.)
1848+
static SectionSP FindMatchingSection(const SectionList &section_list,
1849+
SectionSP section) {
1850+
SectionSP sect_sp;
1851+
1852+
addr_t vm_addr = section->GetFileAddress();
1853+
ConstString name = section->GetName();
1854+
offset_t byte_size = section->GetByteSize();
1855+
bool thread_specific = section->IsThreadSpecific();
1856+
uint32_t permissions = section->GetPermissions();
1857+
uint32_t alignment = section->GetLog2Align();
1858+
1859+
for (auto sect : section_list) {
1860+
if (sect->GetName() == name &&
1861+
sect->IsThreadSpecific() == thread_specific &&
1862+
sect->GetPermissions() == permissions &&
1863+
sect->GetByteSize() == byte_size && sect->GetFileAddress() == vm_addr &&
1864+
sect->GetLog2Align() == alignment) {
1865+
sect_sp = sect;
1866+
break;
1867+
} else {
1868+
sect_sp = FindMatchingSection(sect->GetChildren(), section);
1869+
if (sect_sp)
1870+
break;
1871+
}
1872+
}
1873+
1874+
return sect_sp;
1875+
}
1876+
18441877
void ObjectFileELF::CreateSections(SectionList &unified_section_list) {
18451878
if (m_sections_up)
18461879
return;
@@ -2054,10 +2087,12 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
20542087
SectionList *module_section_list =
20552088
module_sp ? module_sp->GetSectionList() : nullptr;
20562089

2057-
// Local cache to avoid doing a FindSectionByName for each symbol. The "const
2058-
// char*" key must came from a ConstString object so they can be compared by
2059-
// pointer
2060-
std::unordered_map<const char *, lldb::SectionSP> section_name_to_section;
2090+
// We might have debug information in a separate object, in which case
2091+
// we need to map the sections from that object to the sections in the
2092+
// main object during symbol lookup. If we had to compare the sections
2093+
// for every single symbol, that would be expensive, so this map is
2094+
// used to accelerate the process.
2095+
std::unordered_map<lldb::SectionSP, lldb::SectionSP> section_map;
20612096

20622097
unsigned i;
20632098
for (i = 0; i < num_symbols; ++i) {
@@ -2262,14 +2297,14 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id,
22622297

22632298
if (symbol_section_sp && module_section_list &&
22642299
module_section_list != section_list) {
2265-
ConstString sect_name = symbol_section_sp->GetName();
2266-
auto section_it = section_name_to_section.find(sect_name.GetCString());
2267-
if (section_it == section_name_to_section.end())
2268-
section_it =
2269-
section_name_to_section
2270-
.emplace(sect_name.GetCString(),
2271-
module_section_list->FindSectionByName(sect_name))
2272-
.first;
2300+
auto section_it = section_map.find(symbol_section_sp);
2301+
if (section_it == section_map.end()) {
2302+
section_it = section_map
2303+
.emplace(symbol_section_sp,
2304+
FindMatchingSection(*module_section_list,
2305+
symbol_section_sp))
2306+
.first;
2307+
}
22732308
if (section_it->second)
22742309
symbol_section_sp = section_it->second;
22752310
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Test handling of object files that have duplicate sections. This is legal,
2+
# according to the System V ABI (Edition 4.1); see 4-20 where it says:
3+
#
4+
# Section names with a dot (.) prefix are reserved for the system,
5+
# although applications may use these sections if their existing
6+
# meanings are satisfactory. ... **An object file may have more than
7+
# one section with the same name.**
8+
#
9+
# (See https://github.com/llvm/llvm-project/issues/88001)
10+
11+
# RUN: yaml2obj %s -o %t
12+
# RUN: lldb-test symbols %t | FileCheck %s
13+
14+
# CHECK: 0x0000000000400010 {{.*}} my_function
15+
# CHECK: 0x0000000000401020 {{.*}} my_other_function
16+
17+
!ELF
18+
FileHeader:
19+
Class: ELFCLASS64
20+
Data: ELFDATA2LSB
21+
Type: ET_EXEC
22+
Machine: EM_X86_64
23+
ProgramHeaders:
24+
- Type: PT_LOAD
25+
Flags: [ PF_X, PF_R ]
26+
FirstSec: .text
27+
LastSec: '.text (1)'
28+
VAddr: 0x400000
29+
Align: 0x1000
30+
Offset: 0x0
31+
Sections:
32+
- Name: .text
33+
Type: SHT_PROGBITS
34+
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
35+
Address: 0x400010
36+
AddressAlign: 0x10
37+
- Name: '.text (1)'
38+
Type: SHT_PROGBITS
39+
Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GNU_RETAIN ]
40+
Address: 0x401000
41+
AddressAlign: 0x10
42+
Symbols:
43+
- Name: my_function
44+
Section: .text
45+
Value: 0x400010
46+
- Name: my_other_function
47+
Section: '.text (1)'
48+
Value: 0x401020

0 commit comments

Comments
 (0)