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