1//===-- DynamicLoader.cpp ---------------------------------------*- C++ -*-===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8 9#include "lldb/Target/DynamicLoader.h" 10 11#include "lldb/Core/Module.h" 12#include "lldb/Core/ModuleList.h" 13#include "lldb/Core/ModuleSpec.h" 14#include "lldb/Core/PluginManager.h" 15#include "lldb/Core/Section.h" 16#include "lldb/Symbol/ObjectFile.h" 17#include "lldb/Target/MemoryRegionInfo.h" 18#include "lldb/Target/Process.h" 19#include "lldb/Target/Target.h" 20#include "lldb/Utility/ConstString.h" 21#include "lldb/lldb-private-interfaces.h" 22 23#include "llvm/ADT/StringRef.h" 24 25#include <memory> 26 27#include <assert.h> 28 29using namespace lldb; 30using namespace lldb_private; 31 32DynamicLoader *DynamicLoader::FindPlugin(Process *process, 33 const char *plugin_name) { 34 DynamicLoaderCreateInstance create_callback = nullptr; 35 if (plugin_name) { 36 ConstString const_plugin_name(plugin_name); 37 create_callback = 38 PluginManager::GetDynamicLoaderCreateCallbackForPluginName( 39 const_plugin_name); 40 if (create_callback) { 41 std::unique_ptr<DynamicLoader> instance_up( 42 create_callback(process, true)); 43 if (instance_up) 44 return instance_up.release(); 45 } 46 } else { 47 for (uint32_t idx = 0; 48 (create_callback = 49 PluginManager::GetDynamicLoaderCreateCallbackAtIndex(idx)) != 50 nullptr; 51 ++idx) { 52 std::unique_ptr<DynamicLoader> instance_up( 53 create_callback(process, false)); 54 if (instance_up) 55 return instance_up.release(); 56 } 57 } 58 return nullptr; 59} 60 61DynamicLoader::DynamicLoader(Process *process) : m_process(process) {} 62 63DynamicLoader::~DynamicLoader() = default; 64 65// Accessosors to the global setting as to whether to stop at image (shared 66// library) loading/unloading. 67 68bool DynamicLoader::GetStopWhenImagesChange() const { 69 return m_process->GetStopOnSharedLibraryEvents(); 70} 71 72void DynamicLoader::SetStopWhenImagesChange(bool stop) { 73 m_process->SetStopOnSharedLibraryEvents(stop); 74} 75 76ModuleSP DynamicLoader::GetTargetExecutable() { 77 Target &target = m_process->GetTarget(); 78 ModuleSP executable = target.GetExecutableModule(); 79 80 if (executable) { 81 if (FileSystem::Instance().Exists(executable->GetFileSpec())) { 82 ModuleSpec module_spec(executable->GetFileSpec(), 83 executable->GetArchitecture()); 84 auto module_sp = std::make_shared<Module>(module_spec); 85 86 // Check if the executable has changed and set it to the target 87 // executable if they differ. 88 if (module_sp && module_sp->GetUUID().IsValid() && 89 executable->GetUUID().IsValid()) { 90 if (module_sp->GetUUID() != executable->GetUUID()) 91 executable.reset(); 92 } else if (executable->FileHasChanged()) { 93 executable.reset(); 94 } 95 96 if (!executable) { 97 executable = target.GetOrCreateModule(module_spec, true /* notify */); 98 if (executable.get() != target.GetExecutableModulePointer()) { 99 // Don't load dependent images since we are in dyld where we will 100 // know and find out about all images that are loaded 101 target.SetExecutableModule(executable, eLoadDependentsNo); 102 } 103 } 104 } 105 } 106 return executable; 107} 108 109void DynamicLoader::UpdateLoadedSections(ModuleSP module, addr_t link_map_addr, 110 addr_t base_addr, 111 bool base_addr_is_offset) { 112 UpdateLoadedSectionsCommon(module, base_addr, base_addr_is_offset); 113} 114 115void DynamicLoader::UpdateLoadedSectionsCommon(ModuleSP module, 116 addr_t base_addr, 117 bool base_addr_is_offset) { 118 bool changed; 119 module->SetLoadAddress(m_process->GetTarget(), base_addr, base_addr_is_offset, 120 changed); 121} 122 123void DynamicLoader::UnloadSections(const ModuleSP module) { 124 UnloadSectionsCommon(module); 125} 126 127void DynamicLoader::UnloadSectionsCommon(const ModuleSP module) { 128 Target &target = m_process->GetTarget(); 129 const SectionList *sections = GetSectionListFromModule(module); 130 131 assert(sections && "SectionList missing from unloaded module."); 132 133 const size_t num_sections = sections->GetSize(); 134 for (size_t i = 0; i < num_sections; ++i) { 135 SectionSP section_sp(sections->GetSectionAtIndex(i)); 136 target.SetSectionUnloaded(section_sp); 137 } 138} 139 140const SectionList * 141DynamicLoader::GetSectionListFromModule(const ModuleSP module) const { 142 SectionList *sections = nullptr; 143 if (module) { 144 ObjectFile *obj_file = module->GetObjectFile(); 145 if (obj_file != nullptr) { 146 sections = obj_file->GetSectionList(); 147 } 148 } 149 return sections; 150} 151 152ModuleSP DynamicLoader::LoadModuleAtAddress(const FileSpec &file, 153 addr_t link_map_addr, 154 addr_t base_addr, 155 bool base_addr_is_offset) { 156 Target &target = m_process->GetTarget(); 157 ModuleList &modules = target.GetImages(); 158 ModuleSpec module_spec(file, target.GetArchitecture()); 159 ModuleSP module_sp; 160 161 if ((module_sp = modules.FindFirstModule(module_spec))) { 162 UpdateLoadedSections(module_sp, link_map_addr, base_addr, 163 base_addr_is_offset); 164 return module_sp; 165 } 166 167 if ((module_sp = target.GetOrCreateModule(module_spec, 168 true /* notify */))) { 169 UpdateLoadedSections(module_sp, link_map_addr, base_addr, 170 base_addr_is_offset); 171 return module_sp; 172 } 173 174 bool check_alternative_file_name = true; 175 if (base_addr_is_offset) { 176 // Try to fetch the load address of the file from the process as we need 177 // absolute load address to read the file out of the memory instead of a 178 // load bias. 179 bool is_loaded = false; 180 lldb::addr_t load_addr; 181 Status error = m_process->GetFileLoadAddress(file, is_loaded, load_addr); 182 if (error.Success() && is_loaded) { 183 check_alternative_file_name = false; 184 base_addr = load_addr; 185 } 186 } 187 188 // We failed to find the module based on its name. Lets try to check if we 189 // can find a different name based on the memory region info. 190 if (check_alternative_file_name) { 191 MemoryRegionInfo memory_info; 192 Status error = m_process->GetMemoryRegionInfo(base_addr, memory_info); 193 if (error.Success() && memory_info.GetMapped() && 194 memory_info.GetRange().GetRangeBase() == base_addr && 195 !(memory_info.GetName().IsEmpty())) { 196 ModuleSpec new_module_spec(FileSpec(memory_info.GetName().AsCString()), 197 target.GetArchitecture()); 198 199 if ((module_sp = modules.FindFirstModule(new_module_spec))) { 200 UpdateLoadedSections(module_sp, link_map_addr, base_addr, false); 201 return module_sp; 202 } 203 204 if ((module_sp = target.GetOrCreateModule(new_module_spec, 205 true /* notify */))) { 206 UpdateLoadedSections(module_sp, link_map_addr, base_addr, false); 207 return module_sp; 208 } 209 } 210 } 211 212 if ((module_sp = m_process->ReadModuleFromMemory(file, base_addr))) { 213 UpdateLoadedSections(module_sp, link_map_addr, base_addr, false); 214 target.GetImages().AppendIfNeeded(module_sp); 215 } 216 217 return module_sp; 218} 219 220int64_t DynamicLoader::ReadUnsignedIntWithSizeInBytes(addr_t addr, 221 int size_in_bytes) { 222 Status error; 223 uint64_t value = 224 m_process->ReadUnsignedIntegerFromMemory(addr, size_in_bytes, 0, error); 225 if (error.Fail()) 226 return -1; 227 else 228 return (int64_t)value; 229} 230 231addr_t DynamicLoader::ReadPointer(addr_t addr) { 232 Status error; 233 addr_t value = m_process->ReadPointerFromMemory(addr, error); 234 if (error.Fail()) 235 return LLDB_INVALID_ADDRESS; 236 else 237 return value; 238} 239 240void DynamicLoader::LoadOperatingSystemPlugin(bool flush) 241{ 242 if (m_process) 243 m_process->LoadOperatingSystemPlugin(flush); 244} 245 246