1 //===-- RemoteAwarePlatform.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
9 #include "lldb/Target/RemoteAwarePlatform.h"
10 #include "lldb/Core/Module.h"
11 #include "lldb/Core/ModuleList.h"
12 #include "lldb/Core/ModuleSpec.h"
13 #include "lldb/Host/FileSystem.h"
14 #include "lldb/Host/Host.h"
15 #include "lldb/Host/HostInfo.h"
16 #include "lldb/Utility/StreamString.h"
17
18 using namespace lldb_private;
19 using namespace lldb;
20
GetModuleSpec(const FileSpec & module_file_spec,const ArchSpec & arch,ModuleSpec & module_spec)21 bool RemoteAwarePlatform::GetModuleSpec(const FileSpec &module_file_spec,
22 const ArchSpec &arch,
23 ModuleSpec &module_spec) {
24 if (m_remote_platform_sp)
25 return m_remote_platform_sp->GetModuleSpec(module_file_spec, arch,
26 module_spec);
27
28 return false;
29 }
30
ResolveExecutable(const ModuleSpec & module_spec,ModuleSP & exe_module_sp,const FileSpecList * module_search_paths_ptr)31 Status RemoteAwarePlatform::ResolveExecutable(
32 const ModuleSpec &module_spec, ModuleSP &exe_module_sp,
33 const FileSpecList *module_search_paths_ptr) {
34 Status error;
35 // Nothing special to do here, just use the actual file and architecture
36
37 char exe_path[PATH_MAX];
38 ModuleSpec resolved_module_spec(module_spec);
39
40 if (IsHost()) {
41 // If we have "ls" as the exe_file, resolve the executable location based
42 // on the current path variables
43 if (!FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec())) {
44 resolved_module_spec.GetFileSpec().GetPath(exe_path, sizeof(exe_path));
45 resolved_module_spec.GetFileSpec().SetFile(exe_path,
46 FileSpec::Style::native);
47 FileSystem::Instance().Resolve(resolved_module_spec.GetFileSpec());
48 }
49
50 if (!FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec()))
51 FileSystem::Instance().ResolveExecutableLocation(
52 resolved_module_spec.GetFileSpec());
53
54 // Resolve any executable within a bundle on MacOSX
55 Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec());
56
57 if (FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec()))
58 error.Clear();
59 else {
60 const uint32_t permissions = FileSystem::Instance().GetPermissions(
61 resolved_module_spec.GetFileSpec());
62 if (permissions && (permissions & eFilePermissionsEveryoneR) == 0)
63 error.SetErrorStringWithFormat(
64 "executable '%s' is not readable",
65 resolved_module_spec.GetFileSpec().GetPath().c_str());
66 else
67 error.SetErrorStringWithFormat(
68 "unable to find executable for '%s'",
69 resolved_module_spec.GetFileSpec().GetPath().c_str());
70 }
71 } else {
72 if (m_remote_platform_sp) {
73 return GetCachedExecutable(resolved_module_spec, exe_module_sp,
74 module_search_paths_ptr);
75 }
76
77 // We may connect to a process and use the provided executable (Don't use
78 // local $PATH).
79
80 // Resolve any executable within a bundle on MacOSX
81 Host::ResolveExecutableInBundle(resolved_module_spec.GetFileSpec());
82
83 if (FileSystem::Instance().Exists(resolved_module_spec.GetFileSpec()))
84 error.Clear();
85 else
86 error.SetErrorStringWithFormat("the platform is not currently "
87 "connected, and '%s' doesn't exist in "
88 "the system root.",
89 exe_path);
90 }
91
92 if (error.Success()) {
93 if (resolved_module_spec.GetArchitecture().IsValid()) {
94 error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
95 module_search_paths_ptr, nullptr, nullptr);
96 if (error.Fail()) {
97 // If we failed, it may be because the vendor and os aren't known. If
98 // that is the case, try setting them to the host architecture and give
99 // it another try.
100 llvm::Triple &module_triple =
101 resolved_module_spec.GetArchitecture().GetTriple();
102 bool is_vendor_specified =
103 (module_triple.getVendor() != llvm::Triple::UnknownVendor);
104 bool is_os_specified =
105 (module_triple.getOS() != llvm::Triple::UnknownOS);
106 if (!is_vendor_specified || !is_os_specified) {
107 const llvm::Triple &host_triple =
108 HostInfo::GetArchitecture(HostInfo::eArchKindDefault).GetTriple();
109
110 if (!is_vendor_specified)
111 module_triple.setVendorName(host_triple.getVendorName());
112 if (!is_os_specified)
113 module_triple.setOSName(host_triple.getOSName());
114
115 error = ModuleList::GetSharedModule(resolved_module_spec,
116 exe_module_sp, module_search_paths_ptr, nullptr, nullptr);
117 }
118 }
119
120 // TODO find out why exe_module_sp might be NULL
121 if (error.Fail() || !exe_module_sp || !exe_module_sp->GetObjectFile()) {
122 exe_module_sp.reset();
123 error.SetErrorStringWithFormat(
124 "'%s' doesn't contain the architecture %s",
125 resolved_module_spec.GetFileSpec().GetPath().c_str(),
126 resolved_module_spec.GetArchitecture().GetArchitectureName());
127 }
128 } else {
129 // No valid architecture was specified, ask the platform for the
130 // architectures that we should be using (in the correct order) and see
131 // if we can find a match that way
132 StreamString arch_names;
133 llvm::ListSeparator LS;
134 ArchSpec process_host_arch;
135 for (const ArchSpec &arch :
136 GetSupportedArchitectures(process_host_arch)) {
137 resolved_module_spec.GetArchitecture() = arch;
138 error = ModuleList::GetSharedModule(resolved_module_spec, exe_module_sp,
139 module_search_paths_ptr, nullptr, nullptr);
140 // Did we find an executable using one of the
141 if (error.Success()) {
142 if (exe_module_sp && exe_module_sp->GetObjectFile())
143 break;
144 else
145 error.SetErrorToGenericError();
146 }
147
148 arch_names << LS << arch.GetArchitectureName();
149 }
150
151 if (error.Fail() || !exe_module_sp) {
152 if (FileSystem::Instance().Readable(
153 resolved_module_spec.GetFileSpec())) {
154 error.SetErrorStringWithFormatv(
155 "'{0}' doesn't contain any '{1}' platform architectures: {2}",
156 resolved_module_spec.GetFileSpec(), GetPluginName(),
157 arch_names.GetData());
158 } else {
159 error.SetErrorStringWithFormat(
160 "'%s' is not readable",
161 resolved_module_spec.GetFileSpec().GetPath().c_str());
162 }
163 }
164 }
165 }
166
167 return error;
168 }
169
RunShellCommand(llvm::StringRef command,const FileSpec & working_dir,int * status_ptr,int * signo_ptr,std::string * command_output,const Timeout<std::micro> & timeout)170 Status RemoteAwarePlatform::RunShellCommand(
171 llvm::StringRef command, const FileSpec &working_dir, int *status_ptr,
172 int *signo_ptr, std::string *command_output,
173 const Timeout<std::micro> &timeout) {
174 return RunShellCommand(llvm::StringRef(), command, working_dir, status_ptr,
175 signo_ptr, command_output, timeout);
176 }
177
RunShellCommand(llvm::StringRef shell,llvm::StringRef command,const FileSpec & working_dir,int * status_ptr,int * signo_ptr,std::string * command_output,const Timeout<std::micro> & timeout)178 Status RemoteAwarePlatform::RunShellCommand(
179 llvm::StringRef shell, llvm::StringRef command, const FileSpec &working_dir,
180 int *status_ptr, int *signo_ptr, std::string *command_output,
181 const Timeout<std::micro> &timeout) {
182 if (m_remote_platform_sp)
183 return m_remote_platform_sp->RunShellCommand(shell, command, working_dir,
184 status_ptr, signo_ptr,
185 command_output, timeout);
186 return Platform::RunShellCommand(shell, command, working_dir, status_ptr,
187 signo_ptr, command_output, timeout);
188 }
189
MakeDirectory(const FileSpec & file_spec,uint32_t file_permissions)190 Status RemoteAwarePlatform::MakeDirectory(const FileSpec &file_spec,
191 uint32_t file_permissions) {
192 if (m_remote_platform_sp)
193 return m_remote_platform_sp->MakeDirectory(file_spec, file_permissions);
194 return Platform::MakeDirectory(file_spec, file_permissions);
195 }
196
GetFilePermissions(const FileSpec & file_spec,uint32_t & file_permissions)197 Status RemoteAwarePlatform::GetFilePermissions(const FileSpec &file_spec,
198 uint32_t &file_permissions) {
199 if (m_remote_platform_sp)
200 return m_remote_platform_sp->GetFilePermissions(file_spec,
201 file_permissions);
202 return Platform::GetFilePermissions(file_spec, file_permissions);
203 }
204
SetFilePermissions(const FileSpec & file_spec,uint32_t file_permissions)205 Status RemoteAwarePlatform::SetFilePermissions(const FileSpec &file_spec,
206 uint32_t file_permissions) {
207 if (m_remote_platform_sp)
208 return m_remote_platform_sp->SetFilePermissions(file_spec,
209 file_permissions);
210 return Platform::SetFilePermissions(file_spec, file_permissions);
211 }
212
OpenFile(const FileSpec & file_spec,File::OpenOptions flags,uint32_t mode,Status & error)213 lldb::user_id_t RemoteAwarePlatform::OpenFile(const FileSpec &file_spec,
214 File::OpenOptions flags,
215 uint32_t mode, Status &error) {
216 if (m_remote_platform_sp)
217 return m_remote_platform_sp->OpenFile(file_spec, flags, mode, error);
218 return Platform::OpenFile(file_spec, flags, mode, error);
219 }
220
CloseFile(lldb::user_id_t fd,Status & error)221 bool RemoteAwarePlatform::CloseFile(lldb::user_id_t fd, Status &error) {
222 if (m_remote_platform_sp)
223 return m_remote_platform_sp->CloseFile(fd, error);
224 return Platform::CloseFile(fd, error);
225 }
226
ReadFile(lldb::user_id_t fd,uint64_t offset,void * dst,uint64_t dst_len,Status & error)227 uint64_t RemoteAwarePlatform::ReadFile(lldb::user_id_t fd, uint64_t offset,
228 void *dst, uint64_t dst_len,
229 Status &error) {
230 if (m_remote_platform_sp)
231 return m_remote_platform_sp->ReadFile(fd, offset, dst, dst_len, error);
232 return Platform::ReadFile(fd, offset, dst, dst_len, error);
233 }
234
WriteFile(lldb::user_id_t fd,uint64_t offset,const void * src,uint64_t src_len,Status & error)235 uint64_t RemoteAwarePlatform::WriteFile(lldb::user_id_t fd, uint64_t offset,
236 const void *src, uint64_t src_len,
237 Status &error) {
238 if (m_remote_platform_sp)
239 return m_remote_platform_sp->WriteFile(fd, offset, src, src_len, error);
240 return Platform::WriteFile(fd, offset, src, src_len, error);
241 }
242
GetFileSize(const FileSpec & file_spec)243 lldb::user_id_t RemoteAwarePlatform::GetFileSize(const FileSpec &file_spec) {
244 if (m_remote_platform_sp)
245 return m_remote_platform_sp->GetFileSize(file_spec);
246 return Platform::GetFileSize(file_spec);
247 }
248
CreateSymlink(const FileSpec & src,const FileSpec & dst)249 Status RemoteAwarePlatform::CreateSymlink(const FileSpec &src,
250 const FileSpec &dst) {
251 if (m_remote_platform_sp)
252 return m_remote_platform_sp->CreateSymlink(src, dst);
253 return Platform::CreateSymlink(src, dst);
254 }
255
GetFileExists(const FileSpec & file_spec)256 bool RemoteAwarePlatform::GetFileExists(const FileSpec &file_spec) {
257 if (m_remote_platform_sp)
258 return m_remote_platform_sp->GetFileExists(file_spec);
259 return Platform::GetFileExists(file_spec);
260 }
261
Unlink(const FileSpec & file_spec)262 Status RemoteAwarePlatform::Unlink(const FileSpec &file_spec) {
263 if (m_remote_platform_sp)
264 return m_remote_platform_sp->Unlink(file_spec);
265 return Platform::Unlink(file_spec);
266 }
267
CalculateMD5(const FileSpec & file_spec,uint64_t & low,uint64_t & high)268 bool RemoteAwarePlatform::CalculateMD5(const FileSpec &file_spec, uint64_t &low,
269 uint64_t &high) {
270 if (m_remote_platform_sp)
271 return m_remote_platform_sp->CalculateMD5(file_spec, low, high);
272 return Platform::CalculateMD5(file_spec, low, high);
273 }
274
GetRemoteWorkingDirectory()275 FileSpec RemoteAwarePlatform::GetRemoteWorkingDirectory() {
276 if (IsRemote() && m_remote_platform_sp)
277 return m_remote_platform_sp->GetRemoteWorkingDirectory();
278 return Platform::GetRemoteWorkingDirectory();
279 }
280
SetRemoteWorkingDirectory(const FileSpec & working_dir)281 bool RemoteAwarePlatform::SetRemoteWorkingDirectory(
282 const FileSpec &working_dir) {
283 if (IsRemote() && m_remote_platform_sp)
284 return m_remote_platform_sp->SetRemoteWorkingDirectory(working_dir);
285 return Platform::SetRemoteWorkingDirectory(working_dir);
286 }
287
GetFileWithUUID(const FileSpec & platform_file,const UUID * uuid_ptr,FileSpec & local_file)288 Status RemoteAwarePlatform::GetFileWithUUID(const FileSpec &platform_file,
289 const UUID *uuid_ptr,
290 FileSpec &local_file) {
291 if (IsRemote() && m_remote_platform_sp)
292 return m_remote_platform_sp->GetFileWithUUID(platform_file, uuid_ptr,
293 local_file);
294
295 // Default to the local case
296 local_file = platform_file;
297 return Status();
298 }
299
GetRemoteOSVersion()300 bool RemoteAwarePlatform::GetRemoteOSVersion() {
301 if (m_remote_platform_sp) {
302 m_os_version = m_remote_platform_sp->GetOSVersion();
303 return !m_os_version.empty();
304 }
305 return false;
306 }
307
GetRemoteOSBuildString()308 llvm::Optional<std::string> RemoteAwarePlatform::GetRemoteOSBuildString() {
309 if (m_remote_platform_sp)
310 return m_remote_platform_sp->GetRemoteOSBuildString();
311 return llvm::None;
312 }
313
GetRemoteOSKernelDescription()314 llvm::Optional<std::string> RemoteAwarePlatform::GetRemoteOSKernelDescription() {
315 if (m_remote_platform_sp)
316 return m_remote_platform_sp->GetRemoteOSKernelDescription();
317 return llvm::None;
318 }
319
GetRemoteSystemArchitecture()320 ArchSpec RemoteAwarePlatform::GetRemoteSystemArchitecture() {
321 if (m_remote_platform_sp)
322 return m_remote_platform_sp->GetRemoteSystemArchitecture();
323 return ArchSpec();
324 }
325
GetHostname()326 const char *RemoteAwarePlatform::GetHostname() {
327 if (m_remote_platform_sp)
328 return m_remote_platform_sp->GetHostname();
329 return Platform::GetHostname();
330 }
331
GetUserIDResolver()332 UserIDResolver &RemoteAwarePlatform::GetUserIDResolver() {
333 if (m_remote_platform_sp)
334 return m_remote_platform_sp->GetUserIDResolver();
335 return Platform::GetUserIDResolver();
336 }
337
GetEnvironment()338 Environment RemoteAwarePlatform::GetEnvironment() {
339 if (m_remote_platform_sp)
340 return m_remote_platform_sp->GetEnvironment();
341 return Platform::GetEnvironment();
342 }
343
IsConnected() const344 bool RemoteAwarePlatform::IsConnected() const {
345 if (m_remote_platform_sp)
346 return m_remote_platform_sp->IsConnected();
347 return Platform::IsConnected();
348 }
349
GetProcessInfo(lldb::pid_t pid,ProcessInstanceInfo & process_info)350 bool RemoteAwarePlatform::GetProcessInfo(lldb::pid_t pid,
351 ProcessInstanceInfo &process_info) {
352 if (m_remote_platform_sp)
353 return m_remote_platform_sp->GetProcessInfo(pid, process_info);
354 return Platform::GetProcessInfo(pid, process_info);
355 }
356
357 uint32_t
FindProcesses(const ProcessInstanceInfoMatch & match_info,ProcessInstanceInfoList & process_infos)358 RemoteAwarePlatform::FindProcesses(const ProcessInstanceInfoMatch &match_info,
359 ProcessInstanceInfoList &process_infos) {
360 if (m_remote_platform_sp)
361 return m_remote_platform_sp->FindProcesses(match_info, process_infos);
362 return Platform::FindProcesses(match_info, process_infos);
363 }
364
ConnectProcess(llvm::StringRef connect_url,llvm::StringRef plugin_name,Debugger & debugger,Target * target,Status & error)365 lldb::ProcessSP RemoteAwarePlatform::ConnectProcess(llvm::StringRef connect_url,
366 llvm::StringRef plugin_name,
367 Debugger &debugger,
368 Target *target,
369 Status &error) {
370 if (m_remote_platform_sp)
371 return m_remote_platform_sp->ConnectProcess(connect_url, plugin_name,
372 debugger, target, error);
373 return Platform::ConnectProcess(connect_url, plugin_name, debugger, target,
374 error);
375 }
376
LaunchProcess(ProcessLaunchInfo & launch_info)377 Status RemoteAwarePlatform::LaunchProcess(ProcessLaunchInfo &launch_info) {
378 if (m_remote_platform_sp)
379 return m_remote_platform_sp->LaunchProcess(launch_info);
380 return Platform::LaunchProcess(launch_info);
381 }
382
KillProcess(const lldb::pid_t pid)383 Status RemoteAwarePlatform::KillProcess(const lldb::pid_t pid) {
384 if (m_remote_platform_sp)
385 return m_remote_platform_sp->KillProcess(pid);
386 return Platform::KillProcess(pid);
387 }
388
ConnectToWaitingProcesses(Debugger & debugger,Status & error)389 size_t RemoteAwarePlatform::ConnectToWaitingProcesses(Debugger &debugger,
390 Status &error) {
391 if (m_remote_platform_sp)
392 return m_remote_platform_sp->ConnectToWaitingProcesses(debugger, error);
393 return Platform::ConnectToWaitingProcesses(debugger, error);
394 }
395