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