xref: /freebsd/contrib/llvm-project/lldb/source/API/SBPlatform.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===-- SBPlatform.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/API/SBPlatform.h"
10 #include "lldb/API/SBDebugger.h"
11 #include "lldb/API/SBEnvironment.h"
12 #include "lldb/API/SBError.h"
13 #include "lldb/API/SBFileSpec.h"
14 #include "lldb/API/SBLaunchInfo.h"
15 #include "lldb/API/SBModuleSpec.h"
16 #include "lldb/API/SBProcessInfoList.h"
17 #include "lldb/API/SBTarget.h"
18 #include "lldb/API/SBUnixSignals.h"
19 #include "lldb/Host/File.h"
20 #include "lldb/Target/Platform.h"
21 #include "lldb/Target/Target.h"
22 #include "lldb/Utility/ArchSpec.h"
23 #include "lldb/Utility/Args.h"
24 #include "lldb/Utility/Instrumentation.h"
25 #include "lldb/Utility/Status.h"
26 
27 #include "llvm/Support/FileSystem.h"
28 
29 #include <functional>
30 
31 using namespace lldb;
32 using namespace lldb_private;
33 
34 // PlatformConnectOptions
35 struct PlatformConnectOptions {
PlatformConnectOptionsPlatformConnectOptions36   PlatformConnectOptions(const char *url = nullptr) {
37     if (url && url[0])
38       m_url = url;
39   }
40 
41   ~PlatformConnectOptions() = default;
42 
43   std::string m_url;
44   std::string m_rsync_options;
45   std::string m_rsync_remote_path_prefix;
46   bool m_rsync_enabled = false;
47   bool m_rsync_omit_hostname_from_remote_path = false;
48   ConstString m_local_cache_directory;
49 };
50 
51 // PlatformShellCommand
52 struct PlatformShellCommand {
PlatformShellCommandPlatformShellCommand53   PlatformShellCommand(llvm::StringRef shell_interpreter,
54                        llvm::StringRef shell_command) {
55     if (!shell_interpreter.empty())
56       m_shell = shell_interpreter.str();
57 
58     if (!m_shell.empty() && !shell_command.empty())
59       m_command = shell_command.str();
60   }
61 
PlatformShellCommandPlatformShellCommand62   PlatformShellCommand(llvm::StringRef shell_command = llvm::StringRef()) {
63     if (!shell_command.empty())
64       m_command = shell_command.str();
65   }
66 
67   ~PlatformShellCommand() = default;
68 
69   std::string m_shell;
70   std::string m_command;
71   std::string m_working_dir;
72   std::string m_output;
73   int m_status = 0;
74   int m_signo = 0;
75   Timeout<std::ratio<1>> m_timeout = std::nullopt;
76 };
77 // SBPlatformConnectOptions
SBPlatformConnectOptions(const char * url)78 SBPlatformConnectOptions::SBPlatformConnectOptions(const char *url)
79     : m_opaque_ptr(new PlatformConnectOptions(url)) {
80   LLDB_INSTRUMENT_VA(this, url);
81 }
82 
SBPlatformConnectOptions(const SBPlatformConnectOptions & rhs)83 SBPlatformConnectOptions::SBPlatformConnectOptions(
84     const SBPlatformConnectOptions &rhs)
85     : m_opaque_ptr(new PlatformConnectOptions()) {
86   LLDB_INSTRUMENT_VA(this, rhs);
87 
88   *m_opaque_ptr = *rhs.m_opaque_ptr;
89 }
90 
~SBPlatformConnectOptions()91 SBPlatformConnectOptions::~SBPlatformConnectOptions() { delete m_opaque_ptr; }
92 
93 SBPlatformConnectOptions &
operator =(const SBPlatformConnectOptions & rhs)94 SBPlatformConnectOptions::operator=(const SBPlatformConnectOptions &rhs) {
95   LLDB_INSTRUMENT_VA(this, rhs);
96 
97   *m_opaque_ptr = *rhs.m_opaque_ptr;
98   return *this;
99 }
100 
GetURL()101 const char *SBPlatformConnectOptions::GetURL() {
102   LLDB_INSTRUMENT_VA(this);
103 
104   if (m_opaque_ptr->m_url.empty())
105     return nullptr;
106   return ConstString(m_opaque_ptr->m_url.c_str()).GetCString();
107 }
108 
SetURL(const char * url)109 void SBPlatformConnectOptions::SetURL(const char *url) {
110   LLDB_INSTRUMENT_VA(this, url);
111 
112   if (url && url[0])
113     m_opaque_ptr->m_url = url;
114   else
115     m_opaque_ptr->m_url.clear();
116 }
117 
GetRsyncEnabled()118 bool SBPlatformConnectOptions::GetRsyncEnabled() {
119   LLDB_INSTRUMENT_VA(this);
120 
121   return m_opaque_ptr->m_rsync_enabled;
122 }
123 
EnableRsync(const char * options,const char * remote_path_prefix,bool omit_hostname_from_remote_path)124 void SBPlatformConnectOptions::EnableRsync(
125     const char *options, const char *remote_path_prefix,
126     bool omit_hostname_from_remote_path) {
127   LLDB_INSTRUMENT_VA(this, options, remote_path_prefix,
128                      omit_hostname_from_remote_path);
129 
130   m_opaque_ptr->m_rsync_enabled = true;
131   m_opaque_ptr->m_rsync_omit_hostname_from_remote_path =
132       omit_hostname_from_remote_path;
133   if (remote_path_prefix && remote_path_prefix[0])
134     m_opaque_ptr->m_rsync_remote_path_prefix = remote_path_prefix;
135   else
136     m_opaque_ptr->m_rsync_remote_path_prefix.clear();
137 
138   if (options && options[0])
139     m_opaque_ptr->m_rsync_options = options;
140   else
141     m_opaque_ptr->m_rsync_options.clear();
142 }
143 
DisableRsync()144 void SBPlatformConnectOptions::DisableRsync() {
145   LLDB_INSTRUMENT_VA(this);
146 
147   m_opaque_ptr->m_rsync_enabled = false;
148 }
149 
GetLocalCacheDirectory()150 const char *SBPlatformConnectOptions::GetLocalCacheDirectory() {
151   LLDB_INSTRUMENT_VA(this);
152 
153   return m_opaque_ptr->m_local_cache_directory.GetCString();
154 }
155 
SetLocalCacheDirectory(const char * path)156 void SBPlatformConnectOptions::SetLocalCacheDirectory(const char *path) {
157   LLDB_INSTRUMENT_VA(this, path);
158 
159   if (path && path[0])
160     m_opaque_ptr->m_local_cache_directory.SetCString(path);
161   else
162     m_opaque_ptr->m_local_cache_directory = ConstString();
163 }
164 
165 // SBPlatformShellCommand
SBPlatformShellCommand(const char * shell_interpreter,const char * shell_command)166 SBPlatformShellCommand::SBPlatformShellCommand(const char *shell_interpreter,
167                                                const char *shell_command)
168     : m_opaque_ptr(new PlatformShellCommand(shell_interpreter, shell_command)) {
169   LLDB_INSTRUMENT_VA(this, shell_interpreter, shell_command);
170 }
171 
SBPlatformShellCommand(const char * shell_command)172 SBPlatformShellCommand::SBPlatformShellCommand(const char *shell_command)
173     : m_opaque_ptr(new PlatformShellCommand(shell_command)) {
174   LLDB_INSTRUMENT_VA(this, shell_command);
175 }
176 
SBPlatformShellCommand(const SBPlatformShellCommand & rhs)177 SBPlatformShellCommand::SBPlatformShellCommand(
178     const SBPlatformShellCommand &rhs)
179     : m_opaque_ptr(new PlatformShellCommand()) {
180   LLDB_INSTRUMENT_VA(this, rhs);
181 
182   *m_opaque_ptr = *rhs.m_opaque_ptr;
183 }
184 
185 SBPlatformShellCommand &
operator =(const SBPlatformShellCommand & rhs)186 SBPlatformShellCommand::operator=(const SBPlatformShellCommand &rhs) {
187 
188   LLDB_INSTRUMENT_VA(this, rhs);
189 
190   *m_opaque_ptr = *rhs.m_opaque_ptr;
191   return *this;
192 }
193 
~SBPlatformShellCommand()194 SBPlatformShellCommand::~SBPlatformShellCommand() { delete m_opaque_ptr; }
195 
Clear()196 void SBPlatformShellCommand::Clear() {
197   LLDB_INSTRUMENT_VA(this);
198 
199   m_opaque_ptr->m_output = std::string();
200   m_opaque_ptr->m_status = 0;
201   m_opaque_ptr->m_signo = 0;
202 }
203 
GetShell()204 const char *SBPlatformShellCommand::GetShell() {
205   LLDB_INSTRUMENT_VA(this);
206 
207   if (m_opaque_ptr->m_shell.empty())
208     return nullptr;
209   return ConstString(m_opaque_ptr->m_shell.c_str()).GetCString();
210 }
211 
SetShell(const char * shell_interpreter)212 void SBPlatformShellCommand::SetShell(const char *shell_interpreter) {
213   LLDB_INSTRUMENT_VA(this, shell_interpreter);
214 
215   if (shell_interpreter && shell_interpreter[0])
216     m_opaque_ptr->m_shell = shell_interpreter;
217   else
218     m_opaque_ptr->m_shell.clear();
219 }
220 
GetCommand()221 const char *SBPlatformShellCommand::GetCommand() {
222   LLDB_INSTRUMENT_VA(this);
223 
224   if (m_opaque_ptr->m_command.empty())
225     return nullptr;
226   return ConstString(m_opaque_ptr->m_command.c_str()).GetCString();
227 }
228 
SetCommand(const char * shell_command)229 void SBPlatformShellCommand::SetCommand(const char *shell_command) {
230   LLDB_INSTRUMENT_VA(this, shell_command);
231 
232   if (shell_command && shell_command[0])
233     m_opaque_ptr->m_command = shell_command;
234   else
235     m_opaque_ptr->m_command.clear();
236 }
237 
GetWorkingDirectory()238 const char *SBPlatformShellCommand::GetWorkingDirectory() {
239   LLDB_INSTRUMENT_VA(this);
240 
241   if (m_opaque_ptr->m_working_dir.empty())
242     return nullptr;
243   return ConstString(m_opaque_ptr->m_working_dir.c_str()).GetCString();
244 }
245 
SetWorkingDirectory(const char * path)246 void SBPlatformShellCommand::SetWorkingDirectory(const char *path) {
247   LLDB_INSTRUMENT_VA(this, path);
248 
249   if (path && path[0])
250     m_opaque_ptr->m_working_dir = path;
251   else
252     m_opaque_ptr->m_working_dir.clear();
253 }
254 
GetTimeoutSeconds()255 uint32_t SBPlatformShellCommand::GetTimeoutSeconds() {
256   LLDB_INSTRUMENT_VA(this);
257 
258   if (m_opaque_ptr->m_timeout)
259     return m_opaque_ptr->m_timeout->count();
260   return UINT32_MAX;
261 }
262 
SetTimeoutSeconds(uint32_t sec)263 void SBPlatformShellCommand::SetTimeoutSeconds(uint32_t sec) {
264   LLDB_INSTRUMENT_VA(this, sec);
265 
266   if (sec == UINT32_MAX)
267     m_opaque_ptr->m_timeout = std::nullopt;
268   else
269     m_opaque_ptr->m_timeout = std::chrono::seconds(sec);
270 }
271 
GetSignal()272 int SBPlatformShellCommand::GetSignal() {
273   LLDB_INSTRUMENT_VA(this);
274 
275   return m_opaque_ptr->m_signo;
276 }
277 
GetStatus()278 int SBPlatformShellCommand::GetStatus() {
279   LLDB_INSTRUMENT_VA(this);
280 
281   return m_opaque_ptr->m_status;
282 }
283 
GetOutput()284 const char *SBPlatformShellCommand::GetOutput() {
285   LLDB_INSTRUMENT_VA(this);
286 
287   if (m_opaque_ptr->m_output.empty())
288     return nullptr;
289   return ConstString(m_opaque_ptr->m_output.c_str()).GetCString();
290 }
291 
292 // SBPlatform
SBPlatform()293 SBPlatform::SBPlatform() { LLDB_INSTRUMENT_VA(this); }
294 
SBPlatform(const char * platform_name)295 SBPlatform::SBPlatform(const char *platform_name) {
296   LLDB_INSTRUMENT_VA(this, platform_name);
297 
298   m_opaque_sp = Platform::Create(platform_name);
299 }
300 
SBPlatform(const SBPlatform & rhs)301 SBPlatform::SBPlatform(const SBPlatform &rhs) {
302   LLDB_INSTRUMENT_VA(this, rhs);
303 
304   m_opaque_sp = rhs.m_opaque_sp;
305 }
306 
operator =(const SBPlatform & rhs)307 SBPlatform &SBPlatform::operator=(const SBPlatform &rhs) {
308   LLDB_INSTRUMENT_VA(this, rhs);
309 
310   m_opaque_sp = rhs.m_opaque_sp;
311   return *this;
312 }
313 
314 SBPlatform::~SBPlatform() = default;
315 
GetHostPlatform()316 SBPlatform SBPlatform::GetHostPlatform() {
317   LLDB_INSTRUMENT();
318 
319   SBPlatform host_platform;
320   host_platform.m_opaque_sp = Platform::GetHostPlatform();
321   return host_platform;
322 }
323 
IsValid() const324 bool SBPlatform::IsValid() const {
325   LLDB_INSTRUMENT_VA(this);
326   return this->operator bool();
327 }
operator bool() const328 SBPlatform::operator bool() const {
329   LLDB_INSTRUMENT_VA(this);
330 
331   return m_opaque_sp.get() != nullptr;
332 }
333 
Clear()334 void SBPlatform::Clear() {
335   LLDB_INSTRUMENT_VA(this);
336 
337   m_opaque_sp.reset();
338 }
339 
GetName()340 const char *SBPlatform::GetName() {
341   LLDB_INSTRUMENT_VA(this);
342 
343   PlatformSP platform_sp(GetSP());
344   if (platform_sp)
345     return ConstString(platform_sp->GetName()).AsCString();
346   return nullptr;
347 }
348 
GetSP() const349 lldb::PlatformSP SBPlatform::GetSP() const { return m_opaque_sp; }
350 
SetSP(const lldb::PlatformSP & platform_sp)351 void SBPlatform::SetSP(const lldb::PlatformSP &platform_sp) {
352   m_opaque_sp = platform_sp;
353 }
354 
GetWorkingDirectory()355 const char *SBPlatform::GetWorkingDirectory() {
356   LLDB_INSTRUMENT_VA(this);
357 
358   PlatformSP platform_sp(GetSP());
359   if (platform_sp)
360     return platform_sp->GetWorkingDirectory().GetPathAsConstString().AsCString();
361   return nullptr;
362 }
363 
SetWorkingDirectory(const char * path)364 bool SBPlatform::SetWorkingDirectory(const char *path) {
365   LLDB_INSTRUMENT_VA(this, path);
366 
367   PlatformSP platform_sp(GetSP());
368   if (platform_sp) {
369     if (path)
370       platform_sp->SetWorkingDirectory(FileSpec(path));
371     else
372       platform_sp->SetWorkingDirectory(FileSpec());
373     return true;
374   }
375   return false;
376 }
377 
ConnectRemote(SBPlatformConnectOptions & connect_options)378 SBError SBPlatform::ConnectRemote(SBPlatformConnectOptions &connect_options) {
379   LLDB_INSTRUMENT_VA(this, connect_options);
380 
381   SBError sb_error;
382   PlatformSP platform_sp(GetSP());
383   if (platform_sp && connect_options.GetURL()) {
384     Args args;
385     args.AppendArgument(connect_options.GetURL());
386     sb_error.ref() = platform_sp->ConnectRemote(args);
387   } else {
388     sb_error = Status::FromErrorString("invalid platform");
389   }
390   return sb_error;
391 }
392 
DisconnectRemote()393 void SBPlatform::DisconnectRemote() {
394   LLDB_INSTRUMENT_VA(this);
395 
396   PlatformSP platform_sp(GetSP());
397   if (platform_sp)
398     platform_sp->DisconnectRemote();
399 }
400 
IsConnected()401 bool SBPlatform::IsConnected() {
402   LLDB_INSTRUMENT_VA(this);
403 
404   PlatformSP platform_sp(GetSP());
405   if (platform_sp)
406     return platform_sp->IsConnected();
407   return false;
408 }
409 
GetTriple()410 const char *SBPlatform::GetTriple() {
411   LLDB_INSTRUMENT_VA(this);
412 
413   PlatformSP platform_sp(GetSP());
414   if (platform_sp) {
415     ArchSpec arch(platform_sp->GetSystemArchitecture());
416     if (arch.IsValid()) {
417       // Const-ify the string so we don't need to worry about the lifetime of
418       // the string
419       return ConstString(arch.GetTriple().getTriple().c_str()).GetCString();
420     }
421   }
422   return nullptr;
423 }
424 
GetOSBuild()425 const char *SBPlatform::GetOSBuild() {
426   LLDB_INSTRUMENT_VA(this);
427 
428   PlatformSP platform_sp(GetSP());
429   if (platform_sp) {
430     std::string s = platform_sp->GetOSBuildString().value_or("");
431     if (!s.empty()) {
432       // Const-ify the string so we don't need to worry about the lifetime of
433       // the string
434       return ConstString(s).GetCString();
435     }
436   }
437   return nullptr;
438 }
439 
GetOSDescription()440 const char *SBPlatform::GetOSDescription() {
441   LLDB_INSTRUMENT_VA(this);
442 
443   PlatformSP platform_sp(GetSP());
444   if (platform_sp) {
445     std::string s = platform_sp->GetOSKernelDescription().value_or("");
446     if (!s.empty()) {
447       // Const-ify the string so we don't need to worry about the lifetime of
448       // the string
449       return ConstString(s.c_str()).GetCString();
450     }
451   }
452   return nullptr;
453 }
454 
GetHostname()455 const char *SBPlatform::GetHostname() {
456   LLDB_INSTRUMENT_VA(this);
457 
458   PlatformSP platform_sp(GetSP());
459   if (platform_sp)
460     return ConstString(platform_sp->GetHostname()).GetCString();
461   return nullptr;
462 }
463 
GetOSMajorVersion()464 uint32_t SBPlatform::GetOSMajorVersion() {
465   LLDB_INSTRUMENT_VA(this);
466 
467   llvm::VersionTuple version;
468   if (PlatformSP platform_sp = GetSP())
469     version = platform_sp->GetOSVersion();
470   return version.empty() ? UINT32_MAX : version.getMajor();
471 }
472 
GetOSMinorVersion()473 uint32_t SBPlatform::GetOSMinorVersion() {
474   LLDB_INSTRUMENT_VA(this);
475 
476   llvm::VersionTuple version;
477   if (PlatformSP platform_sp = GetSP())
478     version = platform_sp->GetOSVersion();
479   return version.getMinor().value_or(UINT32_MAX);
480 }
481 
GetOSUpdateVersion()482 uint32_t SBPlatform::GetOSUpdateVersion() {
483   LLDB_INSTRUMENT_VA(this);
484 
485   llvm::VersionTuple version;
486   if (PlatformSP platform_sp = GetSP())
487     version = platform_sp->GetOSVersion();
488   return version.getSubminor().value_or(UINT32_MAX);
489 }
490 
SetSDKRoot(const char * sysroot)491 void SBPlatform::SetSDKRoot(const char *sysroot) {
492   LLDB_INSTRUMENT_VA(this, sysroot);
493   if (PlatformSP platform_sp = GetSP())
494     platform_sp->SetSDKRootDirectory(llvm::StringRef(sysroot).str());
495 }
496 
Get(SBFileSpec & src,SBFileSpec & dst)497 SBError SBPlatform::Get(SBFileSpec &src, SBFileSpec &dst) {
498   LLDB_INSTRUMENT_VA(this, src, dst);
499 
500   SBError sb_error;
501   PlatformSP platform_sp(GetSP());
502   if (platform_sp) {
503     sb_error.ref() = platform_sp->GetFile(src.ref(), dst.ref());
504   } else {
505     sb_error = Status::FromErrorString("invalid platform");
506   }
507   return sb_error;
508 }
509 
Put(SBFileSpec & src,SBFileSpec & dst)510 SBError SBPlatform::Put(SBFileSpec &src, SBFileSpec &dst) {
511   LLDB_INSTRUMENT_VA(this, src, dst);
512   return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) {
513     if (src.Exists()) {
514       uint32_t permissions = FileSystem::Instance().GetPermissions(src.ref());
515       if (permissions == 0) {
516         if (FileSystem::Instance().IsDirectory(src.ref()))
517           permissions = eFilePermissionsDirectoryDefault;
518         else
519           permissions = eFilePermissionsFileDefault;
520       }
521 
522       return platform_sp->PutFile(src.ref(), dst.ref(), permissions);
523     }
524 
525     return Status::FromErrorStringWithFormat(
526         "'src' argument doesn't exist: '%s'", src.ref().GetPath().c_str());
527   });
528 }
529 
Install(SBFileSpec & src,SBFileSpec & dst)530 SBError SBPlatform::Install(SBFileSpec &src, SBFileSpec &dst) {
531   LLDB_INSTRUMENT_VA(this, src, dst);
532   return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) {
533     if (src.Exists())
534       return platform_sp->Install(src.ref(), dst.ref());
535 
536     Status error;
537     error = Status::FromErrorStringWithFormat(
538         "'src' argument doesn't exist: '%s'", src.ref().GetPath().c_str());
539     return error;
540   });
541 }
542 
Run(SBPlatformShellCommand & shell_command)543 SBError SBPlatform::Run(SBPlatformShellCommand &shell_command) {
544   LLDB_INSTRUMENT_VA(this, shell_command);
545   return ExecuteConnected(
546       [&](const lldb::PlatformSP &platform_sp) {
547         const char *command = shell_command.GetCommand();
548         if (!command)
549           return Status::FromErrorString("invalid shell command (empty)");
550 
551         if (shell_command.GetWorkingDirectory() == nullptr) {
552           std::string platform_working_dir =
553               platform_sp->GetWorkingDirectory().GetPath();
554           if (!platform_working_dir.empty())
555             shell_command.SetWorkingDirectory(platform_working_dir.c_str());
556         }
557         return platform_sp->RunShellCommand(
558             shell_command.m_opaque_ptr->m_shell, command,
559             FileSpec(shell_command.GetWorkingDirectory()),
560             &shell_command.m_opaque_ptr->m_status,
561             &shell_command.m_opaque_ptr->m_signo,
562             &shell_command.m_opaque_ptr->m_output,
563             shell_command.m_opaque_ptr->m_timeout);
564       });
565 }
566 
Launch(SBLaunchInfo & launch_info)567 SBError SBPlatform::Launch(SBLaunchInfo &launch_info) {
568   LLDB_INSTRUMENT_VA(this, launch_info);
569   return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) {
570     ProcessLaunchInfo info = launch_info.ref();
571     Status error = platform_sp->LaunchProcess(info);
572     launch_info.set_ref(info);
573     return error;
574   });
575 }
576 
Attach(SBAttachInfo & attach_info,const SBDebugger & debugger,SBTarget & target,SBError & error)577 SBProcess SBPlatform::Attach(SBAttachInfo &attach_info,
578                              const SBDebugger &debugger, SBTarget &target,
579                              SBError &error) {
580   LLDB_INSTRUMENT_VA(this, attach_info, debugger, target, error);
581 
582   if (PlatformSP platform_sp = GetSP()) {
583     if (platform_sp->IsConnected()) {
584       ProcessAttachInfo &info = attach_info.ref();
585       Status status;
586       ProcessSP process_sp = platform_sp->Attach(info, debugger.ref(),
587                                                  target.GetSP().get(), status);
588       error.SetError(std::move(status));
589       return SBProcess(process_sp);
590     }
591 
592     error = Status::FromErrorString("not connected");
593     return {};
594   }
595 
596   error = Status::FromErrorString("invalid platform");
597   return {};
598 }
599 
GetAllProcesses(SBError & error)600 SBProcessInfoList SBPlatform::GetAllProcesses(SBError &error) {
601   if (PlatformSP platform_sp = GetSP()) {
602     if (platform_sp->IsConnected()) {
603       ProcessInstanceInfoList list = platform_sp->GetAllProcesses();
604       return SBProcessInfoList(list);
605     }
606     error = Status::FromErrorString("not connected");
607     return {};
608   }
609 
610   error = Status::FromErrorString("invalid platform");
611   return {};
612 }
613 
Kill(const lldb::pid_t pid)614 SBError SBPlatform::Kill(const lldb::pid_t pid) {
615   LLDB_INSTRUMENT_VA(this, pid);
616   return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) {
617     return platform_sp->KillProcess(pid);
618   });
619 }
620 
ExecuteConnected(const std::function<Status (const lldb::PlatformSP &)> & func)621 SBError SBPlatform::ExecuteConnected(
622     const std::function<Status(const lldb::PlatformSP &)> &func) {
623   SBError sb_error;
624   const auto platform_sp(GetSP());
625   if (platform_sp) {
626     if (platform_sp->IsConnected())
627       sb_error.ref() = func(platform_sp);
628     else
629       sb_error = Status::FromErrorString("not connected");
630   } else
631     sb_error = Status::FromErrorString("invalid platform");
632 
633   return sb_error;
634 }
635 
MakeDirectory(const char * path,uint32_t file_permissions)636 SBError SBPlatform::MakeDirectory(const char *path, uint32_t file_permissions) {
637   LLDB_INSTRUMENT_VA(this, path, file_permissions);
638 
639   SBError sb_error;
640   PlatformSP platform_sp(GetSP());
641   if (platform_sp) {
642     sb_error.ref() =
643         platform_sp->MakeDirectory(FileSpec(path), file_permissions);
644   } else {
645     sb_error = Status::FromErrorString("invalid platform");
646   }
647   return sb_error;
648 }
649 
GetFilePermissions(const char * path)650 uint32_t SBPlatform::GetFilePermissions(const char *path) {
651   LLDB_INSTRUMENT_VA(this, path);
652 
653   PlatformSP platform_sp(GetSP());
654   if (platform_sp) {
655     uint32_t file_permissions = 0;
656     platform_sp->GetFilePermissions(FileSpec(path), file_permissions);
657     return file_permissions;
658   }
659   return 0;
660 }
661 
SetFilePermissions(const char * path,uint32_t file_permissions)662 SBError SBPlatform::SetFilePermissions(const char *path,
663                                        uint32_t file_permissions) {
664   LLDB_INSTRUMENT_VA(this, path, file_permissions);
665 
666   SBError sb_error;
667   PlatformSP platform_sp(GetSP());
668   if (platform_sp) {
669     sb_error.ref() =
670         platform_sp->SetFilePermissions(FileSpec(path), file_permissions);
671   } else {
672     sb_error = Status::FromErrorString("invalid platform");
673   }
674   return sb_error;
675 }
676 
GetUnixSignals() const677 SBUnixSignals SBPlatform::GetUnixSignals() const {
678   LLDB_INSTRUMENT_VA(this);
679 
680   if (auto platform_sp = GetSP())
681     return SBUnixSignals{platform_sp};
682 
683   return SBUnixSignals();
684 }
685 
GetEnvironment()686 SBEnvironment SBPlatform::GetEnvironment() {
687   LLDB_INSTRUMENT_VA(this);
688   PlatformSP platform_sp(GetSP());
689 
690   if (platform_sp) {
691     return SBEnvironment(platform_sp->GetEnvironment());
692   }
693 
694   return SBEnvironment();
695 }
696 
SetLocateModuleCallback(lldb::SBPlatformLocateModuleCallback callback,void * callback_baton)697 SBError SBPlatform::SetLocateModuleCallback(
698     lldb::SBPlatformLocateModuleCallback callback, void *callback_baton) {
699   LLDB_INSTRUMENT_VA(this, callback, callback_baton);
700   PlatformSP platform_sp(GetSP());
701   if (!platform_sp)
702     return SBError("invalid platform");
703 
704   if (!callback) {
705     // Clear the callback.
706     platform_sp->SetLocateModuleCallback(nullptr);
707     return SBError();
708   }
709 
710   // Platform.h does not accept lldb::SBPlatformLocateModuleCallback directly
711   // because of the SBModuleSpec and SBFileSpec dependencies. Use a lambda to
712   // convert ModuleSpec/FileSpec <--> SBModuleSpec/SBFileSpec for the callback
713   // arguments.
714   platform_sp->SetLocateModuleCallback(
715       [callback, callback_baton](const ModuleSpec &module_spec,
716                                  FileSpec &module_file_spec,
717                                  FileSpec &symbol_file_spec) {
718         SBModuleSpec module_spec_sb(module_spec);
719         SBFileSpec module_file_spec_sb;
720         SBFileSpec symbol_file_spec_sb;
721 
722         SBError error = callback(callback_baton, module_spec_sb,
723                                  module_file_spec_sb, symbol_file_spec_sb);
724 
725         if (error.Success()) {
726           module_file_spec = module_file_spec_sb.ref();
727           symbol_file_spec = symbol_file_spec_sb.ref();
728         }
729 
730         return error.ref().Clone();
731       });
732   return SBError();
733 }
734