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