15ffd83dbSDimitry Andric //===-- DynamicLoader.cpp -------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "lldb/Target/DynamicLoader.h"
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #include "lldb/Core/Module.h"
120b57cec5SDimitry Andric #include "lldb/Core/ModuleList.h"
130b57cec5SDimitry Andric #include "lldb/Core/ModuleSpec.h"
140b57cec5SDimitry Andric #include "lldb/Core/PluginManager.h"
150b57cec5SDimitry Andric #include "lldb/Core/Section.h"
160b57cec5SDimitry Andric #include "lldb/Symbol/ObjectFile.h"
170b57cec5SDimitry Andric #include "lldb/Target/MemoryRegionInfo.h"
180b57cec5SDimitry Andric #include "lldb/Target/Process.h"
190b57cec5SDimitry Andric #include "lldb/Target/Target.h"
200b57cec5SDimitry Andric #include "lldb/Utility/ConstString.h"
210b57cec5SDimitry Andric #include "lldb/lldb-private-interfaces.h"
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric #include <memory>
260b57cec5SDimitry Andric 
27*5f7ddb14SDimitry Andric #include <cassert>
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric using namespace lldb;
300b57cec5SDimitry Andric using namespace lldb_private;
310b57cec5SDimitry Andric 
FindPlugin(Process * process,const char * plugin_name)320b57cec5SDimitry Andric DynamicLoader *DynamicLoader::FindPlugin(Process *process,
330b57cec5SDimitry Andric                                          const char *plugin_name) {
340b57cec5SDimitry Andric   DynamicLoaderCreateInstance create_callback = nullptr;
350b57cec5SDimitry Andric   if (plugin_name) {
360b57cec5SDimitry Andric     ConstString const_plugin_name(plugin_name);
370b57cec5SDimitry Andric     create_callback =
380b57cec5SDimitry Andric         PluginManager::GetDynamicLoaderCreateCallbackForPluginName(
390b57cec5SDimitry Andric             const_plugin_name);
400b57cec5SDimitry Andric     if (create_callback) {
410b57cec5SDimitry Andric       std::unique_ptr<DynamicLoader> instance_up(
420b57cec5SDimitry Andric           create_callback(process, true));
430b57cec5SDimitry Andric       if (instance_up)
440b57cec5SDimitry Andric         return instance_up.release();
450b57cec5SDimitry Andric     }
460b57cec5SDimitry Andric   } else {
470b57cec5SDimitry Andric     for (uint32_t idx = 0;
480b57cec5SDimitry Andric          (create_callback =
490b57cec5SDimitry Andric               PluginManager::GetDynamicLoaderCreateCallbackAtIndex(idx)) !=
500b57cec5SDimitry Andric          nullptr;
510b57cec5SDimitry Andric          ++idx) {
520b57cec5SDimitry Andric       std::unique_ptr<DynamicLoader> instance_up(
530b57cec5SDimitry Andric           create_callback(process, false));
540b57cec5SDimitry Andric       if (instance_up)
550b57cec5SDimitry Andric         return instance_up.release();
560b57cec5SDimitry Andric     }
570b57cec5SDimitry Andric   }
580b57cec5SDimitry Andric   return nullptr;
590b57cec5SDimitry Andric }
600b57cec5SDimitry Andric 
DynamicLoader(Process * process)610b57cec5SDimitry Andric DynamicLoader::DynamicLoader(Process *process) : m_process(process) {}
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric // Accessosors to the global setting as to whether to stop at image (shared
640b57cec5SDimitry Andric // library) loading/unloading.
650b57cec5SDimitry Andric 
GetStopWhenImagesChange() const660b57cec5SDimitry Andric bool DynamicLoader::GetStopWhenImagesChange() const {
670b57cec5SDimitry Andric   return m_process->GetStopOnSharedLibraryEvents();
680b57cec5SDimitry Andric }
690b57cec5SDimitry Andric 
SetStopWhenImagesChange(bool stop)700b57cec5SDimitry Andric void DynamicLoader::SetStopWhenImagesChange(bool stop) {
710b57cec5SDimitry Andric   m_process->SetStopOnSharedLibraryEvents(stop);
720b57cec5SDimitry Andric }
730b57cec5SDimitry Andric 
GetTargetExecutable()740b57cec5SDimitry Andric ModuleSP DynamicLoader::GetTargetExecutable() {
750b57cec5SDimitry Andric   Target &target = m_process->GetTarget();
760b57cec5SDimitry Andric   ModuleSP executable = target.GetExecutableModule();
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric   if (executable) {
790b57cec5SDimitry Andric     if (FileSystem::Instance().Exists(executable->GetFileSpec())) {
800b57cec5SDimitry Andric       ModuleSpec module_spec(executable->GetFileSpec(),
810b57cec5SDimitry Andric                              executable->GetArchitecture());
820b57cec5SDimitry Andric       auto module_sp = std::make_shared<Module>(module_spec);
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric       // Check if the executable has changed and set it to the target
850b57cec5SDimitry Andric       // executable if they differ.
860b57cec5SDimitry Andric       if (module_sp && module_sp->GetUUID().IsValid() &&
870b57cec5SDimitry Andric           executable->GetUUID().IsValid()) {
880b57cec5SDimitry Andric         if (module_sp->GetUUID() != executable->GetUUID())
890b57cec5SDimitry Andric           executable.reset();
900b57cec5SDimitry Andric       } else if (executable->FileHasChanged()) {
910b57cec5SDimitry Andric         executable.reset();
920b57cec5SDimitry Andric       }
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric       if (!executable) {
950b57cec5SDimitry Andric         executable = target.GetOrCreateModule(module_spec, true /* notify */);
960b57cec5SDimitry Andric         if (executable.get() != target.GetExecutableModulePointer()) {
970b57cec5SDimitry Andric           // Don't load dependent images since we are in dyld where we will
980b57cec5SDimitry Andric           // know and find out about all images that are loaded
990b57cec5SDimitry Andric           target.SetExecutableModule(executable, eLoadDependentsNo);
1000b57cec5SDimitry Andric         }
1010b57cec5SDimitry Andric       }
1020b57cec5SDimitry Andric     }
1030b57cec5SDimitry Andric   }
1040b57cec5SDimitry Andric   return executable;
1050b57cec5SDimitry Andric }
1060b57cec5SDimitry Andric 
UpdateLoadedSections(ModuleSP module,addr_t link_map_addr,addr_t base_addr,bool base_addr_is_offset)1070b57cec5SDimitry Andric void DynamicLoader::UpdateLoadedSections(ModuleSP module, addr_t link_map_addr,
1080b57cec5SDimitry Andric                                          addr_t base_addr,
1090b57cec5SDimitry Andric                                          bool base_addr_is_offset) {
1100b57cec5SDimitry Andric   UpdateLoadedSectionsCommon(module, base_addr, base_addr_is_offset);
1110b57cec5SDimitry Andric }
1120b57cec5SDimitry Andric 
UpdateLoadedSectionsCommon(ModuleSP module,addr_t base_addr,bool base_addr_is_offset)1130b57cec5SDimitry Andric void DynamicLoader::UpdateLoadedSectionsCommon(ModuleSP module,
1140b57cec5SDimitry Andric                                                addr_t base_addr,
1150b57cec5SDimitry Andric                                                bool base_addr_is_offset) {
1160b57cec5SDimitry Andric   bool changed;
1170b57cec5SDimitry Andric   module->SetLoadAddress(m_process->GetTarget(), base_addr, base_addr_is_offset,
1180b57cec5SDimitry Andric                          changed);
1190b57cec5SDimitry Andric }
1200b57cec5SDimitry Andric 
UnloadSections(const ModuleSP module)1210b57cec5SDimitry Andric void DynamicLoader::UnloadSections(const ModuleSP module) {
1220b57cec5SDimitry Andric   UnloadSectionsCommon(module);
1230b57cec5SDimitry Andric }
1240b57cec5SDimitry Andric 
UnloadSectionsCommon(const ModuleSP module)1250b57cec5SDimitry Andric void DynamicLoader::UnloadSectionsCommon(const ModuleSP module) {
1260b57cec5SDimitry Andric   Target &target = m_process->GetTarget();
1270b57cec5SDimitry Andric   const SectionList *sections = GetSectionListFromModule(module);
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric   assert(sections && "SectionList missing from unloaded module.");
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric   const size_t num_sections = sections->GetSize();
1320b57cec5SDimitry Andric   for (size_t i = 0; i < num_sections; ++i) {
1330b57cec5SDimitry Andric     SectionSP section_sp(sections->GetSectionAtIndex(i));
1340b57cec5SDimitry Andric     target.SetSectionUnloaded(section_sp);
1350b57cec5SDimitry Andric   }
1360b57cec5SDimitry Andric }
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric const SectionList *
GetSectionListFromModule(const ModuleSP module) const1390b57cec5SDimitry Andric DynamicLoader::GetSectionListFromModule(const ModuleSP module) const {
1400b57cec5SDimitry Andric   SectionList *sections = nullptr;
1410b57cec5SDimitry Andric   if (module) {
1420b57cec5SDimitry Andric     ObjectFile *obj_file = module->GetObjectFile();
1430b57cec5SDimitry Andric     if (obj_file != nullptr) {
1440b57cec5SDimitry Andric       sections = obj_file->GetSectionList();
1450b57cec5SDimitry Andric     }
1460b57cec5SDimitry Andric   }
1470b57cec5SDimitry Andric   return sections;
1480b57cec5SDimitry Andric }
1490b57cec5SDimitry Andric 
LoadModuleAtAddress(const FileSpec & file,addr_t link_map_addr,addr_t base_addr,bool base_addr_is_offset)1500b57cec5SDimitry Andric ModuleSP DynamicLoader::LoadModuleAtAddress(const FileSpec &file,
1510b57cec5SDimitry Andric                                             addr_t link_map_addr,
1520b57cec5SDimitry Andric                                             addr_t base_addr,
1530b57cec5SDimitry Andric                                             bool base_addr_is_offset) {
1540b57cec5SDimitry Andric   Target &target = m_process->GetTarget();
1550b57cec5SDimitry Andric   ModuleList &modules = target.GetImages();
1560b57cec5SDimitry Andric   ModuleSpec module_spec(file, target.GetArchitecture());
1570b57cec5SDimitry Andric   ModuleSP module_sp;
1580b57cec5SDimitry Andric 
1590b57cec5SDimitry Andric   if ((module_sp = modules.FindFirstModule(module_spec))) {
1600b57cec5SDimitry Andric     UpdateLoadedSections(module_sp, link_map_addr, base_addr,
1610b57cec5SDimitry Andric                          base_addr_is_offset);
1620b57cec5SDimitry Andric     return module_sp;
1630b57cec5SDimitry Andric   }
1640b57cec5SDimitry Andric 
1650b57cec5SDimitry Andric   if ((module_sp = target.GetOrCreateModule(module_spec,
1660b57cec5SDimitry Andric                                             true /* notify */))) {
1670b57cec5SDimitry Andric     UpdateLoadedSections(module_sp, link_map_addr, base_addr,
1680b57cec5SDimitry Andric                          base_addr_is_offset);
1690b57cec5SDimitry Andric     return module_sp;
1700b57cec5SDimitry Andric   }
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric   bool check_alternative_file_name = true;
1730b57cec5SDimitry Andric   if (base_addr_is_offset) {
1740b57cec5SDimitry Andric     // Try to fetch the load address of the file from the process as we need
1750b57cec5SDimitry Andric     // absolute load address to read the file out of the memory instead of a
1760b57cec5SDimitry Andric     // load bias.
1770b57cec5SDimitry Andric     bool is_loaded = false;
1780b57cec5SDimitry Andric     lldb::addr_t load_addr;
1790b57cec5SDimitry Andric     Status error = m_process->GetFileLoadAddress(file, is_loaded, load_addr);
1800b57cec5SDimitry Andric     if (error.Success() && is_loaded) {
1810b57cec5SDimitry Andric       check_alternative_file_name = false;
1820b57cec5SDimitry Andric       base_addr = load_addr;
1830b57cec5SDimitry Andric     }
1840b57cec5SDimitry Andric   }
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric   // We failed to find the module based on its name. Lets try to check if we
1870b57cec5SDimitry Andric   // can find a different name based on the memory region info.
1880b57cec5SDimitry Andric   if (check_alternative_file_name) {
1890b57cec5SDimitry Andric     MemoryRegionInfo memory_info;
1900b57cec5SDimitry Andric     Status error = m_process->GetMemoryRegionInfo(base_addr, memory_info);
1910b57cec5SDimitry Andric     if (error.Success() && memory_info.GetMapped() &&
1920b57cec5SDimitry Andric         memory_info.GetRange().GetRangeBase() == base_addr &&
1930b57cec5SDimitry Andric         !(memory_info.GetName().IsEmpty())) {
1945ffd83dbSDimitry Andric       ModuleSpec new_module_spec(FileSpec(memory_info.GetName().GetStringRef()),
1950b57cec5SDimitry Andric                                  target.GetArchitecture());
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric       if ((module_sp = modules.FindFirstModule(new_module_spec))) {
1980b57cec5SDimitry Andric         UpdateLoadedSections(module_sp, link_map_addr, base_addr, false);
1990b57cec5SDimitry Andric         return module_sp;
2000b57cec5SDimitry Andric       }
2010b57cec5SDimitry Andric 
2020b57cec5SDimitry Andric       if ((module_sp = target.GetOrCreateModule(new_module_spec,
2030b57cec5SDimitry Andric                                                 true /* notify */))) {
2040b57cec5SDimitry Andric         UpdateLoadedSections(module_sp, link_map_addr, base_addr, false);
2050b57cec5SDimitry Andric         return module_sp;
2060b57cec5SDimitry Andric       }
2070b57cec5SDimitry Andric     }
2080b57cec5SDimitry Andric   }
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric   if ((module_sp = m_process->ReadModuleFromMemory(file, base_addr))) {
2110b57cec5SDimitry Andric     UpdateLoadedSections(module_sp, link_map_addr, base_addr, false);
2120b57cec5SDimitry Andric     target.GetImages().AppendIfNeeded(module_sp);
2130b57cec5SDimitry Andric   }
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric   return module_sp;
2160b57cec5SDimitry Andric }
2170b57cec5SDimitry Andric 
ReadUnsignedIntWithSizeInBytes(addr_t addr,int size_in_bytes)2180b57cec5SDimitry Andric int64_t DynamicLoader::ReadUnsignedIntWithSizeInBytes(addr_t addr,
2190b57cec5SDimitry Andric                                                       int size_in_bytes) {
2200b57cec5SDimitry Andric   Status error;
2210b57cec5SDimitry Andric   uint64_t value =
2220b57cec5SDimitry Andric       m_process->ReadUnsignedIntegerFromMemory(addr, size_in_bytes, 0, error);
2230b57cec5SDimitry Andric   if (error.Fail())
2240b57cec5SDimitry Andric     return -1;
2250b57cec5SDimitry Andric   else
2260b57cec5SDimitry Andric     return (int64_t)value;
2270b57cec5SDimitry Andric }
2280b57cec5SDimitry Andric 
ReadPointer(addr_t addr)2290b57cec5SDimitry Andric addr_t DynamicLoader::ReadPointer(addr_t addr) {
2300b57cec5SDimitry Andric   Status error;
2310b57cec5SDimitry Andric   addr_t value = m_process->ReadPointerFromMemory(addr, error);
2320b57cec5SDimitry Andric   if (error.Fail())
2330b57cec5SDimitry Andric     return LLDB_INVALID_ADDRESS;
2340b57cec5SDimitry Andric   else
2350b57cec5SDimitry Andric     return value;
2360b57cec5SDimitry Andric }
2370b57cec5SDimitry Andric 
LoadOperatingSystemPlugin(bool flush)2380b57cec5SDimitry Andric void DynamicLoader::LoadOperatingSystemPlugin(bool flush)
2390b57cec5SDimitry Andric {
2400b57cec5SDimitry Andric     if (m_process)
2410b57cec5SDimitry Andric         m_process->LoadOperatingSystemPlugin(flush);
2420b57cec5SDimitry Andric }
2430b57cec5SDimitry Andric 
244