1 //===-- DynamicLoader.cpp ---------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 // C Includes
11 // C++ Includes
12 // Other libraries and framework includes
13 // Project includes
14 #include "lldb/lldb-private.h"
15 #include "lldb/Core/Module.h"
16 #include "lldb/Core/ModuleSpec.h"
17 #include "lldb/Core/PluginManager.h"
18 #include "lldb/Core/Section.h"
19 #include "lldb/Target/DynamicLoader.h"
20 #include "lldb/Target/MemoryRegionInfo.h"
21 #include "lldb/Target/Process.h"
22 #include "lldb/Target/Target.h"
23 
24 using namespace lldb;
25 using namespace lldb_private;
26 
27 DynamicLoader*
28 DynamicLoader::FindPlugin (Process *process, const char *plugin_name)
29 {
30     DynamicLoaderCreateInstance create_callback = nullptr;
31     if (plugin_name)
32     {
33         ConstString const_plugin_name(plugin_name);
34         create_callback  = PluginManager::GetDynamicLoaderCreateCallbackForPluginName (const_plugin_name);
35         if (create_callback)
36         {
37             std::unique_ptr<DynamicLoader> instance_ap(create_callback(process, true));
38             if (instance_ap)
39                 return instance_ap.release();
40         }
41     }
42     else
43     {
44         for (uint32_t idx = 0; (create_callback = PluginManager::GetDynamicLoaderCreateCallbackAtIndex(idx)) != nullptr; ++idx)
45         {
46             std::unique_ptr<DynamicLoader> instance_ap(create_callback(process, false));
47             if (instance_ap)
48                 return instance_ap.release();
49         }
50     }
51     return nullptr;
52 }
53 
54 DynamicLoader::DynamicLoader(Process *process) :
55     m_process (process)
56 {
57 }
58 
59 DynamicLoader::~DynamicLoader() = default;
60 
61 //----------------------------------------------------------------------
62 // Accessosors to the global setting as to whether to stop at image
63 // (shared library) loading/unloading.
64 //----------------------------------------------------------------------
65 
66 bool
67 DynamicLoader::GetStopWhenImagesChange () const
68 {
69     return m_process->GetStopOnSharedLibraryEvents();
70 }
71 
72 void
73 DynamicLoader::SetStopWhenImagesChange (bool stop)
74 {
75     m_process->SetStopOnSharedLibraryEvents (stop);
76 }
77 
78 ModuleSP
79 DynamicLoader::GetTargetExecutable()
80 {
81     Target &target = m_process->GetTarget();
82     ModuleSP executable = target.GetExecutableModule();
83 
84     if (executable)
85     {
86         if (executable->GetFileSpec().Exists())
87         {
88             ModuleSpec module_spec (executable->GetFileSpec(), executable->GetArchitecture());
89             ModuleSP module_sp (new Module (module_spec));
90 
91             // Check if the executable has changed and set it to the target executable if they differ.
92             if (module_sp && module_sp->GetUUID().IsValid() && executable->GetUUID().IsValid())
93             {
94                 if (module_sp->GetUUID() != executable->GetUUID())
95                     executable.reset();
96             }
97             else if (executable->FileHasChanged())
98             {
99                 executable.reset();
100             }
101 
102             if (!executable)
103             {
104                 executable = target.GetSharedModule(module_spec);
105                 if (executable.get() != target.GetExecutableModulePointer())
106                 {
107                     // Don't load dependent images since we are in dyld where we will know
108                     // and find out about all images that are loaded
109                     const bool get_dependent_images = false;
110                     target.SetExecutableModule(executable, get_dependent_images);
111                 }
112             }
113         }
114     }
115     return executable;
116 }
117 
118 void
119 DynamicLoader::UpdateLoadedSections(ModuleSP module,
120                                     addr_t link_map_addr,
121                                     addr_t base_addr,
122                                     bool base_addr_is_offset)
123 {
124     UpdateLoadedSectionsCommon(module, base_addr, base_addr_is_offset);
125 }
126 
127 void
128 DynamicLoader::UpdateLoadedSectionsCommon(ModuleSP module,
129                                           addr_t base_addr,
130                                           bool base_addr_is_offset)
131 {
132     bool changed;
133     module->SetLoadAddress(m_process->GetTarget(), base_addr, base_addr_is_offset, changed);
134 }
135 
136 void
137 DynamicLoader::UnloadSections(const ModuleSP module)
138 {
139     UnloadSectionsCommon(module);
140 }
141 
142 void
143 DynamicLoader::UnloadSectionsCommon(const ModuleSP module)
144 {
145     Target &target = m_process->GetTarget();
146     const SectionList *sections = GetSectionListFromModule(module);
147 
148     assert(sections && "SectionList missing from unloaded module.");
149 
150     const size_t num_sections = sections->GetSize();
151     for (size_t i = 0; i < num_sections; ++i)
152     {
153         SectionSP section_sp (sections->GetSectionAtIndex(i));
154         target.SetSectionUnloaded(section_sp);
155     }
156 }
157 
158 const SectionList *
159 DynamicLoader::GetSectionListFromModule(const ModuleSP module) const
160 {
161     SectionList *sections = nullptr;
162     if (module)
163     {
164         ObjectFile *obj_file = module->GetObjectFile();
165         if (obj_file != nullptr)
166         {
167             sections = obj_file->GetSectionList();
168         }
169     }
170     return sections;
171 }
172 
173 ModuleSP
174 DynamicLoader::LoadModuleAtAddress(const FileSpec &file,
175                                    addr_t link_map_addr,
176                                    addr_t base_addr,
177                                    bool base_addr_is_offset)
178 {
179     Target &target = m_process->GetTarget();
180     ModuleList &modules = target.GetImages();
181     ModuleSpec module_spec (file, target.GetArchitecture());
182     ModuleSP module_sp;
183 
184     if ((module_sp = modules.FindFirstModule (module_spec)))
185     {
186         UpdateLoadedSections(module_sp, link_map_addr, base_addr, base_addr_is_offset);
187         return module_sp;
188     }
189 
190     if ((module_sp = target.GetSharedModule(module_spec)))
191     {
192         UpdateLoadedSections(module_sp, link_map_addr, base_addr, base_addr_is_offset);
193         return module_sp;
194     }
195 
196     bool check_alternative_file_name = true;
197     if (base_addr_is_offset)
198     {
199         // Try to fetch the load address of the file from the process as we need absolute load
200         // address to read the file out of the memory instead of a load bias.
201         bool is_loaded = false;
202         lldb::addr_t load_addr;
203         Error error = m_process->GetFileLoadAddress(file, is_loaded, load_addr);
204         if (error.Success() && is_loaded)
205         {
206             check_alternative_file_name = false;
207             base_addr = load_addr;
208         }
209     }
210 
211     // We failed to find the module based on its name. Lets try to check if we can find a
212     // different name based on the memory region info.
213     if (check_alternative_file_name)
214     {
215         MemoryRegionInfo memory_info;
216         Error error = m_process->GetMemoryRegionInfo(base_addr, memory_info);
217         if (error.Success() && memory_info.GetMapped() && memory_info.GetRange().GetRangeBase() == base_addr)
218         {
219             ModuleSpec new_module_spec(FileSpec(memory_info.GetName().AsCString(), false),
220                                        target.GetArchitecture());
221 
222             if ((module_sp = modules.FindFirstModule(new_module_spec)))
223             {
224                 UpdateLoadedSections(module_sp, link_map_addr, base_addr, false);
225                 return module_sp;
226             }
227 
228             if ((module_sp = target.GetSharedModule(new_module_spec)))
229             {
230                 UpdateLoadedSections(module_sp, link_map_addr, base_addr, false);
231                 return module_sp;
232             }
233         }
234     }
235 
236     if ((module_sp = m_process->ReadModuleFromMemory(file, base_addr)))
237     {
238         UpdateLoadedSections(module_sp, link_map_addr, base_addr, false);
239         target.GetImages().AppendIfNeeded(module_sp);
240     }
241 
242     return module_sp;
243 }
244 
245 int64_t
246 DynamicLoader::ReadUnsignedIntWithSizeInBytes(addr_t addr, int size_in_bytes)
247 {
248     Error error;
249     uint64_t value = m_process->ReadUnsignedIntegerFromMemory(addr, size_in_bytes, 0, error);
250     if (error.Fail())
251         return -1;
252     else
253         return (int64_t)value;
254 }
255 
256 addr_t
257 DynamicLoader::ReadPointer(addr_t addr)
258 {
259     Error error;
260     addr_t value = m_process->ReadPointerFromMemory(addr, error);
261     if (error.Fail())
262         return LLDB_INVALID_ADDRESS;
263     else
264         return value;
265 }
266