]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/API/SBPlatform.cpp
Merge clang 7.0.1 and several follow-up changes
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / API / SBPlatform.cpp
1 //===-- SBPlatform.cpp ------------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "lldb/API/SBPlatform.h"
11 #include "lldb/API/SBError.h"
12 #include "lldb/API/SBFileSpec.h"
13 #include "lldb/API/SBLaunchInfo.h"
14 #include "lldb/API/SBUnixSignals.h"
15 #include "lldb/Host/File.h"
16 #include "lldb/Target/Platform.h"
17 #include "lldb/Target/Target.h"
18 #include "lldb/Utility/ArchSpec.h"
19 #include "lldb/Utility/Args.h"
20 #include "lldb/Utility/Status.h"
21
22 #include "llvm/Support/FileSystem.h"
23
24 #include <functional>
25
26 using namespace lldb;
27 using namespace lldb_private;
28
29 //----------------------------------------------------------------------
30 // PlatformConnectOptions
31 //----------------------------------------------------------------------
32 struct PlatformConnectOptions {
33   PlatformConnectOptions(const char *url = NULL)
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() {}
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 //----------------------------------------------------------------------
52 // PlatformShellCommand
53 //----------------------------------------------------------------------
54 struct PlatformShellCommand {
55   PlatformShellCommand(const char *shell_command = NULL)
56       : m_command(), m_working_dir(), m_status(0), m_signo(0) {
57     if (shell_command && shell_command[0])
58       m_command = shell_command;
59   }
60
61   ~PlatformShellCommand() {}
62
63   std::string m_command;
64   std::string m_working_dir;
65   std::string m_output;
66   int m_status;
67   int m_signo;
68   Timeout<std::ratio<1>> m_timeout = llvm::None;
69 };
70 //----------------------------------------------------------------------
71 // SBPlatformConnectOptions
72 //----------------------------------------------------------------------
73 SBPlatformConnectOptions::SBPlatformConnectOptions(const char *url)
74     : m_opaque_ptr(new PlatformConnectOptions(url)) {}
75
76 SBPlatformConnectOptions::SBPlatformConnectOptions(
77     const SBPlatformConnectOptions &rhs)
78     : m_opaque_ptr(new PlatformConnectOptions()) {
79   *m_opaque_ptr = *rhs.m_opaque_ptr;
80 }
81
82 SBPlatformConnectOptions::~SBPlatformConnectOptions() { delete m_opaque_ptr; }
83
84 void SBPlatformConnectOptions::operator=(const SBPlatformConnectOptions &rhs) {
85   *m_opaque_ptr = *rhs.m_opaque_ptr;
86 }
87
88 const char *SBPlatformConnectOptions::GetURL() {
89   if (m_opaque_ptr->m_url.empty())
90     return NULL;
91   return m_opaque_ptr->m_url.c_str();
92 }
93
94 void SBPlatformConnectOptions::SetURL(const char *url) {
95   if (url && url[0])
96     m_opaque_ptr->m_url = url;
97   else
98     m_opaque_ptr->m_url.clear();
99 }
100
101 bool SBPlatformConnectOptions::GetRsyncEnabled() {
102   return m_opaque_ptr->m_rsync_enabled;
103 }
104
105 void SBPlatformConnectOptions::EnableRsync(
106     const char *options, const char *remote_path_prefix,
107     bool omit_hostname_from_remote_path) {
108   m_opaque_ptr->m_rsync_enabled = true;
109   m_opaque_ptr->m_rsync_omit_hostname_from_remote_path =
110       omit_hostname_from_remote_path;
111   if (remote_path_prefix && remote_path_prefix[0])
112     m_opaque_ptr->m_rsync_remote_path_prefix = remote_path_prefix;
113   else
114     m_opaque_ptr->m_rsync_remote_path_prefix.clear();
115
116   if (options && options[0])
117     m_opaque_ptr->m_rsync_options = options;
118   else
119     m_opaque_ptr->m_rsync_options.clear();
120 }
121
122 void SBPlatformConnectOptions::DisableRsync() {
123   m_opaque_ptr->m_rsync_enabled = false;
124 }
125
126 const char *SBPlatformConnectOptions::GetLocalCacheDirectory() {
127   return m_opaque_ptr->m_local_cache_directory.GetCString();
128 }
129
130 void SBPlatformConnectOptions::SetLocalCacheDirectory(const char *path) {
131   if (path && path[0])
132     m_opaque_ptr->m_local_cache_directory.SetCString(path);
133   else
134     m_opaque_ptr->m_local_cache_directory = ConstString();
135 }
136
137 //----------------------------------------------------------------------
138 // SBPlatformShellCommand
139 //----------------------------------------------------------------------
140 SBPlatformShellCommand::SBPlatformShellCommand(const char *shell_command)
141     : m_opaque_ptr(new PlatformShellCommand(shell_command)) {}
142
143 SBPlatformShellCommand::SBPlatformShellCommand(
144     const SBPlatformShellCommand &rhs)
145     : m_opaque_ptr(new PlatformShellCommand()) {
146   *m_opaque_ptr = *rhs.m_opaque_ptr;
147 }
148
149 SBPlatformShellCommand::~SBPlatformShellCommand() { delete m_opaque_ptr; }
150
151 void SBPlatformShellCommand::Clear() {
152   m_opaque_ptr->m_output = std::string();
153   m_opaque_ptr->m_status = 0;
154   m_opaque_ptr->m_signo = 0;
155 }
156
157 const char *SBPlatformShellCommand::GetCommand() {
158   if (m_opaque_ptr->m_command.empty())
159     return NULL;
160   return m_opaque_ptr->m_command.c_str();
161 }
162
163 void SBPlatformShellCommand::SetCommand(const char *shell_command) {
164   if (shell_command && shell_command[0])
165     m_opaque_ptr->m_command = shell_command;
166   else
167     m_opaque_ptr->m_command.clear();
168 }
169
170 const char *SBPlatformShellCommand::GetWorkingDirectory() {
171   if (m_opaque_ptr->m_working_dir.empty())
172     return NULL;
173   return m_opaque_ptr->m_working_dir.c_str();
174 }
175
176 void SBPlatformShellCommand::SetWorkingDirectory(const char *path) {
177   if (path && path[0])
178     m_opaque_ptr->m_working_dir = path;
179   else
180     m_opaque_ptr->m_working_dir.clear();
181 }
182
183 uint32_t SBPlatformShellCommand::GetTimeoutSeconds() {
184   if (m_opaque_ptr->m_timeout)
185     return m_opaque_ptr->m_timeout->count();
186   return UINT32_MAX;
187 }
188
189 void SBPlatformShellCommand::SetTimeoutSeconds(uint32_t sec) {
190   if (sec == UINT32_MAX)
191     m_opaque_ptr->m_timeout = llvm::None;
192   else
193     m_opaque_ptr->m_timeout = std::chrono::seconds(sec);
194 }
195
196 int SBPlatformShellCommand::GetSignal() { return m_opaque_ptr->m_signo; }
197
198 int SBPlatformShellCommand::GetStatus() { return m_opaque_ptr->m_status; }
199
200 const char *SBPlatformShellCommand::GetOutput() {
201   if (m_opaque_ptr->m_output.empty())
202     return NULL;
203   return m_opaque_ptr->m_output.c_str();
204 }
205
206 //----------------------------------------------------------------------
207 // SBPlatform
208 //----------------------------------------------------------------------
209 SBPlatform::SBPlatform() : m_opaque_sp() {}
210
211 SBPlatform::SBPlatform(const char *platform_name) : m_opaque_sp() {
212   Status error;
213   if (platform_name && platform_name[0])
214     m_opaque_sp = Platform::Create(ConstString(platform_name), error);
215 }
216
217 SBPlatform::~SBPlatform() {}
218
219 bool SBPlatform::IsValid() const { return m_opaque_sp.get() != NULL; }
220
221 void SBPlatform::Clear() { m_opaque_sp.reset(); }
222
223 const char *SBPlatform::GetName() {
224   PlatformSP platform_sp(GetSP());
225   if (platform_sp)
226     return platform_sp->GetName().GetCString();
227   return NULL;
228 }
229
230 lldb::PlatformSP SBPlatform::GetSP() const { return m_opaque_sp; }
231
232 void SBPlatform::SetSP(const lldb::PlatformSP &platform_sp) {
233   m_opaque_sp = platform_sp;
234 }
235
236 const char *SBPlatform::GetWorkingDirectory() {
237   PlatformSP platform_sp(GetSP());
238   if (platform_sp)
239     return platform_sp->GetWorkingDirectory().GetCString();
240   return NULL;
241 }
242
243 bool SBPlatform::SetWorkingDirectory(const char *path) {
244   PlatformSP platform_sp(GetSP());
245   if (platform_sp) {
246     if (path)
247       platform_sp->SetWorkingDirectory(FileSpec{path, false});
248     else
249       platform_sp->SetWorkingDirectory(FileSpec{});
250     return true;
251   }
252   return false;
253 }
254
255 SBError SBPlatform::ConnectRemote(SBPlatformConnectOptions &connect_options) {
256   SBError sb_error;
257   PlatformSP platform_sp(GetSP());
258   if (platform_sp && connect_options.GetURL()) {
259     Args args;
260     args.AppendArgument(
261         llvm::StringRef::withNullAsEmpty(connect_options.GetURL()));
262     sb_error.ref() = platform_sp->ConnectRemote(args);
263   } else {
264     sb_error.SetErrorString("invalid platform");
265   }
266   return sb_error;
267 }
268
269 void SBPlatform::DisconnectRemote() {
270   PlatformSP platform_sp(GetSP());
271   if (platform_sp)
272     platform_sp->DisconnectRemote();
273 }
274
275 bool SBPlatform::IsConnected() {
276   PlatformSP platform_sp(GetSP());
277   if (platform_sp)
278     return platform_sp->IsConnected();
279   return false;
280 }
281
282 const char *SBPlatform::GetTriple() {
283   PlatformSP platform_sp(GetSP());
284   if (platform_sp) {
285     ArchSpec arch(platform_sp->GetSystemArchitecture());
286     if (arch.IsValid()) {
287       // Const-ify the string so we don't need to worry about the lifetime of
288       // the string
289       return ConstString(arch.GetTriple().getTriple().c_str()).GetCString();
290     }
291   }
292   return NULL;
293 }
294
295 const char *SBPlatform::GetOSBuild() {
296   PlatformSP platform_sp(GetSP());
297   if (platform_sp) {
298     std::string s;
299     if (platform_sp->GetOSBuildString(s)) {
300       if (!s.empty()) {
301         // Const-ify the string so we don't need to worry about the lifetime of
302         // the string
303         return ConstString(s.c_str()).GetCString();
304       }
305     }
306   }
307   return NULL;
308 }
309
310 const char *SBPlatform::GetOSDescription() {
311   PlatformSP platform_sp(GetSP());
312   if (platform_sp) {
313     std::string s;
314     if (platform_sp->GetOSKernelDescription(s)) {
315       if (!s.empty()) {
316         // Const-ify the string so we don't need to worry about the lifetime of
317         // the string
318         return ConstString(s.c_str()).GetCString();
319       }
320     }
321   }
322   return NULL;
323 }
324
325 const char *SBPlatform::GetHostname() {
326   PlatformSP platform_sp(GetSP());
327   if (platform_sp)
328     return platform_sp->GetHostname();
329   return NULL;
330 }
331
332 uint32_t SBPlatform::GetOSMajorVersion() {
333   llvm::VersionTuple version;
334   if (PlatformSP platform_sp = GetSP())
335     version = platform_sp->GetOSVersion();
336   return version.empty() ? UINT32_MAX : version.getMajor();
337 }
338
339 uint32_t SBPlatform::GetOSMinorVersion() {
340   llvm::VersionTuple version;
341   if (PlatformSP platform_sp = GetSP())
342     version = platform_sp->GetOSVersion();
343   return version.getMinor().getValueOr(UINT32_MAX);
344 }
345
346 uint32_t SBPlatform::GetOSUpdateVersion() {
347   llvm::VersionTuple version;
348   if (PlatformSP platform_sp = GetSP())
349     version = platform_sp->GetOSVersion();
350   return version.getSubminor().getValueOr(UINT32_MAX);
351 }
352
353 SBError SBPlatform::Get(SBFileSpec &src, SBFileSpec &dst) {
354   SBError sb_error;
355   PlatformSP platform_sp(GetSP());
356   if (platform_sp) {
357     sb_error.ref() = platform_sp->GetFile(src.ref(), dst.ref());
358   } else {
359     sb_error.SetErrorString("invalid platform");
360   }
361   return sb_error;
362 }
363
364 SBError SBPlatform::Put(SBFileSpec &src, SBFileSpec &dst) {
365   return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) {
366     if (src.Exists()) {
367       uint32_t permissions = src.ref().GetPermissions();
368       if (permissions == 0) {
369         if (llvm::sys::fs::is_directory(src.ref().GetPath()))
370           permissions = eFilePermissionsDirectoryDefault;
371         else
372           permissions = eFilePermissionsFileDefault;
373       }
374
375       return platform_sp->PutFile(src.ref(), dst.ref(), permissions);
376     }
377
378     Status error;
379     error.SetErrorStringWithFormat("'src' argument doesn't exist: '%s'",
380                                    src.ref().GetPath().c_str());
381     return error;
382   });
383 }
384
385 SBError SBPlatform::Install(SBFileSpec &src, SBFileSpec &dst) {
386   return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) {
387     if (src.Exists())
388       return platform_sp->Install(src.ref(), dst.ref());
389
390     Status error;
391     error.SetErrorStringWithFormat("'src' argument doesn't exist: '%s'",
392                                    src.ref().GetPath().c_str());
393     return error;
394   });
395 }
396
397 SBError SBPlatform::Run(SBPlatformShellCommand &shell_command) {
398   return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) {
399     const char *command = shell_command.GetCommand();
400     if (!command)
401       return Status("invalid shell command (empty)");
402
403     const char *working_dir = shell_command.GetWorkingDirectory();
404     if (working_dir == NULL) {
405       working_dir = platform_sp->GetWorkingDirectory().GetCString();
406       if (working_dir)
407         shell_command.SetWorkingDirectory(working_dir);
408     }
409     return platform_sp->RunShellCommand(command, FileSpec{working_dir, false},
410                                         &shell_command.m_opaque_ptr->m_status,
411                                         &shell_command.m_opaque_ptr->m_signo,
412                                         &shell_command.m_opaque_ptr->m_output,
413                                         shell_command.m_opaque_ptr->m_timeout);
414   });
415 }
416
417 SBError SBPlatform::Launch(SBLaunchInfo &launch_info) {
418   return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) {
419     ProcessLaunchInfo info = launch_info.ref();
420     Status error = platform_sp->LaunchProcess(info);
421     launch_info.set_ref(info);
422     return error;
423   });
424 }
425
426 SBError SBPlatform::Kill(const lldb::pid_t pid) {
427   return ExecuteConnected([&](const lldb::PlatformSP &platform_sp) {
428     return platform_sp->KillProcess(pid);
429   });
430 }
431
432 SBError SBPlatform::ExecuteConnected(
433     const std::function<Status(const lldb::PlatformSP &)> &func) {
434   SBError sb_error;
435   const auto platform_sp(GetSP());
436   if (platform_sp) {
437     if (platform_sp->IsConnected())
438       sb_error.ref() = func(platform_sp);
439     else
440       sb_error.SetErrorString("not connected");
441   } else
442     sb_error.SetErrorString("invalid platform");
443
444   return sb_error;
445 }
446
447 SBError SBPlatform::MakeDirectory(const char *path, uint32_t file_permissions) {
448   SBError sb_error;
449   PlatformSP platform_sp(GetSP());
450   if (platform_sp) {
451     sb_error.ref() =
452         platform_sp->MakeDirectory(FileSpec{path, false}, file_permissions);
453   } else {
454     sb_error.SetErrorString("invalid platform");
455   }
456   return sb_error;
457 }
458
459 uint32_t SBPlatform::GetFilePermissions(const char *path) {
460   PlatformSP platform_sp(GetSP());
461   if (platform_sp) {
462     uint32_t file_permissions = 0;
463     platform_sp->GetFilePermissions(FileSpec{path, false}, file_permissions);
464     return file_permissions;
465   }
466   return 0;
467 }
468
469 SBError SBPlatform::SetFilePermissions(const char *path,
470                                        uint32_t file_permissions) {
471   SBError sb_error;
472   PlatformSP platform_sp(GetSP());
473   if (platform_sp) {
474     sb_error.ref() = platform_sp->SetFilePermissions(FileSpec{path, false},
475                                                      file_permissions);
476   } else {
477     sb_error.SetErrorString("invalid platform");
478   }
479   return sb_error;
480 }
481
482 SBUnixSignals SBPlatform::GetUnixSignals() const {
483   if (auto platform_sp = GetSP())
484     return SBUnixSignals{platform_sp};
485
486   return {};
487 }