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
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 Target &target = m_process->GetTarget();
159 ModuleSpec module_spec(file, target.GetArchitecture());
160 if (UUID uuid = m_process->FindModuleUUID(file.GetPath())) {
161 // Process may be able to augment the module_spec with UUID, e.g. ELF core.
162 module_spec.GetUUID() = uuid;
163 }
164
165 if (ModuleSP module_sp = target.GetImages().FindFirstModule(module_spec))
166 return module_sp;
167
168 if (ModuleSP module_sp =
169 target.GetOrCreateModule(module_spec, /*notify=*/false))
170 return module_sp;
171
172 return nullptr;
173}
174
176 addr_t link_map_addr,
177 addr_t base_addr,
178 bool base_addr_is_offset) {
179 ModuleSP module_sp = FindModuleViaTarget(file);
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 module_sp = m_process->ReadModuleFromMemory(file, base_addr);
184 m_process->GetTarget().GetImages().AppendIfNeeded(module_sp, false);
185 }
186 if (module_sp)
187 UpdateLoadedSections(module_sp, link_map_addr, base_addr,
188 base_addr_is_offset);
189 return module_sp;
190}
191
193 llvm::StringRef name) {
194 char namebuf[80];
195 if (name.empty()) {
196 snprintf(namebuf, sizeof(namebuf), "memory-image-0x%" PRIx64, addr);
197 name = namebuf;
198 }
199 return process->ReadModuleFromMemory(FileSpec(name), addr);
200}
201
203 Process *process, llvm::StringRef name, UUID uuid, addr_t value,
204 bool value_is_offset, bool force_symbol_search, bool notify,
205 bool set_address_in_target, bool allow_memory_image_last_resort) {
206 ModuleSP memory_module_sp;
207 ModuleSP module_sp;
208 PlatformSP platform_sp = process->GetTarget().GetPlatform();
209 Target &target = process->GetTarget();
211
212 StreamString prog_str;
213 if (!name.empty()) {
214 prog_str << name.str() << " ";
215 }
216 if (uuid.IsValid())
217 prog_str << uuid.GetAsString();
218 if (value_is_offset == 0 && value != LLDB_INVALID_ADDRESS) {
219 prog_str << " at 0x";
220 prog_str.PutHex64(value);
221 }
222
223 if (!uuid.IsValid() && !value_is_offset) {
224 memory_module_sp = ReadUnnamedMemoryModule(process, value, name);
225
226 if (memory_module_sp) {
227 uuid = memory_module_sp->GetUUID();
228 if (uuid.IsValid()) {
229 prog_str << " ";
230 prog_str << uuid.GetAsString();
231 }
232 }
233 }
234 ModuleSpec module_spec;
235 module_spec.SetTarget(target.shared_from_this());
236 module_spec.GetUUID() = uuid;
237 FileSpec name_filespec(name);
238 if (FileSystem::Instance().Exists(name_filespec))
239 module_spec.GetFileSpec() = name_filespec;
240
241 if (uuid.IsValid()) {
242 Progress progress("Locating binary", prog_str.GetString().str());
243
244 // Has lldb already seen a module with this UUID?
245 // Or have external lookup enabled in DebugSymbols on macOS.
246 if (!module_sp)
247 error =
248 ModuleList::GetSharedModule(module_spec, module_sp, nullptr, nullptr);
249
250 // Can lldb's symbol/executable location schemes
251 // find an executable and symbol file.
252 if (!module_sp) {
254 StatisticsMap symbol_locator_map;
255 module_spec.GetSymbolFileSpec() =
256 PluginManager::LocateExecutableSymbolFile(module_spec, search_paths,
257 symbol_locator_map);
258 ModuleSpec objfile_module_spec =
260 symbol_locator_map);
261 module_spec.GetFileSpec() = objfile_module_spec.GetFileSpec();
262 if (FileSystem::Instance().Exists(module_spec.GetFileSpec()) &&
263 FileSystem::Instance().Exists(module_spec.GetSymbolFileSpec())) {
264 module_sp = std::make_shared<Module>(module_spec);
265 }
266
267 if (module_sp) {
268 module_sp->GetSymbolLocatorStatistics().merge(symbol_locator_map);
269 }
270 }
271
272 // If we haven't found a binary, or we don't have a SymbolFile, see
273 // if there is an external search tool that can find it.
274 if (!module_sp || !module_sp->GetSymbolFileFileSpec()) {
276 force_symbol_search);
277 if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) {
278 module_sp = std::make_shared<Module>(module_spec);
279 } else if (force_symbol_search && error.AsCString("") &&
280 error.AsCString("")[0] != '\0') {
281 *target.GetDebugger().GetAsyncErrorStream() << error.AsCString();
282 }
283 }
284
285 // If we only found the executable, create a Module based on that.
286 if (!module_sp && FileSystem::Instance().Exists(module_spec.GetFileSpec()))
287 module_sp = std::make_shared<Module>(module_spec);
288 }
289
290 // If we couldn't find the binary anywhere else, as a last resort,
291 // read it out of memory.
292 if (allow_memory_image_last_resort && !module_sp.get() &&
293 value != LLDB_INVALID_ADDRESS && !value_is_offset) {
294 if (!memory_module_sp)
295 memory_module_sp = ReadUnnamedMemoryModule(process, value, name);
296 if (memory_module_sp)
297 module_sp = memory_module_sp;
298 }
299
301 if (module_sp.get()) {
302 // Ensure the Target has an architecture set in case
303 // we need it while processing this binary/eh_frame/debug info.
304 if (!target.GetArchitecture().IsValid())
305 target.SetArchitecture(module_sp->GetArchitecture());
306 target.GetImages().AppendIfNeeded(module_sp, false);
307
308 bool changed = false;
309 if (set_address_in_target) {
310 if (module_sp->GetObjectFile()) {
311 if (value != LLDB_INVALID_ADDRESS) {
312 LLDB_LOGF(log,
313 "DynamicLoader::LoadBinaryWithUUIDAndAddress Loading "
314 "binary %s UUID %s at %s 0x%" PRIx64,
315 name.str().c_str(), uuid.GetAsString().c_str(),
316 value_is_offset ? "offset" : "address", value);
317 module_sp->SetLoadAddress(target, value, value_is_offset, changed);
318 } else {
319 // No address/offset/slide, load the binary at file address,
320 // offset 0.
321 LLDB_LOGF(log,
322 "DynamicLoader::LoadBinaryWithUUIDAndAddress Loading "
323 "binary %s UUID %s at file address",
324 name.str().c_str(), uuid.GetAsString().c_str());
325 module_sp->SetLoadAddress(target, 0, true /* value_is_slide */,
326 changed);
327 }
328 } else {
329 // In-memory image, load at its true address, offset 0.
330 LLDB_LOGF(log,
331 "DynamicLoader::LoadBinaryWithUUIDAndAddress Loading binary "
332 "%s UUID %s from memory at address 0x%" PRIx64,
333 name.str().c_str(), uuid.GetAsString().c_str(), value);
334 module_sp->SetLoadAddress(target, 0, true /* value_is_slide */,
335 changed);
336 }
337 }
338
339 if (notify) {
340 ModuleList added_module;
341 added_module.Append(module_sp, false);
342 target.ModulesDidLoad(added_module);
343 }
344 } else {
345 if (force_symbol_search) {
347 s->Printf("Unable to find file");
348 if (!name.empty())
349 s->Printf(" %s", name.str().c_str());
350 if (uuid.IsValid())
351 s->Printf(" with UUID %s", uuid.GetAsString().c_str());
352 if (value != LLDB_INVALID_ADDRESS) {
353 if (value_is_offset)
354 s->Printf(" with slide 0x%" PRIx64, value);
355 else
356 s->Printf(" at address 0x%" PRIx64, value);
357 }
358 s->Printf("\n");
359 }
360 LLDB_LOGF(log,
361 "Unable to find binary %s with UUID %s and load it at "
362 "%s 0x%" PRIx64,
363 name.str().c_str(), uuid.GetAsString().c_str(),
364 value_is_offset ? "offset" : "address", value);
365 }
366
367 return module_sp;
368}
369
371 int size_in_bytes) {
373 uint64_t value =
374 m_process->ReadUnsignedIntegerFromMemory(addr, size_in_bytes, 0, error);
375 if (error.Fail())
376 return -1;
377 else
378 return (int64_t)value;
379}
380
383 addr_t value = m_process->ReadPointerFromMemory(addr, error);
384 if (error.Fail())
386 else
387 return value;
388}
389
391{
392 if (m_process)
393 m_process->LoadOperatingSystemPlugin(flush);
394}
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:376
bool IsValid() const
Tests if this ArchSpec is valid.
Definition ArchSpec.h:366
lldb::StreamUP GetAsyncErrorStream()
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)
Find a module in the target that matches the given file.
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
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition FileSpec.cpp:374
static FileSystem & Instance()
A collection class for Module objects.
Definition ModuleList.h:101
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.
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:141
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 GetDynamicLoaderCreateCallbackAtIndex(uint32_t idx)
static DynamicLoaderCreateInstance GetDynamicLoaderCreateCallbackForPluginName(llvm::StringRef name)
static ModuleSpec LocateExecutableObjectFile(const ModuleSpec &module_spec, StatisticsMap &map)
A plug-in interface definition class for debugging a process.
Definition Process.h:354
lldb::ModuleSP ReadModuleFromMemory(const FileSpec &file_spec, lldb::addr_t header_addr, size_t size_to_read=512)
Definition Process.cpp:2622
Target & GetTarget()
Get the target object pointer for this module.
Definition Process.h:1267
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:557
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:1858
Module * GetExecutableModulePointer()
Definition Target.cpp:1540
Debugger & GetDebugger() const
Definition Target.h:1194
bool SetSectionUnloaded(const lldb::SectionSP &section_sp)
Definition Target.cpp:3383
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:2351
bool SetArchitecture(const ArchSpec &arch_spec, bool set_platform=false, bool merge=true)
Set the architecture for this target.
Definition Target.cpp:1704
lldb::ModuleSP GetExecutableModule()
Gets the module for the main executable.
Definition Target.cpp:1524
static FileSpecList GetDefaultDebugFileSearchPaths()
Definition Target.cpp:2801
lldb::PlatformSP GetPlatform()
Definition Target.h:1648
const ModuleList & GetImages() const
Get accessor for the images for this process.
Definition Target.h:1111
const ArchSpec & GetArchitecture() const
Definition Target.h:1153
void SetExecutableModule(lldb::ModuleSP &module_sp, LoadDependentFiles load_dependent_files=eLoadDependentsDefault)
Set the main executable module.
Definition Target.cpp:1575
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:332
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