diff options
-rw-r--r-- | lldb/include/lldb/Symbol/ObjectFile.h | 13 | ||||
-rw-r--r-- | lldb/include/lldb/Target/DynamicLoader.h | 54 | ||||
-rw-r--r-- | lldb/source/Core/DynamicLoader.cpp | 137 | ||||
-rw-r--r-- | lldb/source/Core/Module.cpp | 24 | ||||
-rw-r--r-- | lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp | 138 | ||||
-rw-r--r-- | lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h | 17 | ||||
-rw-r--r-- | lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 33 | ||||
-rw-r--r-- | lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h | 3 |
8 files changed, 254 insertions, 165 deletions
diff --git a/lldb/include/lldb/Symbol/ObjectFile.h b/lldb/include/lldb/Symbol/ObjectFile.h index ad500f5413b..80d42925d33 100644 --- a/lldb/include/lldb/Symbol/ObjectFile.h +++ b/lldb/include/lldb/Symbol/ObjectFile.h @@ -451,6 +451,19 @@ public: } //------------------------------------------------------------------ + /// Sets the load address for an entire module, assuming a rigid + /// slide of sections, if possible in the implementation. + /// + /// @return + /// Returns true iff any section's load address changed. + //------------------------------------------------------------------ + virtual bool + SetLoadAddress(Target &target, lldb::addr_t base_addr) + { + return false; + } + + //------------------------------------------------------------------ /// Gets whether endian swapping should occur when extracting data /// from this object file. /// diff --git a/lldb/include/lldb/Target/DynamicLoader.h b/lldb/include/lldb/Target/DynamicLoader.h index 272f64f3311..6652a5ec144 100644 --- a/lldb/include/lldb/Target/DynamicLoader.h +++ b/lldb/include/lldb/Target/DynamicLoader.h @@ -246,6 +246,60 @@ public: protected: //------------------------------------------------------------------ + // Utility methods for derived classes + //------------------------------------------------------------------ + + /// Checks to see if the target module has changed, updates the target + /// accordingly and returns the target executable module. + lldb::ModuleSP + GetTargetExecutable(); + + /// Updates the load address of every allocatable section in @p module. + /// + /// @param module The module to traverse. + /// + /// @param link_map_addr The virtual address of the link map for the @p module. + /// + /// @param base_addr The virtual base address @p module is loaded at. + virtual void + UpdateLoadedSections(lldb::ModuleSP module, + lldb::addr_t link_map_addr, + lldb::addr_t base_addr); + + // Utility method so base classes can share implementation of UpdateLoadedSections + void + UpdateLoadedSectionsCommon(lldb::ModuleSP module, + lldb::addr_t base_addr); + + /// Removes the loaded sections from the target in @p module. + /// + /// @param module The module to traverse. + virtual void + UnloadSections(const lldb::ModuleSP module); + + // Utility method so base classes can share implementation of UnloadSections + void + UnloadSectionsCommon(const lldb::ModuleSP module); + + /// Locates or creates a module given by @p file and updates/loads the + /// resulting module at the virtual base address @p base_addr. + lldb::ModuleSP + LoadModuleAtAddress(const lldb_private::FileSpec &file, lldb::addr_t link_map_addr, lldb::addr_t base_addr); + + const lldb_private::SectionList * + GetSectionListFromModule(const lldb::ModuleSP module) const; + + // Read an unsigned int of the given size from memory at the given addr. + // Return -1 if the read fails, otherwise return the result as an int64_t. + int64_t + ReadUnsignedIntWithSizeInBytes(lldb::addr_t addr, int size_in_bytes); + + // Read a pointer from memory at the given addr. + // Return LLDB_INVALID_ADDRESS if the read fails. + lldb::addr_t + ReadPointer(lldb::addr_t addr); + + //------------------------------------------------------------------ // Member variables. //------------------------------------------------------------------ Process* m_process; ///< The process that this dynamic loader plug-in is tracking. diff --git a/lldb/source/Core/DynamicLoader.cpp b/lldb/source/Core/DynamicLoader.cpp index 82f84048b32..0f53da8b97f 100644 --- a/lldb/source/Core/DynamicLoader.cpp +++ b/lldb/source/Core/DynamicLoader.cpp @@ -10,7 +10,11 @@ #include "lldb/lldb-private.h" #include "lldb/Target/DynamicLoader.h" #include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" #include "lldb/Core/PluginManager.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/Section.h" using namespace lldb; using namespace lldb_private; @@ -74,3 +78,136 @@ DynamicLoader::SetStopWhenImagesChange (bool stop) m_process->SetStopOnSharedLibraryEvents (stop); } +ModuleSP +DynamicLoader::GetTargetExecutable() +{ + Target &target = m_process->GetTarget(); + ModuleSP executable = target.GetExecutableModule(); + + if (executable.get()) + { + if (executable->GetFileSpec().Exists()) + { + ModuleSpec module_spec (executable->GetFileSpec(), executable->GetArchitecture()); + ModuleSP module_sp (new Module (module_spec)); + + // Check if the executable has changed and set it to the target executable if they differ. + if (module_sp.get() && module_sp->GetUUID().IsValid() && executable->GetUUID().IsValid()) + { + if (module_sp->GetUUID() != executable->GetUUID()) + executable.reset(); + } + else if (executable->FileHasChanged()) + { + executable.reset(); + } + + if (!executable.get()) + { + executable = target.GetSharedModule(module_spec); + if (executable.get() != target.GetExecutableModulePointer()) + { + // Don't load dependent images since we are in dyld where we will know + // and find out about all images that are loaded + const bool get_dependent_images = false; + target.SetExecutableModule(executable, get_dependent_images); + } + } + } + } + return executable; +} + +void +DynamicLoader::UpdateLoadedSections(ModuleSP module, addr_t link_map_addr, addr_t base_addr) +{ + UpdateLoadedSectionsCommon(module, base_addr); +} + +void +DynamicLoader::UpdateLoadedSectionsCommon(ModuleSP module, addr_t base_addr) +{ + bool changed; + module->SetLoadAddress(m_process->GetTarget(), base_addr, changed); +} + +void +DynamicLoader::UnloadSections(const ModuleSP module) +{ + UnloadSectionsCommon(module); +} + +void +DynamicLoader::UnloadSectionsCommon(const ModuleSP module) +{ + Target &target = m_process->GetTarget(); + const SectionList *sections = GetSectionListFromModule(module); + + assert(sections && "SectionList missing from unloaded module."); + + const size_t num_sections = sections->GetSize(); + for (size_t i = 0; i < num_sections; ++i) + { + SectionSP section_sp (sections->GetSectionAtIndex(i)); + target.SetSectionUnloaded(section_sp); + } +} + + +const SectionList * +DynamicLoader::GetSectionListFromModule(const ModuleSP module) const +{ + SectionList *sections = nullptr; + if (module.get()) + { + ObjectFile *obj_file = module->GetObjectFile(); + if (obj_file) + { + sections = obj_file->GetSectionList(); + } + } + return sections; +} + +ModuleSP +DynamicLoader::LoadModuleAtAddress(const FileSpec &file, addr_t link_map_addr, addr_t base_addr) +{ + Target &target = m_process->GetTarget(); + ModuleList &modules = target.GetImages(); + ModuleSP module_sp; + + ModuleSpec module_spec (file, target.GetArchitecture()); + if ((module_sp = modules.FindFirstModule (module_spec))) + { + UpdateLoadedSections(module_sp, link_map_addr, base_addr); + } + else if ((module_sp = target.GetSharedModule(module_spec))) + { + UpdateLoadedSections(module_sp, link_map_addr, base_addr); + } + + return module_sp; +} + +int64_t +DynamicLoader::ReadUnsignedIntWithSizeInBytes(addr_t addr, int size_in_bytes) +{ + Error error; + + uint64_t value = m_process->ReadUnsignedIntegerFromMemory(addr, size_in_bytes, 0, error); + if (error.Fail()) + return -1; + else + return (int64_t)value; +} + +addr_t +DynamicLoader::ReadPointer(addr_t addr) +{ + Error error; + addr_t value = m_process->ReadPointerFromMemory(addr, error); + if (error.Fail()) + return LLDB_INVALID_ADDRESS; + else + return value; +} diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp index 3815a2b08e6..64a16798608 100644 --- a/lldb/source/Core/Module.cpp +++ b/lldb/source/Core/Module.cpp @@ -1502,28 +1502,12 @@ Module::SetArchitecture (const ArchSpec &new_arch) bool Module::SetLoadAddress (Target &target, lldb::addr_t offset, bool &changed) { - size_t num_loaded_sections = 0; - SectionList *section_list = GetSectionList (); - if (section_list) + ObjectFile *object_file = GetObjectFile(); + if (object_file) { - const size_t num_sections = section_list->GetSize(); - size_t sect_idx = 0; - for (sect_idx = 0; sect_idx < num_sections; ++sect_idx) - { - // Iterate through the object file sections to find the - // first section that starts of file offset zero and that - // has bytes in the file... - SectionSP section_sp (section_list->GetSectionAtIndex (sect_idx)); - // Only load non-thread specific sections when given a slide - if (section_sp && !section_sp->IsThreadSpecific()) - { - if (target.GetSectionLoadList().SetSectionLoadAddress (section_sp, section_sp->GetFileAddress() + offset)) - ++num_loaded_sections; - } - } + return object_file->SetLoadAddress(target, offset); } - changed = num_loaded_sections > 0; - return num_loaded_sections > 0; + return false; } diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp index 7b29904f0d0..c84aec1c17f 100644 --- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp +++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp @@ -150,46 +150,6 @@ DynamicLoaderPOSIXDYLD::DidLaunch() } } -ModuleSP -DynamicLoaderPOSIXDYLD::GetTargetExecutable() -{ - Target &target = m_process->GetTarget(); - ModuleSP executable = target.GetExecutableModule(); - - if (executable.get()) - { - if (executable->GetFileSpec().Exists()) - { - ModuleSpec module_spec (executable->GetFileSpec(), executable->GetArchitecture()); - ModuleSP module_sp (new Module (module_spec)); - - // Check if the executable has changed and set it to the target executable if they differ. - if (module_sp.get() && module_sp->GetUUID().IsValid() && executable->GetUUID().IsValid()) - { - if (module_sp->GetUUID() != executable->GetUUID()) - executable.reset(); - } - else if (executable->FileHasChanged()) - { - executable.reset(); - } - - if (!executable.get()) - { - executable = target.GetSharedModule(module_spec); - if (executable.get() != target.GetExecutableModulePointer()) - { - // Don't load dependent images since we are in dyld where we will know - // and find out about all images that are loaded - const bool get_dependent_images = false; - target.SetExecutableModule(executable, get_dependent_images); - } - } - } - } - return executable; -} - Error DynamicLoaderPOSIXDYLD::ExecutePluginCommand(Args &command, Stream *strm) { @@ -211,45 +171,17 @@ DynamicLoaderPOSIXDYLD::CanLoadImage() void DynamicLoaderPOSIXDYLD::UpdateLoadedSections(ModuleSP module, addr_t link_map_addr, addr_t base_addr) { - Target &target = m_process->GetTarget(); - const SectionList *sections = GetSectionListFromModule(module); - - assert(sections && "SectionList missing from loaded module."); - m_loaded_modules[module] = link_map_addr; - const size_t num_sections = sections->GetSize(); - - for (unsigned i = 0; i < num_sections; ++i) - { - SectionSP section_sp (sections->GetSectionAtIndex(i)); - lldb::addr_t new_load_addr = section_sp->GetFileAddress() + base_addr; - - // If the file address of the section is zero then this is not an - // allocatable/loadable section (property of ELF sh_addr). Skip it. - if (new_load_addr == base_addr) - continue; - - target.SetSectionLoadAddress(section_sp, new_load_addr); - } + UpdateLoadedSectionsCommon(module, base_addr); } void DynamicLoaderPOSIXDYLD::UnloadSections(const ModuleSP module) { - Target &target = m_process->GetTarget(); - const SectionList *sections = GetSectionListFromModule(module); - - assert(sections && "SectionList missing from unloaded module."); - m_loaded_modules.erase(module); - const size_t num_sections = sections->GetSize(); - for (size_t i = 0; i < num_sections; ++i) - { - SectionSP section_sp (sections->GetSectionAtIndex(i)); - target.SetSectionUnloaded(section_sp); - } + UnloadSectionsCommon(module); } void @@ -467,26 +399,6 @@ DynamicLoaderPOSIXDYLD::LoadAllCurrentModules() m_process->GetTarget().ModulesDidLoad(module_list); } -ModuleSP -DynamicLoaderPOSIXDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t link_map_addr, addr_t base_addr) -{ - Target &target = m_process->GetTarget(); - ModuleList &modules = target.GetImages(); - ModuleSP module_sp; - - ModuleSpec module_spec (file, target.GetArchitecture()); - if ((module_sp = modules.FindFirstModule (module_spec))) - { - UpdateLoadedSections(module_sp, link_map_addr, base_addr); - } - else if ((module_sp = target.GetSharedModule(module_spec))) - { - UpdateLoadedSections(module_sp, link_map_addr, base_addr); - } - - return module_sp; -} - addr_t DynamicLoaderPOSIXDYLD::ComputeLoadOffset() { @@ -530,41 +442,6 @@ DynamicLoaderPOSIXDYLD::GetEntryPoint() return m_entry_point; } -const SectionList * -DynamicLoaderPOSIXDYLD::GetSectionListFromModule(const ModuleSP module) const -{ - SectionList *sections = nullptr; - if (module.get()) - { - ObjectFile *obj_file = module->GetObjectFile(); - if (obj_file) - { - sections = obj_file->GetSectionList(); - } - } - return sections; -} - -static int ReadInt(Process *process, addr_t addr) -{ - Error error; - int value = (int)process->ReadUnsignedIntegerFromMemory(addr, sizeof(uint32_t), 0, error); - if (error.Fail()) - return -1; - else - return value; -} - -static addr_t ReadPointer(Process *process, addr_t addr) -{ - Error error; - addr_t value = process->ReadPointerFromMemory(addr, error); - if (error.Fail()) - return LLDB_INVALID_ADDRESS; - else - return value; -} - lldb::addr_t DynamicLoaderPOSIXDYLD::GetThreadLocalData (const lldb::ModuleSP module, const lldb::ThreadSP thread) { @@ -586,26 +463,27 @@ DynamicLoaderPOSIXDYLD::GetThreadLocalData (const lldb::ModuleSP module, const l return LLDB_INVALID_ADDRESS; // Find the module's modid. - int modid = ReadInt (m_process, link_map + metadata.modid_offset); + int modid_size = 4; // FIXME(spucci): This isn't right for big-endian 64-bit + int64_t modid = ReadUnsignedIntWithSizeInBytes (link_map + metadata.modid_offset, modid_size); if (modid == -1) return LLDB_INVALID_ADDRESS; // Lookup the DTV stucture for this thread. addr_t dtv_ptr = tp + metadata.dtv_offset; - addr_t dtv = ReadPointer (m_process, dtv_ptr); + addr_t dtv = ReadPointer (dtv_ptr); if (dtv == LLDB_INVALID_ADDRESS) return LLDB_INVALID_ADDRESS; // Find the TLS block for this module. addr_t dtv_slot = dtv + metadata.dtv_slot_size*modid; - addr_t tls_block = ReadPointer (m_process, dtv_slot + metadata.tls_offset); + addr_t tls_block = ReadPointer (dtv_slot + metadata.tls_offset); Module *mod = module.get(); Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER)); if (log) log->Printf("DynamicLoaderPOSIXDYLD::Performed TLS lookup: " - "module=%s, link_map=0x%" PRIx64 ", tp=0x%" PRIx64 ", modid=%i, tls_block=0x%" PRIx64 "\n", - mod->GetObjectName().AsCString(""), link_map, tp, modid, tls_block); + "module=%s, link_map=0x%" PRIx64 ", tp=0x%" PRIx64 ", modid=%ld, tls_block=0x%" PRIx64 "\n", + mod->GetObjectName().AsCString(""), link_map, tp, (int64_t)modid, tls_block); return tls_block; } diff --git a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h index 7997b34195a..9ced5da8a01 100644 --- a/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h +++ b/lldb/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h @@ -126,7 +126,7 @@ protected: /// @param link_map_addr The virtual address of the link map for the @p module. /// /// @param base_addr The virtual base address @p module is loaded at. - void + virtual void UpdateLoadedSections(lldb::ModuleSP module, lldb::addr_t link_map_addr, lldb::addr_t base_addr); @@ -134,14 +134,9 @@ protected: /// Removes the loaded sections from the target in @p module. /// /// @param module The module to traverse. - void + virtual void UnloadSections(const lldb::ModuleSP module); - /// Locates or creates a module given by @p file and updates/loads the - /// resulting module at the virtual base address @p base_addr. - lldb::ModuleSP - LoadModuleAtAddress(const lldb_private::FileSpec &file, lldb::addr_t link_map_addr, lldb::addr_t base_addr); - /// Resolves the entry point for the current inferior process and sets a /// breakpoint at that address. void @@ -173,16 +168,8 @@ protected: lldb::addr_t GetEntryPoint(); - /// Checks to see if the target module has changed, updates the target - /// accordingly and returns the target executable module. - lldb::ModuleSP - GetTargetExecutable(); - private: DISALLOW_COPY_AND_ASSIGN(DynamicLoaderPOSIXDYLD); - - const lldb_private::SectionList * - GetSectionListFromModule(const lldb::ModuleSP module) const; }; #endif // liblldb_DynamicLoaderPOSIXDYLD_H_ diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index 7bdacfe14cd..2f3cd8b78cf 100644 --- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -24,6 +24,7 @@ #include "lldb/Core/Stream.h" #include "lldb/Symbol/DWARFCallFrameInfo.h" #include "lldb/Symbol/SymbolContext.h" +#include "lldb/Target/SectionLoadList.h" #include "lldb/Target/Target.h" #include "lldb/Host/Host.h" @@ -462,6 +463,38 @@ ObjectFileELF::IsExecutable() const return m_header.e_entry != 0; } +bool +ObjectFileELF::SetLoadAddress(Target &target, addr_t base_addr) +{ + bool changed = false; + ModuleSP module_sp = GetModule(); + if (module_sp) + { + size_t num_loaded_sections = 0; + 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) + { + // 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() + base_addr)) + ++num_loaded_sections; + } + } + } + changed = num_loaded_sections > 0; + return num_loaded_sections > 0; + } + return changed; +} + ByteOrder ObjectFileELF::GetByteOrder() const { diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h index a2ab9b8f370..4fb0250108a 100644 --- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h +++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.h @@ -118,6 +118,9 @@ public: virtual bool ParseHeader(); + virtual bool + SetLoadAddress(lldb_private::Target &target, lldb::addr_t base_addr); + virtual lldb::ByteOrder GetByteOrder() const; |