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 (uint32_t idx = 0;
51 (create_callback =
53 nullptr;
54 ++idx) {
55 std::unique_ptr<DynamicLoader> instance_up(
56 create_callback(process, false));
57 if (instance_up)
58 return instance_up.release();
59 }
60 }
61 return nullptr;
62}
63
64DynamicLoader::DynamicLoader(Process *process) : m_process(process) {}
65
66// Accessors to the global setting as to whether to stop at image (shared
67// library) loading/unloading.
68
71}
72
75}
76
78 Target &target = m_process->GetTarget();
79 ModuleSP executable = target.GetExecutableModule();
80
81 if (executable) {
82 if (FileSystem::Instance().Exists(executable->GetFileSpec())) {
83 ModuleSpec module_spec(executable->GetFileSpec(),
84 executable->GetArchitecture());
85 auto module_sp = std::make_shared<Module>(module_spec);
86
87 // Check if the executable has changed and set it to the target
88 // executable if they differ.
89 if (module_sp && module_sp->GetUUID().IsValid() &&
90 executable->GetUUID().IsValid()) {
91 if (module_sp->GetUUID() != executable->GetUUID())
92 executable.reset();
93 } else if (executable->FileHasChanged()) {
94 executable.reset();
95 }
96
97 if (!executable) {
98 executable = target.GetOrCreateModule(module_spec, true /* notify */);
99 if (executable.get() != target.GetExecutableModulePointer()) {
100 // Don't load dependent images since we are in dyld where we will
101 // know and find out about all images that are loaded
102 target.SetExecutableModule(executable, eLoadDependentsNo);
103 }
104 }
105 }
106 }
107 return executable;
108}
109
111 addr_t base_addr,
112 bool base_addr_is_offset) {
113 UpdateLoadedSectionsCommon(module, base_addr, base_addr_is_offset);
114}
115
117 addr_t base_addr,
118 bool base_addr_is_offset) {
119 bool changed;
120 module->SetLoadAddress(m_process->GetTarget(), base_addr, base_addr_is_offset,
121 changed);
122}
123
125 UnloadSectionsCommon(module);
126}
127
129 Target &target = m_process->GetTarget();
130 const SectionList *sections = GetSectionListFromModule(module);
131
132 assert(sections && "SectionList missing from unloaded module.");
133
134 const size_t num_sections = sections->GetSize();
135 for (size_t i = 0; i < num_sections; ++i) {
136 SectionSP section_sp(sections->GetSectionAtIndex(i));
137 target.SetSectionUnloaded(section_sp);
138 }
139}
140
141const SectionList *
143 SectionList *sections = nullptr;
144 if (module) {
145 ObjectFile *obj_file = module->GetObjectFile();
146 if (obj_file != nullptr) {
147 sections = obj_file->GetSectionList();
148 }
149 }
150 return sections;
151}
152
154 Target &target = m_process->GetTarget();
155 ModuleSpec module_spec(file, target.GetArchitecture());
156
157 if (ModuleSP module_sp = target.GetImages().FindFirstModule(module_spec))
158 return module_sp;
159
160 if (ModuleSP module_sp = target.GetOrCreateModule(module_spec, false))
161 return module_sp;
162
163 return nullptr;
164}
165
167 addr_t link_map_addr,
168 addr_t base_addr,
169 bool base_addr_is_offset) {
170 if (ModuleSP module_sp = FindModuleViaTarget(file)) {
171 UpdateLoadedSections(module_sp, link_map_addr, base_addr,
172 base_addr_is_offset);
173 return module_sp;
174 }
175
176 return nullptr;
177}
178
180 llvm::StringRef name) {
181 char namebuf[80];
182 if (name.empty()) {
183 snprintf(namebuf, sizeof(namebuf), "memory-image-0x%" PRIx64, addr);
184 name = namebuf;
185 }
186 return process->ReadModuleFromMemory(FileSpec(name), addr);
187}
188
190 Process *process, llvm::StringRef name, UUID uuid, addr_t value,
191 bool value_is_offset, bool force_symbol_search, bool notify,
192 bool set_address_in_target, bool allow_memory_image_last_resort) {
193 ModuleSP memory_module_sp;
194 ModuleSP module_sp;
195 PlatformSP platform_sp = process->GetTarget().GetPlatform();
196 Target &target = process->GetTarget();
198
199 StreamString prog_str;
200 if (!name.empty()) {
201 prog_str << name.str() << " ";
202 }
203 if (uuid.IsValid())
204 prog_str << uuid.GetAsString();
205 if (value_is_offset == 0 && value != LLDB_INVALID_ADDRESS) {
206 prog_str << "at 0x";
207 prog_str.PutHex64(value);
208 }
209
210 if (!uuid.IsValid() && !value_is_offset) {
211 memory_module_sp = ReadUnnamedMemoryModule(process, value, name);
212
213 if (memory_module_sp) {
214 uuid = memory_module_sp->GetUUID();
215 if (uuid.IsValid()) {
216 prog_str << " ";
217 prog_str << uuid.GetAsString();
218 }
219 }
220 }
221 ModuleSpec module_spec;
222 module_spec.GetUUID() = uuid;
223 FileSpec name_filespec(name);
224
225 if (uuid.IsValid()) {
226 Progress progress("Locating binary", prog_str.GetString().str());
227
228 // Has lldb already seen a module with this UUID?
229 // Or have external lookup enabled in DebugSymbols on macOS.
230 if (!module_sp)
231 error = ModuleList::GetSharedModule(module_spec, module_sp, nullptr,
232 nullptr, nullptr);
233
234 // Can lldb's symbol/executable location schemes
235 // find an executable and symbol file.
236 if (!module_sp) {
238 module_spec.GetSymbolFileSpec() =
239 PluginManager::LocateExecutableSymbolFile(module_spec, search_paths);
240 ModuleSpec objfile_module_spec =
242 module_spec.GetFileSpec() = objfile_module_spec.GetFileSpec();
243 if (FileSystem::Instance().Exists(module_spec.GetFileSpec()) &&
245 module_sp = std::make_shared<Module>(module_spec);
246 }
247 }
248
249 // If we haven't found a binary, or we don't have a SymbolFile, see
250 // if there is an external search tool that can find it.
251 if (!module_sp || !module_sp->GetSymbolFileFileSpec()) {
253 force_symbol_search);
254 if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) {
255 module_sp = std::make_shared<Module>(module_spec);
256 } else if (force_symbol_search && error.AsCString("") &&
257 error.AsCString("")[0] != '\0') {
258 target.GetDebugger().GetErrorStream() << error.AsCString();
259 }
260 }
261
262 // If we only found the executable, create a Module based on that.
263 if (!module_sp && FileSystem::Instance().Exists(module_spec.GetFileSpec()))
264 module_sp = std::make_shared<Module>(module_spec);
265 }
266
267 // If we couldn't find the binary anywhere else, as a last resort,
268 // read it out of memory.
269 if (allow_memory_image_last_resort && !module_sp.get() &&
270 value != LLDB_INVALID_ADDRESS && !value_is_offset) {
271 if (!memory_module_sp)
272 memory_module_sp = ReadUnnamedMemoryModule(process, value, name);
273 if (memory_module_sp)
274 module_sp = memory_module_sp;
275 }
276
278 if (module_sp.get()) {
279 // Ensure the Target has an architecture set in case
280 // we need it while processing this binary/eh_frame/debug info.
281 if (!target.GetArchitecture().IsValid())
282 target.SetArchitecture(module_sp->GetArchitecture());
283 target.GetImages().AppendIfNeeded(module_sp, false);
284
285 bool changed = false;
286 if (set_address_in_target) {
287 if (module_sp->GetObjectFile()) {
288 if (value != LLDB_INVALID_ADDRESS) {
289 LLDB_LOGF(log,
290 "DynamicLoader::LoadBinaryWithUUIDAndAddress Loading "
291 "binary %s UUID %s at %s 0x%" PRIx64,
292 name.str().c_str(), uuid.GetAsString().c_str(),
293 value_is_offset ? "offset" : "address", value);
294 module_sp->SetLoadAddress(target, value, value_is_offset, changed);
295 } else {
296 // No address/offset/slide, load the binary at file address,
297 // offset 0.
298 LLDB_LOGF(log,
299 "DynamicLoader::LoadBinaryWithUUIDAndAddress Loading "
300 "binary %s UUID %s at file address",
301 name.str().c_str(), uuid.GetAsString().c_str());
302 module_sp->SetLoadAddress(target, 0, true /* value_is_slide */,
303 changed);
304 }
305 } else {
306 // In-memory image, load at its true address, offset 0.
307 LLDB_LOGF(log,
308 "DynamicLoader::LoadBinaryWithUUIDAndAddress Loading binary "
309 "%s UUID %s from memory at address 0x%" PRIx64,
310 name.str().c_str(), uuid.GetAsString().c_str(), value);
311 module_sp->SetLoadAddress(target, 0, true /* value_is_slide */,
312 changed);
313 }
314 }
315
316 if (notify) {
317 ModuleList added_module;
318 added_module.Append(module_sp, false);
319 target.ModulesDidLoad(added_module);
320 }
321 } else {
322 if (force_symbol_search) {
323 Stream &s = target.GetDebugger().GetErrorStream();
324 s.Printf("Unable to find file");
325 if (!name.empty())
326 s.Printf(" %s", name.str().c_str());
327 if (uuid.IsValid())
328 s.Printf(" with UUID %s", uuid.GetAsString().c_str());
329 if (value != LLDB_INVALID_ADDRESS) {
330 if (value_is_offset)
331 s.Printf(" with slide 0x%" PRIx64, value);
332 else
333 s.Printf(" at address 0x%" PRIx64, value);
334 }
335 s.Printf("\n");
336 }
337 LLDB_LOGF(log,
338 "Unable to find binary %s with UUID %s and load it at "
339 "%s 0x%" PRIx64,
340 name.str().c_str(), uuid.GetAsString().c_str(),
341 value_is_offset ? "offset" : "address", value);
342 }
343
344 return module_sp;
345}
346
348 int size_in_bytes) {
350 uint64_t value =
351 m_process->ReadUnsignedIntegerFromMemory(addr, size_in_bytes, 0, error);
352 if (error.Fail())
353 return -1;
354 else
355 return (int64_t)value;
356}
357
361 if (error.Fail())
363 else
364 return value;
365}
366
368{
369 if (m_process)
371}
372
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:366
bool IsValid() const
Tests if this ArchSpec is valid.
Definition: ArchSpec.h:348
StreamFile & GetErrorStream()
Definition: Debugger.h:148
A plug-in interface definition class for dynamic loaders.
Definition: DynamicLoader.h:53
void LoadOperatingSystemPlugin(bool flush)
void SetStopWhenImagesChange(bool stop)
Set whether the process should stop when images change.
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)
lldb::ModuleSP FindModuleViaTarget(const FileSpec &file)
virtual void UnloadSections(const lldb::ModuleSP module)
Removes the loaded sections from the target in module.
A file collection class.
Definition: FileSpecList.h:85
A file utility class.
Definition: FileSpec.h:56
bool Exists(const FileSpec &file_spec) const
Returns whether the given file exists.
static FileSystem & Instance()
A collection class for Module objects.
Definition: ModuleList.h:103
lldb::ModuleSP FindFirstModule(const ModuleSpec &module_spec) const
Definition: ModuleList.cpp:626
bool AppendIfNeeded(const lldb::ModuleSP &new_module, bool notify=true)
Append a module to the module list, if it is not already there.
Definition: ModuleList.cpp:280
static Status GetSharedModule(const ModuleSpec &module_spec, lldb::ModuleSP &module_sp, const FileSpecList *module_search_paths_ptr, llvm::SmallVectorImpl< lldb::ModuleSP > *old_modules, bool *did_create_ptr, bool always_create=false)
Definition: ModuleList.cpp:789
void Append(const lldb::ModuleSP &module_sp, bool notify=true)
Append a module to the module list.
Definition: ModuleList.cpp:247
FileSpec & GetFileSpec()
Definition: ModuleSpec.h:53
FileSpec & GetSymbolFileSpec()
Definition: ModuleSpec.h:77
A plug-in interface definition class for object file parsers.
Definition: ObjectFile.h:44
virtual SectionList * GetSectionList(bool update_module_section_list=true)
Gets the section list for the currently selected architecture (and object for archives).
Definition: ObjectFile.cpp:599
static bool DownloadObjectAndSymbolFile(ModuleSpec &module_spec, Status &error, bool force_lookup=true, bool copy_executable=true)
static ModuleSpec LocateExecutableObjectFile(const ModuleSpec &module_spec)
static DynamicLoaderCreateInstance GetDynamicLoaderCreateCallbackAtIndex(uint32_t idx)
static DynamicLoaderCreateInstance GetDynamicLoaderCreateCallbackForPluginName(llvm::StringRef name)
static FileSpec LocateExecutableSymbolFile(const ModuleSpec &module_spec, const FileSpecList &default_search_paths)
void SetStopOnSharedLibraryEvents(bool stop)
Definition: Process.cpp:302
bool GetStopOnSharedLibraryEvents() const
Definition: Process.cpp:296
A plug-in interface definition class for debugging a process.
Definition: Process.h:341
void LoadOperatingSystemPlugin(bool flush)
Definition: Process.cpp:2620
uint64_t ReadUnsignedIntegerFromMemory(lldb::addr_t load_addr, size_t byte_size, uint64_t fail_value, Status &error)
Reads an unsigned integer of the specified byte size from process memory.
Definition: Process.cpp:2234
lldb::addr_t ReadPointerFromMemory(lldb::addr_t vm_addr, Status &error)
Definition: Process.cpp:2256
lldb::ModuleSP ReadModuleFromMemory(const FileSpec &file_spec, lldb::addr_t header_addr, size_t size_to_read=512)
Definition: Process.cpp:2542
Target & GetTarget()
Get the target object pointer for this module.
Definition: Process.h:1279
A Progress indicator helper class.
Definition: Progress.h:59
size_t GetSize() const
Definition: Section.h:75
lldb::SectionSP GetSectionAtIndex(size_t idx) const
Definition: Section.cpp:544
An error handling class.
Definition: Status.h:44
llvm::StringRef GetString() const
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
size_t PutHex64(uint64_t uvalue, lldb::ByteOrder byte_order=lldb::eByteOrderInvalid)
Definition: Stream.cpp:299
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:134
void ModulesDidLoad(ModuleList &module_list)
Definition: Target.cpp:1690
Module * GetExecutableModulePointer()
Definition: Target.cpp:1436
Debugger & GetDebugger()
Definition: Target.h:1064
bool SetSectionUnloaded(const lldb::SectionSP &section_sp)
Definition: Target.cpp:3163
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:2158
bool SetArchitecture(const ArchSpec &arch_spec, bool set_platform=false, bool merge=true)
Set the architecture for this target.
Definition: Target.cpp:1538
lldb::ModuleSP GetExecutableModule()
Gets the module for the main executable.
Definition: Target.cpp:1422
static FileSpecList GetDefaultDebugFileSearchPaths()
Definition: Target.cpp:2601
lldb::PlatformSP GetPlatform()
Definition: Target.h:1444
const ModuleList & GetImages() const
Get accessor for the images for this process.
Definition: Target.h:981
const ArchSpec & GetArchitecture() const
Definition: Target.h:1023
void SetExecutableModule(lldb::ModuleSP &module_sp, LoadDependentFiles load_dependent_files=eLoadDependentsDefault)
Set the main executable module.
Definition: Target.cpp:1471
std::string GetAsString(llvm::StringRef separator="-") const
Definition: UUID.cpp:49
bool IsValid() const
Definition: UUID.h:69
#define LLDB_INVALID_ADDRESS
Definition: lldb-defines.h:82
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:331
DynamicLoader *(* DynamicLoaderCreateInstance)(Process *process, bool force)
Definition: SBAddress.h:15
std::shared_ptr< lldb_private::Platform > PlatformSP
Definition: lldb-forward.h:385
std::shared_ptr< lldb_private::Section > SectionSP
Definition: lldb-forward.h:413
uint64_t addr_t
Definition: lldb-types.h:80
std::shared_ptr< lldb_private::Module > ModuleSP
Definition: lldb-forward.h:370