xref: /src/contrib/llvm-project/lldb/source/Commands/CommandObjectPlatform.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1cfca06d7SDimitry Andric //===-- CommandObjectPlatform.cpp -----------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste 
9f3fbd1c0SDimitry Andric #include "CommandObjectPlatform.h"
107fa27ce4SDimitry Andric #include "CommandOptionsProcessAttach.h"
11b60736ecSDimitry Andric #include "CommandOptionsProcessLaunch.h"
12f034231aSEd Maste #include "lldb/Core/Debugger.h"
13f034231aSEd Maste #include "lldb/Core/Module.h"
14f034231aSEd Maste #include "lldb/Core/PluginManager.h"
1574a628f7SDimitry Andric #include "lldb/Host/OptionParser.h"
16f034231aSEd Maste #include "lldb/Interpreter/CommandInterpreter.h"
174b4fe385SDimitry Andric #include "lldb/Interpreter/CommandOptionArgumentTable.h"
180cac4ca3SEd Maste #include "lldb/Interpreter/CommandOptionValidators.h"
19f034231aSEd Maste #include "lldb/Interpreter/CommandReturnObject.h"
2086758c71SEd Maste #include "lldb/Interpreter/OptionGroupFile.h"
21f034231aSEd Maste #include "lldb/Interpreter/OptionGroupPlatform.h"
227fa27ce4SDimitry Andric #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"
23f034231aSEd Maste #include "lldb/Target/ExecutionContext.h"
24f034231aSEd Maste #include "lldb/Target/Platform.h"
25f034231aSEd Maste #include "lldb/Target/Process.h"
26f73363f1SDimitry Andric #include "lldb/Utility/Args.h"
277fa27ce4SDimitry Andric #include "lldb/Utility/ScriptedMetadata.h"
287fa27ce4SDimitry Andric #include "lldb/Utility/State.h"
29f034231aSEd Maste 
3014f1b3e8SDimitry Andric #include "llvm/ADT/SmallString.h"
3114f1b3e8SDimitry Andric 
32f034231aSEd Maste using namespace lldb;
33f034231aSEd Maste using namespace lldb_private;
34f034231aSEd Maste 
3514f1b3e8SDimitry Andric static mode_t ParsePermissionString(const char *) = delete;
3614f1b3e8SDimitry Andric 
ParsePermissionString(llvm::StringRef permissions)3714f1b3e8SDimitry Andric static mode_t ParsePermissionString(llvm::StringRef permissions) {
3814f1b3e8SDimitry Andric   if (permissions.size() != 9)
39f21a844fSEd Maste     return (mode_t)(-1);
4014f1b3e8SDimitry Andric   bool user_r, user_w, user_x, group_r, group_w, group_x, world_r, world_w,
4114f1b3e8SDimitry Andric       world_x;
42f21a844fSEd Maste 
43f21a844fSEd Maste   user_r = (permissions[0] == 'r');
44f21a844fSEd Maste   user_w = (permissions[1] == 'w');
45f21a844fSEd Maste   user_x = (permissions[2] == 'x');
46f21a844fSEd Maste 
47f21a844fSEd Maste   group_r = (permissions[3] == 'r');
48f21a844fSEd Maste   group_w = (permissions[4] == 'w');
49f21a844fSEd Maste   group_x = (permissions[5] == 'x');
50f21a844fSEd Maste 
51f21a844fSEd Maste   world_r = (permissions[6] == 'r');
52f21a844fSEd Maste   world_w = (permissions[7] == 'w');
53f21a844fSEd Maste   world_x = (permissions[8] == 'x');
54f21a844fSEd Maste 
55f21a844fSEd Maste   mode_t user, group, world;
56f21a844fSEd Maste   user = (user_r ? 4 : 0) | (user_w ? 2 : 0) | (user_x ? 1 : 0);
57f21a844fSEd Maste   group = (group_r ? 4 : 0) | (group_w ? 2 : 0) | (group_x ? 1 : 0);
58f21a844fSEd Maste   world = (world_r ? 4 : 0) | (world_w ? 2 : 0) | (world_x ? 1 : 0);
59f21a844fSEd Maste 
60f21a844fSEd Maste   return user | group | world;
61f21a844fSEd Maste }
62f21a844fSEd Maste 
63ead24645SDimitry Andric #define LLDB_OPTIONS_permissions
64ead24645SDimitry Andric #include "CommandOptions.inc"
65f21a844fSEd Maste 
6614f1b3e8SDimitry Andric class OptionPermissions : public OptionGroup {
67f21a844fSEd Maste public:
68344a3780SDimitry Andric   OptionPermissions() = default;
69f21a844fSEd Maste 
70f3fbd1c0SDimitry Andric   ~OptionPermissions() override = default;
71f21a844fSEd Maste 
72b76161e4SDimitry Andric   lldb_private::Status
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)7314f1b3e8SDimitry Andric   SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
7414f1b3e8SDimitry Andric                  ExecutionContext *execution_context) override {
75b76161e4SDimitry Andric     Status error;
76f21a844fSEd Maste     char short_option = (char)GetDefinitions()[option_idx].short_option;
7714f1b3e8SDimitry Andric     switch (short_option) {
7814f1b3e8SDimitry Andric     case 'v': {
7914f1b3e8SDimitry Andric       if (option_arg.getAsInteger(8, m_permissions)) {
8014f1b3e8SDimitry Andric         m_permissions = 0777;
8114f1b3e8SDimitry Andric         error.SetErrorStringWithFormat("invalid value for permissions: %s",
8214f1b3e8SDimitry Andric                                        option_arg.str().c_str());
83f21a844fSEd Maste       }
8414f1b3e8SDimitry Andric 
8514f1b3e8SDimitry Andric     } break;
8614f1b3e8SDimitry Andric     case 's': {
87f21a844fSEd Maste       mode_t perms = ParsePermissionString(option_arg);
88f21a844fSEd Maste       if (perms == (mode_t)-1)
8914f1b3e8SDimitry Andric         error.SetErrorStringWithFormat("invalid value for permissions: %s",
9014f1b3e8SDimitry Andric                                        option_arg.str().c_str());
91f21a844fSEd Maste       else
92f21a844fSEd Maste         m_permissions = perms;
9314f1b3e8SDimitry Andric     } break;
94f21a844fSEd Maste     case 'r':
9586758c71SEd Maste       m_permissions |= lldb::eFilePermissionsUserRead;
96f21a844fSEd Maste       break;
97f21a844fSEd Maste     case 'w':
9886758c71SEd Maste       m_permissions |= lldb::eFilePermissionsUserWrite;
99f21a844fSEd Maste       break;
100f21a844fSEd Maste     case 'x':
10186758c71SEd Maste       m_permissions |= lldb::eFilePermissionsUserExecute;
102f21a844fSEd Maste       break;
103f21a844fSEd Maste     case 'R':
10486758c71SEd Maste       m_permissions |= lldb::eFilePermissionsGroupRead;
105f21a844fSEd Maste       break;
106f21a844fSEd Maste     case 'W':
10786758c71SEd Maste       m_permissions |= lldb::eFilePermissionsGroupWrite;
108f21a844fSEd Maste       break;
109f21a844fSEd Maste     case 'X':
11086758c71SEd Maste       m_permissions |= lldb::eFilePermissionsGroupExecute;
111f21a844fSEd Maste       break;
112f21a844fSEd Maste     case 'd':
11386758c71SEd Maste       m_permissions |= lldb::eFilePermissionsWorldRead;
114f21a844fSEd Maste       break;
115f21a844fSEd Maste     case 't':
11686758c71SEd Maste       m_permissions |= lldb::eFilePermissionsWorldWrite;
117f21a844fSEd Maste       break;
118f21a844fSEd Maste     case 'e':
11986758c71SEd Maste       m_permissions |= lldb::eFilePermissionsWorldExecute;
120f21a844fSEd Maste       break;
121f21a844fSEd Maste     default:
122ead24645SDimitry Andric       llvm_unreachable("Unimplemented option");
123f21a844fSEd Maste     }
124f21a844fSEd Maste 
125f21a844fSEd Maste     return error;
126f21a844fSEd Maste   }
127f21a844fSEd Maste 
OptionParsingStarting(ExecutionContext * execution_context)12814f1b3e8SDimitry Andric   void OptionParsingStarting(ExecutionContext *execution_context) override {
129f21a844fSEd Maste     m_permissions = 0;
130f21a844fSEd Maste   }
131f21a844fSEd Maste 
GetDefinitions()13214f1b3e8SDimitry Andric   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
133e3b55780SDimitry Andric     return llvm::ArrayRef(g_permissions_options);
134f21a844fSEd Maste   }
135f21a844fSEd Maste 
136f21a844fSEd Maste   // Instance variables to hold the values for command options.
137f21a844fSEd Maste 
138f21a844fSEd Maste   uint32_t m_permissions;
139f3fbd1c0SDimitry Andric 
140f21a844fSEd Maste private:
141cfca06d7SDimitry Andric   OptionPermissions(const OptionPermissions &) = delete;
142cfca06d7SDimitry Andric   const OptionPermissions &operator=(const OptionPermissions &) = delete;
143f21a844fSEd Maste };
144f034231aSEd Maste 
145f034231aSEd Maste // "platform select <platform-name>"
14614f1b3e8SDimitry Andric class CommandObjectPlatformSelect : public CommandObjectParsed {
147f034231aSEd Maste public:
CommandObjectPlatformSelect(CommandInterpreter & interpreter)14814f1b3e8SDimitry Andric   CommandObjectPlatformSelect(CommandInterpreter &interpreter)
14914f1b3e8SDimitry Andric       : CommandObjectParsed(interpreter, "platform select",
15014f1b3e8SDimitry Andric                             "Create a platform if needed and select it as the "
15114f1b3e8SDimitry Andric                             "current platform.",
15214f1b3e8SDimitry Andric                             "platform select <platform-name>", 0),
15314f1b3e8SDimitry Andric         m_platform_options(
15414f1b3e8SDimitry Andric             false) // Don't include the "--platform" option by passing false
155f034231aSEd Maste   {
156f034231aSEd Maste     m_option_group.Append(&m_platform_options, LLDB_OPT_SET_ALL, 1);
157f034231aSEd Maste     m_option_group.Finalize();
158ac9a064cSDimitry Andric     AddSimpleArgumentList(eArgTypePlatform);
159f034231aSEd Maste   }
160f034231aSEd Maste 
161f3fbd1c0SDimitry Andric   ~CommandObjectPlatformSelect() override = default;
162f034231aSEd Maste 
HandleCompletion(CompletionRequest & request)163ead24645SDimitry Andric   void HandleCompletion(CompletionRequest &request) override {
1647fa27ce4SDimitry Andric     lldb_private::CommandCompletions::PlatformPluginNames(
1657fa27ce4SDimitry Andric         GetCommandInterpreter(), request, nullptr);
166f034231aSEd Maste   }
167f034231aSEd Maste 
GetOptions()16814f1b3e8SDimitry Andric   Options *GetOptions() override { return &m_option_group; }
169f034231aSEd Maste 
170f034231aSEd Maste protected:
DoExecute(Args & args,CommandReturnObject & result)171b1c73532SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
17214f1b3e8SDimitry Andric     if (args.GetArgumentCount() == 1) {
173f034231aSEd Maste       const char *platform_name = args.GetArgumentAtIndex(0);
17414f1b3e8SDimitry Andric       if (platform_name && platform_name[0]) {
175f034231aSEd Maste         const bool select = true;
176f034231aSEd Maste         m_platform_options.SetPlatformName(platform_name);
177b76161e4SDimitry Andric         Status error;
178f034231aSEd Maste         ArchSpec platform_arch;
17914f1b3e8SDimitry Andric         PlatformSP platform_sp(m_platform_options.CreatePlatformWithOptions(
18014f1b3e8SDimitry Andric             m_interpreter, ArchSpec(), select, error, platform_arch));
18114f1b3e8SDimitry Andric         if (platform_sp) {
1825f29bb8aSDimitry Andric           GetDebugger().GetPlatformList().SetSelectedPlatform(platform_sp);
18312bd4897SEd Maste 
184f034231aSEd Maste           platform_sp->GetStatus(result.GetOutputStream());
185f034231aSEd Maste           result.SetStatus(eReturnStatusSuccessFinishResult);
18614f1b3e8SDimitry Andric         } else {
187f034231aSEd Maste           result.AppendError(error.AsCString());
188f034231aSEd Maste         }
18914f1b3e8SDimitry Andric       } else {
190f034231aSEd Maste         result.AppendError("invalid platform name");
191f034231aSEd Maste       }
19214f1b3e8SDimitry Andric     } else {
19314f1b3e8SDimitry Andric       result.AppendError(
19414f1b3e8SDimitry Andric           "platform create takes a platform name as an argument\n");
195f034231aSEd Maste     }
196f034231aSEd Maste   }
197f034231aSEd Maste 
198f034231aSEd Maste   OptionGroupOptions m_option_group;
199f034231aSEd Maste   OptionGroupPlatform m_platform_options;
200f034231aSEd Maste };
201f034231aSEd Maste 
202f034231aSEd Maste // "platform list"
20314f1b3e8SDimitry Andric class CommandObjectPlatformList : public CommandObjectParsed {
204f034231aSEd Maste public:
CommandObjectPlatformList(CommandInterpreter & interpreter)20514f1b3e8SDimitry Andric   CommandObjectPlatformList(CommandInterpreter &interpreter)
20614f1b3e8SDimitry Andric       : CommandObjectParsed(interpreter, "platform list",
20714f1b3e8SDimitry Andric                             "List all platforms that are available.", nullptr,
20814f1b3e8SDimitry Andric                             0) {}
209f034231aSEd Maste 
210f3fbd1c0SDimitry Andric   ~CommandObjectPlatformList() override = default;
211f034231aSEd Maste 
212f034231aSEd Maste protected:
DoExecute(Args & args,CommandReturnObject & result)213b1c73532SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
214f034231aSEd Maste     Stream &ostrm = result.GetOutputStream();
215f034231aSEd Maste     ostrm.Printf("Available platforms:\n");
216f034231aSEd Maste 
217205afe67SEd Maste     PlatformSP host_platform_sp(Platform::GetHostPlatform());
218c0981da4SDimitry Andric     ostrm.Format("{0}: {1}\n", host_platform_sp->GetPluginName(),
219f034231aSEd Maste                  host_platform_sp->GetDescription());
220f034231aSEd Maste 
221f034231aSEd Maste     uint32_t idx;
2225f29bb8aSDimitry Andric     for (idx = 0; true; ++idx) {
223c0981da4SDimitry Andric       llvm::StringRef plugin_name =
22414f1b3e8SDimitry Andric           PluginManager::GetPlatformPluginNameAtIndex(idx);
225c0981da4SDimitry Andric       if (plugin_name.empty())
226f034231aSEd Maste         break;
227c0981da4SDimitry Andric       llvm::StringRef plugin_desc =
22814f1b3e8SDimitry Andric           PluginManager::GetPlatformPluginDescriptionAtIndex(idx);
229c0981da4SDimitry Andric       ostrm.Format("{0}: {1}\n", plugin_name, plugin_desc);
230f034231aSEd Maste     }
231f034231aSEd Maste 
23214f1b3e8SDimitry Andric     if (idx == 0) {
233f034231aSEd Maste       result.AppendError("no platforms are available\n");
23414f1b3e8SDimitry Andric     } else
235f034231aSEd Maste       result.SetStatus(eReturnStatusSuccessFinishResult);
236f034231aSEd Maste   }
237f034231aSEd Maste };
238f034231aSEd Maste 
239f034231aSEd Maste // "platform status"
24014f1b3e8SDimitry Andric class CommandObjectPlatformStatus : public CommandObjectParsed {
241f034231aSEd Maste public:
CommandObjectPlatformStatus(CommandInterpreter & interpreter)242f3fbd1c0SDimitry Andric   CommandObjectPlatformStatus(CommandInterpreter &interpreter)
24314f1b3e8SDimitry Andric       : CommandObjectParsed(interpreter, "platform status",
24414f1b3e8SDimitry Andric                             "Display status for the current platform.", nullptr,
24514f1b3e8SDimitry Andric                             0) {}
246f034231aSEd Maste 
247f3fbd1c0SDimitry Andric   ~CommandObjectPlatformStatus() override = default;
248f034231aSEd Maste 
249f034231aSEd Maste protected:
DoExecute(Args & args,CommandReturnObject & result)250b1c73532SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
251f034231aSEd Maste     Stream &ostrm = result.GetOutputStream();
252f034231aSEd Maste 
2535f29bb8aSDimitry Andric     Target *target = GetDebugger().GetSelectedTarget().get();
254f034231aSEd Maste     PlatformSP platform_sp;
25514f1b3e8SDimitry Andric     if (target) {
256f034231aSEd Maste       platform_sp = target->GetPlatform();
257f034231aSEd Maste     }
25814f1b3e8SDimitry Andric     if (!platform_sp) {
2595f29bb8aSDimitry Andric       platform_sp = GetDebugger().GetPlatformList().GetSelectedPlatform();
260f034231aSEd Maste     }
26114f1b3e8SDimitry Andric     if (platform_sp) {
262f034231aSEd Maste       platform_sp->GetStatus(ostrm);
263f034231aSEd Maste       result.SetStatus(eReturnStatusSuccessFinishResult);
26414f1b3e8SDimitry Andric     } else {
265ef5d0b5eSDimitry Andric       result.AppendError("no platform is currently selected\n");
266f034231aSEd Maste     }
267f034231aSEd Maste   }
268f034231aSEd Maste };
269f034231aSEd Maste 
270f034231aSEd Maste // "platform connect <connect-url>"
27114f1b3e8SDimitry Andric class CommandObjectPlatformConnect : public CommandObjectParsed {
272f034231aSEd Maste public:
CommandObjectPlatformConnect(CommandInterpreter & interpreter)273f3fbd1c0SDimitry Andric   CommandObjectPlatformConnect(CommandInterpreter &interpreter)
27414f1b3e8SDimitry Andric       : CommandObjectParsed(
27514f1b3e8SDimitry Andric             interpreter, "platform connect",
276f3fbd1c0SDimitry Andric             "Select the current platform by providing a connection URL.",
277145449b1SDimitry Andric             "platform connect <connect-url>", 0) {
278ac9a064cSDimitry Andric     AddSimpleArgumentList(eArgTypeConnectURL);
279145449b1SDimitry Andric   }
280f034231aSEd Maste 
281f3fbd1c0SDimitry Andric   ~CommandObjectPlatformConnect() override = default;
282f034231aSEd Maste 
283f034231aSEd Maste protected:
DoExecute(Args & args,CommandReturnObject & result)284b1c73532SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
285f034231aSEd Maste     Stream &ostrm = result.GetOutputStream();
286f034231aSEd Maste 
28714f1b3e8SDimitry Andric     PlatformSP platform_sp(
2885f29bb8aSDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
28914f1b3e8SDimitry Andric     if (platform_sp) {
290b76161e4SDimitry Andric       Status error(platform_sp->ConnectRemote(args));
29114f1b3e8SDimitry Andric       if (error.Success()) {
292f034231aSEd Maste         platform_sp->GetStatus(ostrm);
293f034231aSEd Maste         result.SetStatus(eReturnStatusSuccessFinishResult);
294e81d9d49SDimitry Andric 
2955f29bb8aSDimitry Andric         platform_sp->ConnectToWaitingProcesses(GetDebugger(), error);
29614f1b3e8SDimitry Andric         if (error.Fail()) {
297e81d9d49SDimitry Andric           result.AppendError(error.AsCString());
298e81d9d49SDimitry Andric         }
29914f1b3e8SDimitry Andric       } else {
300f034231aSEd Maste         result.AppendErrorWithFormat("%s\n", error.AsCString());
301f034231aSEd Maste       }
30214f1b3e8SDimitry Andric     } else {
303f21a844fSEd Maste       result.AppendError("no platform is currently selected\n");
304f034231aSEd Maste     }
305f034231aSEd Maste   }
306f21a844fSEd Maste 
GetOptions()30714f1b3e8SDimitry Andric   Options *GetOptions() override {
30814f1b3e8SDimitry Andric     PlatformSP platform_sp(
3095f29bb8aSDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
310f3fbd1c0SDimitry Andric     OptionGroupOptions *m_platform_options = nullptr;
31114f1b3e8SDimitry Andric     if (platform_sp) {
312f21a844fSEd Maste       m_platform_options = platform_sp->GetConnectionOptions(m_interpreter);
313f3fbd1c0SDimitry Andric       if (m_platform_options != nullptr && !m_platform_options->m_did_finalize)
314f21a844fSEd Maste         m_platform_options->Finalize();
315f21a844fSEd Maste     }
316f21a844fSEd Maste     return m_platform_options;
317f21a844fSEd Maste   }
318f034231aSEd Maste };
319f034231aSEd Maste 
320f034231aSEd Maste // "platform disconnect"
32114f1b3e8SDimitry Andric class CommandObjectPlatformDisconnect : public CommandObjectParsed {
322f034231aSEd Maste public:
CommandObjectPlatformDisconnect(CommandInterpreter & interpreter)323f3fbd1c0SDimitry Andric   CommandObjectPlatformDisconnect(CommandInterpreter &interpreter)
32414f1b3e8SDimitry Andric       : CommandObjectParsed(interpreter, "platform disconnect",
32514f1b3e8SDimitry Andric                             "Disconnect from the current platform.",
32614f1b3e8SDimitry Andric                             "platform disconnect", 0) {}
327f034231aSEd Maste 
328f3fbd1c0SDimitry Andric   ~CommandObjectPlatformDisconnect() override = default;
329f034231aSEd Maste 
330f034231aSEd Maste protected:
DoExecute(Args & args,CommandReturnObject & result)331b1c73532SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
33214f1b3e8SDimitry Andric     PlatformSP platform_sp(
3335f29bb8aSDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
33414f1b3e8SDimitry Andric     if (platform_sp) {
33514f1b3e8SDimitry Andric       if (args.GetArgumentCount() == 0) {
336b76161e4SDimitry Andric         Status error;
337f034231aSEd Maste 
33814f1b3e8SDimitry Andric         if (platform_sp->IsConnected()) {
339f73363f1SDimitry Andric           // Cache the instance name if there is one since we are about to
340f73363f1SDimitry Andric           // disconnect and the name might go with it.
341f034231aSEd Maste           const char *hostname_cstr = platform_sp->GetHostname();
342f034231aSEd Maste           std::string hostname;
343f034231aSEd Maste           if (hostname_cstr)
344f034231aSEd Maste             hostname.assign(hostname_cstr);
345f034231aSEd Maste 
346f034231aSEd Maste           error = platform_sp->DisconnectRemote();
34714f1b3e8SDimitry Andric           if (error.Success()) {
348f034231aSEd Maste             Stream &ostrm = result.GetOutputStream();
349f034231aSEd Maste             if (hostname.empty())
350c0981da4SDimitry Andric               ostrm.Format("Disconnected from \"{0}\"\n",
351c0981da4SDimitry Andric                            platform_sp->GetPluginName());
352f034231aSEd Maste             else
353f034231aSEd Maste               ostrm.Printf("Disconnected from \"%s\"\n", hostname.c_str());
354f034231aSEd Maste             result.SetStatus(eReturnStatusSuccessFinishResult);
35514f1b3e8SDimitry Andric           } else {
356f034231aSEd Maste             result.AppendErrorWithFormat("%s", error.AsCString());
357f034231aSEd Maste           }
35814f1b3e8SDimitry Andric         } else {
359f034231aSEd Maste           // Not connected...
360c0981da4SDimitry Andric           result.AppendErrorWithFormatv("not connected to '{0}'",
361c0981da4SDimitry Andric                                         platform_sp->GetPluginName());
362f034231aSEd Maste         }
36314f1b3e8SDimitry Andric       } else {
364f034231aSEd Maste         // Bad args
36514f1b3e8SDimitry Andric         result.AppendError(
36614f1b3e8SDimitry Andric             "\"platform disconnect\" doesn't take any arguments");
367f034231aSEd Maste       }
36814f1b3e8SDimitry Andric     } else {
369f034231aSEd Maste       result.AppendError("no platform is currently selected");
370f034231aSEd Maste     }
371f034231aSEd Maste   }
372f034231aSEd Maste };
373f21a844fSEd Maste 
37486758c71SEd Maste // "platform settings"
37514f1b3e8SDimitry Andric class CommandObjectPlatformSettings : public CommandObjectParsed {
37686758c71SEd Maste public:
CommandObjectPlatformSettings(CommandInterpreter & interpreter)37714f1b3e8SDimitry Andric   CommandObjectPlatformSettings(CommandInterpreter &interpreter)
37814f1b3e8SDimitry Andric       : CommandObjectParsed(interpreter, "platform settings",
379e3b55780SDimitry Andric                             "Set settings for the current target's platform.",
38014f1b3e8SDimitry Andric                             "platform settings", 0),
381b60736ecSDimitry Andric         m_option_working_dir(LLDB_OPT_SET_1, false, "working-dir", 'w',
3827fa27ce4SDimitry Andric                              lldb::eRemoteDiskDirectoryCompletion, eArgTypePath,
38314f1b3e8SDimitry Andric                              "The working directory for the platform.") {
38486758c71SEd Maste     m_options.Append(&m_option_working_dir, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
38586758c71SEd Maste   }
38686758c71SEd Maste 
387f3fbd1c0SDimitry Andric   ~CommandObjectPlatformSettings() override = default;
38886758c71SEd Maste 
38986758c71SEd Maste protected:
DoExecute(Args & args,CommandReturnObject & result)390b1c73532SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
39114f1b3e8SDimitry Andric     PlatformSP platform_sp(
3925f29bb8aSDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
39314f1b3e8SDimitry Andric     if (platform_sp) {
39486758c71SEd Maste       if (m_option_working_dir.GetOptionValue().OptionWasSet())
39514f1b3e8SDimitry Andric         platform_sp->SetWorkingDirectory(
39614f1b3e8SDimitry Andric             m_option_working_dir.GetOptionValue().GetCurrentValue());
39714f1b3e8SDimitry Andric     } else {
39886758c71SEd Maste       result.AppendError("no platform is currently selected");
39986758c71SEd Maste     }
40086758c71SEd Maste   }
40186758c71SEd Maste 
GetOptions()40214f1b3e8SDimitry Andric   Options *GetOptions() override {
403f3fbd1c0SDimitry Andric     if (!m_options.DidFinalize())
40486758c71SEd Maste       m_options.Finalize();
40586758c71SEd Maste     return &m_options;
40686758c71SEd Maste   }
40786758c71SEd Maste 
40886758c71SEd Maste   OptionGroupOptions m_options;
40986758c71SEd Maste   OptionGroupFile m_option_working_dir;
41086758c71SEd Maste };
41186758c71SEd Maste 
412f21a844fSEd Maste // "platform mkdir"
41314f1b3e8SDimitry Andric class CommandObjectPlatformMkDir : public CommandObjectParsed {
414f21a844fSEd Maste public:
CommandObjectPlatformMkDir(CommandInterpreter & interpreter)41514f1b3e8SDimitry Andric   CommandObjectPlatformMkDir(CommandInterpreter &interpreter)
41614f1b3e8SDimitry Andric       : CommandObjectParsed(interpreter, "platform mkdir",
41714f1b3e8SDimitry Andric                             "Make a new directory on the remote end.", nullptr,
418145449b1SDimitry Andric                             0) {
419ac9a064cSDimitry Andric     AddSimpleArgumentList(eArgTypeRemotePath);
420145449b1SDimitry Andric   }
421f21a844fSEd Maste 
422f3fbd1c0SDimitry Andric   ~CommandObjectPlatformMkDir() override = default;
423f21a844fSEd Maste 
DoExecute(Args & args,CommandReturnObject & result)424b1c73532SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
42514f1b3e8SDimitry Andric     PlatformSP platform_sp(
4265f29bb8aSDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
42714f1b3e8SDimitry Andric     if (platform_sp) {
428f21a844fSEd Maste       std::string cmd_line;
429f21a844fSEd Maste       args.GetCommandString(cmd_line);
43086758c71SEd Maste       uint32_t mode;
43114f1b3e8SDimitry Andric       const OptionPermissions *options_permissions =
43214f1b3e8SDimitry Andric           (const OptionPermissions *)m_options.GetGroupWithOption('r');
433f21a844fSEd Maste       if (options_permissions)
43486758c71SEd Maste         mode = options_permissions->m_permissions;
435f21a844fSEd Maste       else
43614f1b3e8SDimitry Andric         mode = lldb::eFilePermissionsUserRWX | lldb::eFilePermissionsGroupRWX |
43714f1b3e8SDimitry Andric                lldb::eFilePermissionsWorldRX;
43894994d37SDimitry Andric       Status error = platform_sp->MakeDirectory(FileSpec(cmd_line), mode);
43914f1b3e8SDimitry Andric       if (error.Success()) {
440f21a844fSEd Maste         result.SetStatus(eReturnStatusSuccessFinishResult);
44114f1b3e8SDimitry Andric       } else {
44286758c71SEd Maste         result.AppendError(error.AsCString());
44386758c71SEd Maste       }
44414f1b3e8SDimitry Andric     } else {
445f21a844fSEd Maste       result.AppendError("no platform currently selected\n");
446f21a844fSEd Maste     }
447f21a844fSEd Maste   }
448f21a844fSEd Maste 
GetOptions()44914f1b3e8SDimitry Andric   Options *GetOptions() override {
45014f1b3e8SDimitry Andric     if (!m_options.DidFinalize()) {
451e3b55780SDimitry Andric       m_options.Append(&m_option_permissions);
452f21a844fSEd Maste       m_options.Finalize();
453f21a844fSEd Maste     }
454f21a844fSEd Maste     return &m_options;
455f21a844fSEd Maste   }
456f21a844fSEd Maste 
457e3b55780SDimitry Andric   OptionPermissions m_option_permissions;
458f3fbd1c0SDimitry Andric   OptionGroupOptions m_options;
459f21a844fSEd Maste };
460f21a844fSEd Maste 
461f21a844fSEd Maste // "platform fopen"
46214f1b3e8SDimitry Andric class CommandObjectPlatformFOpen : public CommandObjectParsed {
463f21a844fSEd Maste public:
CommandObjectPlatformFOpen(CommandInterpreter & interpreter)46414f1b3e8SDimitry Andric   CommandObjectPlatformFOpen(CommandInterpreter &interpreter)
46514f1b3e8SDimitry Andric       : CommandObjectParsed(interpreter, "platform file open",
466145449b1SDimitry Andric                             "Open a file on the remote end.", nullptr, 0) {
467ac9a064cSDimitry Andric     AddSimpleArgumentList(eArgTypeRemotePath);
468145449b1SDimitry Andric   }
469f21a844fSEd Maste 
470f3fbd1c0SDimitry Andric   ~CommandObjectPlatformFOpen() override = default;
471f21a844fSEd Maste 
DoExecute(Args & args,CommandReturnObject & result)472b1c73532SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
47314f1b3e8SDimitry Andric     PlatformSP platform_sp(
4745f29bb8aSDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
47514f1b3e8SDimitry Andric     if (platform_sp) {
476b76161e4SDimitry Andric       Status error;
477f21a844fSEd Maste       std::string cmd_line;
478f21a844fSEd Maste       args.GetCommandString(cmd_line);
479f21a844fSEd Maste       mode_t perms;
48014f1b3e8SDimitry Andric       const OptionPermissions *options_permissions =
48114f1b3e8SDimitry Andric           (const OptionPermissions *)m_options.GetGroupWithOption('r');
482f21a844fSEd Maste       if (options_permissions)
483f21a844fSEd Maste         perms = options_permissions->m_permissions;
484f21a844fSEd Maste       else
48514f1b3e8SDimitry Andric         perms = lldb::eFilePermissionsUserRW | lldb::eFilePermissionsGroupRW |
48614f1b3e8SDimitry Andric                 lldb::eFilePermissionsWorldRead;
48714f1b3e8SDimitry Andric       lldb::user_id_t fd = platform_sp->OpenFile(
48894994d37SDimitry Andric           FileSpec(cmd_line),
489c0981da4SDimitry Andric           File::eOpenOptionReadWrite | File::eOpenOptionCanCreate,
49014f1b3e8SDimitry Andric           perms, error);
49114f1b3e8SDimitry Andric       if (error.Success()) {
492f21a844fSEd Maste         result.AppendMessageWithFormat("File Descriptor = %" PRIu64 "\n", fd);
493f21a844fSEd Maste         result.SetStatus(eReturnStatusSuccessFinishResult);
49414f1b3e8SDimitry Andric       } else {
495f21a844fSEd Maste         result.AppendError(error.AsCString());
496f21a844fSEd Maste       }
49714f1b3e8SDimitry Andric     } else {
498f21a844fSEd Maste       result.AppendError("no platform currently selected\n");
499f21a844fSEd Maste     }
500f21a844fSEd Maste   }
501f3fbd1c0SDimitry Andric 
GetOptions()50214f1b3e8SDimitry Andric   Options *GetOptions() override {
50314f1b3e8SDimitry Andric     if (!m_options.DidFinalize()) {
504e3b55780SDimitry Andric       m_options.Append(&m_option_permissions);
505f21a844fSEd Maste       m_options.Finalize();
506f21a844fSEd Maste     }
507f21a844fSEd Maste     return &m_options;
508f21a844fSEd Maste   }
509f3fbd1c0SDimitry Andric 
510e3b55780SDimitry Andric   OptionPermissions m_option_permissions;
511f21a844fSEd Maste   OptionGroupOptions m_options;
512f21a844fSEd Maste };
513f21a844fSEd Maste 
514f21a844fSEd Maste // "platform fclose"
51514f1b3e8SDimitry Andric class CommandObjectPlatformFClose : public CommandObjectParsed {
516f21a844fSEd Maste public:
CommandObjectPlatformFClose(CommandInterpreter & interpreter)51714f1b3e8SDimitry Andric   CommandObjectPlatformFClose(CommandInterpreter &interpreter)
51814f1b3e8SDimitry Andric       : CommandObjectParsed(interpreter, "platform file close",
519145449b1SDimitry Andric                             "Close a file on the remote end.", nullptr, 0) {
520ac9a064cSDimitry Andric     AddSimpleArgumentList(eArgTypeUnsignedInteger);
521145449b1SDimitry Andric   }
522f21a844fSEd Maste 
523f3fbd1c0SDimitry Andric   ~CommandObjectPlatformFClose() override = default;
524f21a844fSEd Maste 
DoExecute(Args & args,CommandReturnObject & result)525b1c73532SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
52614f1b3e8SDimitry Andric     PlatformSP platform_sp(
5275f29bb8aSDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
52814f1b3e8SDimitry Andric     if (platform_sp) {
529f21a844fSEd Maste       std::string cmd_line;
530f21a844fSEd Maste       args.GetCommandString(cmd_line);
531cfca06d7SDimitry Andric       lldb::user_id_t fd;
532cfca06d7SDimitry Andric       if (!llvm::to_integer(cmd_line, fd)) {
533cfca06d7SDimitry Andric         result.AppendErrorWithFormatv("'{0}' is not a valid file descriptor.\n",
534cfca06d7SDimitry Andric                                       cmd_line);
535b1c73532SDimitry Andric         return;
536cfca06d7SDimitry Andric       }
537b76161e4SDimitry Andric       Status error;
538f21a844fSEd Maste       bool success = platform_sp->CloseFile(fd, error);
53914f1b3e8SDimitry Andric       if (success) {
540f21a844fSEd Maste         result.AppendMessageWithFormat("file %" PRIu64 " closed.\n", fd);
541f21a844fSEd Maste         result.SetStatus(eReturnStatusSuccessFinishResult);
54214f1b3e8SDimitry Andric       } else {
543f21a844fSEd Maste         result.AppendError(error.AsCString());
544f21a844fSEd Maste       }
54514f1b3e8SDimitry Andric     } else {
546f21a844fSEd Maste       result.AppendError("no platform currently selected\n");
547f21a844fSEd Maste     }
548f21a844fSEd Maste   }
549f21a844fSEd Maste };
550f21a844fSEd Maste 
551f21a844fSEd Maste // "platform fread"
55214f1b3e8SDimitry Andric 
553ead24645SDimitry Andric #define LLDB_OPTIONS_platform_fread
554ead24645SDimitry Andric #include "CommandOptions.inc"
55514f1b3e8SDimitry Andric 
55614f1b3e8SDimitry Andric class CommandObjectPlatformFRead : public CommandObjectParsed {
557f21a844fSEd Maste public:
CommandObjectPlatformFRead(CommandInterpreter & interpreter)55814f1b3e8SDimitry Andric   CommandObjectPlatformFRead(CommandInterpreter &interpreter)
55914f1b3e8SDimitry Andric       : CommandObjectParsed(interpreter, "platform file read",
56014f1b3e8SDimitry Andric                             "Read data from a file on the remote end.", nullptr,
561145449b1SDimitry Andric                             0) {
562ac9a064cSDimitry Andric     AddSimpleArgumentList(eArgTypeUnsignedInteger);
563145449b1SDimitry Andric   }
564f21a844fSEd Maste 
565f3fbd1c0SDimitry Andric   ~CommandObjectPlatformFRead() override = default;
566f21a844fSEd Maste 
DoExecute(Args & args,CommandReturnObject & result)567b1c73532SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
56814f1b3e8SDimitry Andric     PlatformSP platform_sp(
5695f29bb8aSDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
57014f1b3e8SDimitry Andric     if (platform_sp) {
571f21a844fSEd Maste       std::string cmd_line;
572f21a844fSEd Maste       args.GetCommandString(cmd_line);
573cfca06d7SDimitry Andric       lldb::user_id_t fd;
574cfca06d7SDimitry Andric       if (!llvm::to_integer(cmd_line, fd)) {
575cfca06d7SDimitry Andric         result.AppendErrorWithFormatv("'{0}' is not a valid file descriptor.\n",
576cfca06d7SDimitry Andric                                       cmd_line);
577b1c73532SDimitry Andric         return;
578cfca06d7SDimitry Andric       }
579f21a844fSEd Maste       std::string buffer(m_options.m_count, 0);
580b76161e4SDimitry Andric       Status error;
581c0981da4SDimitry Andric       uint64_t retcode = platform_sp->ReadFile(
58214f1b3e8SDimitry Andric           fd, m_options.m_offset, &buffer[0], m_options.m_count, error);
583c0981da4SDimitry Andric       if (retcode != UINT64_MAX) {
584c0981da4SDimitry Andric         result.AppendMessageWithFormat("Return = %" PRIu64 "\n", retcode);
585f21a844fSEd Maste         result.AppendMessageWithFormat("Data = \"%s\"\n", buffer.c_str());
586f21a844fSEd Maste         result.SetStatus(eReturnStatusSuccessFinishResult);
58714f1b3e8SDimitry Andric       } else {
588c0981da4SDimitry Andric         result.AppendError(error.AsCString());
589c0981da4SDimitry Andric       }
590c0981da4SDimitry Andric     } else {
591f21a844fSEd Maste       result.AppendError("no platform currently selected\n");
592f21a844fSEd Maste     }
593f21a844fSEd Maste   }
594f3fbd1c0SDimitry Andric 
GetOptions()59514f1b3e8SDimitry Andric   Options *GetOptions() override { return &m_options; }
596f21a844fSEd Maste 
597f21a844fSEd Maste protected:
59814f1b3e8SDimitry Andric   class CommandOptions : public Options {
599f21a844fSEd Maste   public:
600145449b1SDimitry Andric     CommandOptions() = default;
601f21a844fSEd Maste 
602f3fbd1c0SDimitry Andric     ~CommandOptions() override = default;
603f21a844fSEd Maste 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)604b76161e4SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
60514f1b3e8SDimitry Andric                           ExecutionContext *execution_context) override {
606b76161e4SDimitry Andric       Status error;
607f21a844fSEd Maste       char short_option = (char)m_getopt_table[option_idx].val;
608f21a844fSEd Maste 
60914f1b3e8SDimitry Andric       switch (short_option) {
610f21a844fSEd Maste       case 'o':
61114f1b3e8SDimitry Andric         if (option_arg.getAsInteger(0, m_offset))
61214f1b3e8SDimitry Andric           error.SetErrorStringWithFormat("invalid offset: '%s'",
61314f1b3e8SDimitry Andric                                          option_arg.str().c_str());
614f21a844fSEd Maste         break;
615f21a844fSEd Maste       case 'c':
61614f1b3e8SDimitry Andric         if (option_arg.getAsInteger(0, m_count))
61714f1b3e8SDimitry Andric           error.SetErrorStringWithFormat("invalid offset: '%s'",
61814f1b3e8SDimitry Andric                                          option_arg.str().c_str());
619f21a844fSEd Maste         break;
620f21a844fSEd Maste       default:
621ead24645SDimitry Andric         llvm_unreachable("Unimplemented option");
622f21a844fSEd Maste       }
623f21a844fSEd Maste 
624f21a844fSEd Maste       return error;
625f21a844fSEd Maste     }
626f21a844fSEd Maste 
OptionParsingStarting(ExecutionContext * execution_context)62714f1b3e8SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
628f21a844fSEd Maste       m_offset = 0;
629f21a844fSEd Maste       m_count = 1;
630f21a844fSEd Maste     }
631f21a844fSEd Maste 
GetDefinitions()63214f1b3e8SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
633e3b55780SDimitry Andric       return llvm::ArrayRef(g_platform_fread_options);
634f21a844fSEd Maste     }
635f21a844fSEd Maste 
636f21a844fSEd Maste     // Instance variables to hold the values for command options.
637f21a844fSEd Maste 
638f21a844fSEd Maste     uint32_t m_offset;
639f21a844fSEd Maste     uint32_t m_count;
640f21a844fSEd Maste   };
641f3fbd1c0SDimitry Andric 
642f21a844fSEd Maste   CommandOptions m_options;
643f21a844fSEd Maste };
644f3fbd1c0SDimitry Andric 
645f21a844fSEd Maste // "platform fwrite"
64614f1b3e8SDimitry Andric 
647ead24645SDimitry Andric #define LLDB_OPTIONS_platform_fwrite
648ead24645SDimitry Andric #include "CommandOptions.inc"
64914f1b3e8SDimitry Andric 
65014f1b3e8SDimitry Andric class CommandObjectPlatformFWrite : public CommandObjectParsed {
651f21a844fSEd Maste public:
CommandObjectPlatformFWrite(CommandInterpreter & interpreter)65214f1b3e8SDimitry Andric   CommandObjectPlatformFWrite(CommandInterpreter &interpreter)
65314f1b3e8SDimitry Andric       : CommandObjectParsed(interpreter, "platform file write",
65414f1b3e8SDimitry Andric                             "Write data to a file on the remote end.", nullptr,
655145449b1SDimitry Andric                             0) {
656ac9a064cSDimitry Andric     AddSimpleArgumentList(eArgTypeUnsignedInteger);
657145449b1SDimitry Andric   }
658f21a844fSEd Maste 
659f3fbd1c0SDimitry Andric   ~CommandObjectPlatformFWrite() override = default;
660f21a844fSEd Maste 
DoExecute(Args & args,CommandReturnObject & result)661b1c73532SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
66214f1b3e8SDimitry Andric     PlatformSP platform_sp(
6635f29bb8aSDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
66414f1b3e8SDimitry Andric     if (platform_sp) {
665f21a844fSEd Maste       std::string cmd_line;
666f21a844fSEd Maste       args.GetCommandString(cmd_line);
667b76161e4SDimitry Andric       Status error;
668cfca06d7SDimitry Andric       lldb::user_id_t fd;
669cfca06d7SDimitry Andric       if (!llvm::to_integer(cmd_line, fd)) {
670cfca06d7SDimitry Andric         result.AppendErrorWithFormatv("'{0}' is not a valid file descriptor.",
671cfca06d7SDimitry Andric                                       cmd_line);
672b1c73532SDimitry Andric         return;
673cfca06d7SDimitry Andric       }
674c0981da4SDimitry Andric       uint64_t retcode =
67514f1b3e8SDimitry Andric           platform_sp->WriteFile(fd, m_options.m_offset, &m_options.m_data[0],
67614f1b3e8SDimitry Andric                                  m_options.m_data.size(), error);
677c0981da4SDimitry Andric       if (retcode != UINT64_MAX) {
678c0981da4SDimitry Andric         result.AppendMessageWithFormat("Return = %" PRIu64 "\n", retcode);
679f21a844fSEd Maste         result.SetStatus(eReturnStatusSuccessFinishResult);
68014f1b3e8SDimitry Andric       } else {
681c0981da4SDimitry Andric         result.AppendError(error.AsCString());
682c0981da4SDimitry Andric       }
683c0981da4SDimitry Andric     } else {
684f21a844fSEd Maste       result.AppendError("no platform currently selected\n");
685f21a844fSEd Maste     }
686f21a844fSEd Maste   }
687f3fbd1c0SDimitry Andric 
GetOptions()68814f1b3e8SDimitry Andric   Options *GetOptions() override { return &m_options; }
689f21a844fSEd Maste 
690f21a844fSEd Maste protected:
69114f1b3e8SDimitry Andric   class CommandOptions : public Options {
692f21a844fSEd Maste   public:
693145449b1SDimitry Andric     CommandOptions() = default;
694f21a844fSEd Maste 
695f3fbd1c0SDimitry Andric     ~CommandOptions() override = default;
696f21a844fSEd Maste 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)697b76161e4SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
69814f1b3e8SDimitry Andric                           ExecutionContext *execution_context) override {
699b76161e4SDimitry Andric       Status error;
700f21a844fSEd Maste       char short_option = (char)m_getopt_table[option_idx].val;
701f21a844fSEd Maste 
70214f1b3e8SDimitry Andric       switch (short_option) {
703f21a844fSEd Maste       case 'o':
70414f1b3e8SDimitry Andric         if (option_arg.getAsInteger(0, m_offset))
70514f1b3e8SDimitry Andric           error.SetErrorStringWithFormat("invalid offset: '%s'",
70614f1b3e8SDimitry Andric                                          option_arg.str().c_str());
707f21a844fSEd Maste         break;
708f21a844fSEd Maste       case 'd':
709cfca06d7SDimitry Andric         m_data.assign(std::string(option_arg));
710f21a844fSEd Maste         break;
711f21a844fSEd Maste       default:
712ead24645SDimitry Andric         llvm_unreachable("Unimplemented option");
713f21a844fSEd Maste       }
714f21a844fSEd Maste 
715f21a844fSEd Maste       return error;
716f21a844fSEd Maste     }
717f21a844fSEd Maste 
OptionParsingStarting(ExecutionContext * execution_context)71814f1b3e8SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
719f21a844fSEd Maste       m_offset = 0;
720f21a844fSEd Maste       m_data.clear();
721f21a844fSEd Maste     }
722f21a844fSEd Maste 
GetDefinitions()72314f1b3e8SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
724e3b55780SDimitry Andric       return llvm::ArrayRef(g_platform_fwrite_options);
725f21a844fSEd Maste     }
726f21a844fSEd Maste 
727f21a844fSEd Maste     // Instance variables to hold the values for command options.
728f21a844fSEd Maste 
729f21a844fSEd Maste     uint32_t m_offset;
730f21a844fSEd Maste     std::string m_data;
731f21a844fSEd Maste   };
732f3fbd1c0SDimitry Andric 
733f21a844fSEd Maste   CommandOptions m_options;
734f21a844fSEd Maste };
735f3fbd1c0SDimitry Andric 
73614f1b3e8SDimitry Andric class CommandObjectPlatformFile : public CommandObjectMultiword {
737f21a844fSEd Maste public:
738f21a844fSEd Maste   // Constructors and Destructors
CommandObjectPlatformFile(CommandInterpreter & interpreter)739f3fbd1c0SDimitry Andric   CommandObjectPlatformFile(CommandInterpreter &interpreter)
74014f1b3e8SDimitry Andric       : CommandObjectMultiword(
74114f1b3e8SDimitry Andric             interpreter, "platform file",
74214f1b3e8SDimitry Andric             "Commands to access files on the current platform.",
74314f1b3e8SDimitry Andric             "platform file [open|close|read|write] ...") {
74414f1b3e8SDimitry Andric     LoadSubCommand(
74514f1b3e8SDimitry Andric         "open", CommandObjectSP(new CommandObjectPlatformFOpen(interpreter)));
74614f1b3e8SDimitry Andric     LoadSubCommand(
74714f1b3e8SDimitry Andric         "close", CommandObjectSP(new CommandObjectPlatformFClose(interpreter)));
74814f1b3e8SDimitry Andric     LoadSubCommand(
74914f1b3e8SDimitry Andric         "read", CommandObjectSP(new CommandObjectPlatformFRead(interpreter)));
75014f1b3e8SDimitry Andric     LoadSubCommand(
75114f1b3e8SDimitry Andric         "write", CommandObjectSP(new CommandObjectPlatformFWrite(interpreter)));
752f21a844fSEd Maste   }
753f21a844fSEd Maste 
754f3fbd1c0SDimitry Andric   ~CommandObjectPlatformFile() override = default;
755f21a844fSEd Maste 
756f21a844fSEd Maste private:
757f21a844fSEd Maste   // For CommandObjectPlatform only
758cfca06d7SDimitry Andric   CommandObjectPlatformFile(const CommandObjectPlatformFile &) = delete;
759cfca06d7SDimitry Andric   const CommandObjectPlatformFile &
760cfca06d7SDimitry Andric   operator=(const CommandObjectPlatformFile &) = delete;
761f21a844fSEd Maste };
762f21a844fSEd Maste 
763f21a844fSEd Maste // "platform get-file remote-file-path host-file-path"
76414f1b3e8SDimitry Andric class CommandObjectPlatformGetFile : public CommandObjectParsed {
765f21a844fSEd Maste public:
CommandObjectPlatformGetFile(CommandInterpreter & interpreter)76614f1b3e8SDimitry Andric   CommandObjectPlatformGetFile(CommandInterpreter &interpreter)
76714f1b3e8SDimitry Andric       : CommandObjectParsed(
76814f1b3e8SDimitry Andric             interpreter, "platform get-file",
769f21a844fSEd Maste             "Transfer a file from the remote end to the local host.",
77014f1b3e8SDimitry Andric             "platform get-file <remote-file-spec> <local-file-spec>", 0) {
771f21a844fSEd Maste     SetHelpLong(
772027f1c96SDimitry Andric         R"(Examples:
773027f1c96SDimitry Andric 
774027f1c96SDimitry Andric (lldb) platform get-file /the/remote/file/path /the/local/file/path
775027f1c96SDimitry Andric 
77614f1b3e8SDimitry Andric     Transfer a file from the remote end with file path /the/remote/file/path to the local host.)");
777f21a844fSEd Maste 
778f21a844fSEd Maste     CommandArgumentEntry arg1, arg2;
779f21a844fSEd Maste     CommandArgumentData file_arg_remote, file_arg_host;
780f21a844fSEd Maste 
781f21a844fSEd Maste     // Define the first (and only) variant of this arg.
782ac9a064cSDimitry Andric     file_arg_remote.arg_type = eArgTypeRemoteFilename;
783f21a844fSEd Maste     file_arg_remote.arg_repetition = eArgRepeatPlain;
78414f1b3e8SDimitry Andric     // There is only one variant this argument could be; put it into the
78514f1b3e8SDimitry Andric     // argument entry.
786f21a844fSEd Maste     arg1.push_back(file_arg_remote);
787f21a844fSEd Maste 
788f21a844fSEd Maste     // Define the second (and only) variant of this arg.
789f21a844fSEd Maste     file_arg_host.arg_type = eArgTypeFilename;
790f21a844fSEd Maste     file_arg_host.arg_repetition = eArgRepeatPlain;
79114f1b3e8SDimitry Andric     // There is only one variant this argument could be; put it into the
79214f1b3e8SDimitry Andric     // argument entry.
793f21a844fSEd Maste     arg2.push_back(file_arg_host);
794f21a844fSEd Maste 
795f73363f1SDimitry Andric     // Push the data for the first and the second arguments into the
796f73363f1SDimitry Andric     // m_arguments vector.
797f21a844fSEd Maste     m_arguments.push_back(arg1);
798f21a844fSEd Maste     m_arguments.push_back(arg2);
799f21a844fSEd Maste   }
800f21a844fSEd Maste 
801f3fbd1c0SDimitry Andric   ~CommandObjectPlatformGetFile() override = default;
802f21a844fSEd Maste 
803b60736ecSDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)804b60736ecSDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
805b60736ecSDimitry Andric                            OptionElementVector &opt_element_vector) override {
806b60736ecSDimitry Andric     if (request.GetCursorIndex() == 0)
8077fa27ce4SDimitry Andric       lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
8087fa27ce4SDimitry Andric           GetCommandInterpreter(), lldb::eRemoteDiskFileCompletion, request,
8097fa27ce4SDimitry Andric           nullptr);
810b60736ecSDimitry Andric     else if (request.GetCursorIndex() == 1)
8117fa27ce4SDimitry Andric       lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
8127fa27ce4SDimitry Andric           GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr);
813b60736ecSDimitry Andric   }
814b60736ecSDimitry Andric 
DoExecute(Args & args,CommandReturnObject & result)815b1c73532SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
816f21a844fSEd Maste     // If the number of arguments is incorrect, issue an error message.
81714f1b3e8SDimitry Andric     if (args.GetArgumentCount() != 2) {
818344a3780SDimitry Andric       result.AppendError("required arguments missing; specify both the "
819344a3780SDimitry Andric                          "source and destination file paths");
820b1c73532SDimitry Andric       return;
821f21a844fSEd Maste     }
822f21a844fSEd Maste 
82314f1b3e8SDimitry Andric     PlatformSP platform_sp(
8245f29bb8aSDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
82514f1b3e8SDimitry Andric     if (platform_sp) {
826f21a844fSEd Maste       const char *remote_file_path = args.GetArgumentAtIndex(0);
827f21a844fSEd Maste       const char *local_file_path = args.GetArgumentAtIndex(1);
82894994d37SDimitry Andric       Status error = platform_sp->GetFile(FileSpec(remote_file_path),
82994994d37SDimitry Andric                                           FileSpec(local_file_path));
83014f1b3e8SDimitry Andric       if (error.Success()) {
83114f1b3e8SDimitry Andric         result.AppendMessageWithFormat(
83214f1b3e8SDimitry Andric             "successfully get-file from %s (remote) to %s (host)\n",
833f21a844fSEd Maste             remote_file_path, local_file_path);
834f21a844fSEd Maste         result.SetStatus(eReturnStatusSuccessFinishResult);
83514f1b3e8SDimitry Andric       } else {
83614f1b3e8SDimitry Andric         result.AppendMessageWithFormat("get-file failed: %s\n",
83714f1b3e8SDimitry Andric                                        error.AsCString());
838f21a844fSEd Maste       }
83914f1b3e8SDimitry Andric     } else {
840f21a844fSEd Maste       result.AppendError("no platform currently selected\n");
841f21a844fSEd Maste     }
842f21a844fSEd Maste   }
843f21a844fSEd Maste };
844f21a844fSEd Maste 
845f21a844fSEd Maste // "platform get-size remote-file-path"
84614f1b3e8SDimitry Andric class CommandObjectPlatformGetSize : public CommandObjectParsed {
847f21a844fSEd Maste public:
CommandObjectPlatformGetSize(CommandInterpreter & interpreter)84814f1b3e8SDimitry Andric   CommandObjectPlatformGetSize(CommandInterpreter &interpreter)
84914f1b3e8SDimitry Andric       : CommandObjectParsed(interpreter, "platform get-size",
850f21a844fSEd Maste                             "Get the file size from the remote end.",
85114f1b3e8SDimitry Andric                             "platform get-size <remote-file-spec>", 0) {
852f21a844fSEd Maste     SetHelpLong(
853027f1c96SDimitry Andric         R"(Examples:
854027f1c96SDimitry Andric 
855027f1c96SDimitry Andric (lldb) platform get-size /the/remote/file/path
856027f1c96SDimitry Andric 
85714f1b3e8SDimitry Andric     Get the file size from the remote end with path /the/remote/file/path.)");
858f21a844fSEd Maste 
859ac9a064cSDimitry Andric     AddSimpleArgumentList(eArgTypeRemoteFilename);
860f21a844fSEd Maste   }
861f21a844fSEd Maste 
862f3fbd1c0SDimitry Andric   ~CommandObjectPlatformGetSize() override = default;
863f21a844fSEd Maste 
DoExecute(Args & args,CommandReturnObject & result)864b1c73532SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
865f21a844fSEd Maste     // If the number of arguments is incorrect, issue an error message.
86614f1b3e8SDimitry Andric     if (args.GetArgumentCount() != 1) {
867344a3780SDimitry Andric       result.AppendError("required argument missing; specify the source file "
868344a3780SDimitry Andric                          "path as the only argument");
869b1c73532SDimitry Andric       return;
870f21a844fSEd Maste     }
871f21a844fSEd Maste 
87214f1b3e8SDimitry Andric     PlatformSP platform_sp(
8735f29bb8aSDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
87414f1b3e8SDimitry Andric     if (platform_sp) {
875f21a844fSEd Maste       std::string remote_file_path(args.GetArgumentAtIndex(0));
87694994d37SDimitry Andric       user_id_t size = platform_sp->GetFileSize(FileSpec(remote_file_path));
87714f1b3e8SDimitry Andric       if (size != UINT64_MAX) {
87814f1b3e8SDimitry Andric         result.AppendMessageWithFormat("File size of %s (remote): %" PRIu64
87914f1b3e8SDimitry Andric                                        "\n",
88014f1b3e8SDimitry Andric                                        remote_file_path.c_str(), size);
881f21a844fSEd Maste         result.SetStatus(eReturnStatusSuccessFinishResult);
88214f1b3e8SDimitry Andric       } else {
88314f1b3e8SDimitry Andric         result.AppendMessageWithFormat(
88414f1b3e8SDimitry Andric             "Error getting file size of %s (remote)\n",
88514f1b3e8SDimitry Andric             remote_file_path.c_str());
886f21a844fSEd Maste       }
88714f1b3e8SDimitry Andric     } else {
888f21a844fSEd Maste       result.AppendError("no platform currently selected\n");
889f21a844fSEd Maste     }
890f21a844fSEd Maste   }
891f21a844fSEd Maste };
892f21a844fSEd Maste 
893c0981da4SDimitry Andric // "platform get-permissions remote-file-path"
894c0981da4SDimitry Andric class CommandObjectPlatformGetPermissions : public CommandObjectParsed {
895c0981da4SDimitry Andric public:
CommandObjectPlatformGetPermissions(CommandInterpreter & interpreter)896c0981da4SDimitry Andric   CommandObjectPlatformGetPermissions(CommandInterpreter &interpreter)
897c0981da4SDimitry Andric       : CommandObjectParsed(interpreter, "platform get-permissions",
898c0981da4SDimitry Andric                             "Get the file permission bits from the remote end.",
899c0981da4SDimitry Andric                             "platform get-permissions <remote-file-spec>", 0) {
900c0981da4SDimitry Andric     SetHelpLong(
901c0981da4SDimitry Andric         R"(Examples:
902c0981da4SDimitry Andric 
903c0981da4SDimitry Andric (lldb) platform get-permissions /the/remote/file/path
904c0981da4SDimitry Andric 
905c0981da4SDimitry Andric     Get the file permissions from the remote end with path /the/remote/file/path.)");
906c0981da4SDimitry Andric 
907ac9a064cSDimitry Andric     AddSimpleArgumentList(eArgTypeRemoteFilename);
908c0981da4SDimitry Andric   }
909c0981da4SDimitry Andric 
910c0981da4SDimitry Andric   ~CommandObjectPlatformGetPermissions() override = default;
911c0981da4SDimitry Andric 
DoExecute(Args & args,CommandReturnObject & result)912b1c73532SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
913c0981da4SDimitry Andric     // If the number of arguments is incorrect, issue an error message.
914c0981da4SDimitry Andric     if (args.GetArgumentCount() != 1) {
915c0981da4SDimitry Andric       result.AppendError("required argument missing; specify the source file "
916c0981da4SDimitry Andric                          "path as the only argument");
917b1c73532SDimitry Andric       return;
918c0981da4SDimitry Andric     }
919c0981da4SDimitry Andric 
920c0981da4SDimitry Andric     PlatformSP platform_sp(
921c0981da4SDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
922c0981da4SDimitry Andric     if (platform_sp) {
923c0981da4SDimitry Andric       std::string remote_file_path(args.GetArgumentAtIndex(0));
924c0981da4SDimitry Andric       uint32_t permissions;
925c0981da4SDimitry Andric       Status error = platform_sp->GetFilePermissions(FileSpec(remote_file_path),
926c0981da4SDimitry Andric                                                      permissions);
927c0981da4SDimitry Andric       if (error.Success()) {
928c0981da4SDimitry Andric         result.AppendMessageWithFormat(
929c0981da4SDimitry Andric             "File permissions of %s (remote): 0o%04" PRIo32 "\n",
930c0981da4SDimitry Andric             remote_file_path.c_str(), permissions);
931c0981da4SDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishResult);
932c0981da4SDimitry Andric       } else
933c0981da4SDimitry Andric         result.AppendError(error.AsCString());
934c0981da4SDimitry Andric     } else {
935c0981da4SDimitry Andric       result.AppendError("no platform currently selected\n");
936c0981da4SDimitry Andric     }
937c0981da4SDimitry Andric   }
938c0981da4SDimitry Andric };
939c0981da4SDimitry Andric 
940c0981da4SDimitry Andric // "platform file-exists remote-file-path"
941c0981da4SDimitry Andric class CommandObjectPlatformFileExists : public CommandObjectParsed {
942c0981da4SDimitry Andric public:
CommandObjectPlatformFileExists(CommandInterpreter & interpreter)943c0981da4SDimitry Andric   CommandObjectPlatformFileExists(CommandInterpreter &interpreter)
944c0981da4SDimitry Andric       : CommandObjectParsed(interpreter, "platform file-exists",
945c0981da4SDimitry Andric                             "Check if the file exists on the remote end.",
946c0981da4SDimitry Andric                             "platform file-exists <remote-file-spec>", 0) {
947c0981da4SDimitry Andric     SetHelpLong(
948c0981da4SDimitry Andric         R"(Examples:
949c0981da4SDimitry Andric 
950c0981da4SDimitry Andric (lldb) platform file-exists /the/remote/file/path
951c0981da4SDimitry Andric 
952c0981da4SDimitry Andric     Check if /the/remote/file/path exists on the remote end.)");
953c0981da4SDimitry Andric 
954ac9a064cSDimitry Andric     AddSimpleArgumentList(eArgTypeRemoteFilename);
955c0981da4SDimitry Andric   }
956c0981da4SDimitry Andric 
957c0981da4SDimitry Andric   ~CommandObjectPlatformFileExists() override = default;
958c0981da4SDimitry Andric 
DoExecute(Args & args,CommandReturnObject & result)959b1c73532SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
960c0981da4SDimitry Andric     // If the number of arguments is incorrect, issue an error message.
961c0981da4SDimitry Andric     if (args.GetArgumentCount() != 1) {
962c0981da4SDimitry Andric       result.AppendError("required argument missing; specify the source file "
963c0981da4SDimitry Andric                          "path as the only argument");
964b1c73532SDimitry Andric       return;
965c0981da4SDimitry Andric     }
966c0981da4SDimitry Andric 
967c0981da4SDimitry Andric     PlatformSP platform_sp(
968c0981da4SDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
969c0981da4SDimitry Andric     if (platform_sp) {
970c0981da4SDimitry Andric       std::string remote_file_path(args.GetArgumentAtIndex(0));
971c0981da4SDimitry Andric       bool exists = platform_sp->GetFileExists(FileSpec(remote_file_path));
972c0981da4SDimitry Andric       result.AppendMessageWithFormat(
973c0981da4SDimitry Andric           "File %s (remote) %s\n",
974c0981da4SDimitry Andric           remote_file_path.c_str(), exists ? "exists" : "does not exist");
975c0981da4SDimitry Andric       result.SetStatus(eReturnStatusSuccessFinishResult);
976c0981da4SDimitry Andric     } else {
977c0981da4SDimitry Andric       result.AppendError("no platform currently selected\n");
978c0981da4SDimitry Andric     }
979c0981da4SDimitry Andric   }
980c0981da4SDimitry Andric };
981c0981da4SDimitry Andric 
982f21a844fSEd Maste // "platform put-file"
98314f1b3e8SDimitry Andric class CommandObjectPlatformPutFile : public CommandObjectParsed {
984f21a844fSEd Maste public:
CommandObjectPlatformPutFile(CommandInterpreter & interpreter)98514f1b3e8SDimitry Andric   CommandObjectPlatformPutFile(CommandInterpreter &interpreter)
98614f1b3e8SDimitry Andric       : CommandObjectParsed(
98714f1b3e8SDimitry Andric             interpreter, "platform put-file",
988c0981da4SDimitry Andric             "Transfer a file from this system to the remote end.",
989c0981da4SDimitry Andric             "platform put-file <source> [<destination>]", 0) {
990c0981da4SDimitry Andric     SetHelpLong(
991c0981da4SDimitry Andric         R"(Examples:
992c0981da4SDimitry Andric 
993c0981da4SDimitry Andric (lldb) platform put-file /source/foo.txt /destination/bar.txt
994c0981da4SDimitry Andric 
995c0981da4SDimitry Andric (lldb) platform put-file /source/foo.txt
996c0981da4SDimitry Andric 
997c0981da4SDimitry Andric     Relative source file paths are resolved against lldb's local working directory.
998c0981da4SDimitry Andric 
999c0981da4SDimitry Andric     Omitting the destination places the file in the platform working directory.)");
1000145449b1SDimitry Andric     CommandArgumentData source_arg{eArgTypePath, eArgRepeatPlain};
1001ac9a064cSDimitry Andric     CommandArgumentData path_arg{eArgTypeRemotePath, eArgRepeatOptional};
1002145449b1SDimitry Andric     m_arguments.push_back({source_arg});
1003145449b1SDimitry Andric     m_arguments.push_back({path_arg});
1004f21a844fSEd Maste   }
1005f21a844fSEd Maste 
1006f3fbd1c0SDimitry Andric   ~CommandObjectPlatformPutFile() override = default;
1007f21a844fSEd Maste 
1008b60736ecSDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)1009b60736ecSDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
1010b60736ecSDimitry Andric                            OptionElementVector &opt_element_vector) override {
1011b60736ecSDimitry Andric     if (request.GetCursorIndex() == 0)
10127fa27ce4SDimitry Andric       lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
10137fa27ce4SDimitry Andric           GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr);
1014b60736ecSDimitry Andric     else if (request.GetCursorIndex() == 1)
10157fa27ce4SDimitry Andric       lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
10167fa27ce4SDimitry Andric           GetCommandInterpreter(), lldb::eRemoteDiskFileCompletion, request,
10177fa27ce4SDimitry Andric           nullptr);
1018b60736ecSDimitry Andric   }
1019b60736ecSDimitry Andric 
DoExecute(Args & args,CommandReturnObject & result)1020b1c73532SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
1021f21a844fSEd Maste     const char *src = args.GetArgumentAtIndex(0);
1022f21a844fSEd Maste     const char *dst = args.GetArgumentAtIndex(1);
1023f21a844fSEd Maste 
102494994d37SDimitry Andric     FileSpec src_fs(src);
102594994d37SDimitry Andric     FileSystem::Instance().Resolve(src_fs);
102694994d37SDimitry Andric     FileSpec dst_fs(dst ? dst : src_fs.GetFilename().GetCString());
1027f21a844fSEd Maste 
102814f1b3e8SDimitry Andric     PlatformSP platform_sp(
10295f29bb8aSDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
103014f1b3e8SDimitry Andric     if (platform_sp) {
1031b76161e4SDimitry Andric       Status error(platform_sp->PutFile(src_fs, dst_fs));
103214f1b3e8SDimitry Andric       if (error.Success()) {
1033f21a844fSEd Maste         result.SetStatus(eReturnStatusSuccessFinishNoResult);
103414f1b3e8SDimitry Andric       } else {
1035f21a844fSEd Maste         result.AppendError(error.AsCString());
1036f21a844fSEd Maste       }
103714f1b3e8SDimitry Andric     } else {
1038f21a844fSEd Maste       result.AppendError("no platform currently selected\n");
1039f21a844fSEd Maste     }
1040f21a844fSEd Maste   }
1041f21a844fSEd Maste };
1042f21a844fSEd Maste 
1043f034231aSEd Maste // "platform process launch"
104414f1b3e8SDimitry Andric class CommandObjectPlatformProcessLaunch : public CommandObjectParsed {
1045f034231aSEd Maste public:
CommandObjectPlatformProcessLaunch(CommandInterpreter & interpreter)104614f1b3e8SDimitry Andric   CommandObjectPlatformProcessLaunch(CommandInterpreter &interpreter)
104714f1b3e8SDimitry Andric       : CommandObjectParsed(interpreter, "platform process launch",
1048f034231aSEd Maste                             "Launch a new process on a remote platform.",
1049f034231aSEd Maste                             "platform process launch program",
10507fa27ce4SDimitry Andric                             eCommandRequiresTarget | eCommandTryTargetAPILock),
10517fa27ce4SDimitry Andric         m_class_options("scripted process", true, 'C', 'k', 'v', 0) {
1052344a3780SDimitry Andric     m_all_options.Append(&m_options);
10537fa27ce4SDimitry Andric     m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2,
10547fa27ce4SDimitry Andric                          LLDB_OPT_SET_ALL);
1055344a3780SDimitry Andric     m_all_options.Finalize();
1056ac9a064cSDimitry Andric     AddSimpleArgumentList(eArgTypeRunArgs, eArgRepeatStar);
1057ac9a064cSDimitry Andric   }
1058ac9a064cSDimitry Andric 
1059ac9a064cSDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)1060ac9a064cSDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
1061ac9a064cSDimitry Andric                            OptionElementVector &opt_element_vector) override {
1062ac9a064cSDimitry Andric     // I didn't make a type for RemoteRunArgs, but since we're going to run
1063ac9a064cSDimitry Andric     // this on the remote system we should use the remote completer.
1064ac9a064cSDimitry Andric     lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1065ac9a064cSDimitry Andric         GetCommandInterpreter(), lldb::eRemoteDiskFileCompletion, request,
1066ac9a064cSDimitry Andric         nullptr);
1067344a3780SDimitry Andric   }
1068f034231aSEd Maste 
1069f3fbd1c0SDimitry Andric   ~CommandObjectPlatformProcessLaunch() override = default;
1070f034231aSEd Maste 
GetOptions()1071344a3780SDimitry Andric   Options *GetOptions() override { return &m_all_options; }
1072f034231aSEd Maste 
1073f034231aSEd Maste protected:
DoExecute(Args & args,CommandReturnObject & result)1074b1c73532SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
10755f29bb8aSDimitry Andric     Target *target = GetDebugger().GetSelectedTarget().get();
1076f034231aSEd Maste     PlatformSP platform_sp;
107714f1b3e8SDimitry Andric     if (target) {
1078f034231aSEd Maste       platform_sp = target->GetPlatform();
1079f034231aSEd Maste     }
108014f1b3e8SDimitry Andric     if (!platform_sp) {
10815f29bb8aSDimitry Andric       platform_sp = GetDebugger().GetPlatformList().GetSelectedPlatform();
1082f034231aSEd Maste     }
1083f034231aSEd Maste 
108414f1b3e8SDimitry Andric     if (platform_sp) {
1085b76161e4SDimitry Andric       Status error;
1086f034231aSEd Maste       const size_t argc = args.GetArgumentCount();
1087f034231aSEd Maste       Target *target = m_exe_ctx.GetTargetPtr();
1088f034231aSEd Maste       Module *exe_module = target->GetExecutableModulePointer();
108914f1b3e8SDimitry Andric       if (exe_module) {
1090f034231aSEd Maste         m_options.launch_info.GetExecutableFile() = exe_module->GetFileSpec();
109194994d37SDimitry Andric         llvm::SmallString<128> exe_path;
109214f1b3e8SDimitry Andric         m_options.launch_info.GetExecutableFile().GetPath(exe_path);
109314f1b3e8SDimitry Andric         if (!exe_path.empty())
1094f034231aSEd Maste           m_options.launch_info.GetArguments().AppendArgument(exe_path);
1095f034231aSEd Maste         m_options.launch_info.GetArchitecture() = exe_module->GetArchitecture();
1096f034231aSEd Maste       }
1097f034231aSEd Maste 
10987fa27ce4SDimitry Andric       if (!m_class_options.GetName().empty()) {
10997fa27ce4SDimitry Andric         m_options.launch_info.SetProcessPluginName("ScriptedProcess");
11007fa27ce4SDimitry Andric         ScriptedMetadataSP metadata_sp = std::make_shared<ScriptedMetadata>(
11017fa27ce4SDimitry Andric             m_class_options.GetName(), m_class_options.GetStructuredData());
11027fa27ce4SDimitry Andric         m_options.launch_info.SetScriptedMetadata(metadata_sp);
11037fa27ce4SDimitry Andric         target->SetProcessLaunchInfo(m_options.launch_info);
11047fa27ce4SDimitry Andric       }
11057fa27ce4SDimitry Andric 
110614f1b3e8SDimitry Andric       if (argc > 0) {
110714f1b3e8SDimitry Andric         if (m_options.launch_info.GetExecutableFile()) {
1108f73363f1SDimitry Andric           // We already have an executable file, so we will use this and all
1109f73363f1SDimitry Andric           // arguments to this function are extra arguments
1110f034231aSEd Maste           m_options.launch_info.GetArguments().AppendArguments(args);
111114f1b3e8SDimitry Andric         } else {
1112f034231aSEd Maste           // We don't have any file yet, so the first argument is our
1113f034231aSEd Maste           // executable, and the rest are program arguments
1114f034231aSEd Maste           const bool first_arg_is_executable = true;
1115f034231aSEd Maste           m_options.launch_info.SetArguments(args, first_arg_is_executable);
1116f034231aSEd Maste         }
1117f034231aSEd Maste       }
1118f034231aSEd Maste 
111914f1b3e8SDimitry Andric       if (m_options.launch_info.GetExecutableFile()) {
11205f29bb8aSDimitry Andric         Debugger &debugger = GetDebugger();
1121f034231aSEd Maste 
11227fa27ce4SDimitry Andric         if (argc == 0) {
11237fa27ce4SDimitry Andric           // If no arguments were given to the command, use target.run-args.
11247fa27ce4SDimitry Andric           Args target_run_args;
11257fa27ce4SDimitry Andric           target->GetRunArguments(target_run_args);
11267fa27ce4SDimitry Andric           m_options.launch_info.GetArguments().AppendArguments(target_run_args);
11277fa27ce4SDimitry Andric         }
1128f034231aSEd Maste 
112914f1b3e8SDimitry Andric         ProcessSP process_sp(platform_sp->DebugProcess(
1130c0981da4SDimitry Andric             m_options.launch_info, debugger, *target, error));
11317fa27ce4SDimitry Andric 
11327fa27ce4SDimitry Andric         if (!process_sp && error.Success()) {
11337fa27ce4SDimitry Andric           result.AppendError("failed to launch or debug process");
1134b1c73532SDimitry Andric           return;
11357fa27ce4SDimitry Andric         } else if (!error.Success()) {
11367fa27ce4SDimitry Andric           result.AppendError(error.AsCString());
1137b1c73532SDimitry Andric           return;
11387fa27ce4SDimitry Andric         }
11397fa27ce4SDimitry Andric 
11407fa27ce4SDimitry Andric         const bool synchronous_execution =
11417fa27ce4SDimitry Andric             debugger.GetCommandInterpreter().GetSynchronous();
11427fa27ce4SDimitry Andric         auto launch_info = m_options.launch_info;
11437fa27ce4SDimitry Andric         bool rebroadcast_first_stop =
11447fa27ce4SDimitry Andric             !synchronous_execution &&
11457fa27ce4SDimitry Andric             launch_info.GetFlags().Test(eLaunchFlagStopAtEntry);
11467fa27ce4SDimitry Andric 
11477fa27ce4SDimitry Andric         EventSP first_stop_event_sp;
11487fa27ce4SDimitry Andric         StateType state = process_sp->WaitForProcessToStop(
11497fa27ce4SDimitry Andric             std::nullopt, &first_stop_event_sp, rebroadcast_first_stop,
11507fa27ce4SDimitry Andric             launch_info.GetHijackListener());
11517fa27ce4SDimitry Andric         process_sp->RestoreProcessEvents();
11527fa27ce4SDimitry Andric 
11537fa27ce4SDimitry Andric         if (rebroadcast_first_stop) {
11547fa27ce4SDimitry Andric           assert(first_stop_event_sp);
11557fa27ce4SDimitry Andric           process_sp->BroadcastEvent(first_stop_event_sp);
1156b1c73532SDimitry Andric           return;
11577fa27ce4SDimitry Andric         }
11587fa27ce4SDimitry Andric 
11597fa27ce4SDimitry Andric         switch (state) {
11607fa27ce4SDimitry Andric         case eStateStopped: {
11617fa27ce4SDimitry Andric           if (launch_info.GetFlags().Test(eLaunchFlagStopAtEntry))
11627fa27ce4SDimitry Andric             break;
11637fa27ce4SDimitry Andric           if (synchronous_execution) {
11647fa27ce4SDimitry Andric             // Now we have handled the stop-from-attach, and we are just
11657fa27ce4SDimitry Andric             // switching to a synchronous resume.  So we should switch to the
11667fa27ce4SDimitry Andric             // SyncResume hijacker.
11677fa27ce4SDimitry Andric             process_sp->ResumeSynchronous(&result.GetOutputStream());
11687fa27ce4SDimitry Andric           } else {
11697fa27ce4SDimitry Andric             error = process_sp->Resume();
11707fa27ce4SDimitry Andric             if (!error.Success()) {
11717fa27ce4SDimitry Andric               result.AppendErrorWithFormat(
11727fa27ce4SDimitry Andric                   "process resume at entry point failed: %s",
11737fa27ce4SDimitry Andric                   error.AsCString());
11747fa27ce4SDimitry Andric             }
11757fa27ce4SDimitry Andric           }
11767fa27ce4SDimitry Andric         } break;
11777fa27ce4SDimitry Andric         default:
11787fa27ce4SDimitry Andric           result.AppendErrorWithFormat(
11797fa27ce4SDimitry Andric               "initial process state wasn't stopped: %s",
11807fa27ce4SDimitry Andric               StateAsCString(state));
11817fa27ce4SDimitry Andric           break;
11827fa27ce4SDimitry Andric         }
11837fa27ce4SDimitry Andric 
118414f1b3e8SDimitry Andric         if (process_sp && process_sp->IsAlive()) {
1185f034231aSEd Maste           result.SetStatus(eReturnStatusSuccessFinishNoResult);
1186b1c73532SDimitry Andric           return;
1187f034231aSEd Maste         }
118814f1b3e8SDimitry Andric       } else {
118914f1b3e8SDimitry Andric         result.AppendError("'platform process launch' uses the current target "
119014f1b3e8SDimitry Andric                            "file and arguments, or the executable and its "
119114f1b3e8SDimitry Andric                            "arguments can be specified in this command");
1192b1c73532SDimitry Andric         return;
1193f034231aSEd Maste       }
119414f1b3e8SDimitry Andric     } else {
1195f034231aSEd Maste       result.AppendError("no platform is selected\n");
1196f034231aSEd Maste     }
1197f034231aSEd Maste   }
1198f034231aSEd Maste 
1199b60736ecSDimitry Andric   CommandOptionsProcessLaunch m_options;
12007fa27ce4SDimitry Andric   OptionGroupPythonClassWithDict m_class_options;
1201344a3780SDimitry Andric   OptionGroupOptions m_all_options;
1202f034231aSEd Maste };
1203f034231aSEd Maste 
1204f034231aSEd Maste // "platform process list"
1205f034231aSEd Maste 
1206ead24645SDimitry Andric static PosixPlatformCommandOptionValidator posix_validator;
1207ead24645SDimitry Andric #define LLDB_OPTIONS_platform_process_list
1208ead24645SDimitry Andric #include "CommandOptions.inc"
120914f1b3e8SDimitry Andric 
121014f1b3e8SDimitry Andric class CommandObjectPlatformProcessList : public CommandObjectParsed {
121114f1b3e8SDimitry Andric public:
CommandObjectPlatformProcessList(CommandInterpreter & interpreter)121214f1b3e8SDimitry Andric   CommandObjectPlatformProcessList(CommandInterpreter &interpreter)
121314f1b3e8SDimitry Andric       : CommandObjectParsed(interpreter, "platform process list",
121414f1b3e8SDimitry Andric                             "List processes on a remote platform by name, pid, "
121514f1b3e8SDimitry Andric                             "or many other matching attributes.",
12166f8fc217SDimitry Andric                             "platform process list", 0) {}
121714f1b3e8SDimitry Andric 
121814f1b3e8SDimitry Andric   ~CommandObjectPlatformProcessList() override = default;
121914f1b3e8SDimitry Andric 
GetOptions()122014f1b3e8SDimitry Andric   Options *GetOptions() override { return &m_options; }
122114f1b3e8SDimitry Andric 
122214f1b3e8SDimitry Andric protected:
DoExecute(Args & args,CommandReturnObject & result)1223b1c73532SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
12245f29bb8aSDimitry Andric     Target *target = GetDebugger().GetSelectedTarget().get();
122514f1b3e8SDimitry Andric     PlatformSP platform_sp;
122614f1b3e8SDimitry Andric     if (target) {
122714f1b3e8SDimitry Andric       platform_sp = target->GetPlatform();
122814f1b3e8SDimitry Andric     }
122914f1b3e8SDimitry Andric     if (!platform_sp) {
12305f29bb8aSDimitry Andric       platform_sp = GetDebugger().GetPlatformList().GetSelectedPlatform();
123114f1b3e8SDimitry Andric     }
123214f1b3e8SDimitry Andric 
123314f1b3e8SDimitry Andric     if (platform_sp) {
1234b76161e4SDimitry Andric       Status error;
123514f1b3e8SDimitry Andric       if (platform_sp) {
123614f1b3e8SDimitry Andric         Stream &ostrm = result.GetOutputStream();
123714f1b3e8SDimitry Andric 
1238145449b1SDimitry Andric         lldb::pid_t pid = m_options.match_info.GetProcessInfo().GetProcessID();
123914f1b3e8SDimitry Andric         if (pid != LLDB_INVALID_PROCESS_ID) {
124014f1b3e8SDimitry Andric           ProcessInstanceInfo proc_info;
124114f1b3e8SDimitry Andric           if (platform_sp->GetProcessInfo(pid, proc_info)) {
12425f29bb8aSDimitry Andric             ProcessInstanceInfo::DumpTableHeader(ostrm, m_options.show_args,
124314f1b3e8SDimitry Andric                                                  m_options.verbose);
12445f29bb8aSDimitry Andric             proc_info.DumpAsTableRow(ostrm, platform_sp->GetUserIDResolver(),
124514f1b3e8SDimitry Andric                                      m_options.show_args, m_options.verbose);
124614f1b3e8SDimitry Andric             result.SetStatus(eReturnStatusSuccessFinishResult);
124714f1b3e8SDimitry Andric           } else {
124814f1b3e8SDimitry Andric             result.AppendErrorWithFormat(
124914f1b3e8SDimitry Andric                 "no process found with pid = %" PRIu64 "\n", pid);
125014f1b3e8SDimitry Andric           }
125114f1b3e8SDimitry Andric         } else {
125214f1b3e8SDimitry Andric           ProcessInstanceInfoList proc_infos;
125314f1b3e8SDimitry Andric           const uint32_t matches =
125414f1b3e8SDimitry Andric               platform_sp->FindProcesses(m_options.match_info, proc_infos);
125514f1b3e8SDimitry Andric           const char *match_desc = nullptr;
125614f1b3e8SDimitry Andric           const char *match_name =
125714f1b3e8SDimitry Andric               m_options.match_info.GetProcessInfo().GetName();
125814f1b3e8SDimitry Andric           if (match_name && match_name[0]) {
125914f1b3e8SDimitry Andric             switch (m_options.match_info.GetNameMatchType()) {
126074a628f7SDimitry Andric             case NameMatch::Ignore:
126114f1b3e8SDimitry Andric               break;
126274a628f7SDimitry Andric             case NameMatch::Equals:
126314f1b3e8SDimitry Andric               match_desc = "matched";
126414f1b3e8SDimitry Andric               break;
126574a628f7SDimitry Andric             case NameMatch::Contains:
126614f1b3e8SDimitry Andric               match_desc = "contained";
126714f1b3e8SDimitry Andric               break;
126874a628f7SDimitry Andric             case NameMatch::StartsWith:
126914f1b3e8SDimitry Andric               match_desc = "started with";
127014f1b3e8SDimitry Andric               break;
127174a628f7SDimitry Andric             case NameMatch::EndsWith:
127214f1b3e8SDimitry Andric               match_desc = "ended with";
127314f1b3e8SDimitry Andric               break;
127474a628f7SDimitry Andric             case NameMatch::RegularExpression:
127514f1b3e8SDimitry Andric               match_desc = "matched the regular expression";
127614f1b3e8SDimitry Andric               break;
127714f1b3e8SDimitry Andric             }
127814f1b3e8SDimitry Andric           }
127914f1b3e8SDimitry Andric 
128014f1b3e8SDimitry Andric           if (matches == 0) {
128114f1b3e8SDimitry Andric             if (match_desc)
1282c0981da4SDimitry Andric               result.AppendErrorWithFormatv(
1283c0981da4SDimitry Andric                   "no processes were found that {0} \"{1}\" on the \"{2}\" "
128414f1b3e8SDimitry Andric                   "platform\n",
1285145449b1SDimitry Andric                   match_desc, match_name, platform_sp->GetName());
128614f1b3e8SDimitry Andric             else
1287c0981da4SDimitry Andric               result.AppendErrorWithFormatv(
1288c0981da4SDimitry Andric                   "no processes were found on the \"{0}\" platform\n",
1289145449b1SDimitry Andric                   platform_sp->GetName());
129014f1b3e8SDimitry Andric           } else {
1291145449b1SDimitry Andric             result.AppendMessageWithFormatv(
1292145449b1SDimitry Andric                 "{0} matching process{1} found on \"{2}\"", matches,
1293145449b1SDimitry Andric                 matches > 1 ? "es were" : " was", platform_sp->GetName());
129414f1b3e8SDimitry Andric             if (match_desc)
129514f1b3e8SDimitry Andric               result.AppendMessageWithFormat(" whose name %s \"%s\"",
129614f1b3e8SDimitry Andric                                              match_desc, match_name);
129714f1b3e8SDimitry Andric             result.AppendMessageWithFormat("\n");
12985f29bb8aSDimitry Andric             ProcessInstanceInfo::DumpTableHeader(ostrm, m_options.show_args,
129914f1b3e8SDimitry Andric                                                  m_options.verbose);
130014f1b3e8SDimitry Andric             for (uint32_t i = 0; i < matches; ++i) {
1301cfca06d7SDimitry Andric               proc_infos[i].DumpAsTableRow(
1302145449b1SDimitry Andric                   ostrm, platform_sp->GetUserIDResolver(), m_options.show_args,
1303145449b1SDimitry Andric                   m_options.verbose);
130414f1b3e8SDimitry Andric             }
130514f1b3e8SDimitry Andric           }
130614f1b3e8SDimitry Andric         }
130714f1b3e8SDimitry Andric       }
130814f1b3e8SDimitry Andric     } else {
130914f1b3e8SDimitry Andric       result.AppendError("no platform is selected\n");
131014f1b3e8SDimitry Andric     }
131114f1b3e8SDimitry Andric   }
131214f1b3e8SDimitry Andric 
131314f1b3e8SDimitry Andric   class CommandOptions : public Options {
131414f1b3e8SDimitry Andric   public:
1315145449b1SDimitry Andric     CommandOptions() = default;
131614f1b3e8SDimitry Andric 
131714f1b3e8SDimitry Andric     ~CommandOptions() override = default;
131814f1b3e8SDimitry Andric 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)1319b76161e4SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
132014f1b3e8SDimitry Andric                           ExecutionContext *execution_context) override {
1321b76161e4SDimitry Andric       Status error;
132214f1b3e8SDimitry Andric       const int short_option = m_getopt_table[option_idx].val;
132314f1b3e8SDimitry Andric       bool success = false;
132414f1b3e8SDimitry Andric 
132514f1b3e8SDimitry Andric       uint32_t id = LLDB_INVALID_PROCESS_ID;
132614f1b3e8SDimitry Andric       success = !option_arg.getAsInteger(0, id);
132714f1b3e8SDimitry Andric       switch (short_option) {
132814f1b3e8SDimitry Andric       case 'p': {
132914f1b3e8SDimitry Andric         match_info.GetProcessInfo().SetProcessID(id);
133014f1b3e8SDimitry Andric         if (!success)
133114f1b3e8SDimitry Andric           error.SetErrorStringWithFormat("invalid process ID string: '%s'",
133214f1b3e8SDimitry Andric                                          option_arg.str().c_str());
133314f1b3e8SDimitry Andric         break;
133414f1b3e8SDimitry Andric       }
133514f1b3e8SDimitry Andric       case 'P':
133614f1b3e8SDimitry Andric         match_info.GetProcessInfo().SetParentProcessID(id);
133714f1b3e8SDimitry Andric         if (!success)
133814f1b3e8SDimitry Andric           error.SetErrorStringWithFormat(
133914f1b3e8SDimitry Andric               "invalid parent process ID string: '%s'",
134014f1b3e8SDimitry Andric               option_arg.str().c_str());
134114f1b3e8SDimitry Andric         break;
134214f1b3e8SDimitry Andric 
134314f1b3e8SDimitry Andric       case 'u':
134414f1b3e8SDimitry Andric         match_info.GetProcessInfo().SetUserID(success ? id : UINT32_MAX);
134514f1b3e8SDimitry Andric         if (!success)
134614f1b3e8SDimitry Andric           error.SetErrorStringWithFormat("invalid user ID string: '%s'",
134714f1b3e8SDimitry Andric                                          option_arg.str().c_str());
134814f1b3e8SDimitry Andric         break;
134914f1b3e8SDimitry Andric 
135014f1b3e8SDimitry Andric       case 'U':
135114f1b3e8SDimitry Andric         match_info.GetProcessInfo().SetEffectiveUserID(success ? id
135214f1b3e8SDimitry Andric                                                                : UINT32_MAX);
135314f1b3e8SDimitry Andric         if (!success)
135414f1b3e8SDimitry Andric           error.SetErrorStringWithFormat(
135514f1b3e8SDimitry Andric               "invalid effective user ID string: '%s'",
135614f1b3e8SDimitry Andric               option_arg.str().c_str());
135714f1b3e8SDimitry Andric         break;
135814f1b3e8SDimitry Andric 
135914f1b3e8SDimitry Andric       case 'g':
136014f1b3e8SDimitry Andric         match_info.GetProcessInfo().SetGroupID(success ? id : UINT32_MAX);
136114f1b3e8SDimitry Andric         if (!success)
136214f1b3e8SDimitry Andric           error.SetErrorStringWithFormat("invalid group ID string: '%s'",
136314f1b3e8SDimitry Andric                                          option_arg.str().c_str());
136414f1b3e8SDimitry Andric         break;
136514f1b3e8SDimitry Andric 
136614f1b3e8SDimitry Andric       case 'G':
136714f1b3e8SDimitry Andric         match_info.GetProcessInfo().SetEffectiveGroupID(success ? id
136814f1b3e8SDimitry Andric                                                                 : UINT32_MAX);
136914f1b3e8SDimitry Andric         if (!success)
137014f1b3e8SDimitry Andric           error.SetErrorStringWithFormat(
137114f1b3e8SDimitry Andric               "invalid effective group ID string: '%s'",
137214f1b3e8SDimitry Andric               option_arg.str().c_str());
137314f1b3e8SDimitry Andric         break;
137414f1b3e8SDimitry Andric 
137514f1b3e8SDimitry Andric       case 'a': {
137614f1b3e8SDimitry Andric         TargetSP target_sp =
137714f1b3e8SDimitry Andric             execution_context ? execution_context->GetTargetSP() : TargetSP();
137814f1b3e8SDimitry Andric         DebuggerSP debugger_sp =
137914f1b3e8SDimitry Andric             target_sp ? target_sp->GetDebugger().shared_from_this()
138014f1b3e8SDimitry Andric                       : DebuggerSP();
138114f1b3e8SDimitry Andric         PlatformSP platform_sp =
138214f1b3e8SDimitry Andric             debugger_sp ? debugger_sp->GetPlatformList().GetSelectedPlatform()
138314f1b3e8SDimitry Andric                         : PlatformSP();
1384ef5d0b5eSDimitry Andric         match_info.GetProcessInfo().GetArchitecture() =
1385ef5d0b5eSDimitry Andric             Platform::GetAugmentedArchSpec(platform_sp.get(), option_arg);
138614f1b3e8SDimitry Andric       } break;
138714f1b3e8SDimitry Andric 
138814f1b3e8SDimitry Andric       case 'n':
1389f73363f1SDimitry Andric         match_info.GetProcessInfo().GetExecutableFile().SetFile(
139094994d37SDimitry Andric             option_arg, FileSpec::Style::native);
139174a628f7SDimitry Andric         match_info.SetNameMatchType(NameMatch::Equals);
139214f1b3e8SDimitry Andric         break;
139314f1b3e8SDimitry Andric 
139414f1b3e8SDimitry Andric       case 'e':
1395f73363f1SDimitry Andric         match_info.GetProcessInfo().GetExecutableFile().SetFile(
139694994d37SDimitry Andric             option_arg, FileSpec::Style::native);
139774a628f7SDimitry Andric         match_info.SetNameMatchType(NameMatch::EndsWith);
139814f1b3e8SDimitry Andric         break;
139914f1b3e8SDimitry Andric 
140014f1b3e8SDimitry Andric       case 's':
1401f73363f1SDimitry Andric         match_info.GetProcessInfo().GetExecutableFile().SetFile(
140294994d37SDimitry Andric             option_arg, FileSpec::Style::native);
140374a628f7SDimitry Andric         match_info.SetNameMatchType(NameMatch::StartsWith);
140414f1b3e8SDimitry Andric         break;
140514f1b3e8SDimitry Andric 
140614f1b3e8SDimitry Andric       case 'c':
1407f73363f1SDimitry Andric         match_info.GetProcessInfo().GetExecutableFile().SetFile(
140894994d37SDimitry Andric             option_arg, FileSpec::Style::native);
140974a628f7SDimitry Andric         match_info.SetNameMatchType(NameMatch::Contains);
141014f1b3e8SDimitry Andric         break;
141114f1b3e8SDimitry Andric 
141214f1b3e8SDimitry Andric       case 'r':
1413f73363f1SDimitry Andric         match_info.GetProcessInfo().GetExecutableFile().SetFile(
141494994d37SDimitry Andric             option_arg, FileSpec::Style::native);
141574a628f7SDimitry Andric         match_info.SetNameMatchType(NameMatch::RegularExpression);
141614f1b3e8SDimitry Andric         break;
141714f1b3e8SDimitry Andric 
141814f1b3e8SDimitry Andric       case 'A':
141914f1b3e8SDimitry Andric         show_args = true;
142014f1b3e8SDimitry Andric         break;
142114f1b3e8SDimitry Andric 
142214f1b3e8SDimitry Andric       case 'v':
142314f1b3e8SDimitry Andric         verbose = true;
142414f1b3e8SDimitry Andric         break;
142514f1b3e8SDimitry Andric 
1426ead24645SDimitry Andric       case 'x':
1427ead24645SDimitry Andric         match_info.SetMatchAllUsers(true);
142814f1b3e8SDimitry Andric         break;
1429ead24645SDimitry Andric 
1430ead24645SDimitry Andric       default:
1431ead24645SDimitry Andric         llvm_unreachable("Unimplemented option");
143214f1b3e8SDimitry Andric       }
143314f1b3e8SDimitry Andric 
143414f1b3e8SDimitry Andric       return error;
143514f1b3e8SDimitry Andric     }
143614f1b3e8SDimitry Andric 
OptionParsingStarting(ExecutionContext * execution_context)143714f1b3e8SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
143814f1b3e8SDimitry Andric       match_info.Clear();
143914f1b3e8SDimitry Andric       show_args = false;
144014f1b3e8SDimitry Andric       verbose = false;
144114f1b3e8SDimitry Andric     }
144214f1b3e8SDimitry Andric 
GetDefinitions()144314f1b3e8SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1444e3b55780SDimitry Andric       return llvm::ArrayRef(g_platform_process_list_options);
144514f1b3e8SDimitry Andric     }
144614f1b3e8SDimitry Andric 
144714f1b3e8SDimitry Andric     // Instance variables to hold the values for command options.
144814f1b3e8SDimitry Andric 
144914f1b3e8SDimitry Andric     ProcessInstanceInfoMatch match_info;
1450344a3780SDimitry Andric     bool show_args = false;
1451344a3780SDimitry Andric     bool verbose = false;
145214f1b3e8SDimitry Andric   };
145314f1b3e8SDimitry Andric 
145414f1b3e8SDimitry Andric   CommandOptions m_options;
1455f034231aSEd Maste };
1456f034231aSEd Maste 
1457f034231aSEd Maste // "platform process info"
145814f1b3e8SDimitry Andric class CommandObjectPlatformProcessInfo : public CommandObjectParsed {
1459f034231aSEd Maste public:
CommandObjectPlatformProcessInfo(CommandInterpreter & interpreter)146014f1b3e8SDimitry Andric   CommandObjectPlatformProcessInfo(CommandInterpreter &interpreter)
146114f1b3e8SDimitry Andric       : CommandObjectParsed(
146214f1b3e8SDimitry Andric             interpreter, "platform process info",
1463f034231aSEd Maste             "Get detailed information for one or more process by process ID.",
146414f1b3e8SDimitry Andric             "platform process info <pid> [<pid> <pid> ...]", 0) {
1465ac9a064cSDimitry Andric     AddSimpleArgumentList(eArgTypePid, eArgRepeatStar);
1466f034231aSEd Maste   }
1467f034231aSEd Maste 
1468f3fbd1c0SDimitry Andric   ~CommandObjectPlatformProcessInfo() override = default;
1469f034231aSEd Maste 
1470f034231aSEd Maste protected:
DoExecute(Args & args,CommandReturnObject & result)1471b1c73532SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
14725f29bb8aSDimitry Andric     Target *target = GetDebugger().GetSelectedTarget().get();
1473f034231aSEd Maste     PlatformSP platform_sp;
147414f1b3e8SDimitry Andric     if (target) {
1475f034231aSEd Maste       platform_sp = target->GetPlatform();
1476f034231aSEd Maste     }
147714f1b3e8SDimitry Andric     if (!platform_sp) {
14785f29bb8aSDimitry Andric       platform_sp = GetDebugger().GetPlatformList().GetSelectedPlatform();
1479f034231aSEd Maste     }
1480f034231aSEd Maste 
148114f1b3e8SDimitry Andric     if (platform_sp) {
1482f034231aSEd Maste       const size_t argc = args.GetArgumentCount();
148314f1b3e8SDimitry Andric       if (argc > 0) {
1484b76161e4SDimitry Andric         Status error;
1485f034231aSEd Maste 
148614f1b3e8SDimitry Andric         if (platform_sp->IsConnected()) {
1487f034231aSEd Maste           Stream &ostrm = result.GetOutputStream();
148814f1b3e8SDimitry Andric           for (auto &entry : args.entries()) {
148914f1b3e8SDimitry Andric             lldb::pid_t pid;
1490ead24645SDimitry Andric             if (entry.ref().getAsInteger(0, pid)) {
149114f1b3e8SDimitry Andric               result.AppendErrorWithFormat("invalid process ID argument '%s'",
1492ead24645SDimitry Andric                                            entry.ref().str().c_str());
149314f1b3e8SDimitry Andric               break;
149414f1b3e8SDimitry Andric             } else {
1495f034231aSEd Maste               ProcessInstanceInfo proc_info;
149614f1b3e8SDimitry Andric               if (platform_sp->GetProcessInfo(pid, proc_info)) {
149714f1b3e8SDimitry Andric                 ostrm.Printf("Process information for process %" PRIu64 ":\n",
149814f1b3e8SDimitry Andric                              pid);
14995f29bb8aSDimitry Andric                 proc_info.Dump(ostrm, platform_sp->GetUserIDResolver());
150014f1b3e8SDimitry Andric               } else {
150114f1b3e8SDimitry Andric                 ostrm.Printf("error: no process information is available for "
150214f1b3e8SDimitry Andric                              "process %" PRIu64 "\n",
150314f1b3e8SDimitry Andric                              pid);
1504f034231aSEd Maste               }
1505f034231aSEd Maste               ostrm.EOL();
1506f034231aSEd Maste             }
1507f034231aSEd Maste           }
150814f1b3e8SDimitry Andric         } else {
1509f034231aSEd Maste           // Not connected...
1510c0981da4SDimitry Andric           result.AppendErrorWithFormatv("not connected to '{0}'",
1511c0981da4SDimitry Andric                                         platform_sp->GetPluginName());
1512f034231aSEd Maste         }
151314f1b3e8SDimitry Andric       } else {
1514f034231aSEd Maste         // No args
1515f034231aSEd Maste         result.AppendError("one or more process id(s) must be specified");
1516f034231aSEd Maste       }
151714f1b3e8SDimitry Andric     } else {
1518f034231aSEd Maste       result.AppendError("no platform is currently selected");
1519f034231aSEd Maste     }
1520f034231aSEd Maste   }
1521f034231aSEd Maste };
1522f034231aSEd Maste 
1523ead24645SDimitry Andric #define LLDB_OPTIONS_platform_process_attach
1524ead24645SDimitry Andric #include "CommandOptions.inc"
152514f1b3e8SDimitry Andric 
152614f1b3e8SDimitry Andric class CommandObjectPlatformProcessAttach : public CommandObjectParsed {
1527f21a844fSEd Maste public:
CommandObjectPlatformProcessAttach(CommandInterpreter & interpreter)152814f1b3e8SDimitry Andric   CommandObjectPlatformProcessAttach(CommandInterpreter &interpreter)
152914f1b3e8SDimitry Andric       : CommandObjectParsed(interpreter, "platform process attach",
1530f21a844fSEd Maste                             "Attach to a process.",
15317fa27ce4SDimitry Andric                             "platform process attach <cmd-options>"),
15327fa27ce4SDimitry Andric         m_class_options("scripted process", true, 'C', 'k', 'v', 0) {
15337fa27ce4SDimitry Andric     m_all_options.Append(&m_options);
15347fa27ce4SDimitry Andric     m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2,
15357fa27ce4SDimitry Andric                          LLDB_OPT_SET_ALL);
15367fa27ce4SDimitry Andric     m_all_options.Finalize();
15377fa27ce4SDimitry Andric   }
1538f21a844fSEd Maste 
1539f3fbd1c0SDimitry Andric   ~CommandObjectPlatformProcessAttach() override = default;
1540f21a844fSEd Maste 
DoExecute(Args & command,CommandReturnObject & result)1541b1c73532SDimitry Andric   void DoExecute(Args &command, CommandReturnObject &result) override {
154214f1b3e8SDimitry Andric     PlatformSP platform_sp(
15435f29bb8aSDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
154414f1b3e8SDimitry Andric     if (platform_sp) {
15457fa27ce4SDimitry Andric 
15467fa27ce4SDimitry Andric       if (!m_class_options.GetName().empty()) {
15477fa27ce4SDimitry Andric         m_options.attach_info.SetProcessPluginName("ScriptedProcess");
15487fa27ce4SDimitry Andric         ScriptedMetadataSP metadata_sp = std::make_shared<ScriptedMetadata>(
15497fa27ce4SDimitry Andric             m_class_options.GetName(), m_class_options.GetStructuredData());
15507fa27ce4SDimitry Andric         m_options.attach_info.SetScriptedMetadata(metadata_sp);
15517fa27ce4SDimitry Andric       }
15527fa27ce4SDimitry Andric 
1553b76161e4SDimitry Andric       Status err;
155414f1b3e8SDimitry Andric       ProcessSP remote_process_sp = platform_sp->Attach(
15555f29bb8aSDimitry Andric           m_options.attach_info, GetDebugger(), nullptr, err);
155614f1b3e8SDimitry Andric       if (err.Fail()) {
1557f21a844fSEd Maste         result.AppendError(err.AsCString());
155814f1b3e8SDimitry Andric       } else if (!remote_process_sp) {
1559f21a844fSEd Maste         result.AppendError("could not attach: unknown reason");
156014f1b3e8SDimitry Andric       } else
1561f21a844fSEd Maste         result.SetStatus(eReturnStatusSuccessFinishResult);
156214f1b3e8SDimitry Andric     } else {
1563f21a844fSEd Maste       result.AppendError("no platform is currently selected");
1564f21a844fSEd Maste     }
1565f21a844fSEd Maste   }
1566f21a844fSEd Maste 
GetOptions()15677fa27ce4SDimitry Andric   Options *GetOptions() override { return &m_all_options; }
1568f21a844fSEd Maste 
1569f21a844fSEd Maste protected:
15707fa27ce4SDimitry Andric   CommandOptionsProcessAttach m_options;
15717fa27ce4SDimitry Andric   OptionGroupPythonClassWithDict m_class_options;
15727fa27ce4SDimitry Andric   OptionGroupOptions m_all_options;
1573f21a844fSEd Maste };
1574f21a844fSEd Maste 
157514f1b3e8SDimitry Andric class CommandObjectPlatformProcess : public CommandObjectMultiword {
1576f034231aSEd Maste public:
1577f034231aSEd Maste   // Constructors and Destructors
CommandObjectPlatformProcess(CommandInterpreter & interpreter)1578f3fbd1c0SDimitry Andric   CommandObjectPlatformProcess(CommandInterpreter &interpreter)
1579f3fbd1c0SDimitry Andric       : CommandObjectMultiword(interpreter, "platform process",
158014f1b3e8SDimitry Andric                                "Commands to query, launch and attach to "
158114f1b3e8SDimitry Andric                                "processes on the current platform.",
158214f1b3e8SDimitry Andric                                "platform process [attach|launch|list] ...") {
158314f1b3e8SDimitry Andric     LoadSubCommand(
158414f1b3e8SDimitry Andric         "attach",
158514f1b3e8SDimitry Andric         CommandObjectSP(new CommandObjectPlatformProcessAttach(interpreter)));
158614f1b3e8SDimitry Andric     LoadSubCommand(
158714f1b3e8SDimitry Andric         "launch",
158814f1b3e8SDimitry Andric         CommandObjectSP(new CommandObjectPlatformProcessLaunch(interpreter)));
158914f1b3e8SDimitry Andric     LoadSubCommand("info", CommandObjectSP(new CommandObjectPlatformProcessInfo(
159014f1b3e8SDimitry Andric                                interpreter)));
159114f1b3e8SDimitry Andric     LoadSubCommand("list", CommandObjectSP(new CommandObjectPlatformProcessList(
159214f1b3e8SDimitry Andric                                interpreter)));
1593f034231aSEd Maste   }
1594f034231aSEd Maste 
1595f3fbd1c0SDimitry Andric   ~CommandObjectPlatformProcess() override = default;
1596f034231aSEd Maste 
1597f034231aSEd Maste private:
1598f034231aSEd Maste   // For CommandObjectPlatform only
1599cfca06d7SDimitry Andric   CommandObjectPlatformProcess(const CommandObjectPlatformProcess &) = delete;
1600cfca06d7SDimitry Andric   const CommandObjectPlatformProcess &
1601cfca06d7SDimitry Andric   operator=(const CommandObjectPlatformProcess &) = delete;
1602f034231aSEd Maste };
1603f034231aSEd Maste 
1604f21a844fSEd Maste // "platform shell"
1605ead24645SDimitry Andric #define LLDB_OPTIONS_platform_shell
1606ead24645SDimitry Andric #include "CommandOptions.inc"
160714f1b3e8SDimitry Andric 
160814f1b3e8SDimitry Andric class CommandObjectPlatformShell : public CommandObjectRaw {
1609f034231aSEd Maste public:
161014f1b3e8SDimitry Andric   class CommandOptions : public Options {
1611f21a844fSEd Maste   public:
1612145449b1SDimitry Andric     CommandOptions() = default;
1613f21a844fSEd Maste 
1614f3fbd1c0SDimitry Andric     ~CommandOptions() override = default;
1615f21a844fSEd Maste 
GetDefinitions()161614f1b3e8SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1617e3b55780SDimitry Andric       return llvm::ArrayRef(g_platform_shell_options);
1618f21a844fSEd Maste     }
1619f21a844fSEd Maste 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)1620b76161e4SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
162114f1b3e8SDimitry Andric                           ExecutionContext *execution_context) override {
1622b76161e4SDimitry Andric       Status error;
1623f21a844fSEd Maste 
162414f1b3e8SDimitry Andric       const char short_option = (char)GetDefinitions()[option_idx].short_option;
1625f21a844fSEd Maste 
162614f1b3e8SDimitry Andric       switch (short_option) {
1627cfca06d7SDimitry Andric       case 'h':
1628cfca06d7SDimitry Andric         m_use_host_platform = true;
1629cfca06d7SDimitry Andric         break;
1630f21a844fSEd Maste       case 't':
1631f73363f1SDimitry Andric         uint32_t timeout_sec;
1632f73363f1SDimitry Andric         if (option_arg.getAsInteger(10, timeout_sec))
163314f1b3e8SDimitry Andric           error.SetErrorStringWithFormat(
163414f1b3e8SDimitry Andric               "could not convert \"%s\" to a numeric value.",
163514f1b3e8SDimitry Andric               option_arg.str().c_str());
1636f73363f1SDimitry Andric         else
1637cfca06d7SDimitry Andric           m_timeout = std::chrono::seconds(timeout_sec);
1638f21a844fSEd Maste         break;
1639b60736ecSDimitry Andric       case 's': {
1640b60736ecSDimitry Andric         if (option_arg.empty()) {
1641b60736ecSDimitry Andric           error.SetErrorStringWithFormat(
1642b60736ecSDimitry Andric               "missing shell interpreter path for option -i|--interpreter.");
1643b60736ecSDimitry Andric           return error;
1644b60736ecSDimitry Andric         }
1645b60736ecSDimitry Andric 
1646b60736ecSDimitry Andric         m_shell_interpreter = option_arg.str();
1647b60736ecSDimitry Andric         break;
1648b60736ecSDimitry Andric       }
1649f21a844fSEd Maste       default:
1650ead24645SDimitry Andric         llvm_unreachable("Unimplemented option");
1651f21a844fSEd Maste       }
1652f21a844fSEd Maste 
1653f21a844fSEd Maste       return error;
1654f21a844fSEd Maste     }
1655f21a844fSEd Maste 
OptionParsingStarting(ExecutionContext * execution_context)1656cfca06d7SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
1657cfca06d7SDimitry Andric       m_timeout.reset();
1658cfca06d7SDimitry Andric       m_use_host_platform = false;
1659b60736ecSDimitry Andric       m_shell_interpreter.clear();
1660cfca06d7SDimitry Andric     }
1661f21a844fSEd Maste 
1662cfca06d7SDimitry Andric     Timeout<std::micro> m_timeout = std::chrono::seconds(10);
1663cfca06d7SDimitry Andric     bool m_use_host_platform;
1664b60736ecSDimitry Andric     std::string m_shell_interpreter;
1665f21a844fSEd Maste   };
1666f21a844fSEd Maste 
CommandObjectPlatformShell(CommandInterpreter & interpreter)1667f3fbd1c0SDimitry Andric   CommandObjectPlatformShell(CommandInterpreter &interpreter)
166814f1b3e8SDimitry Andric       : CommandObjectRaw(interpreter, "platform shell",
166914f1b3e8SDimitry Andric                          "Run a shell command on the current platform.",
1670145449b1SDimitry Andric                          "platform shell <shell-command>", 0) {
1671ac9a064cSDimitry Andric     AddSimpleArgumentList(eArgTypeNone, eArgRepeatStar);
1672145449b1SDimitry Andric   }
1673f034231aSEd Maste 
1674f3fbd1c0SDimitry Andric   ~CommandObjectPlatformShell() override = default;
1675f034231aSEd Maste 
GetOptions()167614f1b3e8SDimitry Andric   Options *GetOptions() override { return &m_options; }
1677f21a844fSEd Maste 
DoExecute(llvm::StringRef raw_command_line,CommandReturnObject & result)1678b1c73532SDimitry Andric   void DoExecute(llvm::StringRef raw_command_line,
167914f1b3e8SDimitry Andric                  CommandReturnObject &result) override {
168014f1b3e8SDimitry Andric     ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext();
168114f1b3e8SDimitry Andric     m_options.NotifyOptionParsingStarting(&exe_ctx);
1682f21a844fSEd Maste 
1683f21a844fSEd Maste     // Print out an usage syntax on an empty command line.
1684f73363f1SDimitry Andric     if (raw_command_line.empty()) {
168514f1b3e8SDimitry Andric       result.GetOutputStream().Printf("%s\n", this->GetSyntax().str().c_str());
1686b1c73532SDimitry Andric       return;
1687f21a844fSEd Maste     }
1688f21a844fSEd Maste 
1689cfca06d7SDimitry Andric     const bool is_alias = !raw_command_line.contains("platform");
1690f73363f1SDimitry Andric     OptionsWithRaw args(raw_command_line);
1691f21a844fSEd Maste 
1692f73363f1SDimitry Andric     if (args.HasArgs())
1693f73363f1SDimitry Andric       if (!ParseOptions(args.GetArgs(), result))
1694b1c73532SDimitry Andric         return;
1695f21a844fSEd Maste 
1696cfca06d7SDimitry Andric     if (args.GetRawPart().empty()) {
1697cfca06d7SDimitry Andric       result.GetOutputStream().Printf("%s <shell-command>\n",
1698cfca06d7SDimitry Andric                                       is_alias ? "shell" : "platform shell");
1699b1c73532SDimitry Andric       return;
1700cfca06d7SDimitry Andric     }
1701cfca06d7SDimitry Andric 
1702b60736ecSDimitry Andric     llvm::StringRef cmd = args.GetRawPart();
1703b60736ecSDimitry Andric 
170414f1b3e8SDimitry Andric     PlatformSP platform_sp(
1705cfca06d7SDimitry Andric         m_options.m_use_host_platform
1706cfca06d7SDimitry Andric             ? Platform::GetHostPlatform()
1707cfca06d7SDimitry Andric             : GetDebugger().GetPlatformList().GetSelectedPlatform());
1708b76161e4SDimitry Andric     Status error;
170914f1b3e8SDimitry Andric     if (platform_sp) {
17105e95aa85SEd Maste       FileSpec working_dir{};
1711f034231aSEd Maste       std::string output;
1712f034231aSEd Maste       int status = -1;
1713f034231aSEd Maste       int signo = -1;
1714b60736ecSDimitry Andric       error = (platform_sp->RunShellCommand(m_options.m_shell_interpreter, cmd,
1715b60736ecSDimitry Andric                                             working_dir, &status, &signo,
1716cfca06d7SDimitry Andric                                             &output, m_options.m_timeout));
1717f034231aSEd Maste       if (!output.empty())
171814f1b3e8SDimitry Andric         result.GetOutputStream().PutCString(output);
171914f1b3e8SDimitry Andric       if (status > 0) {
172014f1b3e8SDimitry Andric         if (signo > 0) {
1721f034231aSEd Maste           const char *signo_cstr = Host::GetSignalAsCString(signo);
1722f034231aSEd Maste           if (signo_cstr)
172314f1b3e8SDimitry Andric             result.GetOutputStream().Printf(
172414f1b3e8SDimitry Andric                 "error: command returned with status %i and signal %s\n",
172514f1b3e8SDimitry Andric                 status, signo_cstr);
1726f034231aSEd Maste           else
172714f1b3e8SDimitry Andric             result.GetOutputStream().Printf(
172814f1b3e8SDimitry Andric                 "error: command returned with status %i and signal %i\n",
172914f1b3e8SDimitry Andric                 status, signo);
173014f1b3e8SDimitry Andric         } else
173114f1b3e8SDimitry Andric           result.GetOutputStream().Printf(
173214f1b3e8SDimitry Andric               "error: command returned with status %i\n", status);
1733f034231aSEd Maste       }
173414f1b3e8SDimitry Andric     } else {
173514f1b3e8SDimitry Andric       result.GetOutputStream().Printf(
173614f1b3e8SDimitry Andric           "error: cannot run remote shell commands without a platform\n");
173714f1b3e8SDimitry Andric       error.SetErrorString(
173814f1b3e8SDimitry Andric           "error: cannot run remote shell commands without a platform");
1739f21a844fSEd Maste     }
1740f034231aSEd Maste 
174114f1b3e8SDimitry Andric     if (error.Fail()) {
1742f034231aSEd Maste       result.AppendError(error.AsCString());
174314f1b3e8SDimitry Andric     } else {
1744f034231aSEd Maste       result.SetStatus(eReturnStatusSuccessFinishResult);
1745f034231aSEd Maste     }
1746f034231aSEd Maste   }
1747f3fbd1c0SDimitry Andric 
1748f21a844fSEd Maste   CommandOptions m_options;
1749f21a844fSEd Maste };
1750f21a844fSEd Maste 
1751f21a844fSEd Maste // "platform install" - install a target to a remote end
175214f1b3e8SDimitry Andric class CommandObjectPlatformInstall : public CommandObjectParsed {
1753f21a844fSEd Maste public:
CommandObjectPlatformInstall(CommandInterpreter & interpreter)175414f1b3e8SDimitry Andric   CommandObjectPlatformInstall(CommandInterpreter &interpreter)
175514f1b3e8SDimitry Andric       : CommandObjectParsed(
175614f1b3e8SDimitry Andric             interpreter, "platform target-install",
1757f21a844fSEd Maste             "Install a target (bundle or executable file) to the remote end.",
1758145449b1SDimitry Andric             "platform target-install <local-thing> <remote-sandbox>", 0) {
1759145449b1SDimitry Andric     CommandArgumentData local_arg{eArgTypePath, eArgRepeatPlain};
1760ac9a064cSDimitry Andric     CommandArgumentData remote_arg{eArgTypeRemotePath, eArgRepeatPlain};
1761145449b1SDimitry Andric     m_arguments.push_back({local_arg});
1762145449b1SDimitry Andric     m_arguments.push_back({remote_arg});
1763145449b1SDimitry Andric   }
1764f21a844fSEd Maste 
1765f3fbd1c0SDimitry Andric   ~CommandObjectPlatformInstall() override = default;
1766f21a844fSEd Maste 
1767b60736ecSDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)1768b60736ecSDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
1769b60736ecSDimitry Andric                            OptionElementVector &opt_element_vector) override {
1770b60736ecSDimitry Andric     if (request.GetCursorIndex())
1771b60736ecSDimitry Andric       return;
17727fa27ce4SDimitry Andric     lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
17737fa27ce4SDimitry Andric         GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr);
1774b60736ecSDimitry Andric   }
1775b60736ecSDimitry Andric 
DoExecute(Args & args,CommandReturnObject & result)1776b1c73532SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
177714f1b3e8SDimitry Andric     if (args.GetArgumentCount() != 2) {
1778f21a844fSEd Maste       result.AppendError("platform target-install takes two arguments");
1779b1c73532SDimitry Andric       return;
1780f21a844fSEd Maste     }
1781f21a844fSEd Maste     // TODO: move the bulk of this code over to the platform itself
178294994d37SDimitry Andric     FileSpec src(args.GetArgumentAtIndex(0));
178394994d37SDimitry Andric     FileSystem::Instance().Resolve(src);
178494994d37SDimitry Andric     FileSpec dst(args.GetArgumentAtIndex(1));
178594994d37SDimitry Andric     if (!FileSystem::Instance().Exists(src)) {
1786f21a844fSEd Maste       result.AppendError("source location does not exist or is not accessible");
1787b1c73532SDimitry Andric       return;
1788f21a844fSEd Maste     }
178914f1b3e8SDimitry Andric     PlatformSP platform_sp(
17905f29bb8aSDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
179114f1b3e8SDimitry Andric     if (!platform_sp) {
1792f21a844fSEd Maste       result.AppendError("no platform currently selected");
1793b1c73532SDimitry Andric       return;
1794f21a844fSEd Maste     }
179586758c71SEd Maste 
1796b76161e4SDimitry Andric     Status error = platform_sp->Install(src, dst);
179714f1b3e8SDimitry Andric     if (error.Success()) {
1798f21a844fSEd Maste       result.SetStatus(eReturnStatusSuccessFinishNoResult);
179914f1b3e8SDimitry Andric     } else {
180086758c71SEd Maste       result.AppendErrorWithFormat("install failed: %s", error.AsCString());
1801f21a844fSEd Maste     }
1802f21a844fSEd Maste   }
1803f034231aSEd Maste };
1804f034231aSEd Maste 
CommandObjectPlatform(CommandInterpreter & interpreter)1805f3fbd1c0SDimitry Andric CommandObjectPlatform::CommandObjectPlatform(CommandInterpreter &interpreter)
180614f1b3e8SDimitry Andric     : CommandObjectMultiword(
180714f1b3e8SDimitry Andric           interpreter, "platform", "Commands to manage and create platforms.",
180814f1b3e8SDimitry Andric           "platform [connect|disconnect|info|list|status|select] ...") {
180914f1b3e8SDimitry Andric   LoadSubCommand("select",
181014f1b3e8SDimitry Andric                  CommandObjectSP(new CommandObjectPlatformSelect(interpreter)));
181114f1b3e8SDimitry Andric   LoadSubCommand("list",
181214f1b3e8SDimitry Andric                  CommandObjectSP(new CommandObjectPlatformList(interpreter)));
181314f1b3e8SDimitry Andric   LoadSubCommand("status",
181414f1b3e8SDimitry Andric                  CommandObjectSP(new CommandObjectPlatformStatus(interpreter)));
181514f1b3e8SDimitry Andric   LoadSubCommand("connect", CommandObjectSP(
181614f1b3e8SDimitry Andric                                 new CommandObjectPlatformConnect(interpreter)));
181714f1b3e8SDimitry Andric   LoadSubCommand(
181814f1b3e8SDimitry Andric       "disconnect",
181914f1b3e8SDimitry Andric       CommandObjectSP(new CommandObjectPlatformDisconnect(interpreter)));
182014f1b3e8SDimitry Andric   LoadSubCommand("settings", CommandObjectSP(new CommandObjectPlatformSettings(
182114f1b3e8SDimitry Andric                                  interpreter)));
182214f1b3e8SDimitry Andric   LoadSubCommand("mkdir",
182314f1b3e8SDimitry Andric                  CommandObjectSP(new CommandObjectPlatformMkDir(interpreter)));
182414f1b3e8SDimitry Andric   LoadSubCommand("file",
182514f1b3e8SDimitry Andric                  CommandObjectSP(new CommandObjectPlatformFile(interpreter)));
1826c0981da4SDimitry Andric   LoadSubCommand("file-exists",
1827c0981da4SDimitry Andric       CommandObjectSP(new CommandObjectPlatformFileExists(interpreter)));
182814f1b3e8SDimitry Andric   LoadSubCommand("get-file", CommandObjectSP(new CommandObjectPlatformGetFile(
182914f1b3e8SDimitry Andric                                  interpreter)));
1830c0981da4SDimitry Andric   LoadSubCommand("get-permissions",
1831c0981da4SDimitry Andric       CommandObjectSP(new CommandObjectPlatformGetPermissions(interpreter)));
183214f1b3e8SDimitry Andric   LoadSubCommand("get-size", CommandObjectSP(new CommandObjectPlatformGetSize(
183314f1b3e8SDimitry Andric                                  interpreter)));
183414f1b3e8SDimitry Andric   LoadSubCommand("put-file", CommandObjectSP(new CommandObjectPlatformPutFile(
183514f1b3e8SDimitry Andric                                  interpreter)));
183614f1b3e8SDimitry Andric   LoadSubCommand("process", CommandObjectSP(
183714f1b3e8SDimitry Andric                                 new CommandObjectPlatformProcess(interpreter)));
183814f1b3e8SDimitry Andric   LoadSubCommand("shell",
183914f1b3e8SDimitry Andric                  CommandObjectSP(new CommandObjectPlatformShell(interpreter)));
184014f1b3e8SDimitry Andric   LoadSubCommand(
184114f1b3e8SDimitry Andric       "target-install",
184214f1b3e8SDimitry Andric       CommandObjectSP(new CommandObjectPlatformInstall(interpreter)));
1843f034231aSEd Maste }
1844f034231aSEd Maste 
1845f3fbd1c0SDimitry Andric CommandObjectPlatform::~CommandObjectPlatform() = default;
1846