130fdc8d8SChris Lattner //===-- DynamicLoader.cpp ---------------------------------------*- C++ -*-===//
230fdc8d8SChris Lattner //
330fdc8d8SChris Lattner //                     The LLVM Compiler Infrastructure
430fdc8d8SChris Lattner //
530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source
630fdc8d8SChris Lattner // License. See LICENSE.TXT for details.
730fdc8d8SChris Lattner //
830fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
930fdc8d8SChris Lattner 
10b9c1b51eSKate Stone #include "lldb/Target/DynamicLoader.h"
112f3df613SZachary Turner 
129e02dacdSSteve Pucci #include "lldb/Core/Module.h"
132f3df613SZachary Turner #include "lldb/Core/ModuleList.h" // for ModuleList
149e02dacdSSteve Pucci #include "lldb/Core/ModuleSpec.h"
15d7d69f80STamas Berghammer #include "lldb/Core/PluginManager.h"
169e02dacdSSteve Pucci #include "lldb/Core/Section.h"
172f3df613SZachary Turner #include "lldb/Symbol/ObjectFile.h" // for ObjectFile
18d7d69f80STamas Berghammer #include "lldb/Target/MemoryRegionInfo.h"
19d7d69f80STamas Berghammer #include "lldb/Target/Process.h"
20d7d69f80STamas Berghammer #include "lldb/Target/Target.h"
212f3df613SZachary Turner #include "lldb/Utility/ConstString.h"     // for ConstString
222f3df613SZachary Turner #include "lldb/lldb-private-interfaces.h" // for DynamicLoaderCreateInstance
232f3df613SZachary Turner 
242f3df613SZachary Turner #include "llvm/ADT/StringRef.h" // for StringRef
252f3df613SZachary Turner 
262f3df613SZachary Turner #include <memory> // for shared_ptr, unique_ptr
272f3df613SZachary Turner 
282f3df613SZachary Turner #include <assert.h> // for assert
2930fdc8d8SChris Lattner 
3030fdc8d8SChris Lattner using namespace lldb;
3130fdc8d8SChris Lattner using namespace lldb_private;
3230fdc8d8SChris Lattner 
33b9c1b51eSKate Stone DynamicLoader *DynamicLoader::FindPlugin(Process *process,
34b9c1b51eSKate Stone                                          const char *plugin_name) {
3534ede34aSEugene Zelenko   DynamicLoaderCreateInstance create_callback = nullptr;
36b9c1b51eSKate Stone   if (plugin_name) {
3757abc5d6SGreg Clayton     ConstString const_plugin_name(plugin_name);
38b9c1b51eSKate Stone     create_callback =
39b9c1b51eSKate Stone         PluginManager::GetDynamicLoaderCreateCallbackForPluginName(
40b9c1b51eSKate Stone             const_plugin_name);
41b9c1b51eSKate Stone     if (create_callback) {
42b9c1b51eSKate Stone       std::unique_ptr<DynamicLoader> instance_ap(
43b9c1b51eSKate Stone           create_callback(process, true));
4434ede34aSEugene Zelenko       if (instance_ap)
4530fdc8d8SChris Lattner         return instance_ap.release();
4630fdc8d8SChris Lattner     }
47b9c1b51eSKate Stone   } else {
48b9c1b51eSKate Stone     for (uint32_t idx = 0;
49b9c1b51eSKate Stone          (create_callback =
50b9c1b51eSKate Stone               PluginManager::GetDynamicLoaderCreateCallbackAtIndex(idx)) !=
51b9c1b51eSKate Stone          nullptr;
52b9c1b51eSKate Stone          ++idx) {
53b9c1b51eSKate Stone       std::unique_ptr<DynamicLoader> instance_ap(
54b9c1b51eSKate Stone           create_callback(process, false));
5534ede34aSEugene Zelenko       if (instance_ap)
5630fdc8d8SChris Lattner         return instance_ap.release();
5730fdc8d8SChris Lattner     }
5830fdc8d8SChris Lattner   }
5934ede34aSEugene Zelenko   return nullptr;
6030fdc8d8SChris Lattner }
6130fdc8d8SChris Lattner 
62b9c1b51eSKate Stone DynamicLoader::DynamicLoader(Process *process) : m_process(process) {}
6330fdc8d8SChris Lattner 
6434ede34aSEugene Zelenko DynamicLoader::~DynamicLoader() = default;
6530fdc8d8SChris Lattner 
6630fdc8d8SChris Lattner //----------------------------------------------------------------------
6705097246SAdrian Prantl // Accessosors to the global setting as to whether to stop at image (shared
6805097246SAdrian Prantl // library) loading/unloading.
6930fdc8d8SChris Lattner //----------------------------------------------------------------------
7034ede34aSEugene Zelenko 
71b9c1b51eSKate Stone bool DynamicLoader::GetStopWhenImagesChange() const {
722995077dSJim Ingham   return m_process->GetStopOnSharedLibraryEvents();
7330fdc8d8SChris Lattner }
7430fdc8d8SChris Lattner 
75b9c1b51eSKate Stone void DynamicLoader::SetStopWhenImagesChange(bool stop) {
762995077dSJim Ingham   m_process->SetStopOnSharedLibraryEvents(stop);
7730fdc8d8SChris Lattner }
7830fdc8d8SChris Lattner 
79b9c1b51eSKate Stone ModuleSP DynamicLoader::GetTargetExecutable() {
809e02dacdSSteve Pucci   Target &target = m_process->GetTarget();
819e02dacdSSteve Pucci   ModuleSP executable = target.GetExecutableModule();
829e02dacdSSteve Pucci 
83b9c1b51eSKate Stone   if (executable) {
84*dbd7fabaSJonas Devlieghere     if (FileSystem::Instance().Exists(executable->GetFileSpec())) {
85b9c1b51eSKate Stone       ModuleSpec module_spec(executable->GetFileSpec(),
86b9c1b51eSKate Stone                              executable->GetArchitecture());
872f3df613SZachary Turner       auto module_sp = std::make_shared<Module>(module_spec);
889e02dacdSSteve Pucci 
8905097246SAdrian Prantl       // Check if the executable has changed and set it to the target
9005097246SAdrian Prantl       // executable if they differ.
91b9c1b51eSKate Stone       if (module_sp && module_sp->GetUUID().IsValid() &&
92b9c1b51eSKate Stone           executable->GetUUID().IsValid()) {
939e02dacdSSteve Pucci         if (module_sp->GetUUID() != executable->GetUUID())
949e02dacdSSteve Pucci           executable.reset();
95b9c1b51eSKate Stone       } else if (executable->FileHasChanged()) {
969e02dacdSSteve Pucci         executable.reset();
979e02dacdSSteve Pucci       }
989e02dacdSSteve Pucci 
99b9c1b51eSKate Stone       if (!executable) {
1009e02dacdSSteve Pucci         executable = target.GetSharedModule(module_spec);
101b9c1b51eSKate Stone         if (executable.get() != target.GetExecutableModulePointer()) {
10205097246SAdrian Prantl           // Don't load dependent images since we are in dyld where we will
10305097246SAdrian Prantl           // know and find out about all images that are loaded
104f9a07e9fSJonas Devlieghere           target.SetExecutableModule(executable, eLoadDependentsNo);
1059e02dacdSSteve Pucci         }
1069e02dacdSSteve Pucci       }
1079e02dacdSSteve Pucci     }
1089e02dacdSSteve Pucci   }
1099e02dacdSSteve Pucci   return executable;
1109e02dacdSSteve Pucci }
1119e02dacdSSteve Pucci 
112b9c1b51eSKate Stone void DynamicLoader::UpdateLoadedSections(ModuleSP module, addr_t link_map_addr,
11342ecef3bSTamas Berghammer                                          addr_t base_addr,
114b9c1b51eSKate Stone                                          bool base_addr_is_offset) {
11542ecef3bSTamas Berghammer   UpdateLoadedSectionsCommon(module, base_addr, base_addr_is_offset);
1169e02dacdSSteve Pucci }
1179e02dacdSSteve Pucci 
118b9c1b51eSKate Stone void DynamicLoader::UpdateLoadedSectionsCommon(ModuleSP module,
11942ecef3bSTamas Berghammer                                                addr_t base_addr,
120b9c1b51eSKate Stone                                                bool base_addr_is_offset) {
1219e02dacdSSteve Pucci   bool changed;
122b9c1b51eSKate Stone   module->SetLoadAddress(m_process->GetTarget(), base_addr, base_addr_is_offset,
123b9c1b51eSKate Stone                          changed);
1249e02dacdSSteve Pucci }
1259e02dacdSSteve Pucci 
126b9c1b51eSKate Stone void DynamicLoader::UnloadSections(const ModuleSP module) {
1279e02dacdSSteve Pucci   UnloadSectionsCommon(module);
1289e02dacdSSteve Pucci }
1299e02dacdSSteve Pucci 
130b9c1b51eSKate Stone void DynamicLoader::UnloadSectionsCommon(const ModuleSP module) {
1319e02dacdSSteve Pucci   Target &target = m_process->GetTarget();
1329e02dacdSSteve Pucci   const SectionList *sections = GetSectionListFromModule(module);
1339e02dacdSSteve Pucci 
1349e02dacdSSteve Pucci   assert(sections && "SectionList missing from unloaded module.");
1359e02dacdSSteve Pucci 
1369e02dacdSSteve Pucci   const size_t num_sections = sections->GetSize();
137b9c1b51eSKate Stone   for (size_t i = 0; i < num_sections; ++i) {
1389e02dacdSSteve Pucci     SectionSP section_sp(sections->GetSectionAtIndex(i));
1399e02dacdSSteve Pucci     target.SetSectionUnloaded(section_sp);
1409e02dacdSSteve Pucci   }
1419e02dacdSSteve Pucci }
1429e02dacdSSteve Pucci 
1439e02dacdSSteve Pucci const SectionList *
144b9c1b51eSKate Stone DynamicLoader::GetSectionListFromModule(const ModuleSP module) const {
1459e02dacdSSteve Pucci   SectionList *sections = nullptr;
146b9c1b51eSKate Stone   if (module) {
1479e02dacdSSteve Pucci     ObjectFile *obj_file = module->GetObjectFile();
148b9c1b51eSKate Stone     if (obj_file != nullptr) {
1499e02dacdSSteve Pucci       sections = obj_file->GetSectionList();
1509e02dacdSSteve Pucci     }
1519e02dacdSSteve Pucci   }
1529e02dacdSSteve Pucci   return sections;
1539e02dacdSSteve Pucci }
1549e02dacdSSteve Pucci 
155b9c1b51eSKate Stone ModuleSP DynamicLoader::LoadModuleAtAddress(const FileSpec &file,
15642ecef3bSTamas Berghammer                                             addr_t link_map_addr,
15742ecef3bSTamas Berghammer                                             addr_t base_addr,
158b9c1b51eSKate Stone                                             bool base_addr_is_offset) {
1599e02dacdSSteve Pucci   Target &target = m_process->GetTarget();
1609e02dacdSSteve Pucci   ModuleList &modules = target.GetImages();
161d7d69f80STamas Berghammer   ModuleSpec module_spec(file, target.GetArchitecture());
1629e02dacdSSteve Pucci   ModuleSP module_sp;
1639e02dacdSSteve Pucci 
164b9c1b51eSKate Stone   if ((module_sp = modules.FindFirstModule(module_spec))) {
165b9c1b51eSKate Stone     UpdateLoadedSections(module_sp, link_map_addr, base_addr,
166b9c1b51eSKate Stone                          base_addr_is_offset);
167d7d69f80STamas Berghammer     return module_sp;
1689e02dacdSSteve Pucci   }
169d7d69f80STamas Berghammer 
170b9c1b51eSKate Stone   if ((module_sp = target.GetSharedModule(module_spec))) {
171b9c1b51eSKate Stone     UpdateLoadedSections(module_sp, link_map_addr, base_addr,
172b9c1b51eSKate Stone                          base_addr_is_offset);
173d7d69f80STamas Berghammer     return module_sp;
1749e02dacdSSteve Pucci   }
175d7d69f80STamas Berghammer 
176d7d69f80STamas Berghammer   bool check_alternative_file_name = true;
177b9c1b51eSKate Stone   if (base_addr_is_offset) {
178b9c1b51eSKate Stone     // Try to fetch the load address of the file from the process as we need
17905097246SAdrian Prantl     // absolute load address to read the file out of the memory instead of a
18005097246SAdrian Prantl     // load bias.
1815d410241SJason Molenda     bool is_loaded = false;
182f2561846STamas Berghammer     lldb::addr_t load_addr;
18397206d57SZachary Turner     Status error = m_process->GetFileLoadAddress(file, is_loaded, load_addr);
184b9c1b51eSKate Stone     if (error.Success() && is_loaded) {
185d7d69f80STamas Berghammer       check_alternative_file_name = false;
18642ecef3bSTamas Berghammer       base_addr = load_addr;
18742ecef3bSTamas Berghammer     }
188d7d69f80STamas Berghammer   }
189d7d69f80STamas Berghammer 
19005097246SAdrian Prantl   // We failed to find the module based on its name. Lets try to check if we
19105097246SAdrian Prantl   // can find a different name based on the memory region info.
192b9c1b51eSKate Stone   if (check_alternative_file_name) {
193d7d69f80STamas Berghammer     MemoryRegionInfo memory_info;
19497206d57SZachary Turner     Status error = m_process->GetMemoryRegionInfo(base_addr, memory_info);
195b9c1b51eSKate Stone     if (error.Success() && memory_info.GetMapped() &&
1965ba3d85cSNitesh Jain         memory_info.GetRange().GetRangeBase() == base_addr &&
1975ba3d85cSNitesh Jain         !(memory_info.GetName().IsEmpty())) {
198b9c1b51eSKate Stone       ModuleSpec new_module_spec(
199b9c1b51eSKate Stone           FileSpec(memory_info.GetName().AsCString(), false),
200d7d69f80STamas Berghammer           target.GetArchitecture());
201d7d69f80STamas Berghammer 
202b9c1b51eSKate Stone       if ((module_sp = modules.FindFirstModule(new_module_spec))) {
203d7d69f80STamas Berghammer         UpdateLoadedSections(module_sp, link_map_addr, base_addr, false);
204d7d69f80STamas Berghammer         return module_sp;
205d7d69f80STamas Berghammer       }
206d7d69f80STamas Berghammer 
207b9c1b51eSKate Stone       if ((module_sp = target.GetSharedModule(new_module_spec))) {
208d7d69f80STamas Berghammer         UpdateLoadedSections(module_sp, link_map_addr, base_addr, false);
209d7d69f80STamas Berghammer         return module_sp;
210d7d69f80STamas Berghammer       }
211d7d69f80STamas Berghammer     }
212d7d69f80STamas Berghammer   }
213f2561846STamas Berghammer 
214b9c1b51eSKate Stone   if ((module_sp = m_process->ReadModuleFromMemory(file, base_addr))) {
21542ecef3bSTamas Berghammer     UpdateLoadedSections(module_sp, link_map_addr, base_addr, false);
216f2561846STamas Berghammer     target.GetImages().AppendIfNeeded(module_sp);
217f2561846STamas Berghammer   }
2189e02dacdSSteve Pucci 
2199e02dacdSSteve Pucci   return module_sp;
2209e02dacdSSteve Pucci }
2219e02dacdSSteve Pucci 
222b9c1b51eSKate Stone int64_t DynamicLoader::ReadUnsignedIntWithSizeInBytes(addr_t addr,
223b9c1b51eSKate Stone                                                       int size_in_bytes) {
22497206d57SZachary Turner   Status error;
225b9c1b51eSKate Stone   uint64_t value =
226b9c1b51eSKate Stone       m_process->ReadUnsignedIntegerFromMemory(addr, size_in_bytes, 0, error);
2279e02dacdSSteve Pucci   if (error.Fail())
2289e02dacdSSteve Pucci     return -1;
2299e02dacdSSteve Pucci   else
2309e02dacdSSteve Pucci     return (int64_t)value;
2319e02dacdSSteve Pucci }
2329e02dacdSSteve Pucci 
233b9c1b51eSKate Stone addr_t DynamicLoader::ReadPointer(addr_t addr) {
23497206d57SZachary Turner   Status error;
2359e02dacdSSteve Pucci   addr_t value = m_process->ReadPointerFromMemory(addr, error);
2369e02dacdSSteve Pucci   if (error.Fail())
2379e02dacdSSteve Pucci     return LLDB_INVALID_ADDRESS;
2389e02dacdSSteve Pucci   else
2399e02dacdSSteve Pucci     return value;
2409e02dacdSSteve Pucci }
241519b0816SJim Ingham 
242519b0816SJim Ingham void DynamicLoader::LoadOperatingSystemPlugin(bool flush)
243519b0816SJim Ingham {
244519b0816SJim Ingham     if (m_process)
245519b0816SJim Ingham         m_process->LoadOperatingSystemPlugin(flush);
246519b0816SJim Ingham }
247519b0816SJim Ingham 
248