LLDB  mainline
CommandObjectPlatform.cpp
Go to the documentation of this file.
1 //===-- CommandObjectPlatform.cpp -------------------------------*- C++ -*-===//
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 <mutex>
10 #include "CommandObjectPlatform.h"
11 #include "lldb/Core/Debugger.h"
12 #include "lldb/Core/Module.h"
14 #include "lldb/Host/OptionParser.h"
22 #include "lldb/Target/Platform.h"
23 #include "lldb/Target/Process.h"
24 #include "lldb/Utility/Args.h"
26 
27 #include "llvm/ADT/SmallString.h"
28 #include "llvm/Support/Threading.h"
29 
30 using namespace lldb;
31 using namespace lldb_private;
32 
33 static mode_t ParsePermissionString(const char *) = delete;
34 
35 static mode_t ParsePermissionString(llvm::StringRef permissions) {
36  if (permissions.size() != 9)
37  return (mode_t)(-1);
38  bool user_r, user_w, user_x, group_r, group_w, group_x, world_r, world_w,
39  world_x;
40 
41  user_r = (permissions[0] == 'r');
42  user_w = (permissions[1] == 'w');
43  user_x = (permissions[2] == 'x');
44 
45  group_r = (permissions[3] == 'r');
46  group_w = (permissions[4] == 'w');
47  group_x = (permissions[5] == 'x');
48 
49  world_r = (permissions[6] == 'r');
50  world_w = (permissions[7] == 'w');
51  world_x = (permissions[8] == 'x');
52 
53  mode_t user, group, world;
54  user = (user_r ? 4 : 0) | (user_w ? 2 : 0) | (user_x ? 1 : 0);
55  group = (group_r ? 4 : 0) | (group_w ? 2 : 0) | (group_x ? 1 : 0);
56  world = (world_r ? 4 : 0) | (world_w ? 2 : 0) | (world_x ? 1 : 0);
57 
58  return user | group | world;
59 }
60 
61 static constexpr OptionDefinition g_permissions_options[] = {
62  // clang-format off
63  {LLDB_OPT_SET_ALL, false, "permissions-value", 'v', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePermissionsNumber, "Give out the numeric value for permissions (e.g. 757)"},
64  {LLDB_OPT_SET_ALL, false, "permissions-string", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePermissionsString, "Give out the string value for permissions (e.g. rwxr-xr--)."},
65  {LLDB_OPT_SET_ALL, false, "user-read", 'r', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow user to read."},
66  {LLDB_OPT_SET_ALL, false, "user-write", 'w', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow user to write."},
67  {LLDB_OPT_SET_ALL, false, "user-exec", 'x', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow user to execute."},
68  {LLDB_OPT_SET_ALL, false, "group-read", 'R', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow group to read."},
69  {LLDB_OPT_SET_ALL, false, "group-write", 'W', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow group to write."},
70  {LLDB_OPT_SET_ALL, false, "group-exec", 'X', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow group to execute."},
71  {LLDB_OPT_SET_ALL, false, "world-read", 'd', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow world to read."},
72  {LLDB_OPT_SET_ALL, false, "world-write", 't', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow world to write."},
73  {LLDB_OPT_SET_ALL, false, "world-exec", 'e', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow world to execute."},
74  // clang-format on
75 };
76 
78 public:
80 
81  ~OptionPermissions() override = default;
82 
84  SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
85  ExecutionContext *execution_context) override {
86  Status error;
87  char short_option = (char)GetDefinitions()[option_idx].short_option;
88  switch (short_option) {
89  case 'v': {
90  if (option_arg.getAsInteger(8, m_permissions)) {
91  m_permissions = 0777;
92  error.SetErrorStringWithFormat("invalid value for permissions: %s",
93  option_arg.str().c_str());
94  }
95 
96  } break;
97  case 's': {
98  mode_t perms = ParsePermissionString(option_arg);
99  if (perms == (mode_t)-1)
100  error.SetErrorStringWithFormat("invalid value for permissions: %s",
101  option_arg.str().c_str());
102  else
103  m_permissions = perms;
104  } break;
105  case 'r':
106  m_permissions |= lldb::eFilePermissionsUserRead;
107  break;
108  case 'w':
109  m_permissions |= lldb::eFilePermissionsUserWrite;
110  break;
111  case 'x':
112  m_permissions |= lldb::eFilePermissionsUserExecute;
113  break;
114  case 'R':
115  m_permissions |= lldb::eFilePermissionsGroupRead;
116  break;
117  case 'W':
118  m_permissions |= lldb::eFilePermissionsGroupWrite;
119  break;
120  case 'X':
121  m_permissions |= lldb::eFilePermissionsGroupExecute;
122  break;
123  case 'd':
124  m_permissions |= lldb::eFilePermissionsWorldRead;
125  break;
126  case 't':
127  m_permissions |= lldb::eFilePermissionsWorldWrite;
128  break;
129  case 'e':
130  m_permissions |= lldb::eFilePermissionsWorldExecute;
131  break;
132  default:
133  error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
134  break;
135  }
136 
137  return error;
138  }
139 
140  void OptionParsingStarting(ExecutionContext *execution_context) override {
141  m_permissions = 0;
142  }
143 
144  llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
145  return llvm::makeArrayRef(g_permissions_options);
146  }
147 
148  // Instance variables to hold the values for command options.
149 
151 
152 private:
153  DISALLOW_COPY_AND_ASSIGN(OptionPermissions);
154 };
155 
156 // "platform select <platform-name>"
158 public:
160  : CommandObjectParsed(interpreter, "platform select",
161  "Create a platform if needed and select it as the "
162  "current platform.",
163  "platform select <platform-name>", 0),
164  m_option_group(),
165  m_platform_options(
166  false) // Don't include the "--platform" option by passing false
167  {
168  m_option_group.Append(&m_platform_options, LLDB_OPT_SET_ALL, 1);
169  m_option_group.Finalize();
170  }
171 
172  ~CommandObjectPlatformSelect() override = default;
173 
174  int HandleCompletion(CompletionRequest &request) override {
175  CommandCompletions::PlatformPluginNames(GetCommandInterpreter(), request,
176  nullptr);
177  return request.GetNumberOfMatches();
178  }
179 
180  Options *GetOptions() override { return &m_option_group; }
181 
182 protected:
183  bool DoExecute(Args &args, CommandReturnObject &result) override {
184  if (args.GetArgumentCount() == 1) {
185  const char *platform_name = args.GetArgumentAtIndex(0);
186  if (platform_name && platform_name[0]) {
187  const bool select = true;
188  m_platform_options.SetPlatformName(platform_name);
189  Status error;
190  ArchSpec platform_arch;
191  PlatformSP platform_sp(m_platform_options.CreatePlatformWithOptions(
192  m_interpreter, ArchSpec(), select, error, platform_arch));
193  if (platform_sp) {
194  GetDebugger().GetPlatformList().SetSelectedPlatform(platform_sp);
195 
196  platform_sp->GetStatus(result.GetOutputStream());
198  } else {
199  result.AppendError(error.AsCString());
201  }
202  } else {
203  result.AppendError("invalid platform name");
205  }
206  } else {
207  result.AppendError(
208  "platform create takes a platform name as an argument\n");
210  }
211  return result.Succeeded();
212  }
213 
216 };
217 
218 // "platform list"
220 public:
222  : CommandObjectParsed(interpreter, "platform list",
223  "List all platforms that are available.", nullptr,
224  0) {}
225 
226  ~CommandObjectPlatformList() override = default;
227 
228 protected:
229  bool DoExecute(Args &args, CommandReturnObject &result) override {
230  Stream &ostrm = result.GetOutputStream();
231  ostrm.Printf("Available platforms:\n");
232 
233  PlatformSP host_platform_sp(Platform::GetHostPlatform());
234  ostrm.Printf("%s: %s\n", host_platform_sp->GetPluginName().GetCString(),
235  host_platform_sp->GetDescription());
236 
237  uint32_t idx;
238  for (idx = 0; 1; ++idx) {
239  const char *plugin_name =
240  PluginManager::GetPlatformPluginNameAtIndex(idx);
241  if (plugin_name == nullptr)
242  break;
243  const char *plugin_desc =
244  PluginManager::GetPlatformPluginDescriptionAtIndex(idx);
245  if (plugin_desc == nullptr)
246  break;
247  ostrm.Printf("%s: %s\n", plugin_name, plugin_desc);
248  }
249 
250  if (idx == 0) {
251  result.AppendError("no platforms are available\n");
253  } else
255  return result.Succeeded();
256  }
257 };
258 
259 // "platform status"
261 public:
263  : CommandObjectParsed(interpreter, "platform status",
264  "Display status for the current platform.", nullptr,
265  0) {}
266 
267  ~CommandObjectPlatformStatus() override = default;
268 
269 protected:
270  bool DoExecute(Args &args, CommandReturnObject &result) override {
271  Stream &ostrm = result.GetOutputStream();
272 
273  Target *target = GetDebugger().GetSelectedTarget().get();
274  PlatformSP platform_sp;
275  if (target) {
276  platform_sp = target->GetPlatform();
277  }
278  if (!platform_sp) {
279  platform_sp = GetDebugger().GetPlatformList().GetSelectedPlatform();
280  }
281  if (platform_sp) {
282  platform_sp->GetStatus(ostrm);
284  } else {
285  result.AppendError("no platform is currently selected\n");
287  }
288  return result.Succeeded();
289  }
290 };
291 
292 // "platform connect <connect-url>"
294 public:
297  interpreter, "platform connect",
298  "Select the current platform by providing a connection URL.",
299  "platform connect <connect-url>", 0) {}
300 
301  ~CommandObjectPlatformConnect() override = default;
302 
303 protected:
304  bool DoExecute(Args &args, CommandReturnObject &result) override {
305  Stream &ostrm = result.GetOutputStream();
306 
307  PlatformSP platform_sp(
308  GetDebugger().GetPlatformList().GetSelectedPlatform());
309  if (platform_sp) {
310  Status error(platform_sp->ConnectRemote(args));
311  if (error.Success()) {
312  platform_sp->GetStatus(ostrm);
314 
315  platform_sp->ConnectToWaitingProcesses(GetDebugger(), error);
316  if (error.Fail()) {
317  result.AppendError(error.AsCString());
319  }
320  } else {
321  result.AppendErrorWithFormat("%s\n", error.AsCString());
323  }
324  } else {
325  result.AppendError("no platform is currently selected\n");
327  }
328  return result.Succeeded();
329  }
330 
331  Options *GetOptions() override {
332  PlatformSP platform_sp(
333  GetDebugger().GetPlatformList().GetSelectedPlatform());
334  OptionGroupOptions *m_platform_options = nullptr;
335  if (platform_sp) {
336  m_platform_options = platform_sp->GetConnectionOptions(m_interpreter);
337  if (m_platform_options != nullptr && !m_platform_options->m_did_finalize)
338  m_platform_options->Finalize();
339  }
340  return m_platform_options;
341  }
342 };
343 
344 // "platform disconnect"
346 public:
348  : CommandObjectParsed(interpreter, "platform disconnect",
349  "Disconnect from the current platform.",
350  "platform disconnect", 0) {}
351 
352  ~CommandObjectPlatformDisconnect() override = default;
353 
354 protected:
355  bool DoExecute(Args &args, CommandReturnObject &result) override {
356  PlatformSP platform_sp(
357  GetDebugger().GetPlatformList().GetSelectedPlatform());
358  if (platform_sp) {
359  if (args.GetArgumentCount() == 0) {
360  Status error;
361 
362  if (platform_sp->IsConnected()) {
363  // Cache the instance name if there is one since we are about to
364  // disconnect and the name might go with it.
365  const char *hostname_cstr = platform_sp->GetHostname();
366  std::string hostname;
367  if (hostname_cstr)
368  hostname.assign(hostname_cstr);
369 
370  error = platform_sp->DisconnectRemote();
371  if (error.Success()) {
372  Stream &ostrm = result.GetOutputStream();
373  if (hostname.empty())
374  ostrm.Printf("Disconnected from \"%s\"\n",
375  platform_sp->GetPluginName().GetCString());
376  else
377  ostrm.Printf("Disconnected from \"%s\"\n", hostname.c_str());
379  } else {
380  result.AppendErrorWithFormat("%s", error.AsCString());
382  }
383  } else {
384  // Not connected...
385  result.AppendErrorWithFormat(
386  "not connected to '%s'",
387  platform_sp->GetPluginName().GetCString());
389  }
390  } else {
391  // Bad args
392  result.AppendError(
393  "\"platform disconnect\" doesn't take any arguments");
395  }
396  } else {
397  result.AppendError("no platform is currently selected");
399  }
400  return result.Succeeded();
401  }
402 };
403 
404 // "platform settings"
406 public:
408  : CommandObjectParsed(interpreter, "platform settings",
409  "Set settings for the current target's platform, "
410  "or for a platform by name.",
411  "platform settings", 0),
412  m_options(),
413  m_option_working_dir(LLDB_OPT_SET_1, false, "working-dir", 'w', 0,
414  eArgTypePath,
415  "The working directory for the platform.") {
416  m_options.Append(&m_option_working_dir, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
417  }
418 
419  ~CommandObjectPlatformSettings() override = default;
420 
421 protected:
422  bool DoExecute(Args &args, CommandReturnObject &result) override {
423  PlatformSP platform_sp(
424  GetDebugger().GetPlatformList().GetSelectedPlatform());
425  if (platform_sp) {
426  if (m_option_working_dir.GetOptionValue().OptionWasSet())
427  platform_sp->SetWorkingDirectory(
428  m_option_working_dir.GetOptionValue().GetCurrentValue());
429  } else {
430  result.AppendError("no platform is currently selected");
432  }
433  return result.Succeeded();
434  }
435 
436  Options *GetOptions() override {
437  if (!m_options.DidFinalize())
438  m_options.Finalize();
439  return &m_options;
440  }
441 
442 protected:
445 };
446 
447 // "platform mkdir"
449 public:
451  : CommandObjectParsed(interpreter, "platform mkdir",
452  "Make a new directory on the remote end.", nullptr,
453  0),
454  m_options() {}
455 
456  ~CommandObjectPlatformMkDir() override = default;
457 
458  bool DoExecute(Args &args, CommandReturnObject &result) override {
459  PlatformSP platform_sp(
460  GetDebugger().GetPlatformList().GetSelectedPlatform());
461  if (platform_sp) {
462  std::string cmd_line;
463  args.GetCommandString(cmd_line);
464  uint32_t mode;
465  const OptionPermissions *options_permissions =
466  (const OptionPermissions *)m_options.GetGroupWithOption('r');
467  if (options_permissions)
468  mode = options_permissions->m_permissions;
469  else
470  mode = lldb::eFilePermissionsUserRWX | lldb::eFilePermissionsGroupRWX |
471  lldb::eFilePermissionsWorldRX;
472  Status error = platform_sp->MakeDirectory(FileSpec(cmd_line), mode);
473  if (error.Success()) {
475  } else {
476  result.AppendError(error.AsCString());
478  }
479  } else {
480  result.AppendError("no platform currently selected\n");
482  }
483  return result.Succeeded();
484  }
485 
486  Options *GetOptions() override {
487  if (!m_options.DidFinalize()) {
488  m_options.Append(new OptionPermissions());
489  m_options.Finalize();
490  }
491  return &m_options;
492  }
493 
495 };
496 
497 // "platform fopen"
499 public:
501  : CommandObjectParsed(interpreter, "platform file open",
502  "Open a file on the remote end.", nullptr, 0),
503  m_options() {}
504 
505  ~CommandObjectPlatformFOpen() override = default;
506 
507  bool DoExecute(Args &args, CommandReturnObject &result) override {
508  PlatformSP platform_sp(
509  GetDebugger().GetPlatformList().GetSelectedPlatform());
510  if (platform_sp) {
511  Status error;
512  std::string cmd_line;
513  args.GetCommandString(cmd_line);
514  mode_t perms;
515  const OptionPermissions *options_permissions =
516  (const OptionPermissions *)m_options.GetGroupWithOption('r');
517  if (options_permissions)
518  perms = options_permissions->m_permissions;
519  else
520  perms = lldb::eFilePermissionsUserRW | lldb::eFilePermissionsGroupRW |
521  lldb::eFilePermissionsWorldRead;
522  lldb::user_id_t fd = platform_sp->OpenFile(
523  FileSpec(cmd_line),
524  File::eOpenOptionRead | File::eOpenOptionWrite |
525  File::eOpenOptionAppend | File::eOpenOptionCanCreate,
526  perms, error);
527  if (error.Success()) {
528  result.AppendMessageWithFormat("File Descriptor = %" PRIu64 "\n", fd);
530  } else {
531  result.AppendError(error.AsCString());
533  }
534  } else {
535  result.AppendError("no platform currently selected\n");
537  }
538  return result.Succeeded();
539  }
540 
541  Options *GetOptions() override {
542  if (!m_options.DidFinalize()) {
543  m_options.Append(new OptionPermissions());
544  m_options.Finalize();
545  }
546  return &m_options;
547  }
548 
550 };
551 
552 // "platform fclose"
554 public:
556  : CommandObjectParsed(interpreter, "platform file close",
557  "Close a file on the remote end.", nullptr, 0) {}
558 
559  ~CommandObjectPlatformFClose() override = default;
560 
561  bool DoExecute(Args &args, CommandReturnObject &result) override {
562  PlatformSP platform_sp(
563  GetDebugger().GetPlatformList().GetSelectedPlatform());
564  if (platform_sp) {
565  std::string cmd_line;
566  args.GetCommandString(cmd_line);
567  const lldb::user_id_t fd =
568  StringConvert::ToUInt64(cmd_line.c_str(), UINT64_MAX);
569  Status error;
570  bool success = platform_sp->CloseFile(fd, error);
571  if (success) {
572  result.AppendMessageWithFormat("file %" PRIu64 " closed.\n", fd);
574  } else {
575  result.AppendError(error.AsCString());
577  }
578  } else {
579  result.AppendError("no platform currently selected\n");
581  }
582  return result.Succeeded();
583  }
584 };
585 
586 // "platform fread"
587 
588 static constexpr OptionDefinition g_platform_fread_options[] = {
589  // clang-format off
590  { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeIndex, "Offset into the file at which to start reading." },
591  { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "Number of bytes to read from the file." },
592  // clang-format on
593 };
594 
596 public:
598  : CommandObjectParsed(interpreter, "platform file read",
599  "Read data from a file on the remote end.", nullptr,
600  0),
601  m_options() {}
602 
603  ~CommandObjectPlatformFRead() override = default;
604 
605  bool DoExecute(Args &args, CommandReturnObject &result) override {
606  PlatformSP platform_sp(
607  GetDebugger().GetPlatformList().GetSelectedPlatform());
608  if (platform_sp) {
609  std::string cmd_line;
610  args.GetCommandString(cmd_line);
611  const lldb::user_id_t fd =
612  StringConvert::ToUInt64(cmd_line.c_str(), UINT64_MAX);
613  std::string buffer(m_options.m_count, 0);
614  Status error;
615  uint32_t retcode = platform_sp->ReadFile(
616  fd, m_options.m_offset, &buffer[0], m_options.m_count, error);
617  result.AppendMessageWithFormat("Return = %d\n", retcode);
618  result.AppendMessageWithFormat("Data = \"%s\"\n", buffer.c_str());
620  } else {
621  result.AppendError("no platform currently selected\n");
623  }
624  return result.Succeeded();
625  }
626 
627  Options *GetOptions() override { return &m_options; }
628 
629 protected:
630  class CommandOptions : public Options {
631  public:
633 
634  ~CommandOptions() override = default;
635 
636  Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
637  ExecutionContext *execution_context) override {
638  Status error;
639  char short_option = (char)m_getopt_table[option_idx].val;
640 
641  switch (short_option) {
642  case 'o':
643  if (option_arg.getAsInteger(0, m_offset))
644  error.SetErrorStringWithFormat("invalid offset: '%s'",
645  option_arg.str().c_str());
646  break;
647  case 'c':
648  if (option_arg.getAsInteger(0, m_count))
649  error.SetErrorStringWithFormat("invalid offset: '%s'",
650  option_arg.str().c_str());
651  break;
652  default:
653  error.SetErrorStringWithFormat("unrecognized option '%c'",
654  short_option);
655  break;
656  }
657 
658  return error;
659  }
660 
661  void OptionParsingStarting(ExecutionContext *execution_context) override {
662  m_offset = 0;
663  m_count = 1;
664  }
665 
666  llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
667  return llvm::makeArrayRef(g_platform_fread_options);
668  }
669 
670  // Instance variables to hold the values for command options.
671 
674  };
675 
677 };
678 
679 // "platform fwrite"
680 
681 static constexpr OptionDefinition g_platform_fwrite_options[] = {
682  // clang-format off
683  { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeIndex, "Offset into the file at which to start reading." },
684  { LLDB_OPT_SET_1, false, "data", 'd', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeValue, "Text to write to the file." },
685  // clang-format on
686 };
687 
689 public:
691  : CommandObjectParsed(interpreter, "platform file write",
692  "Write data to a file on the remote end.", nullptr,
693  0),
694  m_options() {}
695 
696  ~CommandObjectPlatformFWrite() override = default;
697 
698  bool DoExecute(Args &args, CommandReturnObject &result) override {
699  PlatformSP platform_sp(
700  GetDebugger().GetPlatformList().GetSelectedPlatform());
701  if (platform_sp) {
702  std::string cmd_line;
703  args.GetCommandString(cmd_line);
704  Status error;
705  const lldb::user_id_t fd =
706  StringConvert::ToUInt64(cmd_line.c_str(), UINT64_MAX);
707  uint32_t retcode =
708  platform_sp->WriteFile(fd, m_options.m_offset, &m_options.m_data[0],
709  m_options.m_data.size(), error);
710  result.AppendMessageWithFormat("Return = %d\n", retcode);
712  } else {
713  result.AppendError("no platform currently selected\n");
715  }
716  return result.Succeeded();
717  }
718 
719  Options *GetOptions() override { return &m_options; }
720 
721 protected:
722  class CommandOptions : public Options {
723  public:
725 
726  ~CommandOptions() override = default;
727 
728  Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
729  ExecutionContext *execution_context) override {
730  Status error;
731  char short_option = (char)m_getopt_table[option_idx].val;
732 
733  switch (short_option) {
734  case 'o':
735  if (option_arg.getAsInteger(0, m_offset))
736  error.SetErrorStringWithFormat("invalid offset: '%s'",
737  option_arg.str().c_str());
738  break;
739  case 'd':
740  m_data.assign(option_arg);
741  break;
742  default:
743  error.SetErrorStringWithFormat("unrecognized option '%c'",
744  short_option);
745  break;
746  }
747 
748  return error;
749  }
750 
751  void OptionParsingStarting(ExecutionContext *execution_context) override {
752  m_offset = 0;
753  m_data.clear();
754  }
755 
756  llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
757  return llvm::makeArrayRef(g_platform_fwrite_options);
758  }
759 
760  // Instance variables to hold the values for command options.
761 
763  std::string m_data;
764  };
765 
767 };
768 
770 public:
771  // Constructors and Destructors
774  interpreter, "platform file",
775  "Commands to access files on the current platform.",
776  "platform file [open|close|read|write] ...") {
777  LoadSubCommand(
778  "open", CommandObjectSP(new CommandObjectPlatformFOpen(interpreter)));
779  LoadSubCommand(
780  "close", CommandObjectSP(new CommandObjectPlatformFClose(interpreter)));
781  LoadSubCommand(
782  "read", CommandObjectSP(new CommandObjectPlatformFRead(interpreter)));
783  LoadSubCommand(
784  "write", CommandObjectSP(new CommandObjectPlatformFWrite(interpreter)));
785  }
786 
787  ~CommandObjectPlatformFile() override = default;
788 
789 private:
790  // For CommandObjectPlatform only
791  DISALLOW_COPY_AND_ASSIGN(CommandObjectPlatformFile);
792 };
793 
794 // "platform get-file remote-file-path host-file-path"
796 public:
799  interpreter, "platform get-file",
800  "Transfer a file from the remote end to the local host.",
801  "platform get-file <remote-file-spec> <local-file-spec>", 0) {
802  SetHelpLong(
803  R"(Examples:
804 
805 (lldb) platform get-file /the/remote/file/path /the/local/file/path
806 
807  Transfer a file from the remote end with file path /the/remote/file/path to the local host.)");
808 
809  CommandArgumentEntry arg1, arg2;
810  CommandArgumentData file_arg_remote, file_arg_host;
811 
812  // Define the first (and only) variant of this arg.
813  file_arg_remote.arg_type = eArgTypeFilename;
814  file_arg_remote.arg_repetition = eArgRepeatPlain;
815  // There is only one variant this argument could be; put it into the
816  // argument entry.
817  arg1.push_back(file_arg_remote);
818 
819  // Define the second (and only) variant of this arg.
820  file_arg_host.arg_type = eArgTypeFilename;
821  file_arg_host.arg_repetition = eArgRepeatPlain;
822  // There is only one variant this argument could be; put it into the
823  // argument entry.
824  arg2.push_back(file_arg_host);
825 
826  // Push the data for the first and the second arguments into the
827  // m_arguments vector.
828  m_arguments.push_back(arg1);
829  m_arguments.push_back(arg2);
830  }
831 
832  ~CommandObjectPlatformGetFile() override = default;
833 
834  bool DoExecute(Args &args, CommandReturnObject &result) override {
835  // If the number of arguments is incorrect, issue an error message.
836  if (args.GetArgumentCount() != 2) {
837  result.GetErrorStream().Printf("error: required arguments missing; "
838  "specify both the source and destination "
839  "file paths\n");
841  return false;
842  }
843 
844  PlatformSP platform_sp(
845  GetDebugger().GetPlatformList().GetSelectedPlatform());
846  if (platform_sp) {
847  const char *remote_file_path = args.GetArgumentAtIndex(0);
848  const char *local_file_path = args.GetArgumentAtIndex(1);
849  Status error = platform_sp->GetFile(FileSpec(remote_file_path),
850  FileSpec(local_file_path));
851  if (error.Success()) {
853  "successfully get-file from %s (remote) to %s (host)\n",
854  remote_file_path, local_file_path);
856  } else {
857  result.AppendMessageWithFormat("get-file failed: %s\n",
858  error.AsCString());
860  }
861  } else {
862  result.AppendError("no platform currently selected\n");
864  }
865  return result.Succeeded();
866  }
867 };
868 
869 // "platform get-size remote-file-path"
871 public:
873  : CommandObjectParsed(interpreter, "platform get-size",
874  "Get the file size from the remote end.",
875  "platform get-size <remote-file-spec>", 0) {
876  SetHelpLong(
877  R"(Examples:
878 
879 (lldb) platform get-size /the/remote/file/path
880 
881  Get the file size from the remote end with path /the/remote/file/path.)");
882 
884  CommandArgumentData file_arg_remote;
885 
886  // Define the first (and only) variant of this arg.
887  file_arg_remote.arg_type = eArgTypeFilename;
888  file_arg_remote.arg_repetition = eArgRepeatPlain;
889  // There is only one variant this argument could be; put it into the
890  // argument entry.
891  arg1.push_back(file_arg_remote);
892 
893  // Push the data for the first argument into the m_arguments vector.
894  m_arguments.push_back(arg1);
895  }
896 
897  ~CommandObjectPlatformGetSize() override = default;
898 
899  bool DoExecute(Args &args, CommandReturnObject &result) override {
900  // If the number of arguments is incorrect, issue an error message.
901  if (args.GetArgumentCount() != 1) {
902  result.GetErrorStream().Printf("error: required argument missing; "
903  "specify the source file path as the only "
904  "argument\n");
906  return false;
907  }
908 
909  PlatformSP platform_sp(
910  GetDebugger().GetPlatformList().GetSelectedPlatform());
911  if (platform_sp) {
912  std::string remote_file_path(args.GetArgumentAtIndex(0));
913  user_id_t size = platform_sp->GetFileSize(FileSpec(remote_file_path));
914  if (size != UINT64_MAX) {
915  result.AppendMessageWithFormat("File size of %s (remote): %" PRIu64
916  "\n",
917  remote_file_path.c_str(), size);
919  } else {
921  "Error getting file size of %s (remote)\n",
922  remote_file_path.c_str());
924  }
925  } else {
926  result.AppendError("no platform currently selected\n");
928  }
929  return result.Succeeded();
930  }
931 };
932 
933 // "platform put-file"
935 public:
938  interpreter, "platform put-file",
939  "Transfer a file from this system to the remote end.", nullptr, 0) {
940  }
941 
942  ~CommandObjectPlatformPutFile() override = default;
943 
944  bool DoExecute(Args &args, CommandReturnObject &result) override {
945  const char *src = args.GetArgumentAtIndex(0);
946  const char *dst = args.GetArgumentAtIndex(1);
947 
948  FileSpec src_fs(src);
949  FileSystem::Instance().Resolve(src_fs);
950  FileSpec dst_fs(dst ? dst : src_fs.GetFilename().GetCString());
951 
952  PlatformSP platform_sp(
953  GetDebugger().GetPlatformList().GetSelectedPlatform());
954  if (platform_sp) {
955  Status error(platform_sp->PutFile(src_fs, dst_fs));
956  if (error.Success()) {
958  } else {
959  result.AppendError(error.AsCString());
961  }
962  } else {
963  result.AppendError("no platform currently selected\n");
965  }
966  return result.Succeeded();
967  }
968 };
969 
970 // "platform process launch"
972 public:
974  : CommandObjectParsed(interpreter, "platform process launch",
975  "Launch a new process on a remote platform.",
976  "platform process launch program",
977  eCommandRequiresTarget | eCommandTryTargetAPILock),
978  m_options() {}
979 
980  ~CommandObjectPlatformProcessLaunch() override = default;
981 
982  Options *GetOptions() override { return &m_options; }
983 
984 protected:
985  bool DoExecute(Args &args, CommandReturnObject &result) override {
986  Target *target = GetDebugger().GetSelectedTarget().get();
987  PlatformSP platform_sp;
988  if (target) {
989  platform_sp = target->GetPlatform();
990  }
991  if (!platform_sp) {
992  platform_sp = GetDebugger().GetPlatformList().GetSelectedPlatform();
993  }
994 
995  if (platform_sp) {
996  Status error;
997  const size_t argc = args.GetArgumentCount();
998  Target *target = m_exe_ctx.GetTargetPtr();
999  Module *exe_module = target->GetExecutableModulePointer();
1000  if (exe_module) {
1001  m_options.launch_info.GetExecutableFile() = exe_module->GetFileSpec();
1002  llvm::SmallString<128> exe_path;
1003  m_options.launch_info.GetExecutableFile().GetPath(exe_path);
1004  if (!exe_path.empty())
1005  m_options.launch_info.GetArguments().AppendArgument(exe_path);
1006  m_options.launch_info.GetArchitecture() = exe_module->GetArchitecture();
1007  }
1008 
1009  if (argc > 0) {
1010  if (m_options.launch_info.GetExecutableFile()) {
1011  // We already have an executable file, so we will use this and all
1012  // arguments to this function are extra arguments
1013  m_options.launch_info.GetArguments().AppendArguments(args);
1014  } else {
1015  // We don't have any file yet, so the first argument is our
1016  // executable, and the rest are program arguments
1017  const bool first_arg_is_executable = true;
1018  m_options.launch_info.SetArguments(args, first_arg_is_executable);
1019  }
1020  }
1021 
1022  if (m_options.launch_info.GetExecutableFile()) {
1023  Debugger &debugger = GetDebugger();
1024 
1025  if (argc == 0)
1026  target->GetRunArguments(m_options.launch_info.GetArguments());
1027 
1028  ProcessSP process_sp(platform_sp->DebugProcess(
1029  m_options.launch_info, debugger, target, error));
1030  if (process_sp && process_sp->IsAlive()) {
1032  return true;
1033  }
1034 
1035  if (error.Success())
1036  result.AppendError("process launch failed");
1037  else
1038  result.AppendError(error.AsCString());
1040  } else {
1041  result.AppendError("'platform process launch' uses the current target "
1042  "file and arguments, or the executable and its "
1043  "arguments can be specified in this command");
1045  return false;
1046  }
1047  } else {
1048  result.AppendError("no platform is selected\n");
1049  }
1050  return result.Succeeded();
1051  }
1052 
1053 protected:
1055 };
1056 
1057 // "platform process list"
1058 
1059 static OptionDefinition g_platform_process_list_options[] = {
1060  // clang-format off
1061  { LLDB_OPT_SET_1, false, "pid", 'p', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePid, "List the process info for a specific process ID." },
1062  { LLDB_OPT_SET_2, true, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeProcessName, "Find processes with executable basenames that match a string." },
1063  { LLDB_OPT_SET_3, true, "ends-with", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeProcessName, "Find processes with executable basenames that end with a string." },
1064  { LLDB_OPT_SET_4, true, "starts-with", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeProcessName, "Find processes with executable basenames that start with a string." },
1065  { LLDB_OPT_SET_5, true, "contains", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeProcessName, "Find processes with executable basenames that contain a string." },
1066  { LLDB_OPT_SET_6, true, "regex", 'r', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeRegularExpression, "Find processes with executable basenames that match a regular expression." },
1067  { LLDB_OPT_SET_FROM_TO(2, 6), false, "parent", 'P', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePid, "Find processes that have a matching parent process ID." },
1068  { LLDB_OPT_SET_FROM_TO(2, 6), false, "uid", 'u', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Find processes that have a matching user ID." },
1069  { LLDB_OPT_SET_FROM_TO(2, 6), false, "euid", 'U', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Find processes that have a matching effective user ID." },
1070  { LLDB_OPT_SET_FROM_TO(2, 6), false, "gid", 'g', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Find processes that have a matching group ID." },
1071  { LLDB_OPT_SET_FROM_TO(2, 6), false, "egid", 'G', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Find processes that have a matching effective group ID." },
1072  { LLDB_OPT_SET_FROM_TO(2, 6), false, "arch", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeArchitecture, "Find processes that have a matching architecture." },
1073  { LLDB_OPT_SET_FROM_TO(1, 6), false, "show-args", 'A', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Show process arguments instead of the process executable basename." },
1074  { LLDB_OPT_SET_FROM_TO(1, 6), false, "verbose", 'v', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Enable verbose output." },
1075  // clang-format on
1076 };
1077 
1079 public:
1081  : CommandObjectParsed(interpreter, "platform process list",
1082  "List processes on a remote platform by name, pid, "
1083  "or many other matching attributes.",
1084  "platform process list", 0),
1085  m_options() {}
1086 
1087  ~CommandObjectPlatformProcessList() override = default;
1088 
1089  Options *GetOptions() override { return &m_options; }
1090 
1091 protected:
1092  bool DoExecute(Args &args, CommandReturnObject &result) override {
1093  Target *target = GetDebugger().GetSelectedTarget().get();
1094  PlatformSP platform_sp;
1095  if (target) {
1096  platform_sp = target->GetPlatform();
1097  }
1098  if (!platform_sp) {
1099  platform_sp = GetDebugger().GetPlatformList().GetSelectedPlatform();
1100  }
1101 
1102  if (platform_sp) {
1103  Status error;
1104  if (args.GetArgumentCount() == 0) {
1105  if (platform_sp) {
1106  Stream &ostrm = result.GetOutputStream();
1107 
1108  lldb::pid_t pid =
1109  m_options.match_info.GetProcessInfo().GetProcessID();
1110  if (pid != LLDB_INVALID_PROCESS_ID) {
1111  ProcessInstanceInfo proc_info;
1112  if (platform_sp->GetProcessInfo(pid, proc_info)) {
1113  ProcessInstanceInfo::DumpTableHeader(ostrm, m_options.show_args,
1114  m_options.verbose);
1115  proc_info.DumpAsTableRow(ostrm, platform_sp->GetUserIDResolver(),
1116  m_options.show_args, m_options.verbose);
1118  } else {
1119  result.AppendErrorWithFormat(
1120  "no process found with pid = %" PRIu64 "\n", pid);
1122  }
1123  } else {
1124  ProcessInstanceInfoList proc_infos;
1125  const uint32_t matches =
1126  platform_sp->FindProcesses(m_options.match_info, proc_infos);
1127  const char *match_desc = nullptr;
1128  const char *match_name =
1129  m_options.match_info.GetProcessInfo().GetName();
1130  if (match_name && match_name[0]) {
1131  switch (m_options.match_info.GetNameMatchType()) {
1132  case NameMatch::Ignore:
1133  break;
1134  case NameMatch::Equals:
1135  match_desc = "matched";
1136  break;
1137  case NameMatch::Contains:
1138  match_desc = "contained";
1139  break;
1140  case NameMatch::StartsWith:
1141  match_desc = "started with";
1142  break;
1143  case NameMatch::EndsWith:
1144  match_desc = "ended with";
1145  break;
1146  case NameMatch::RegularExpression:
1147  match_desc = "matched the regular expression";
1148  break;
1149  }
1150  }
1151 
1152  if (matches == 0) {
1153  if (match_desc)
1154  result.AppendErrorWithFormat(
1155  "no processes were found that %s \"%s\" on the \"%s\" "
1156  "platform\n",
1157  match_desc, match_name,
1158  platform_sp->GetPluginName().GetCString());
1159  else
1160  result.AppendErrorWithFormat(
1161  "no processes were found on the \"%s\" platform\n",
1162  platform_sp->GetPluginName().GetCString());
1164  } else {
1165  result.AppendMessageWithFormat(
1166  "%u matching process%s found on \"%s\"", matches,
1167  matches > 1 ? "es were" : " was",
1168  platform_sp->GetName().GetCString());
1169  if (match_desc)
1170  result.AppendMessageWithFormat(" whose name %s \"%s\"",
1171  match_desc, match_name);
1172  result.AppendMessageWithFormat("\n");
1173  ProcessInstanceInfo::DumpTableHeader(ostrm, m_options.show_args,
1174  m_options.verbose);
1175  for (uint32_t i = 0; i < matches; ++i) {
1176  proc_infos.GetProcessInfoAtIndex(i).DumpAsTableRow(
1177  ostrm, platform_sp->GetUserIDResolver(),
1178  m_options.show_args, m_options.verbose);
1179  }
1180  }
1181  }
1182  }
1183  } else {
1184  result.AppendError("invalid args: process list takes only options\n");
1186  }
1187  } else {
1188  result.AppendError("no platform is selected\n");
1190  }
1191  return result.Succeeded();
1192  }
1193 
1194  class CommandOptions : public Options {
1195  public:
1197  : Options(), match_info(), show_args(false), verbose(false) {
1198  static llvm::once_flag g_once_flag;
1199  llvm::call_once(g_once_flag, []() {
1200  PosixPlatformCommandOptionValidator *posix_validator =
1202  for (auto &Option : g_platform_process_list_options) {
1203  switch (Option.short_option) {
1204  case 'u':
1205  case 'U':
1206  case 'g':
1207  case 'G':
1208  Option.validator = posix_validator;
1209  break;
1210  default:
1211  break;
1212  }
1213  }
1214  });
1215  }
1216 
1217  ~CommandOptions() override = default;
1218 
1219  Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1220  ExecutionContext *execution_context) override {
1221  Status error;
1222  const int short_option = m_getopt_table[option_idx].val;
1223  bool success = false;
1224 
1226  success = !option_arg.getAsInteger(0, id);
1227  switch (short_option) {
1228  case 'p': {
1229  match_info.GetProcessInfo().SetProcessID(id);
1230  if (!success)
1231  error.SetErrorStringWithFormat("invalid process ID string: '%s'",
1232  option_arg.str().c_str());
1233  break;
1234  }
1235  case 'P':
1236  match_info.GetProcessInfo().SetParentProcessID(id);
1237  if (!success)
1239  "invalid parent process ID string: '%s'",
1240  option_arg.str().c_str());
1241  break;
1242 
1243  case 'u':
1244  match_info.GetProcessInfo().SetUserID(success ? id : UINT32_MAX);
1245  if (!success)
1246  error.SetErrorStringWithFormat("invalid user ID string: '%s'",
1247  option_arg.str().c_str());
1248  break;
1249 
1250  case 'U':
1251  match_info.GetProcessInfo().SetEffectiveUserID(success ? id
1252  : UINT32_MAX);
1253  if (!success)
1255  "invalid effective user ID string: '%s'",
1256  option_arg.str().c_str());
1257  break;
1258 
1259  case 'g':
1260  match_info.GetProcessInfo().SetGroupID(success ? id : UINT32_MAX);
1261  if (!success)
1262  error.SetErrorStringWithFormat("invalid group ID string: '%s'",
1263  option_arg.str().c_str());
1264  break;
1265 
1266  case 'G':
1267  match_info.GetProcessInfo().SetEffectiveGroupID(success ? id
1268  : UINT32_MAX);
1269  if (!success)
1271  "invalid effective group ID string: '%s'",
1272  option_arg.str().c_str());
1273  break;
1274 
1275  case 'a': {
1276  TargetSP target_sp =
1277  execution_context ? execution_context->GetTargetSP() : TargetSP();
1278  DebuggerSP debugger_sp =
1279  target_sp ? target_sp->GetDebugger().shared_from_this()
1280  : DebuggerSP();
1281  PlatformSP platform_sp =
1282  debugger_sp ? debugger_sp->GetPlatformList().GetSelectedPlatform()
1283  : PlatformSP();
1284  match_info.GetProcessInfo().GetArchitecture() =
1285  Platform::GetAugmentedArchSpec(platform_sp.get(), option_arg);
1286  } break;
1287 
1288  case 'n':
1289  match_info.GetProcessInfo().GetExecutableFile().SetFile(
1290  option_arg, FileSpec::Style::native);
1291  match_info.SetNameMatchType(NameMatch::Equals);
1292  break;
1293 
1294  case 'e':
1295  match_info.GetProcessInfo().GetExecutableFile().SetFile(
1296  option_arg, FileSpec::Style::native);
1297  match_info.SetNameMatchType(NameMatch::EndsWith);
1298  break;
1299 
1300  case 's':
1301  match_info.GetProcessInfo().GetExecutableFile().SetFile(
1302  option_arg, FileSpec::Style::native);
1303  match_info.SetNameMatchType(NameMatch::StartsWith);
1304  break;
1305 
1306  case 'c':
1307  match_info.GetProcessInfo().GetExecutableFile().SetFile(
1308  option_arg, FileSpec::Style::native);
1309  match_info.SetNameMatchType(NameMatch::Contains);
1310  break;
1311 
1312  case 'r':
1313  match_info.GetProcessInfo().GetExecutableFile().SetFile(
1314  option_arg, FileSpec::Style::native);
1315  match_info.SetNameMatchType(NameMatch::RegularExpression);
1316  break;
1317 
1318  case 'A':
1319  show_args = true;
1320  break;
1321 
1322  case 'v':
1323  verbose = true;
1324  break;
1325 
1326  default:
1327  error.SetErrorStringWithFormat("unrecognized option '%c'",
1328  short_option);
1329  break;
1330  }
1331 
1332  return error;
1333  }
1334 
1335  void OptionParsingStarting(ExecutionContext *execution_context) override {
1336  match_info.Clear();
1337  show_args = false;
1338  verbose = false;
1339  }
1340 
1341  llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1342  return llvm::makeArrayRef(g_platform_process_list_options);
1343  }
1344 
1345  // Instance variables to hold the values for command options.
1346 
1349  bool verbose;
1350  };
1351 
1353 };
1354 
1355 // "platform process info"
1357 public:
1360  interpreter, "platform process info",
1361  "Get detailed information for one or more process by process ID.",
1362  "platform process info <pid> [<pid> <pid> ...]", 0) {
1364  CommandArgumentData pid_args;
1365 
1366  // Define the first (and only) variant of this arg.
1367  pid_args.arg_type = eArgTypePid;
1368  pid_args.arg_repetition = eArgRepeatStar;
1369 
1370  // There is only one variant this argument could be; put it into the
1371  // argument entry.
1372  arg.push_back(pid_args);
1373 
1374  // Push the data for the first argument into the m_arguments vector.
1375  m_arguments.push_back(arg);
1376  }
1377 
1378  ~CommandObjectPlatformProcessInfo() override = default;
1379 
1380 protected:
1381  bool DoExecute(Args &args, CommandReturnObject &result) override {
1382  Target *target = GetDebugger().GetSelectedTarget().get();
1383  PlatformSP platform_sp;
1384  if (target) {
1385  platform_sp = target->GetPlatform();
1386  }
1387  if (!platform_sp) {
1388  platform_sp = GetDebugger().GetPlatformList().GetSelectedPlatform();
1389  }
1390 
1391  if (platform_sp) {
1392  const size_t argc = args.GetArgumentCount();
1393  if (argc > 0) {
1394  Status error;
1395 
1396  if (platform_sp->IsConnected()) {
1397  Stream &ostrm = result.GetOutputStream();
1398  for (auto &entry : args.entries()) {
1399  lldb::pid_t pid;
1400  if (entry.ref.getAsInteger(0, pid)) {
1401  result.AppendErrorWithFormat("invalid process ID argument '%s'",
1402  entry.ref.str().c_str());
1404  break;
1405  } else {
1406  ProcessInstanceInfo proc_info;
1407  if (platform_sp->GetProcessInfo(pid, proc_info)) {
1408  ostrm.Printf("Process information for process %" PRIu64 ":\n",
1409  pid);
1410  proc_info.Dump(ostrm, platform_sp->GetUserIDResolver());
1411  } else {
1412  ostrm.Printf("error: no process information is available for "
1413  "process %" PRIu64 "\n",
1414  pid);
1415  }
1416  ostrm.EOL();
1417  }
1418  }
1419  } else {
1420  // Not connected...
1421  result.AppendErrorWithFormat(
1422  "not connected to '%s'",
1423  platform_sp->GetPluginName().GetCString());
1425  }
1426  } else {
1427  // No args
1428  result.AppendError("one or more process id(s) must be specified");
1430  }
1431  } else {
1432  result.AppendError("no platform is currently selected");
1434  }
1435  return result.Succeeded();
1436  }
1437 };
1438 
1439 static constexpr OptionDefinition g_platform_process_attach_options[] = {
1440  // clang-format off
1441  { LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePlugin, "Name of the process plugin you want to use." },
1442  { LLDB_OPT_SET_1, false, "pid", 'p', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePid, "The process ID of an existing process to attach to." },
1443  { LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeProcessName, "The name of the process to attach to." },
1444  { LLDB_OPT_SET_2, false, "waitfor", 'w', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Wait for the process with <process-name> to launch." },
1445  // clang-format on
1446 };
1447 
1449 public:
1450  class CommandOptions : public Options {
1451  public:
1453  // Keep default values of all options in one place: OptionParsingStarting
1454  // ()
1455  OptionParsingStarting(nullptr);
1456  }
1457 
1458  ~CommandOptions() override = default;
1459 
1460  Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1461  ExecutionContext *execution_context) override {
1462  Status error;
1463  char short_option = (char)m_getopt_table[option_idx].val;
1464  switch (short_option) {
1465  case 'p': {
1467  if (option_arg.getAsInteger(0, pid)) {
1468  error.SetErrorStringWithFormat("invalid process ID '%s'",
1469  option_arg.str().c_str());
1470  } else {
1471  attach_info.SetProcessID(pid);
1472  }
1473  } break;
1474 
1475  case 'P':
1476  attach_info.SetProcessPluginName(option_arg);
1477  break;
1478 
1479  case 'n':
1480  attach_info.GetExecutableFile().SetFile(option_arg,
1481  FileSpec::Style::native);
1482  break;
1483 
1484  case 'w':
1485  attach_info.SetWaitForLaunch(true);
1486  break;
1487 
1488  default:
1489  error.SetErrorStringWithFormat("invalid short option character '%c'",
1490  short_option);
1491  break;
1492  }
1493  return error;
1494  }
1495 
1496  void OptionParsingStarting(ExecutionContext *execution_context) override {
1497  attach_info.Clear();
1498  }
1499 
1500  llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1501  return llvm::makeArrayRef(g_platform_process_attach_options);
1502  }
1503 
1505  CompletionRequest &request, OptionElementVector &opt_element_vector,
1506  int opt_element_index, CommandInterpreter &interpreter) override {
1507  int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
1508  int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
1509 
1510  // We are only completing the name option for now...
1511 
1512  if (GetDefinitions()[opt_defs_index].short_option == 'n') {
1513  // Are we in the name?
1514 
1515  // Look to see if there is a -P argument provided, and if so use that
1516  // plugin, otherwise use the default plugin.
1517 
1518  const char *partial_name = nullptr;
1519  partial_name = request.GetParsedLine().GetArgumentAtIndex(opt_arg_pos);
1520 
1521  PlatformSP platform_sp(interpreter.GetPlatform(true));
1522  if (platform_sp) {
1523  ProcessInstanceInfoList process_infos;
1524  ProcessInstanceInfoMatch match_info;
1525  if (partial_name) {
1526  match_info.GetProcessInfo().GetExecutableFile().SetFile(
1527  partial_name, FileSpec::Style::native);
1528  match_info.SetNameMatchType(NameMatch::StartsWith);
1529  }
1530  platform_sp->FindProcesses(match_info, process_infos);
1531  const uint32_t num_matches = process_infos.GetSize();
1532  if (num_matches > 0) {
1533  for (uint32_t i = 0; i < num_matches; ++i) {
1534  request.AddCompletion(llvm::StringRef(
1535  process_infos.GetProcessNameAtIndex(i),
1536  process_infos.GetProcessNameLengthAtIndex(i)));
1537  }
1538  }
1539  }
1540  }
1541 
1542  return false;
1543  }
1544 
1545  // Options table: Required for subclasses of Options.
1546 
1547  static OptionDefinition g_option_table[];
1548 
1549  // Instance variables to hold the values for command options.
1550 
1552  };
1553 
1555  : CommandObjectParsed(interpreter, "platform process attach",
1556  "Attach to a process.",
1557  "platform process attach <cmd-options>"),
1558  m_options() {}
1559 
1560  ~CommandObjectPlatformProcessAttach() override = default;
1561 
1562  bool DoExecute(Args &command, CommandReturnObject &result) override {
1563  PlatformSP platform_sp(
1564  GetDebugger().GetPlatformList().GetSelectedPlatform());
1565  if (platform_sp) {
1566  Status err;
1567  ProcessSP remote_process_sp = platform_sp->Attach(
1568  m_options.attach_info, GetDebugger(), nullptr, err);
1569  if (err.Fail()) {
1570  result.AppendError(err.AsCString());
1572  } else if (!remote_process_sp) {
1573  result.AppendError("could not attach: unknown reason");
1575  } else
1577  } else {
1578  result.AppendError("no platform is currently selected");
1580  }
1581  return result.Succeeded();
1582  }
1583 
1584  Options *GetOptions() override { return &m_options; }
1585 
1586 protected:
1588 };
1589 
1591 public:
1592  // Constructors and Destructors
1594  : CommandObjectMultiword(interpreter, "platform process",
1595  "Commands to query, launch and attach to "
1596  "processes on the current platform.",
1597  "platform process [attach|launch|list] ...") {
1598  LoadSubCommand(
1599  "attach",
1600  CommandObjectSP(new CommandObjectPlatformProcessAttach(interpreter)));
1601  LoadSubCommand(
1602  "launch",
1603  CommandObjectSP(new CommandObjectPlatformProcessLaunch(interpreter)));
1604  LoadSubCommand("info", CommandObjectSP(new CommandObjectPlatformProcessInfo(
1605  interpreter)));
1606  LoadSubCommand("list", CommandObjectSP(new CommandObjectPlatformProcessList(
1607  interpreter)));
1608  }
1609 
1610  ~CommandObjectPlatformProcess() override = default;
1611 
1612 private:
1613  // For CommandObjectPlatform only
1614  DISALLOW_COPY_AND_ASSIGN(CommandObjectPlatformProcess);
1615 };
1616 
1617 // "platform shell"
1618 static constexpr OptionDefinition g_platform_shell_options[] = {
1619  // clang-format off
1620  { LLDB_OPT_SET_ALL, false, "timeout", 't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeValue, "Seconds to wait for the remote host to finish running the command." },
1621  // clang-format on
1622 };
1623 
1625 public:
1626  class CommandOptions : public Options {
1627  public:
1629 
1630  ~CommandOptions() override = default;
1631 
1632  llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1633  return llvm::makeArrayRef(g_platform_shell_options);
1634  }
1635 
1636  Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1637  ExecutionContext *execution_context) override {
1638  Status error;
1639 
1640  const char short_option = (char)GetDefinitions()[option_idx].short_option;
1641 
1642  switch (short_option) {
1643  case 't':
1644  uint32_t timeout_sec;
1645  if (option_arg.getAsInteger(10, timeout_sec))
1647  "could not convert \"%s\" to a numeric value.",
1648  option_arg.str().c_str());
1649  else
1650  timeout = std::chrono::seconds(timeout_sec);
1651  break;
1652  default:
1653  error.SetErrorStringWithFormat("invalid short option character '%c'",
1654  short_option);
1655  break;
1656  }
1657 
1658  return error;
1659  }
1660 
1661  void OptionParsingStarting(ExecutionContext *execution_context) override {}
1662 
1663  Timeout<std::micro> timeout = std::chrono::seconds(10);
1664  };
1665 
1667  : CommandObjectRaw(interpreter, "platform shell",
1668  "Run a shell command on the current platform.",
1669  "platform shell <shell-command>", 0),
1670  m_options() {}
1671 
1672  ~CommandObjectPlatformShell() override = default;
1673 
1674  Options *GetOptions() override { return &m_options; }
1675 
1676  bool DoExecute(llvm::StringRef raw_command_line,
1677  CommandReturnObject &result) override {
1678  ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext();
1679  m_options.NotifyOptionParsingStarting(&exe_ctx);
1680 
1681 
1682  // Print out an usage syntax on an empty command line.
1683  if (raw_command_line.empty()) {
1684  result.GetOutputStream().Printf("%s\n", this->GetSyntax().str().c_str());
1685  return true;
1686  }
1687 
1688  OptionsWithRaw args(raw_command_line);
1689  const char *expr = args.GetRawPart().c_str();
1690 
1691  if (args.HasArgs())
1692  if (!ParseOptions(args.GetArgs(), result))
1693  return false;
1694 
1695  PlatformSP platform_sp(
1696  GetDebugger().GetPlatformList().GetSelectedPlatform());
1697  Status error;
1698  if (platform_sp) {
1699  FileSpec working_dir{};
1700  std::string output;
1701  int status = -1;
1702  int signo = -1;
1703  error = (platform_sp->RunShellCommand(expr, working_dir, &status, &signo,
1704  &output, m_options.timeout));
1705  if (!output.empty())
1706  result.GetOutputStream().PutCString(output);
1707  if (status > 0) {
1708  if (signo > 0) {
1709  const char *signo_cstr = Host::GetSignalAsCString(signo);
1710  if (signo_cstr)
1711  result.GetOutputStream().Printf(
1712  "error: command returned with status %i and signal %s\n",
1713  status, signo_cstr);
1714  else
1715  result.GetOutputStream().Printf(
1716  "error: command returned with status %i and signal %i\n",
1717  status, signo);
1718  } else
1719  result.GetOutputStream().Printf(
1720  "error: command returned with status %i\n", status);
1721  }
1722  } else {
1723  result.GetOutputStream().Printf(
1724  "error: cannot run remote shell commands without a platform\n");
1725  error.SetErrorString(
1726  "error: cannot run remote shell commands without a platform");
1727  }
1728 
1729  if (error.Fail()) {
1730  result.AppendError(error.AsCString());
1732  } else {
1734  }
1735  return true;
1736  }
1737 
1739 };
1740 
1741 // "platform install" - install a target to a remote end
1743 public:
1746  interpreter, "platform target-install",
1747  "Install a target (bundle or executable file) to the remote end.",
1748  "platform target-install <local-thing> <remote-sandbox>", 0) {}
1749 
1750  ~CommandObjectPlatformInstall() override = default;
1751 
1752  bool DoExecute(Args &args, CommandReturnObject &result) override {
1753  if (args.GetArgumentCount() != 2) {
1754  result.AppendError("platform target-install takes two arguments");
1756  return false;
1757  }
1758  // TODO: move the bulk of this code over to the platform itself
1759  FileSpec src(args.GetArgumentAtIndex(0));
1760  FileSystem::Instance().Resolve(src);
1761  FileSpec dst(args.GetArgumentAtIndex(1));
1762  if (!FileSystem::Instance().Exists(src)) {
1763  result.AppendError("source location does not exist or is not accessible");
1765  return false;
1766  }
1767  PlatformSP platform_sp(
1768  GetDebugger().GetPlatformList().GetSelectedPlatform());
1769  if (!platform_sp) {
1770  result.AppendError("no platform currently selected");
1772  return false;
1773  }
1774 
1775  Status error = platform_sp->Install(src, dst);
1776  if (error.Success()) {
1778  } else {
1779  result.AppendErrorWithFormat("install failed: %s", error.AsCString());
1781  }
1782  return result.Succeeded();
1783  }
1784 };
1785 
1786 CommandObjectPlatform::CommandObjectPlatform(CommandInterpreter &interpreter)
1788  interpreter, "platform", "Commands to manage and create platforms.",
1789  "platform [connect|disconnect|info|list|status|select] ...") {
1790  LoadSubCommand("select",
1791  CommandObjectSP(new CommandObjectPlatformSelect(interpreter)));
1792  LoadSubCommand("list",
1793  CommandObjectSP(new CommandObjectPlatformList(interpreter)));
1794  LoadSubCommand("status",
1795  CommandObjectSP(new CommandObjectPlatformStatus(interpreter)));
1796  LoadSubCommand("connect", CommandObjectSP(
1797  new CommandObjectPlatformConnect(interpreter)));
1799  "disconnect",
1800  CommandObjectSP(new CommandObjectPlatformDisconnect(interpreter)));
1801  LoadSubCommand("settings", CommandObjectSP(new CommandObjectPlatformSettings(
1802  interpreter)));
1803  LoadSubCommand("mkdir",
1804  CommandObjectSP(new CommandObjectPlatformMkDir(interpreter)));
1805  LoadSubCommand("file",
1806  CommandObjectSP(new CommandObjectPlatformFile(interpreter)));
1807  LoadSubCommand("get-file", CommandObjectSP(new CommandObjectPlatformGetFile(
1808  interpreter)));
1809  LoadSubCommand("get-size", CommandObjectSP(new CommandObjectPlatformGetSize(
1810  interpreter)));
1811  LoadSubCommand("put-file", CommandObjectSP(new CommandObjectPlatformPutFile(
1812  interpreter)));
1813  LoadSubCommand("process", CommandObjectSP(
1814  new CommandObjectPlatformProcess(interpreter)));
1815  LoadSubCommand("shell",
1816  CommandObjectSP(new CommandObjectPlatformShell(interpreter)));
1818  "target-install",
1819  CommandObjectSP(new CommandObjectPlatformInstall(interpreter)));
1820 }
1821 
bool DoExecute(Args &args, CommandReturnObject &result) override
CommandObjectPlatformFRead(CommandInterpreter &interpreter)
A class to manage flag bits.
Definition: Debugger.h:82
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
ConstString & GetFilename()
Filename string get accessor.
Definition: FileSpec.cpp:369
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition: Stream.cpp:61
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
std::vector< CommandArgumentData > CommandArgumentEntry
A command line argument class.
Definition: Args.h:32
void OptionParsingStarting(ExecutionContext *execution_context) override
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
CommandObjectPlatformFWrite(CommandInterpreter &interpreter)
static OptionDefinition g_platform_process_list_options[]
bool DoExecute(Args &args, CommandReturnObject &result) override
void OptionParsingStarting(ExecutionContext *execution_context) override
void OptionParsingStarting(ExecutionContext *execution_context) override
bool DoExecute(Args &command, CommandReturnObject &result) override
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
CommandObjectPlatformPutFile(CommandInterpreter &interpreter)
llvm::ArrayRef< ArgEntry > entries() const
Definition: Args.h:123
const FileSpec & GetFileSpec() const
Get const accessor for the module file specification.
Definition: Module.h:531
CommandObjectPlatformProcess(CommandInterpreter &interpreter)
bool DoExecute(Args &args, CommandReturnObject &result) override
bool DoExecute(Args &args, CommandReturnObject &result) override
bool LoadSubCommand(llvm::StringRef cmd_name, const lldb::CommandObjectSP &command_obj) override
const lldb::TargetSP & GetTargetSP() const
Get accessor to get the target shared pointer.
bool DoExecute(Args &args, CommandReturnObject &result) override
#define LLDB_INVALID_PROCESS_ID
Definition: lldb-defines.h:92
static constexpr OptionDefinition g_platform_fwrite_options[]
void AppendErrorWithFormat(const char *format,...) __attribute__((format(printf
void OptionParsingStarting(ExecutionContext *execution_context) override
bool DoExecute(Args &args, CommandReturnObject &result) override
ProcessInstanceInfo & GetProcessInfo()
Definition: ProcessInfo.h:216
size_t GetArgumentCount() const
Gets the number of arguments left in this command object.
Definition: Args.cpp:254
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
size_t GetProcessNameLengthAtIndex(size_t idx)
Definition: ProcessInfo.h:172
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
bool DoExecute(Args &args, CommandReturnObject &result) override
A file utility class.
Definition: FileSpec.h:55
An architecture specification class.
Definition: ArchSpec.h:32
static mode_t ParsePermissionString(const char *)=delete
CommandObjectPlatformStatus(CommandInterpreter &interpreter)
CommandObjectPlatformFile(CommandInterpreter &interpreter)
CommandObjectPlatformFClose(CommandInterpreter &interpreter)
std::size_t GetNumberOfMatches() const
lldb::PlatformSP GetPlatform(bool prefer_target_platform)
CommandObjectPlatformShell(CommandInterpreter &interpreter)
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
void SetNameMatchType(NameMatch name_match_type)
Definition: ProcessInfo.h:226
void AddCompletion(llvm::StringRef completion, llvm::StringRef description="")
Adds a possible completion string.
bool HandleOptionArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector, int opt_element_index, CommandInterpreter &interpreter) override
Handles the generic bits of figuring out whether we are in an option, and if so completing it...
bool HasArgs() const
Returns true if there are any arguments before the raw suffix.
Definition: Args.h:352
Module * GetExecutableModulePointer()
Definition: Target.cpp:1394
static constexpr OptionDefinition g_option_table[]
CommandObjectPlatformProcessList(CommandInterpreter &interpreter)
const char * GetArgumentAtIndex(size_t idx) const
Gets the NULL terminated C string argument pointer for the argument at index idx. ...
Definition: Args.cpp:256
void Dump(Stream &s, UserIDResolver &resolver) const
const ArchSpec & GetArchitecture() const
Get const accessor for the module architecture.
Definition: Module.cpp:1074
#define LLDB_OPT_SET_3
Definition: lldb-defines.h:113
CommandObjectPlatformProcessAttach(CommandInterpreter &interpreter)
"lldb/Utility/ArgCompletionRequest.h"
void OptionParsingStarting(ExecutionContext *execution_context) override
bool DoExecute(Args &args, CommandReturnObject &result) override
std::vector< OptionArgElement > OptionElementVector
Definition: Options.h:41
#define UINT32_MAX
Definition: lldb-defines.h:31
bool DoExecute(Args &args, CommandReturnObject &result) override
uint64_t user_id_t
Definition: lldb-types.h:84
bool DoExecute(Args &args, CommandReturnObject &result) override
static std::vector< PlatformSP > & GetPlatformList()
Definition: Platform.cpp:130
CommandObjectPlatformGetSize(CommandInterpreter &interpreter)
CommandObjectPlatformProcessInfo(CommandInterpreter &interpreter)
size_t EOL()
Output and End of Line character to the stream.
Definition: Stream.cpp:127
A class that describes an executable image and its associated object and symbol files.
Definition: Module.h:109
bool DoExecute(Args &args, CommandReturnObject &result) override
static constexpr OptionDefinition g_platform_shell_options[]
const ProcessInstanceInfo & GetProcessInfoAtIndex(size_t idx) const
Definition: ProcessInfo.h:189
void AppendMessageWithFormat(const char *format,...) __attribute__((format(printf
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
void SetErrorString(llvm::StringRef err_str)
Set the current error string to err_str.
Definition: Status.cpp:241
bool DoExecute(llvm::StringRef raw_command_line, CommandReturnObject &result) override
const std::string & GetRawPart() const
Returns the raw suffix part of the parsed string.
Definition: Args.h:390
CommandObjectPlatformMkDir(CommandInterpreter &interpreter)
#define LLDB_OPT_SET_4
Definition: lldb-defines.h:114
FileSpec & GetExecutableFile()
Definition: ProcessInfo.h:43
bool DoExecute(Args &args, CommandReturnObject &result) override
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:106
bool Success() const
Test for success condition.
Definition: Status.cpp:287
CommandObjectPlatformSettings(CommandInterpreter &interpreter)
const char * GetProcessNameAtIndex(size_t idx)
Definition: ProcessInfo.h:168
CommandObjectPlatformConnect(CommandInterpreter &interpreter)
#define LLDB_OPT_SET_2
Definition: lldb-defines.h:112
CommandObjectPlatformFOpen(CommandInterpreter &interpreter)
CommandObjectPlatformProcessLaunch(CommandInterpreter &interpreter)
bool DoExecute(Args &args, CommandReturnObject &result) override
static constexpr OptionDefinition g_platform_process_attach_options[]
CommandObjectPlatformInstall(CommandInterpreter &interpreter)
A command line option parsing protocol class.
Definition: Options.h:62
void void AppendError(llvm::StringRef in_string)
bool DoExecute(Args &args, CommandReturnObject &result) override
lldb::PlatformSP GetPlatform()
Definition: Target.h:1214
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
bool DoExecute(Args &args, CommandReturnObject &result) override
bool Fail() const
Test for error condition.
Definition: Status.cpp:181
const char * GetCString() const
Get the string value as a C string.
Definition: ConstString.h:247
Definition: SBAddress.h:15
bool DoExecute(Args &args, CommandReturnObject &result) override
void OptionParsingStarting(ExecutionContext *execution_context) override
#define LLDB_OPT_SET_FROM_TO(A, B)
Definition: lldb-defines.h:122
uint64_t pid_t
Definition: lldb-types.h:85
int HandleCompletion(CompletionRequest &request) override
This default version handles calling option argument completions and then calls HandleArgumentComplet...
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
static constexpr OptionDefinition g_permissions_options[]
bool DoExecute(Args &args, CommandReturnObject &result) override
void DumpAsTableRow(Stream &s, UserIDResolver &resolver, bool show_args, bool verbose) const
#define LLDB_OPT_SET_ALL
Definition: lldb-defines.h:110
Args & GetArgs()
Returns the list of arguments.
Definition: Args.h:357
const Args & GetParsedLine() const
bool GetCommandString(std::string &command) const
Definition: Args.cpp:207
int SetErrorStringWithFormat(const char *format,...) __attribute__((format(printf
Set the current error string to a formatted error string.
Definition: Status.cpp:255
void SetFile(llvm::StringRef path, Style style)
Change the file specified with a new path.
Definition: FileSpec.cpp:198
#define LLDB_OPT_SET_1
Definition: lldb-defines.h:111
const char * AsCString(const char *default_error_str="unknown error") const
Get the error string associated with the current error.
Definition: Status.cpp:130
uint64_t ToUInt64(const char *s, uint64_t fail_value=0, int base=0, bool *success_ptr=nullptr)
static constexpr OptionDefinition g_platform_fread_options[]
CommandObjectPlatformSelect(CommandInterpreter &interpreter)
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition: FileSpec.cpp:376
#define UINT64_MAX
Definition: lldb-defines.h:35
#define LLDB_OPT_SET_5
Definition: lldb-defines.h:115
CommandObjectPlatformList(CommandInterpreter &interpreter)
A pair of an option list with a &#39;raw&#39; string as a suffix.
Definition: Args.h:341
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
CommandObjectPlatformGetFile(CommandInterpreter &interpreter)
CommandObjectPlatformDisconnect(CommandInterpreter &interpreter)
#define LLDB_OPT_SET_6
Definition: lldb-defines.h:116
void SetStatus(lldb::ReturnStatus status)
bool DoExecute(Args &args, CommandReturnObject &result) override
An error handling class.
Definition: Status.h:44
lldb_private::Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
bool GetRunArguments(Args &args) const
Definition: Target.cpp:3825