LLDB mainline
DynamicLoaderAcceleratorGDBRemote.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
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
11#include "lldb/Core/Module.h"
13#include "lldb/Core/Section.h"
14#include "lldb/Target/Target.h"
19#include "lldb/Utility/Log.h"
20
21using namespace lldb;
22using namespace lldb_private;
24
26
29 bool force) {
30 // The library list comes from the accelerator's GDB server.
31 if (!force ||
33 return nullptr;
34 return new DynamicLoaderAcceleratorGDBRemote(process);
35}
36
40
44
48
52
55
56 // CreateInstance ensures that m_process is a ProcessGDBRemote.
57 ProcessGDBRemote *accelerator_process =
58 static_cast<ProcessGDBRemote *>(m_process);
59 // Check jLLDBSettings to determine whether to send the library request on
60 // the accelerator GDB remote connection or on the native connection, which
61 // forwards it to the selected LLDBServerAcceleratorPlugin.
62 ProcessGDBRemote *send_process = accelerator_process;
64 args.full = full;
65
66 Target &target = m_process->GetTarget();
67 std::shared_ptr<TargetGroupCPUAndAccelerators> group_sp =
69 TargetSP native_target_sp = group_sp ? group_sp->GetCPUTarget() : nullptr;
70 ProcessSP native_process_sp =
71 native_target_sp ? native_target_sp->GetProcessSP() : nullptr;
72
73 std::optional<LLDBSettings> process_settings =
74 accelerator_process->GetGDBRemote().GetLLDBSettings();
75 if (process_settings && !process_settings->send_dyld_packet_to_accelerator) {
76 if (process_settings->accelerator_plugin_name.empty()) {
77 LLDB_LOG(log, "cannot route dynamic-loader request through the native "
78 "connection without an accelerator plugin name");
79 return false;
80 }
81
82 if (!native_process_sp || native_process_sp->GetPluginName() !=
84 LLDB_LOG(log, "cannot route dynamic-loader request through the native "
85 "connection: no native gdb-remote process");
86 return false;
87 }
88
89 send_process = static_cast<ProcessGDBRemote *>(native_process_sp.get());
90 args.plugin_name = process_settings->accelerator_plugin_name;
91 }
92
93 ModuleList loaded_module_list;
94 std::optional<AcceleratorDynamicLoaderResponse> response =
96 args);
97 if (!response) {
98 LLDB_LOG(log, "failed to get dynamic loader info from the GDB server");
99 return false;
100 }
101
102 for (const AcceleratorDynamicLoaderLibraryInfo &info :
103 response->library_infos) {
104 std::shared_ptr<DataBufferHeap> data_sp;
105 if (info.load && info.native_memory_address && info.native_memory_size) {
106 LLDB_LOG(log, "reading \"{0}\" from native memory at {1:x}",
107 info.pathname, *info.native_memory_address);
108 if (native_process_sp) {
109 data_sp = std::make_shared<DataBufferHeap>(*info.native_memory_size, 0);
111 const size_t bytes_read = native_process_sp->ReadMemory(
112 *info.native_memory_address, data_sp->GetBytes(),
113 data_sp->GetByteSize(), error);
114 if (bytes_read != *info.native_memory_size) {
115 LLDB_LOG(log,
116 "failed to read \"{0}\" from native memory at {1:x}: {2}",
118 data_sp.reset();
119 }
120 } else {
121 LLDB_LOG(log, "no native process available to read \"{0}\" at {1:x}",
122 info.pathname, *info.native_memory_address);
123 }
124 }
125
126 UUID uuid;
127 if (info.uuid_str)
128 uuid.SetFromStringRef(*info.uuid_str);
129
130 DataExtractorSP extractor_sp;
131 if (data_sp)
132 extractor_sp = std::make_shared<DataExtractor>(data_sp);
133 ModuleSpec module_spec(FileSpec(info.pathname), uuid, extractor_sp);
134
135 // Restrict the object to a slice of the containing file, when provided.
136 if (info.file_offset)
137 module_spec.SetObjectOffset(*info.file_offset);
138 if (info.file_size)
139 module_spec.SetObjectSize(*info.file_size);
140
141 if (!info.load) {
142 ModuleList matching_module_list;
143 target.GetImages().FindModules(module_spec, matching_module_list);
144 matching_module_list.ForEach(
145 [this](const ModuleSP &module_sp) -> IterationAction {
146 UnloadSections(module_sp);
148 });
149 target.ModulesDidUnload(matching_module_list,
150 /*delete_locations=*/false);
151 continue;
152 }
153
154 ModuleSP module_sp =
155 target.GetOrCreateModule(module_spec, /*notify=*/false);
156 if (!module_sp)
157 continue;
158
159 bool changed = false;
160 if (info.load_address) {
161 module_sp->SetLoadAddress(target, *info.load_address,
162 /*value_is_offset=*/true, changed);
163 } else if (!info.loaded_sections.empty()) {
164 for (const AcceleratorSectionInfo &sect : info.loaded_sections) {
165 if (sect.names.empty())
166 continue;
167 SectionSP section_sp;
168 for (const std::string &name : sect.names) {
169 ConstString section_name(name);
170 if (section_sp)
171 section_sp =
172 section_sp->GetChildren().FindSectionByName(section_name);
173 else
174 section_sp =
175 module_sp->GetSectionList()->FindSectionByName(section_name);
176 if (!section_sp)
177 break;
178 }
179 if (section_sp)
180 changed |= target.SetSectionLoadAddress(section_sp, sect.load_address,
181 /*warn_multiple=*/true);
182 }
183 } else {
184 // No slide: load at the file addresses.
185 module_sp->SetLoadAddress(target, 0, /*value_is_offset=*/true, changed);
186 }
187
188 if (changed)
189 loaded_module_list.AppendIfNeeded(module_sp);
190 }
191
192 target.ModulesDidLoad(loaded_module_list);
193 return true;
194}
195
200
202 return Status::FromErrorString("can't load images on accelerator targets");
203}
204
209
213
214llvm::StringRef
216 return "Dynamic loader plug-in that gets shared library loads/unloads from "
217 "an lldb-server accelerator plugin.";
218}
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition Log.h:375
#define LLDB_PLUGIN_DEFINE(PluginName)
Dynamic loader for accelerator targets whose library changes are reported by the remote server instea...
void DidLaunch() override
Called after launching a process.
bool HandleStopReasonDynamicLoader() override
Allow the dynamic loader to handle a request to update loaded modules.
void DidAttach() override
Called after attaching a process.
lldb::ThreadPlanSP GetStepThroughTrampolinePlan(lldb_private::Thread &thread, bool stop_others) override
Provides a plan to step through the dynamic loader trampoline for the current state of thread.
DynamicLoaderAcceleratorGDBRemote(lldb_private::Process *process)
bool LoadModulesFromGDBServer(bool full)
Returns true if the server answered the packet.
static lldb_private::DynamicLoader * CreateInstance(lldb_private::Process *process, bool force)
lldb_private::Status CanLoadImage() override
Ask if it is ok to try and load or unload an shared library (image).
A uniqued constant string class.
Definition ConstString.h:40
A plug-in interface definition class for dynamic loaders.
Process * m_process
The process that this dynamic loader plug-in is tracking.
DynamicLoader(Process *process)
Construct with a process.
virtual void UnloadSections(const lldb::ModuleSP module)
Removes the loaded sections from the target in module.
A file utility class.
Definition FileSpec.h:56
A collection class for Module objects.
Definition ModuleList.h:128
bool AppendIfNeeded(const lldb::ModuleSP &new_module, bool notify=true)
Append a module to the module list, if it is not already there.
void FindModules(const ModuleSpec &module_spec, ModuleList &matching_module_list) const
Finds modules whose file specification matches module_spec.
void ForEach(std::function< IterationAction(const lldb::ModuleSP &module_sp)> const &callback) const
Applies 'callback' to each module in this ModuleList.
void SetObjectSize(uint64_t object_size)
Definition ModuleSpec.h:119
void SetObjectOffset(uint64_t object_offset)
Definition ModuleSpec.h:113
virtual llvm::StringRef GetPluginName()=0
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ABICreateInstance create_callback)
static bool UnregisterPlugin(ABICreateInstance create_callback)
A plug-in interface definition class for debugging a process.
Definition Process.h:369
An error handling class.
Definition Status.h:118
static Status FromErrorString(const char *str)
Definition Status.h:141
A group that accepts a CPU target as its first member, followed by accelerator targets.
Definition TargetGroup.h:97
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:1979
lldb::ModuleSP GetOrCreateModule(const ModuleSpec &module_spec, bool notify, Status *error_ptr=nullptr, bool invoke_symbol_locators=true)
Find a binary on the system and return its Module, or return an existing Module that is already in th...
Definition Target.cpp:2488
void ModulesDidUnload(ModuleList &module_list, bool delete_locations)
Definition Target.cpp:2023
const ModuleList & GetImages() const
Get accessor for the images for this process.
Definition Target.h:1283
std::shared_ptr< GroupT > GetFirstTargetGroupOfType() const
Return the first target group that can be cast to GroupT.
Definition Target.h:2085
bool SetSectionLoadAddress(const lldb::SectionSP &section, lldb::addr_t load_addr, bool warn_multiple=false)
Definition Target.cpp:3536
Represents UUID's of various sizes.
Definition UUID.h:27
bool SetFromStringRef(llvm::StringRef str)
Definition UUID.cpp:101
std::optional< LLDBSettings > GetLLDBSettings()
Return LLDB-specific settings for this GDB-remote process.
std::optional< AcceleratorDynamicLoaderResponse > GetAcceleratorDynamicLoaderLibraryInfos(const AcceleratorDynamicLoaderArgs &args)
Returns std::nullopt if the packet failed or the response did not parse.
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
IterationAction
Useful for callbacks whose return type indicates whether to continue iteration or short-circuit.
std::shared_ptr< lldb_private::ThreadPlan > ThreadPlanSP
std::shared_ptr< lldb_private::Process > ProcessSP
std::shared_ptr< lldb_private::Section > SectionSP
std::shared_ptr< lldb_private::Target > TargetSP
std::shared_ptr< lldb_private::DataExtractor > DataExtractorSP
std::shared_ptr< lldb_private::Module > ModuleSP
Arguments for the jAcceleratorPluginGetDynamicLoaderLibraryInfo packet.
bool full
If false, return only what changed since the last query.
std::string pathname
Path to the object file, or a unique name identifying the module in the target when it has no file on...
std::optional< std::string > uuid_str
UUID of the object file, when the plugin knows it.
std::optional< uint64_t > native_memory_address
Where the image can be read in the native process, meaning the host process driving the accelerator,...
std::vector< AcceleratorSectionInfo > loaded_sections
Used when sections load at independent addresses.
std::optional< uint64_t > file_offset
Slice of pathname holding the object file, when embedded in a container.
std::optional< uint64_t > load_address
Slides the whole object file.
std::vector< std::string > names
A list of section names.
uint64_t load_address
Address the section named by names is loaded at.