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