Index: include/lldb/Core/Section.h =================================================================== --- include/lldb/Core/Section.h +++ include/lldb/Core/Section.h @@ -238,7 +238,7 @@ /// 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 @@ // 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 @@ 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 Index: include/lldb/Symbol/ArmUnwindInfo.h =================================================================== --- include/lldb/Symbol/ArmUnwindInfo.h +++ include/lldb/Symbol/ArmUnwindInfo.h @@ -31,7 +31,7 @@ class ArmUnwindInfo { public: - ArmUnwindInfo(const ObjectFile &objfile, lldb::SectionSP &arm_exidx, + ArmUnwindInfo(ObjectFile &objfile, lldb::SectionSP &arm_exidx, lldb::SectionSP &arm_extab); ~ArmUnwindInfo(); Index: include/lldb/Symbol/ObjectFile.h =================================================================== --- include/lldb/Symbol/ObjectFile.h +++ include/lldb/Symbol/ObjectFile.h @@ -352,6 +352,12 @@ virtual Symtab *GetSymtab() = 0; //------------------------------------------------------------------ + /// Perform relocations on the section if necessary. + /// + //------------------------------------------------------------------ + virtual void RelocateSectionIfNeeded(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 @@ 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; } Index: source/Core/Section.cpp =================================================================== --- source/Core/Section.cpp +++ source/Core/Section.cpp @@ -135,7 +135,7 @@ 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 @@ 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 @@ 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; Index: source/Plugins/ObjectFile/ELF/ObjectFileELF.h =================================================================== --- source/Plugins/ObjectFile/ELF/ObjectFileELF.h +++ source/Plugins/ObjectFile/ELF/ObjectFileELF.h @@ -296,7 +296,10 @@ /// 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); + + void RelocateSectionIfNeeded(lldb_private::Section *section) override; unsigned RelocateSection(lldb_private::Symtab *symtab, const elf::ELFHeader *hdr, Index: source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp =================================================================== --- source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -405,7 +405,7 @@ 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 @@ // 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 @@ 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 @@ ? 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 @@ 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. @@ -2797,7 +2810,8 @@ } 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,9 +2847,10 @@ 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, + if (GetData(rel->GetFileOffset(), rel->GetFileSize(), rel_data) && + GetData(symtab->GetFileOffset(), symtab->GetFileSize(), symtab_data) && + GetData(debug->GetFileOffset(), debug->GetFileSize(), debug_data)) { + RelocateSection(thetab, &m_header, rel_hdr, symtab_hdr, debug_hdr, rel_data, symtab_data, debug_data, debug); } @@ -2930,21 +2945,48 @@ m_symtab_ap->CalculateSymbolSizes(); } + return m_symtab_ap.get(); +} + +void ObjectFileELF::RelocateSectionIfNeeded(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, Index: source/Plugins/ObjectFile/JIT/ObjectFileJIT.h =================================================================== --- source/Plugins/ObjectFile/JIT/ObjectFileJIT.h +++ source/Plugins/ObjectFile/JIT/ObjectFileJIT.h @@ -83,13 +83,13 @@ 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; Index: source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp =================================================================== --- source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp +++ source/Plugins/ObjectFile/JIT/ObjectFileJIT.cpp @@ -230,9 +230,9 @@ 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( - 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(); Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -436,7 +436,7 @@ 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 Index: source/Symbol/ArmUnwindInfo.cpp =================================================================== --- source/Symbol/ArmUnwindInfo.cpp +++ source/Symbol/ArmUnwindInfo.cpp @@ -46,7 +46,7 @@ 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) { Index: source/Symbol/ObjectFile.cpp =================================================================== --- source/Symbol/ObjectFile.cpp +++ source/Symbol/ObjectFile.cpp @@ -483,9 +483,9 @@ 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 @@ dst_len, error); } } else { + if (!section->IsRelocated()) + RelocateSectionIfNeeded(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 @@ //---------------------------------------------------------------------- // 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::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 @@ if (IsInMemory()) { return ReadSectionData(section, section_data); } else { + if (!section->IsRelocated()) + RelocateSectionIfNeeded(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 @@ } return error; } + +void ObjectFile::RelocateSectionIfNeeded(lldb_private::Section *section) +{ +}