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