From 751caf65c26cf20b805e73ef650d688cfe7f7bc6 Mon Sep 17 00:00:00 2001 From: Greg Clayton Date: Fri, 7 Feb 2014 22:54:47 +0000 Subject: [PATCH] Modified ObjectFile::SetLoadAddress() to now be: ObjectFile::SetLoadAddress (Target &target, lldb::addr_t value, bool value_is_offset); Now "value" is a slide if "value_is_offset" is true, and "value" is an image base address otherwise. All previous usage of this API was using slides. Updated the ObjectFileELF and ObjectFileMachO SetLoadAddress methods to do the right thing. Also updated the ObjectFileMachO::SetLoadAddress() function to not load __LINKEDIT when it isn't needed and to only load sections that belong to the executable object file. llvm-svn: 201003 --- lldb/include/lldb/Core/Module.h | 19 +++- lldb/include/lldb/Symbol/ObjectFile.h | 4 +- lldb/source/API/SBModule.cpp | 2 +- lldb/source/API/SBTarget.cpp | 2 +- lldb/source/Commands/CommandObjectTarget.cpp | 3 +- lldb/source/Core/DynamicLoader.cpp | 3 +- lldb/source/Core/Module.cpp | 4 +- .../DynamicLoaderDarwinKernel.cpp | 2 +- .../Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 37 +++--- .../Plugins/ObjectFile/ELF/ObjectFileELF.h | 4 +- .../ObjectFile/Mach-O/ObjectFileMachO.cpp | 105 ++++++++++++++---- .../ObjectFile/Mach-O/ObjectFileMachO.h | 4 +- 12 files changed, 139 insertions(+), 50 deletions(-) diff --git a/lldb/include/lldb/Core/Module.h b/lldb/include/lldb/Core/Module.h index cae5a30be704..56650582791b 100644 --- a/lldb/include/lldb/Core/Module.h +++ b/lldb/include/lldb/Core/Module.h @@ -113,10 +113,18 @@ public: /// @param[in] target /// The target in which to apply the section load addresses. /// - /// @param[in] offset - /// The offset to apply to all file addresses for all top - /// level sections in the object file as each section load - /// address is being set. + /// @param[in] value + /// if \a value_is_offset is true, then value is the offset to + /// apply to all file addresses for all top level sections in + /// the object file as each section load address is being set. + /// If \a value_is_offset is false, then "value" is the new + /// absolute base address for the image. + /// + /// @param[in] value_is_offset + /// If \b true, then \a value is an offset to apply to each + /// file address of each top level section. + /// If \b false, then \a value is the image base address that + /// will be used to rigidly slide all loadable sections. /// /// @param[out] changed /// If any section load addresses were changed in \a target, @@ -133,7 +141,8 @@ public: //------------------------------------------------------------------ bool SetLoadAddress (Target &target, - lldb::addr_t offset, + lldb::addr_t value, + bool value_is_offset, bool &changed); //------------------------------------------------------------------ diff --git a/lldb/include/lldb/Symbol/ObjectFile.h b/lldb/include/lldb/Symbol/ObjectFile.h index 80d42925d336..afa1f9b40902 100644 --- a/lldb/include/lldb/Symbol/ObjectFile.h +++ b/lldb/include/lldb/Symbol/ObjectFile.h @@ -458,7 +458,9 @@ public: /// Returns true iff any section's load address changed. //------------------------------------------------------------------ virtual bool - SetLoadAddress(Target &target, lldb::addr_t base_addr) + SetLoadAddress(Target &target, + lldb::addr_t value, + bool value_is_offset) { return false; } diff --git a/lldb/source/API/SBModule.cpp b/lldb/source/API/SBModule.cpp index 19c3ee7fce53..c8543d4de298 100644 --- a/lldb/source/API/SBModule.cpp +++ b/lldb/source/API/SBModule.cpp @@ -69,7 +69,7 @@ SBModule::SBModule (lldb::SBProcess &process, lldb::addr_t header_addr) : { Target &target = process_sp->GetTarget(); bool changed = false; - m_opaque_sp->SetLoadAddress(target, 0, changed); + m_opaque_sp->SetLoadAddress(target, 0, true, changed); target.GetImages().Append(m_opaque_sp); } } diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp index 52203f6b31b1..224349c0bce6 100644 --- a/lldb/source/API/SBTarget.cpp +++ b/lldb/source/API/SBTarget.cpp @@ -2499,7 +2499,7 @@ SBTarget::SetModuleLoadAddress (lldb::SBModule module, int64_t slide_offset) if (module_sp) { bool changed = false; - if (module_sp->SetLoadAddress (*target_sp, slide_offset, changed)) + if (module_sp->SetLoadAddress (*target_sp, slide_offset, true, changed)) { // The load was successful, make sure that at least some sections // changed before we notify that our module was loaded. diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp index 7a46d1cb7829..308b72f355d3 100644 --- a/lldb/source/Commands/CommandObjectTarget.cpp +++ b/lldb/source/Commands/CommandObjectTarget.cpp @@ -2894,7 +2894,8 @@ protected: if (m_slide_option.GetOptionValue().OptionWasSet()) { const addr_t slide = m_slide_option.GetOptionValue().GetCurrentValue(); - module->SetLoadAddress (*target, slide, changed); + const bool slide_is_offset = true; + module->SetLoadAddress (*target, slide, slide_is_offset, changed); } else { diff --git a/lldb/source/Core/DynamicLoader.cpp b/lldb/source/Core/DynamicLoader.cpp index 0f53da8b97f9..1f545b727a1e 100644 --- a/lldb/source/Core/DynamicLoader.cpp +++ b/lldb/source/Core/DynamicLoader.cpp @@ -128,7 +128,8 @@ void DynamicLoader::UpdateLoadedSectionsCommon(ModuleSP module, addr_t base_addr) { bool changed; - module->SetLoadAddress(m_process->GetTarget(), base_addr, changed); + const bool base_addr_is_offset = true; + module->SetLoadAddress(m_process->GetTarget(), base_addr, base_addr_is_offset, changed); } void diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp index ab4bcbbb0d07..d5758c09b1e2 100644 --- a/lldb/source/Core/Module.cpp +++ b/lldb/source/Core/Module.cpp @@ -1500,12 +1500,12 @@ Module::SetArchitecture (const ArchSpec &new_arch) } bool -Module::SetLoadAddress (Target &target, lldb::addr_t offset, bool &changed) +Module::SetLoadAddress (Target &target, lldb::addr_t value, bool value_is_offset, bool &changed) { ObjectFile *object_file = GetObjectFile(); if (object_file) { - changed = object_file->SetLoadAddress(target, offset); + changed = object_file->SetLoadAddress(target, value, value_is_offset); return true; } else diff --git a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp index dcee569943a2..a27d4b9d814e 100644 --- a/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp +++ b/lldb/source/Plugins/DynamicLoader/Darwin-Kernel/DynamicLoaderDarwinKernel.cpp @@ -542,7 +542,7 @@ DynamicLoaderDarwinKernel::KextImageInfo::LoadImageAtFileAddress (Process *proce if (m_module_sp) { bool changed = false; - if (m_module_sp->SetLoadAddress (process->GetTarget(), 0, changed)) + if (m_module_sp->SetLoadAddress (process->GetTarget(), 0, true, changed)) m_load_process_stop_id = process->GetStopID(); } return false; diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index 2f3cd8b78cf7..02db05b3c6b2 100644 --- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -464,7 +464,9 @@ ObjectFileELF::IsExecutable() const } bool -ObjectFileELF::SetLoadAddress(Target &target, addr_t base_addr) +ObjectFileELF::SetLoadAddress (Target &target, + lldb::addr_t value, + bool value_is_offset) { bool changed = false; ModuleSP module_sp = GetModule(); @@ -474,23 +476,32 @@ ObjectFileELF::SetLoadAddress(Target &target, addr_t base_addr) SectionList *section_list = GetSectionList (); if (section_list) { - const size_t num_sections = section_list->GetSize(); - size_t sect_idx = 0; - for (sect_idx = 0; sect_idx < num_sections; ++sect_idx) + if (value_is_offset) { - // Iterate through the object file sections to find all - // of the sections that have SHF_ALLOC in their flag bits. - SectionSP section_sp (section_list->GetSectionAtIndex (sect_idx)); - // if (section_sp && !section_sp->IsThreadSpecific()) - if (section_sp && section_sp->Test(SHF_ALLOC)) + const size_t num_sections = section_list->GetSize(); + size_t sect_idx = 0; + + for (sect_idx = 0; sect_idx < num_sections; ++sect_idx) { - if (target.GetSectionLoadList().SetSectionLoadAddress (section_sp, section_sp->GetFileAddress() + base_addr)) - ++num_loaded_sections; + // Iterate through the object file sections to find all + // of the sections that have SHF_ALLOC in their flag bits. + SectionSP section_sp (section_list->GetSectionAtIndex (sect_idx)); + // if (section_sp && !section_sp->IsThreadSpecific()) + if (section_sp && section_sp->Test(SHF_ALLOC)) + { + if (target.GetSectionLoadList().SetSectionLoadAddress (section_sp, section_sp->GetFileAddress() + value)) + ++num_loaded_sections; + } } + changed = num_loaded_sections > 0; + return num_loaded_sections > 0; + } + else + { + // Not sure how to slide an ELF file given the base address + // of the ELF file in memory } } - changed = num_loaded_sections > 0; - return num_loaded_sections > 0; } return changed; } diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h index 4fb0250108a4..9b7c073d902d 100644 --- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h +++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h @@ -119,7 +119,9 @@ public: ParseHeader(); virtual bool - SetLoadAddress(lldb_private::Target &target, lldb::addr_t base_addr); + SetLoadAddress (lldb_private::Target &target, + lldb::addr_t value, + bool value_is_offset); virtual lldb::ByteOrder GetByteOrder() const; diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp index 5cbb31ef5b22..a4bfc5caec53 100644 --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp @@ -4706,7 +4706,9 @@ ObjectFileMachO::GetPluginVersion() bool -ObjectFileMachO::SetLoadAddress(Target &target, addr_t base_addr) +ObjectFileMachO::SetLoadAddress (Target &target, + lldb::addr_t value, + bool value_is_offset) { bool changed = false; ModuleSP module_sp = GetModule(); @@ -4719,39 +4721,98 @@ ObjectFileMachO::SetLoadAddress(Target &target, addr_t base_addr) lldb::addr_t mach_base_file_addr = LLDB_INVALID_ADDRESS; const size_t num_sections = section_list->GetSize(); - // First find the address of the mach header which is the first non-zero - // file sized section whose file offset is zero as this will be subtracted - // from each other valid section's vmaddr and then get "base_addr" added to - // it when loading the module in the target - for (size_t sect_idx = 0; - sect_idx < num_sections && mach_base_file_addr == LLDB_INVALID_ADDRESS; - ++sect_idx) - { - // Iterate through the object file sections to find all - // of the sections that size on disk (to avoid __PAGEZERO) - // and load them - Section *section = section_list->GetSectionAtIndex (sect_idx).get(); - if (section && section->GetFileSize() > 0 && section->GetFileOffset() == 0) - { - mach_base_file_addr = section->GetFileAddress(); - } - } - - if (mach_base_file_addr != LLDB_INVALID_ADDRESS) + const bool is_memory_image = (bool)m_process_wp.lock(); + const Strata strata = GetStrata(); + static ConstString g_linkedit_segname ("__LINKEDIT"); + if (value_is_offset) { + // "value" is an offset to apply to each top level segment for (size_t sect_idx = 0; sect_idx < num_sections; ++sect_idx) { // Iterate through the object file sections to find all // of the sections that size on disk (to avoid __PAGEZERO) // and load them SectionSP section_sp (section_list->GetSectionAtIndex (sect_idx)); - if (section_sp && section_sp->GetFileSize() > 0 && !section_sp->IsThreadSpecific()) + if (section_sp && + section_sp->GetFileSize() > 0 && + section_sp->IsThreadSpecific() == false && + module_sp.get() == section_sp->GetModule().get()) { - if (target.GetSectionLoadList().SetSectionLoadAddress (section_sp, section_sp->GetFileAddress() - mach_base_file_addr + base_addr)) + // Ignore __LINKEDIT and __DWARF segments + if (section_sp->GetName() == g_linkedit_segname) + { + // Only map __LINKEDIT if we have an in memory image and this isn't + // a kernel binary like a kext or mach_kernel. + if (is_memory_image == false || strata == eStrataKernel) + continue; + } + if (target.GetSectionLoadList().SetSectionLoadAddress (section_sp, section_sp->GetFileAddress() + value)) ++num_loaded_sections; } } } + else + { + // "value" is the new base address of the mach_header, adjust each + // section accordingly + + // First find the address of the mach header which is the first non-zero + // file sized section whose file offset is zero as this will be subtracted + // from each other valid section's vmaddr and then get "base_addr" added to + // it when loading the module in the target + for (size_t sect_idx = 0; + sect_idx < num_sections && mach_base_file_addr == LLDB_INVALID_ADDRESS; + ++sect_idx) + { + // Iterate through the object file sections to find all + // of the sections that size on disk (to avoid __PAGEZERO) + // and load them + Section *section = section_list->GetSectionAtIndex (sect_idx).get(); + if (section && + section->GetFileSize() > 0 && + section->GetFileOffset() == 0 && + section->IsThreadSpecific() == false && + module_sp.get() == section->GetModule().get()) + { + // Ignore __LINKEDIT and __DWARF segments + if (section->GetName() == g_linkedit_segname) + { + // Only map __LINKEDIT if we have an in memory image and this isn't + // a kernel binary like a kext or mach_kernel. + if (is_memory_image == false || strata == eStrataKernel) + continue; + } + mach_base_file_addr = section->GetFileAddress(); + } + } + + if (mach_base_file_addr != LLDB_INVALID_ADDRESS) + { + for (size_t sect_idx = 0; sect_idx < num_sections; ++sect_idx) + { + // Iterate through the object file sections to find all + // of the sections that size on disk (to avoid __PAGEZERO) + // and load them + SectionSP section_sp (section_list->GetSectionAtIndex (sect_idx)); + if (section_sp && + section_sp->GetFileSize() > 0 && + section_sp->IsThreadSpecific() == false && + module_sp.get() == section_sp->GetModule().get()) + { + // Ignore __LINKEDIT and __DWARF segments + if (section_sp->GetName() == g_linkedit_segname) + { + // Only map __LINKEDIT if we have an in memory image and this isn't + // a kernel binary like a kext or mach_kernel. + if (is_memory_image == false || strata == eStrataKernel) + continue; + } + if (target.GetSectionLoadList().SetSectionLoadAddress (section_sp, section_sp->GetFileAddress() - mach_base_file_addr + value)) + ++num_loaded_sections; + } + } + } + } } changed = num_loaded_sections > 0; return num_loaded_sections > 0; diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h index e1ab99959b56..f6b0e3a89cc6 100644 --- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h +++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.h @@ -90,7 +90,9 @@ public: ParseHeader (); virtual bool - SetLoadAddress(lldb_private::Target &target, lldb::addr_t base_addr); + SetLoadAddress(lldb_private::Target &target, + lldb::addr_t value, + bool value_is_offset); virtual lldb::ByteOrder GetByteOrder () const;