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