//===-- 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 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 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; }