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