1//===-- DynamicLoader.cpp -------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "lldb/Target/DynamicLoader.h"
10
11#include "lldb/Core/Debugger.h"
12#include "lldb/Core/Module.h"
13#include "lldb/Core/ModuleList.h"
14#include "lldb/Core/ModuleSpec.h"
15#include "lldb/Core/PluginManager.h"
16#include "lldb/Core/Section.h"
17#include "lldb/Symbol/ObjectFile.h"
18#include "lldb/Target/MemoryRegionInfo.h"
19#include "lldb/Target/Platform.h"
20#include "lldb/Target/Process.h"
21#include "lldb/Target/Target.h"
22#include "lldb/Utility/ConstString.h"
23#include "lldb/Utility/LLDBLog.h"
24#include "lldb/Utility/Log.h"
25#include "lldb/lldb-private-interfaces.h"
26
27#include "llvm/ADT/StringRef.h"
28
29#include <memory>
30
31#include <cassert>
32
33using namespace lldb;
34using namespace lldb_private;
35
36DynamicLoader *DynamicLoader::FindPlugin(Process *process,
37                                         llvm::StringRef plugin_name) {
38  DynamicLoaderCreateInstance create_callback = nullptr;
39  if (!plugin_name.empty()) {
40    create_callback =
41        PluginManager::GetDynamicLoaderCreateCallbackForPluginName(plugin_name);
42    if (create_callback) {
43      std::unique_ptr<DynamicLoader> instance_up(
44          create_callback(process, true));
45      if (instance_up)
46        return instance_up.release();
47    }
48  } else {
49    for (uint32_t idx = 0;
50         (create_callback =
51              PluginManager::GetDynamicLoaderCreateCallbackAtIndex(idx)) !=
52         nullptr;
53         ++idx) {
54      std::unique_ptr<DynamicLoader> instance_up(
55          create_callback(process, false));
56      if (instance_up)
57        return instance_up.release();
58    }
59  }
60  return nullptr;
61}
62
63DynamicLoader::DynamicLoader(Process *process) : m_process(process) {}
64
65// Accessors to the global setting as to whether to stop at image (shared
66// library) loading/unloading.
67
68bool DynamicLoader::GetStopWhenImagesChange() const {
69  return m_process->GetStopOnSharedLibraryEvents();
70}
71
72void DynamicLoader::SetStopWhenImagesChange(bool stop) {
73  m_process->SetStopOnSharedLibraryEvents(stop);
74}
75
76ModuleSP DynamicLoader::GetTargetExecutable() {
77  Target &target = m_process->GetTarget();
78  ModuleSP executable = target.GetExecutableModule();
79
80  if (executable) {
81    if (FileSystem::Instance().Exists(executable->GetFileSpec())) {
82      ModuleSpec module_spec(executable->GetFileSpec(),
83                             executable->GetArchitecture());
84      auto module_sp = std::make_shared<Module>(module_spec);
85
86      // Check if the executable has changed and set it to the target
87      // executable if they differ.
88      if (module_sp && module_sp->GetUUID().IsValid() &&
89          executable->GetUUID().IsValid()) {
90        if (module_sp->GetUUID() != executable->GetUUID())
91          executable.reset();
92      } else if (executable->FileHasChanged()) {
93        executable.reset();
94      }
95
96      if (!executable) {
97        executable = target.GetOrCreateModule(module_spec, true /* notify */);
98        if (executable.get() != target.GetExecutableModulePointer()) {
99          // Don't load dependent images since we are in dyld where we will
100          // know and find out about all images that are loaded
101          target.SetExecutableModule(executable, eLoadDependentsNo);
102        }
103      }
104    }
105  }
106  return executable;
107}
108
109void DynamicLoader::UpdateLoadedSections(ModuleSP module, addr_t link_map_addr,
110                                         addr_t base_addr,
111                                         bool base_addr_is_offset) {
112  UpdateLoadedSectionsCommon(module, base_addr, base_addr_is_offset);
113}
114
115void DynamicLoader::UpdateLoadedSectionsCommon(ModuleSP module,
116                                               addr_t base_addr,
117                                               bool base_addr_is_offset) {
118  bool changed;
119  module->SetLoadAddress(m_process->GetTarget(), base_addr, base_addr_is_offset,
120                         changed);
121}
122
123void DynamicLoader::UnloadSections(const ModuleSP module) {
124  UnloadSectionsCommon(module);
125}
126
127void DynamicLoader::UnloadSectionsCommon(const ModuleSP module) {
128  Target &target = m_process->GetTarget();
129  const SectionList *sections = GetSectionListFromModule(module);
130
131  assert(sections && "SectionList missing from unloaded module.");
132
133  const size_t num_sections = sections->GetSize();
134  for (size_t i = 0; i < num_sections; ++i) {
135    SectionSP section_sp(sections->GetSectionAtIndex(i));
136    target.SetSectionUnloaded(section_sp);
137  }
138}
139
140const SectionList *
141DynamicLoader::GetSectionListFromModule(const ModuleSP module) const {
142  SectionList *sections = nullptr;
143  if (module) {
144    ObjectFile *obj_file = module->GetObjectFile();
145    if (obj_file != nullptr) {
146      sections = obj_file->GetSectionList();
147    }
148  }
149  return sections;
150}
151
152ModuleSP DynamicLoader::FindModuleViaTarget(const FileSpec &file) {
153  Target &target = m_process->GetTarget();
154  ModuleSpec module_spec(file, target.GetArchitecture());
155
156  if (ModuleSP module_sp = target.GetImages().FindFirstModule(module_spec))
157    return module_sp;
158
159  if (ModuleSP module_sp = target.GetOrCreateModule(module_spec, false))
160    return module_sp;
161
162  return nullptr;
163}
164
165ModuleSP DynamicLoader::LoadModuleAtAddress(const FileSpec &file,
166                                            addr_t link_map_addr,
167                                            addr_t base_addr,
168                                            bool base_addr_is_offset) {
169  if (ModuleSP module_sp = FindModuleViaTarget(file)) {
170    UpdateLoadedSections(module_sp, link_map_addr, base_addr,
171                         base_addr_is_offset);
172    return module_sp;
173  }
174
175  return nullptr;
176}
177
178static ModuleSP ReadUnnamedMemoryModule(Process *process, addr_t addr,
179                                        llvm::StringRef name) {
180  char namebuf[80];
181  if (name.empty()) {
182    snprintf(namebuf, sizeof(namebuf), "memory-image-0x%" PRIx64, addr);
183    name = namebuf;
184  }
185  return process->ReadModuleFromMemory(FileSpec(name), addr);
186}
187
188ModuleSP DynamicLoader::LoadBinaryWithUUIDAndAddress(
189    Process *process, llvm::StringRef name, UUID uuid, addr_t value,
190    bool value_is_offset, bool force_symbol_search, bool notify,
191    bool set_address_in_target, bool allow_memory_image_last_resort) {
192  ModuleSP memory_module_sp;
193  ModuleSP module_sp;
194  PlatformSP platform_sp = process->GetTarget().GetPlatform();
195  Target &target = process->GetTarget();
196  Status error;
197
198  if (!uuid.IsValid() && !value_is_offset) {
199    memory_module_sp = ReadUnnamedMemoryModule(process, value, name);
200
201    if (memory_module_sp)
202      uuid = memory_module_sp->GetUUID();
203  }
204  ModuleSpec module_spec;
205  module_spec.GetUUID() = uuid;
206  FileSpec name_filespec(name);
207  if (FileSystem::Instance().Exists(name_filespec))
208    module_spec.GetFileSpec() = name_filespec;
209
210  if (uuid.IsValid()) {
211    // Has lldb already seen a module with this UUID?
212    if (!module_sp)
213      error = ModuleList::GetSharedModule(module_spec, module_sp, nullptr,
214                                          nullptr, nullptr);
215
216    // Can lldb's symbol/executable location schemes
217    // find an executable and symbol file.
218    if (!module_sp) {
219      FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths();
220      module_spec.GetSymbolFileSpec() =
221          PluginManager::LocateExecutableSymbolFile(module_spec, search_paths);
222      ModuleSpec objfile_module_spec =
223          PluginManager::LocateExecutableObjectFile(module_spec);
224      module_spec.GetFileSpec() = objfile_module_spec.GetFileSpec();
225      if (FileSystem::Instance().Exists(module_spec.GetFileSpec()) &&
226          FileSystem::Instance().Exists(module_spec.GetSymbolFileSpec())) {
227        module_sp = std::make_shared<Module>(module_spec);
228      }
229    }
230
231    // If we haven't found a binary, or we don't have a SymbolFile, see
232    // if there is an external search tool that can find it.
233    if (!module_sp || !module_sp->GetSymbolFileFileSpec()) {
234      PluginManager::DownloadObjectAndSymbolFile(module_spec, error,
235                                                 force_symbol_search);
236      if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) {
237        module_sp = std::make_shared<Module>(module_spec);
238      } else if (force_symbol_search && error.AsCString("") &&
239                 error.AsCString("")[0] != '\0') {
240        target.GetDebugger().GetErrorStream() << error.AsCString();
241      }
242    }
243
244    // If we only found the executable, create a Module based on that.
245    if (!module_sp && FileSystem::Instance().Exists(module_spec.GetFileSpec()))
246      module_sp = std::make_shared<Module>(module_spec);
247  }
248
249  // If we couldn't find the binary anywhere else, as a last resort,
250  // read it out of memory.
251  if (allow_memory_image_last_resort && !module_sp.get() &&
252      value != LLDB_INVALID_ADDRESS && !value_is_offset) {
253    if (!memory_module_sp)
254      memory_module_sp = ReadUnnamedMemoryModule(process, value, name);
255    if (memory_module_sp)
256      module_sp = memory_module_sp;
257  }
258
259  Log *log = GetLog(LLDBLog::DynamicLoader);
260  if (module_sp.get()) {
261    // Ensure the Target has an architecture set in case
262    // we need it while processing this binary/eh_frame/debug info.
263    if (!target.GetArchitecture().IsValid())
264      target.SetArchitecture(module_sp->GetArchitecture());
265    target.GetImages().AppendIfNeeded(module_sp, false);
266
267    bool changed = false;
268    if (set_address_in_target) {
269      if (module_sp->GetObjectFile()) {
270        if (value != LLDB_INVALID_ADDRESS) {
271          LLDB_LOGF(log,
272                    "DynamicLoader::LoadBinaryWithUUIDAndAddress Loading "
273                    "binary %s UUID %s at %s 0x%" PRIx64,
274                    name.str().c_str(), uuid.GetAsString().c_str(),
275                    value_is_offset ? "offset" : "address", value);
276          module_sp->SetLoadAddress(target, value, value_is_offset, changed);
277        } else {
278          // No address/offset/slide, load the binary at file address,
279          // offset 0.
280          LLDB_LOGF(log,
281                    "DynamicLoader::LoadBinaryWithUUIDAndAddress Loading "
282                    "binary %s UUID %s at file address",
283                    name.str().c_str(), uuid.GetAsString().c_str());
284          module_sp->SetLoadAddress(target, 0, true /* value_is_slide */,
285                                    changed);
286        }
287      } else {
288        // In-memory image, load at its true address, offset 0.
289        LLDB_LOGF(log,
290                  "DynamicLoader::LoadBinaryWithUUIDAndAddress Loading binary "
291                  "%s UUID %s from memory at address 0x%" PRIx64,
292                  name.str().c_str(), uuid.GetAsString().c_str(), value);
293        module_sp->SetLoadAddress(target, 0, true /* value_is_slide */,
294                                  changed);
295      }
296    }
297
298    if (notify) {
299      ModuleList added_module;
300      added_module.Append(module_sp, false);
301      target.ModulesDidLoad(added_module);
302    }
303  } else {
304    if (force_symbol_search) {
305      Stream &s = target.GetDebugger().GetErrorStream();
306      s.Printf("Unable to find file");
307      if (!name.empty())
308        s.Printf(" %s", name.str().c_str());
309      if (uuid.IsValid())
310        s.Printf(" with UUID %s", uuid.GetAsString().c_str());
311      if (value != LLDB_INVALID_ADDRESS) {
312        if (value_is_offset)
313          s.Printf(" with slide 0x%" PRIx64, value);
314        else
315          s.Printf(" at address 0x%" PRIx64, value);
316      }
317      s.Printf("\n");
318    }
319    LLDB_LOGF(log,
320              "Unable to find binary %s with UUID %s and load it at "
321              "%s 0x%" PRIx64,
322              name.str().c_str(), uuid.GetAsString().c_str(),
323              value_is_offset ? "offset" : "address", value);
324  }
325
326  return module_sp;
327}
328
329int64_t DynamicLoader::ReadUnsignedIntWithSizeInBytes(addr_t addr,
330                                                      int size_in_bytes) {
331  Status error;
332  uint64_t value =
333      m_process->ReadUnsignedIntegerFromMemory(addr, size_in_bytes, 0, error);
334  if (error.Fail())
335    return -1;
336  else
337    return (int64_t)value;
338}
339
340addr_t DynamicLoader::ReadPointer(addr_t addr) {
341  Status error;
342  addr_t value = m_process->ReadPointerFromMemory(addr, error);
343  if (error.Fail())
344    return LLDB_INVALID_ADDRESS;
345  else
346    return value;
347}
348
349void DynamicLoader::LoadOperatingSystemPlugin(bool flush)
350{
351    if (m_process)
352        m_process->LoadOperatingSystemPlugin(flush);
353}
354
355