diff options
Diffstat (limited to 'lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp')
| -rw-r--r-- | lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 91 |
1 files changed, 83 insertions, 8 deletions
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index e507f0e4d74..64e32e5aa41 100644 --- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -18,6 +18,7 @@ #include "lldb/Core/PluginManager.h" #include "lldb/Core/Section.h" #include "lldb/Host/FileSystem.h" +#include "lldb/Host/LZMA.h" #include "lldb/Symbol/DWARFCallFrameInfo.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Target/SectionLoadList.h" @@ -1842,6 +1843,70 @@ void ObjectFileELF::CreateSections(SectionList &unified_section_list) { // unified section list. if (GetType() != eTypeDebugInfo) unified_section_list = *m_sections_up; + + // If there's a .gnu_debugdata section, we'll try to read the .symtab that's + // embedded in there and replace the one in the original object file (if any). + // If there's none in the orignal object file, we add it to it. + if (auto gdd_obj_file = GetGnuDebugDataObjectFile()) { + if (auto gdd_objfile_section_list = gdd_obj_file->GetSectionList()) { + if (SectionSP symtab_section_sp = + gdd_objfile_section_list->FindSectionByType( + eSectionTypeELFSymbolTable, true)) { + SectionSP module_section_sp = unified_section_list.FindSectionByType( + eSectionTypeELFSymbolTable, true); + if (module_section_sp) + unified_section_list.ReplaceSection(module_section_sp->GetID(), + symtab_section_sp); + else + unified_section_list.AddSection(symtab_section_sp); + } + } + } +} + +std::shared_ptr<ObjectFileELF> ObjectFileELF::GetGnuDebugDataObjectFile() { + if (m_gnu_debug_data_object_file != nullptr) + return m_gnu_debug_data_object_file; + + SectionSP section = + GetSectionList()->FindSectionByName(ConstString(".gnu_debugdata")); + if (!section) + return nullptr; + + if (!lldb_private::lzma::isAvailable()) { + GetModule()->ReportWarning( + "No LZMA support found for reading .gnu_debugdata section"); + return nullptr; + } + + // Uncompress the data + DataExtractor data; + section->GetSectionData(data); + llvm::SmallVector<uint8_t, 0> uncompressedData; + auto err = lldb_private::lzma::uncompress(data.GetData(), uncompressedData); + if (err) { + GetModule()->ReportWarning( + "An error occurred while decompression the section %s: %s", + section->GetName().AsCString(), llvm::toString(std::move(err)).c_str()); + return nullptr; + } + + // Construct ObjectFileELF object from decompressed buffer + DataBufferSP gdd_data_buf( + new DataBufferHeap(uncompressedData.data(), uncompressedData.size())); + auto fspec = GetFileSpec().CopyByAppendingPathComponent( + llvm::StringRef("gnu_debugdata")); + m_gnu_debug_data_object_file.reset(new ObjectFileELF( + GetModule(), gdd_data_buf, 0, &fspec, 0, gdd_data_buf->GetByteSize())); + + // This line is essential; otherwise a breakpoint can be set but not hit. + m_gnu_debug_data_object_file->SetType(ObjectFile::eTypeDebugInfo); + + ArchSpec spec = m_gnu_debug_data_object_file->GetArchitecture(); + if (spec && m_gnu_debug_data_object_file->SetModulesArchitecture(spec)) + return m_gnu_debug_data_object_file; + + return nullptr; } // Find the arm/aarch64 mapping symbol character in the given symbol name. @@ -2649,19 +2714,29 @@ Symtab *ObjectFileELF::GetSymtab() { // while the reverse is not necessarily true. Section *symtab = section_list->FindSectionByType(eSectionTypeELFSymbolTable, true).get(); - if (!symtab) { - // The symtab section is non-allocable and can be stripped, so if it - // doesn't exist then use the dynsym section which should always be - // there. - symtab = - section_list->FindSectionByType(eSectionTypeELFDynamicSymbols, true) - .get(); - } if (symtab) { m_symtab_up.reset(new 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.reset(new Symtab(dynsym->GetObjectFile())); + symbol_id += ParseSymbolTable(m_symtab_up.get(), symbol_id, dynsym); + } + } + // DT_JMPREL // If present, this entry's d_ptr member holds the address of // relocation |

