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