diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2021-12-02 21:49:08 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2022-05-14 11:43:49 +0000 |
commit | 4824e7fd18a1223177218d4aec1b3c6c5c4a444e (patch) | |
tree | 5ca6493b1b0bf6a41f257794c0116d5e50fbf37c /contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF | |
parent | 5e801ac66d24704442eba426ed13c3effb8a34e7 (diff) | |
parent | f65dcba83ce5035ab88a85fe17628b447eb56e1b (diff) |
Diffstat (limited to 'contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF')
-rw-r--r-- | contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 244 | ||||
-rw-r--r-- | contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h | 11 |
2 files changed, 116 insertions, 139 deletions
diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index 8e0f228a988f..96e94ef08a45 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -2687,155 +2687,131 @@ unsigned ObjectFileELF::RelocateDebugSections(const ELFSectionHeader *rel_hdr, return 0; } -Symtab *ObjectFileELF::GetSymtab() { +void ObjectFileELF::ParseSymtab(Symtab &lldb_symtab) { ModuleSP module_sp(GetModule()); if (!module_sp) - return nullptr; + return; + + Progress progress( + llvm::formatv("Parsing symbol table for {0}", + m_file.GetFilename().AsCString("<Unknown>"))); + ElapsedTime elapsed(module_sp->GetSymtabParseTime()); // We always want to use the main object file so we (hopefully) only have one // cached copy of our symtab, dynamic sections, etc. ObjectFile *module_obj_file = module_sp->GetObjectFile(); if (module_obj_file && module_obj_file != this) - return module_obj_file->GetSymtab(); - - if (m_symtab_up == nullptr) { - Progress progress( - llvm::formatv("Parsing symbol table for {0}", - m_file.GetFilename().AsCString("<Unknown>"))); - ElapsedTime elapsed(module_sp->GetSymtabParseTime()); - SectionList *section_list = module_sp->GetSectionList(); - if (!section_list) - return nullptr; + return module_obj_file->ParseSymtab(lldb_symtab); - uint64_t symbol_id = 0; - std::lock_guard<std::recursive_mutex> guard(module_sp->GetMutex()); - - // Sharable objects and dynamic executables usually have 2 distinct symbol - // tables, one named ".symtab", and the other ".dynsym". The dynsym is a - // smaller version of the symtab that only contains global symbols. The - // information found in the dynsym is therefore also found in the symtab, - // while the reverse is not necessarily true. - Section *symtab = - section_list->FindSectionByType(eSectionTypeELFSymbolTable, true).get(); - if (symtab) { - m_symtab_up = std::make_unique<Symtab>(symtab->GetObjectFile()); - symbol_id += ParseSymbolTable(m_symtab_up.get(), symbol_id, symtab); - } - - // The symtab section is non-allocable and can be stripped, while the - // .dynsym section which should always be always be there. To support the - // minidebuginfo case we parse .dynsym when there's a .gnu_debuginfo - // section, nomatter if .symtab was already parsed or not. This is because - // minidebuginfo normally removes the .symtab symbols which have their - // matching .dynsym counterparts. - if (!symtab || - GetSectionList()->FindSectionByName(ConstString(".gnu_debugdata"))) { - Section *dynsym = - section_list->FindSectionByType(eSectionTypeELFDynamicSymbols, true) - .get(); - if (dynsym) { - if (!m_symtab_up) - m_symtab_up = std::make_unique<Symtab>(dynsym->GetObjectFile()); - symbol_id += ParseSymbolTable(m_symtab_up.get(), symbol_id, dynsym); - } - } + SectionList *section_list = module_sp->GetSectionList(); + if (!section_list) + return; - // DT_JMPREL - // If present, this entry's d_ptr member holds the address of - // relocation - // entries associated solely with the procedure linkage table. - // Separating - // these relocation entries lets the dynamic linker ignore them during - // process initialization, if lazy binding is enabled. If this entry is - // present, the related entries of types DT_PLTRELSZ and DT_PLTREL must - // also be present. - const ELFDynamic *symbol = FindDynamicSymbol(DT_JMPREL); - if (symbol) { - // Synthesize trampoline symbols to help navigate the PLT. - addr_t addr = symbol->d_ptr; - Section *reloc_section = - section_list->FindSectionContainingFileAddress(addr).get(); - if (reloc_section) { - user_id_t reloc_id = reloc_section->GetID(); - const ELFSectionHeaderInfo *reloc_header = - GetSectionHeaderByIndex(reloc_id); - if (reloc_header) { - if (m_symtab_up == nullptr) - m_symtab_up = - std::make_unique<Symtab>(reloc_section->GetObjectFile()); - - ParseTrampolineSymbols(m_symtab_up.get(), symbol_id, reloc_header, - reloc_id); - } - } - } + uint64_t symbol_id = 0; - if (DWARFCallFrameInfo *eh_frame = - GetModule()->GetUnwindTable().GetEHFrameInfo()) { - if (m_symtab_up == nullptr) - m_symtab_up = std::make_unique<Symtab>(this); - ParseUnwindSymbols(m_symtab_up.get(), eh_frame); + // Sharable objects and dynamic executables usually have 2 distinct symbol + // tables, one named ".symtab", and the other ".dynsym". The dynsym is a + // smaller version of the symtab that only contains global symbols. The + // information found in the dynsym is therefore also found in the symtab, + // while the reverse is not necessarily true. + Section *symtab = + section_list->FindSectionByType(eSectionTypeELFSymbolTable, true).get(); + if (symtab) + symbol_id += ParseSymbolTable(&lldb_symtab, symbol_id, symtab); + + // The symtab section is non-allocable and can be stripped, while the + // .dynsym section which should always be always be there. To support the + // minidebuginfo case we parse .dynsym when there's a .gnu_debuginfo + // section, nomatter if .symtab was already parsed or not. This is because + // minidebuginfo normally removes the .symtab symbols which have their + // matching .dynsym counterparts. + if (!symtab || + GetSectionList()->FindSectionByName(ConstString(".gnu_debugdata"))) { + Section *dynsym = + section_list->FindSectionByType(eSectionTypeELFDynamicSymbols, true) + .get(); + if (dynsym) + symbol_id += ParseSymbolTable(&lldb_symtab, symbol_id, dynsym); + } + + // DT_JMPREL + // If present, this entry's d_ptr member holds the address of + // relocation + // entries associated solely with the procedure linkage table. + // Separating + // these relocation entries lets the dynamic linker ignore them during + // process initialization, if lazy binding is enabled. If this entry is + // present, the related entries of types DT_PLTRELSZ and DT_PLTREL must + // also be present. + const ELFDynamic *symbol = FindDynamicSymbol(DT_JMPREL); + if (symbol) { + // Synthesize trampoline symbols to help navigate the PLT. + addr_t addr = symbol->d_ptr; + Section *reloc_section = + section_list->FindSectionContainingFileAddress(addr).get(); + if (reloc_section) { + user_id_t reloc_id = reloc_section->GetID(); + const ELFSectionHeaderInfo *reloc_header = + GetSectionHeaderByIndex(reloc_id); + if (reloc_header) + ParseTrampolineSymbols(&lldb_symtab, symbol_id, reloc_header, reloc_id); } + } - // If we still don't have any symtab then create an empty instance to avoid - // do the section lookup next time. - if (m_symtab_up == nullptr) - m_symtab_up = std::make_unique<Symtab>(this); - - // In the event that there's no symbol entry for the entry point we'll - // artificially create one. We delegate to the symtab object the figuring - // out of the proper size, this will usually make it span til the next - // symbol it finds in the section. This means that if there are missing - // symbols the entry point might span beyond its function definition. - // We're fine with this as it doesn't make it worse than not having a - // symbol entry at all. - if (CalculateType() == eTypeExecutable) { - ArchSpec arch = GetArchitecture(); - auto entry_point_addr = GetEntryPointAddress(); - bool is_valid_entry_point = - entry_point_addr.IsValid() && entry_point_addr.IsSectionOffset(); - addr_t entry_point_file_addr = entry_point_addr.GetFileAddress(); - if (is_valid_entry_point && !m_symtab_up->FindSymbolContainingFileAddress( - entry_point_file_addr)) { - uint64_t symbol_id = m_symtab_up->GetNumSymbols(); - // Don't set the name for any synthetic symbols, the Symbol - // object will generate one if needed when the name is accessed - // via accessors. - SectionSP section_sp = entry_point_addr.GetSection(); - Symbol symbol( - /*symID=*/symbol_id, - /*name=*/llvm::StringRef(), // Name will be auto generated. - /*type=*/eSymbolTypeCode, - /*external=*/true, - /*is_debug=*/false, - /*is_trampoline=*/false, - /*is_artificial=*/true, - /*section_sp=*/section_sp, - /*offset=*/0, - /*size=*/0, // FDE can span multiple symbols so don't use its size. - /*size_is_valid=*/false, - /*contains_linker_annotations=*/false, - /*flags=*/0); - // When the entry point is arm thumb we need to explicitly set its - // class address to reflect that. This is important because expression - // evaluation relies on correctly setting a breakpoint at this - // address. - if (arch.GetMachine() == llvm::Triple::arm && - (entry_point_file_addr & 1)) { - symbol.GetAddressRef().SetOffset(entry_point_addr.GetOffset() ^ 1); - m_address_class_map[entry_point_file_addr ^ 1] = - AddressClass::eCodeAlternateISA; - } else { - m_address_class_map[entry_point_file_addr] = AddressClass::eCode; - } - m_symtab_up->AddSymbol(symbol); + if (DWARFCallFrameInfo *eh_frame = + GetModule()->GetUnwindTable().GetEHFrameInfo()) { + ParseUnwindSymbols(&lldb_symtab, eh_frame); + } + + // In the event that there's no symbol entry for the entry point we'll + // artificially create one. We delegate to the symtab object the figuring + // out of the proper size, this will usually make it span til the next + // symbol it finds in the section. This means that if there are missing + // symbols the entry point might span beyond its function definition. + // We're fine with this as it doesn't make it worse than not having a + // symbol entry at all. + if (CalculateType() == eTypeExecutable) { + ArchSpec arch = GetArchitecture(); + auto entry_point_addr = GetEntryPointAddress(); + bool is_valid_entry_point = + entry_point_addr.IsValid() && entry_point_addr.IsSectionOffset(); + addr_t entry_point_file_addr = entry_point_addr.GetFileAddress(); + if (is_valid_entry_point && !lldb_symtab.FindSymbolContainingFileAddress( + entry_point_file_addr)) { + uint64_t symbol_id = lldb_symtab.GetNumSymbols(); + // Don't set the name for any synthetic symbols, the Symbol + // object will generate one if needed when the name is accessed + // via accessors. + SectionSP section_sp = entry_point_addr.GetSection(); + Symbol symbol( + /*symID=*/symbol_id, + /*name=*/llvm::StringRef(), // Name will be auto generated. + /*type=*/eSymbolTypeCode, + /*external=*/true, + /*is_debug=*/false, + /*is_trampoline=*/false, + /*is_artificial=*/true, + /*section_sp=*/section_sp, + /*offset=*/0, + /*size=*/0, // FDE can span multiple symbols so don't use its size. + /*size_is_valid=*/false, + /*contains_linker_annotations=*/false, + /*flags=*/0); + // When the entry point is arm thumb we need to explicitly set its + // class address to reflect that. This is important because expression + // evaluation relies on correctly setting a breakpoint at this + // address. + if (arch.GetMachine() == llvm::Triple::arm && + (entry_point_file_addr & 1)) { + symbol.GetAddressRef().SetOffset(entry_point_addr.GetOffset() ^ 1); + m_address_class_map[entry_point_file_addr ^ 1] = + AddressClass::eCodeAlternateISA; + } else { + m_address_class_map[entry_point_file_addr] = AddressClass::eCode; } + lldb_symtab.AddSymbol(symbol); } - - m_symtab_up->CalculateSymbolSizes(); } - - return m_symtab_up.get(); } void ObjectFileELF::RelocateSection(lldb_private::Section *section) diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h index 5738e5cf60d5..554f623ec8af 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h @@ -110,7 +110,7 @@ public: lldb_private::AddressClass GetAddressClass(lldb::addr_t file_addr) override; - lldb_private::Symtab *GetSymtab() override; + void ParseSymtab(lldb_private::Symtab &symtab) override; bool IsStripped() override; @@ -123,7 +123,7 @@ public: lldb_private::UUID GetUUID() override; /// Return the contents of the .gnu_debuglink section, if the object file - /// contains it. + /// contains it. llvm::Optional<lldb_private::FileSpec> GetDebugLink(); uint32_t GetDependentModules(lldb_private::FileSpecList &files) override; @@ -278,8 +278,9 @@ private: /// number of dynamic symbols parsed. size_t ParseDynamicSymbols(); - /// Populates m_symtab_up will all non-dynamic linker symbols. This method - /// will parse the symbols only once. Returns the number of symbols parsed. + /// Populates the symbol table with all non-dynamic linker symbols. This + /// method will parse the symbols only once. Returns the number of symbols + /// parsed. unsigned ParseSymbolTable(lldb_private::Symtab *symbol_table, lldb::user_id_t start_id, lldb_private::Section *symtab); @@ -384,7 +385,7 @@ private: lldb_private::UUID &uuid); bool AnySegmentHasPhysicalAddress(); - + /// Takes the .gnu_debugdata and returns the decompressed object file that is /// stored within that section. /// |