1//===-- DynamicLoader.cpp -------------------------------------------------===// 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/Debugger.h" 12#include "lldb/Core/Module.h" 13#include "lldb/Core/ModuleList.h" 14#include "lldb/Core/ModuleSpec.h" 15#include "lldb/Core/PluginManager.h" 16#include "lldb/Core/Section.h" 17#include "lldb/Symbol/ObjectFile.h" 18#include "lldb/Target/MemoryRegionInfo.h" 19#include "lldb/Target/Platform.h" 20#include "lldb/Target/Process.h" 21#include "lldb/Target/Target.h" 22#include "lldb/Utility/ConstString.h" 23#include "lldb/Utility/LLDBLog.h" 24#include "lldb/Utility/Log.h" 25#include "lldb/lldb-private-interfaces.h" 26 27#include "llvm/ADT/StringRef.h" 28 29#include <memory> 30 31#include <cassert> 32 33using namespace lldb; 34using namespace lldb_private; 35 36DynamicLoader *DynamicLoader::FindPlugin(Process *process, 37 llvm::StringRef plugin_name) { 38 DynamicLoaderCreateInstance create_callback = nullptr; 39 if (!plugin_name.empty()) { 40 create_callback = 41 PluginManager::GetDynamicLoaderCreateCallbackForPluginName(plugin_name); 42 if (create_callback) { 43 std::unique_ptr<DynamicLoader> instance_up( 44 create_callback(process, true)); 45 if (instance_up) 46 return instance_up.release(); 47 } 48 } else { 49 for (uint32_t idx = 0; 50 (create_callback = 51 PluginManager::GetDynamicLoaderCreateCallbackAtIndex(idx)) != 52 nullptr; 53 ++idx) { 54 std::unique_ptr<DynamicLoader> instance_up( 55 create_callback(process, false)); 56 if (instance_up) 57 return instance_up.release(); 58 } 59 } 60 return nullptr; 61} 62 63DynamicLoader::DynamicLoader(Process *process) : m_process(process) {} 64 65// Accessors 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::FindModuleViaTarget(const FileSpec &file) { 153 Target &target = m_process->GetTarget(); 154 ModuleSpec module_spec(file, target.GetArchitecture()); 155 156 if (ModuleSP module_sp = target.GetImages().FindFirstModule(module_spec)) 157 return module_sp; 158 159 if (ModuleSP module_sp = target.GetOrCreateModule(module_spec, false)) 160 return module_sp; 161 162 return nullptr; 163} 164 165ModuleSP DynamicLoader::LoadModuleAtAddress(const FileSpec &file, 166 addr_t link_map_addr, 167 addr_t base_addr, 168 bool base_addr_is_offset) { 169 if (ModuleSP module_sp = FindModuleViaTarget(file)) { 170 UpdateLoadedSections(module_sp, link_map_addr, base_addr, 171 base_addr_is_offset); 172 return module_sp; 173 } 174 175 return nullptr; 176} 177 178static ModuleSP ReadUnnamedMemoryModule(Process *process, addr_t addr, 179 llvm::StringRef name) { 180 char namebuf[80]; 181 if (name.empty()) { 182 snprintf(namebuf, sizeof(namebuf), "memory-image-0x%" PRIx64, addr); 183 name = namebuf; 184 } 185 return process->ReadModuleFromMemory(FileSpec(name), addr); 186} 187 188ModuleSP DynamicLoader::LoadBinaryWithUUIDAndAddress( 189 Process *process, llvm::StringRef name, UUID uuid, addr_t value, 190 bool value_is_offset, bool force_symbol_search, bool notify, 191 bool set_address_in_target, bool allow_memory_image_last_resort) { 192 ModuleSP memory_module_sp; 193 ModuleSP module_sp; 194 PlatformSP platform_sp = process->GetTarget().GetPlatform(); 195 Target &target = process->GetTarget(); 196 Status error; 197 198 if (!uuid.IsValid() && !value_is_offset) { 199 memory_module_sp = ReadUnnamedMemoryModule(process, value, name); 200 201 if (memory_module_sp) 202 uuid = memory_module_sp->GetUUID(); 203 } 204 ModuleSpec module_spec; 205 module_spec.GetUUID() = uuid; 206 FileSpec name_filespec(name); 207 if (FileSystem::Instance().Exists(name_filespec)) 208 module_spec.GetFileSpec() = name_filespec; 209 210 if (uuid.IsValid()) { 211 // Has lldb already seen a module with this UUID? 212 if (!module_sp) 213 error = ModuleList::GetSharedModule(module_spec, module_sp, nullptr, 214 nullptr, nullptr); 215 216 // Can lldb's symbol/executable location schemes 217 // find an executable and symbol file. 218 if (!module_sp) { 219 FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths(); 220 module_spec.GetSymbolFileSpec() = 221 PluginManager::LocateExecutableSymbolFile(module_spec, search_paths); 222 ModuleSpec objfile_module_spec = 223 PluginManager::LocateExecutableObjectFile(module_spec); 224 module_spec.GetFileSpec() = objfile_module_spec.GetFileSpec(); 225 if (FileSystem::Instance().Exists(module_spec.GetFileSpec()) && 226 FileSystem::Instance().Exists(module_spec.GetSymbolFileSpec())) { 227 module_sp = std::make_shared<Module>(module_spec); 228 } 229 } 230 231 // If we haven't found a binary, or we don't have a SymbolFile, see 232 // if there is an external search tool that can find it. 233 if (!module_sp || !module_sp->GetSymbolFileFileSpec()) { 234 PluginManager::DownloadObjectAndSymbolFile(module_spec, error, 235 force_symbol_search); 236 if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) { 237 module_sp = std::make_shared<Module>(module_spec); 238 } else if (force_symbol_search && error.AsCString("") && 239 error.AsCString("")[0] != '\0') { 240 target.GetDebugger().GetErrorStream() << error.AsCString(); 241 } 242 } 243 244 // If we only found the executable, create a Module based on that. 245 if (!module_sp && FileSystem::Instance().Exists(module_spec.GetFileSpec())) 246 module_sp = std::make_shared<Module>(module_spec); 247 } 248 249 // If we couldn't find the binary anywhere else, as a last resort, 250 // read it out of memory. 251 if (allow_memory_image_last_resort && !module_sp.get() && 252 value != LLDB_INVALID_ADDRESS && !value_is_offset) { 253 if (!memory_module_sp) 254 memory_module_sp = ReadUnnamedMemoryModule(process, value, name); 255 if (memory_module_sp) 256 module_sp = memory_module_sp; 257 } 258 259 Log *log = GetLog(LLDBLog::DynamicLoader); 260 if (module_sp.get()) { 261 // Ensure the Target has an architecture set in case 262 // we need it while processing this binary/eh_frame/debug info. 263 if (!target.GetArchitecture().IsValid()) 264 target.SetArchitecture(module_sp->GetArchitecture()); 265 target.GetImages().AppendIfNeeded(module_sp, false); 266 267 bool changed = false; 268 if (set_address_in_target) { 269 if (module_sp->GetObjectFile()) { 270 if (value != LLDB_INVALID_ADDRESS) { 271 LLDB_LOGF(log, 272 "DynamicLoader::LoadBinaryWithUUIDAndAddress Loading " 273 "binary %s UUID %s at %s 0x%" PRIx64, 274 name.str().c_str(), uuid.GetAsString().c_str(), 275 value_is_offset ? "offset" : "address", value); 276 module_sp->SetLoadAddress(target, value, value_is_offset, changed); 277 } else { 278 // No address/offset/slide, load the binary at file address, 279 // offset 0. 280 LLDB_LOGF(log, 281 "DynamicLoader::LoadBinaryWithUUIDAndAddress Loading " 282 "binary %s UUID %s at file address", 283 name.str().c_str(), uuid.GetAsString().c_str()); 284 module_sp->SetLoadAddress(target, 0, true /* value_is_slide */, 285 changed); 286 } 287 } else { 288 // In-memory image, load at its true address, offset 0. 289 LLDB_LOGF(log, 290 "DynamicLoader::LoadBinaryWithUUIDAndAddress Loading binary " 291 "%s UUID %s from memory at address 0x%" PRIx64, 292 name.str().c_str(), uuid.GetAsString().c_str(), value); 293 module_sp->SetLoadAddress(target, 0, true /* value_is_slide */, 294 changed); 295 } 296 } 297 298 if (notify) { 299 ModuleList added_module; 300 added_module.Append(module_sp, false); 301 target.ModulesDidLoad(added_module); 302 } 303 } else { 304 if (force_symbol_search) { 305 Stream &s = target.GetDebugger().GetErrorStream(); 306 s.Printf("Unable to find file"); 307 if (!name.empty()) 308 s.Printf(" %s", name.str().c_str()); 309 if (uuid.IsValid()) 310 s.Printf(" with UUID %s", uuid.GetAsString().c_str()); 311 if (value != LLDB_INVALID_ADDRESS) { 312 if (value_is_offset) 313 s.Printf(" with slide 0x%" PRIx64, value); 314 else 315 s.Printf(" at address 0x%" PRIx64, value); 316 } 317 s.Printf("\n"); 318 } 319 LLDB_LOGF(log, 320 "Unable to find binary %s with UUID %s and load it at " 321 "%s 0x%" PRIx64, 322 name.str().c_str(), uuid.GetAsString().c_str(), 323 value_is_offset ? "offset" : "address", value); 324 } 325 326 return module_sp; 327} 328 329int64_t DynamicLoader::ReadUnsignedIntWithSizeInBytes(addr_t addr, 330 int size_in_bytes) { 331 Status error; 332 uint64_t value = 333 m_process->ReadUnsignedIntegerFromMemory(addr, size_in_bytes, 0, error); 334 if (error.Fail()) 335 return -1; 336 else 337 return (int64_t)value; 338} 339 340addr_t DynamicLoader::ReadPointer(addr_t addr) { 341 Status error; 342 addr_t value = m_process->ReadPointerFromMemory(addr, error); 343 if (error.Fail()) 344 return LLDB_INVALID_ADDRESS; 345 else 346 return value; 347} 348 349void DynamicLoader::LoadOperatingSystemPlugin(bool flush) 350{ 351 if (m_process) 352 m_process->LoadOperatingSystemPlugin(flush); 353} 354 355