[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
This commit is contained in:
committed by
GitHub
parent
6e31714d24
commit
4cbe7607c7
@@ -1854,6 +1854,39 @@ public:
|
||||
};
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user