diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-12-20 19:53:05 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-12-20 19:53:05 +0000 |
commit | 0b57cec536236d46e3dba9bd041533462f33dbb7 (patch) | |
tree | 56229dbdbbf76d18580f72f789003db17246c8d9 /contrib/llvm-project/lldb/source/Core/DynamicLoader.cpp | |
parent | 718ef55ec7785aae63f98f8ca05dc07ed399c16d (diff) |
Notes
Diffstat (limited to 'contrib/llvm-project/lldb/source/Core/DynamicLoader.cpp')
-rw-r--r-- | contrib/llvm-project/lldb/source/Core/DynamicLoader.cpp | 245 |
1 files changed, 245 insertions, 0 deletions
diff --git a/contrib/llvm-project/lldb/source/Core/DynamicLoader.cpp b/contrib/llvm-project/lldb/source/Core/DynamicLoader.cpp new file mode 100644 index 000000000000..57130d6fa57a --- /dev/null +++ b/contrib/llvm-project/lldb/source/Core/DynamicLoader.cpp @@ -0,0 +1,245 @@ +//===-- DynamicLoader.cpp ---------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Target/DynamicLoader.h" + +#include "lldb/Core/Module.h" +#include "lldb/Core/ModuleList.h" +#include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Section.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Target/MemoryRegionInfo.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/lldb-private-interfaces.h" + +#include "llvm/ADT/StringRef.h" + +#include <memory> + +#include <assert.h> + +using namespace lldb; +using namespace lldb_private; + +DynamicLoader *DynamicLoader::FindPlugin(Process *process, + const char *plugin_name) { + DynamicLoaderCreateInstance create_callback = nullptr; + if (plugin_name) { + ConstString const_plugin_name(plugin_name); + create_callback = + PluginManager::GetDynamicLoaderCreateCallbackForPluginName( + const_plugin_name); + if (create_callback) { + std::unique_ptr<DynamicLoader> instance_up( + create_callback(process, true)); + if (instance_up) + return instance_up.release(); + } + } else { + for (uint32_t idx = 0; + (create_callback = + PluginManager::GetDynamicLoaderCreateCallbackAtIndex(idx)) != + nullptr; + ++idx) { + std::unique_ptr<DynamicLoader> instance_up( + create_callback(process, false)); + if (instance_up) + return instance_up.release(); + } + } + return nullptr; +} + +DynamicLoader::DynamicLoader(Process *process) : m_process(process) {} + +DynamicLoader::~DynamicLoader() = default; + +// 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) { + if (FileSystem::Instance().Exists(executable->GetFileSpec())) { + ModuleSpec module_spec(executable->GetFileSpec(), + executable->GetArchitecture()); + auto module_sp = std::make_shared<Module>(module_spec); + + // Check if the executable has changed and set it to the target + // executable if they differ. + if (module_sp && module_sp->GetUUID().IsValid() && + executable->GetUUID().IsValid()) { + if (module_sp->GetUUID() != executable->GetUUID()) + executable.reset(); + } else if (executable->FileHasChanged()) { + executable.reset(); + } + + if (!executable) { + executable = target.GetOrCreateModule(module_spec, true /* notify */); + 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 + target.SetExecutableModule(executable, eLoadDependentsNo); + } + } + } + } + return executable; +} + +void DynamicLoader::UpdateLoadedSections(ModuleSP module, addr_t link_map_addr, + addr_t base_addr, + bool base_addr_is_offset) { + UpdateLoadedSectionsCommon(module, base_addr, base_addr_is_offset); +} + +void DynamicLoader::UpdateLoadedSectionsCommon(ModuleSP module, + addr_t base_addr, + bool base_addr_is_offset) { + bool changed; + 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) { + ObjectFile *obj_file = module->GetObjectFile(); + if (obj_file != nullptr) { + sections = obj_file->GetSectionList(); + } + } + return sections; +} + +ModuleSP DynamicLoader::LoadModuleAtAddress(const FileSpec &file, + addr_t link_map_addr, + addr_t base_addr, + bool base_addr_is_offset) { + Target &target = m_process->GetTarget(); + ModuleList &modules = target.GetImages(); + ModuleSpec module_spec(file, target.GetArchitecture()); + ModuleSP module_sp; + + if ((module_sp = modules.FindFirstModule(module_spec))) { + UpdateLoadedSections(module_sp, link_map_addr, base_addr, + base_addr_is_offset); + return module_sp; + } + + if ((module_sp = target.GetOrCreateModule(module_spec, + true /* notify */))) { + UpdateLoadedSections(module_sp, link_map_addr, base_addr, + base_addr_is_offset); + return module_sp; + } + + bool check_alternative_file_name = true; + if (base_addr_is_offset) { + // Try to fetch the load address of the file from the process as we need + // absolute load address to read the file out of the memory instead of a + // load bias. + bool is_loaded = false; + lldb::addr_t load_addr; + Status error = m_process->GetFileLoadAddress(file, is_loaded, load_addr); + if (error.Success() && is_loaded) { + check_alternative_file_name = false; + base_addr = load_addr; + } + } + + // We failed to find the module based on its name. Lets try to check if we + // can find a different name based on the memory region info. + if (check_alternative_file_name) { + MemoryRegionInfo memory_info; + Status error = m_process->GetMemoryRegionInfo(base_addr, memory_info); + if (error.Success() && memory_info.GetMapped() && + memory_info.GetRange().GetRangeBase() == base_addr && + !(memory_info.GetName().IsEmpty())) { + ModuleSpec new_module_spec(FileSpec(memory_info.GetName().AsCString()), + target.GetArchitecture()); + + if ((module_sp = modules.FindFirstModule(new_module_spec))) { + UpdateLoadedSections(module_sp, link_map_addr, base_addr, false); + return module_sp; + } + + if ((module_sp = target.GetOrCreateModule(new_module_spec, + true /* notify */))) { + UpdateLoadedSections(module_sp, link_map_addr, base_addr, false); + return module_sp; + } + } + } + + if ((module_sp = m_process->ReadModuleFromMemory(file, base_addr))) { + UpdateLoadedSections(module_sp, link_map_addr, base_addr, false); + target.GetImages().AppendIfNeeded(module_sp); + } + + return module_sp; +} + +int64_t DynamicLoader::ReadUnsignedIntWithSizeInBytes(addr_t addr, + int size_in_bytes) { + Status 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) { + Status error; + addr_t value = m_process->ReadPointerFromMemory(addr, error); + if (error.Fail()) + return LLDB_INVALID_ADDRESS; + else + return value; +} + +void DynamicLoader::LoadOperatingSystemPlugin(bool flush) +{ + if (m_process) + m_process->LoadOperatingSystemPlugin(flush); +} + |