[Go to site: main page, start]

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"
22#include "lldb/Target/Process.h"
23#include "lldb/Target/Target.h"
26#include "lldb/Utility/Log.h"
28
29#include "llvm/ADT/StringRef.h"
30#include "llvm/Support/Error.h"
31
32#include <memory>
33#include <string>
34
35#include <cassert>
36
37using namespace lldb;
38using namespace lldb_private;
39
41 llvm::StringRef plugin_name) {
42 DynamicLoaderCreateInstance create_callback = nullptr;
43 if (!plugin_name.empty()) {
44 create_callback =
46 if (create_callback) {
47 std::unique_ptr<DynamicLoader> instance_up(
48 create_callback(process, true));
49 if (instance_up)
50 return instance_up.release();
51 }
52 } else {
53 for (auto create_callback :
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
65
66// Accessors to the global setting as to whether to stop at image (shared
67// library) loading/unloading.
68
70 return m_process->GetStopOnSharedLibraryEvents();
71}
72
74 m_process->SetStopOnSharedLibraryEvents(stop);
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 // If we're a coredump and we already have a main executable, we don't
87 // need to reload the module list that target already has
88 if (!m_process->IsLiveDebugSession()) {
89 return executable;
90 }
91 // Check if the executable has changed and set it to the target
92 // executable if they differ.
93 if (module_sp && module_sp->GetUUID().IsValid() &&
94 executable->GetUUID().IsValid()) {
95 if (module_sp->GetUUID() != executable->GetUUID())
96 executable.reset();
97 } else if (executable->FileHasChanged()) {
98 executable.reset();
99 }
100
101 if (!executable) {
102 executable = target.GetOrCreateModule(module_spec, true /* notify */);
103 if (executable.get() != target.GetExecutableModulePointer()) {
104 // Don't load dependent images since we are in dyld where we will
105 // know and find out about all images that are loaded
106 target.SetExecutableModule(executable, eLoadDependentsNo);
107 }
108 }
109 }
110 }
111 return executable;
112}
113
115 addr_t base_addr,
116 bool base_addr_is_offset) {
117 UpdateLoadedSectionsCommon(module, base_addr, base_addr_is_offset);
118}
119
121 addr_t base_addr,
122 bool base_addr_is_offset) {
123 bool changed;
124 module->SetLoadAddress(m_process->GetTarget(), base_addr, base_addr_is_offset,
125 changed);
126}
127
129 UnloadSectionsCommon(module);
130}
131
133 Target &target = m_process->GetTarget();
134 const SectionList *sections = GetSectionListFromModule(module);
135
136 assert(sections && "SectionList missing from unloaded module.");
137
138 const size_t num_sections = sections->GetSize();
139 for (size_t i = 0; i < num_sections; ++i) {
140 SectionSP section_sp(sections->GetSectionAtIndex(i));
141 target.SetSectionUnloaded(section_sp);
142 }
143}
144
145const SectionList *
147 SectionList *sections = nullptr;
148 if (module) {
149 ObjectFile *obj_file = module->GetObjectFile();
150 if (obj_file != nullptr) {
151 sections = obj_file->GetSectionList();
152 }
153 }
154 return sections;
155}
156
158 ModuleSpec module_spec(spec);
159 Target &target = m_process->GetTarget();
160 // The process may be able to augment the module_spec with a UUID.
161 if (!module_spec.GetUUID().IsValid())
162 m_process->FindModuleUUID(module_spec);
163 if (ModuleSP module_sp = target.GetImages().FindFirstModule(module_spec))
164 return module_sp;
165
166 if (ModuleSP module_sp =
167 target.GetOrCreateModule(module_spec, /*notify=*/false))
168 return module_sp;
169
170 return nullptr;
171}
172
174 addr_t link_map_addr,
175 addr_t base_addr,
176 bool base_addr_is_offset) {
177 Target &target = m_process->GetTarget();
178 ModuleSpec module_spec(file, target.GetArchitecture());
179 module_spec.SetLoadAddress(base_addr);
180 ModuleSP module_sp = FindModuleViaTarget(module_spec);
181 // We have a core file, try to load the image from memory if we didn't find
182 // the module.
183 if (!module_sp && !m_process->IsLiveDebugSession()) {
184 llvm::Expected<ModuleSP> memory_module_sp_or_err =
185 m_process->ReadModuleFromMemory(file, base_addr);
186 if (auto err = memory_module_sp_or_err.takeError())
188 "Failed to read module from memory: {0}");
189 else {
190 module_sp = *memory_module_sp_or_err;
191 m_process->GetTarget().GetImages().AppendIfNeeded(module_sp, false);
192 }
193 }
194 if (module_sp)
195 UpdateLoadedSections(module_sp, link_map_addr, base_addr,
196 base_addr_is_offset);
197 return module_sp;
198}
199
201 llvm::StringRef name) {
202 char namebuf[80];
203 if (name.empty()) {
204 snprintf(namebuf, sizeof(namebuf), "memory-image-0x%" PRIx64, addr);
205 name = namebuf;
206 }
207 llvm::Expected<ModuleSP> module_sp_or_err =
208 process->ReadModuleFromMemory(FileSpec(name), addr);
209 if (auto err = module_sp_or_err.takeError()) {
211 "Failed to read module from memory: {0}");
212 return {};
213 }
214 return *module_sp_or_err;
215}
216
217static std::string
219 StreamString desc;
220 if (!bin_spec.name.empty())
221 desc << bin_spec.name << " ";
222 if (bin_spec.uuid.IsValid())
223 desc << bin_spec.uuid.GetAsString();
224 if (!bin_spec.value_is_offset && bin_spec.value != LLDB_INVALID_ADDRESS) {
225 desc << " at 0x";
226 desc.PutHex64(bin_spec.value);
227 }
228 return desc.GetString().str();
229}
230
231static std::string
233 StreamString msg;
234 msg << "Unable to find file";
235 if (!bin_spec.name.empty())
236 msg << " " << bin_spec.name;
237 if (bin_spec.uuid.IsValid())
238 msg << " with UUID " << bin_spec.uuid.GetAsString();
239 if (bin_spec.value != LLDB_INVALID_ADDRESS) {
240 if (bin_spec.value_is_offset)
241 msg.Printf(" with slide 0x%" PRIx64, bin_spec.value);
242 else
243 msg.Printf(" at address 0x%" PRIx64, bin_spec.value);
244 }
245 return msg.GetString().str();
246}
247
248/// Search for a binary with a known UUID, and create a module for it.
249///
250/// Does not mutate the Target, but does read from it, and reaches the global
251/// shared module list, the symbol locator plugins, and a locate module callback
252/// the user may have installed.
253static void SearchForBinary(Target &target, DynamicLoader::BinarySpec &bin_spec,
254 const FileSpecList &search_paths) {
255 ModuleSpec module_spec;
256 module_spec.SetTarget(target.shared_from_this());
257 module_spec.GetUUID() = bin_spec.uuid;
258 FileSpec name_filespec(bin_spec.name);
259 if (FileSystem::Instance().Exists(name_filespec))
260 module_spec.GetFileSpec() = name_filespec;
261
262 // Has lldb already seen a module with this UUID? A module whose symbols are
263 // already in hand is the answer, and searching would only find them again.
264 // Without them the search still has something to add.
265 ModuleList::GetSharedModule(module_spec, bin_spec.module_sp, nullptr, nullptr,
266 /*invoke_locate_callback=*/true,
267 /*invoke_symbol_locators=*/false);
268 if (bin_spec.module_sp && bin_spec.module_sp->GetSymbolFileFileSpec())
269 return;
270
271 // Search for the binary and its symbols.
273 request.module_spec = module_spec;
274 request.platform = target.GetPlatform();
275 request.external_lookup = bin_spec.force_symbol_search;
276
277 llvm::Expected<SymbolLocator::Result> located =
278 SymbolLocator::Locate(request, search_paths);
279 if (!located) {
280 // This function's caller names the binary it could not find, so a plain
281 // miss needs nothing added to it. An explanation from a symbol server does.
282 llvm::Error error = located.takeError();
284 llvm::consumeError(std::move(error));
285 else
286 bin_spec.error = Status::FromError(std::move(error));
287 return;
288 }
289
290 // A binary was found. Its symbols are another matter, and the caller reports
291 // that in its own order.
292 if (located->symbol_error)
293 bin_spec.error = Status::FromError(std::move(*located->symbol_error));
294
295 // Create a module for what was found, sharing it with any other Target that
296 // asks for the same binary. The module is not registered with this Target
297 // until LoadBinaryInTarget. The locators have run, so don't run them again.
298 ModuleSP located_module_sp;
299 ModuleList::GetSharedModule(located->module_spec, located_module_sp, nullptr,
300 nullptr, /*invoke_locate_callback=*/false,
301 /*invoke_symbol_locators=*/false);
302
303 // A located binary always yields a module, whatever ObjectFile makes of the
304 // file, because the caller has nowhere else to record what the search found.
305 if (!located_module_sp)
306 located_module_sp = std::make_shared<Module>(located->module_spec);
307
308 // Published only now, so that a search that came up empty leaves whatever the
309 // shared module list had in hand.
310 bin_spec.module_sp = std::move(located_module_sp);
311 bin_spec.module_sp->GetSymbolLocatorStatistics().merge(located->statistics);
312}
313
314static void FindBinaryUUIDInMemory(Process *process,
315 DynamicLoader::BinarySpec &bin_spec) {
316 bin_spec.memory_module_sp =
317 ReadUnnamedMemoryModule(process, bin_spec.value, bin_spec.name);
318 if (bin_spec.memory_module_sp)
319 bin_spec.uuid = bin_spec.memory_module_sp->GetUUID();
320}
321
323 Process *process, llvm::MutableArrayRef<BinarySpec> bin_specs) {
324 Target &target = process->GetTarget();
326
327 for (BinarySpec &bin_spec : bin_specs) {
328 if (!bin_spec.uuid.IsValid() && !bin_spec.value_is_offset)
329 FindBinaryUUIDInMemory(process, bin_spec);
330 if (!bin_spec.uuid.IsValid())
331 continue;
332 Progress progress("Locating binary", GetBinaryDescription(bin_spec));
333 SearchForBinary(target, bin_spec, search_paths);
334 }
335}
336
337llvm::Expected<ModuleSP>
339 Target &target = process->GetTarget();
340
341 // The error belongs to this function now: every path below either reports it
342 // or folds it into the failure.
343 llvm::Error search_error = bin_spec.error.takeError();
344
345 // If we couldn't find the binary anywhere else, as a last resort,
346 // read it out of memory.
347 if (bin_spec.allow_memory_image_last_resort && !bin_spec.module_sp &&
348 bin_spec.value != LLDB_INVALID_ADDRESS && !bin_spec.value_is_offset) {
349 if (!bin_spec.memory_module_sp)
350 bin_spec.memory_module_sp =
351 ReadUnnamedMemoryModule(process, bin_spec.value, bin_spec.name);
352 if (bin_spec.memory_module_sp)
353 bin_spec.module_sp = bin_spec.memory_module_sp;
354 }
355
357 if (!bin_spec.module_sp) {
358 std::string message = GetBinaryNotFoundMessage(bin_spec);
359 LLDB_LOG(log, "{0}", message);
360 llvm::Error error = llvm::createStringError(message);
361 if (search_error)
362 return llvm::joinErrors(std::move(search_error), std::move(error));
363 return std::move(error);
364 }
365
366 // A binary was found, but a symbol server may still have had something to say
367 // about its symbols. Name the binary: a symbol locator's error is not
368 // required to identify what it was asked to look for.
369 if (search_error)
371 << GetBinaryDescription(bin_spec) << ": "
372 << llvm::toString(std::move(search_error)) << "\n";
373
374 // Ensure the Target has an architecture set in case
375 // we need it while processing this binary/eh_frame/debug info.
376 if (!target.GetArchitecture().IsValid())
377 target.SetArchitecture(bin_spec.module_sp->GetArchitecture());
378 target.GetImages().AppendIfNeeded(bin_spec.module_sp, false);
379
380 bool changed = false;
381 if (bin_spec.set_address_in_target) {
382 if (bin_spec.module_sp->GetObjectFile()) {
383 if (bin_spec.value != LLDB_INVALID_ADDRESS) {
384 LLDB_LOGF(log,
385 "DynamicLoader::LoadBinaryInTarget Loading "
386 "binary %s UUID %s at %s 0x%" PRIx64,
387 bin_spec.name.c_str(), bin_spec.uuid.GetAsString().c_str(),
388 bin_spec.value_is_offset ? "offset" : "address",
389 bin_spec.value);
390 bin_spec.module_sp->SetLoadAddress(target, bin_spec.value,
391 bin_spec.value_is_offset, changed);
392 } else {
393 // No address/offset/slide, load the binary at file address,
394 // offset 0.
395 LLDB_LOGF(log,
396 "DynamicLoader::LoadBinaryInTarget Loading "
397 "binary %s UUID %s at file address",
398 bin_spec.name.c_str(), bin_spec.uuid.GetAsString().c_str());
399 bin_spec.module_sp->SetLoadAddress(target, 0, true /* value_is_slide */,
400 changed);
401 }
402 } else {
403 // In-memory image, load at its true address, offset 0.
404 LLDB_LOGF(log,
405 "DynamicLoader::LoadBinaryInTarget Loading binary "
406 "%s UUID %s from memory at address 0x%" PRIx64,
407 bin_spec.name.c_str(), bin_spec.uuid.GetAsString().c_str(),
408 bin_spec.value);
409 bin_spec.module_sp->SetLoadAddress(target, 0, true /* value_is_slide */,
410 changed);
411 }
412 }
413
414 if (bin_spec.notify) {
415 ModuleList added_module;
416 added_module.Append(bin_spec.module_sp, false);
417 target.ModulesDidLoad(added_module);
418 }
419
420 return bin_spec.module_sp;
421}
422
423llvm::Expected<ModuleSP>
425 LocateBinaries(process, bin_spec);
426 return LoadBinaryInTarget(process, bin_spec);
427}
428
430 int size_in_bytes) {
432 uint64_t value =
433 m_process->ReadUnsignedIntegerFromMemory(addr, size_in_bytes, 0, error);
434 if (error.Fail())
435 return -1;
436 else
437 return (int64_t)value;
438}
439
442 addr_t value = m_process->ReadPointerFromMemory(addr, error);
443 if (error.Fail())
445 else
446 return value;
447}
448
450{
451 if (m_process)
452 m_process->LoadOperatingSystemPlugin(flush);
453}
static llvm::raw_ostream & error(Stream &strm)
static ModuleSP ReadUnnamedMemoryModule(Process *process, addr_t addr, llvm::StringRef name)
static void SearchForBinary(Target &target, DynamicLoader::BinarySpec &bin_spec, const FileSpecList &search_paths)
Search for a binary with a known UUID, and create a module for it.
static void FindBinaryUUIDInMemory(Process *process, DynamicLoader::BinarySpec &bin_spec)
static std::string GetBinaryDescription(const DynamicLoader::BinarySpec &bin_spec)
static std::string GetBinaryNotFoundMessage(const DynamicLoader::BinarySpec &bin_spec)
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition Log.h:375
#define LLDB_LOGF(log,...)
Definition Log.h:389
#define LLDB_LOG_ERROR(log, error,...)
Definition Log.h:405
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)
static llvm::Expected< lldb::ModuleSP > LocateAndLoadBinary(Process *process, BinarySpec &bin_spec)
Find a binary and load it into a Target.
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 void LocateBinaries(Process *process, llvm::MutableArrayRef< BinarySpec > bin_specs)
Search for a batch of binaries, without mutating the Target.
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.
static llvm::Expected< lldb::ModuleSP > LoadBinaryInTarget(Process *process, BinarySpec &bin_spec)
Add a binary that LocateBinaries searched for to the Target, and set its load address.
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:56
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, bool invoke_symbol_locators=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
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 DynamicLoaderCreateInstance GetDynamicLoaderCreateCallbackForPluginName(llvm::StringRef name)
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:555
An error handling class.
Definition Status.h:118
llvm::Error takeError()
Definition Status.h:170
static Status FromError(llvm::Error error)
Avoid using this in new code. Migrate APIs to llvm::Expected instead.
Definition Status.cpp:136
llvm::StringRef GetString() const
size_t PutHex64(uint64_t uvalue, lldb::ByteOrder byte_order=lldb::eByteOrderInvalid)
Definition Stream.cpp:307
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition Stream.cpp:134
A binary was not found and nothing could say why.
static llvm::Expected< Result > Locate(const Request &request, const FileSpecList &search_paths)
Find a binary and, if possible, its symbols.
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:1940
Module * GetExecutableModulePointer()
Definition Target.cpp:1640
Debugger & GetDebugger() const
Definition Target.h:1330
bool SetSectionUnloaded(const lldb::SectionSP &section_sp)
Definition Target.cpp:3551
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:2449
bool SetArchitecture(const ArchSpec &arch_spec, bool set_platform=false, bool merge=true)
Set the architecture for this target.
Definition Target.cpp:1786
lldb::ModuleSP GetExecutableModule()
Gets the module for the main executable.
Definition Target.cpp:1624
static FileSpecList GetDefaultDebugFileSearchPaths()
Definition Target.cpp:2901
lldb::PlatformSP GetPlatform()
Definition Target.h:1973
const ModuleList & GetImages() const
Get accessor for the images for this process.
Definition Target.h:1247
const ArchSpec & GetArchitecture() const
Definition Target.h:1289
void SetExecutableModule(lldb::ModuleSP &module_sp, LoadDependentFiles load_dependent_files=eLoadDependentsDefault)
Set the main executable module.
Definition Target.cpp:1657
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:338
DynamicLoader *(* DynamicLoaderCreateInstance)(Process *process, bool force)
std::shared_ptr< lldb_private::Section > SectionSP
uint64_t addr_t
Definition lldb-types.h:80
std::shared_ptr< lldb_private::Module > ModuleSP
A binary to find and load into a Target.
lldb::addr_t value
Address where the binary should be loaded, or read out of memory.
bool allow_memory_image_last_resort
If no better binary image can be found, allow reading the binary out of memory, if possible,...
UUID uuid
UUID of the binary to be loaded.
lldb::ModuleSP memory_module_sp
The binary as it was read out of the process' memory, if it had to be, so that it is not read a secon...
std::string name
Name of the binary, if available.
lldb::ModuleSP module_sp
The module found for the binary, or empty if it was not found.
Status error
What an external symbol server had to say about this binary.
bool force_symbol_search
Allow the search to do a possibly expensive external search for the ObjectFile and/or SymbolFile.
bool set_address_in_target
Whether the address of the binary should be set in the Target if it is added.
bool notify
Whether ModulesDidLoad should be called once the binary has been added to the Target.
bool value_is_offset
A flag indicating that value is an address, or an offset to be applied to the file addresses.
One binary to search for.
lldb::PlatformSP platform
A platform that may know where the binary is.
ModuleSpec module_spec
What to look for.
bool external_lookup
Allow contacting an external symbol server when the local searches come up empty.