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