LLDB mainline
DynamicLoader.cpp
Go to the documentation of this file.
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
10
11#include "lldb/Core/Debugger.h"
12#include "lldb/Core/Module.h"
16#include "lldb/Core/Progress.h"
17#include "lldb/Core/Section.h"
21#include "lldb/Target/Process.h"
22#include "lldb/Target/Target.h"
25#include "lldb/Utility/Log.h"
27
28#include "llvm/ADT/StringRef.h"
29
30#include <memory>
31
32#include <cassert>
33
34using namespace lldb;
35using namespace lldb_private;
36
38 llvm::StringRef plugin_name) {
39 DynamicLoaderCreateInstance create_callback = nullptr;
40 if (!plugin_name.empty()) {
41 create_callback =
43 if (create_callback) {
44 std::unique_ptr<DynamicLoader> instance_up(
45 create_callback(process, true));
46 if (instance_up)
47 return instance_up.release();
48 }
49 } else {
50 for (auto create_callback :
52 std::unique_ptr<DynamicLoader> instance_up(
53 create_callback(process, false));
54 if (instance_up)
55 return instance_up.release();
56 }
57 }
58 return nullptr;
59}
60
62
63// Accessors to the global setting as to whether to stop at image (shared
64// library) loading/unloading.
65
67 return m_process->GetStopOnSharedLibraryEvents();
68}
69
71 m_process->SetStopOnSharedLibraryEvents(stop);
72}
73
75 Target &target = m_process->GetTarget();
76 ModuleSP executable = target.GetExecutableModule();
77
78 if (executable) {
79 if (FileSystem::Instance().Exists(executable->GetFileSpec())) {
80 ModuleSpec module_spec(executable->GetFileSpec(),
81 executable->GetArchitecture());
82 auto module_sp = std::make_shared<Module>(module_spec);
83 // If we're a coredump and we already have a main executable, we don't
84 // need to reload the module list that target already has
85 if (!m_process->IsLiveDebugSession()) {
86 return executable;
87 }
88 // Check if the executable has changed and set it to the target
89 // executable if they differ.
90 if (module_sp && module_sp->GetUUID().IsValid() &&
91 executable->GetUUID().IsValid()) {
92 if (module_sp->GetUUID() != executable->GetUUID())
93 executable.reset();
94 } else if (executable->FileHasChanged()) {
95 executable.reset();
96 }
97
98 if (!executable) {
99 executable = target.GetOrCreateModule(module_spec, true /* notify */);
100 if (executable.get() != target.GetExecutableModulePointer()) {
101 // Don't load dependent images since we are in dyld where we will
102 // know and find out about all images that are loaded
103 target.SetExecutableModule(executable, eLoadDependentsNo);
104 }
105 }
106 }
107 }
108 return executable;
109}
110
112 addr_t base_addr,
113 bool base_addr_is_offset) {
114 UpdateLoadedSectionsCommon(module, base_addr, base_addr_is_offset);
115}
116
118 addr_t base_addr,
119 bool base_addr_is_offset) {
120 bool changed;
121 module->SetLoadAddress(m_process->GetTarget(), base_addr, base_addr_is_offset,
122 changed);
123}
124
126 UnloadSectionsCommon(module);
127}
128
130 Target &target = m_process->GetTarget();
131 const SectionList *sections = GetSectionListFromModule(module);
132
133 assert(sections && "SectionList missing from unloaded module.");
134
135 const size_t num_sections = sections->GetSize();
136 for (size_t i = 0; i < num_sections; ++i) {
137 SectionSP section_sp(sections->GetSectionAtIndex(i));
138 target.SetSectionUnloaded(section_sp);
139 }
140}
141
142const SectionList *
144 SectionList *sections = nullptr;
145 if (module) {
146 ObjectFile *obj_file = module->GetObjectFile();
147 if (obj_file != nullptr) {
148 sections = obj_file->GetSectionList();
149 }
150 }
151 return sections;
152}
153
155 ModuleSpec module_spec(spec);
156 Target &target = m_process->GetTarget();
157 // The process may be able to augment the module_spec with a UUID.
158 if (!module_spec.GetUUID().IsValid())
159 m_process->FindModuleUUID(module_spec);
160 if (ModuleSP module_sp = target.GetImages().FindFirstModule(module_spec))
161 return module_sp;
162
163 if (ModuleSP module_sp =
164 target.GetOrCreateModule(module_spec, /*notify=*/false))
165 return module_sp;
166
167 return nullptr;
168}
169
171 addr_t link_map_addr,
172 addr_t base_addr,
173 bool base_addr_is_offset) {
174 Target &target = m_process->GetTarget();
175 ModuleSpec module_spec(file, target.GetArchitecture());
176 module_spec.SetLoadAddress(base_addr);
177 ModuleSP module_sp = FindModuleViaTarget(module_spec);
178 // We have a core file, try to load the image from memory if we didn't find
179 // the module.
180 if (!module_sp && !m_process->IsLiveDebugSession()) {
181 llvm::Expected<ModuleSP> memory_module_sp_or_err =
182 m_process->ReadModuleFromMemory(file, base_addr);
183 if (auto err = memory_module_sp_or_err.takeError())
185 "Failed to read module from memory: {0}");
186 else {
187 module_sp = *memory_module_sp_or_err;
188 m_process->GetTarget().GetImages().AppendIfNeeded(module_sp, false);
189 }
190 }
191 if (module_sp)
192 UpdateLoadedSections(module_sp, link_map_addr, base_addr,
193 base_addr_is_offset);
194 return module_sp;
195}
196
198 llvm::StringRef name) {
199 char namebuf[80];
200 if (name.empty()) {
201 snprintf(namebuf, sizeof(namebuf), "memory-image-0x%" PRIx64, addr);
202 name = namebuf;
203 }
204 llvm::Expected<ModuleSP> module_sp_or_err =
205 process->ReadModuleFromMemory(FileSpec(name), addr);
206 if (auto err = module_sp_or_err.takeError()) {
208 "Failed to read module from memory: {0}");
209 return {};
210 }
211 return *module_sp_or_err;
212}
213
215 Process *process, llvm::StringRef name, UUID uuid, addr_t value,
216 bool value_is_offset, bool force_symbol_search, bool notify,
217 bool set_address_in_target, bool allow_memory_image_last_resort) {
218 ModuleSP memory_module_sp;
219 ModuleSP module_sp;
220 PlatformSP platform_sp = process->GetTarget().GetPlatform();
221 Target &target = process->GetTarget();
223
224 StreamString prog_str;
225 if (!name.empty()) {
226 prog_str << name.str() << " ";
227 }
228 if (uuid.IsValid())
229 prog_str << uuid.GetAsString();
230 if (value_is_offset == 0 && value != LLDB_INVALID_ADDRESS) {
231 prog_str << " at 0x";
232 prog_str.PutHex64(value);
233 }
234
235 if (!uuid.IsValid() && !value_is_offset) {
236 memory_module_sp = ReadUnnamedMemoryModule(process, value, name);
237
238 if (memory_module_sp) {
239 uuid = memory_module_sp->GetUUID();
240 if (uuid.IsValid()) {
241 prog_str << " ";
242 prog_str << uuid.GetAsString();
243 }
244 }
245 }
246 ModuleSpec module_spec;
247 module_spec.SetTarget(target.shared_from_this());
248 module_spec.GetUUID() = uuid;
249 FileSpec name_filespec(name);
250 if (FileSystem::Instance().Exists(name_filespec))
251 module_spec.GetFileSpec() = name_filespec;
252
253 if (uuid.IsValid()) {
254 Progress progress("Locating binary", prog_str.GetString().str());
255
256 // Has lldb already seen a module with this UUID?
257 // Or have external lookup enabled in DebugSymbols on macOS.
258 if (!module_sp)
259 error =
260 ModuleList::GetSharedModule(module_spec, module_sp, nullptr, nullptr);
261
262 // Can lldb's symbol/executable location schemes
263 // find an executable and symbol file.
264 if (!module_sp) {
266 StatisticsMap symbol_locator_map;
267 module_spec.GetSymbolFileSpec() =
268 PluginManager::LocateExecutableSymbolFile(module_spec, search_paths,
269 symbol_locator_map);
270 ModuleSpec objfile_module_spec =
272 symbol_locator_map);
273 module_spec.GetFileSpec() = objfile_module_spec.GetFileSpec();
274 if (FileSystem::Instance().Exists(module_spec.GetFileSpec()) &&
275 FileSystem::Instance().Exists(module_spec.GetSymbolFileSpec())) {
276 module_sp = std::make_shared<Module>(module_spec);
277 }
278
279 if (module_sp) {
280 module_sp->GetSymbolLocatorStatistics().merge(symbol_locator_map);
281 }
282 }
283
284 // If we haven't found a binary, or we don't have a SymbolFile, see
285 // if there is an external search tool that can find it.
286 if (!module_sp || !module_sp->GetSymbolFileFileSpec()) {
288 force_symbol_search);
289 if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) {
290 module_sp = std::make_shared<Module>(module_spec);
291 } else if (force_symbol_search && error.AsCString("") &&
292 error.AsCString("")[0] != '\0') {
293 *target.GetDebugger().GetAsyncErrorStream() << error.AsCString();
294 }
295 }
296
297 // If we only found the executable, create a Module based on that.
298 if (!module_sp && FileSystem::Instance().Exists(module_spec.GetFileSpec()))
299 module_sp = std::make_shared<Module>(module_spec);
300 }
301
302 // If we couldn't find the binary anywhere else, as a last resort,
303 // read it out of memory.
304 if (allow_memory_image_last_resort && !module_sp.get() &&
305 value != LLDB_INVALID_ADDRESS && !value_is_offset) {
306 if (!memory_module_sp)
307 memory_module_sp = ReadUnnamedMemoryModule(process, value, name);
308 if (memory_module_sp)
309 module_sp = memory_module_sp;
310 }
311
313 if (module_sp.get()) {
314 // Ensure the Target has an architecture set in case
315 // we need it while processing this binary/eh_frame/debug info.
316 if (!target.GetArchitecture().IsValid())
317 target.SetArchitecture(module_sp->GetArchitecture());
318 target.GetImages().AppendIfNeeded(module_sp, false);
319
320 bool changed = false;
321 if (set_address_in_target) {
322 if (module_sp->GetObjectFile()) {
323 if (value != LLDB_INVALID_ADDRESS) {
324 LLDB_LOGF(log,
325 "DynamicLoader::LoadBinaryWithUUIDAndAddress Loading "
326 "binary %s UUID %s at %s 0x%" PRIx64,
327 name.str().c_str(), uuid.GetAsString().c_str(),
328 value_is_offset ? "offset" : "address", value);
329 module_sp->SetLoadAddress(target, value, value_is_offset, changed);
330 } else {
331 // No address/offset/slide, load the binary at file address,
332 // offset 0.
333 LLDB_LOGF(log,
334 "DynamicLoader::LoadBinaryWithUUIDAndAddress Loading "
335 "binary %s UUID %s at file address",
336 name.str().c_str(), uuid.GetAsString().c_str());
337 module_sp->SetLoadAddress(target, 0, true /* value_is_slide */,
338 changed);
339 }
340 } else {
341 // In-memory image, load at its true address, offset 0.
342 LLDB_LOGF(log,
343 "DynamicLoader::LoadBinaryWithUUIDAndAddress Loading binary "
344 "%s UUID %s from memory at address 0x%" PRIx64,
345 name.str().c_str(), uuid.GetAsString().c_str(), value);
346 module_sp->SetLoadAddress(target, 0, true /* value_is_slide */,
347 changed);
348 }
349 }
350
351 if (notify) {
352 ModuleList added_module;
353 added_module.Append(module_sp, false);
354 target.ModulesDidLoad(added_module);
355 }
356 } else {
357 if (force_symbol_search) {
359 s->Printf("Unable to find file");
360 if (!name.empty())
361 s->Printf(" %s", name.str().c_str());
362 if (uuid.IsValid())
363 s->Printf(" with UUID %s", uuid.GetAsString().c_str());
364 if (value != LLDB_INVALID_ADDRESS) {
365 if (value_is_offset)
366 s->Printf(" with slide 0x%" PRIx64, value);
367 else
368 s->Printf(" at address 0x%" PRIx64, value);
369 }
370 s->Printf("\n");
371 }
372 LLDB_LOGF(log,
373 "Unable to find binary %s with UUID %s and load it at "
374 "%s 0x%" PRIx64,
375 name.str().c_str(), uuid.GetAsString().c_str(),
376 value_is_offset ? "offset" : "address", value);
377 }
378
379 return module_sp;
380}
381
383 int size_in_bytes) {
385 uint64_t value =
386 m_process->ReadUnsignedIntegerFromMemory(addr, size_in_bytes, 0, error);
387 if (error.Fail())
388 return -1;
389 else
390 return (int64_t)value;
391}
392
395 addr_t value = m_process->ReadPointerFromMemory(addr, error);
396 if (error.Fail())
398 else
399 return value;
400}
401
403{
404 if (m_process)
405 m_process->LoadOperatingSystemPlugin(flush);
406}
static llvm::raw_ostream & error(Stream &strm)
static ModuleSP ReadUnnamedMemoryModule(Process *process, addr_t addr, llvm::StringRef name)
#define LLDB_LOGF(log,...)
Definition Log.h:390
#define LLDB_LOG_ERROR(log, error,...)
Definition Log.h:406
bool IsValid() const
Tests if this ArchSpec is valid.
Definition ArchSpec.h:452
lldb::StreamUP GetAsyncErrorStream()
void LoadOperatingSystemPlugin(bool flush)
void SetStopWhenImagesChange(bool stop)
Set whether the process should stop when images change.
lldb::ModuleSP FindModuleViaTarget(const ModuleSpec &module_spec)
Find a module in the target that matches the given module spec.
int64_t ReadUnsignedIntWithSizeInBytes(lldb::addr_t addr, int size_in_bytes)
lldb::addr_t ReadPointer(lldb::addr_t addr)
Process * m_process
The process that this dynamic loader plug-in is tracking.
void UpdateLoadedSectionsCommon(lldb::ModuleSP module, lldb::addr_t base_addr, bool base_addr_is_offset)
lldb::ModuleSP GetTargetExecutable()
Checks to see if the target module has changed, updates the target accordingly and returns the target...
bool GetStopWhenImagesChange() const
Get whether the process should stop when images change.
static lldb::ModuleSP LoadBinaryWithUUIDAndAddress(Process *process, llvm::StringRef name, UUID uuid, lldb::addr_t value, bool value_is_offset, bool force_symbol_search, bool notify, bool set_address_in_target, bool allow_memory_image_last_resort)
Find/load a binary into lldb given a UUID and the address where it is loaded in memory,...
virtual lldb::ModuleSP LoadModuleAtAddress(const lldb_private::FileSpec &file, lldb::addr_t link_map_addr, lldb::addr_t base_addr, bool base_addr_is_offset)
Locates or creates a module given by file and updates/loads the resulting module at the virtual base ...
virtual void UpdateLoadedSections(lldb::ModuleSP module, lldb::addr_t link_map_addr, lldb::addr_t base_addr, bool base_addr_is_offset)
Updates the load address of every allocatable section in module.
DynamicLoader(Process *process)
Construct with a process.
const lldb_private::SectionList * GetSectionListFromModule(const lldb::ModuleSP module) const
static DynamicLoader * FindPlugin(Process *process, llvm::StringRef plugin_name)
Find a dynamic loader plugin for a given process.
void UnloadSectionsCommon(const lldb::ModuleSP module)
virtual void UnloadSections(const lldb::ModuleSP module)
Removes the loaded sections from the target in module.
A file collection class.
A file utility class.
Definition FileSpec.h:57
static FileSystem & Instance()
A collection class for Module objects.
Definition ModuleList.h:125
static Status GetSharedModule(const ModuleSpec &module_spec, lldb::ModuleSP &module_sp, llvm::SmallVectorImpl< lldb::ModuleSP > *old_modules, bool *did_create_ptr, bool invoke_locate_callback=true)
lldb::ModuleSP FindFirstModule(const ModuleSpec &module_spec) const
Finds the first module whose file specification matches module_spec.
bool AppendIfNeeded(const lldb::ModuleSP &new_module, bool notify=true)
Append a module to the module list, if it is not already there.
void Append(const lldb::ModuleSP &module_sp, bool notify=true)
Append a module to the module list.
void SetLoadAddress(lldb::addr_t addr)
Set the load address of a module in process memory.
Definition ModuleSpec.h:126
FileSpec & GetFileSpec()
Definition ModuleSpec.h:57
FileSpec & GetSymbolFileSpec()
Definition ModuleSpec.h:81
void SetTarget(lldb::TargetSP target)
Set the target to be used when resolving a module.
Definition ModuleSpec.h:150
A plug-in interface definition class for object file parsers.
Definition ObjectFile.h:46
virtual SectionList * GetSectionList(bool update_module_section_list=true)
Gets the section list for the currently selected architecture (and object for archives).
static bool DownloadObjectAndSymbolFile(ModuleSpec &module_spec, Status &error, bool force_lookup=true, bool copy_executable=true)
static FileSpec LocateExecutableSymbolFile(const ModuleSpec &module_spec, const FileSpecList &default_search_paths, StatisticsMap &map)
static DynamicLoaderCreateInstance GetDynamicLoaderCreateCallbackForPluginName(llvm::StringRef name)
static ModuleSpec LocateExecutableObjectFile(const ModuleSpec &module_spec, StatisticsMap &map)
static llvm::SmallVector< DynamicLoaderCreateInstance > GetDynamicLoaderCreateCallbacks()
A plug-in interface definition class for debugging a process.
Definition Process.h:359
llvm::Expected< lldb::ModuleSP > ReadModuleFromMemory(const FileSpec &file_spec, lldb::addr_t header_addr, size_t size_to_read=512)
Creates and populates a module using an in-memory object file.
Definition Process.cpp:2793
Target & GetTarget()
Get the target object pointer for this module.
Definition Process.h:1258
A Progress indicator helper class.
Definition Progress.h:60
size_t GetSize() const
Definition Section.h:77
lldb::SectionSP GetSectionAtIndex(size_t idx) const
Definition Section.cpp:552
A class to count time for plugins.
Definition Statistics.h:94
An error handling class.
Definition Status.h:118
llvm::StringRef GetString() const
size_t PutHex64(uint64_t uvalue, lldb::ByteOrder byte_order=lldb::eByteOrderInvalid)
Definition Stream.cpp:307
void ModulesDidLoad(ModuleList &module_list)
This call may preload module symbols, and may do so in parallel depending on the following target set...
Definition Target.cpp:1941
Module * GetExecutableModulePointer()
Definition Target.cpp:1641
Debugger & GetDebugger() const
Definition Target.h:1326
bool SetSectionUnloaded(const lldb::SectionSP &section_sp)
Definition Target.cpp:3544
lldb::ModuleSP GetOrCreateModule(const ModuleSpec &module_spec, bool notify, Status *error_ptr=nullptr)
Find a binary on the system and return its Module, or return an existing Module that is already in th...
Definition Target.cpp:2441
bool SetArchitecture(const ArchSpec &arch_spec, bool set_platform=false, bool merge=true)
Set the architecture for this target.
Definition Target.cpp:1787
lldb::ModuleSP GetExecutableModule()
Gets the module for the main executable.
Definition Target.cpp:1625
static FileSpecList GetDefaultDebugFileSearchPaths()
Definition Target.cpp:2896
lldb::PlatformSP GetPlatform()
Definition Target.h:1971
const ModuleList & GetImages() const
Get accessor for the images for this process.
Definition Target.h:1243
const ArchSpec & GetArchitecture() const
Definition Target.h:1285
void SetExecutableModule(lldb::ModuleSP &module_sp, LoadDependentFiles load_dependent_files=eLoadDependentsDefault)
Set the main executable module.
Definition Target.cpp:1658
Represents UUID's of various sizes.
Definition UUID.h:27
std::string GetAsString(llvm::StringRef separator="-") const
Definition UUID.cpp:54
bool IsValid() const
Definition UUID.h:69
#define LLDB_INVALID_ADDRESS
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:339
DynamicLoader *(* DynamicLoaderCreateInstance)(Process *process, bool force)
std::shared_ptr< lldb_private::Platform > PlatformSP
std::shared_ptr< lldb_private::Section > SectionSP
uint64_t addr_t
Definition lldb-types.h:80
std::unique_ptr< lldb_private::Stream > StreamUP
std::shared_ptr< lldb_private::Module > ModuleSP