1 //===-- CommandObjectPlatform.cpp -------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
9 #include "CommandObjectPlatform.h"
10 #include "lldb/Core/Debugger.h"
11 #include "lldb/Core/Module.h"
12 #include "lldb/Core/PluginManager.h"
13 #include "lldb/Host/OptionParser.h"
14 #include "lldb/Host/StringConvert.h"
15 #include "lldb/Interpreter/CommandInterpreter.h"
16 #include "lldb/Interpreter/CommandOptionValidators.h"
17 #include "lldb/Interpreter/CommandReturnObject.h"
18 #include "lldb/Interpreter/OptionGroupFile.h"
19 #include "lldb/Interpreter/OptionGroupPlatform.h"
20 #include "lldb/Target/ExecutionContext.h"
21 #include "lldb/Target/Platform.h"
22 #include "lldb/Target/Process.h"
23 #include "lldb/Utility/Args.h"
25 #include "llvm/ADT/SmallString.h"
28 using namespace lldb_private
;
30 static mode_t
ParsePermissionString(const char *) = delete;
32 static mode_t
ParsePermissionString(llvm::StringRef permissions
) {
33 if (permissions
.size() != 9)
35 bool user_r
, user_w
, user_x
, group_r
, group_w
, group_x
, world_r
, world_w
,
38 user_r
= (permissions
[0] == 'r');
39 user_w
= (permissions
[1] == 'w');
40 user_x
= (permissions
[2] == 'x');
42 group_r
= (permissions
[3] == 'r');
43 group_w
= (permissions
[4] == 'w');
44 group_x
= (permissions
[5] == 'x');
46 world_r
= (permissions
[6] == 'r');
47 world_w
= (permissions
[7] == 'w');
48 world_x
= (permissions
[8] == 'x');
50 mode_t user
, group
, world
;
51 user
= (user_r
? 4 : 0) | (user_w
? 2 : 0) | (user_x
? 1 : 0);
52 group
= (group_r
? 4 : 0) | (group_w
? 2 : 0) | (group_x
? 1 : 0);
53 world
= (world_r
? 4 : 0) | (world_w
? 2 : 0) | (world_x
? 1 : 0);
55 return user
| group
| world
;
58 #define LLDB_OPTIONS_permissions
59 #include "CommandOptions.inc"
61 class OptionPermissions
: public OptionGroup
{
63 OptionPermissions() {}
65 ~OptionPermissions() override
= default;
68 SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
69 ExecutionContext
*execution_context
) override
{
71 char short_option
= (char)GetDefinitions()[option_idx
].short_option
;
72 switch (short_option
) {
74 if (option_arg
.getAsInteger(8, m_permissions
)) {
76 error
.SetErrorStringWithFormat("invalid value for permissions: %s",
77 option_arg
.str().c_str());
82 mode_t perms
= ParsePermissionString(option_arg
);
83 if (perms
== (mode_t
)-1)
84 error
.SetErrorStringWithFormat("invalid value for permissions: %s",
85 option_arg
.str().c_str());
87 m_permissions
= perms
;
90 m_permissions
|= lldb::eFilePermissionsUserRead
;
93 m_permissions
|= lldb::eFilePermissionsUserWrite
;
96 m_permissions
|= lldb::eFilePermissionsUserExecute
;
99 m_permissions
|= lldb::eFilePermissionsGroupRead
;
102 m_permissions
|= lldb::eFilePermissionsGroupWrite
;
105 m_permissions
|= lldb::eFilePermissionsGroupExecute
;
108 m_permissions
|= lldb::eFilePermissionsWorldRead
;
111 m_permissions
|= lldb::eFilePermissionsWorldWrite
;
114 m_permissions
|= lldb::eFilePermissionsWorldExecute
;
117 llvm_unreachable("Unimplemented option");
123 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
127 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
128 return llvm::makeArrayRef(g_permissions_options
);
131 // Instance variables to hold the values for command options.
133 uint32_t m_permissions
;
136 DISALLOW_COPY_AND_ASSIGN(OptionPermissions
);
139 // "platform select <platform-name>"
140 class CommandObjectPlatformSelect
: public CommandObjectParsed
{
142 CommandObjectPlatformSelect(CommandInterpreter
&interpreter
)
143 : CommandObjectParsed(interpreter
, "platform select",
144 "Create a platform if needed and select it as the "
146 "platform select <platform-name>", 0),
149 false) // Don't include the "--platform" option by passing false
151 m_option_group
.Append(&m_platform_options
, LLDB_OPT_SET_ALL
, 1);
152 m_option_group
.Finalize();
155 ~CommandObjectPlatformSelect() override
= default;
157 void HandleCompletion(CompletionRequest
&request
) override
{
158 CommandCompletions::PlatformPluginNames(GetCommandInterpreter(), request
,
162 Options
*GetOptions() override
{ return &m_option_group
; }
165 bool DoExecute(Args
&args
, CommandReturnObject
&result
) override
{
166 if (args
.GetArgumentCount() == 1) {
167 const char *platform_name
= args
.GetArgumentAtIndex(0);
168 if (platform_name
&& platform_name
[0]) {
169 const bool select
= true;
170 m_platform_options
.SetPlatformName(platform_name
);
172 ArchSpec platform_arch
;
173 PlatformSP
platform_sp(m_platform_options
.CreatePlatformWithOptions(
174 m_interpreter
, ArchSpec(), select
, error
, platform_arch
));
176 GetDebugger().GetPlatformList().SetSelectedPlatform(platform_sp
);
178 platform_sp
->GetStatus(result
.GetOutputStream());
179 result
.SetStatus(eReturnStatusSuccessFinishResult
);
181 result
.AppendError(error
.AsCString());
182 result
.SetStatus(eReturnStatusFailed
);
185 result
.AppendError("invalid platform name");
186 result
.SetStatus(eReturnStatusFailed
);
190 "platform create takes a platform name as an argument\n");
191 result
.SetStatus(eReturnStatusFailed
);
193 return result
.Succeeded();
196 OptionGroupOptions m_option_group
;
197 OptionGroupPlatform m_platform_options
;
201 class CommandObjectPlatformList
: public CommandObjectParsed
{
203 CommandObjectPlatformList(CommandInterpreter
&interpreter
)
204 : CommandObjectParsed(interpreter
, "platform list",
205 "List all platforms that are available.", nullptr,
208 ~CommandObjectPlatformList() override
= default;
211 bool DoExecute(Args
&args
, CommandReturnObject
&result
) override
{
212 Stream
&ostrm
= result
.GetOutputStream();
213 ostrm
.Printf("Available platforms:\n");
215 PlatformSP
host_platform_sp(Platform::GetHostPlatform());
216 ostrm
.Printf("%s: %s\n", host_platform_sp
->GetPluginName().GetCString(),
217 host_platform_sp
->GetDescription());
220 for (idx
= 0; true; ++idx
) {
221 const char *plugin_name
=
222 PluginManager::GetPlatformPluginNameAtIndex(idx
);
223 if (plugin_name
== nullptr)
225 const char *plugin_desc
=
226 PluginManager::GetPlatformPluginDescriptionAtIndex(idx
);
227 if (plugin_desc
== nullptr)
229 ostrm
.Printf("%s: %s\n", plugin_name
, plugin_desc
);
233 result
.AppendError("no platforms are available\n");
234 result
.SetStatus(eReturnStatusFailed
);
236 result
.SetStatus(eReturnStatusSuccessFinishResult
);
237 return result
.Succeeded();
242 class CommandObjectPlatformStatus
: public CommandObjectParsed
{
244 CommandObjectPlatformStatus(CommandInterpreter
&interpreter
)
245 : CommandObjectParsed(interpreter
, "platform status",
246 "Display status for the current platform.", nullptr,
249 ~CommandObjectPlatformStatus() override
= default;
252 bool DoExecute(Args
&args
, CommandReturnObject
&result
) override
{
253 Stream
&ostrm
= result
.GetOutputStream();
255 Target
*target
= GetDebugger().GetSelectedTarget().get();
256 PlatformSP platform_sp
;
258 platform_sp
= target
->GetPlatform();
261 platform_sp
= GetDebugger().GetPlatformList().GetSelectedPlatform();
264 platform_sp
->GetStatus(ostrm
);
265 result
.SetStatus(eReturnStatusSuccessFinishResult
);
267 result
.AppendError("no platform is currently selected\n");
268 result
.SetStatus(eReturnStatusFailed
);
270 return result
.Succeeded();
274 // "platform connect <connect-url>"
275 class CommandObjectPlatformConnect
: public CommandObjectParsed
{
277 CommandObjectPlatformConnect(CommandInterpreter
&interpreter
)
278 : CommandObjectParsed(
279 interpreter
, "platform connect",
280 "Select the current platform by providing a connection URL.",
281 "platform connect <connect-url>", 0) {}
283 ~CommandObjectPlatformConnect() override
= default;
286 bool DoExecute(Args
&args
, CommandReturnObject
&result
) override
{
287 Stream
&ostrm
= result
.GetOutputStream();
289 PlatformSP
platform_sp(
290 GetDebugger().GetPlatformList().GetSelectedPlatform());
292 Status
error(platform_sp
->ConnectRemote(args
));
293 if (error
.Success()) {
294 platform_sp
->GetStatus(ostrm
);
295 result
.SetStatus(eReturnStatusSuccessFinishResult
);
297 platform_sp
->ConnectToWaitingProcesses(GetDebugger(), error
);
299 result
.AppendError(error
.AsCString());
300 result
.SetStatus(eReturnStatusFailed
);
303 result
.AppendErrorWithFormat("%s\n", error
.AsCString());
304 result
.SetStatus(eReturnStatusFailed
);
307 result
.AppendError("no platform is currently selected\n");
308 result
.SetStatus(eReturnStatusFailed
);
310 return result
.Succeeded();
313 Options
*GetOptions() override
{
314 PlatformSP
platform_sp(
315 GetDebugger().GetPlatformList().GetSelectedPlatform());
316 OptionGroupOptions
*m_platform_options
= nullptr;
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();
322 return m_platform_options
;
326 // "platform disconnect"
327 class CommandObjectPlatformDisconnect
: public CommandObjectParsed
{
329 CommandObjectPlatformDisconnect(CommandInterpreter
&interpreter
)
330 : CommandObjectParsed(interpreter
, "platform disconnect",
331 "Disconnect from the current platform.",
332 "platform disconnect", 0) {}
334 ~CommandObjectPlatformDisconnect() override
= default;
337 bool DoExecute(Args
&args
, CommandReturnObject
&result
) override
{
338 PlatformSP
platform_sp(
339 GetDebugger().GetPlatformList().GetSelectedPlatform());
341 if (args
.GetArgumentCount() == 0) {
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
;
350 hostname
.assign(hostname_cstr
);
352 error
= platform_sp
->DisconnectRemote();
353 if (error
.Success()) {
354 Stream
&ostrm
= result
.GetOutputStream();
355 if (hostname
.empty())
356 ostrm
.Printf("Disconnected from \"%s\"\n",
357 platform_sp
->GetPluginName().GetCString());
359 ostrm
.Printf("Disconnected from \"%s\"\n", hostname
.c_str());
360 result
.SetStatus(eReturnStatusSuccessFinishResult
);
362 result
.AppendErrorWithFormat("%s", error
.AsCString());
363 result
.SetStatus(eReturnStatusFailed
);
367 result
.AppendErrorWithFormat(
368 "not connected to '%s'",
369 platform_sp
->GetPluginName().GetCString());
370 result
.SetStatus(eReturnStatusFailed
);
375 "\"platform disconnect\" doesn't take any arguments");
376 result
.SetStatus(eReturnStatusFailed
);
379 result
.AppendError("no platform is currently selected");
380 result
.SetStatus(eReturnStatusFailed
);
382 return result
.Succeeded();
386 // "platform settings"
387 class CommandObjectPlatformSettings
: public CommandObjectParsed
{
389 CommandObjectPlatformSettings(CommandInterpreter
&interpreter
)
390 : CommandObjectParsed(interpreter
, "platform settings",
391 "Set settings for the current target's platform, "
392 "or for a platform by name.",
393 "platform settings", 0),
395 m_option_working_dir(LLDB_OPT_SET_1
, false, "working-dir", 'w', 0,
397 "The working directory for the platform.") {
398 m_options
.Append(&m_option_working_dir
, LLDB_OPT_SET_ALL
, LLDB_OPT_SET_1
);
401 ~CommandObjectPlatformSettings() override
= default;
404 bool DoExecute(Args
&args
, CommandReturnObject
&result
) override
{
405 PlatformSP
platform_sp(
406 GetDebugger().GetPlatformList().GetSelectedPlatform());
408 if (m_option_working_dir
.GetOptionValue().OptionWasSet())
409 platform_sp
->SetWorkingDirectory(
410 m_option_working_dir
.GetOptionValue().GetCurrentValue());
412 result
.AppendError("no platform is currently selected");
413 result
.SetStatus(eReturnStatusFailed
);
415 return result
.Succeeded();
418 Options
*GetOptions() override
{
419 if (!m_options
.DidFinalize())
420 m_options
.Finalize();
425 OptionGroupOptions m_options
;
426 OptionGroupFile m_option_working_dir
;
430 class CommandObjectPlatformMkDir
: public CommandObjectParsed
{
432 CommandObjectPlatformMkDir(CommandInterpreter
&interpreter
)
433 : CommandObjectParsed(interpreter
, "platform mkdir",
434 "Make a new directory on the remote end.", nullptr,
438 ~CommandObjectPlatformMkDir() override
= default;
440 bool DoExecute(Args
&args
, CommandReturnObject
&result
) override
{
441 PlatformSP
platform_sp(
442 GetDebugger().GetPlatformList().GetSelectedPlatform());
444 std::string cmd_line
;
445 args
.GetCommandString(cmd_line
);
447 const OptionPermissions
*options_permissions
=
448 (const OptionPermissions
*)m_options
.GetGroupWithOption('r');
449 if (options_permissions
)
450 mode
= options_permissions
->m_permissions
;
452 mode
= lldb::eFilePermissionsUserRWX
| lldb::eFilePermissionsGroupRWX
|
453 lldb::eFilePermissionsWorldRX
;
454 Status error
= platform_sp
->MakeDirectory(FileSpec(cmd_line
), mode
);
455 if (error
.Success()) {
456 result
.SetStatus(eReturnStatusSuccessFinishResult
);
458 result
.AppendError(error
.AsCString());
459 result
.SetStatus(eReturnStatusFailed
);
462 result
.AppendError("no platform currently selected\n");
463 result
.SetStatus(eReturnStatusFailed
);
465 return result
.Succeeded();
468 Options
*GetOptions() override
{
469 if (!m_options
.DidFinalize()) {
470 m_options
.Append(new OptionPermissions());
471 m_options
.Finalize();
476 OptionGroupOptions m_options
;
480 class CommandObjectPlatformFOpen
: public CommandObjectParsed
{
482 CommandObjectPlatformFOpen(CommandInterpreter
&interpreter
)
483 : CommandObjectParsed(interpreter
, "platform file open",
484 "Open a file on the remote end.", nullptr, 0),
487 ~CommandObjectPlatformFOpen() override
= default;
489 bool DoExecute(Args
&args
, CommandReturnObject
&result
) override
{
490 PlatformSP
platform_sp(
491 GetDebugger().GetPlatformList().GetSelectedPlatform());
494 std::string cmd_line
;
495 args
.GetCommandString(cmd_line
);
497 const OptionPermissions
*options_permissions
=
498 (const OptionPermissions
*)m_options
.GetGroupWithOption('r');
499 if (options_permissions
)
500 perms
= options_permissions
->m_permissions
;
502 perms
= lldb::eFilePermissionsUserRW
| lldb::eFilePermissionsGroupRW
|
503 lldb::eFilePermissionsWorldRead
;
504 lldb::user_id_t fd
= platform_sp
->OpenFile(
506 File::eOpenOptionRead
| File::eOpenOptionWrite
|
507 File::eOpenOptionAppend
| File::eOpenOptionCanCreate
,
509 if (error
.Success()) {
510 result
.AppendMessageWithFormat("File Descriptor = %" PRIu64
"\n", fd
);
511 result
.SetStatus(eReturnStatusSuccessFinishResult
);
513 result
.AppendError(error
.AsCString());
514 result
.SetStatus(eReturnStatusFailed
);
517 result
.AppendError("no platform currently selected\n");
518 result
.SetStatus(eReturnStatusFailed
);
520 return result
.Succeeded();
523 Options
*GetOptions() override
{
524 if (!m_options
.DidFinalize()) {
525 m_options
.Append(new OptionPermissions());
526 m_options
.Finalize();
531 OptionGroupOptions m_options
;
535 class CommandObjectPlatformFClose
: public CommandObjectParsed
{
537 CommandObjectPlatformFClose(CommandInterpreter
&interpreter
)
538 : CommandObjectParsed(interpreter
, "platform file close",
539 "Close a file on the remote end.", nullptr, 0) {}
541 ~CommandObjectPlatformFClose() override
= default;
543 bool DoExecute(Args
&args
, CommandReturnObject
&result
) override
{
544 PlatformSP
platform_sp(
545 GetDebugger().GetPlatformList().GetSelectedPlatform());
547 std::string cmd_line
;
548 args
.GetCommandString(cmd_line
);
549 const lldb::user_id_t fd
=
550 StringConvert::ToUInt64(cmd_line
.c_str(), UINT64_MAX
);
552 bool success
= platform_sp
->CloseFile(fd
, error
);
554 result
.AppendMessageWithFormat("file %" PRIu64
" closed.\n", fd
);
555 result
.SetStatus(eReturnStatusSuccessFinishResult
);
557 result
.AppendError(error
.AsCString());
558 result
.SetStatus(eReturnStatusFailed
);
561 result
.AppendError("no platform currently selected\n");
562 result
.SetStatus(eReturnStatusFailed
);
564 return result
.Succeeded();
570 #define LLDB_OPTIONS_platform_fread
571 #include "CommandOptions.inc"
573 class CommandObjectPlatformFRead
: public CommandObjectParsed
{
575 CommandObjectPlatformFRead(CommandInterpreter
&interpreter
)
576 : CommandObjectParsed(interpreter
, "platform file read",
577 "Read data from a file on the remote end.", nullptr,
581 ~CommandObjectPlatformFRead() override
= default;
583 bool DoExecute(Args
&args
, CommandReturnObject
&result
) override
{
584 PlatformSP
platform_sp(
585 GetDebugger().GetPlatformList().GetSelectedPlatform());
587 std::string cmd_line
;
588 args
.GetCommandString(cmd_line
);
589 const lldb::user_id_t fd
=
590 StringConvert::ToUInt64(cmd_line
.c_str(), UINT64_MAX
);
591 std::string
buffer(m_options
.m_count
, 0);
593 uint32_t retcode
= platform_sp
->ReadFile(
594 fd
, m_options
.m_offset
, &buffer
[0], m_options
.m_count
, error
);
595 result
.AppendMessageWithFormat("Return = %d\n", retcode
);
596 result
.AppendMessageWithFormat("Data = \"%s\"\n", buffer
.c_str());
597 result
.SetStatus(eReturnStatusSuccessFinishResult
);
599 result
.AppendError("no platform currently selected\n");
600 result
.SetStatus(eReturnStatusFailed
);
602 return result
.Succeeded();
605 Options
*GetOptions() override
{ return &m_options
; }
608 class CommandOptions
: public Options
{
610 CommandOptions() : Options() {}
612 ~CommandOptions() override
= default;
614 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
615 ExecutionContext
*execution_context
) override
{
617 char short_option
= (char)m_getopt_table
[option_idx
].val
;
619 switch (short_option
) {
621 if (option_arg
.getAsInteger(0, m_offset
))
622 error
.SetErrorStringWithFormat("invalid offset: '%s'",
623 option_arg
.str().c_str());
626 if (option_arg
.getAsInteger(0, m_count
))
627 error
.SetErrorStringWithFormat("invalid offset: '%s'",
628 option_arg
.str().c_str());
631 llvm_unreachable("Unimplemented option");
637 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
642 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
643 return llvm::makeArrayRef(g_platform_fread_options
);
646 // Instance variables to hold the values for command options.
652 CommandOptions m_options
;
657 #define LLDB_OPTIONS_platform_fwrite
658 #include "CommandOptions.inc"
660 class CommandObjectPlatformFWrite
: public CommandObjectParsed
{
662 CommandObjectPlatformFWrite(CommandInterpreter
&interpreter
)
663 : CommandObjectParsed(interpreter
, "platform file write",
664 "Write data to a file on the remote end.", nullptr,
668 ~CommandObjectPlatformFWrite() override
= default;
670 bool DoExecute(Args
&args
, CommandReturnObject
&result
) override
{
671 PlatformSP
platform_sp(
672 GetDebugger().GetPlatformList().GetSelectedPlatform());
674 std::string cmd_line
;
675 args
.GetCommandString(cmd_line
);
677 const lldb::user_id_t fd
=
678 StringConvert::ToUInt64(cmd_line
.c_str(), UINT64_MAX
);
680 platform_sp
->WriteFile(fd
, m_options
.m_offset
, &m_options
.m_data
[0],
681 m_options
.m_data
.size(), error
);
682 result
.AppendMessageWithFormat("Return = %d\n", retcode
);
683 result
.SetStatus(eReturnStatusSuccessFinishResult
);
685 result
.AppendError("no platform currently selected\n");
686 result
.SetStatus(eReturnStatusFailed
);
688 return result
.Succeeded();
691 Options
*GetOptions() override
{ return &m_options
; }
694 class CommandOptions
: public Options
{
696 CommandOptions() : Options() {}
698 ~CommandOptions() override
= default;
700 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
701 ExecutionContext
*execution_context
) override
{
703 char short_option
= (char)m_getopt_table
[option_idx
].val
;
705 switch (short_option
) {
707 if (option_arg
.getAsInteger(0, m_offset
))
708 error
.SetErrorStringWithFormat("invalid offset: '%s'",
709 option_arg
.str().c_str());
712 m_data
.assign(option_arg
);
715 llvm_unreachable("Unimplemented option");
721 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
726 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
727 return llvm::makeArrayRef(g_platform_fwrite_options
);
730 // Instance variables to hold the values for command options.
736 CommandOptions m_options
;
739 class CommandObjectPlatformFile
: public CommandObjectMultiword
{
741 // Constructors and Destructors
742 CommandObjectPlatformFile(CommandInterpreter
&interpreter
)
743 : CommandObjectMultiword(
744 interpreter
, "platform file",
745 "Commands to access files on the current platform.",
746 "platform file [open|close|read|write] ...") {
748 "open", CommandObjectSP(new CommandObjectPlatformFOpen(interpreter
)));
750 "close", CommandObjectSP(new CommandObjectPlatformFClose(interpreter
)));
752 "read", CommandObjectSP(new CommandObjectPlatformFRead(interpreter
)));
754 "write", CommandObjectSP(new CommandObjectPlatformFWrite(interpreter
)));
757 ~CommandObjectPlatformFile() override
= default;
760 // For CommandObjectPlatform only
761 DISALLOW_COPY_AND_ASSIGN(CommandObjectPlatformFile
);
764 // "platform get-file remote-file-path host-file-path"
765 class CommandObjectPlatformGetFile
: public CommandObjectParsed
{
767 CommandObjectPlatformGetFile(CommandInterpreter
&interpreter
)
768 : CommandObjectParsed(
769 interpreter
, "platform get-file",
770 "Transfer a file from the remote end to the local host.",
771 "platform get-file <remote-file-spec> <local-file-spec>", 0) {
775 (lldb) platform get-file /the/remote/file/path /the/local/file/path
777 Transfer a file from the remote end with file path /the/remote/file/path to the local host.)");
779 CommandArgumentEntry arg1
, arg2
;
780 CommandArgumentData file_arg_remote
, file_arg_host
;
782 // Define the first (and only) variant of this arg.
783 file_arg_remote
.arg_type
= eArgTypeFilename
;
784 file_arg_remote
.arg_repetition
= eArgRepeatPlain
;
785 // There is only one variant this argument could be; put it into the
787 arg1
.push_back(file_arg_remote
);
789 // Define the second (and only) variant of this arg.
790 file_arg_host
.arg_type
= eArgTypeFilename
;
791 file_arg_host
.arg_repetition
= eArgRepeatPlain
;
792 // There is only one variant this argument could be; put it into the
794 arg2
.push_back(file_arg_host
);
796 // Push the data for the first and the second arguments into the
797 // m_arguments vector.
798 m_arguments
.push_back(arg1
);
799 m_arguments
.push_back(arg2
);
802 ~CommandObjectPlatformGetFile() override
= default;
804 bool DoExecute(Args
&args
, CommandReturnObject
&result
) override
{
805 // If the number of arguments is incorrect, issue an error message.
806 if (args
.GetArgumentCount() != 2) {
807 result
.GetErrorStream().Printf("error: required arguments missing; "
808 "specify both the source and destination "
810 result
.SetStatus(eReturnStatusFailed
);
814 PlatformSP
platform_sp(
815 GetDebugger().GetPlatformList().GetSelectedPlatform());
817 const char *remote_file_path
= args
.GetArgumentAtIndex(0);
818 const char *local_file_path
= args
.GetArgumentAtIndex(1);
819 Status error
= platform_sp
->GetFile(FileSpec(remote_file_path
),
820 FileSpec(local_file_path
));
821 if (error
.Success()) {
822 result
.AppendMessageWithFormat(
823 "successfully get-file from %s (remote) to %s (host)\n",
824 remote_file_path
, local_file_path
);
825 result
.SetStatus(eReturnStatusSuccessFinishResult
);
827 result
.AppendMessageWithFormat("get-file failed: %s\n",
829 result
.SetStatus(eReturnStatusFailed
);
832 result
.AppendError("no platform currently selected\n");
833 result
.SetStatus(eReturnStatusFailed
);
835 return result
.Succeeded();
839 // "platform get-size remote-file-path"
840 class CommandObjectPlatformGetSize
: public CommandObjectParsed
{
842 CommandObjectPlatformGetSize(CommandInterpreter
&interpreter
)
843 : CommandObjectParsed(interpreter
, "platform get-size",
844 "Get the file size from the remote end.",
845 "platform get-size <remote-file-spec>", 0) {
849 (lldb) platform get-size /the/remote/file/path
851 Get the file size from the remote end with path /the/remote/file/path.)");
853 CommandArgumentEntry arg1
;
854 CommandArgumentData file_arg_remote
;
856 // Define the first (and only) variant of this arg.
857 file_arg_remote
.arg_type
= eArgTypeFilename
;
858 file_arg_remote
.arg_repetition
= eArgRepeatPlain
;
859 // There is only one variant this argument could be; put it into the
861 arg1
.push_back(file_arg_remote
);
863 // Push the data for the first argument into the m_arguments vector.
864 m_arguments
.push_back(arg1
);
867 ~CommandObjectPlatformGetSize() override
= default;
869 bool DoExecute(Args
&args
, CommandReturnObject
&result
) override
{
870 // If the number of arguments is incorrect, issue an error message.
871 if (args
.GetArgumentCount() != 1) {
872 result
.GetErrorStream().Printf("error: required argument missing; "
873 "specify the source file path as the only "
875 result
.SetStatus(eReturnStatusFailed
);
879 PlatformSP
platform_sp(
880 GetDebugger().GetPlatformList().GetSelectedPlatform());
882 std::string
remote_file_path(args
.GetArgumentAtIndex(0));
883 user_id_t size
= platform_sp
->GetFileSize(FileSpec(remote_file_path
));
884 if (size
!= UINT64_MAX
) {
885 result
.AppendMessageWithFormat("File size of %s (remote): %" PRIu64
887 remote_file_path
.c_str(), size
);
888 result
.SetStatus(eReturnStatusSuccessFinishResult
);
890 result
.AppendMessageWithFormat(
891 "Error getting file size of %s (remote)\n",
892 remote_file_path
.c_str());
893 result
.SetStatus(eReturnStatusFailed
);
896 result
.AppendError("no platform currently selected\n");
897 result
.SetStatus(eReturnStatusFailed
);
899 return result
.Succeeded();
903 // "platform put-file"
904 class CommandObjectPlatformPutFile
: public CommandObjectParsed
{
906 CommandObjectPlatformPutFile(CommandInterpreter
&interpreter
)
907 : CommandObjectParsed(
908 interpreter
, "platform put-file",
909 "Transfer a file from this system to the remote end.", nullptr, 0) {
912 ~CommandObjectPlatformPutFile() override
= default;
914 bool DoExecute(Args
&args
, CommandReturnObject
&result
) override
{
915 const char *src
= args
.GetArgumentAtIndex(0);
916 const char *dst
= args
.GetArgumentAtIndex(1);
918 FileSpec
src_fs(src
);
919 FileSystem::Instance().Resolve(src_fs
);
920 FileSpec
dst_fs(dst
? dst
: src_fs
.GetFilename().GetCString());
922 PlatformSP
platform_sp(
923 GetDebugger().GetPlatformList().GetSelectedPlatform());
925 Status
error(platform_sp
->PutFile(src_fs
, dst_fs
));
926 if (error
.Success()) {
927 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
929 result
.AppendError(error
.AsCString());
930 result
.SetStatus(eReturnStatusFailed
);
933 result
.AppendError("no platform currently selected\n");
934 result
.SetStatus(eReturnStatusFailed
);
936 return result
.Succeeded();
940 // "platform process launch"
941 class CommandObjectPlatformProcessLaunch
: public CommandObjectParsed
{
943 CommandObjectPlatformProcessLaunch(CommandInterpreter
&interpreter
)
944 : CommandObjectParsed(interpreter
, "platform process launch",
945 "Launch a new process on a remote platform.",
946 "platform process launch program",
947 eCommandRequiresTarget
| eCommandTryTargetAPILock
),
950 ~CommandObjectPlatformProcessLaunch() override
= default;
952 Options
*GetOptions() override
{ return &m_options
; }
955 bool DoExecute(Args
&args
, CommandReturnObject
&result
) override
{
956 Target
*target
= GetDebugger().GetSelectedTarget().get();
957 PlatformSP platform_sp
;
959 platform_sp
= target
->GetPlatform();
962 platform_sp
= GetDebugger().GetPlatformList().GetSelectedPlatform();
967 const size_t argc
= args
.GetArgumentCount();
968 Target
*target
= m_exe_ctx
.GetTargetPtr();
969 Module
*exe_module
= target
->GetExecutableModulePointer();
971 m_options
.launch_info
.GetExecutableFile() = exe_module
->GetFileSpec();
972 llvm::SmallString
<128> exe_path
;
973 m_options
.launch_info
.GetExecutableFile().GetPath(exe_path
);
974 if (!exe_path
.empty())
975 m_options
.launch_info
.GetArguments().AppendArgument(exe_path
);
976 m_options
.launch_info
.GetArchitecture() = exe_module
->GetArchitecture();
980 if (m_options
.launch_info
.GetExecutableFile()) {
981 // We already have an executable file, so we will use this and all
982 // arguments to this function are extra arguments
983 m_options
.launch_info
.GetArguments().AppendArguments(args
);
985 // We don't have any file yet, so the first argument is our
986 // executable, and the rest are program arguments
987 const bool first_arg_is_executable
= true;
988 m_options
.launch_info
.SetArguments(args
, first_arg_is_executable
);
992 if (m_options
.launch_info
.GetExecutableFile()) {
993 Debugger
&debugger
= GetDebugger();
996 target
->GetRunArguments(m_options
.launch_info
.GetArguments());
998 ProcessSP
process_sp(platform_sp
->DebugProcess(
999 m_options
.launch_info
, debugger
, target
, error
));
1000 if (process_sp
&& process_sp
->IsAlive()) {
1001 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
1005 if (error
.Success())
1006 result
.AppendError("process launch failed");
1008 result
.AppendError(error
.AsCString());
1009 result
.SetStatus(eReturnStatusFailed
);
1011 result
.AppendError("'platform process launch' uses the current target "
1012 "file and arguments, or the executable and its "
1013 "arguments can be specified in this command");
1014 result
.SetStatus(eReturnStatusFailed
);
1018 result
.AppendError("no platform is selected\n");
1020 return result
.Succeeded();
1024 ProcessLaunchCommandOptions m_options
;
1027 // "platform process list"
1029 static PosixPlatformCommandOptionValidator posix_validator
;
1030 #define LLDB_OPTIONS_platform_process_list
1031 #include "CommandOptions.inc"
1033 class CommandObjectPlatformProcessList
: public CommandObjectParsed
{
1035 CommandObjectPlatformProcessList(CommandInterpreter
&interpreter
)
1036 : CommandObjectParsed(interpreter
, "platform process list",
1037 "List processes on a remote platform by name, pid, "
1038 "or many other matching attributes.",
1039 "platform process list", 0),
1042 ~CommandObjectPlatformProcessList() override
= default;
1044 Options
*GetOptions() override
{ return &m_options
; }
1047 bool DoExecute(Args
&args
, CommandReturnObject
&result
) override
{
1048 Target
*target
= GetDebugger().GetSelectedTarget().get();
1049 PlatformSP platform_sp
;
1051 platform_sp
= target
->GetPlatform();
1054 platform_sp
= GetDebugger().GetPlatformList().GetSelectedPlatform();
1059 if (args
.GetArgumentCount() == 0) {
1061 Stream
&ostrm
= result
.GetOutputStream();
1064 m_options
.match_info
.GetProcessInfo().GetProcessID();
1065 if (pid
!= LLDB_INVALID_PROCESS_ID
) {
1066 ProcessInstanceInfo proc_info
;
1067 if (platform_sp
->GetProcessInfo(pid
, proc_info
)) {
1068 ProcessInstanceInfo::DumpTableHeader(ostrm
, m_options
.show_args
,
1070 proc_info
.DumpAsTableRow(ostrm
, platform_sp
->GetUserIDResolver(),
1071 m_options
.show_args
, m_options
.verbose
);
1072 result
.SetStatus(eReturnStatusSuccessFinishResult
);
1074 result
.AppendErrorWithFormat(
1075 "no process found with pid = %" PRIu64
"\n", pid
);
1076 result
.SetStatus(eReturnStatusFailed
);
1079 ProcessInstanceInfoList proc_infos
;
1080 const uint32_t matches
=
1081 platform_sp
->FindProcesses(m_options
.match_info
, proc_infos
);
1082 const char *match_desc
= nullptr;
1083 const char *match_name
=
1084 m_options
.match_info
.GetProcessInfo().GetName();
1085 if (match_name
&& match_name
[0]) {
1086 switch (m_options
.match_info
.GetNameMatchType()) {
1087 case NameMatch::Ignore
:
1089 case NameMatch::Equals
:
1090 match_desc
= "matched";
1092 case NameMatch::Contains
:
1093 match_desc
= "contained";
1095 case NameMatch::StartsWith
:
1096 match_desc
= "started with";
1098 case NameMatch::EndsWith
:
1099 match_desc
= "ended with";
1101 case NameMatch::RegularExpression
:
1102 match_desc
= "matched the regular expression";
1109 result
.AppendErrorWithFormat(
1110 "no processes were found that %s \"%s\" on the \"%s\" "
1112 match_desc
, match_name
,
1113 platform_sp
->GetPluginName().GetCString());
1115 result
.AppendErrorWithFormat(
1116 "no processes were found on the \"%s\" platform\n",
1117 platform_sp
->GetPluginName().GetCString());
1118 result
.SetStatus(eReturnStatusFailed
);
1120 result
.AppendMessageWithFormat(
1121 "%u matching process%s found on \"%s\"", matches
,
1122 matches
> 1 ? "es were" : " was",
1123 platform_sp
->GetName().GetCString());
1125 result
.AppendMessageWithFormat(" whose name %s \"%s\"",
1126 match_desc
, match_name
);
1127 result
.AppendMessageWithFormat("\n");
1128 ProcessInstanceInfo::DumpTableHeader(ostrm
, m_options
.show_args
,
1130 for (uint32_t i
= 0; i
< matches
; ++i
) {
1131 proc_infos
.GetProcessInfoAtIndex(i
).DumpAsTableRow(
1132 ostrm
, platform_sp
->GetUserIDResolver(),
1133 m_options
.show_args
, m_options
.verbose
);
1139 result
.AppendError("invalid args: process list takes only options\n");
1140 result
.SetStatus(eReturnStatusFailed
);
1143 result
.AppendError("no platform is selected\n");
1144 result
.SetStatus(eReturnStatusFailed
);
1146 return result
.Succeeded();
1149 class CommandOptions
: public Options
{
1152 : Options(), match_info(), show_args(false), verbose(false) {}
1154 ~CommandOptions() override
= default;
1156 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
1157 ExecutionContext
*execution_context
) override
{
1159 const int short_option
= m_getopt_table
[option_idx
].val
;
1160 bool success
= false;
1162 uint32_t id
= LLDB_INVALID_PROCESS_ID
;
1163 success
= !option_arg
.getAsInteger(0, id
);
1164 switch (short_option
) {
1166 match_info
.GetProcessInfo().SetProcessID(id
);
1168 error
.SetErrorStringWithFormat("invalid process ID string: '%s'",
1169 option_arg
.str().c_str());
1173 match_info
.GetProcessInfo().SetParentProcessID(id
);
1175 error
.SetErrorStringWithFormat(
1176 "invalid parent process ID string: '%s'",
1177 option_arg
.str().c_str());
1181 match_info
.GetProcessInfo().SetUserID(success
? id
: UINT32_MAX
);
1183 error
.SetErrorStringWithFormat("invalid user ID string: '%s'",
1184 option_arg
.str().c_str());
1188 match_info
.GetProcessInfo().SetEffectiveUserID(success
? id
1191 error
.SetErrorStringWithFormat(
1192 "invalid effective user ID string: '%s'",
1193 option_arg
.str().c_str());
1197 match_info
.GetProcessInfo().SetGroupID(success
? id
: UINT32_MAX
);
1199 error
.SetErrorStringWithFormat("invalid group ID string: '%s'",
1200 option_arg
.str().c_str());
1204 match_info
.GetProcessInfo().SetEffectiveGroupID(success
? id
1207 error
.SetErrorStringWithFormat(
1208 "invalid effective group ID string: '%s'",
1209 option_arg
.str().c_str());
1213 TargetSP target_sp
=
1214 execution_context
? execution_context
->GetTargetSP() : TargetSP();
1215 DebuggerSP debugger_sp
=
1216 target_sp
? target_sp
->GetDebugger().shared_from_this()
1218 PlatformSP platform_sp
=
1219 debugger_sp
? debugger_sp
->GetPlatformList().GetSelectedPlatform()
1221 match_info
.GetProcessInfo().GetArchitecture() =
1222 Platform::GetAugmentedArchSpec(platform_sp
.get(), option_arg
);
1226 match_info
.GetProcessInfo().GetExecutableFile().SetFile(
1227 option_arg
, FileSpec::Style::native
);
1228 match_info
.SetNameMatchType(NameMatch::Equals
);
1232 match_info
.GetProcessInfo().GetExecutableFile().SetFile(
1233 option_arg
, FileSpec::Style::native
);
1234 match_info
.SetNameMatchType(NameMatch::EndsWith
);
1238 match_info
.GetProcessInfo().GetExecutableFile().SetFile(
1239 option_arg
, FileSpec::Style::native
);
1240 match_info
.SetNameMatchType(NameMatch::StartsWith
);
1244 match_info
.GetProcessInfo().GetExecutableFile().SetFile(
1245 option_arg
, FileSpec::Style::native
);
1246 match_info
.SetNameMatchType(NameMatch::Contains
);
1250 match_info
.GetProcessInfo().GetExecutableFile().SetFile(
1251 option_arg
, FileSpec::Style::native
);
1252 match_info
.SetNameMatchType(NameMatch::RegularExpression
);
1264 match_info
.SetMatchAllUsers(true);
1268 llvm_unreachable("Unimplemented option");
1274 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
1280 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
1281 return llvm::makeArrayRef(g_platform_process_list_options
);
1284 // Instance variables to hold the values for command options.
1286 ProcessInstanceInfoMatch match_info
;
1291 CommandOptions m_options
;
1294 // "platform process info"
1295 class CommandObjectPlatformProcessInfo
: public CommandObjectParsed
{
1297 CommandObjectPlatformProcessInfo(CommandInterpreter
&interpreter
)
1298 : CommandObjectParsed(
1299 interpreter
, "platform process info",
1300 "Get detailed information for one or more process by process ID.",
1301 "platform process info <pid> [<pid> <pid> ...]", 0) {
1302 CommandArgumentEntry arg
;
1303 CommandArgumentData pid_args
;
1305 // Define the first (and only) variant of this arg.
1306 pid_args
.arg_type
= eArgTypePid
;
1307 pid_args
.arg_repetition
= eArgRepeatStar
;
1309 // There is only one variant this argument could be; put it into the
1311 arg
.push_back(pid_args
);
1313 // Push the data for the first argument into the m_arguments vector.
1314 m_arguments
.push_back(arg
);
1317 ~CommandObjectPlatformProcessInfo() override
= default;
1320 bool DoExecute(Args
&args
, CommandReturnObject
&result
) override
{
1321 Target
*target
= GetDebugger().GetSelectedTarget().get();
1322 PlatformSP platform_sp
;
1324 platform_sp
= target
->GetPlatform();
1327 platform_sp
= GetDebugger().GetPlatformList().GetSelectedPlatform();
1331 const size_t argc
= args
.GetArgumentCount();
1335 if (platform_sp
->IsConnected()) {
1336 Stream
&ostrm
= result
.GetOutputStream();
1337 for (auto &entry
: args
.entries()) {
1339 if (entry
.ref().getAsInteger(0, pid
)) {
1340 result
.AppendErrorWithFormat("invalid process ID argument '%s'",
1341 entry
.ref().str().c_str());
1342 result
.SetStatus(eReturnStatusFailed
);
1345 ProcessInstanceInfo proc_info
;
1346 if (platform_sp
->GetProcessInfo(pid
, proc_info
)) {
1347 ostrm
.Printf("Process information for process %" PRIu64
":\n",
1349 proc_info
.Dump(ostrm
, platform_sp
->GetUserIDResolver());
1351 ostrm
.Printf("error: no process information is available for "
1352 "process %" PRIu64
"\n",
1360 result
.AppendErrorWithFormat(
1361 "not connected to '%s'",
1362 platform_sp
->GetPluginName().GetCString());
1363 result
.SetStatus(eReturnStatusFailed
);
1367 result
.AppendError("one or more process id(s) must be specified");
1368 result
.SetStatus(eReturnStatusFailed
);
1371 result
.AppendError("no platform is currently selected");
1372 result
.SetStatus(eReturnStatusFailed
);
1374 return result
.Succeeded();
1378 #define LLDB_OPTIONS_platform_process_attach
1379 #include "CommandOptions.inc"
1381 class CommandObjectPlatformProcessAttach
: public CommandObjectParsed
{
1383 class CommandOptions
: public Options
{
1385 CommandOptions() : Options() {
1386 // Keep default values of all options in one place: OptionParsingStarting
1388 OptionParsingStarting(nullptr);
1391 ~CommandOptions() override
= default;
1393 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
1394 ExecutionContext
*execution_context
) override
{
1396 char short_option
= (char)m_getopt_table
[option_idx
].val
;
1397 switch (short_option
) {
1399 lldb::pid_t pid
= LLDB_INVALID_PROCESS_ID
;
1400 if (option_arg
.getAsInteger(0, pid
)) {
1401 error
.SetErrorStringWithFormat("invalid process ID '%s'",
1402 option_arg
.str().c_str());
1404 attach_info
.SetProcessID(pid
);
1409 attach_info
.SetProcessPluginName(option_arg
);
1413 attach_info
.GetExecutableFile().SetFile(option_arg
,
1414 FileSpec::Style::native
);
1418 attach_info
.SetWaitForLaunch(true);
1422 llvm_unreachable("Unimplemented option");
1427 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{
1428 attach_info
.Clear();
1431 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
1432 return llvm::makeArrayRef(g_platform_process_attach_options
);
1435 void HandleOptionArgumentCompletion(
1436 CompletionRequest
&request
, OptionElementVector
&opt_element_vector
,
1437 int opt_element_index
, CommandInterpreter
&interpreter
) override
{
1438 int opt_arg_pos
= opt_element_vector
[opt_element_index
].opt_arg_pos
;
1439 int opt_defs_index
= opt_element_vector
[opt_element_index
].opt_defs_index
;
1441 // We are only completing the name option for now...
1443 // Are we in the name?
1444 if (GetDefinitions()[opt_defs_index
].short_option
!= 'n')
1447 // Look to see if there is a -P argument provided, and if so use that
1448 // plugin, otherwise use the default plugin.
1450 const char *partial_name
= nullptr;
1451 partial_name
= request
.GetParsedLine().GetArgumentAtIndex(opt_arg_pos
);
1453 PlatformSP
platform_sp(interpreter
.GetPlatform(true));
1457 ProcessInstanceInfoList process_infos
;
1458 ProcessInstanceInfoMatch match_info
;
1460 match_info
.GetProcessInfo().GetExecutableFile().SetFile(
1461 partial_name
, FileSpec::Style::native
);
1462 match_info
.SetNameMatchType(NameMatch::StartsWith
);
1464 platform_sp
->FindProcesses(match_info
, process_infos
);
1465 const uint32_t num_matches
= process_infos
.GetSize();
1466 if (num_matches
== 0)
1469 for (uint32_t i
= 0; i
< num_matches
; ++i
) {
1470 request
.AddCompletion(process_infos
.GetProcessNameAtIndex(i
));
1475 // Options table: Required for subclasses of Options.
1477 static OptionDefinition g_option_table
[];
1479 // Instance variables to hold the values for command options.
1481 ProcessAttachInfo attach_info
;
1484 CommandObjectPlatformProcessAttach(CommandInterpreter
&interpreter
)
1485 : CommandObjectParsed(interpreter
, "platform process attach",
1486 "Attach to a process.",
1487 "platform process attach <cmd-options>"),
1490 ~CommandObjectPlatformProcessAttach() override
= default;
1492 bool DoExecute(Args
&command
, CommandReturnObject
&result
) override
{
1493 PlatformSP
platform_sp(
1494 GetDebugger().GetPlatformList().GetSelectedPlatform());
1497 ProcessSP remote_process_sp
= platform_sp
->Attach(
1498 m_options
.attach_info
, GetDebugger(), nullptr, err
);
1500 result
.AppendError(err
.AsCString());
1501 result
.SetStatus(eReturnStatusFailed
);
1502 } else if (!remote_process_sp
) {
1503 result
.AppendError("could not attach: unknown reason");
1504 result
.SetStatus(eReturnStatusFailed
);
1506 result
.SetStatus(eReturnStatusSuccessFinishResult
);
1508 result
.AppendError("no platform is currently selected");
1509 result
.SetStatus(eReturnStatusFailed
);
1511 return result
.Succeeded();
1514 Options
*GetOptions() override
{ return &m_options
; }
1517 CommandOptions m_options
;
1520 class CommandObjectPlatformProcess
: public CommandObjectMultiword
{
1522 // Constructors and Destructors
1523 CommandObjectPlatformProcess(CommandInterpreter
&interpreter
)
1524 : CommandObjectMultiword(interpreter
, "platform process",
1525 "Commands to query, launch and attach to "
1526 "processes on the current platform.",
1527 "platform process [attach|launch|list] ...") {
1530 CommandObjectSP(new CommandObjectPlatformProcessAttach(interpreter
)));
1533 CommandObjectSP(new CommandObjectPlatformProcessLaunch(interpreter
)));
1534 LoadSubCommand("info", CommandObjectSP(new CommandObjectPlatformProcessInfo(
1536 LoadSubCommand("list", CommandObjectSP(new CommandObjectPlatformProcessList(
1540 ~CommandObjectPlatformProcess() override
= default;
1543 // For CommandObjectPlatform only
1544 DISALLOW_COPY_AND_ASSIGN(CommandObjectPlatformProcess
);
1548 #define LLDB_OPTIONS_platform_shell
1549 #include "CommandOptions.inc"
1551 class CommandObjectPlatformShell
: public CommandObjectRaw
{
1553 class CommandOptions
: public Options
{
1555 CommandOptions() : Options() {}
1557 ~CommandOptions() override
= default;
1559 llvm::ArrayRef
<OptionDefinition
> GetDefinitions() override
{
1560 return llvm::makeArrayRef(g_platform_shell_options
);
1563 Status
SetOptionValue(uint32_t option_idx
, llvm::StringRef option_arg
,
1564 ExecutionContext
*execution_context
) override
{
1567 const char short_option
= (char)GetDefinitions()[option_idx
].short_option
;
1569 switch (short_option
) {
1571 uint32_t timeout_sec
;
1572 if (option_arg
.getAsInteger(10, timeout_sec
))
1573 error
.SetErrorStringWithFormat(
1574 "could not convert \"%s\" to a numeric value.",
1575 option_arg
.str().c_str());
1577 timeout
= std::chrono::seconds(timeout_sec
);
1580 llvm_unreachable("Unimplemented option");
1586 void OptionParsingStarting(ExecutionContext
*execution_context
) override
{}
1588 Timeout
<std::micro
> timeout
= std::chrono::seconds(10);
1591 CommandObjectPlatformShell(CommandInterpreter
&interpreter
)
1592 : CommandObjectRaw(interpreter
, "platform shell",
1593 "Run a shell command on the current platform.",
1594 "platform shell <shell-command>", 0),
1597 ~CommandObjectPlatformShell() override
= default;
1599 Options
*GetOptions() override
{ return &m_options
; }
1601 bool DoExecute(llvm::StringRef raw_command_line
,
1602 CommandReturnObject
&result
) override
{
1603 ExecutionContext exe_ctx
= GetCommandInterpreter().GetExecutionContext();
1604 m_options
.NotifyOptionParsingStarting(&exe_ctx
);
1606 // Print out an usage syntax on an empty command line.
1607 if (raw_command_line
.empty()) {
1608 result
.GetOutputStream().Printf("%s\n", this->GetSyntax().str().c_str());
1612 OptionsWithRaw
args(raw_command_line
);
1613 const char *expr
= args
.GetRawPart().c_str();
1616 if (!ParseOptions(args
.GetArgs(), result
))
1619 PlatformSP
platform_sp(
1620 GetDebugger().GetPlatformList().GetSelectedPlatform());
1623 FileSpec working_dir
{};
1627 error
= (platform_sp
->RunShellCommand(expr
, working_dir
, &status
, &signo
,
1628 &output
, m_options
.timeout
));
1629 if (!output
.empty())
1630 result
.GetOutputStream().PutCString(output
);
1633 const char *signo_cstr
= Host::GetSignalAsCString(signo
);
1635 result
.GetOutputStream().Printf(
1636 "error: command returned with status %i and signal %s\n",
1637 status
, signo_cstr
);
1639 result
.GetOutputStream().Printf(
1640 "error: command returned with status %i and signal %i\n",
1643 result
.GetOutputStream().Printf(
1644 "error: command returned with status %i\n", status
);
1647 result
.GetOutputStream().Printf(
1648 "error: cannot run remote shell commands without a platform\n");
1649 error
.SetErrorString(
1650 "error: cannot run remote shell commands without a platform");
1654 result
.AppendError(error
.AsCString());
1655 result
.SetStatus(eReturnStatusFailed
);
1657 result
.SetStatus(eReturnStatusSuccessFinishResult
);
1662 CommandOptions m_options
;
1665 // "platform install" - install a target to a remote end
1666 class CommandObjectPlatformInstall
: public CommandObjectParsed
{
1668 CommandObjectPlatformInstall(CommandInterpreter
&interpreter
)
1669 : CommandObjectParsed(
1670 interpreter
, "platform target-install",
1671 "Install a target (bundle or executable file) to the remote end.",
1672 "platform target-install <local-thing> <remote-sandbox>", 0) {}
1674 ~CommandObjectPlatformInstall() override
= default;
1676 bool DoExecute(Args
&args
, CommandReturnObject
&result
) override
{
1677 if (args
.GetArgumentCount() != 2) {
1678 result
.AppendError("platform target-install takes two arguments");
1679 result
.SetStatus(eReturnStatusFailed
);
1682 // TODO: move the bulk of this code over to the platform itself
1683 FileSpec
src(args
.GetArgumentAtIndex(0));
1684 FileSystem::Instance().Resolve(src
);
1685 FileSpec
dst(args
.GetArgumentAtIndex(1));
1686 if (!FileSystem::Instance().Exists(src
)) {
1687 result
.AppendError("source location does not exist or is not accessible");
1688 result
.SetStatus(eReturnStatusFailed
);
1691 PlatformSP
platform_sp(
1692 GetDebugger().GetPlatformList().GetSelectedPlatform());
1694 result
.AppendError("no platform currently selected");
1695 result
.SetStatus(eReturnStatusFailed
);
1699 Status error
= platform_sp
->Install(src
, dst
);
1700 if (error
.Success()) {
1701 result
.SetStatus(eReturnStatusSuccessFinishNoResult
);
1703 result
.AppendErrorWithFormat("install failed: %s", error
.AsCString());
1704 result
.SetStatus(eReturnStatusFailed
);
1706 return result
.Succeeded();
1710 CommandObjectPlatform::CommandObjectPlatform(CommandInterpreter
&interpreter
)
1711 : CommandObjectMultiword(
1712 interpreter
, "platform", "Commands to manage and create platforms.",
1713 "platform [connect|disconnect|info|list|status|select] ...") {
1714 LoadSubCommand("select",
1715 CommandObjectSP(new CommandObjectPlatformSelect(interpreter
)));
1716 LoadSubCommand("list",
1717 CommandObjectSP(new CommandObjectPlatformList(interpreter
)));
1718 LoadSubCommand("status",
1719 CommandObjectSP(new CommandObjectPlatformStatus(interpreter
)));
1720 LoadSubCommand("connect", CommandObjectSP(
1721 new CommandObjectPlatformConnect(interpreter
)));
1724 CommandObjectSP(new CommandObjectPlatformDisconnect(interpreter
)));
1725 LoadSubCommand("settings", CommandObjectSP(new CommandObjectPlatformSettings(
1727 LoadSubCommand("mkdir",
1728 CommandObjectSP(new CommandObjectPlatformMkDir(interpreter
)));
1729 LoadSubCommand("file",
1730 CommandObjectSP(new CommandObjectPlatformFile(interpreter
)));
1731 LoadSubCommand("get-file", CommandObjectSP(new CommandObjectPlatformGetFile(
1733 LoadSubCommand("get-size", CommandObjectSP(new CommandObjectPlatformGetSize(
1735 LoadSubCommand("put-file", CommandObjectSP(new CommandObjectPlatformPutFile(
1737 LoadSubCommand("process", CommandObjectSP(
1738 new CommandObjectPlatformProcess(interpreter
)));
1739 LoadSubCommand("shell",
1740 CommandObjectSP(new CommandObjectPlatformShell(interpreter
)));
1743 CommandObjectSP(new CommandObjectPlatformInstall(interpreter
)));
1746 CommandObjectPlatform::~CommandObjectPlatform() = default;