Author: emaste Date: Mon Oct 2 07:35:07 2017 New Revision: 314672 URL: http://llvm.org/viewvc/llvm-project?rev=314672&view=rev Log: Improve FreeBSD kernel debugging
FreeBSD kernel modules are actually relocatable (.o) ELF files and this previously caused some issues for LLDB. This change addresses these when using lldb to symbolicate FreeBSD kernel backtraces. The major problems: - Relocations were not being applied to the DWARF debug info despite there being code to do this. Several issues prevented it from working: - Relocations are computed at the same time as the symbol table, but in the case of split debug files, symbol table parsing always redirects to the primary object file, meaning that relocations would never be applied in the debug file. - There's actually no guarantee that the symbol table has been parsed yet when trying to parse debug information. - When actually applying relocations, it will segfault because the object files are not mapped with MAP_PRIVATE and PROT_WRITE. - LLDB returned invalid results when performing ordinary address-to- symbol resolution. It turned out that the addresses specified in the section headers were all 0, so LLDB believed all the sections had overlapping "file addresses" and would sometimes return a symbol from the wrong section. Patch by Brian Koropoff Differential Revision: https://reviews.llvm.org/D38142 Modified: lldb/trunk/include/lldb/Core/Section.h lldb/trunk/include/lldb/Symbol/ArmUnwindInfo.h lldb/trunk/include/lldb/Symbol/ObjectFile.h lldb/trunk/source/Core/Section.cpp lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h lldb/trunk/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp lldb/trunk/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp lldb/trunk/source/Symbol/ArmUnwindInfo.cpp lldb/trunk/source/Symbol/ObjectFile.cpp Modified: lldb/trunk/include/lldb/Core/Section.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Section.h?rev=314672&r1=314671&r2=314672&view=diff ============================================================================== --- lldb/trunk/include/lldb/Core/Section.h (original) +++ lldb/trunk/include/lldb/Core/Section.h Mon Oct 2 07:35:07 2017 @@ -238,7 +238,7 @@ public: /// section has no data or \a offset is not a valid offset /// in this section. //------------------------------------------------------------------ - lldb::offset_t GetSectionData(DataExtractor &data) const; + lldb::offset_t GetSectionData(DataExtractor &data); uint32_t GetLog2Align() { return m_log2align; } @@ -247,6 +247,10 @@ public: // Get the number of host bytes required to hold a target byte uint32_t GetTargetByteSize() const { return m_target_byte_size; } + bool IsRelocated() const { return m_relocated; } + + void SetIsRelocated(bool b) { m_relocated = b; } + protected: ObjectFile *m_obj_file; // The object file that data for this section should // be read from @@ -274,7 +278,8 @@ protected: m_thread_specific : 1, // This section is thread specific m_readable : 1, // If this section has read permissions m_writable : 1, // If this section has write permissions - m_executable : 1; // If this section has executable permissions + m_executable : 1, // If this section has executable permissions + m_relocated : 1; // If this section has had relocations applied uint32_t m_target_byte_size; // Some architectures have non-8-bit byte size. // This is specified as // as a multiple number of a host bytes Modified: lldb/trunk/include/lldb/Symbol/ArmUnwindInfo.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/ArmUnwindInfo.h?rev=314672&r1=314671&r2=314672&view=diff ============================================================================== --- lldb/trunk/include/lldb/Symbol/ArmUnwindInfo.h (original) +++ lldb/trunk/include/lldb/Symbol/ArmUnwindInfo.h Mon Oct 2 07:35:07 2017 @@ -31,7 +31,7 @@ namespace lldb_private { class ArmUnwindInfo { public: - ArmUnwindInfo(const ObjectFile &objfile, lldb::SectionSP &arm_exidx, + ArmUnwindInfo(ObjectFile &objfile, lldb::SectionSP &arm_exidx, lldb::SectionSP &arm_extab); ~ArmUnwindInfo(); Modified: lldb/trunk/include/lldb/Symbol/ObjectFile.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/ObjectFile.h?rev=314672&r1=314671&r2=314672&view=diff ============================================================================== --- lldb/trunk/include/lldb/Symbol/ObjectFile.h (original) +++ lldb/trunk/include/lldb/Symbol/ObjectFile.h Mon Oct 2 07:35:07 2017 @@ -352,6 +352,12 @@ public: virtual Symtab *GetSymtab() = 0; //------------------------------------------------------------------ + /// Perform relocations on the section if necessary. + /// + //------------------------------------------------------------------ + virtual void RelocateSection(lldb_private::Section *section); + + //------------------------------------------------------------------ /// Appends a Symbol for the specified so_addr to the symbol table. /// /// If verify_unique is false, the symbol table is not searched @@ -792,15 +798,15 @@ public: size_t CopyData(lldb::offset_t offset, size_t length, void *dst) const; - virtual size_t ReadSectionData(const Section *section, + virtual size_t ReadSectionData(Section *section, lldb::offset_t section_offset, void *dst, - size_t dst_len) const; + size_t dst_len); - virtual size_t ReadSectionData(const Section *section, - DataExtractor §ion_data) const; + virtual size_t ReadSectionData(Section *section, + DataExtractor §ion_data); - size_t MemoryMapSectionData(const Section *section, - DataExtractor §ion_data) const; + size_t MemoryMapSectionData(Section *section, + DataExtractor §ion_data); bool IsInMemory() const { return m_memory_addr != LLDB_INVALID_ADDRESS; } Modified: lldb/trunk/source/Core/Section.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Section.cpp?rev=314672&r1=314671&r2=314672&view=diff ============================================================================== --- lldb/trunk/source/Core/Section.cpp (original) +++ lldb/trunk/source/Core/Section.cpp Mon Oct 2 07:35:07 2017 @@ -135,7 +135,7 @@ Section::Section(const ModuleSP &module_ m_file_offset(file_offset), m_file_size(file_size), m_log2align(log2align), m_children(), m_fake(false), m_encrypted(false), m_thread_specific(false), m_readable(false), m_writable(false), - m_executable(false), m_target_byte_size(target_byte_size) { + m_executable(false), m_relocated(false), m_target_byte_size(target_byte_size) { // printf ("Section::Section(%p): module=%p, sect_id = 0x%16.16" PRIx64 ", // addr=[0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), file [0x%16.16" PRIx64 " // - 0x%16.16" PRIx64 "), flags = 0x%8.8x, name = %s\n", @@ -157,7 +157,7 @@ Section::Section(const lldb::SectionSP & m_file_offset(file_offset), m_file_size(file_size), m_log2align(log2align), m_children(), m_fake(false), m_encrypted(false), m_thread_specific(false), m_readable(false), m_writable(false), - m_executable(false), m_target_byte_size(target_byte_size) { + m_executable(false), m_relocated(false), m_target_byte_size(target_byte_size) { // printf ("Section::Section(%p): module=%p, sect_id = 0x%16.16" PRIx64 ", // addr=[0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), file [0x%16.16" PRIx64 " // - 0x%16.16" PRIx64 "), flags = 0x%8.8x, name = %s.%s\n", @@ -392,7 +392,7 @@ lldb::offset_t Section::GetSectionData(v return 0; } -lldb::offset_t Section::GetSectionData(DataExtractor §ion_data) const { +lldb::offset_t Section::GetSectionData(DataExtractor §ion_data) { if (m_obj_file) return m_obj_file->ReadSectionData(this, section_data); return 0; Modified: lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp?rev=314672&r1=314671&r2=314672&view=diff ============================================================================== --- lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp (original) +++ lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp Mon Oct 2 07:35:07 2017 @@ -405,7 +405,7 @@ ObjectFile *ObjectFileELF::CreateInstanc lldb::offset_t length) { if (!data_sp) { data_sp = - DataBufferLLVM::CreateSliceFromPath(file->GetPath(), length, file_offset); + DataBufferLLVM::CreateSliceFromPath(file->GetPath(), length, file_offset, true); if (!data_sp) return nullptr; data_offset = 0; @@ -423,7 +423,7 @@ ObjectFile *ObjectFileELF::CreateInstanc // Update the data to contain the entire file if it doesn't already if (data_sp->GetByteSize() < length) { data_sp = - DataBufferLLVM::CreateSliceFromPath(file->GetPath(), length, file_offset); + DataBufferLLVM::CreateSliceFromPath(file->GetPath(), length, file_offset, true); if (!data_sp) return nullptr; data_offset = 0; @@ -1818,6 +1818,12 @@ void ObjectFileELF::CreateSections(Secti if (!m_sections_ap.get() && ParseSectionHeaders()) { m_sections_ap.reset(new SectionList()); + // Object files frequently have 0 for every section address, meaning we + // need to compute synthetic addresses in order for "file addresses" from + // different sections to not overlap + bool synthaddrs = (CalculateType() == ObjectFile::Type::eTypeObjectFile); + uint64_t nextaddr = 0; + for (SectionHeaderCollIter I = m_section_headers.begin(); I != m_section_headers.end(); ++I) { const ELFSectionHeaderInfo &header = *I; @@ -1990,11 +1996,18 @@ void ObjectFileELF::CreateSections(Secti ? m_arch_spec.GetDataByteSize() : eSectionTypeCode == sect_type ? m_arch_spec.GetCodeByteSize() : 1; - const addr_t sect_file_addr = header.sh_flags & SHF_ALLOC - ? header.sh_addr - : LLDB_INVALID_ADDRESS; elf::elf_xword log2align = (header.sh_addralign == 0) ? 0 : llvm::Log2_64(header.sh_addralign); + + uint64_t addr = header.sh_addr; + + if ((header.sh_flags & SHF_ALLOC) && synthaddrs) { + nextaddr = + (nextaddr + header.sh_addralign - 1) & ~(header.sh_addralign - 1); + addr = nextaddr; + nextaddr += vm_size; + } + SectionSP section_sp(new Section( GetModule(), // Module to which this section belongs. this, // ObjectFile to which this section belongs and should read @@ -2002,7 +2015,7 @@ void ObjectFileELF::CreateSections(Secti SectionIndex(I), // Section ID. name, // Section name. sect_type, // Section type. - sect_file_addr, // VM address. + addr, // VM address. vm_size, // VM size in bytes of this section. header.sh_offset, // Offset of this section in the file. file_size, // Size of the section as found in the file. @@ -2720,7 +2733,7 @@ ObjectFileELF::ParseTrampolineSymbols(Sy rel_data, symtab_data, strtab_data); } -unsigned ObjectFileELF::RelocateSection( +unsigned ObjectFileELF::ApplyRelocations( Symtab *symtab, const ELFHeader *hdr, const ELFSectionHeader *rel_hdr, const ELFSectionHeader *symtab_hdr, const ELFSectionHeader *debug_hdr, DataExtractor &rel_data, DataExtractor &symtab_data, @@ -2797,7 +2810,8 @@ unsigned ObjectFileELF::RelocateSection( } unsigned ObjectFileELF::RelocateDebugSections(const ELFSectionHeader *rel_hdr, - user_id_t rel_id) { + user_id_t rel_id, + lldb_private::Symtab *thetab) { assert(rel_hdr->sh_type == SHT_RELA || rel_hdr->sh_type == SHT_REL); // Parse in the section list if needed. @@ -2833,10 +2847,11 @@ unsigned ObjectFileELF::RelocateDebugSec DataExtractor symtab_data; DataExtractor debug_data; - if (ReadSectionData(rel, rel_data) && ReadSectionData(symtab, symtab_data) && - ReadSectionData(debug, debug_data)) { - RelocateSection(m_symtab_ap.get(), &m_header, rel_hdr, symtab_hdr, - debug_hdr, rel_data, symtab_data, debug_data, debug); + if (GetData(rel->GetFileOffset(), rel->GetFileSize(), rel_data) && + GetData(symtab->GetFileOffset(), symtab->GetFileSize(), symtab_data) && + GetData(debug->GetFileOffset(), debug->GetFileSize(), debug_data)) { + ApplyRelocations(thetab, &m_header, rel_hdr, symtab_hdr, debug_hdr, + rel_data, symtab_data, debug_data, debug); } return 0; @@ -2930,21 +2945,48 @@ Symtab *ObjectFileELF::GetSymtab() { m_symtab_ap->CalculateSymbolSizes(); } + return m_symtab_ap.get(); +} + +void ObjectFileELF::RelocateSection(lldb_private::Section *section) +{ + static const char *debug_prefix = ".debug"; + + // Set relocated bit so we stop getting called, regardless of + // whether we actually relocate. + section->SetIsRelocated(true); + + // We only relocate in ELF relocatable files + if (CalculateType() != eTypeObjectFile) + return; + + const char *section_name = section->GetName().GetCString(); + // Can't relocate that which can't be named + if (section_name == nullptr) + return; + + // We don't relocate non-debug sections at the moment + if (strncmp(section_name, debug_prefix, strlen(debug_prefix))) + return; + + // Relocation section names to look for + std::string needle = std::string(".rel") + section_name; + std::string needlea = std::string(".rela") + section_name; + for (SectionHeaderCollIter I = m_section_headers.begin(); I != m_section_headers.end(); ++I) { if (I->sh_type == SHT_RELA || I->sh_type == SHT_REL) { - if (CalculateType() == eTypeObjectFile) { - const char *section_name = I->section_name.AsCString(""); - if (strstr(section_name, ".rela.debug") || - strstr(section_name, ".rel.debug")) { - const ELFSectionHeader &reloc_header = *I; - user_id_t reloc_id = SectionIndex(I); - RelocateDebugSections(&reloc_header, reloc_id); - } + const char *hay_name = I->section_name.GetCString(); + if (hay_name == nullptr) + continue; + if (needle == hay_name || needlea == hay_name) { + const ELFSectionHeader &reloc_header = *I; + user_id_t reloc_id = SectionIndex(I); + RelocateDebugSections(&reloc_header, reloc_id, GetSymtab()); + break; } } } - return m_symtab_ap.get(); } void ObjectFileELF::ParseUnwindSymbols(Symtab *symbol_table, Modified: lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h?rev=314672&r1=314671&r2=314672&view=diff ============================================================================== --- lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h (original) +++ lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.h Mon Oct 2 07:35:07 2017 @@ -154,6 +154,8 @@ public: llvm::StringRef StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const override; + void RelocateSection(lldb_private::Section *section) override; + private: ObjectFileELF(const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp, lldb::offset_t data_offset, const lldb_private::FileSpec *file, @@ -296,17 +298,18 @@ private: /// Relocates debug sections unsigned RelocateDebugSections(const elf::ELFSectionHeader *rel_hdr, - lldb::user_id_t rel_id); + lldb::user_id_t rel_id, + lldb_private::Symtab *thetab); - unsigned RelocateSection(lldb_private::Symtab *symtab, - const elf::ELFHeader *hdr, - const elf::ELFSectionHeader *rel_hdr, - const elf::ELFSectionHeader *symtab_hdr, - const elf::ELFSectionHeader *debug_hdr, - lldb_private::DataExtractor &rel_data, - lldb_private::DataExtractor &symtab_data, - lldb_private::DataExtractor &debug_data, - lldb_private::Section *rel_section); + unsigned ApplyRelocations(lldb_private::Symtab *symtab, + const elf::ELFHeader *hdr, + const elf::ELFSectionHeader *rel_hdr, + const elf::ELFSectionHeader *symtab_hdr, + const elf::ELFSectionHeader *debug_hdr, + lldb_private::DataExtractor &rel_data, + lldb_private::DataExtractor &symtab_data, + lldb_private::DataExtractor &debug_data, + lldb_private::Section *rel_section); /// Loads the section name string table into m_shstr_data. Returns the /// number of bytes constituting the table. Modified: lldb/trunk/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp?rev=314672&r1=314671&r2=314672&view=diff ============================================================================== --- lldb/trunk/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp (original) +++ lldb/trunk/source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp Mon Oct 2 07:35:07 2017 @@ -230,9 +230,9 @@ bool ObjectFileJIT::SetLoadAddress(Targe return num_loaded_sections > 0; } -size_t ObjectFileJIT::ReadSectionData(const lldb_private::Section *section, +size_t ObjectFileJIT::ReadSectionData(lldb_private::Section *section, lldb::offset_t section_offset, void *dst, - size_t dst_len) const { + size_t dst_len) { lldb::offset_t file_size = section->GetFileSize(); if (section_offset < file_size) { size_t src_len = file_size - section_offset; @@ -248,8 +248,8 @@ size_t ObjectFileJIT::ReadSectionData(co } size_t ObjectFileJIT::ReadSectionData( - const lldb_private::Section *section, - lldb_private::DataExtractor §ion_data) const { + lldb_private::Section *section, + lldb_private::DataExtractor §ion_data) { if (section->GetFileSize()) { const void *src = (void *)(uintptr_t)section->GetFileOffset(); Modified: lldb/trunk/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h?rev=314672&r1=314671&r2=314672&view=diff ============================================================================== --- lldb/trunk/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h (original) +++ lldb/trunk/source/Plugins/ObjectFile/JIT/ObjectFileJIT.h Mon Oct 2 07:35:07 2017 @@ -83,13 +83,13 @@ public: uint32_t GetDependentModules(lldb_private::FileSpecList &files) override; - size_t ReadSectionData(const lldb_private::Section *section, + size_t ReadSectionData(lldb_private::Section *section, lldb::offset_t section_offset, void *dst, - size_t dst_len) const override; + size_t dst_len) override; size_t - ReadSectionData(const lldb_private::Section *section, - lldb_private::DataExtractor §ion_data) const override; + ReadSectionData(lldb_private::Section *section, + lldb_private::DataExtractor §ion_data) override; lldb_private::Address GetEntryPointAddress() override; Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp?rev=314672&r1=314671&r2=314672&view=diff ============================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (original) +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Mon Oct 2 07:35:07 2017 @@ -436,7 +436,7 @@ void SymbolFileDWARF::InitializeObject() ModuleSP module_sp(m_obj_file->GetModule()); if (module_sp) { const SectionList *section_list = module_sp->GetSectionList(); - const Section *section = + Section *section = section_list->FindSectionByName(GetDWARFMachOSegmentName()).get(); // Memory map the DWARF mach-o segment so we have everything mmap'ed Modified: lldb/trunk/source/Symbol/ArmUnwindInfo.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ArmUnwindInfo.cpp?rev=314672&r1=314671&r2=314672&view=diff ============================================================================== --- lldb/trunk/source/Symbol/ArmUnwindInfo.cpp (original) +++ lldb/trunk/source/Symbol/ArmUnwindInfo.cpp Mon Oct 2 07:35:07 2017 @@ -46,7 +46,7 @@ bool ArmUnwindInfo::ArmExidxEntry::opera return address < other.address; } -ArmUnwindInfo::ArmUnwindInfo(const ObjectFile &objfile, SectionSP &arm_exidx, +ArmUnwindInfo::ArmUnwindInfo(ObjectFile &objfile, SectionSP &arm_exidx, SectionSP &arm_extab) : m_byte_order(objfile.GetByteOrder()), m_arm_exidx_sp(arm_exidx), m_arm_extab_sp(arm_extab) { Modified: lldb/trunk/source/Symbol/ObjectFile.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ObjectFile.cpp?rev=314672&r1=314671&r2=314672&view=diff ============================================================================== --- lldb/trunk/source/Symbol/ObjectFile.cpp (original) +++ lldb/trunk/source/Symbol/ObjectFile.cpp Mon Oct 2 07:35:07 2017 @@ -483,9 +483,9 @@ size_t ObjectFile::CopyData(lldb::offset return m_data.CopyData(offset, length, dst); } -size_t ObjectFile::ReadSectionData(const Section *section, +size_t ObjectFile::ReadSectionData(Section *section, lldb::offset_t section_offset, void *dst, - size_t dst_len) const { + size_t dst_len) { assert(section); section_offset *= section->GetTargetByteSize(); @@ -505,6 +505,9 @@ size_t ObjectFile::ReadSectionData(const dst_len, error); } } else { + if (!section->IsRelocated()) + RelocateSection(section); + const lldb::offset_t section_file_size = section->GetFileSize(); if (section_offset < section_file_size) { const size_t section_bytes_left = section_file_size - section_offset; @@ -531,8 +534,8 @@ size_t ObjectFile::ReadSectionData(const //---------------------------------------------------------------------- // Get the section data the file on disk //---------------------------------------------------------------------- -size_t ObjectFile::ReadSectionData(const Section *section, - DataExtractor §ion_data) const { +size_t ObjectFile::ReadSectionData(Section *section, + DataExtractor §ion_data) { // If some other objectfile owns this data, pass this to them. if (section->GetObjectFile() != this) return section->GetObjectFile()->ReadSectionData(section, section_data); @@ -562,8 +565,8 @@ size_t ObjectFile::ReadSectionData(const } } -size_t ObjectFile::MemoryMapSectionData(const Section *section, - DataExtractor §ion_data) const { +size_t ObjectFile::MemoryMapSectionData(Section *section, + DataExtractor §ion_data) { // If some other objectfile owns this data, pass this to them. if (section->GetObjectFile() != this) return section->GetObjectFile()->MemoryMapSectionData(section, @@ -572,6 +575,9 @@ size_t ObjectFile::MemoryMapSectionData( if (IsInMemory()) { return ReadSectionData(section, section_data); } else { + if (!section->IsRelocated()) + RelocateSection(section); + // The object file now contains a full mmap'ed copy of the object file data, // so just use this return GetData(section->GetFileOffset(), section->GetFileSize(), @@ -694,3 +700,7 @@ Status ObjectFile::LoadInMemory(Target & } return error; } + +void ObjectFile::RelocateSection(lldb_private::Section *section) +{ +} _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits