LLDB mainline
CommandObjectPlatform.cpp
Go to the documentation of this file.
1//===-- CommandObjectPlatform.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
12#include "lldb/Core/Debugger.h"
13#include "lldb/Core/Module.h"
25#include "lldb/Target/Process.h"
26#include "lldb/Utility/Args.h"
28#include "lldb/Utility/State.h"
29
30#include "llvm/ADT/SmallString.h"
31
32using namespace lldb;
33using namespace lldb_private;
34
35static mode_t ParsePermissionString(const char *) = delete;
36
37static mode_t ParsePermissionString(llvm::StringRef permissions) {
38 if (permissions.size() != 9)
39 return (mode_t)(-1);
40 bool user_r, user_w, user_x, group_r, group_w, group_x, world_r, world_w,
41 world_x;
42
43 user_r = (permissions[0] == 'r');
44 user_w = (permissions[1] == 'w');
45 user_x = (permissions[2] == 'x');
46
47 group_r = (permissions[3] == 'r');
48 group_w = (permissions[4] == 'w');
49 group_x = (permissions[5] == 'x');
50
51 world_r = (permissions[6] == 'r');
52 world_w = (permissions[7] == 'w');
53 world_x = (permissions[8] == 'x');
54
55 mode_t user, group, world;
56 user = (user_r ? 4 : 0) | (user_w ? 2 : 0) | (user_x ? 1 : 0);
57 group = (group_r ? 4 : 0) | (group_w ? 2 : 0) | (group_x ? 1 : 0);
58 world = (world_r ? 4 : 0) | (world_w ? 2 : 0) | (world_x ? 1 : 0);
59
60 return user | group | world;
61}
62
63#define LLDB_OPTIONS_permissions
64#include "CommandOptions.inc"
65
67public:
68 OptionPermissions() = default;
69
70 ~OptionPermissions() override = default;
71
73 SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
74 ExecutionContext *execution_context) override {
76 char short_option = (char)GetDefinitions()[option_idx].short_option;
77 switch (short_option) {
78 case 'v': {
79 if (option_arg.getAsInteger(8, m_permissions)) {
80 m_permissions = 0777;
81 error.SetErrorStringWithFormat("invalid value for permissions: %s",
82 option_arg.str().c_str());
83 }
84
85 } break;
86 case 's': {
87 mode_t perms = ParsePermissionString(option_arg);
88 if (perms == (mode_t)-1)
89 error.SetErrorStringWithFormat("invalid value for permissions: %s",
90 option_arg.str().c_str());
91 else
92 m_permissions = perms;
93 } break;
94 case 'r':
95 m_permissions |= lldb::eFilePermissionsUserRead;
96 break;
97 case 'w':
98 m_permissions |= lldb::eFilePermissionsUserWrite;
99 break;
100 case 'x':
101 m_permissions |= lldb::eFilePermissionsUserExecute;
102 break;
103 case 'R':
104 m_permissions |= lldb::eFilePermissionsGroupRead;
105 break;
106 case 'W':
107 m_permissions |= lldb::eFilePermissionsGroupWrite;
108 break;
109 case 'X':
110 m_permissions |= lldb::eFilePermissionsGroupExecute;
111 break;
112 case 'd':
113 m_permissions |= lldb::eFilePermissionsWorldRead;
114 break;
115 case 't':
116 m_permissions |= lldb::eFilePermissionsWorldWrite;
117 break;
118 case 'e':
119 m_permissions |= lldb::eFilePermissionsWorldExecute;
120 break;
121 default:
122 llvm_unreachable("Unimplemented option");
123 }
124
125 return error;
126 }
127
128 void OptionParsingStarting(ExecutionContext *execution_context) override {
129 m_permissions = 0;
130 }
131
132 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
133 return llvm::ArrayRef(g_permissions_options);
134 }
135
136 // Instance variables to hold the values for command options.
137
139
140private:
143};
144
145// "platform select <platform-name>"
147public:
149 : CommandObjectParsed(interpreter, "platform select",
150 "Create a platform if needed and select it as the "
151 "current platform.",
152 "platform select <platform-name>", 0),
154 false) // Don't include the "--platform" option by passing false
155 {
159 m_arguments.push_back({platform_arg});
160 }
161
162 ~CommandObjectPlatformSelect() override = default;
163
164 void HandleCompletion(CompletionRequest &request) override {
166 GetCommandInterpreter(), request, nullptr);
167 }
168
169 Options *GetOptions() override { return &m_option_group; }
170
171protected:
172 bool DoExecute(Args &args, CommandReturnObject &result) override {
173 if (args.GetArgumentCount() == 1) {
174 const char *platform_name = args.GetArgumentAtIndex(0);
175 if (platform_name && platform_name[0]) {
176 const bool select = true;
177 m_platform_options.SetPlatformName(platform_name);
179 ArchSpec platform_arch;
181 m_interpreter, ArchSpec(), select, error, platform_arch));
182 if (platform_sp) {
184
185 platform_sp->GetStatus(result.GetOutputStream());
187 } else {
188 result.AppendError(error.AsCString());
189 }
190 } else {
191 result.AppendError("invalid platform name");
192 }
193 } else {
194 result.AppendError(
195 "platform create takes a platform name as an argument\n");
196 }
197 return result.Succeeded();
198 }
199
202};
203
204// "platform list"
206public:
208 : CommandObjectParsed(interpreter, "platform list",
209 "List all platforms that are available.", nullptr,
210 0) {}
211
212 ~CommandObjectPlatformList() override = default;
213
214protected:
215 bool DoExecute(Args &args, CommandReturnObject &result) override {
216 Stream &ostrm = result.GetOutputStream();
217 ostrm.Printf("Available platforms:\n");
218
219 PlatformSP host_platform_sp(Platform::GetHostPlatform());
220 ostrm.Format("{0}: {1}\n", host_platform_sp->GetPluginName(),
221 host_platform_sp->GetDescription());
222
223 uint32_t idx;
224 for (idx = 0; true; ++idx) {
225 llvm::StringRef plugin_name =
227 if (plugin_name.empty())
228 break;
229 llvm::StringRef plugin_desc =
231 ostrm.Format("{0}: {1}\n", plugin_name, plugin_desc);
232 }
233
234 if (idx == 0) {
235 result.AppendError("no platforms are available\n");
236 } else
238 return result.Succeeded();
239 }
240};
241
242// "platform status"
244public:
246 : CommandObjectParsed(interpreter, "platform status",
247 "Display status for the current platform.", nullptr,
248 0) {}
249
250 ~CommandObjectPlatformStatus() override = default;
251
252protected:
253 bool DoExecute(Args &args, CommandReturnObject &result) override {
254 Stream &ostrm = result.GetOutputStream();
255
256 Target *target = GetDebugger().GetSelectedTarget().get();
257 PlatformSP platform_sp;
258 if (target) {
259 platform_sp = target->GetPlatform();
260 }
261 if (!platform_sp) {
263 }
264 if (platform_sp) {
265 platform_sp->GetStatus(ostrm);
267 } else {
268 result.AppendError("no platform is currently selected\n");
269 }
270 return result.Succeeded();
271 }
272};
273
274// "platform connect <connect-url>"
276public:
279 interpreter, "platform connect",
280 "Select the current platform by providing a connection URL.",
281 "platform connect <connect-url>", 0) {
283 m_arguments.push_back({platform_arg});
284 }
285
286 ~CommandObjectPlatformConnect() override = default;
287
288protected:
289 bool DoExecute(Args &args, CommandReturnObject &result) override {
290 Stream &ostrm = result.GetOutputStream();
291
292 PlatformSP platform_sp(
293 GetDebugger().GetPlatformList().GetSelectedPlatform());
294 if (platform_sp) {
295 Status error(platform_sp->ConnectRemote(args));
296 if (error.Success()) {
297 platform_sp->GetStatus(ostrm);
299
300 platform_sp->ConnectToWaitingProcesses(GetDebugger(), error);
301 if (error.Fail()) {
302 result.AppendError(error.AsCString());
303 }
304 } else {
305 result.AppendErrorWithFormat("%s\n", error.AsCString());
306 }
307 } else {
308 result.AppendError("no platform is currently selected\n");
309 }
310 return result.Succeeded();
311 }
312
313 Options *GetOptions() override {
314 PlatformSP platform_sp(
315 GetDebugger().GetPlatformList().GetSelectedPlatform());
316 OptionGroupOptions *m_platform_options = nullptr;
317 if (platform_sp) {
318 m_platform_options = platform_sp->GetConnectionOptions(m_interpreter);
319 if (m_platform_options != nullptr && !m_platform_options->m_did_finalize)
320 m_platform_options->Finalize();
321 }
322 return m_platform_options;
323 }
324};
325
326// "platform disconnect"
328public:
330 : CommandObjectParsed(interpreter, "platform disconnect",
331 "Disconnect from the current platform.",
332 "platform disconnect", 0) {}
333
335
336protected:
337 bool DoExecute(Args &args, CommandReturnObject &result) override {
338 PlatformSP platform_sp(
339 GetDebugger().GetPlatformList().GetSelectedPlatform());
340 if (platform_sp) {
341 if (args.GetArgumentCount() == 0) {
343
344 if (platform_sp->IsConnected()) {
345 // Cache the instance name if there is one since we are about to
346 // disconnect and the name might go with it.
347 const char *hostname_cstr = platform_sp->GetHostname();
348 std::string hostname;
349 if (hostname_cstr)
350 hostname.assign(hostname_cstr);
351
352 error = platform_sp->DisconnectRemote();
353 if (error.Success()) {
354 Stream &ostrm = result.GetOutputStream();
355 if (hostname.empty())
356 ostrm.Format("Disconnected from \"{0}\"\n",
357 platform_sp->GetPluginName());
358 else
359 ostrm.Printf("Disconnected from \"%s\"\n", hostname.c_str());
361 } else {
362 result.AppendErrorWithFormat("%s", error.AsCString());
363 }
364 } else {
365 // Not connected...
366 result.AppendErrorWithFormatv("not connected to '{0}'",
367 platform_sp->GetPluginName());
368 }
369 } else {
370 // Bad args
371 result.AppendError(
372 "\"platform disconnect\" doesn't take any arguments");
373 }
374 } else {
375 result.AppendError("no platform is currently selected");
376 }
377 return result.Succeeded();
378 }
379};
380
381// "platform settings"
383public:
385 : CommandObjectParsed(interpreter, "platform settings",
386 "Set settings for the current target's platform.",
387 "platform settings", 0),
388 m_option_working_dir(LLDB_OPT_SET_1, false, "working-dir", 'w',
390 "The working directory for the platform.") {
392 }
393
394 ~CommandObjectPlatformSettings() override = default;
395
396protected:
397 bool DoExecute(Args &args, CommandReturnObject &result) override {
398 PlatformSP platform_sp(
399 GetDebugger().GetPlatformList().GetSelectedPlatform());
400 if (platform_sp) {
402 platform_sp->SetWorkingDirectory(
404 } else {
405 result.AppendError("no platform is currently selected");
406 }
407 return result.Succeeded();
408 }
409
410 Options *GetOptions() override {
411 if (!m_options.DidFinalize())
413 return &m_options;
414 }
415
418};
419
420// "platform mkdir"
422public:
424 : CommandObjectParsed(interpreter, "platform mkdir",
425 "Make a new directory on the remote end.", nullptr,
426 0) {
428 m_arguments.push_back({thread_arg});
429 }
430
431 ~CommandObjectPlatformMkDir() override = default;
432
433 bool DoExecute(Args &args, CommandReturnObject &result) override {
434 PlatformSP platform_sp(
435 GetDebugger().GetPlatformList().GetSelectedPlatform());
436 if (platform_sp) {
437 std::string cmd_line;
438 args.GetCommandString(cmd_line);
439 uint32_t mode;
440 const OptionPermissions *options_permissions =
442 if (options_permissions)
443 mode = options_permissions->m_permissions;
444 else
445 mode = lldb::eFilePermissionsUserRWX | lldb::eFilePermissionsGroupRWX |
446 lldb::eFilePermissionsWorldRX;
447 Status error = platform_sp->MakeDirectory(FileSpec(cmd_line), mode);
448 if (error.Success()) {
450 } else {
451 result.AppendError(error.AsCString());
452 }
453 } else {
454 result.AppendError("no platform currently selected\n");
455 }
456 return result.Succeeded();
457 }
458
459 Options *GetOptions() override {
460 if (!m_options.DidFinalize()) {
463 }
464 return &m_options;
465 }
466
469};
470
471// "platform fopen"
473public:
475 : CommandObjectParsed(interpreter, "platform file open",
476 "Open a file on the remote end.", nullptr, 0) {
478 m_arguments.push_back({path_arg});
479 }
480
481 ~CommandObjectPlatformFOpen() override = default;
482
483 void
485 OptionElementVector &opt_element_vector) override {
486 if (request.GetCursorIndex() == 0)
489 nullptr);
490 }
491
492 bool DoExecute(Args &args, CommandReturnObject &result) override {
493 PlatformSP platform_sp(
494 GetDebugger().GetPlatformList().GetSelectedPlatform());
495 if (platform_sp) {
497 std::string cmd_line;
498 args.GetCommandString(cmd_line);
499 mode_t perms;
500 const OptionPermissions *options_permissions =
502 if (options_permissions)
503 perms = options_permissions->m_permissions;
504 else
505 perms = lldb::eFilePermissionsUserRW | lldb::eFilePermissionsGroupRW |
506 lldb::eFilePermissionsWorldRead;
507 lldb::user_id_t fd = platform_sp->OpenFile(
508 FileSpec(cmd_line),
510 perms, error);
511 if (error.Success()) {
512 result.AppendMessageWithFormat("File Descriptor = %" PRIu64 "\n", fd);
514 } else {
515 result.AppendError(error.AsCString());
516 }
517 } else {
518 result.AppendError("no platform currently selected\n");
519 }
520 return result.Succeeded();
521 }
522
523 Options *GetOptions() override {
524 if (!m_options.DidFinalize()) {
527 }
528 return &m_options;
529 }
530
533};
534
535// "platform fclose"
537public:
539 : CommandObjectParsed(interpreter, "platform file close",
540 "Close a file on the remote end.", nullptr, 0) {
542 m_arguments.push_back({path_arg});
543 }
544
545 ~CommandObjectPlatformFClose() override = default;
546
547 bool DoExecute(Args &args, CommandReturnObject &result) override {
548 PlatformSP platform_sp(
549 GetDebugger().GetPlatformList().GetSelectedPlatform());
550 if (platform_sp) {
551 std::string cmd_line;
552 args.GetCommandString(cmd_line);
554 if (!llvm::to_integer(cmd_line, fd)) {
555 result.AppendErrorWithFormatv("'{0}' is not a valid file descriptor.\n",
556 cmd_line);
557 return result.Succeeded();
558 }
560 bool success = platform_sp->CloseFile(fd, error);
561 if (success) {
562 result.AppendMessageWithFormat("file %" PRIu64 " closed.\n", fd);
564 } else {
565 result.AppendError(error.AsCString());
566 }
567 } else {
568 result.AppendError("no platform currently selected\n");
569 }
570 return result.Succeeded();
571 }
572};
573
574// "platform fread"
575
576#define LLDB_OPTIONS_platform_fread
577#include "CommandOptions.inc"
578
580public:
582 : CommandObjectParsed(interpreter, "platform file read",
583 "Read data from a file on the remote end.", nullptr,
584 0) {
586 m_arguments.push_back({path_arg});
587 }
588
589 ~CommandObjectPlatformFRead() override = default;
590
591 bool DoExecute(Args &args, CommandReturnObject &result) override {
592 PlatformSP platform_sp(
593 GetDebugger().GetPlatformList().GetSelectedPlatform());
594 if (platform_sp) {
595 std::string cmd_line;
596 args.GetCommandString(cmd_line);
598 if (!llvm::to_integer(cmd_line, fd)) {
599 result.AppendErrorWithFormatv("'{0}' is not a valid file descriptor.\n",
600 cmd_line);
601 return result.Succeeded();
602 }
603 std::string buffer(m_options.m_count, 0);
605 uint64_t retcode = platform_sp->ReadFile(
606 fd, m_options.m_offset, &buffer[0], m_options.m_count, error);
607 if (retcode != UINT64_MAX) {
608 result.AppendMessageWithFormat("Return = %" PRIu64 "\n", retcode);
609 result.AppendMessageWithFormat("Data = \"%s\"\n", buffer.c_str());
611 } else {
612 result.AppendError(error.AsCString());
613 }
614 } else {
615 result.AppendError("no platform currently selected\n");
616 }
617 return result.Succeeded();
618 }
619
620 Options *GetOptions() override { return &m_options; }
621
622protected:
623 class CommandOptions : public Options {
624 public:
625 CommandOptions() = default;
626
627 ~CommandOptions() override = default;
628
629 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
630 ExecutionContext *execution_context) override {
632 char short_option = (char)m_getopt_table[option_idx].val;
633
634 switch (short_option) {
635 case 'o':
636 if (option_arg.getAsInteger(0, m_offset))
637 error.SetErrorStringWithFormat("invalid offset: '%s'",
638 option_arg.str().c_str());
639 break;
640 case 'c':
641 if (option_arg.getAsInteger(0, m_count))
642 error.SetErrorStringWithFormat("invalid offset: '%s'",
643 option_arg.str().c_str());
644 break;
645 default:
646 llvm_unreachable("Unimplemented option");
647 }
648
649 return error;
650 }
651
652 void OptionParsingStarting(ExecutionContext *execution_context) override {
653 m_offset = 0;
654 m_count = 1;
655 }
656
657 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
658 return llvm::ArrayRef(g_platform_fread_options);
659 }
660
661 // Instance variables to hold the values for command options.
662
663 uint32_t m_offset;
664 uint32_t m_count;
665 };
666
668};
669
670// "platform fwrite"
671
672#define LLDB_OPTIONS_platform_fwrite
673#include "CommandOptions.inc"
674
676public:
678 : CommandObjectParsed(interpreter, "platform file write",
679 "Write data to a file on the remote end.", nullptr,
680 0) {
682 m_arguments.push_back({path_arg});
683 }
684
685 ~CommandObjectPlatformFWrite() override = default;
686
687 bool DoExecute(Args &args, CommandReturnObject &result) override {
688 PlatformSP platform_sp(
689 GetDebugger().GetPlatformList().GetSelectedPlatform());
690 if (platform_sp) {
691 std::string cmd_line;
692 args.GetCommandString(cmd_line);
695 if (!llvm::to_integer(cmd_line, fd)) {
696 result.AppendErrorWithFormatv("'{0}' is not a valid file descriptor.",
697 cmd_line);
698 return result.Succeeded();
699 }
700 uint64_t retcode =
701 platform_sp->WriteFile(fd, m_options.m_offset, &m_options.m_data[0],
702 m_options.m_data.size(), error);
703 if (retcode != UINT64_MAX) {
704 result.AppendMessageWithFormat("Return = %" PRIu64 "\n", retcode);
706 } else {
707 result.AppendError(error.AsCString());
708 }
709 } else {
710 result.AppendError("no platform currently selected\n");
711 }
712 return result.Succeeded();
713 }
714
715 Options *GetOptions() override { return &m_options; }
716
717protected:
718 class CommandOptions : public Options {
719 public:
720 CommandOptions() = default;
721
722 ~CommandOptions() override = default;
723
724 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
725 ExecutionContext *execution_context) override {
727 char short_option = (char)m_getopt_table[option_idx].val;
728
729 switch (short_option) {
730 case 'o':
731 if (option_arg.getAsInteger(0, m_offset))
732 error.SetErrorStringWithFormat("invalid offset: '%s'",
733 option_arg.str().c_str());
734 break;
735 case 'd':
736 m_data.assign(std::string(option_arg));
737 break;
738 default:
739 llvm_unreachable("Unimplemented option");
740 }
741
742 return error;
743 }
744
745 void OptionParsingStarting(ExecutionContext *execution_context) override {
746 m_offset = 0;
747 m_data.clear();
748 }
749
750 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
751 return llvm::ArrayRef(g_platform_fwrite_options);
752 }
753
754 // Instance variables to hold the values for command options.
755
756 uint32_t m_offset;
757 std::string m_data;
758 };
759
761};
762
764public:
765 // Constructors and Destructors
768 interpreter, "platform file",
769 "Commands to access files on the current platform.",
770 "platform file [open|close|read|write] ...") {
772 "open", CommandObjectSP(new CommandObjectPlatformFOpen(interpreter)));
774 "close", CommandObjectSP(new CommandObjectPlatformFClose(interpreter)));
776 "read", CommandObjectSP(new CommandObjectPlatformFRead(interpreter)));
778 "write", CommandObjectSP(new CommandObjectPlatformFWrite(interpreter)));
779 }
780
781 ~CommandObjectPlatformFile() override = default;
782
783private:
784 // For CommandObjectPlatform only
788};
789
790// "platform get-file remote-file-path host-file-path"
792public:
795 interpreter, "platform get-file",
796 "Transfer a file from the remote end to the local host.",
797 "platform get-file <remote-file-spec> <local-file-spec>", 0) {
799 R"(Examples:
800
801(lldb) platform get-file /the/remote/file/path /the/local/file/path
802
803 Transfer a file from the remote end with file path /the/remote/file/path to the local host.)");
804
805 CommandArgumentEntry arg1, arg2;
806 CommandArgumentData file_arg_remote, file_arg_host;
807
808 // Define the first (and only) variant of this arg.
809 file_arg_remote.arg_type = eArgTypeFilename;
810 file_arg_remote.arg_repetition = eArgRepeatPlain;
811 // There is only one variant this argument could be; put it into the
812 // argument entry.
813 arg1.push_back(file_arg_remote);
814
815 // Define the second (and only) variant of this arg.
816 file_arg_host.arg_type = eArgTypeFilename;
817 file_arg_host.arg_repetition = eArgRepeatPlain;
818 // There is only one variant this argument could be; put it into the
819 // argument entry.
820 arg2.push_back(file_arg_host);
821
822 // Push the data for the first and the second arguments into the
823 // m_arguments vector.
824 m_arguments.push_back(arg1);
825 m_arguments.push_back(arg2);
826 }
828 ~CommandObjectPlatformGetFile() override = default;
829
830 void
832 OptionElementVector &opt_element_vector) override {
833 if (request.GetCursorIndex() == 0)
836 nullptr);
837 else if (request.GetCursorIndex() == 1)
840 }
841
842 bool DoExecute(Args &args, CommandReturnObject &result) override {
843 // If the number of arguments is incorrect, issue an error message.
844 if (args.GetArgumentCount() != 2) {
845 result.AppendError("required arguments missing; specify both the "
846 "source and destination file paths");
847 return false;
848 }
849
850 PlatformSP platform_sp(
851 GetDebugger().GetPlatformList().GetSelectedPlatform());
852 if (platform_sp) {
853 const char *remote_file_path = args.GetArgumentAtIndex(0);
854 const char *local_file_path = args.GetArgumentAtIndex(1);
855 Status error = platform_sp->GetFile(FileSpec(remote_file_path),
856 FileSpec(local_file_path));
857 if (error.Success()) {
859 "successfully get-file from %s (remote) to %s (host)\n",
860 remote_file_path, local_file_path);
862 } else {
863 result.AppendMessageWithFormat("get-file failed: %s\n",
864 error.AsCString());
865 }
866 } else {
867 result.AppendError("no platform currently selected\n");
868 }
869 return result.Succeeded();
870 }
871};
872
873// "platform get-size remote-file-path"
875public:
877 : CommandObjectParsed(interpreter, "platform get-size",
878 "Get the file size from the remote end.",
879 "platform get-size <remote-file-spec>", 0) {
881 R"(Examples:
882
883(lldb) platform get-size /the/remote/file/path
884
885 Get the file size from the remote end with path /the/remote/file/path.)");
886
888 CommandArgumentData file_arg_remote;
889
890 // Define the first (and only) variant of this arg.
891 file_arg_remote.arg_type = eArgTypeFilename;
892 file_arg_remote.arg_repetition = eArgRepeatPlain;
893 // There is only one variant this argument could be; put it into the
894 // argument entry.
895 arg1.push_back(file_arg_remote);
896
897 // Push the data for the first argument into the m_arguments vector.
898 m_arguments.push_back(arg1);
899 }
901 ~CommandObjectPlatformGetSize() override = default;
902
903 void
905 OptionElementVector &opt_element_vector) override {
906 if (request.GetCursorIndex() != 0)
907 return;
908
911 nullptr);
912 }
913
914 bool DoExecute(Args &args, CommandReturnObject &result) override {
915 // If the number of arguments is incorrect, issue an error message.
916 if (args.GetArgumentCount() != 1) {
917 result.AppendError("required argument missing; specify the source file "
918 "path as the only argument");
919 return false;
920 }
921
922 PlatformSP platform_sp(
923 GetDebugger().GetPlatformList().GetSelectedPlatform());
924 if (platform_sp) {
925 std::string remote_file_path(args.GetArgumentAtIndex(0));
926 user_id_t size = platform_sp->GetFileSize(FileSpec(remote_file_path));
927 if (size != UINT64_MAX) {
928 result.AppendMessageWithFormat("File size of %s (remote): %" PRIu64
929 "\n",
930 remote_file_path.c_str(), size);
932 } else {
934 "Error getting file size of %s (remote)\n",
935 remote_file_path.c_str());
936 }
937 } else {
938 result.AppendError("no platform currently selected\n");
939 }
940 return result.Succeeded();
941 }
942};
943
944// "platform get-permissions remote-file-path"
946public:
948 : CommandObjectParsed(interpreter, "platform get-permissions",
949 "Get the file permission bits from the remote end.",
950 "platform get-permissions <remote-file-spec>", 0) {
952 R"(Examples:
953
954(lldb) platform get-permissions /the/remote/file/path
955
956 Get the file permissions from the remote end with path /the/remote/file/path.)");
957
959 CommandArgumentData file_arg_remote;
960
961 // Define the first (and only) variant of this arg.
962 file_arg_remote.arg_type = eArgTypeFilename;
963 file_arg_remote.arg_repetition = eArgRepeatPlain;
964 // There is only one variant this argument could be; put it into the
965 // argument entry.
966 arg1.push_back(file_arg_remote);
967
968 // Push the data for the first argument into the m_arguments vector.
969 m_arguments.push_back(arg1);
970 }
972 ~CommandObjectPlatformGetPermissions() override = default;
973
974 void
976 OptionElementVector &opt_element_vector) override {
977 if (request.GetCursorIndex() != 0)
978 return;
979
982 nullptr);
983 }
984
985 bool DoExecute(Args &args, CommandReturnObject &result) override {
986 // If the number of arguments is incorrect, issue an error message.
987 if (args.GetArgumentCount() != 1) {
988 result.AppendError("required argument missing; specify the source file "
989 "path as the only argument");
990 return false;
991 }
992
993 PlatformSP platform_sp(
994 GetDebugger().GetPlatformList().GetSelectedPlatform());
995 if (platform_sp) {
996 std::string remote_file_path(args.GetArgumentAtIndex(0));
997 uint32_t permissions;
998 Status error = platform_sp->GetFilePermissions(FileSpec(remote_file_path),
999 permissions);
1000 if (error.Success()) {
1002 "File permissions of %s (remote): 0o%04" PRIo32 "\n",
1003 remote_file_path.c_str(), permissions);
1005 } else
1006 result.AppendError(error.AsCString());
1007 } else {
1008 result.AppendError("no platform currently selected\n");
1009 }
1010 return result.Succeeded();
1011 }
1012};
1013
1014// "platform file-exists remote-file-path"
1016public:
1018 : CommandObjectParsed(interpreter, "platform file-exists",
1019 "Check if the file exists on the remote end.",
1020 "platform file-exists <remote-file-spec>", 0) {
1022 R"(Examples:
1023
1024(lldb) platform file-exists /the/remote/file/path
1025
1026 Check if /the/remote/file/path exists on the remote end.)");
1027
1029 CommandArgumentData file_arg_remote;
1030
1031 // Define the first (and only) variant of this arg.
1032 file_arg_remote.arg_type = eArgTypeFilename;
1033 file_arg_remote.arg_repetition = eArgRepeatPlain;
1034 // There is only one variant this argument could be; put it into the
1035 // argument entry.
1036 arg1.push_back(file_arg_remote);
1037
1038 // Push the data for the first argument into the m_arguments vector.
1039 m_arguments.push_back(arg1);
1040 }
1042 ~CommandObjectPlatformFileExists() override = default;
1043
1044 void
1046 OptionElementVector &opt_element_vector) override {
1047 if (request.GetCursorIndex() != 0)
1048 return;
1049
1052 nullptr);
1053 }
1054
1055 bool DoExecute(Args &args, CommandReturnObject &result) override {
1056 // If the number of arguments is incorrect, issue an error message.
1057 if (args.GetArgumentCount() != 1) {
1058 result.AppendError("required argument missing; specify the source file "
1059 "path as the only argument");
1060 return false;
1061 }
1062
1063 PlatformSP platform_sp(
1064 GetDebugger().GetPlatformList().GetSelectedPlatform());
1065 if (platform_sp) {
1066 std::string remote_file_path(args.GetArgumentAtIndex(0));
1067 bool exists = platform_sp->GetFileExists(FileSpec(remote_file_path));
1069 "File %s (remote) %s\n",
1070 remote_file_path.c_str(), exists ? "exists" : "does not exist");
1072 } else {
1073 result.AppendError("no platform currently selected\n");
1074 }
1075 return result.Succeeded();
1076 }
1077};
1078
1079// "platform put-file"
1081public:
1084 interpreter, "platform put-file",
1085 "Transfer a file from this system to the remote end.",
1086 "platform put-file <source> [<destination>]", 0) {
1088 R"(Examples:
1089
1090(lldb) platform put-file /source/foo.txt /destination/bar.txt
1091
1092(lldb) platform put-file /source/foo.txt
1093
1094 Relative source file paths are resolved against lldb's local working directory.
1096 Omitting the destination places the file in the platform working directory.)");
1099 m_arguments.push_back({source_arg});
1100 m_arguments.push_back({path_arg});
1101 }
1102
1103 ~CommandObjectPlatformPutFile() override = default;
1104
1105 void
1107 OptionElementVector &opt_element_vector) override {
1108 if (request.GetCursorIndex() == 0)
1111 else if (request.GetCursorIndex() == 1)
1114 nullptr);
1115 }
1116
1117 bool DoExecute(Args &args, CommandReturnObject &result) override {
1118 const char *src = args.GetArgumentAtIndex(0);
1119 const char *dst = args.GetArgumentAtIndex(1);
1120
1121 FileSpec src_fs(src);
1122 FileSystem::Instance().Resolve(src_fs);
1123 FileSpec dst_fs(dst ? dst : src_fs.GetFilename().GetCString());
1124
1125 PlatformSP platform_sp(
1126 GetDebugger().GetPlatformList().GetSelectedPlatform());
1127 if (platform_sp) {
1128 Status error(platform_sp->PutFile(src_fs, dst_fs));
1129 if (error.Success()) {
1131 } else {
1132 result.AppendError(error.AsCString());
1133 }
1134 } else {
1135 result.AppendError("no platform currently selected\n");
1136 }
1137 return result.Succeeded();
1138 }
1139};
1140
1141// "platform process launch"
1143public:
1145 : CommandObjectParsed(interpreter, "platform process launch",
1146 "Launch a new process on a remote platform.",
1147 "platform process launch program",
1148 eCommandRequiresTarget | eCommandTryTargetAPILock),
1149 m_class_options("scripted process", true, 'C', 'k', 'v', 0) {
1155 m_arguments.push_back({run_arg_arg});
1156 }
1157
1159
1160 Options *GetOptions() override { return &m_all_options; }
1161
1162protected:
1163 bool DoExecute(Args &args, CommandReturnObject &result) override {
1164 Target *target = GetDebugger().GetSelectedTarget().get();
1165 PlatformSP platform_sp;
1166 if (target) {
1167 platform_sp = target->GetPlatform();
1168 }
1169 if (!platform_sp) {
1171 }
1172
1173 if (platform_sp) {
1174 Status error;
1175 const size_t argc = args.GetArgumentCount();
1176 Target *target = m_exe_ctx.GetTargetPtr();
1177 Module *exe_module = target->GetExecutableModulePointer();
1178 if (exe_module) {
1180 llvm::SmallString<128> exe_path;
1182 if (!exe_path.empty())
1185 }
1186
1187 if (!m_class_options.GetName().empty()) {
1188 m_options.launch_info.SetProcessPluginName("ScriptedProcess");
1189 ScriptedMetadataSP metadata_sp = std::make_shared<ScriptedMetadata>(
1193 }
1194
1195 if (argc > 0) {
1197 // We already have an executable file, so we will use this and all
1198 // arguments to this function are extra arguments
1200 } else {
1201 // We don't have any file yet, so the first argument is our
1202 // executable, and the rest are program arguments
1203 const bool first_arg_is_executable = true;
1204 m_options.launch_info.SetArguments(args, first_arg_is_executable);
1205 }
1206 }
1207
1209 Debugger &debugger = GetDebugger();
1210
1211 if (argc == 0) {
1212 // If no arguments were given to the command, use target.run-args.
1213 Args target_run_args;
1214 target->GetRunArguments(target_run_args);
1216 }
1217
1218 ProcessSP process_sp(platform_sp->DebugProcess(
1219 m_options.launch_info, debugger, *target, error));
1220
1221 if (!process_sp && error.Success()) {
1222 result.AppendError("failed to launch or debug process");
1223 return false;
1224 } else if (!error.Success()) {
1225 result.AppendError(error.AsCString());
1226 return false;
1227 }
1228
1229 const bool synchronous_execution =
1231 auto launch_info = m_options.launch_info;
1232 bool rebroadcast_first_stop =
1233 !synchronous_execution &&
1234 launch_info.GetFlags().Test(eLaunchFlagStopAtEntry);
1235
1236 EventSP first_stop_event_sp;
1237 StateType state = process_sp->WaitForProcessToStop(
1238 std::nullopt, &first_stop_event_sp, rebroadcast_first_stop,
1239 launch_info.GetHijackListener());
1240 process_sp->RestoreProcessEvents();
1241
1242 if (rebroadcast_first_stop) {
1243 assert(first_stop_event_sp);
1244 process_sp->BroadcastEvent(first_stop_event_sp);
1245 return true;
1246 }
1247
1248 switch (state) {
1249 case eStateStopped: {
1250 if (launch_info.GetFlags().Test(eLaunchFlagStopAtEntry))
1251 break;
1252 if (synchronous_execution) {
1253 // Now we have handled the stop-from-attach, and we are just
1254 // switching to a synchronous resume. So we should switch to the
1255 // SyncResume hijacker.
1256 process_sp->ResumeSynchronous(&result.GetOutputStream());
1257 } else {
1258 error = process_sp->Resume();
1259 if (!error.Success()) {
1260 result.AppendErrorWithFormat(
1261 "process resume at entry point failed: %s",
1262 error.AsCString());
1263 }
1264 }
1265 } break;
1266 default:
1267 result.AppendErrorWithFormat(
1268 "initial process state wasn't stopped: %s",
1269 StateAsCString(state));
1270 break;
1271 }
1272
1273 if (process_sp && process_sp->IsAlive()) {
1275 return true;
1276 }
1277 } else {
1278 result.AppendError("'platform process launch' uses the current target "
1279 "file and arguments, or the executable and its "
1280 "arguments can be specified in this command");
1281 return false;
1282 }
1283 } else {
1284 result.AppendError("no platform is selected\n");
1285 }
1286 return result.Succeeded();
1287 }
1288
1292};
1293
1294// "platform process list"
1295
1297#define LLDB_OPTIONS_platform_process_list
1298#include "CommandOptions.inc"
1299
1301public:
1303 : CommandObjectParsed(interpreter, "platform process list",
1304 "List processes on a remote platform by name, pid, "
1305 "or many other matching attributes.",
1306 "platform process list", 0) {}
1307
1309
1310 Options *GetOptions() override { return &m_options; }
1311
1312protected:
1313 bool DoExecute(Args &args, CommandReturnObject &result) override {
1314 Target *target = GetDebugger().GetSelectedTarget().get();
1315 PlatformSP platform_sp;
1316 if (target) {
1317 platform_sp = target->GetPlatform();
1318 }
1319 if (!platform_sp) {
1321 }
1322
1323 if (platform_sp) {
1324 Status error;
1325 if (platform_sp) {
1326 Stream &ostrm = result.GetOutputStream();
1327
1329 if (pid != LLDB_INVALID_PROCESS_ID) {
1330 ProcessInstanceInfo proc_info;
1331 if (platform_sp->GetProcessInfo(pid, proc_info)) {
1334 proc_info.DumpAsTableRow(ostrm, platform_sp->GetUserIDResolver(),
1337 } else {
1338 result.AppendErrorWithFormat(
1339 "no process found with pid = %" PRIu64 "\n", pid);
1340 }
1341 } else {
1342 ProcessInstanceInfoList proc_infos;
1343 const uint32_t matches =
1344 platform_sp->FindProcesses(m_options.match_info, proc_infos);
1345 const char *match_desc = nullptr;
1346 const char *match_name =
1348 if (match_name && match_name[0]) {
1350 case NameMatch::Ignore:
1351 break;
1352 case NameMatch::Equals:
1353 match_desc = "matched";
1354 break;
1355 case NameMatch::Contains:
1356 match_desc = "contained";
1357 break;
1358 case NameMatch::StartsWith:
1359 match_desc = "started with";
1360 break;
1361 case NameMatch::EndsWith:
1362 match_desc = "ended with";
1363 break;
1364 case NameMatch::RegularExpression:
1365 match_desc = "matched the regular expression";
1366 break;
1367 }
1368 }
1369
1370 if (matches == 0) {
1371 if (match_desc)
1373 "no processes were found that {0} \"{1}\" on the \"{2}\" "
1374 "platform\n",
1375 match_desc, match_name, platform_sp->GetName());
1376 else
1378 "no processes were found on the \"{0}\" platform\n",
1379 platform_sp->GetName());
1380 } else {
1382 "{0} matching process{1} found on \"{2}\"", matches,
1383 matches > 1 ? "es were" : " was", platform_sp->GetName());
1384 if (match_desc)
1385 result.AppendMessageWithFormat(" whose name %s \"%s\"",
1386 match_desc, match_name);
1387 result.AppendMessageWithFormat("\n");
1390 for (uint32_t i = 0; i < matches; ++i) {
1391 proc_infos[i].DumpAsTableRow(
1392 ostrm, platform_sp->GetUserIDResolver(), m_options.show_args,
1394 }
1395 }
1396 }
1397 }
1398 } else {
1399 result.AppendError("no platform is selected\n");
1400 }
1401 return result.Succeeded();
1402 }
1403
1404 class CommandOptions : public Options {
1405 public:
1406 CommandOptions() = default;
1407
1408 ~CommandOptions() override = default;
1409
1410 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1411 ExecutionContext *execution_context) override {
1412 Status error;
1413 const int short_option = m_getopt_table[option_idx].val;
1414 bool success = false;
1415
1416 uint32_t id = LLDB_INVALID_PROCESS_ID;
1417 success = !option_arg.getAsInteger(0, id);
1418 switch (short_option) {
1419 case 'p': {
1421 if (!success)
1422 error.SetErrorStringWithFormat("invalid process ID string: '%s'",
1423 option_arg.str().c_str());
1424 break;
1425 }
1426 case 'P':
1428 if (!success)
1429 error.SetErrorStringWithFormat(
1430 "invalid parent process ID string: '%s'",
1431 option_arg.str().c_str());
1432 break;
1433
1434 case 'u':
1436 if (!success)
1437 error.SetErrorStringWithFormat("invalid user ID string: '%s'",
1438 option_arg.str().c_str());
1439 break;
1440
1441 case 'U':
1443 : UINT32_MAX);
1444 if (!success)
1445 error.SetErrorStringWithFormat(
1446 "invalid effective user ID string: '%s'",
1447 option_arg.str().c_str());
1448 break;
1449
1450 case 'g':
1452 if (!success)
1453 error.SetErrorStringWithFormat("invalid group ID string: '%s'",
1454 option_arg.str().c_str());
1455 break;
1456
1457 case 'G':
1459 : UINT32_MAX);
1460 if (!success)
1461 error.SetErrorStringWithFormat(
1462 "invalid effective group ID string: '%s'",
1463 option_arg.str().c_str());
1464 break;
1465
1466 case 'a': {
1467 TargetSP target_sp =
1468 execution_context ? execution_context->GetTargetSP() : TargetSP();
1469 DebuggerSP debugger_sp =
1470 target_sp ? target_sp->GetDebugger().shared_from_this()
1471 : DebuggerSP();
1472 PlatformSP platform_sp =
1473 debugger_sp ? debugger_sp->GetPlatformList().GetSelectedPlatform()
1474 : PlatformSP();
1476 Platform::GetAugmentedArchSpec(platform_sp.get(), option_arg);
1477 } break;
1478
1479 case 'n':
1481 option_arg, FileSpec::Style::native);
1482 match_info.SetNameMatchType(NameMatch::Equals);
1483 break;
1484
1485 case 'e':
1487 option_arg, FileSpec::Style::native);
1488 match_info.SetNameMatchType(NameMatch::EndsWith);
1489 break;
1490
1491 case 's':
1493 option_arg, FileSpec::Style::native);
1494 match_info.SetNameMatchType(NameMatch::StartsWith);
1495 break;
1496
1497 case 'c':
1499 option_arg, FileSpec::Style::native);
1500 match_info.SetNameMatchType(NameMatch::Contains);
1501 break;
1502
1503 case 'r':
1505 option_arg, FileSpec::Style::native);
1506 match_info.SetNameMatchType(NameMatch::RegularExpression);
1507 break;
1508
1509 case 'A':
1510 show_args = true;
1511 break;
1512
1513 case 'v':
1514 verbose = true;
1515 break;
1516
1517 case 'x':
1519 break;
1520
1521 default:
1522 llvm_unreachable("Unimplemented option");
1523 }
1524
1525 return error;
1526 }
1527
1528 void OptionParsingStarting(ExecutionContext *execution_context) override {
1529 match_info.Clear();
1530 show_args = false;
1531 verbose = false;
1532 }
1533
1534 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1535 return llvm::ArrayRef(g_platform_process_list_options);
1536 }
1537
1538 // Instance variables to hold the values for command options.
1539
1541 bool show_args = false;
1542 bool verbose = false;
1543 };
1544
1546};
1547
1548// "platform process info"
1550public:
1553 interpreter, "platform process info",
1554 "Get detailed information for one or more process by process ID.",
1555 "platform process info <pid> [<pid> <pid> ...]", 0) {
1557 CommandArgumentData pid_args;
1558
1559 // Define the first (and only) variant of this arg.
1560 pid_args.arg_type = eArgTypePid;
1561 pid_args.arg_repetition = eArgRepeatStar;
1562
1563 // There is only one variant this argument could be; put it into the
1564 // argument entry.
1565 arg.push_back(pid_args);
1566
1567 // Push the data for the first argument into the m_arguments vector.
1568 m_arguments.push_back(arg);
1569 }
1570
1572
1573 void
1575 OptionElementVector &opt_element_vector) override {
1578 }
1579
1580protected:
1581 bool DoExecute(Args &args, CommandReturnObject &result) override {
1582 Target *target = GetDebugger().GetSelectedTarget().get();
1583 PlatformSP platform_sp;
1584 if (target) {
1585 platform_sp = target->GetPlatform();
1586 }
1587 if (!platform_sp) {
1589 }
1590
1591 if (platform_sp) {
1592 const size_t argc = args.GetArgumentCount();
1593 if (argc > 0) {
1594 Status error;
1595
1596 if (platform_sp->IsConnected()) {
1597 Stream &ostrm = result.GetOutputStream();
1598 for (auto &entry : args.entries()) {
1599 lldb::pid_t pid;
1600 if (entry.ref().getAsInteger(0, pid)) {
1601 result.AppendErrorWithFormat("invalid process ID argument '%s'",
1602 entry.ref().str().c_str());
1603 break;
1604 } else {
1605 ProcessInstanceInfo proc_info;
1606 if (platform_sp->GetProcessInfo(pid, proc_info)) {
1607 ostrm.Printf("Process information for process %" PRIu64 ":\n",
1608 pid);
1609 proc_info.Dump(ostrm, platform_sp->GetUserIDResolver());
1610 } else {
1611 ostrm.Printf("error: no process information is available for "
1612 "process %" PRIu64 "\n",
1613 pid);
1614 }
1615 ostrm.EOL();
1616 }
1617 }
1618 } else {
1619 // Not connected...
1620 result.AppendErrorWithFormatv("not connected to '{0}'",
1621 platform_sp->GetPluginName());
1622 }
1623 } else {
1624 // No args
1625 result.AppendError("one or more process id(s) must be specified");
1626 }
1627 } else {
1628 result.AppendError("no platform is currently selected");
1629 }
1630 return result.Succeeded();
1631 }
1632};
1633
1634#define LLDB_OPTIONS_platform_process_attach
1635#include "CommandOptions.inc"
1636
1638public:
1640 : CommandObjectParsed(interpreter, "platform process attach",
1641 "Attach to a process.",
1642 "platform process attach <cmd-options>"),
1643 m_class_options("scripted process", true, 'C', 'k', 'v', 0) {
1648 }
1649
1651
1652 bool DoExecute(Args &command, CommandReturnObject &result) override {
1653 PlatformSP platform_sp(
1654 GetDebugger().GetPlatformList().GetSelectedPlatform());
1655 if (platform_sp) {
1656
1657 if (!m_class_options.GetName().empty()) {
1658 m_options.attach_info.SetProcessPluginName("ScriptedProcess");
1659 ScriptedMetadataSP metadata_sp = std::make_shared<ScriptedMetadata>(
1662 }
1663
1664 Status err;
1665 ProcessSP remote_process_sp = platform_sp->Attach(
1666 m_options.attach_info, GetDebugger(), nullptr, err);
1667 if (err.Fail()) {
1668 result.AppendError(err.AsCString());
1669 } else if (!remote_process_sp) {
1670 result.AppendError("could not attach: unknown reason");
1671 } else
1673 } else {
1674 result.AppendError("no platform is currently selected");
1675 }
1676 return result.Succeeded();
1677 }
1678
1679 Options *GetOptions() override { return &m_all_options; }
1680
1681protected:
1685};
1686
1688public:
1689 // Constructors and Destructors
1691 : CommandObjectMultiword(interpreter, "platform process",
1692 "Commands to query, launch and attach to "
1693 "processes on the current platform.",
1694 "platform process [attach|launch|list] ...") {
1696 "attach",
1699 "launch",
1702 interpreter)));
1704 interpreter)));
1705 }
1706
1707 ~CommandObjectPlatformProcess() override = default;
1708
1709private:
1710 // For CommandObjectPlatform only
1714};
1715
1716// "platform shell"
1717#define LLDB_OPTIONS_platform_shell
1718#include "CommandOptions.inc"
1719
1721public:
1722 class CommandOptions : public Options {
1723 public:
1724 CommandOptions() = default;
1725
1726 ~CommandOptions() override = default;
1727
1728 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1729 return llvm::ArrayRef(g_platform_shell_options);
1730 }
1731
1732 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1733 ExecutionContext *execution_context) override {
1734 Status error;
1735
1736 const char short_option = (char)GetDefinitions()[option_idx].short_option;
1737
1738 switch (short_option) {
1739 case 'h':
1740 m_use_host_platform = true;
1741 break;
1742 case 't':
1743 uint32_t timeout_sec;
1744 if (option_arg.getAsInteger(10, timeout_sec))
1745 error.SetErrorStringWithFormat(
1746 "could not convert \"%s\" to a numeric value.",
1747 option_arg.str().c_str());
1748 else
1749 m_timeout = std::chrono::seconds(timeout_sec);
1750 break;
1751 case 's': {
1752 if (option_arg.empty()) {
1753 error.SetErrorStringWithFormat(
1754 "missing shell interpreter path for option -i|--interpreter.");
1755 return error;
1756 }
1757
1758 m_shell_interpreter = option_arg.str();
1759 break;
1760 }
1761 default:
1762 llvm_unreachable("Unimplemented option");
1763 }
1764
1765 return error;
1766 }
1767
1768 void OptionParsingStarting(ExecutionContext *execution_context) override {
1769 m_timeout.reset();
1770 m_use_host_platform = false;
1771 m_shell_interpreter.clear();
1772 }
1773
1774 Timeout<std::micro> m_timeout = std::chrono::seconds(10);
1777 };
1778
1780 : CommandObjectRaw(interpreter, "platform shell",
1781 "Run a shell command on the current platform.",
1782 "platform shell <shell-command>", 0) {
1784 m_arguments.push_back({thread_arg});
1785 }
1786
1787 ~CommandObjectPlatformShell() override = default;
1788
1789 Options *GetOptions() override { return &m_options; }
1790
1791 bool DoExecute(llvm::StringRef raw_command_line,
1792 CommandReturnObject &result) override {
1795
1796 // Print out an usage syntax on an empty command line.
1797 if (raw_command_line.empty()) {
1798 result.GetOutputStream().Printf("%s\n", this->GetSyntax().str().c_str());
1799 return true;
1800 }
1801
1802 const bool is_alias = !raw_command_line.contains("platform");
1803 OptionsWithRaw args(raw_command_line);
1804
1805 if (args.HasArgs())
1806 if (!ParseOptions(args.GetArgs(), result))
1807 return false;
1808
1809 if (args.GetRawPart().empty()) {
1810 result.GetOutputStream().Printf("%s <shell-command>\n",
1811 is_alias ? "shell" : "platform shell");
1812 return false;
1813 }
1814
1815 llvm::StringRef cmd = args.GetRawPart();
1816
1817 PlatformSP platform_sp(
1820 : GetDebugger().GetPlatformList().GetSelectedPlatform());
1821 Status error;
1822 if (platform_sp) {
1823 FileSpec working_dir{};
1824 std::string output;
1825 int status = -1;
1826 int signo = -1;
1827 error = (platform_sp->RunShellCommand(m_options.m_shell_interpreter, cmd,
1828 working_dir, &status, &signo,
1829 &output, m_options.m_timeout));
1830 if (!output.empty())
1831 result.GetOutputStream().PutCString(output);
1832 if (status > 0) {
1833 if (signo > 0) {
1834 const char *signo_cstr = Host::GetSignalAsCString(signo);
1835 if (signo_cstr)
1836 result.GetOutputStream().Printf(
1837 "error: command returned with status %i and signal %s\n",
1838 status, signo_cstr);
1839 else
1840 result.GetOutputStream().Printf(
1841 "error: command returned with status %i and signal %i\n",
1842 status, signo);
1843 } else
1844 result.GetOutputStream().Printf(
1845 "error: command returned with status %i\n", status);
1846 }
1847 } else {
1848 result.GetOutputStream().Printf(
1849 "error: cannot run remote shell commands without a platform\n");
1850 error.SetErrorString(
1851 "error: cannot run remote shell commands without a platform");
1852 }
1853
1854 if (error.Fail()) {
1855 result.AppendError(error.AsCString());
1856 } else {
1858 }
1859 return true;
1860 }
1861
1863};
1864
1865// "platform install" - install a target to a remote end
1867public:
1870 interpreter, "platform target-install",
1871 "Install a target (bundle or executable file) to the remote end.",
1872 "platform target-install <local-thing> <remote-sandbox>", 0) {
1875 m_arguments.push_back({local_arg});
1876 m_arguments.push_back({remote_arg});
1877 }
1878
1879 ~CommandObjectPlatformInstall() override = default;
1880
1881 void
1883 OptionElementVector &opt_element_vector) override {
1884 if (request.GetCursorIndex())
1885 return;
1888 }
1889
1890 bool DoExecute(Args &args, CommandReturnObject &result) override {
1891 if (args.GetArgumentCount() != 2) {
1892 result.AppendError("platform target-install takes two arguments");
1893 return false;
1894 }
1895 // TODO: move the bulk of this code over to the platform itself
1896 FileSpec src(args.GetArgumentAtIndex(0));
1898 FileSpec dst(args.GetArgumentAtIndex(1));
1899 if (!FileSystem::Instance().Exists(src)) {
1900 result.AppendError("source location does not exist or is not accessible");
1901 return false;
1902 }
1903 PlatformSP platform_sp(
1904 GetDebugger().GetPlatformList().GetSelectedPlatform());
1905 if (!platform_sp) {
1906 result.AppendError("no platform currently selected");
1907 return false;
1908 }
1909
1910 Status error = platform_sp->Install(src, dst);
1911 if (error.Success()) {
1913 } else {
1914 result.AppendErrorWithFormat("install failed: %s", error.AsCString());
1915 }
1916 return result.Succeeded();
1917 }
1918};
1919
1922 interpreter, "platform", "Commands to manage and create platforms.",
1923 "platform [connect|disconnect|info|list|status|select] ...") {
1924 LoadSubCommand("select",
1926 LoadSubCommand("list",
1927 CommandObjectSP(new CommandObjectPlatformList(interpreter)));
1928 LoadSubCommand("status",
1931 new CommandObjectPlatformConnect(interpreter)));
1933 "disconnect",
1936 interpreter)));
1937 LoadSubCommand("mkdir",
1939 LoadSubCommand("file",
1940 CommandObjectSP(new CommandObjectPlatformFile(interpreter)));
1941 LoadSubCommand("file-exists",
1944 interpreter)));
1945 LoadSubCommand("get-permissions",
1948 interpreter)));
1950 interpreter)));
1952 new CommandObjectPlatformProcess(interpreter)));
1953 LoadSubCommand("shell",
1956 "target-install",
1958}
1959
static mode_t ParsePermissionString(const char *)=delete
static PosixPlatformCommandOptionValidator posix_validator
static llvm::raw_ostream & error(Stream &strm)
bool DoExecute(Args &args, CommandReturnObject &result) override
~CommandObjectPlatformConnect() override=default
CommandObjectPlatformConnect(CommandInterpreter &interpreter)
~CommandObjectPlatformDisconnect() override=default
CommandObjectPlatformDisconnect(CommandInterpreter &interpreter)
bool DoExecute(Args &args, CommandReturnObject &result) override
bool DoExecute(Args &args, CommandReturnObject &result) override
CommandObjectPlatformFClose(CommandInterpreter &interpreter)
~CommandObjectPlatformFClose() override=default
~CommandObjectPlatformFOpen() override=default
bool DoExecute(Args &args, CommandReturnObject &result) override
CommandObjectPlatformFOpen(CommandInterpreter &interpreter)
void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override
The input array contains a parsed version of the line.
void OptionParsingStarting(ExecutionContext *execution_context) override
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
bool DoExecute(Args &args, CommandReturnObject &result) override
CommandObjectPlatformFRead(CommandInterpreter &interpreter)
~CommandObjectPlatformFRead() override=default
void OptionParsingStarting(ExecutionContext *execution_context) override
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
~CommandObjectPlatformFWrite() override=default
CommandObjectPlatformFWrite(CommandInterpreter &interpreter)
bool DoExecute(Args &args, CommandReturnObject &result) override
bool DoExecute(Args &args, CommandReturnObject &result) override
CommandObjectPlatformFileExists(CommandInterpreter &interpreter)
void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override
The input array contains a parsed version of the line.
~CommandObjectPlatformFileExists() override=default
CommandObjectPlatformFile(CommandInterpreter &interpreter)
const CommandObjectPlatformFile & operator=(const CommandObjectPlatformFile &)=delete
CommandObjectPlatformFile(const CommandObjectPlatformFile &)=delete
~CommandObjectPlatformFile() override=default
~CommandObjectPlatformGetFile() override=default
CommandObjectPlatformGetFile(CommandInterpreter &interpreter)
void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override
The input array contains a parsed version of the line.
bool DoExecute(Args &args, CommandReturnObject &result) override
void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override
The input array contains a parsed version of the line.
~CommandObjectPlatformGetPermissions() override=default
CommandObjectPlatformGetPermissions(CommandInterpreter &interpreter)
bool DoExecute(Args &args, CommandReturnObject &result) override
CommandObjectPlatformGetSize(CommandInterpreter &interpreter)
void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override
The input array contains a parsed version of the line.
bool DoExecute(Args &args, CommandReturnObject &result) override
~CommandObjectPlatformGetSize() override=default
void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override
The input array contains a parsed version of the line.
bool DoExecute(Args &args, CommandReturnObject &result) override
~CommandObjectPlatformInstall() override=default
CommandObjectPlatformInstall(CommandInterpreter &interpreter)
bool DoExecute(Args &args, CommandReturnObject &result) override
CommandObjectPlatformList(CommandInterpreter &interpreter)
~CommandObjectPlatformList() override=default
CommandObjectPlatformMkDir(CommandInterpreter &interpreter)
~CommandObjectPlatformMkDir() override=default
bool DoExecute(Args &args, CommandReturnObject &result) override
CommandObjectPlatformProcessAttach(CommandInterpreter &interpreter)
~CommandObjectPlatformProcessAttach() override=default
bool DoExecute(Args &command, CommandReturnObject &result) override
OptionGroupPythonClassWithDict m_class_options
bool DoExecute(Args &args, CommandReturnObject &result) override
~CommandObjectPlatformProcessInfo() override=default
void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override
The input array contains a parsed version of the line.
CommandObjectPlatformProcessInfo(CommandInterpreter &interpreter)
~CommandObjectPlatformProcessLaunch() override=default
bool DoExecute(Args &args, CommandReturnObject &result) override
OptionGroupPythonClassWithDict m_class_options
CommandObjectPlatformProcessLaunch(CommandInterpreter &interpreter)
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
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.
bool DoExecute(Args &args, CommandReturnObject &result) override
~CommandObjectPlatformProcessList() override=default
CommandObjectPlatformProcessList(CommandInterpreter &interpreter)
const CommandObjectPlatformProcess & operator=(const CommandObjectPlatformProcess &)=delete
CommandObjectPlatformProcess(const CommandObjectPlatformProcess &)=delete
~CommandObjectPlatformProcess() override=default
CommandObjectPlatformProcess(CommandInterpreter &interpreter)
bool DoExecute(Args &args, CommandReturnObject &result) override
void HandleArgumentCompletion(CompletionRequest &request, OptionElementVector &opt_element_vector) override
The input array contains a parsed version of the line.
CommandObjectPlatformPutFile(CommandInterpreter &interpreter)
~CommandObjectPlatformPutFile() override=default
~CommandObjectPlatformSelect() override=default
void HandleCompletion(CompletionRequest &request) override
This default version handles calling option argument completions and then calls HandleArgumentComplet...
bool DoExecute(Args &args, CommandReturnObject &result) override
CommandObjectPlatformSelect(CommandInterpreter &interpreter)
CommandObjectPlatformSettings(CommandInterpreter &interpreter)
bool DoExecute(Args &args, CommandReturnObject &result) override
~CommandObjectPlatformSettings() override=default
void OptionParsingStarting(ExecutionContext *execution_context) override
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
Set the value of an option.
~CommandObjectPlatformShell() override=default
bool DoExecute(llvm::StringRef raw_command_line, CommandReturnObject &result) override
CommandObjectPlatformShell(CommandInterpreter &interpreter)
~CommandObjectPlatformStatus() override=default
bool DoExecute(Args &args, CommandReturnObject &result) override
CommandObjectPlatformStatus(CommandInterpreter &interpreter)
const OptionPermissions & operator=(const OptionPermissions &)=delete
void OptionParsingStarting(ExecutionContext *execution_context) override
OptionPermissions()=default
lldb_private::Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, ExecutionContext *execution_context) override
~OptionPermissions() override=default
OptionPermissions(const OptionPermissions &)=delete
llvm::ArrayRef< OptionDefinition > GetDefinitions() override
An architecture specification class.
Definition: ArchSpec.h:31
A command line argument class.
Definition: Args.h:33
void AppendArguments(const Args &rhs)
Definition: Args.cpp:297
size_t GetArgumentCount() const
Gets the number of arguments left in this command object.
Definition: Args.h:116
void AppendArgument(llvm::StringRef arg_str, char quote_char='\0')
Appends a new argument to the end of the list argument list.
Definition: Args.cpp:322
llvm::ArrayRef< ArgEntry > entries() const
Definition: Args.h:128
const char * GetArgumentAtIndex(size_t idx) const
Gets the NULL terminated C string argument pointer for the argument at index idx.
Definition: Args.cpp:263
bool GetCommandString(std::string &command) const
Definition: Args.cpp:211
static bool InvokeCommonCompletionCallbacks(CommandInterpreter &interpreter, uint32_t completion_mask, lldb_private::CompletionRequest &request, SearchFilter *searcher)
static void PlatformPluginNames(CommandInterpreter &interpreter, CompletionRequest &request, SearchFilter *searcher)
ExecutionContext GetExecutionContext() const
bool LoadSubCommand(llvm::StringRef cmd_name, const lldb::CommandObjectSP &command_obj) override
CommandObjectPlatform(CommandInterpreter &interpreter)
std::vector< CommandArgumentData > CommandArgumentEntry
virtual void SetHelpLong(llvm::StringRef str)
ExecutionContext m_exe_ctx
std::vector< CommandArgumentEntry > m_arguments
CommandInterpreter & GetCommandInterpreter()
CommandInterpreter & m_interpreter
bool ParseOptions(Args &args, CommandReturnObject &result)
virtual llvm::StringRef GetSyntax()
void AppendErrorWithFormatv(const char *format, Args &&... args)
void void AppendError(llvm::StringRef in_string)
void SetStatus(lldb::ReturnStatus status)
void void AppendMessageWithFormatv(const char *format, Args &&... args)
void AppendErrorWithFormat(const char *format,...) __attribute__((format(printf
void AppendMessageWithFormat(const char *format,...) __attribute__((format(printf
"lldb/Utility/ArgCompletionRequest.h"
A class to manage flag bits.
Definition: Debugger.h:79
lldb::TargetSP GetSelectedTarget()
Definition: Debugger.h:192
CommandInterpreter & GetCommandInterpreter()
Definition: Debugger.h:175
PlatformList & GetPlatformList()
Definition: Debugger.h:207
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
const lldb::TargetSP & GetTargetSP() const
Get accessor to get the target shared pointer.
Target * GetTargetPtr() const
Returns a pointer to the target object.
A file utility class.
Definition: FileSpec.h:56
void SetFile(llvm::StringRef path, Style style)
Change the file specified with a new path.
Definition: FileSpec.cpp:174
size_t GetPath(char *path, size_t max_path_length, bool denormalize=true) const
Extract the full path to the file.
Definition: FileSpec.cpp:367
void Resolve(llvm::SmallVectorImpl< char > &path)
Resolve path to make it canonical.
static FileSystem & Instance()
@ eOpenOptionReadWrite
Definition: File.h:53
@ eOpenOptionCanCreate
Definition: File.h:56
bool Test(ValueType bit) const
Test a single flag bit.
Definition: Flags.h:96
static const char * GetSignalAsCString(int signo)
A class that describes an executable image and its associated object and symbol files.
Definition: Module.h:88
const ArchSpec & GetArchitecture() const
Get const accessor for the module architecture.
Definition: Module.cpp:1106
const FileSpec & GetFileSpec() const
Get const accessor for the module file specification.
Definition: Module.h:497
OptionValueFileSpec & GetOptionValue()
const OptionGroup * GetGroupWithOption(char short_opt)
Definition: Options.cpp:763
void Append(OptionGroup *group)
Append options from a OptionGroup class.
Definition: Options.cpp:755
void SetPlatformName(const char *platform_name)
lldb::PlatformSP CreatePlatformWithOptions(CommandInterpreter &interpreter, const ArchSpec &arch, bool make_selected, Status &error, ArchSpec &platform_arch) const
const StructuredData::DictionarySP GetStructuredData()
A pair of an option list with a 'raw' string as a suffix.
Definition: Args.h:315
bool HasArgs() const
Returns true if there are any arguments before the raw suffix.
Definition: Args.h:326
Args & GetArgs()
Returns the list of arguments.
Definition: Args.h:331
const std::string & GetRawPart() const
Returns the raw suffix part of the parsed string.
Definition: Args.h:364
A command line option parsing protocol class.
Definition: Options.h:58
void NotifyOptionParsingStarting(ExecutionContext *execution_context)
Definition: Options.cpp:33
std::vector< Option > m_getopt_table
Definition: Options.h:198
lldb::PlatformSP GetSelectedPlatform()
Select the active platform.
Definition: Platform.h:1030
void SetSelectedPlatform(const lldb::PlatformSP &platform_sp)
Definition: Platform.h:1038
static ArchSpec GetAugmentedArchSpec(Platform *platform, llvm::StringRef triple)
Augments the triple either with information from platform or the host system (if platform is null).
Definition: Platform.cpp:261
static lldb::PlatformSP GetHostPlatform()
Get the native host platform plug-in.
Definition: Platform.cpp:134
static llvm::StringRef GetPlatformPluginDescriptionAtIndex(uint32_t idx)
static llvm::StringRef GetPlatformPluginNameAtIndex(uint32_t idx)
void SetProcessPluginName(llvm::StringRef plugin)
Definition: Process.h:155
void SetGroupID(uint32_t gid)
Definition: ProcessInfo.h:59
const char * GetName() const
Definition: ProcessInfo.cpp:45
lldb::pid_t GetProcessID() const
Definition: ProcessInfo.h:67
void SetScriptedMetadata(lldb::ScriptedMetadataSP metadata_sp)
Definition: ProcessInfo.h:96
void SetArguments(const Args &args, bool first_arg_is_executable)
void SetProcessID(lldb::pid_t pid)
Definition: ProcessInfo.h:69
FileSpec & GetExecutableFile()
Definition: ProcessInfo.h:42
void SetUserID(uint32_t uid)
Definition: ProcessInfo.h:57
ArchSpec & GetArchitecture()
Definition: ProcessInfo.h:61
void SetNameMatchType(NameMatch name_match_type)
Definition: ProcessInfo.h:215
ProcessInstanceInfo & GetProcessInfo()
Definition: ProcessInfo.h:205
void SetEffectiveGroupID(uint32_t gid)
Definition: ProcessInfo.h:165
static void DumpTableHeader(Stream &s, bool show_args, bool verbose)
void Dump(Stream &s, UserIDResolver &resolver) const
void DumpAsTableRow(Stream &s, UserIDResolver &resolver, bool show_args, bool verbose) const
void SetParentProcessID(lldb::pid_t pid)
Definition: ProcessInfo.h:169
void SetEffectiveUserID(uint32_t uid)
Definition: ProcessInfo.h:163
void SetProcessPluginName(llvm::StringRef plugin)
An error handling class.
Definition: Status.h:44
bool Fail() const
Test for error condition.
Definition: Status.cpp:181
const char * AsCString(const char *default_error_str="unknown error") const
Get the error string associated with the current error.
Definition: Status.cpp:130
A stream class that can stream formatted output to a file.
Definition: Stream.h:28
void Format(const char *format, Args &&... args)
Definition: Stream.h:309
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:107
size_t PutCString(llvm::StringRef cstr)
Output a C string to the stream.
Definition: Stream.cpp:63
size_t EOL()
Output and End of Line character to the stream.
Definition: Stream.cpp:128
void SetProcessLaunchInfo(const ProcessLaunchInfo &launch_info)
Definition: Target.cpp:4743
bool GetRunArguments(Args &args) const
Definition: Target.cpp:4330
Module * GetExecutableModulePointer()
Definition: Target.cpp:1389
lldb::PlatformSP GetPlatform()
Definition: Target.h:1428
#define LLDB_OPT_SET_1
Definition: lldb-defines.h:107
#define UINT64_MAX
Definition: lldb-defines.h:23
#define LLDB_OPT_SET_2
Definition: lldb-defines.h:108
#define LLDB_OPT_SET_ALL
Definition: lldb-defines.h:106
#define UINT32_MAX
Definition: lldb-defines.h:19
#define LLDB_INVALID_PROCESS_ID
Definition: lldb-defines.h:86
A class that represents a running process on the host machine.
Definition: SBAttachInfo.h:14
std::vector< OptionArgElement > OptionElementVector
Definition: Options.h:43
const char * StateAsCString(lldb::StateType state)
Converts a StateType to a C string.
Definition: State.cpp:14
std::vector< ProcessInstanceInfo > ProcessInstanceInfoList
Definition: Host.h:32
Definition: SBAddress.h:15
@ eRemoteDiskDirectoryCompletion
@ eDiskFileCompletion
@ eRemoteDiskFileCompletion
@ eProcessIDCompletion
std::shared_ptr< lldb_private::ScriptedMetadata > ScriptedMetadataSP
Definition: lldb-forward.h:386
std::shared_ptr< lldb_private::CommandObject > CommandObjectSP
Definition: lldb-forward.h:315
std::shared_ptr< lldb_private::Platform > PlatformSP
Definition: lldb-forward.h:367
StateType
Process and Thread States.
@ eStateStopped
Process or thread is stopped and can be examined.
std::shared_ptr< lldb_private::Process > ProcessSP
Definition: lldb-forward.h:368
std::shared_ptr< lldb_private::Debugger > DebuggerSP
Definition: lldb-forward.h:321
std::shared_ptr< lldb_private::Event > EventSP
Definition: lldb-forward.h:327
@ eReturnStatusSuccessFinishResult
@ eReturnStatusSuccessFinishNoResult
uint64_t pid_t
Definition: lldb-types.h:81
@ eArgTypeFilename
@ eArgTypeConnectURL
@ eArgTypePlatform
@ eArgTypeUnsignedInteger
uint64_t user_id_t
Definition: lldb-types.h:80
std::shared_ptr< lldb_private::Target > TargetSP
Definition: lldb-forward.h:423
Used to build individual command argument lists.
Definition: CommandObject.h:93