| //===-- DynamicLoader.cpp ---------------------------------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #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; |
| |
| DynamicLoader* |
| DynamicLoader::FindPlugin (Process *process, const char *plugin_name) |
| { |
| DynamicLoaderCreateInstance create_callback = NULL; |
| if (plugin_name) |
| { |
| ConstString const_plugin_name(plugin_name); |
| create_callback = PluginManager::GetDynamicLoaderCreateCallbackForPluginName (const_plugin_name); |
| if (create_callback) |
| { |
| std::unique_ptr<DynamicLoader> instance_ap(create_callback(process, true)); |
| if (instance_ap.get()) |
| return instance_ap.release(); |
| } |
| } |
| else |
| { |
| for (uint32_t idx = 0; (create_callback = PluginManager::GetDynamicLoaderCreateCallbackAtIndex(idx)) != NULL; ++idx) |
| { |
| std::unique_ptr<DynamicLoader> instance_ap(create_callback(process, false)); |
| if (instance_ap.get()) |
| return instance_ap.release(); |
| } |
| } |
| return NULL; |
| } |
| |
| |
| //---------------------------------------------------------------------- |
| // DynamicLoader constructor |
| //---------------------------------------------------------------------- |
| DynamicLoader::DynamicLoader(Process *process) : |
| m_process (process) |
| { |
| } |
| |
| //---------------------------------------------------------------------- |
| // Destructor |
| //---------------------------------------------------------------------- |
| DynamicLoader::~DynamicLoader() |
| { |
| } |
| |
| //---------------------------------------------------------------------- |
| // Accessosors to the global setting as to whether to stop at image |
| // (shared library) loading/unloading. |
| //---------------------------------------------------------------------- |
| bool |
| DynamicLoader::GetStopWhenImagesChange () const |
| { |
| return m_process->GetStopOnSharedLibraryEvents(); |
| } |
| |
| void |
| 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; |
| const bool base_addr_is_offset = true; |
| module->SetLoadAddress(m_process->GetTarget(), base_addr, base_addr_is_offset, 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; |
| } |