1ac7ddfbfSEd Maste //===-- DynamicLoader.cpp ---------------------------------------*- C++ -*-===//
2ac7ddfbfSEd Maste //
3ac7ddfbfSEd Maste // The LLVM Compiler Infrastructure
4ac7ddfbfSEd Maste //
5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source
6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details.
7ac7ddfbfSEd Maste //
8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===//
9ac7ddfbfSEd Maste
10ac7ddfbfSEd Maste #include "lldb/Target/DynamicLoader.h"
11f678e45dSDimitry Andric
1212b93ac6SEd Maste #include "lldb/Core/Module.h"
13*b5893f02SDimitry Andric #include "lldb/Core/ModuleList.h"
1412b93ac6SEd Maste #include "lldb/Core/ModuleSpec.h"
15435933ddSDimitry Andric #include "lldb/Core/PluginManager.h"
1612b93ac6SEd Maste #include "lldb/Core/Section.h"
17*b5893f02SDimitry Andric #include "lldb/Symbol/ObjectFile.h"
18435933ddSDimitry Andric #include "lldb/Target/MemoryRegionInfo.h"
19435933ddSDimitry Andric #include "lldb/Target/Process.h"
20435933ddSDimitry Andric #include "lldb/Target/Target.h"
21*b5893f02SDimitry Andric #include "lldb/Utility/ConstString.h"
22*b5893f02SDimitry Andric #include "lldb/lldb-private-interfaces.h"
23f678e45dSDimitry Andric
24*b5893f02SDimitry Andric #include "llvm/ADT/StringRef.h"
25f678e45dSDimitry Andric
26*b5893f02SDimitry Andric #include <memory>
27f678e45dSDimitry Andric
28*b5893f02SDimitry Andric #include <assert.h>
29ac7ddfbfSEd Maste
30ac7ddfbfSEd Maste using namespace lldb;
31ac7ddfbfSEd Maste using namespace lldb_private;
32ac7ddfbfSEd Maste
FindPlugin(Process * process,const char * plugin_name)33435933ddSDimitry Andric DynamicLoader *DynamicLoader::FindPlugin(Process *process,
34435933ddSDimitry Andric const char *plugin_name) {
354bb0738eSEd Maste DynamicLoaderCreateInstance create_callback = nullptr;
36435933ddSDimitry Andric if (plugin_name) {
37ac7ddfbfSEd Maste ConstString const_plugin_name(plugin_name);
38435933ddSDimitry Andric create_callback =
39435933ddSDimitry Andric PluginManager::GetDynamicLoaderCreateCallbackForPluginName(
40435933ddSDimitry Andric const_plugin_name);
41435933ddSDimitry Andric if (create_callback) {
42435933ddSDimitry Andric std::unique_ptr<DynamicLoader> instance_ap(
43435933ddSDimitry Andric create_callback(process, true));
444bb0738eSEd Maste if (instance_ap)
45ac7ddfbfSEd Maste return instance_ap.release();
46ac7ddfbfSEd Maste }
47435933ddSDimitry Andric } else {
48435933ddSDimitry Andric for (uint32_t idx = 0;
49435933ddSDimitry Andric (create_callback =
50435933ddSDimitry Andric PluginManager::GetDynamicLoaderCreateCallbackAtIndex(idx)) !=
51435933ddSDimitry Andric nullptr;
52435933ddSDimitry Andric ++idx) {
53435933ddSDimitry Andric std::unique_ptr<DynamicLoader> instance_ap(
54435933ddSDimitry Andric create_callback(process, false));
554bb0738eSEd Maste if (instance_ap)
56ac7ddfbfSEd Maste return instance_ap.release();
57ac7ddfbfSEd Maste }
58ac7ddfbfSEd Maste }
594bb0738eSEd Maste return nullptr;
60ac7ddfbfSEd Maste }
61ac7ddfbfSEd Maste
DynamicLoader(Process * process)62435933ddSDimitry Andric DynamicLoader::DynamicLoader(Process *process) : m_process(process) {}
63ac7ddfbfSEd Maste
644bb0738eSEd Maste DynamicLoader::~DynamicLoader() = default;
65ac7ddfbfSEd Maste
66ac7ddfbfSEd Maste //----------------------------------------------------------------------
674ba319b5SDimitry Andric // Accessosors to the global setting as to whether to stop at image (shared
684ba319b5SDimitry Andric // library) loading/unloading.
69ac7ddfbfSEd Maste //----------------------------------------------------------------------
704bb0738eSEd Maste
GetStopWhenImagesChange() const71435933ddSDimitry Andric bool DynamicLoader::GetStopWhenImagesChange() const {
72ac7ddfbfSEd Maste return m_process->GetStopOnSharedLibraryEvents();
73ac7ddfbfSEd Maste }
74ac7ddfbfSEd Maste
SetStopWhenImagesChange(bool stop)75435933ddSDimitry Andric void DynamicLoader::SetStopWhenImagesChange(bool stop) {
76ac7ddfbfSEd Maste m_process->SetStopOnSharedLibraryEvents(stop);
77ac7ddfbfSEd Maste }
78ac7ddfbfSEd Maste
GetTargetExecutable()79435933ddSDimitry Andric ModuleSP DynamicLoader::GetTargetExecutable() {
8012b93ac6SEd Maste Target &target = m_process->GetTarget();
8112b93ac6SEd Maste ModuleSP executable = target.GetExecutableModule();
8212b93ac6SEd Maste
83435933ddSDimitry Andric if (executable) {
84*b5893f02SDimitry Andric if (FileSystem::Instance().Exists(executable->GetFileSpec())) {
85435933ddSDimitry Andric ModuleSpec module_spec(executable->GetFileSpec(),
86435933ddSDimitry Andric executable->GetArchitecture());
87f678e45dSDimitry Andric auto module_sp = std::make_shared<Module>(module_spec);
8812b93ac6SEd Maste
894ba319b5SDimitry Andric // Check if the executable has changed and set it to the target
904ba319b5SDimitry Andric // executable if they differ.
91435933ddSDimitry Andric if (module_sp && module_sp->GetUUID().IsValid() &&
92435933ddSDimitry Andric executable->GetUUID().IsValid()) {
9312b93ac6SEd Maste if (module_sp->GetUUID() != executable->GetUUID())
9412b93ac6SEd Maste executable.reset();
95435933ddSDimitry Andric } else if (executable->FileHasChanged()) {
9612b93ac6SEd Maste executable.reset();
9712b93ac6SEd Maste }
9812b93ac6SEd Maste
99435933ddSDimitry Andric if (!executable) {
10012b93ac6SEd Maste executable = target.GetSharedModule(module_spec);
101435933ddSDimitry Andric if (executable.get() != target.GetExecutableModulePointer()) {
1024ba319b5SDimitry Andric // Don't load dependent images since we are in dyld where we will
1034ba319b5SDimitry Andric // know and find out about all images that are loaded
104*b5893f02SDimitry Andric target.SetExecutableModule(executable, eLoadDependentsNo);
10512b93ac6SEd Maste }
10612b93ac6SEd Maste }
10712b93ac6SEd Maste }
10812b93ac6SEd Maste }
10912b93ac6SEd Maste return executable;
11012b93ac6SEd Maste }
11112b93ac6SEd Maste
UpdateLoadedSections(ModuleSP module,addr_t link_map_addr,addr_t base_addr,bool base_addr_is_offset)112435933ddSDimitry Andric void DynamicLoader::UpdateLoadedSections(ModuleSP module, addr_t link_map_addr,
1139f2f44ceSEd Maste addr_t base_addr,
114435933ddSDimitry Andric bool base_addr_is_offset) {
1159f2f44ceSEd Maste UpdateLoadedSectionsCommon(module, base_addr, base_addr_is_offset);
11612b93ac6SEd Maste }
11712b93ac6SEd Maste
UpdateLoadedSectionsCommon(ModuleSP module,addr_t base_addr,bool base_addr_is_offset)118435933ddSDimitry Andric void DynamicLoader::UpdateLoadedSectionsCommon(ModuleSP module,
1199f2f44ceSEd Maste addr_t base_addr,
120435933ddSDimitry Andric bool base_addr_is_offset) {
12112b93ac6SEd Maste bool changed;
122435933ddSDimitry Andric module->SetLoadAddress(m_process->GetTarget(), base_addr, base_addr_is_offset,
123435933ddSDimitry Andric changed);
12412b93ac6SEd Maste }
12512b93ac6SEd Maste
UnloadSections(const ModuleSP module)126435933ddSDimitry Andric void DynamicLoader::UnloadSections(const ModuleSP module) {
12712b93ac6SEd Maste UnloadSectionsCommon(module);
12812b93ac6SEd Maste }
12912b93ac6SEd Maste
UnloadSectionsCommon(const ModuleSP module)130435933ddSDimitry Andric void DynamicLoader::UnloadSectionsCommon(const ModuleSP module) {
13112b93ac6SEd Maste Target &target = m_process->GetTarget();
13212b93ac6SEd Maste const SectionList *sections = GetSectionListFromModule(module);
13312b93ac6SEd Maste
13412b93ac6SEd Maste assert(sections && "SectionList missing from unloaded module.");
13512b93ac6SEd Maste
13612b93ac6SEd Maste const size_t num_sections = sections->GetSize();
137435933ddSDimitry Andric for (size_t i = 0; i < num_sections; ++i) {
13812b93ac6SEd Maste SectionSP section_sp(sections->GetSectionAtIndex(i));
13912b93ac6SEd Maste target.SetSectionUnloaded(section_sp);
14012b93ac6SEd Maste }
14112b93ac6SEd Maste }
14212b93ac6SEd Maste
14312b93ac6SEd Maste const SectionList *
GetSectionListFromModule(const ModuleSP module) const144435933ddSDimitry Andric DynamicLoader::GetSectionListFromModule(const ModuleSP module) const {
14512b93ac6SEd Maste SectionList *sections = nullptr;
146435933ddSDimitry Andric if (module) {
14712b93ac6SEd Maste ObjectFile *obj_file = module->GetObjectFile();
148435933ddSDimitry Andric if (obj_file != nullptr) {
14912b93ac6SEd Maste sections = obj_file->GetSectionList();
15012b93ac6SEd Maste }
15112b93ac6SEd Maste }
15212b93ac6SEd Maste return sections;
15312b93ac6SEd Maste }
15412b93ac6SEd Maste
LoadModuleAtAddress(const FileSpec & file,addr_t link_map_addr,addr_t base_addr,bool base_addr_is_offset)155435933ddSDimitry Andric ModuleSP DynamicLoader::LoadModuleAtAddress(const FileSpec &file,
1569f2f44ceSEd Maste addr_t link_map_addr,
1579f2f44ceSEd Maste addr_t base_addr,
158435933ddSDimitry Andric bool base_addr_is_offset) {
15912b93ac6SEd Maste Target &target = m_process->GetTarget();
16012b93ac6SEd Maste ModuleList &modules = target.GetImages();
161435933ddSDimitry Andric ModuleSpec module_spec(file, target.GetArchitecture());
16212b93ac6SEd Maste ModuleSP module_sp;
16312b93ac6SEd Maste
164435933ddSDimitry Andric if ((module_sp = modules.FindFirstModule(module_spec))) {
165435933ddSDimitry Andric UpdateLoadedSections(module_sp, link_map_addr, base_addr,
166435933ddSDimitry Andric base_addr_is_offset);
167435933ddSDimitry Andric return module_sp;
16812b93ac6SEd Maste }
169435933ddSDimitry Andric
170435933ddSDimitry Andric if ((module_sp = target.GetSharedModule(module_spec))) {
171435933ddSDimitry Andric UpdateLoadedSections(module_sp, link_map_addr, base_addr,
172435933ddSDimitry Andric base_addr_is_offset);
173435933ddSDimitry Andric return module_sp;
17412b93ac6SEd Maste }
175435933ddSDimitry Andric
176435933ddSDimitry Andric bool check_alternative_file_name = true;
177435933ddSDimitry Andric if (base_addr_is_offset) {
178435933ddSDimitry Andric // Try to fetch the load address of the file from the process as we need
1794ba319b5SDimitry Andric // absolute load address to read the file out of the memory instead of a
1804ba319b5SDimitry Andric // load bias.
1814bb0738eSEd Maste bool is_loaded = false;
1821c3bbb01SEd Maste lldb::addr_t load_addr;
1835517e702SDimitry Andric Status error = m_process->GetFileLoadAddress(file, is_loaded, load_addr);
184435933ddSDimitry Andric if (error.Success() && is_loaded) {
185435933ddSDimitry Andric check_alternative_file_name = false;
1869f2f44ceSEd Maste base_addr = load_addr;
1879f2f44ceSEd Maste }
188435933ddSDimitry Andric }
1891c3bbb01SEd Maste
1904ba319b5SDimitry Andric // We failed to find the module based on its name. Lets try to check if we
1914ba319b5SDimitry Andric // can find a different name based on the memory region info.
192435933ddSDimitry Andric if (check_alternative_file_name) {
193435933ddSDimitry Andric MemoryRegionInfo memory_info;
1945517e702SDimitry Andric Status error = m_process->GetMemoryRegionInfo(base_addr, memory_info);
195435933ddSDimitry Andric if (error.Success() && memory_info.GetMapped() &&
196f678e45dSDimitry Andric memory_info.GetRange().GetRangeBase() == base_addr &&
197f678e45dSDimitry Andric !(memory_info.GetName().IsEmpty())) {
198*b5893f02SDimitry Andric ModuleSpec new_module_spec(FileSpec(memory_info.GetName().AsCString()),
199435933ddSDimitry Andric target.GetArchitecture());
200435933ddSDimitry Andric
201435933ddSDimitry Andric if ((module_sp = modules.FindFirstModule(new_module_spec))) {
202435933ddSDimitry Andric UpdateLoadedSections(module_sp, link_map_addr, base_addr, false);
203435933ddSDimitry Andric return module_sp;
204435933ddSDimitry Andric }
205435933ddSDimitry Andric
206435933ddSDimitry Andric if ((module_sp = target.GetSharedModule(new_module_spec))) {
207435933ddSDimitry Andric UpdateLoadedSections(module_sp, link_map_addr, base_addr, false);
208435933ddSDimitry Andric return module_sp;
209435933ddSDimitry Andric }
210435933ddSDimitry Andric }
211435933ddSDimitry Andric }
212435933ddSDimitry Andric
213435933ddSDimitry Andric if ((module_sp = m_process->ReadModuleFromMemory(file, base_addr))) {
2149f2f44ceSEd Maste UpdateLoadedSections(module_sp, link_map_addr, base_addr, false);
2151c3bbb01SEd Maste target.GetImages().AppendIfNeeded(module_sp);
2161c3bbb01SEd Maste }
21712b93ac6SEd Maste
21812b93ac6SEd Maste return module_sp;
21912b93ac6SEd Maste }
22012b93ac6SEd Maste
ReadUnsignedIntWithSizeInBytes(addr_t addr,int size_in_bytes)221435933ddSDimitry Andric int64_t DynamicLoader::ReadUnsignedIntWithSizeInBytes(addr_t addr,
222435933ddSDimitry Andric int size_in_bytes) {
2235517e702SDimitry Andric Status error;
224435933ddSDimitry Andric uint64_t value =
225435933ddSDimitry Andric m_process->ReadUnsignedIntegerFromMemory(addr, size_in_bytes, 0, error);
22612b93ac6SEd Maste if (error.Fail())
22712b93ac6SEd Maste return -1;
22812b93ac6SEd Maste else
22912b93ac6SEd Maste return (int64_t)value;
23012b93ac6SEd Maste }
23112b93ac6SEd Maste
ReadPointer(addr_t addr)232435933ddSDimitry Andric addr_t DynamicLoader::ReadPointer(addr_t addr) {
2335517e702SDimitry Andric Status error;
23412b93ac6SEd Maste addr_t value = m_process->ReadPointerFromMemory(addr, error);
23512b93ac6SEd Maste if (error.Fail())
23612b93ac6SEd Maste return LLDB_INVALID_ADDRESS;
23712b93ac6SEd Maste else
23812b93ac6SEd Maste return value;
23912b93ac6SEd Maste }
240f678e45dSDimitry Andric
LoadOperatingSystemPlugin(bool flush)241f678e45dSDimitry Andric void DynamicLoader::LoadOperatingSystemPlugin(bool flush)
242f678e45dSDimitry Andric {
243f678e45dSDimitry Andric if (m_process)
244f678e45dSDimitry Andric m_process->LoadOperatingSystemPlugin(flush);
245f678e45dSDimitry Andric }
246f678e45dSDimitry Andric
247