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