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