[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"
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#include "llvm/Support/Error.h"
30
31#include <memory>
32#include <string>
33
34#include <cassert>
35
36using namespace lldb;
37using namespace lldb_private;
38
40 llvm::StringRef plugin_name) {
41 DynamicLoaderCreateInstance create_callback = nullptr;
42 if (!plugin_name.empty()) {
43 create_callback =
45 if (create_callback) {
46 std::unique_ptr<DynamicLoader> instance_up(
47 create_callback(process, true));
48 if (instance_up)
49 return instance_up.release();
50 }
51 } else {
52 for (auto create_callback :
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
64
65// Accessors to the global setting as to whether to stop at image (shared
66// library) loading/unloading.
67
69 return m_process->GetStopOnSharedLibraryEvents();
70}
71
73 m_process->SetStopOnSharedLibraryEvents(stop);
74}
75
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 // If we're a coredump and we already have a main executable, we don't
86 // need to reload the module list that target already has
87 if (!m_process->IsLiveDebugSession()) {
88 return executable;
89 }
90 // Check if the executable has changed and set it to the target
91 // executable if they differ.
92 if (module_sp && module_sp->GetUUID().IsValid() &&
93 executable->GetUUID().IsValid()) {
94 if (module_sp->GetUUID() != executable->GetUUID())
95 executable.reset();
96 } else if (executable->FileHasChanged()) {
97 executable.reset();
98 }
99
100 if (!executable) {
101 executable = target.GetOrCreateModule(module_spec, true /* notify */);
102 if (executable.get() != target.GetExecutableModulePointer()) {
103 // Don't load dependent images since we are in dyld where we will
104 // know and find out about all images that are loaded
105 target.SetExecutableModule(executable, eLoadDependentsNo);
106 }
107 }
108 }
109 }
110 return executable;
111}
112
114 addr_t base_addr,
115 bool base_addr_is_offset) {
116 UpdateLoadedSectionsCommon(module, base_addr, base_addr_is_offset);
117}
118
120 addr_t base_addr,
121 bool base_addr_is_offset) {
122 bool changed;
123 module->SetLoadAddress(m_process->GetTarget(), base_addr, base_addr_is_offset,
124 changed);
125}
126
128 UnloadSectionsCommon(module);
129}
130
132 Target &target = m_process->GetTarget();
133 const SectionList *sections = GetSectionListFromModule(module);
134
135 assert(sections && "SectionList missing from unloaded module.");
136
137 const size_t num_sections = sections->GetSize();
138 for (size_t i = 0; i < num_sections; ++i) {
139 SectionSP section_sp(sections->GetSectionAtIndex(i));
140 target.SetSectionUnloaded(section_sp);
141 }
142}
143
144const SectionList *
146 SectionList *sections = nullptr;
147 if (module) {
148 ObjectFile *obj_file = module->GetObjectFile();
149 if (obj_file != nullptr) {
150 sections = obj_file->GetSectionList();
151 }
152 }
153 return sections;
154}
155
157 ModuleSpec module_spec(spec);
158 Target &target = m_process->GetTarget();
159 // The process may be able to augment the module_spec with a UUID.
160 if (!module_spec.GetUUID().IsValid())
161 m_process->FindModuleUUID(module_spec);
162 if (ModuleSP module_sp = target.GetImages().FindFirstModule(module_spec))
163 return module_sp;
164
165 if (ModuleSP module_sp =
166 target.GetOrCreateModule(module_spec, /*notify=*/false))
167 return module_sp;
168
169 return nullptr;
170}
171
173 addr_t link_map_addr,
174 addr_t base_addr,
175 bool base_addr_is_offset) {
176 Target &target = m_process->GetTarget();
177 ModuleSpec module_spec(file, target.GetArchitecture());
178 module_spec.SetLoadAddress(base_addr);
179 ModuleSP module_sp = FindModuleViaTarget(module_spec);
180 // We have a core file, try to load the image from memory if we didn't find
181 // the module.
182 if (!module_sp && !m_process->IsLiveDebugSession()) {
183 llvm::Expected<ModuleSP> memory_module_sp_or_err =
184 m_process->ReadModuleFromMemory(file, base_addr);
185 if (auto err = memory_module_sp_or_err.takeError())
187 "Failed to read module from memory: {0}");
188 else {
189 module_sp = *memory_module_sp_or_err;
190 m_process->GetTarget().GetImages().AppendIfNeeded(module_sp, false);
191 }
192 }
193 if (module_sp)
194 UpdateLoadedSections(module_sp, link_map_addr, base_addr,
195 base_addr_is_offset);
196 return module_sp;
197}
198
200 llvm::StringRef name) {
201 char namebuf[80];
202 if (name.empty()) {
203 snprintf(namebuf, sizeof(namebuf), "memory-image-0x%" PRIx64, addr);
204 name = namebuf;
205 }
206 llvm::Expected<ModuleSP> module_sp_or_err =
207 process->ReadModuleFromMemory(FileSpec(name), addr);
208 if (auto err = module_sp_or_err.takeError()) {
210 "Failed to read module from memory: {0}");
211 return {};
212 }
213 return *module_sp_or_err;
214}
215
216static std::string
218 StreamString desc;
219 if (!bin_spec.name.empty())
220 desc << bin_spec.name << " ";
221 if (bin_spec.uuid.IsValid())
222 desc << bin_spec.uuid.GetAsString();
223 if (!bin_spec.value_is_offset && bin_spec.value != LLDB_INVALID_ADDRESS) {
224 desc << " at 0x";
225 desc.PutHex64(bin_spec.value);
226 }
227 return desc.GetString().str();
228}
229
230static std::string
232 StreamString msg;
233 msg << "Unable to find file";
234 if (!bin_spec.name.empty())
235 msg << " " << bin_spec.name;
236 if (bin_spec.uuid.IsValid())
237 msg << " with UUID " << bin_spec.uuid.GetAsString();
238 if (bin_spec.value != LLDB_INVALID_ADDRESS) {
239 if (bin_spec.value_is_offset)
240 msg.Printf(" with slide 0x%" PRIx64, bin_spec.value);
241 else
242 msg.Printf(" at address 0x%" PRIx64, bin_spec.value);
243 }
244 return msg.GetString().str();
245}
246
247/// Search for a binary with a known UUID, and create a module for it.
248///
249/// Does not mutate the Target, but does read from it, and reaches the global
250/// shared module list, the symbol locator plugins, and a locate module callback
251/// the user may have installed.
252static void SearchForBinary(Target &target, DynamicLoader::BinarySpec &bin_spec,
253 const FileSpecList &search_paths) {
254 ModuleSpec module_spec;
255 module_spec.SetTarget(target.shared_from_this());
256 module_spec.GetUUID() = bin_spec.uuid;
257 FileSpec name_filespec(bin_spec.name);
258 if (FileSystem::Instance().Exists(name_filespec))
259 module_spec.GetFileSpec() = name_filespec;
260
261 // Has lldb already seen a module with this UUID?
262 // Or have external lookup enabled in DebugSymbols on macOS.
263 Status error = ModuleList::GetSharedModule(module_spec, bin_spec.module_sp,
264 nullptr, nullptr);
265
266 // Can lldb's symbol/executable location schemes find an executable and
267 // symbol file.
268 if (!bin_spec.module_sp) {
269 StatisticsMap symbol_locator_map;
271 module_spec, search_paths, symbol_locator_map);
273 module_spec, symbol_locator_map);
274 module_spec.GetFileSpec() = objfile_module_spec.GetFileSpec();
275 if (FileSystem::Instance().Exists(module_spec.GetFileSpec()) &&
276 FileSystem::Instance().Exists(module_spec.GetSymbolFileSpec())) {
277 bin_spec.module_sp = std::make_shared<Module>(module_spec);
278 }
279
280 if (bin_spec.module_sp) {
281 bin_spec.module_sp->GetSymbolLocatorStatistics().merge(
282 symbol_locator_map);
283 }
284 }
285
286 // If we haven't found a binary, or we don't have a SymbolFile, see
287 // if there is an external search tool that can find it.
288 if (!bin_spec.module_sp || !bin_spec.module_sp->GetSymbolFileFileSpec()) {
290 bin_spec.force_symbol_search);
291 if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) {
292 bin_spec.module_sp = std::make_shared<Module>(module_spec);
293 } else if (bin_spec.force_symbol_search && error.Fail()) {
294 bin_spec.error = std::move(error);
295 }
296 }
297
298 // If we only found the executable, create a Module based on that.
299 if (!bin_spec.module_sp &&
300 FileSystem::Instance().Exists(module_spec.GetFileSpec()))
301 bin_spec.module_sp = std::make_shared<Module>(module_spec);
302}
303
304static void FindBinaryUUIDInMemory(Process *process,
305 DynamicLoader::BinarySpec &bin_spec) {
306 bin_spec.memory_module_sp =
307 ReadUnnamedMemoryModule(process, bin_spec.value, bin_spec.name);
308 if (bin_spec.memory_module_sp)
309 bin_spec.uuid = bin_spec.memory_module_sp->GetUUID();
310}
311
313 Process *process, llvm::MutableArrayRef<BinarySpec> bin_specs) {
314 Target &target = process->GetTarget();
316
317 for (BinarySpec &bin_spec : bin_specs) {
318 if (!bin_spec.uuid.IsValid() && !bin_spec.value_is_offset)
319 FindBinaryUUIDInMemory(process, bin_spec);
320 if (!bin_spec.uuid.IsValid())
321 continue;
322 Progress progress("Locating binary", GetBinaryDescription(bin_spec));
323 SearchForBinary(target, bin_spec, search_paths);
324 }
325}
326
327llvm::Expected<ModuleSP>
329 Target &target = process->GetTarget();
330
331 // The error belongs to this function now: every path below either reports it
332 // or folds it into the failure.
333 llvm::Error search_error = bin_spec.error.takeError();
334
335 // If we couldn't find the binary anywhere else, as a last resort,
336 // read it out of memory.
337 if (bin_spec.allow_memory_image_last_resort && !bin_spec.module_sp &&
338 bin_spec.value != LLDB_INVALID_ADDRESS && !bin_spec.value_is_offset) {
339 if (!bin_spec.memory_module_sp)
340 bin_spec.memory_module_sp =
341 ReadUnnamedMemoryModule(process, bin_spec.value, bin_spec.name);
342 if (bin_spec.memory_module_sp)
343 bin_spec.module_sp = bin_spec.memory_module_sp;
344 }
345
347 if (!bin_spec.module_sp) {
348 std::string message = GetBinaryNotFoundMessage(bin_spec);
349 LLDB_LOG(log, "{0}", message);
350 llvm::Error error = llvm::createStringError(message);
351 if (search_error)
352 return llvm::joinErrors(std::move(search_error), std::move(error));
353 return std::move(error);
354 }
355
356 // A binary was found, but a symbol server may still have had something to say
357 // about its symbols. Name the binary: a symbol locator's error is not
358 // required to identify what it was asked to look for.
359 if (search_error)
361 << GetBinaryDescription(bin_spec) << ": "
362 << llvm::toString(std::move(search_error)) << "\n";
363
364 // Ensure the Target has an architecture set in case
365 // we need it while processing this binary/eh_frame/debug info.
366 if (!target.GetArchitecture().IsValid())
367 target.SetArchitecture(bin_spec.module_sp->GetArchitecture());
368 target.GetImages().AppendIfNeeded(bin_spec.module_sp, false);
369
370 bool changed = false;
371 if (bin_spec.set_address_in_target) {
372 if (bin_spec.module_sp->GetObjectFile()) {
373 if (bin_spec.value != LLDB_INVALID_ADDRESS) {
374 LLDB_LOGF(log,
375 "DynamicLoader::LoadBinaryInTarget Loading "
376 "binary %s UUID %s at %s 0x%" PRIx64,
377 bin_spec.name.c_str(), bin_spec.uuid.GetAsString().c_str(),
378 bin_spec.value_is_offset ? "offset" : "address",
379 bin_spec.value);
380 bin_spec.module_sp->SetLoadAddress(target, bin_spec.value,
381 bin_spec.value_is_offset, changed);
382 } else {
383 // No address/offset/slide, load the binary at file address,
384 // offset 0.
385 LLDB_LOGF(log,
386 "DynamicLoader::LoadBinaryInTarget Loading "
387 "binary %s UUID %s at file address",
388 bin_spec.name.c_str(), bin_spec.uuid.GetAsString().c_str());
389 bin_spec.module_sp->SetLoadAddress(target, 0, true /* value_is_slide */,
390 changed);
391 }
392 } else {
393 // In-memory image, load at its true address, offset 0.
394 LLDB_LOGF(log,
395 "DynamicLoader::LoadBinaryInTarget Loading binary "
396 "%s UUID %s from memory at address 0x%" PRIx64,
397 bin_spec.name.c_str(), bin_spec.uuid.GetAsString().c_str(),
398 bin_spec.value);
399 bin_spec.module_sp->SetLoadAddress(target, 0, true /* value_is_slide */,
400 changed);
401 }
402 }
403
404 if (bin_spec.notify) {
405 ModuleList added_module;
406 added_module.Append(bin_spec.module_sp, false);
407 target.ModulesDidLoad(added_module);
408 }
409
410 return bin_spec.module_sp;
411}
412
413llvm::Expected<ModuleSP>
415 LocateBinaries(process, bin_spec);
416 return LoadBinaryInTarget(process, bin_spec);
417}
418
420 int size_in_bytes) {
422 uint64_t value =
423 m_process->ReadUnsignedIntegerFromMemory(addr, size_in_bytes, 0, error);
424 if (error.Fail())
425 return -1;
426 else
427 return (int64_t)value;
428}
429
432 addr_t value = m_process->ReadPointerFromMemory(addr, error);
433 if (error.Fail())
435 else
436 return value;
437}
438
440{
441 if (m_process)
442 m_process->LoadOperatingSystemPlugin(flush);
443}
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
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:555
A class to count time for plugins.
Definition Statistics.h:94
An error handling class.
Definition Status.h:118
llvm::Error takeError()
Definition Status.h:170
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
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
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.