xref: /freebsd-src/contrib/llvm-project/lldb/source/Commands/CommandObjectPlatform.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
15ffd83dbSDimitry Andric //===-- CommandObjectPlatform.cpp -----------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "CommandObjectPlatform.h"
1006c3fb27SDimitry Andric #include "CommandOptionsProcessAttach.h"
11e8d8bef9SDimitry Andric #include "CommandOptionsProcessLaunch.h"
120b57cec5SDimitry Andric #include "lldb/Core/Debugger.h"
130b57cec5SDimitry Andric #include "lldb/Core/Module.h"
140b57cec5SDimitry Andric #include "lldb/Core/PluginManager.h"
150b57cec5SDimitry Andric #include "lldb/Host/OptionParser.h"
160b57cec5SDimitry Andric #include "lldb/Interpreter/CommandInterpreter.h"
17fcaf7f86SDimitry Andric #include "lldb/Interpreter/CommandOptionArgumentTable.h"
180b57cec5SDimitry Andric #include "lldb/Interpreter/CommandOptionValidators.h"
190b57cec5SDimitry Andric #include "lldb/Interpreter/CommandReturnObject.h"
200b57cec5SDimitry Andric #include "lldb/Interpreter/OptionGroupFile.h"
210b57cec5SDimitry Andric #include "lldb/Interpreter/OptionGroupPlatform.h"
2206c3fb27SDimitry Andric #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"
230b57cec5SDimitry Andric #include "lldb/Target/ExecutionContext.h"
240b57cec5SDimitry Andric #include "lldb/Target/Platform.h"
250b57cec5SDimitry Andric #include "lldb/Target/Process.h"
260b57cec5SDimitry Andric #include "lldb/Utility/Args.h"
2706c3fb27SDimitry Andric #include "lldb/Utility/ScriptedMetadata.h"
2806c3fb27SDimitry Andric #include "lldb/Utility/State.h"
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric using namespace lldb;
330b57cec5SDimitry Andric using namespace lldb_private;
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric static mode_t ParsePermissionString(const char *) = delete;
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric static mode_t ParsePermissionString(llvm::StringRef permissions) {
380b57cec5SDimitry Andric   if (permissions.size() != 9)
390b57cec5SDimitry Andric     return (mode_t)(-1);
400b57cec5SDimitry Andric   bool user_r, user_w, user_x, group_r, group_w, group_x, world_r, world_w,
410b57cec5SDimitry Andric       world_x;
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric   user_r = (permissions[0] == 'r');
440b57cec5SDimitry Andric   user_w = (permissions[1] == 'w');
450b57cec5SDimitry Andric   user_x = (permissions[2] == 'x');
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric   group_r = (permissions[3] == 'r');
480b57cec5SDimitry Andric   group_w = (permissions[4] == 'w');
490b57cec5SDimitry Andric   group_x = (permissions[5] == 'x');
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric   world_r = (permissions[6] == 'r');
520b57cec5SDimitry Andric   world_w = (permissions[7] == 'w');
530b57cec5SDimitry Andric   world_x = (permissions[8] == 'x');
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric   mode_t user, group, world;
560b57cec5SDimitry Andric   user = (user_r ? 4 : 0) | (user_w ? 2 : 0) | (user_x ? 1 : 0);
570b57cec5SDimitry Andric   group = (group_r ? 4 : 0) | (group_w ? 2 : 0) | (group_x ? 1 : 0);
580b57cec5SDimitry Andric   world = (world_r ? 4 : 0) | (world_w ? 2 : 0) | (world_x ? 1 : 0);
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric   return user | group | world;
610b57cec5SDimitry Andric }
620b57cec5SDimitry Andric 
639dba64beSDimitry Andric #define LLDB_OPTIONS_permissions
649dba64beSDimitry Andric #include "CommandOptions.inc"
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric class OptionPermissions : public OptionGroup {
670b57cec5SDimitry Andric public:
68fe6060f1SDimitry Andric   OptionPermissions() = default;
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric   ~OptionPermissions() override = default;
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric   lldb_private::Status
730b57cec5SDimitry Andric   SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
740b57cec5SDimitry Andric                  ExecutionContext *execution_context) override {
750b57cec5SDimitry Andric     Status error;
760b57cec5SDimitry Andric     char short_option = (char)GetDefinitions()[option_idx].short_option;
770b57cec5SDimitry Andric     switch (short_option) {
780b57cec5SDimitry Andric     case 'v': {
790b57cec5SDimitry Andric       if (option_arg.getAsInteger(8, m_permissions)) {
800b57cec5SDimitry Andric         m_permissions = 0777;
810b57cec5SDimitry Andric         error.SetErrorStringWithFormat("invalid value for permissions: %s",
820b57cec5SDimitry Andric                                        option_arg.str().c_str());
830b57cec5SDimitry Andric       }
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric     } break;
860b57cec5SDimitry Andric     case 's': {
870b57cec5SDimitry Andric       mode_t perms = ParsePermissionString(option_arg);
880b57cec5SDimitry Andric       if (perms == (mode_t)-1)
890b57cec5SDimitry Andric         error.SetErrorStringWithFormat("invalid value for permissions: %s",
900b57cec5SDimitry Andric                                        option_arg.str().c_str());
910b57cec5SDimitry Andric       else
920b57cec5SDimitry Andric         m_permissions = perms;
930b57cec5SDimitry Andric     } break;
940b57cec5SDimitry Andric     case 'r':
950b57cec5SDimitry Andric       m_permissions |= lldb::eFilePermissionsUserRead;
960b57cec5SDimitry Andric       break;
970b57cec5SDimitry Andric     case 'w':
980b57cec5SDimitry Andric       m_permissions |= lldb::eFilePermissionsUserWrite;
990b57cec5SDimitry Andric       break;
1000b57cec5SDimitry Andric     case 'x':
1010b57cec5SDimitry Andric       m_permissions |= lldb::eFilePermissionsUserExecute;
1020b57cec5SDimitry Andric       break;
1030b57cec5SDimitry Andric     case 'R':
1040b57cec5SDimitry Andric       m_permissions |= lldb::eFilePermissionsGroupRead;
1050b57cec5SDimitry Andric       break;
1060b57cec5SDimitry Andric     case 'W':
1070b57cec5SDimitry Andric       m_permissions |= lldb::eFilePermissionsGroupWrite;
1080b57cec5SDimitry Andric       break;
1090b57cec5SDimitry Andric     case 'X':
1100b57cec5SDimitry Andric       m_permissions |= lldb::eFilePermissionsGroupExecute;
1110b57cec5SDimitry Andric       break;
1120b57cec5SDimitry Andric     case 'd':
1130b57cec5SDimitry Andric       m_permissions |= lldb::eFilePermissionsWorldRead;
1140b57cec5SDimitry Andric       break;
1150b57cec5SDimitry Andric     case 't':
1160b57cec5SDimitry Andric       m_permissions |= lldb::eFilePermissionsWorldWrite;
1170b57cec5SDimitry Andric       break;
1180b57cec5SDimitry Andric     case 'e':
1190b57cec5SDimitry Andric       m_permissions |= lldb::eFilePermissionsWorldExecute;
1200b57cec5SDimitry Andric       break;
1210b57cec5SDimitry Andric     default:
1229dba64beSDimitry Andric       llvm_unreachable("Unimplemented option");
1230b57cec5SDimitry Andric     }
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric     return error;
1260b57cec5SDimitry Andric   }
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric   void OptionParsingStarting(ExecutionContext *execution_context) override {
1290b57cec5SDimitry Andric     m_permissions = 0;
1300b57cec5SDimitry Andric   }
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric   llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
133bdd1243dSDimitry Andric     return llvm::ArrayRef(g_permissions_options);
1340b57cec5SDimitry Andric   }
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric   // Instance variables to hold the values for command options.
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric   uint32_t m_permissions;
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric private:
1415ffd83dbSDimitry Andric   OptionPermissions(const OptionPermissions &) = delete;
1425ffd83dbSDimitry Andric   const OptionPermissions &operator=(const OptionPermissions &) = delete;
1430b57cec5SDimitry Andric };
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric // "platform select <platform-name>"
1460b57cec5SDimitry Andric class CommandObjectPlatformSelect : public CommandObjectParsed {
1470b57cec5SDimitry Andric public:
1480b57cec5SDimitry Andric   CommandObjectPlatformSelect(CommandInterpreter &interpreter)
1490b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "platform select",
1500b57cec5SDimitry Andric                             "Create a platform if needed and select it as the "
1510b57cec5SDimitry Andric                             "current platform.",
1520b57cec5SDimitry Andric                             "platform select <platform-name>", 0),
1530b57cec5SDimitry Andric         m_platform_options(
1540b57cec5SDimitry Andric             false) // Don't include the "--platform" option by passing false
1550b57cec5SDimitry Andric   {
1560b57cec5SDimitry Andric     m_option_group.Append(&m_platform_options, LLDB_OPT_SET_ALL, 1);
1570b57cec5SDimitry Andric     m_option_group.Finalize();
158*0fca6ea1SDimitry Andric     AddSimpleArgumentList(eArgTypePlatform);
1590b57cec5SDimitry Andric   }
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric   ~CommandObjectPlatformSelect() override = default;
1620b57cec5SDimitry Andric 
1639dba64beSDimitry Andric   void HandleCompletion(CompletionRequest &request) override {
16406c3fb27SDimitry Andric     lldb_private::CommandCompletions::PlatformPluginNames(
16506c3fb27SDimitry Andric         GetCommandInterpreter(), request, nullptr);
1660b57cec5SDimitry Andric   }
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric   Options *GetOptions() override { return &m_option_group; }
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric protected:
1715f757f3fSDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
1720b57cec5SDimitry Andric     if (args.GetArgumentCount() == 1) {
1730b57cec5SDimitry Andric       const char *platform_name = args.GetArgumentAtIndex(0);
1740b57cec5SDimitry Andric       if (platform_name && platform_name[0]) {
1750b57cec5SDimitry Andric         const bool select = true;
1760b57cec5SDimitry Andric         m_platform_options.SetPlatformName(platform_name);
1770b57cec5SDimitry Andric         Status error;
1780b57cec5SDimitry Andric         ArchSpec platform_arch;
1790b57cec5SDimitry Andric         PlatformSP platform_sp(m_platform_options.CreatePlatformWithOptions(
1800b57cec5SDimitry Andric             m_interpreter, ArchSpec(), select, error, platform_arch));
1810b57cec5SDimitry Andric         if (platform_sp) {
1820b57cec5SDimitry Andric           GetDebugger().GetPlatformList().SetSelectedPlatform(platform_sp);
1830b57cec5SDimitry Andric 
1840b57cec5SDimitry Andric           platform_sp->GetStatus(result.GetOutputStream());
1850b57cec5SDimitry Andric           result.SetStatus(eReturnStatusSuccessFinishResult);
1860b57cec5SDimitry Andric         } else {
1870b57cec5SDimitry Andric           result.AppendError(error.AsCString());
1880b57cec5SDimitry Andric         }
1890b57cec5SDimitry Andric       } else {
1900b57cec5SDimitry Andric         result.AppendError("invalid platform name");
1910b57cec5SDimitry Andric       }
1920b57cec5SDimitry Andric     } else {
1930b57cec5SDimitry Andric       result.AppendError(
1940b57cec5SDimitry Andric           "platform create takes a platform name as an argument\n");
1950b57cec5SDimitry Andric     }
1960b57cec5SDimitry Andric   }
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric   OptionGroupOptions m_option_group;
1990b57cec5SDimitry Andric   OptionGroupPlatform m_platform_options;
2000b57cec5SDimitry Andric };
2010b57cec5SDimitry Andric 
2020b57cec5SDimitry Andric // "platform list"
2030b57cec5SDimitry Andric class CommandObjectPlatformList : public CommandObjectParsed {
2040b57cec5SDimitry Andric public:
2050b57cec5SDimitry Andric   CommandObjectPlatformList(CommandInterpreter &interpreter)
2060b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "platform list",
2070b57cec5SDimitry Andric                             "List all platforms that are available.", nullptr,
2080b57cec5SDimitry Andric                             0) {}
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric   ~CommandObjectPlatformList() override = default;
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric protected:
2135f757f3fSDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
2140b57cec5SDimitry Andric     Stream &ostrm = result.GetOutputStream();
2150b57cec5SDimitry Andric     ostrm.Printf("Available platforms:\n");
2160b57cec5SDimitry Andric 
2170b57cec5SDimitry Andric     PlatformSP host_platform_sp(Platform::GetHostPlatform());
218349cc55cSDimitry Andric     ostrm.Format("{0}: {1}\n", host_platform_sp->GetPluginName(),
2190b57cec5SDimitry Andric                  host_platform_sp->GetDescription());
2200b57cec5SDimitry Andric 
2210b57cec5SDimitry Andric     uint32_t idx;
2220b57cec5SDimitry Andric     for (idx = 0; true; ++idx) {
223349cc55cSDimitry Andric       llvm::StringRef plugin_name =
2240b57cec5SDimitry Andric           PluginManager::GetPlatformPluginNameAtIndex(idx);
225349cc55cSDimitry Andric       if (plugin_name.empty())
2260b57cec5SDimitry Andric         break;
227349cc55cSDimitry Andric       llvm::StringRef plugin_desc =
2280b57cec5SDimitry Andric           PluginManager::GetPlatformPluginDescriptionAtIndex(idx);
229349cc55cSDimitry Andric       ostrm.Format("{0}: {1}\n", plugin_name, plugin_desc);
2300b57cec5SDimitry Andric     }
2310b57cec5SDimitry Andric 
2320b57cec5SDimitry Andric     if (idx == 0) {
2330b57cec5SDimitry Andric       result.AppendError("no platforms are available\n");
2340b57cec5SDimitry Andric     } else
2350b57cec5SDimitry Andric       result.SetStatus(eReturnStatusSuccessFinishResult);
2360b57cec5SDimitry Andric   }
2370b57cec5SDimitry Andric };
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric // "platform status"
2400b57cec5SDimitry Andric class CommandObjectPlatformStatus : public CommandObjectParsed {
2410b57cec5SDimitry Andric public:
2420b57cec5SDimitry Andric   CommandObjectPlatformStatus(CommandInterpreter &interpreter)
2430b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "platform status",
2440b57cec5SDimitry Andric                             "Display status for the current platform.", nullptr,
2450b57cec5SDimitry Andric                             0) {}
2460b57cec5SDimitry Andric 
2470b57cec5SDimitry Andric   ~CommandObjectPlatformStatus() override = default;
2480b57cec5SDimitry Andric 
2490b57cec5SDimitry Andric protected:
2505f757f3fSDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
2510b57cec5SDimitry Andric     Stream &ostrm = result.GetOutputStream();
2520b57cec5SDimitry Andric 
2530b57cec5SDimitry Andric     Target *target = GetDebugger().GetSelectedTarget().get();
2540b57cec5SDimitry Andric     PlatformSP platform_sp;
2550b57cec5SDimitry Andric     if (target) {
2560b57cec5SDimitry Andric       platform_sp = target->GetPlatform();
2570b57cec5SDimitry Andric     }
2580b57cec5SDimitry Andric     if (!platform_sp) {
2590b57cec5SDimitry Andric       platform_sp = GetDebugger().GetPlatformList().GetSelectedPlatform();
2600b57cec5SDimitry Andric     }
2610b57cec5SDimitry Andric     if (platform_sp) {
2620b57cec5SDimitry Andric       platform_sp->GetStatus(ostrm);
2630b57cec5SDimitry Andric       result.SetStatus(eReturnStatusSuccessFinishResult);
2640b57cec5SDimitry Andric     } else {
2650b57cec5SDimitry Andric       result.AppendError("no platform is currently selected\n");
2660b57cec5SDimitry Andric     }
2670b57cec5SDimitry Andric   }
2680b57cec5SDimitry Andric };
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric // "platform connect <connect-url>"
2710b57cec5SDimitry Andric class CommandObjectPlatformConnect : public CommandObjectParsed {
2720b57cec5SDimitry Andric public:
2730b57cec5SDimitry Andric   CommandObjectPlatformConnect(CommandInterpreter &interpreter)
2740b57cec5SDimitry Andric       : CommandObjectParsed(
2750b57cec5SDimitry Andric             interpreter, "platform connect",
2760b57cec5SDimitry Andric             "Select the current platform by providing a connection URL.",
27781ad6265SDimitry Andric             "platform connect <connect-url>", 0) {
278*0fca6ea1SDimitry Andric     AddSimpleArgumentList(eArgTypeConnectURL);
27981ad6265SDimitry Andric   }
2800b57cec5SDimitry Andric 
2810b57cec5SDimitry Andric   ~CommandObjectPlatformConnect() override = default;
2820b57cec5SDimitry Andric 
2830b57cec5SDimitry Andric protected:
2845f757f3fSDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
2850b57cec5SDimitry Andric     Stream &ostrm = result.GetOutputStream();
2860b57cec5SDimitry Andric 
2870b57cec5SDimitry Andric     PlatformSP platform_sp(
2880b57cec5SDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
2890b57cec5SDimitry Andric     if (platform_sp) {
2900b57cec5SDimitry Andric       Status error(platform_sp->ConnectRemote(args));
2910b57cec5SDimitry Andric       if (error.Success()) {
2920b57cec5SDimitry Andric         platform_sp->GetStatus(ostrm);
2930b57cec5SDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishResult);
2940b57cec5SDimitry Andric 
2950b57cec5SDimitry Andric         platform_sp->ConnectToWaitingProcesses(GetDebugger(), error);
2960b57cec5SDimitry Andric         if (error.Fail()) {
2970b57cec5SDimitry Andric           result.AppendError(error.AsCString());
2980b57cec5SDimitry Andric         }
2990b57cec5SDimitry Andric       } else {
3000b57cec5SDimitry Andric         result.AppendErrorWithFormat("%s\n", error.AsCString());
3010b57cec5SDimitry Andric       }
3020b57cec5SDimitry Andric     } else {
3030b57cec5SDimitry Andric       result.AppendError("no platform is currently selected\n");
3040b57cec5SDimitry Andric     }
3050b57cec5SDimitry Andric   }
3060b57cec5SDimitry Andric 
3070b57cec5SDimitry Andric   Options *GetOptions() override {
3080b57cec5SDimitry Andric     PlatformSP platform_sp(
3090b57cec5SDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
3100b57cec5SDimitry Andric     OptionGroupOptions *m_platform_options = nullptr;
3110b57cec5SDimitry Andric     if (platform_sp) {
3120b57cec5SDimitry Andric       m_platform_options = platform_sp->GetConnectionOptions(m_interpreter);
3130b57cec5SDimitry Andric       if (m_platform_options != nullptr && !m_platform_options->m_did_finalize)
3140b57cec5SDimitry Andric         m_platform_options->Finalize();
3150b57cec5SDimitry Andric     }
3160b57cec5SDimitry Andric     return m_platform_options;
3170b57cec5SDimitry Andric   }
3180b57cec5SDimitry Andric };
3190b57cec5SDimitry Andric 
3200b57cec5SDimitry Andric // "platform disconnect"
3210b57cec5SDimitry Andric class CommandObjectPlatformDisconnect : public CommandObjectParsed {
3220b57cec5SDimitry Andric public:
3230b57cec5SDimitry Andric   CommandObjectPlatformDisconnect(CommandInterpreter &interpreter)
3240b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "platform disconnect",
3250b57cec5SDimitry Andric                             "Disconnect from the current platform.",
3260b57cec5SDimitry Andric                             "platform disconnect", 0) {}
3270b57cec5SDimitry Andric 
3280b57cec5SDimitry Andric   ~CommandObjectPlatformDisconnect() override = default;
3290b57cec5SDimitry Andric 
3300b57cec5SDimitry Andric protected:
3315f757f3fSDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
3320b57cec5SDimitry Andric     PlatformSP platform_sp(
3330b57cec5SDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
3340b57cec5SDimitry Andric     if (platform_sp) {
3350b57cec5SDimitry Andric       if (args.GetArgumentCount() == 0) {
3360b57cec5SDimitry Andric         Status error;
3370b57cec5SDimitry Andric 
3380b57cec5SDimitry Andric         if (platform_sp->IsConnected()) {
3390b57cec5SDimitry Andric           // Cache the instance name if there is one since we are about to
3400b57cec5SDimitry Andric           // disconnect and the name might go with it.
3410b57cec5SDimitry Andric           const char *hostname_cstr = platform_sp->GetHostname();
3420b57cec5SDimitry Andric           std::string hostname;
3430b57cec5SDimitry Andric           if (hostname_cstr)
3440b57cec5SDimitry Andric             hostname.assign(hostname_cstr);
3450b57cec5SDimitry Andric 
3460b57cec5SDimitry Andric           error = platform_sp->DisconnectRemote();
3470b57cec5SDimitry Andric           if (error.Success()) {
3480b57cec5SDimitry Andric             Stream &ostrm = result.GetOutputStream();
3490b57cec5SDimitry Andric             if (hostname.empty())
350349cc55cSDimitry Andric               ostrm.Format("Disconnected from \"{0}\"\n",
351349cc55cSDimitry Andric                            platform_sp->GetPluginName());
3520b57cec5SDimitry Andric             else
3530b57cec5SDimitry Andric               ostrm.Printf("Disconnected from \"%s\"\n", hostname.c_str());
3540b57cec5SDimitry Andric             result.SetStatus(eReturnStatusSuccessFinishResult);
3550b57cec5SDimitry Andric           } else {
3560b57cec5SDimitry Andric             result.AppendErrorWithFormat("%s", error.AsCString());
3570b57cec5SDimitry Andric           }
3580b57cec5SDimitry Andric         } else {
3590b57cec5SDimitry Andric           // Not connected...
360349cc55cSDimitry Andric           result.AppendErrorWithFormatv("not connected to '{0}'",
361349cc55cSDimitry Andric                                         platform_sp->GetPluginName());
3620b57cec5SDimitry Andric         }
3630b57cec5SDimitry Andric       } else {
3640b57cec5SDimitry Andric         // Bad args
3650b57cec5SDimitry Andric         result.AppendError(
3660b57cec5SDimitry Andric             "\"platform disconnect\" doesn't take any arguments");
3670b57cec5SDimitry Andric       }
3680b57cec5SDimitry Andric     } else {
3690b57cec5SDimitry Andric       result.AppendError("no platform is currently selected");
3700b57cec5SDimitry Andric     }
3710b57cec5SDimitry Andric   }
3720b57cec5SDimitry Andric };
3730b57cec5SDimitry Andric 
3740b57cec5SDimitry Andric // "platform settings"
3750b57cec5SDimitry Andric class CommandObjectPlatformSettings : public CommandObjectParsed {
3760b57cec5SDimitry Andric public:
3770b57cec5SDimitry Andric   CommandObjectPlatformSettings(CommandInterpreter &interpreter)
3780b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "platform settings",
379bdd1243dSDimitry Andric                             "Set settings for the current target's platform.",
3800b57cec5SDimitry Andric                             "platform settings", 0),
381e8d8bef9SDimitry Andric         m_option_working_dir(LLDB_OPT_SET_1, false, "working-dir", 'w',
38206c3fb27SDimitry Andric                              lldb::eRemoteDiskDirectoryCompletion, eArgTypePath,
3830b57cec5SDimitry Andric                              "The working directory for the platform.") {
3840b57cec5SDimitry Andric     m_options.Append(&m_option_working_dir, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
3850b57cec5SDimitry Andric   }
3860b57cec5SDimitry Andric 
3870b57cec5SDimitry Andric   ~CommandObjectPlatformSettings() override = default;
3880b57cec5SDimitry Andric 
3890b57cec5SDimitry Andric protected:
3905f757f3fSDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
3910b57cec5SDimitry Andric     PlatformSP platform_sp(
3920b57cec5SDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
3930b57cec5SDimitry Andric     if (platform_sp) {
3940b57cec5SDimitry Andric       if (m_option_working_dir.GetOptionValue().OptionWasSet())
3950b57cec5SDimitry Andric         platform_sp->SetWorkingDirectory(
3960b57cec5SDimitry Andric             m_option_working_dir.GetOptionValue().GetCurrentValue());
3970b57cec5SDimitry Andric     } else {
3980b57cec5SDimitry Andric       result.AppendError("no platform is currently selected");
3990b57cec5SDimitry Andric     }
4000b57cec5SDimitry Andric   }
4010b57cec5SDimitry Andric 
4020b57cec5SDimitry Andric   Options *GetOptions() override {
4030b57cec5SDimitry Andric     if (!m_options.DidFinalize())
4040b57cec5SDimitry Andric       m_options.Finalize();
4050b57cec5SDimitry Andric     return &m_options;
4060b57cec5SDimitry Andric   }
4070b57cec5SDimitry Andric 
4080b57cec5SDimitry Andric   OptionGroupOptions m_options;
4090b57cec5SDimitry Andric   OptionGroupFile m_option_working_dir;
4100b57cec5SDimitry Andric };
4110b57cec5SDimitry Andric 
4120b57cec5SDimitry Andric // "platform mkdir"
4130b57cec5SDimitry Andric class CommandObjectPlatformMkDir : public CommandObjectParsed {
4140b57cec5SDimitry Andric public:
4150b57cec5SDimitry Andric   CommandObjectPlatformMkDir(CommandInterpreter &interpreter)
4160b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "platform mkdir",
4170b57cec5SDimitry Andric                             "Make a new directory on the remote end.", nullptr,
41881ad6265SDimitry Andric                             0) {
419*0fca6ea1SDimitry Andric     AddSimpleArgumentList(eArgTypeRemotePath);
42081ad6265SDimitry Andric   }
4210b57cec5SDimitry Andric 
4220b57cec5SDimitry Andric   ~CommandObjectPlatformMkDir() override = default;
4230b57cec5SDimitry Andric 
4245f757f3fSDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
4250b57cec5SDimitry Andric     PlatformSP platform_sp(
4260b57cec5SDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
4270b57cec5SDimitry Andric     if (platform_sp) {
4280b57cec5SDimitry Andric       std::string cmd_line;
4290b57cec5SDimitry Andric       args.GetCommandString(cmd_line);
4300b57cec5SDimitry Andric       uint32_t mode;
4310b57cec5SDimitry Andric       const OptionPermissions *options_permissions =
4320b57cec5SDimitry Andric           (const OptionPermissions *)m_options.GetGroupWithOption('r');
4330b57cec5SDimitry Andric       if (options_permissions)
4340b57cec5SDimitry Andric         mode = options_permissions->m_permissions;
4350b57cec5SDimitry Andric       else
4360b57cec5SDimitry Andric         mode = lldb::eFilePermissionsUserRWX | lldb::eFilePermissionsGroupRWX |
4370b57cec5SDimitry Andric                lldb::eFilePermissionsWorldRX;
4380b57cec5SDimitry Andric       Status error = platform_sp->MakeDirectory(FileSpec(cmd_line), mode);
4390b57cec5SDimitry Andric       if (error.Success()) {
4400b57cec5SDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishResult);
4410b57cec5SDimitry Andric       } else {
4420b57cec5SDimitry Andric         result.AppendError(error.AsCString());
4430b57cec5SDimitry Andric       }
4440b57cec5SDimitry Andric     } else {
4450b57cec5SDimitry Andric       result.AppendError("no platform currently selected\n");
4460b57cec5SDimitry Andric     }
4470b57cec5SDimitry Andric   }
4480b57cec5SDimitry Andric 
4490b57cec5SDimitry Andric   Options *GetOptions() override {
4500b57cec5SDimitry Andric     if (!m_options.DidFinalize()) {
451bdd1243dSDimitry Andric       m_options.Append(&m_option_permissions);
4520b57cec5SDimitry Andric       m_options.Finalize();
4530b57cec5SDimitry Andric     }
4540b57cec5SDimitry Andric     return &m_options;
4550b57cec5SDimitry Andric   }
4560b57cec5SDimitry Andric 
457bdd1243dSDimitry Andric   OptionPermissions m_option_permissions;
4580b57cec5SDimitry Andric   OptionGroupOptions m_options;
4590b57cec5SDimitry Andric };
4600b57cec5SDimitry Andric 
4610b57cec5SDimitry Andric // "platform fopen"
4620b57cec5SDimitry Andric class CommandObjectPlatformFOpen : public CommandObjectParsed {
4630b57cec5SDimitry Andric public:
4640b57cec5SDimitry Andric   CommandObjectPlatformFOpen(CommandInterpreter &interpreter)
4650b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "platform file open",
46681ad6265SDimitry Andric                             "Open a file on the remote end.", nullptr, 0) {
467*0fca6ea1SDimitry Andric     AddSimpleArgumentList(eArgTypeRemotePath);
46881ad6265SDimitry Andric   }
4690b57cec5SDimitry Andric 
4700b57cec5SDimitry Andric   ~CommandObjectPlatformFOpen() override = default;
4710b57cec5SDimitry Andric 
4725f757f3fSDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
4730b57cec5SDimitry Andric     PlatformSP platform_sp(
4740b57cec5SDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
4750b57cec5SDimitry Andric     if (platform_sp) {
4760b57cec5SDimitry Andric       Status error;
4770b57cec5SDimitry Andric       std::string cmd_line;
4780b57cec5SDimitry Andric       args.GetCommandString(cmd_line);
4790b57cec5SDimitry Andric       mode_t perms;
4800b57cec5SDimitry Andric       const OptionPermissions *options_permissions =
4810b57cec5SDimitry Andric           (const OptionPermissions *)m_options.GetGroupWithOption('r');
4820b57cec5SDimitry Andric       if (options_permissions)
4830b57cec5SDimitry Andric         perms = options_permissions->m_permissions;
4840b57cec5SDimitry Andric       else
4850b57cec5SDimitry Andric         perms = lldb::eFilePermissionsUserRW | lldb::eFilePermissionsGroupRW |
4860b57cec5SDimitry Andric                 lldb::eFilePermissionsWorldRead;
4870b57cec5SDimitry Andric       lldb::user_id_t fd = platform_sp->OpenFile(
4880b57cec5SDimitry Andric           FileSpec(cmd_line),
489349cc55cSDimitry Andric           File::eOpenOptionReadWrite | File::eOpenOptionCanCreate,
4900b57cec5SDimitry Andric           perms, error);
4910b57cec5SDimitry Andric       if (error.Success()) {
4920b57cec5SDimitry Andric         result.AppendMessageWithFormat("File Descriptor = %" PRIu64 "\n", fd);
4930b57cec5SDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishResult);
4940b57cec5SDimitry Andric       } else {
4950b57cec5SDimitry Andric         result.AppendError(error.AsCString());
4960b57cec5SDimitry Andric       }
4970b57cec5SDimitry Andric     } else {
4980b57cec5SDimitry Andric       result.AppendError("no platform currently selected\n");
4990b57cec5SDimitry Andric     }
5000b57cec5SDimitry Andric   }
5010b57cec5SDimitry Andric 
5020b57cec5SDimitry Andric   Options *GetOptions() override {
5030b57cec5SDimitry Andric     if (!m_options.DidFinalize()) {
504bdd1243dSDimitry Andric       m_options.Append(&m_option_permissions);
5050b57cec5SDimitry Andric       m_options.Finalize();
5060b57cec5SDimitry Andric     }
5070b57cec5SDimitry Andric     return &m_options;
5080b57cec5SDimitry Andric   }
5090b57cec5SDimitry Andric 
510bdd1243dSDimitry Andric   OptionPermissions m_option_permissions;
5110b57cec5SDimitry Andric   OptionGroupOptions m_options;
5120b57cec5SDimitry Andric };
5130b57cec5SDimitry Andric 
5140b57cec5SDimitry Andric // "platform fclose"
5150b57cec5SDimitry Andric class CommandObjectPlatformFClose : public CommandObjectParsed {
5160b57cec5SDimitry Andric public:
5170b57cec5SDimitry Andric   CommandObjectPlatformFClose(CommandInterpreter &interpreter)
5180b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "platform file close",
51981ad6265SDimitry Andric                             "Close a file on the remote end.", nullptr, 0) {
520*0fca6ea1SDimitry Andric     AddSimpleArgumentList(eArgTypeUnsignedInteger);
52181ad6265SDimitry Andric   }
5220b57cec5SDimitry Andric 
5230b57cec5SDimitry Andric   ~CommandObjectPlatformFClose() override = default;
5240b57cec5SDimitry Andric 
5255f757f3fSDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
5260b57cec5SDimitry Andric     PlatformSP platform_sp(
5270b57cec5SDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
5280b57cec5SDimitry Andric     if (platform_sp) {
5290b57cec5SDimitry Andric       std::string cmd_line;
5300b57cec5SDimitry Andric       args.GetCommandString(cmd_line);
5315ffd83dbSDimitry Andric       lldb::user_id_t fd;
5325ffd83dbSDimitry Andric       if (!llvm::to_integer(cmd_line, fd)) {
5335ffd83dbSDimitry Andric         result.AppendErrorWithFormatv("'{0}' is not a valid file descriptor.\n",
5345ffd83dbSDimitry Andric                                       cmd_line);
5355f757f3fSDimitry Andric         return;
5365ffd83dbSDimitry Andric       }
5370b57cec5SDimitry Andric       Status error;
5380b57cec5SDimitry Andric       bool success = platform_sp->CloseFile(fd, error);
5390b57cec5SDimitry Andric       if (success) {
5400b57cec5SDimitry Andric         result.AppendMessageWithFormat("file %" PRIu64 " closed.\n", fd);
5410b57cec5SDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishResult);
5420b57cec5SDimitry Andric       } else {
5430b57cec5SDimitry Andric         result.AppendError(error.AsCString());
5440b57cec5SDimitry Andric       }
5450b57cec5SDimitry Andric     } else {
5460b57cec5SDimitry Andric       result.AppendError("no platform currently selected\n");
5470b57cec5SDimitry Andric     }
5480b57cec5SDimitry Andric   }
5490b57cec5SDimitry Andric };
5500b57cec5SDimitry Andric 
5510b57cec5SDimitry Andric // "platform fread"
5520b57cec5SDimitry Andric 
5539dba64beSDimitry Andric #define LLDB_OPTIONS_platform_fread
5549dba64beSDimitry Andric #include "CommandOptions.inc"
5550b57cec5SDimitry Andric 
5560b57cec5SDimitry Andric class CommandObjectPlatformFRead : public CommandObjectParsed {
5570b57cec5SDimitry Andric public:
5580b57cec5SDimitry Andric   CommandObjectPlatformFRead(CommandInterpreter &interpreter)
5590b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "platform file read",
5600b57cec5SDimitry Andric                             "Read data from a file on the remote end.", nullptr,
56181ad6265SDimitry Andric                             0) {
562*0fca6ea1SDimitry Andric     AddSimpleArgumentList(eArgTypeUnsignedInteger);
56381ad6265SDimitry Andric   }
5640b57cec5SDimitry Andric 
5650b57cec5SDimitry Andric   ~CommandObjectPlatformFRead() override = default;
5660b57cec5SDimitry Andric 
5675f757f3fSDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
5680b57cec5SDimitry Andric     PlatformSP platform_sp(
5690b57cec5SDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
5700b57cec5SDimitry Andric     if (platform_sp) {
5710b57cec5SDimitry Andric       std::string cmd_line;
5720b57cec5SDimitry Andric       args.GetCommandString(cmd_line);
5735ffd83dbSDimitry Andric       lldb::user_id_t fd;
5745ffd83dbSDimitry Andric       if (!llvm::to_integer(cmd_line, fd)) {
5755ffd83dbSDimitry Andric         result.AppendErrorWithFormatv("'{0}' is not a valid file descriptor.\n",
5765ffd83dbSDimitry Andric                                       cmd_line);
5775f757f3fSDimitry Andric         return;
5785ffd83dbSDimitry Andric       }
5790b57cec5SDimitry Andric       std::string buffer(m_options.m_count, 0);
5800b57cec5SDimitry Andric       Status error;
581349cc55cSDimitry Andric       uint64_t retcode = platform_sp->ReadFile(
5820b57cec5SDimitry Andric           fd, m_options.m_offset, &buffer[0], m_options.m_count, error);
583349cc55cSDimitry Andric       if (retcode != UINT64_MAX) {
584349cc55cSDimitry Andric         result.AppendMessageWithFormat("Return = %" PRIu64 "\n", retcode);
5850b57cec5SDimitry Andric         result.AppendMessageWithFormat("Data = \"%s\"\n", buffer.c_str());
5860b57cec5SDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishResult);
5870b57cec5SDimitry Andric       } else {
588349cc55cSDimitry Andric         result.AppendError(error.AsCString());
589349cc55cSDimitry Andric       }
590349cc55cSDimitry Andric     } else {
5910b57cec5SDimitry Andric       result.AppendError("no platform currently selected\n");
5920b57cec5SDimitry Andric     }
5930b57cec5SDimitry Andric   }
5940b57cec5SDimitry Andric 
5950b57cec5SDimitry Andric   Options *GetOptions() override { return &m_options; }
5960b57cec5SDimitry Andric 
5970b57cec5SDimitry Andric protected:
5980b57cec5SDimitry Andric   class CommandOptions : public Options {
5990b57cec5SDimitry Andric   public:
60081ad6265SDimitry Andric     CommandOptions() = default;
6010b57cec5SDimitry Andric 
6020b57cec5SDimitry Andric     ~CommandOptions() override = default;
6030b57cec5SDimitry Andric 
6040b57cec5SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
6050b57cec5SDimitry Andric                           ExecutionContext *execution_context) override {
6060b57cec5SDimitry Andric       Status error;
6070b57cec5SDimitry Andric       char short_option = (char)m_getopt_table[option_idx].val;
6080b57cec5SDimitry Andric 
6090b57cec5SDimitry Andric       switch (short_option) {
6100b57cec5SDimitry Andric       case 'o':
6110b57cec5SDimitry Andric         if (option_arg.getAsInteger(0, m_offset))
6120b57cec5SDimitry Andric           error.SetErrorStringWithFormat("invalid offset: '%s'",
6130b57cec5SDimitry Andric                                          option_arg.str().c_str());
6140b57cec5SDimitry Andric         break;
6150b57cec5SDimitry Andric       case 'c':
6160b57cec5SDimitry Andric         if (option_arg.getAsInteger(0, m_count))
6170b57cec5SDimitry Andric           error.SetErrorStringWithFormat("invalid offset: '%s'",
6180b57cec5SDimitry Andric                                          option_arg.str().c_str());
6190b57cec5SDimitry Andric         break;
6200b57cec5SDimitry Andric       default:
6219dba64beSDimitry Andric         llvm_unreachable("Unimplemented option");
6220b57cec5SDimitry Andric       }
6230b57cec5SDimitry Andric 
6240b57cec5SDimitry Andric       return error;
6250b57cec5SDimitry Andric     }
6260b57cec5SDimitry Andric 
6270b57cec5SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
6280b57cec5SDimitry Andric       m_offset = 0;
6290b57cec5SDimitry Andric       m_count = 1;
6300b57cec5SDimitry Andric     }
6310b57cec5SDimitry Andric 
6320b57cec5SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
633bdd1243dSDimitry Andric       return llvm::ArrayRef(g_platform_fread_options);
6340b57cec5SDimitry Andric     }
6350b57cec5SDimitry Andric 
6360b57cec5SDimitry Andric     // Instance variables to hold the values for command options.
6370b57cec5SDimitry Andric 
6380b57cec5SDimitry Andric     uint32_t m_offset;
6390b57cec5SDimitry Andric     uint32_t m_count;
6400b57cec5SDimitry Andric   };
6410b57cec5SDimitry Andric 
6420b57cec5SDimitry Andric   CommandOptions m_options;
6430b57cec5SDimitry Andric };
6440b57cec5SDimitry Andric 
6450b57cec5SDimitry Andric // "platform fwrite"
6460b57cec5SDimitry Andric 
6479dba64beSDimitry Andric #define LLDB_OPTIONS_platform_fwrite
6489dba64beSDimitry Andric #include "CommandOptions.inc"
6490b57cec5SDimitry Andric 
6500b57cec5SDimitry Andric class CommandObjectPlatformFWrite : public CommandObjectParsed {
6510b57cec5SDimitry Andric public:
6520b57cec5SDimitry Andric   CommandObjectPlatformFWrite(CommandInterpreter &interpreter)
6530b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "platform file write",
6540b57cec5SDimitry Andric                             "Write data to a file on the remote end.", nullptr,
65581ad6265SDimitry Andric                             0) {
656*0fca6ea1SDimitry Andric     AddSimpleArgumentList(eArgTypeUnsignedInteger);
65781ad6265SDimitry Andric   }
6580b57cec5SDimitry Andric 
6590b57cec5SDimitry Andric   ~CommandObjectPlatformFWrite() override = default;
6600b57cec5SDimitry Andric 
6615f757f3fSDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
6620b57cec5SDimitry Andric     PlatformSP platform_sp(
6630b57cec5SDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
6640b57cec5SDimitry Andric     if (platform_sp) {
6650b57cec5SDimitry Andric       std::string cmd_line;
6660b57cec5SDimitry Andric       args.GetCommandString(cmd_line);
6670b57cec5SDimitry Andric       Status error;
6685ffd83dbSDimitry Andric       lldb::user_id_t fd;
6695ffd83dbSDimitry Andric       if (!llvm::to_integer(cmd_line, fd)) {
6705ffd83dbSDimitry Andric         result.AppendErrorWithFormatv("'{0}' is not a valid file descriptor.",
6715ffd83dbSDimitry Andric                                       cmd_line);
6725f757f3fSDimitry Andric         return;
6735ffd83dbSDimitry Andric       }
674349cc55cSDimitry Andric       uint64_t retcode =
6750b57cec5SDimitry Andric           platform_sp->WriteFile(fd, m_options.m_offset, &m_options.m_data[0],
6760b57cec5SDimitry Andric                                  m_options.m_data.size(), error);
677349cc55cSDimitry Andric       if (retcode != UINT64_MAX) {
678349cc55cSDimitry Andric         result.AppendMessageWithFormat("Return = %" PRIu64 "\n", retcode);
6790b57cec5SDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishResult);
6800b57cec5SDimitry Andric       } else {
681349cc55cSDimitry Andric         result.AppendError(error.AsCString());
682349cc55cSDimitry Andric       }
683349cc55cSDimitry Andric     } else {
6840b57cec5SDimitry Andric       result.AppendError("no platform currently selected\n");
6850b57cec5SDimitry Andric     }
6860b57cec5SDimitry Andric   }
6870b57cec5SDimitry Andric 
6880b57cec5SDimitry Andric   Options *GetOptions() override { return &m_options; }
6890b57cec5SDimitry Andric 
6900b57cec5SDimitry Andric protected:
6910b57cec5SDimitry Andric   class CommandOptions : public Options {
6920b57cec5SDimitry Andric   public:
69381ad6265SDimitry Andric     CommandOptions() = default;
6940b57cec5SDimitry Andric 
6950b57cec5SDimitry Andric     ~CommandOptions() override = default;
6960b57cec5SDimitry Andric 
6970b57cec5SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
6980b57cec5SDimitry Andric                           ExecutionContext *execution_context) override {
6990b57cec5SDimitry Andric       Status error;
7000b57cec5SDimitry Andric       char short_option = (char)m_getopt_table[option_idx].val;
7010b57cec5SDimitry Andric 
7020b57cec5SDimitry Andric       switch (short_option) {
7030b57cec5SDimitry Andric       case 'o':
7040b57cec5SDimitry Andric         if (option_arg.getAsInteger(0, m_offset))
7050b57cec5SDimitry Andric           error.SetErrorStringWithFormat("invalid offset: '%s'",
7060b57cec5SDimitry Andric                                          option_arg.str().c_str());
7070b57cec5SDimitry Andric         break;
7080b57cec5SDimitry Andric       case 'd':
7095ffd83dbSDimitry Andric         m_data.assign(std::string(option_arg));
7100b57cec5SDimitry Andric         break;
7110b57cec5SDimitry Andric       default:
7129dba64beSDimitry Andric         llvm_unreachable("Unimplemented option");
7130b57cec5SDimitry Andric       }
7140b57cec5SDimitry Andric 
7150b57cec5SDimitry Andric       return error;
7160b57cec5SDimitry Andric     }
7170b57cec5SDimitry Andric 
7180b57cec5SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
7190b57cec5SDimitry Andric       m_offset = 0;
7200b57cec5SDimitry Andric       m_data.clear();
7210b57cec5SDimitry Andric     }
7220b57cec5SDimitry Andric 
7230b57cec5SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
724bdd1243dSDimitry Andric       return llvm::ArrayRef(g_platform_fwrite_options);
7250b57cec5SDimitry Andric     }
7260b57cec5SDimitry Andric 
7270b57cec5SDimitry Andric     // Instance variables to hold the values for command options.
7280b57cec5SDimitry Andric 
7290b57cec5SDimitry Andric     uint32_t m_offset;
7300b57cec5SDimitry Andric     std::string m_data;
7310b57cec5SDimitry Andric   };
7320b57cec5SDimitry Andric 
7330b57cec5SDimitry Andric   CommandOptions m_options;
7340b57cec5SDimitry Andric };
7350b57cec5SDimitry Andric 
7360b57cec5SDimitry Andric class CommandObjectPlatformFile : public CommandObjectMultiword {
7370b57cec5SDimitry Andric public:
7380b57cec5SDimitry Andric   // Constructors and Destructors
7390b57cec5SDimitry Andric   CommandObjectPlatformFile(CommandInterpreter &interpreter)
7400b57cec5SDimitry Andric       : CommandObjectMultiword(
7410b57cec5SDimitry Andric             interpreter, "platform file",
7420b57cec5SDimitry Andric             "Commands to access files on the current platform.",
7430b57cec5SDimitry Andric             "platform file [open|close|read|write] ...") {
7440b57cec5SDimitry Andric     LoadSubCommand(
7450b57cec5SDimitry Andric         "open", CommandObjectSP(new CommandObjectPlatformFOpen(interpreter)));
7460b57cec5SDimitry Andric     LoadSubCommand(
7470b57cec5SDimitry Andric         "close", CommandObjectSP(new CommandObjectPlatformFClose(interpreter)));
7480b57cec5SDimitry Andric     LoadSubCommand(
7490b57cec5SDimitry Andric         "read", CommandObjectSP(new CommandObjectPlatformFRead(interpreter)));
7500b57cec5SDimitry Andric     LoadSubCommand(
7510b57cec5SDimitry Andric         "write", CommandObjectSP(new CommandObjectPlatformFWrite(interpreter)));
7520b57cec5SDimitry Andric   }
7530b57cec5SDimitry Andric 
7540b57cec5SDimitry Andric   ~CommandObjectPlatformFile() override = default;
7550b57cec5SDimitry Andric 
7560b57cec5SDimitry Andric private:
7570b57cec5SDimitry Andric   // For CommandObjectPlatform only
7585ffd83dbSDimitry Andric   CommandObjectPlatformFile(const CommandObjectPlatformFile &) = delete;
7595ffd83dbSDimitry Andric   const CommandObjectPlatformFile &
7605ffd83dbSDimitry Andric   operator=(const CommandObjectPlatformFile &) = delete;
7610b57cec5SDimitry Andric };
7620b57cec5SDimitry Andric 
7630b57cec5SDimitry Andric // "platform get-file remote-file-path host-file-path"
7640b57cec5SDimitry Andric class CommandObjectPlatformGetFile : public CommandObjectParsed {
7650b57cec5SDimitry Andric public:
7660b57cec5SDimitry Andric   CommandObjectPlatformGetFile(CommandInterpreter &interpreter)
7670b57cec5SDimitry Andric       : CommandObjectParsed(
7680b57cec5SDimitry Andric             interpreter, "platform get-file",
7690b57cec5SDimitry Andric             "Transfer a file from the remote end to the local host.",
7700b57cec5SDimitry Andric             "platform get-file <remote-file-spec> <local-file-spec>", 0) {
7710b57cec5SDimitry Andric     SetHelpLong(
7720b57cec5SDimitry Andric         R"(Examples:
7730b57cec5SDimitry Andric 
7740b57cec5SDimitry Andric (lldb) platform get-file /the/remote/file/path /the/local/file/path
7750b57cec5SDimitry Andric 
7760b57cec5SDimitry Andric     Transfer a file from the remote end with file path /the/remote/file/path to the local host.)");
7770b57cec5SDimitry Andric 
7780b57cec5SDimitry Andric     CommandArgumentEntry arg1, arg2;
7790b57cec5SDimitry Andric     CommandArgumentData file_arg_remote, file_arg_host;
7800b57cec5SDimitry Andric 
7810b57cec5SDimitry Andric     // Define the first (and only) variant of this arg.
782*0fca6ea1SDimitry Andric     file_arg_remote.arg_type = eArgTypeRemoteFilename;
7830b57cec5SDimitry Andric     file_arg_remote.arg_repetition = eArgRepeatPlain;
7840b57cec5SDimitry Andric     // There is only one variant this argument could be; put it into the
7850b57cec5SDimitry Andric     // argument entry.
7860b57cec5SDimitry Andric     arg1.push_back(file_arg_remote);
7870b57cec5SDimitry Andric 
7880b57cec5SDimitry Andric     // Define the second (and only) variant of this arg.
7890b57cec5SDimitry Andric     file_arg_host.arg_type = eArgTypeFilename;
7900b57cec5SDimitry Andric     file_arg_host.arg_repetition = eArgRepeatPlain;
7910b57cec5SDimitry Andric     // There is only one variant this argument could be; put it into the
7920b57cec5SDimitry Andric     // argument entry.
7930b57cec5SDimitry Andric     arg2.push_back(file_arg_host);
7940b57cec5SDimitry Andric 
7950b57cec5SDimitry Andric     // Push the data for the first and the second arguments into the
7960b57cec5SDimitry Andric     // m_arguments vector.
7970b57cec5SDimitry Andric     m_arguments.push_back(arg1);
7980b57cec5SDimitry Andric     m_arguments.push_back(arg2);
7990b57cec5SDimitry Andric   }
8000b57cec5SDimitry Andric 
8010b57cec5SDimitry Andric   ~CommandObjectPlatformGetFile() override = default;
8020b57cec5SDimitry Andric 
803e8d8bef9SDimitry Andric   void
804e8d8bef9SDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
805e8d8bef9SDimitry Andric                            OptionElementVector &opt_element_vector) override {
806e8d8bef9SDimitry Andric     if (request.GetCursorIndex() == 0)
80706c3fb27SDimitry Andric       lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
80806c3fb27SDimitry Andric           GetCommandInterpreter(), lldb::eRemoteDiskFileCompletion, request,
80906c3fb27SDimitry Andric           nullptr);
810e8d8bef9SDimitry Andric     else if (request.GetCursorIndex() == 1)
81106c3fb27SDimitry Andric       lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
81206c3fb27SDimitry Andric           GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr);
813e8d8bef9SDimitry Andric   }
814e8d8bef9SDimitry Andric 
8155f757f3fSDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
8160b57cec5SDimitry Andric     // If the number of arguments is incorrect, issue an error message.
8170b57cec5SDimitry Andric     if (args.GetArgumentCount() != 2) {
818fe6060f1SDimitry Andric       result.AppendError("required arguments missing; specify both the "
819fe6060f1SDimitry Andric                          "source and destination file paths");
8205f757f3fSDimitry Andric       return;
8210b57cec5SDimitry Andric     }
8220b57cec5SDimitry Andric 
8230b57cec5SDimitry Andric     PlatformSP platform_sp(
8240b57cec5SDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
8250b57cec5SDimitry Andric     if (platform_sp) {
8260b57cec5SDimitry Andric       const char *remote_file_path = args.GetArgumentAtIndex(0);
8270b57cec5SDimitry Andric       const char *local_file_path = args.GetArgumentAtIndex(1);
8280b57cec5SDimitry Andric       Status error = platform_sp->GetFile(FileSpec(remote_file_path),
8290b57cec5SDimitry Andric                                           FileSpec(local_file_path));
8300b57cec5SDimitry Andric       if (error.Success()) {
8310b57cec5SDimitry Andric         result.AppendMessageWithFormat(
8320b57cec5SDimitry Andric             "successfully get-file from %s (remote) to %s (host)\n",
8330b57cec5SDimitry Andric             remote_file_path, local_file_path);
8340b57cec5SDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishResult);
8350b57cec5SDimitry Andric       } else {
8360b57cec5SDimitry Andric         result.AppendMessageWithFormat("get-file failed: %s\n",
8370b57cec5SDimitry Andric                                        error.AsCString());
8380b57cec5SDimitry Andric       }
8390b57cec5SDimitry Andric     } else {
8400b57cec5SDimitry Andric       result.AppendError("no platform currently selected\n");
8410b57cec5SDimitry Andric     }
8420b57cec5SDimitry Andric   }
8430b57cec5SDimitry Andric };
8440b57cec5SDimitry Andric 
8450b57cec5SDimitry Andric // "platform get-size remote-file-path"
8460b57cec5SDimitry Andric class CommandObjectPlatformGetSize : public CommandObjectParsed {
8470b57cec5SDimitry Andric public:
8480b57cec5SDimitry Andric   CommandObjectPlatformGetSize(CommandInterpreter &interpreter)
8490b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "platform get-size",
8500b57cec5SDimitry Andric                             "Get the file size from the remote end.",
8510b57cec5SDimitry Andric                             "platform get-size <remote-file-spec>", 0) {
8520b57cec5SDimitry Andric     SetHelpLong(
8530b57cec5SDimitry Andric         R"(Examples:
8540b57cec5SDimitry Andric 
8550b57cec5SDimitry Andric (lldb) platform get-size /the/remote/file/path
8560b57cec5SDimitry Andric 
8570b57cec5SDimitry Andric     Get the file size from the remote end with path /the/remote/file/path.)");
8580b57cec5SDimitry Andric 
859*0fca6ea1SDimitry Andric     AddSimpleArgumentList(eArgTypeRemoteFilename);
8600b57cec5SDimitry Andric   }
8610b57cec5SDimitry Andric 
8620b57cec5SDimitry Andric   ~CommandObjectPlatformGetSize() override = default;
8630b57cec5SDimitry Andric 
8645f757f3fSDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
8650b57cec5SDimitry Andric     // If the number of arguments is incorrect, issue an error message.
8660b57cec5SDimitry Andric     if (args.GetArgumentCount() != 1) {
867fe6060f1SDimitry Andric       result.AppendError("required argument missing; specify the source file "
868fe6060f1SDimitry Andric                          "path as the only argument");
8695f757f3fSDimitry Andric       return;
8700b57cec5SDimitry Andric     }
8710b57cec5SDimitry Andric 
8720b57cec5SDimitry Andric     PlatformSP platform_sp(
8730b57cec5SDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
8740b57cec5SDimitry Andric     if (platform_sp) {
8750b57cec5SDimitry Andric       std::string remote_file_path(args.GetArgumentAtIndex(0));
8760b57cec5SDimitry Andric       user_id_t size = platform_sp->GetFileSize(FileSpec(remote_file_path));
8770b57cec5SDimitry Andric       if (size != UINT64_MAX) {
8780b57cec5SDimitry Andric         result.AppendMessageWithFormat("File size of %s (remote): %" PRIu64
8790b57cec5SDimitry Andric                                        "\n",
8800b57cec5SDimitry Andric                                        remote_file_path.c_str(), size);
8810b57cec5SDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishResult);
8820b57cec5SDimitry Andric       } else {
8830b57cec5SDimitry Andric         result.AppendMessageWithFormat(
8840b57cec5SDimitry Andric             "Error getting file size of %s (remote)\n",
8850b57cec5SDimitry Andric             remote_file_path.c_str());
8860b57cec5SDimitry Andric       }
8870b57cec5SDimitry Andric     } else {
8880b57cec5SDimitry Andric       result.AppendError("no platform currently selected\n");
8890b57cec5SDimitry Andric     }
8900b57cec5SDimitry Andric   }
8910b57cec5SDimitry Andric };
8920b57cec5SDimitry Andric 
893349cc55cSDimitry Andric // "platform get-permissions remote-file-path"
894349cc55cSDimitry Andric class CommandObjectPlatformGetPermissions : public CommandObjectParsed {
895349cc55cSDimitry Andric public:
896349cc55cSDimitry Andric   CommandObjectPlatformGetPermissions(CommandInterpreter &interpreter)
897349cc55cSDimitry Andric       : CommandObjectParsed(interpreter, "platform get-permissions",
898349cc55cSDimitry Andric                             "Get the file permission bits from the remote end.",
899349cc55cSDimitry Andric                             "platform get-permissions <remote-file-spec>", 0) {
900349cc55cSDimitry Andric     SetHelpLong(
901349cc55cSDimitry Andric         R"(Examples:
902349cc55cSDimitry Andric 
903349cc55cSDimitry Andric (lldb) platform get-permissions /the/remote/file/path
904349cc55cSDimitry Andric 
905349cc55cSDimitry Andric     Get the file permissions from the remote end with path /the/remote/file/path.)");
906349cc55cSDimitry Andric 
907*0fca6ea1SDimitry Andric     AddSimpleArgumentList(eArgTypeRemoteFilename);
908349cc55cSDimitry Andric   }
909349cc55cSDimitry Andric 
910349cc55cSDimitry Andric   ~CommandObjectPlatformGetPermissions() override = default;
911349cc55cSDimitry Andric 
9125f757f3fSDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
913349cc55cSDimitry Andric     // If the number of arguments is incorrect, issue an error message.
914349cc55cSDimitry Andric     if (args.GetArgumentCount() != 1) {
915349cc55cSDimitry Andric       result.AppendError("required argument missing; specify the source file "
916349cc55cSDimitry Andric                          "path as the only argument");
9175f757f3fSDimitry Andric       return;
918349cc55cSDimitry Andric     }
919349cc55cSDimitry Andric 
920349cc55cSDimitry Andric     PlatformSP platform_sp(
921349cc55cSDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
922349cc55cSDimitry Andric     if (platform_sp) {
923349cc55cSDimitry Andric       std::string remote_file_path(args.GetArgumentAtIndex(0));
924349cc55cSDimitry Andric       uint32_t permissions;
925349cc55cSDimitry Andric       Status error = platform_sp->GetFilePermissions(FileSpec(remote_file_path),
926349cc55cSDimitry Andric                                                      permissions);
927349cc55cSDimitry Andric       if (error.Success()) {
928349cc55cSDimitry Andric         result.AppendMessageWithFormat(
929349cc55cSDimitry Andric             "File permissions of %s (remote): 0o%04" PRIo32 "\n",
930349cc55cSDimitry Andric             remote_file_path.c_str(), permissions);
931349cc55cSDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishResult);
932349cc55cSDimitry Andric       } else
933349cc55cSDimitry Andric         result.AppendError(error.AsCString());
934349cc55cSDimitry Andric     } else {
935349cc55cSDimitry Andric       result.AppendError("no platform currently selected\n");
936349cc55cSDimitry Andric     }
937349cc55cSDimitry Andric   }
938349cc55cSDimitry Andric };
939349cc55cSDimitry Andric 
940349cc55cSDimitry Andric // "platform file-exists remote-file-path"
941349cc55cSDimitry Andric class CommandObjectPlatformFileExists : public CommandObjectParsed {
942349cc55cSDimitry Andric public:
943349cc55cSDimitry Andric   CommandObjectPlatformFileExists(CommandInterpreter &interpreter)
944349cc55cSDimitry Andric       : CommandObjectParsed(interpreter, "platform file-exists",
945349cc55cSDimitry Andric                             "Check if the file exists on the remote end.",
946349cc55cSDimitry Andric                             "platform file-exists <remote-file-spec>", 0) {
947349cc55cSDimitry Andric     SetHelpLong(
948349cc55cSDimitry Andric         R"(Examples:
949349cc55cSDimitry Andric 
950349cc55cSDimitry Andric (lldb) platform file-exists /the/remote/file/path
951349cc55cSDimitry Andric 
952349cc55cSDimitry Andric     Check if /the/remote/file/path exists on the remote end.)");
953349cc55cSDimitry Andric 
954*0fca6ea1SDimitry Andric     AddSimpleArgumentList(eArgTypeRemoteFilename);
955349cc55cSDimitry Andric   }
956349cc55cSDimitry Andric 
957349cc55cSDimitry Andric   ~CommandObjectPlatformFileExists() override = default;
958349cc55cSDimitry Andric 
9595f757f3fSDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
960349cc55cSDimitry Andric     // If the number of arguments is incorrect, issue an error message.
961349cc55cSDimitry Andric     if (args.GetArgumentCount() != 1) {
962349cc55cSDimitry Andric       result.AppendError("required argument missing; specify the source file "
963349cc55cSDimitry Andric                          "path as the only argument");
9645f757f3fSDimitry Andric       return;
965349cc55cSDimitry Andric     }
966349cc55cSDimitry Andric 
967349cc55cSDimitry Andric     PlatformSP platform_sp(
968349cc55cSDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
969349cc55cSDimitry Andric     if (platform_sp) {
970349cc55cSDimitry Andric       std::string remote_file_path(args.GetArgumentAtIndex(0));
971349cc55cSDimitry Andric       bool exists = platform_sp->GetFileExists(FileSpec(remote_file_path));
972349cc55cSDimitry Andric       result.AppendMessageWithFormat(
973349cc55cSDimitry Andric           "File %s (remote) %s\n",
974349cc55cSDimitry Andric           remote_file_path.c_str(), exists ? "exists" : "does not exist");
975349cc55cSDimitry Andric       result.SetStatus(eReturnStatusSuccessFinishResult);
976349cc55cSDimitry Andric     } else {
977349cc55cSDimitry Andric       result.AppendError("no platform currently selected\n");
978349cc55cSDimitry Andric     }
979349cc55cSDimitry Andric   }
980349cc55cSDimitry Andric };
981349cc55cSDimitry Andric 
9820b57cec5SDimitry Andric // "platform put-file"
9830b57cec5SDimitry Andric class CommandObjectPlatformPutFile : public CommandObjectParsed {
9840b57cec5SDimitry Andric public:
9850b57cec5SDimitry Andric   CommandObjectPlatformPutFile(CommandInterpreter &interpreter)
9860b57cec5SDimitry Andric       : CommandObjectParsed(
9870b57cec5SDimitry Andric             interpreter, "platform put-file",
988349cc55cSDimitry Andric             "Transfer a file from this system to the remote end.",
989349cc55cSDimitry Andric             "platform put-file <source> [<destination>]", 0) {
990349cc55cSDimitry Andric     SetHelpLong(
991349cc55cSDimitry Andric         R"(Examples:
992349cc55cSDimitry Andric 
993349cc55cSDimitry Andric (lldb) platform put-file /source/foo.txt /destination/bar.txt
994349cc55cSDimitry Andric 
995349cc55cSDimitry Andric (lldb) platform put-file /source/foo.txt
996349cc55cSDimitry Andric 
997349cc55cSDimitry Andric     Relative source file paths are resolved against lldb's local working directory.
998349cc55cSDimitry Andric 
999349cc55cSDimitry Andric     Omitting the destination places the file in the platform working directory.)");
100081ad6265SDimitry Andric     CommandArgumentData source_arg{eArgTypePath, eArgRepeatPlain};
1001*0fca6ea1SDimitry Andric     CommandArgumentData path_arg{eArgTypeRemotePath, eArgRepeatOptional};
100281ad6265SDimitry Andric     m_arguments.push_back({source_arg});
100381ad6265SDimitry Andric     m_arguments.push_back({path_arg});
10040b57cec5SDimitry Andric   }
10050b57cec5SDimitry Andric 
10060b57cec5SDimitry Andric   ~CommandObjectPlatformPutFile() override = default;
10070b57cec5SDimitry Andric 
1008e8d8bef9SDimitry Andric   void
1009e8d8bef9SDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
1010e8d8bef9SDimitry Andric                            OptionElementVector &opt_element_vector) override {
1011e8d8bef9SDimitry Andric     if (request.GetCursorIndex() == 0)
101206c3fb27SDimitry Andric       lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
101306c3fb27SDimitry Andric           GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr);
1014e8d8bef9SDimitry Andric     else if (request.GetCursorIndex() == 1)
101506c3fb27SDimitry Andric       lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
101606c3fb27SDimitry Andric           GetCommandInterpreter(), lldb::eRemoteDiskFileCompletion, request,
101706c3fb27SDimitry Andric           nullptr);
1018e8d8bef9SDimitry Andric   }
1019e8d8bef9SDimitry Andric 
10205f757f3fSDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
10210b57cec5SDimitry Andric     const char *src = args.GetArgumentAtIndex(0);
10220b57cec5SDimitry Andric     const char *dst = args.GetArgumentAtIndex(1);
10230b57cec5SDimitry Andric 
10240b57cec5SDimitry Andric     FileSpec src_fs(src);
10250b57cec5SDimitry Andric     FileSystem::Instance().Resolve(src_fs);
10260b57cec5SDimitry Andric     FileSpec dst_fs(dst ? dst : src_fs.GetFilename().GetCString());
10270b57cec5SDimitry Andric 
10280b57cec5SDimitry Andric     PlatformSP platform_sp(
10290b57cec5SDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
10300b57cec5SDimitry Andric     if (platform_sp) {
10310b57cec5SDimitry Andric       Status error(platform_sp->PutFile(src_fs, dst_fs));
10320b57cec5SDimitry Andric       if (error.Success()) {
10330b57cec5SDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishNoResult);
10340b57cec5SDimitry Andric       } else {
10350b57cec5SDimitry Andric         result.AppendError(error.AsCString());
10360b57cec5SDimitry Andric       }
10370b57cec5SDimitry Andric     } else {
10380b57cec5SDimitry Andric       result.AppendError("no platform currently selected\n");
10390b57cec5SDimitry Andric     }
10400b57cec5SDimitry Andric   }
10410b57cec5SDimitry Andric };
10420b57cec5SDimitry Andric 
10430b57cec5SDimitry Andric // "platform process launch"
10440b57cec5SDimitry Andric class CommandObjectPlatformProcessLaunch : public CommandObjectParsed {
10450b57cec5SDimitry Andric public:
10460b57cec5SDimitry Andric   CommandObjectPlatformProcessLaunch(CommandInterpreter &interpreter)
10470b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "platform process launch",
10480b57cec5SDimitry Andric                             "Launch a new process on a remote platform.",
10490b57cec5SDimitry Andric                             "platform process launch program",
105006c3fb27SDimitry Andric                             eCommandRequiresTarget | eCommandTryTargetAPILock),
105106c3fb27SDimitry Andric         m_class_options("scripted process", true, 'C', 'k', 'v', 0) {
1052fe6060f1SDimitry Andric     m_all_options.Append(&m_options);
105306c3fb27SDimitry Andric     m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2,
105406c3fb27SDimitry Andric                          LLDB_OPT_SET_ALL);
1055fe6060f1SDimitry Andric     m_all_options.Finalize();
1056*0fca6ea1SDimitry Andric     AddSimpleArgumentList(eArgTypeRunArgs, eArgRepeatStar);
1057*0fca6ea1SDimitry Andric   }
1058*0fca6ea1SDimitry Andric 
1059*0fca6ea1SDimitry Andric   void
1060*0fca6ea1SDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
1061*0fca6ea1SDimitry Andric                            OptionElementVector &opt_element_vector) override {
1062*0fca6ea1SDimitry Andric     // I didn't make a type for RemoteRunArgs, but since we're going to run
1063*0fca6ea1SDimitry Andric     // this on the remote system we should use the remote completer.
1064*0fca6ea1SDimitry Andric     lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1065*0fca6ea1SDimitry Andric         GetCommandInterpreter(), lldb::eRemoteDiskFileCompletion, request,
1066*0fca6ea1SDimitry Andric         nullptr);
1067fe6060f1SDimitry Andric   }
10680b57cec5SDimitry Andric 
10690b57cec5SDimitry Andric   ~CommandObjectPlatformProcessLaunch() override = default;
10700b57cec5SDimitry Andric 
1071fe6060f1SDimitry Andric   Options *GetOptions() override { return &m_all_options; }
10720b57cec5SDimitry Andric 
10730b57cec5SDimitry Andric protected:
10745f757f3fSDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
10750b57cec5SDimitry Andric     Target *target = GetDebugger().GetSelectedTarget().get();
10760b57cec5SDimitry Andric     PlatformSP platform_sp;
10770b57cec5SDimitry Andric     if (target) {
10780b57cec5SDimitry Andric       platform_sp = target->GetPlatform();
10790b57cec5SDimitry Andric     }
10800b57cec5SDimitry Andric     if (!platform_sp) {
10810b57cec5SDimitry Andric       platform_sp = GetDebugger().GetPlatformList().GetSelectedPlatform();
10820b57cec5SDimitry Andric     }
10830b57cec5SDimitry Andric 
10840b57cec5SDimitry Andric     if (platform_sp) {
10850b57cec5SDimitry Andric       Status error;
10860b57cec5SDimitry Andric       const size_t argc = args.GetArgumentCount();
10870b57cec5SDimitry Andric       Target *target = m_exe_ctx.GetTargetPtr();
10880b57cec5SDimitry Andric       Module *exe_module = target->GetExecutableModulePointer();
10890b57cec5SDimitry Andric       if (exe_module) {
10900b57cec5SDimitry Andric         m_options.launch_info.GetExecutableFile() = exe_module->GetFileSpec();
10910b57cec5SDimitry Andric         llvm::SmallString<128> exe_path;
10920b57cec5SDimitry Andric         m_options.launch_info.GetExecutableFile().GetPath(exe_path);
10930b57cec5SDimitry Andric         if (!exe_path.empty())
10940b57cec5SDimitry Andric           m_options.launch_info.GetArguments().AppendArgument(exe_path);
10950b57cec5SDimitry Andric         m_options.launch_info.GetArchitecture() = exe_module->GetArchitecture();
10960b57cec5SDimitry Andric       }
10970b57cec5SDimitry Andric 
109806c3fb27SDimitry Andric       if (!m_class_options.GetName().empty()) {
109906c3fb27SDimitry Andric         m_options.launch_info.SetProcessPluginName("ScriptedProcess");
110006c3fb27SDimitry Andric         ScriptedMetadataSP metadata_sp = std::make_shared<ScriptedMetadata>(
110106c3fb27SDimitry Andric             m_class_options.GetName(), m_class_options.GetStructuredData());
110206c3fb27SDimitry Andric         m_options.launch_info.SetScriptedMetadata(metadata_sp);
110306c3fb27SDimitry Andric         target->SetProcessLaunchInfo(m_options.launch_info);
110406c3fb27SDimitry Andric       }
110506c3fb27SDimitry Andric 
11060b57cec5SDimitry Andric       if (argc > 0) {
11070b57cec5SDimitry Andric         if (m_options.launch_info.GetExecutableFile()) {
11080b57cec5SDimitry Andric           // We already have an executable file, so we will use this and all
11090b57cec5SDimitry Andric           // arguments to this function are extra arguments
11100b57cec5SDimitry Andric           m_options.launch_info.GetArguments().AppendArguments(args);
11110b57cec5SDimitry Andric         } else {
11120b57cec5SDimitry Andric           // We don't have any file yet, so the first argument is our
11130b57cec5SDimitry Andric           // executable, and the rest are program arguments
11140b57cec5SDimitry Andric           const bool first_arg_is_executable = true;
11150b57cec5SDimitry Andric           m_options.launch_info.SetArguments(args, first_arg_is_executable);
11160b57cec5SDimitry Andric         }
11170b57cec5SDimitry Andric       }
11180b57cec5SDimitry Andric 
11190b57cec5SDimitry Andric       if (m_options.launch_info.GetExecutableFile()) {
11200b57cec5SDimitry Andric         Debugger &debugger = GetDebugger();
11210b57cec5SDimitry Andric 
112206c3fb27SDimitry Andric         if (argc == 0) {
112306c3fb27SDimitry Andric           // If no arguments were given to the command, use target.run-args.
112406c3fb27SDimitry Andric           Args target_run_args;
112506c3fb27SDimitry Andric           target->GetRunArguments(target_run_args);
112606c3fb27SDimitry Andric           m_options.launch_info.GetArguments().AppendArguments(target_run_args);
112706c3fb27SDimitry Andric         }
11280b57cec5SDimitry Andric 
11290b57cec5SDimitry Andric         ProcessSP process_sp(platform_sp->DebugProcess(
1130349cc55cSDimitry Andric             m_options.launch_info, debugger, *target, error));
113106c3fb27SDimitry Andric 
113206c3fb27SDimitry Andric         if (!process_sp && error.Success()) {
113306c3fb27SDimitry Andric           result.AppendError("failed to launch or debug process");
11345f757f3fSDimitry Andric           return;
113506c3fb27SDimitry Andric         } else if (!error.Success()) {
113606c3fb27SDimitry Andric           result.AppendError(error.AsCString());
11375f757f3fSDimitry Andric           return;
113806c3fb27SDimitry Andric         }
113906c3fb27SDimitry Andric 
114006c3fb27SDimitry Andric         const bool synchronous_execution =
114106c3fb27SDimitry Andric             debugger.GetCommandInterpreter().GetSynchronous();
114206c3fb27SDimitry Andric         auto launch_info = m_options.launch_info;
114306c3fb27SDimitry Andric         bool rebroadcast_first_stop =
114406c3fb27SDimitry Andric             !synchronous_execution &&
114506c3fb27SDimitry Andric             launch_info.GetFlags().Test(eLaunchFlagStopAtEntry);
114606c3fb27SDimitry Andric 
114706c3fb27SDimitry Andric         EventSP first_stop_event_sp;
114806c3fb27SDimitry Andric         StateType state = process_sp->WaitForProcessToStop(
114906c3fb27SDimitry Andric             std::nullopt, &first_stop_event_sp, rebroadcast_first_stop,
115006c3fb27SDimitry Andric             launch_info.GetHijackListener());
115106c3fb27SDimitry Andric         process_sp->RestoreProcessEvents();
115206c3fb27SDimitry Andric 
115306c3fb27SDimitry Andric         if (rebroadcast_first_stop) {
115406c3fb27SDimitry Andric           assert(first_stop_event_sp);
115506c3fb27SDimitry Andric           process_sp->BroadcastEvent(first_stop_event_sp);
11565f757f3fSDimitry Andric           return;
115706c3fb27SDimitry Andric         }
115806c3fb27SDimitry Andric 
115906c3fb27SDimitry Andric         switch (state) {
116006c3fb27SDimitry Andric         case eStateStopped: {
116106c3fb27SDimitry Andric           if (launch_info.GetFlags().Test(eLaunchFlagStopAtEntry))
116206c3fb27SDimitry Andric             break;
116306c3fb27SDimitry Andric           if (synchronous_execution) {
116406c3fb27SDimitry Andric             // Now we have handled the stop-from-attach, and we are just
116506c3fb27SDimitry Andric             // switching to a synchronous resume.  So we should switch to the
116606c3fb27SDimitry Andric             // SyncResume hijacker.
116706c3fb27SDimitry Andric             process_sp->ResumeSynchronous(&result.GetOutputStream());
116806c3fb27SDimitry Andric           } else {
116906c3fb27SDimitry Andric             error = process_sp->Resume();
117006c3fb27SDimitry Andric             if (!error.Success()) {
117106c3fb27SDimitry Andric               result.AppendErrorWithFormat(
117206c3fb27SDimitry Andric                   "process resume at entry point failed: %s",
117306c3fb27SDimitry Andric                   error.AsCString());
117406c3fb27SDimitry Andric             }
117506c3fb27SDimitry Andric           }
117606c3fb27SDimitry Andric         } break;
117706c3fb27SDimitry Andric         default:
117806c3fb27SDimitry Andric           result.AppendErrorWithFormat(
117906c3fb27SDimitry Andric               "initial process state wasn't stopped: %s",
118006c3fb27SDimitry Andric               StateAsCString(state));
118106c3fb27SDimitry Andric           break;
118206c3fb27SDimitry Andric         }
118306c3fb27SDimitry Andric 
11840b57cec5SDimitry Andric         if (process_sp && process_sp->IsAlive()) {
11850b57cec5SDimitry Andric           result.SetStatus(eReturnStatusSuccessFinishNoResult);
11865f757f3fSDimitry Andric           return;
11870b57cec5SDimitry Andric         }
11880b57cec5SDimitry Andric       } else {
11890b57cec5SDimitry Andric         result.AppendError("'platform process launch' uses the current target "
11900b57cec5SDimitry Andric                            "file and arguments, or the executable and its "
11910b57cec5SDimitry Andric                            "arguments can be specified in this command");
11925f757f3fSDimitry Andric         return;
11930b57cec5SDimitry Andric       }
11940b57cec5SDimitry Andric     } else {
11950b57cec5SDimitry Andric       result.AppendError("no platform is selected\n");
11960b57cec5SDimitry Andric     }
11970b57cec5SDimitry Andric   }
11980b57cec5SDimitry Andric 
1199e8d8bef9SDimitry Andric   CommandOptionsProcessLaunch m_options;
120006c3fb27SDimitry Andric   OptionGroupPythonClassWithDict m_class_options;
1201fe6060f1SDimitry Andric   OptionGroupOptions m_all_options;
12020b57cec5SDimitry Andric };
12030b57cec5SDimitry Andric 
12040b57cec5SDimitry Andric // "platform process list"
12050b57cec5SDimitry Andric 
12069dba64beSDimitry Andric static PosixPlatformCommandOptionValidator posix_validator;
12079dba64beSDimitry Andric #define LLDB_OPTIONS_platform_process_list
12089dba64beSDimitry Andric #include "CommandOptions.inc"
12090b57cec5SDimitry Andric 
12100b57cec5SDimitry Andric class CommandObjectPlatformProcessList : public CommandObjectParsed {
12110b57cec5SDimitry Andric public:
12120b57cec5SDimitry Andric   CommandObjectPlatformProcessList(CommandInterpreter &interpreter)
12130b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "platform process list",
12140b57cec5SDimitry Andric                             "List processes on a remote platform by name, pid, "
12150b57cec5SDimitry Andric                             "or many other matching attributes.",
121604eeddc0SDimitry Andric                             "platform process list", 0) {}
12170b57cec5SDimitry Andric 
12180b57cec5SDimitry Andric   ~CommandObjectPlatformProcessList() override = default;
12190b57cec5SDimitry Andric 
12200b57cec5SDimitry Andric   Options *GetOptions() override { return &m_options; }
12210b57cec5SDimitry Andric 
12220b57cec5SDimitry Andric protected:
12235f757f3fSDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
12240b57cec5SDimitry Andric     Target *target = GetDebugger().GetSelectedTarget().get();
12250b57cec5SDimitry Andric     PlatformSP platform_sp;
12260b57cec5SDimitry Andric     if (target) {
12270b57cec5SDimitry Andric       platform_sp = target->GetPlatform();
12280b57cec5SDimitry Andric     }
12290b57cec5SDimitry Andric     if (!platform_sp) {
12300b57cec5SDimitry Andric       platform_sp = GetDebugger().GetPlatformList().GetSelectedPlatform();
12310b57cec5SDimitry Andric     }
12320b57cec5SDimitry Andric 
12330b57cec5SDimitry Andric     if (platform_sp) {
12340b57cec5SDimitry Andric       Status error;
12350b57cec5SDimitry Andric       if (platform_sp) {
12360b57cec5SDimitry Andric         Stream &ostrm = result.GetOutputStream();
12370b57cec5SDimitry Andric 
123881ad6265SDimitry Andric         lldb::pid_t pid = m_options.match_info.GetProcessInfo().GetProcessID();
12390b57cec5SDimitry Andric         if (pid != LLDB_INVALID_PROCESS_ID) {
12400b57cec5SDimitry Andric           ProcessInstanceInfo proc_info;
12410b57cec5SDimitry Andric           if (platform_sp->GetProcessInfo(pid, proc_info)) {
12420b57cec5SDimitry Andric             ProcessInstanceInfo::DumpTableHeader(ostrm, m_options.show_args,
12430b57cec5SDimitry Andric                                                  m_options.verbose);
12440b57cec5SDimitry Andric             proc_info.DumpAsTableRow(ostrm, platform_sp->GetUserIDResolver(),
12450b57cec5SDimitry Andric                                      m_options.show_args, m_options.verbose);
12460b57cec5SDimitry Andric             result.SetStatus(eReturnStatusSuccessFinishResult);
12470b57cec5SDimitry Andric           } else {
12480b57cec5SDimitry Andric             result.AppendErrorWithFormat(
12490b57cec5SDimitry Andric                 "no process found with pid = %" PRIu64 "\n", pid);
12500b57cec5SDimitry Andric           }
12510b57cec5SDimitry Andric         } else {
12520b57cec5SDimitry Andric           ProcessInstanceInfoList proc_infos;
12530b57cec5SDimitry Andric           const uint32_t matches =
12540b57cec5SDimitry Andric               platform_sp->FindProcesses(m_options.match_info, proc_infos);
12550b57cec5SDimitry Andric           const char *match_desc = nullptr;
12560b57cec5SDimitry Andric           const char *match_name =
12570b57cec5SDimitry Andric               m_options.match_info.GetProcessInfo().GetName();
12580b57cec5SDimitry Andric           if (match_name && match_name[0]) {
12590b57cec5SDimitry Andric             switch (m_options.match_info.GetNameMatchType()) {
12600b57cec5SDimitry Andric             case NameMatch::Ignore:
12610b57cec5SDimitry Andric               break;
12620b57cec5SDimitry Andric             case NameMatch::Equals:
12630b57cec5SDimitry Andric               match_desc = "matched";
12640b57cec5SDimitry Andric               break;
12650b57cec5SDimitry Andric             case NameMatch::Contains:
12660b57cec5SDimitry Andric               match_desc = "contained";
12670b57cec5SDimitry Andric               break;
12680b57cec5SDimitry Andric             case NameMatch::StartsWith:
12690b57cec5SDimitry Andric               match_desc = "started with";
12700b57cec5SDimitry Andric               break;
12710b57cec5SDimitry Andric             case NameMatch::EndsWith:
12720b57cec5SDimitry Andric               match_desc = "ended with";
12730b57cec5SDimitry Andric               break;
12740b57cec5SDimitry Andric             case NameMatch::RegularExpression:
12750b57cec5SDimitry Andric               match_desc = "matched the regular expression";
12760b57cec5SDimitry Andric               break;
12770b57cec5SDimitry Andric             }
12780b57cec5SDimitry Andric           }
12790b57cec5SDimitry Andric 
12800b57cec5SDimitry Andric           if (matches == 0) {
12810b57cec5SDimitry Andric             if (match_desc)
1282349cc55cSDimitry Andric               result.AppendErrorWithFormatv(
1283349cc55cSDimitry Andric                   "no processes were found that {0} \"{1}\" on the \"{2}\" "
12840b57cec5SDimitry Andric                   "platform\n",
128581ad6265SDimitry Andric                   match_desc, match_name, platform_sp->GetName());
12860b57cec5SDimitry Andric             else
1287349cc55cSDimitry Andric               result.AppendErrorWithFormatv(
1288349cc55cSDimitry Andric                   "no processes were found on the \"{0}\" platform\n",
128981ad6265SDimitry Andric                   platform_sp->GetName());
12900b57cec5SDimitry Andric           } else {
129181ad6265SDimitry Andric             result.AppendMessageWithFormatv(
129281ad6265SDimitry Andric                 "{0} matching process{1} found on \"{2}\"", matches,
129381ad6265SDimitry Andric                 matches > 1 ? "es were" : " was", platform_sp->GetName());
12940b57cec5SDimitry Andric             if (match_desc)
12950b57cec5SDimitry Andric               result.AppendMessageWithFormat(" whose name %s \"%s\"",
12960b57cec5SDimitry Andric                                              match_desc, match_name);
12970b57cec5SDimitry Andric             result.AppendMessageWithFormat("\n");
12980b57cec5SDimitry Andric             ProcessInstanceInfo::DumpTableHeader(ostrm, m_options.show_args,
12990b57cec5SDimitry Andric                                                  m_options.verbose);
13000b57cec5SDimitry Andric             for (uint32_t i = 0; i < matches; ++i) {
13015ffd83dbSDimitry Andric               proc_infos[i].DumpAsTableRow(
130281ad6265SDimitry Andric                   ostrm, platform_sp->GetUserIDResolver(), m_options.show_args,
130381ad6265SDimitry Andric                   m_options.verbose);
13040b57cec5SDimitry Andric             }
13050b57cec5SDimitry Andric           }
13060b57cec5SDimitry Andric         }
13070b57cec5SDimitry Andric       }
13080b57cec5SDimitry Andric     } else {
13090b57cec5SDimitry Andric       result.AppendError("no platform is selected\n");
13100b57cec5SDimitry Andric     }
13110b57cec5SDimitry Andric   }
13120b57cec5SDimitry Andric 
13130b57cec5SDimitry Andric   class CommandOptions : public Options {
13140b57cec5SDimitry Andric   public:
131581ad6265SDimitry Andric     CommandOptions() = default;
13160b57cec5SDimitry Andric 
13170b57cec5SDimitry Andric     ~CommandOptions() override = default;
13180b57cec5SDimitry Andric 
13190b57cec5SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
13200b57cec5SDimitry Andric                           ExecutionContext *execution_context) override {
13210b57cec5SDimitry Andric       Status error;
13220b57cec5SDimitry Andric       const int short_option = m_getopt_table[option_idx].val;
13230b57cec5SDimitry Andric       bool success = false;
13240b57cec5SDimitry Andric 
13250b57cec5SDimitry Andric       uint32_t id = LLDB_INVALID_PROCESS_ID;
13260b57cec5SDimitry Andric       success = !option_arg.getAsInteger(0, id);
13270b57cec5SDimitry Andric       switch (short_option) {
13280b57cec5SDimitry Andric       case 'p': {
13290b57cec5SDimitry Andric         match_info.GetProcessInfo().SetProcessID(id);
13300b57cec5SDimitry Andric         if (!success)
13310b57cec5SDimitry Andric           error.SetErrorStringWithFormat("invalid process ID string: '%s'",
13320b57cec5SDimitry Andric                                          option_arg.str().c_str());
13330b57cec5SDimitry Andric         break;
13340b57cec5SDimitry Andric       }
13350b57cec5SDimitry Andric       case 'P':
13360b57cec5SDimitry Andric         match_info.GetProcessInfo().SetParentProcessID(id);
13370b57cec5SDimitry Andric         if (!success)
13380b57cec5SDimitry Andric           error.SetErrorStringWithFormat(
13390b57cec5SDimitry Andric               "invalid parent process ID string: '%s'",
13400b57cec5SDimitry Andric               option_arg.str().c_str());
13410b57cec5SDimitry Andric         break;
13420b57cec5SDimitry Andric 
13430b57cec5SDimitry Andric       case 'u':
13440b57cec5SDimitry Andric         match_info.GetProcessInfo().SetUserID(success ? id : UINT32_MAX);
13450b57cec5SDimitry Andric         if (!success)
13460b57cec5SDimitry Andric           error.SetErrorStringWithFormat("invalid user ID string: '%s'",
13470b57cec5SDimitry Andric                                          option_arg.str().c_str());
13480b57cec5SDimitry Andric         break;
13490b57cec5SDimitry Andric 
13500b57cec5SDimitry Andric       case 'U':
13510b57cec5SDimitry Andric         match_info.GetProcessInfo().SetEffectiveUserID(success ? id
13520b57cec5SDimitry Andric                                                                : UINT32_MAX);
13530b57cec5SDimitry Andric         if (!success)
13540b57cec5SDimitry Andric           error.SetErrorStringWithFormat(
13550b57cec5SDimitry Andric               "invalid effective user ID string: '%s'",
13560b57cec5SDimitry Andric               option_arg.str().c_str());
13570b57cec5SDimitry Andric         break;
13580b57cec5SDimitry Andric 
13590b57cec5SDimitry Andric       case 'g':
13600b57cec5SDimitry Andric         match_info.GetProcessInfo().SetGroupID(success ? id : UINT32_MAX);
13610b57cec5SDimitry Andric         if (!success)
13620b57cec5SDimitry Andric           error.SetErrorStringWithFormat("invalid group ID string: '%s'",
13630b57cec5SDimitry Andric                                          option_arg.str().c_str());
13640b57cec5SDimitry Andric         break;
13650b57cec5SDimitry Andric 
13660b57cec5SDimitry Andric       case 'G':
13670b57cec5SDimitry Andric         match_info.GetProcessInfo().SetEffectiveGroupID(success ? id
13680b57cec5SDimitry Andric                                                                 : UINT32_MAX);
13690b57cec5SDimitry Andric         if (!success)
13700b57cec5SDimitry Andric           error.SetErrorStringWithFormat(
13710b57cec5SDimitry Andric               "invalid effective group ID string: '%s'",
13720b57cec5SDimitry Andric               option_arg.str().c_str());
13730b57cec5SDimitry Andric         break;
13740b57cec5SDimitry Andric 
13750b57cec5SDimitry Andric       case 'a': {
13760b57cec5SDimitry Andric         TargetSP target_sp =
13770b57cec5SDimitry Andric             execution_context ? execution_context->GetTargetSP() : TargetSP();
13780b57cec5SDimitry Andric         DebuggerSP debugger_sp =
13790b57cec5SDimitry Andric             target_sp ? target_sp->GetDebugger().shared_from_this()
13800b57cec5SDimitry Andric                       : DebuggerSP();
13810b57cec5SDimitry Andric         PlatformSP platform_sp =
13820b57cec5SDimitry Andric             debugger_sp ? debugger_sp->GetPlatformList().GetSelectedPlatform()
13830b57cec5SDimitry Andric                         : PlatformSP();
13840b57cec5SDimitry Andric         match_info.GetProcessInfo().GetArchitecture() =
13850b57cec5SDimitry Andric             Platform::GetAugmentedArchSpec(platform_sp.get(), option_arg);
13860b57cec5SDimitry Andric       } break;
13870b57cec5SDimitry Andric 
13880b57cec5SDimitry Andric       case 'n':
13890b57cec5SDimitry Andric         match_info.GetProcessInfo().GetExecutableFile().SetFile(
13900b57cec5SDimitry Andric             option_arg, FileSpec::Style::native);
13910b57cec5SDimitry Andric         match_info.SetNameMatchType(NameMatch::Equals);
13920b57cec5SDimitry Andric         break;
13930b57cec5SDimitry Andric 
13940b57cec5SDimitry Andric       case 'e':
13950b57cec5SDimitry Andric         match_info.GetProcessInfo().GetExecutableFile().SetFile(
13960b57cec5SDimitry Andric             option_arg, FileSpec::Style::native);
13970b57cec5SDimitry Andric         match_info.SetNameMatchType(NameMatch::EndsWith);
13980b57cec5SDimitry Andric         break;
13990b57cec5SDimitry Andric 
14000b57cec5SDimitry Andric       case 's':
14010b57cec5SDimitry Andric         match_info.GetProcessInfo().GetExecutableFile().SetFile(
14020b57cec5SDimitry Andric             option_arg, FileSpec::Style::native);
14030b57cec5SDimitry Andric         match_info.SetNameMatchType(NameMatch::StartsWith);
14040b57cec5SDimitry Andric         break;
14050b57cec5SDimitry Andric 
14060b57cec5SDimitry Andric       case 'c':
14070b57cec5SDimitry Andric         match_info.GetProcessInfo().GetExecutableFile().SetFile(
14080b57cec5SDimitry Andric             option_arg, FileSpec::Style::native);
14090b57cec5SDimitry Andric         match_info.SetNameMatchType(NameMatch::Contains);
14100b57cec5SDimitry Andric         break;
14110b57cec5SDimitry Andric 
14120b57cec5SDimitry Andric       case 'r':
14130b57cec5SDimitry Andric         match_info.GetProcessInfo().GetExecutableFile().SetFile(
14140b57cec5SDimitry Andric             option_arg, FileSpec::Style::native);
14150b57cec5SDimitry Andric         match_info.SetNameMatchType(NameMatch::RegularExpression);
14160b57cec5SDimitry Andric         break;
14170b57cec5SDimitry Andric 
14180b57cec5SDimitry Andric       case 'A':
14190b57cec5SDimitry Andric         show_args = true;
14200b57cec5SDimitry Andric         break;
14210b57cec5SDimitry Andric 
14220b57cec5SDimitry Andric       case 'v':
14230b57cec5SDimitry Andric         verbose = true;
14240b57cec5SDimitry Andric         break;
14250b57cec5SDimitry Andric 
14269dba64beSDimitry Andric       case 'x':
14279dba64beSDimitry Andric         match_info.SetMatchAllUsers(true);
14280b57cec5SDimitry Andric         break;
14299dba64beSDimitry Andric 
14309dba64beSDimitry Andric       default:
14319dba64beSDimitry Andric         llvm_unreachable("Unimplemented option");
14320b57cec5SDimitry Andric       }
14330b57cec5SDimitry Andric 
14340b57cec5SDimitry Andric       return error;
14350b57cec5SDimitry Andric     }
14360b57cec5SDimitry Andric 
14370b57cec5SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
14380b57cec5SDimitry Andric       match_info.Clear();
14390b57cec5SDimitry Andric       show_args = false;
14400b57cec5SDimitry Andric       verbose = false;
14410b57cec5SDimitry Andric     }
14420b57cec5SDimitry Andric 
14430b57cec5SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1444bdd1243dSDimitry Andric       return llvm::ArrayRef(g_platform_process_list_options);
14450b57cec5SDimitry Andric     }
14460b57cec5SDimitry Andric 
14470b57cec5SDimitry Andric     // Instance variables to hold the values for command options.
14480b57cec5SDimitry Andric 
14490b57cec5SDimitry Andric     ProcessInstanceInfoMatch match_info;
1450fe6060f1SDimitry Andric     bool show_args = false;
1451fe6060f1SDimitry Andric     bool verbose = false;
14520b57cec5SDimitry Andric   };
14530b57cec5SDimitry Andric 
14540b57cec5SDimitry Andric   CommandOptions m_options;
14550b57cec5SDimitry Andric };
14560b57cec5SDimitry Andric 
14570b57cec5SDimitry Andric // "platform process info"
14580b57cec5SDimitry Andric class CommandObjectPlatformProcessInfo : public CommandObjectParsed {
14590b57cec5SDimitry Andric public:
14600b57cec5SDimitry Andric   CommandObjectPlatformProcessInfo(CommandInterpreter &interpreter)
14610b57cec5SDimitry Andric       : CommandObjectParsed(
14620b57cec5SDimitry Andric             interpreter, "platform process info",
14630b57cec5SDimitry Andric             "Get detailed information for one or more process by process ID.",
14640b57cec5SDimitry Andric             "platform process info <pid> [<pid> <pid> ...]", 0) {
1465*0fca6ea1SDimitry Andric     AddSimpleArgumentList(eArgTypePid, eArgRepeatStar);
14660b57cec5SDimitry Andric   }
14670b57cec5SDimitry Andric 
14680b57cec5SDimitry Andric   ~CommandObjectPlatformProcessInfo() override = default;
14690b57cec5SDimitry Andric 
14700b57cec5SDimitry Andric protected:
14715f757f3fSDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
14720b57cec5SDimitry Andric     Target *target = GetDebugger().GetSelectedTarget().get();
14730b57cec5SDimitry Andric     PlatformSP platform_sp;
14740b57cec5SDimitry Andric     if (target) {
14750b57cec5SDimitry Andric       platform_sp = target->GetPlatform();
14760b57cec5SDimitry Andric     }
14770b57cec5SDimitry Andric     if (!platform_sp) {
14780b57cec5SDimitry Andric       platform_sp = GetDebugger().GetPlatformList().GetSelectedPlatform();
14790b57cec5SDimitry Andric     }
14800b57cec5SDimitry Andric 
14810b57cec5SDimitry Andric     if (platform_sp) {
14820b57cec5SDimitry Andric       const size_t argc = args.GetArgumentCount();
14830b57cec5SDimitry Andric       if (argc > 0) {
14840b57cec5SDimitry Andric         Status error;
14850b57cec5SDimitry Andric 
14860b57cec5SDimitry Andric         if (platform_sp->IsConnected()) {
14870b57cec5SDimitry Andric           Stream &ostrm = result.GetOutputStream();
14880b57cec5SDimitry Andric           for (auto &entry : args.entries()) {
14890b57cec5SDimitry Andric             lldb::pid_t pid;
14909dba64beSDimitry Andric             if (entry.ref().getAsInteger(0, pid)) {
14910b57cec5SDimitry Andric               result.AppendErrorWithFormat("invalid process ID argument '%s'",
14929dba64beSDimitry Andric                                            entry.ref().str().c_str());
14930b57cec5SDimitry Andric               break;
14940b57cec5SDimitry Andric             } else {
14950b57cec5SDimitry Andric               ProcessInstanceInfo proc_info;
14960b57cec5SDimitry Andric               if (platform_sp->GetProcessInfo(pid, proc_info)) {
14970b57cec5SDimitry Andric                 ostrm.Printf("Process information for process %" PRIu64 ":\n",
14980b57cec5SDimitry Andric                              pid);
14990b57cec5SDimitry Andric                 proc_info.Dump(ostrm, platform_sp->GetUserIDResolver());
15000b57cec5SDimitry Andric               } else {
15010b57cec5SDimitry Andric                 ostrm.Printf("error: no process information is available for "
15020b57cec5SDimitry Andric                              "process %" PRIu64 "\n",
15030b57cec5SDimitry Andric                              pid);
15040b57cec5SDimitry Andric               }
15050b57cec5SDimitry Andric               ostrm.EOL();
15060b57cec5SDimitry Andric             }
15070b57cec5SDimitry Andric           }
15080b57cec5SDimitry Andric         } else {
15090b57cec5SDimitry Andric           // Not connected...
1510349cc55cSDimitry Andric           result.AppendErrorWithFormatv("not connected to '{0}'",
1511349cc55cSDimitry Andric                                         platform_sp->GetPluginName());
15120b57cec5SDimitry Andric         }
15130b57cec5SDimitry Andric       } else {
15140b57cec5SDimitry Andric         // No args
15150b57cec5SDimitry Andric         result.AppendError("one or more process id(s) must be specified");
15160b57cec5SDimitry Andric       }
15170b57cec5SDimitry Andric     } else {
15180b57cec5SDimitry Andric       result.AppendError("no platform is currently selected");
15190b57cec5SDimitry Andric     }
15200b57cec5SDimitry Andric   }
15210b57cec5SDimitry Andric };
15220b57cec5SDimitry Andric 
15239dba64beSDimitry Andric #define LLDB_OPTIONS_platform_process_attach
15249dba64beSDimitry Andric #include "CommandOptions.inc"
15250b57cec5SDimitry Andric 
15260b57cec5SDimitry Andric class CommandObjectPlatformProcessAttach : public CommandObjectParsed {
15270b57cec5SDimitry Andric public:
15280b57cec5SDimitry Andric   CommandObjectPlatformProcessAttach(CommandInterpreter &interpreter)
15290b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "platform process attach",
15300b57cec5SDimitry Andric                             "Attach to a process.",
153106c3fb27SDimitry Andric                             "platform process attach <cmd-options>"),
153206c3fb27SDimitry Andric         m_class_options("scripted process", true, 'C', 'k', 'v', 0) {
153306c3fb27SDimitry Andric     m_all_options.Append(&m_options);
153406c3fb27SDimitry Andric     m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2,
153506c3fb27SDimitry Andric                          LLDB_OPT_SET_ALL);
153606c3fb27SDimitry Andric     m_all_options.Finalize();
153706c3fb27SDimitry Andric   }
15380b57cec5SDimitry Andric 
15390b57cec5SDimitry Andric   ~CommandObjectPlatformProcessAttach() override = default;
15400b57cec5SDimitry Andric 
15415f757f3fSDimitry Andric   void DoExecute(Args &command, CommandReturnObject &result) override {
15420b57cec5SDimitry Andric     PlatformSP platform_sp(
15430b57cec5SDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
15440b57cec5SDimitry Andric     if (platform_sp) {
154506c3fb27SDimitry Andric 
154606c3fb27SDimitry Andric       if (!m_class_options.GetName().empty()) {
154706c3fb27SDimitry Andric         m_options.attach_info.SetProcessPluginName("ScriptedProcess");
154806c3fb27SDimitry Andric         ScriptedMetadataSP metadata_sp = std::make_shared<ScriptedMetadata>(
154906c3fb27SDimitry Andric             m_class_options.GetName(), m_class_options.GetStructuredData());
155006c3fb27SDimitry Andric         m_options.attach_info.SetScriptedMetadata(metadata_sp);
155106c3fb27SDimitry Andric       }
155206c3fb27SDimitry Andric 
15530b57cec5SDimitry Andric       Status err;
15540b57cec5SDimitry Andric       ProcessSP remote_process_sp = platform_sp->Attach(
15550b57cec5SDimitry Andric           m_options.attach_info, GetDebugger(), nullptr, err);
15560b57cec5SDimitry Andric       if (err.Fail()) {
15570b57cec5SDimitry Andric         result.AppendError(err.AsCString());
15580b57cec5SDimitry Andric       } else if (!remote_process_sp) {
15590b57cec5SDimitry Andric         result.AppendError("could not attach: unknown reason");
15600b57cec5SDimitry Andric       } else
15610b57cec5SDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishResult);
15620b57cec5SDimitry Andric     } else {
15630b57cec5SDimitry Andric       result.AppendError("no platform is currently selected");
15640b57cec5SDimitry Andric     }
15650b57cec5SDimitry Andric   }
15660b57cec5SDimitry Andric 
156706c3fb27SDimitry Andric   Options *GetOptions() override { return &m_all_options; }
15680b57cec5SDimitry Andric 
15690b57cec5SDimitry Andric protected:
157006c3fb27SDimitry Andric   CommandOptionsProcessAttach m_options;
157106c3fb27SDimitry Andric   OptionGroupPythonClassWithDict m_class_options;
157206c3fb27SDimitry Andric   OptionGroupOptions m_all_options;
15730b57cec5SDimitry Andric };
15740b57cec5SDimitry Andric 
15750b57cec5SDimitry Andric class CommandObjectPlatformProcess : public CommandObjectMultiword {
15760b57cec5SDimitry Andric public:
15770b57cec5SDimitry Andric   // Constructors and Destructors
15780b57cec5SDimitry Andric   CommandObjectPlatformProcess(CommandInterpreter &interpreter)
15790b57cec5SDimitry Andric       : CommandObjectMultiword(interpreter, "platform process",
15800b57cec5SDimitry Andric                                "Commands to query, launch and attach to "
15810b57cec5SDimitry Andric                                "processes on the current platform.",
15820b57cec5SDimitry Andric                                "platform process [attach|launch|list] ...") {
15830b57cec5SDimitry Andric     LoadSubCommand(
15840b57cec5SDimitry Andric         "attach",
15850b57cec5SDimitry Andric         CommandObjectSP(new CommandObjectPlatformProcessAttach(interpreter)));
15860b57cec5SDimitry Andric     LoadSubCommand(
15870b57cec5SDimitry Andric         "launch",
15880b57cec5SDimitry Andric         CommandObjectSP(new CommandObjectPlatformProcessLaunch(interpreter)));
15890b57cec5SDimitry Andric     LoadSubCommand("info", CommandObjectSP(new CommandObjectPlatformProcessInfo(
15900b57cec5SDimitry Andric                                interpreter)));
15910b57cec5SDimitry Andric     LoadSubCommand("list", CommandObjectSP(new CommandObjectPlatformProcessList(
15920b57cec5SDimitry Andric                                interpreter)));
15930b57cec5SDimitry Andric   }
15940b57cec5SDimitry Andric 
15950b57cec5SDimitry Andric   ~CommandObjectPlatformProcess() override = default;
15960b57cec5SDimitry Andric 
15970b57cec5SDimitry Andric private:
15980b57cec5SDimitry Andric   // For CommandObjectPlatform only
15995ffd83dbSDimitry Andric   CommandObjectPlatformProcess(const CommandObjectPlatformProcess &) = delete;
16005ffd83dbSDimitry Andric   const CommandObjectPlatformProcess &
16015ffd83dbSDimitry Andric   operator=(const CommandObjectPlatformProcess &) = delete;
16020b57cec5SDimitry Andric };
16030b57cec5SDimitry Andric 
16040b57cec5SDimitry Andric // "platform shell"
16059dba64beSDimitry Andric #define LLDB_OPTIONS_platform_shell
16069dba64beSDimitry Andric #include "CommandOptions.inc"
16070b57cec5SDimitry Andric 
16080b57cec5SDimitry Andric class CommandObjectPlatformShell : public CommandObjectRaw {
16090b57cec5SDimitry Andric public:
16100b57cec5SDimitry Andric   class CommandOptions : public Options {
16110b57cec5SDimitry Andric   public:
161281ad6265SDimitry Andric     CommandOptions() = default;
16130b57cec5SDimitry Andric 
16140b57cec5SDimitry Andric     ~CommandOptions() override = default;
16150b57cec5SDimitry Andric 
16160b57cec5SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1617bdd1243dSDimitry Andric       return llvm::ArrayRef(g_platform_shell_options);
16180b57cec5SDimitry Andric     }
16190b57cec5SDimitry Andric 
16200b57cec5SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
16210b57cec5SDimitry Andric                           ExecutionContext *execution_context) override {
16220b57cec5SDimitry Andric       Status error;
16230b57cec5SDimitry Andric 
16240b57cec5SDimitry Andric       const char short_option = (char)GetDefinitions()[option_idx].short_option;
16250b57cec5SDimitry Andric 
16260b57cec5SDimitry Andric       switch (short_option) {
16275ffd83dbSDimitry Andric       case 'h':
16285ffd83dbSDimitry Andric         m_use_host_platform = true;
16295ffd83dbSDimitry Andric         break;
16300b57cec5SDimitry Andric       case 't':
16310b57cec5SDimitry Andric         uint32_t timeout_sec;
16320b57cec5SDimitry Andric         if (option_arg.getAsInteger(10, timeout_sec))
16330b57cec5SDimitry Andric           error.SetErrorStringWithFormat(
16340b57cec5SDimitry Andric               "could not convert \"%s\" to a numeric value.",
16350b57cec5SDimitry Andric               option_arg.str().c_str());
16360b57cec5SDimitry Andric         else
16375ffd83dbSDimitry Andric           m_timeout = std::chrono::seconds(timeout_sec);
16380b57cec5SDimitry Andric         break;
1639e8d8bef9SDimitry Andric       case 's': {
1640e8d8bef9SDimitry Andric         if (option_arg.empty()) {
1641e8d8bef9SDimitry Andric           error.SetErrorStringWithFormat(
1642e8d8bef9SDimitry Andric               "missing shell interpreter path for option -i|--interpreter.");
1643e8d8bef9SDimitry Andric           return error;
1644e8d8bef9SDimitry Andric         }
1645e8d8bef9SDimitry Andric 
1646e8d8bef9SDimitry Andric         m_shell_interpreter = option_arg.str();
1647e8d8bef9SDimitry Andric         break;
1648e8d8bef9SDimitry Andric       }
16490b57cec5SDimitry Andric       default:
16509dba64beSDimitry Andric         llvm_unreachable("Unimplemented option");
16510b57cec5SDimitry Andric       }
16520b57cec5SDimitry Andric 
16530b57cec5SDimitry Andric       return error;
16540b57cec5SDimitry Andric     }
16550b57cec5SDimitry Andric 
16565ffd83dbSDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
16575ffd83dbSDimitry Andric       m_timeout.reset();
16585ffd83dbSDimitry Andric       m_use_host_platform = false;
1659e8d8bef9SDimitry Andric       m_shell_interpreter.clear();
16605ffd83dbSDimitry Andric     }
16610b57cec5SDimitry Andric 
16625ffd83dbSDimitry Andric     Timeout<std::micro> m_timeout = std::chrono::seconds(10);
16635ffd83dbSDimitry Andric     bool m_use_host_platform;
1664e8d8bef9SDimitry Andric     std::string m_shell_interpreter;
16650b57cec5SDimitry Andric   };
16660b57cec5SDimitry Andric 
16670b57cec5SDimitry Andric   CommandObjectPlatformShell(CommandInterpreter &interpreter)
16680b57cec5SDimitry Andric       : CommandObjectRaw(interpreter, "platform shell",
16690b57cec5SDimitry Andric                          "Run a shell command on the current platform.",
167081ad6265SDimitry Andric                          "platform shell <shell-command>", 0) {
1671*0fca6ea1SDimitry Andric     AddSimpleArgumentList(eArgTypeNone, eArgRepeatStar);
167281ad6265SDimitry Andric   }
16730b57cec5SDimitry Andric 
16740b57cec5SDimitry Andric   ~CommandObjectPlatformShell() override = default;
16750b57cec5SDimitry Andric 
16760b57cec5SDimitry Andric   Options *GetOptions() override { return &m_options; }
16770b57cec5SDimitry Andric 
16785f757f3fSDimitry Andric   void DoExecute(llvm::StringRef raw_command_line,
16790b57cec5SDimitry Andric                  CommandReturnObject &result) override {
16800b57cec5SDimitry Andric     ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext();
16810b57cec5SDimitry Andric     m_options.NotifyOptionParsingStarting(&exe_ctx);
16820b57cec5SDimitry Andric 
16830b57cec5SDimitry Andric     // Print out an usage syntax on an empty command line.
16840b57cec5SDimitry Andric     if (raw_command_line.empty()) {
16850b57cec5SDimitry Andric       result.GetOutputStream().Printf("%s\n", this->GetSyntax().str().c_str());
16865f757f3fSDimitry Andric       return;
16870b57cec5SDimitry Andric     }
16880b57cec5SDimitry Andric 
16895ffd83dbSDimitry Andric     const bool is_alias = !raw_command_line.contains("platform");
16900b57cec5SDimitry Andric     OptionsWithRaw args(raw_command_line);
16910b57cec5SDimitry Andric 
16920b57cec5SDimitry Andric     if (args.HasArgs())
16930b57cec5SDimitry Andric       if (!ParseOptions(args.GetArgs(), result))
16945f757f3fSDimitry Andric         return;
16950b57cec5SDimitry Andric 
16965ffd83dbSDimitry Andric     if (args.GetRawPart().empty()) {
16975ffd83dbSDimitry Andric       result.GetOutputStream().Printf("%s <shell-command>\n",
16985ffd83dbSDimitry Andric                                       is_alias ? "shell" : "platform shell");
16995f757f3fSDimitry Andric       return;
17005ffd83dbSDimitry Andric     }
17015ffd83dbSDimitry Andric 
1702e8d8bef9SDimitry Andric     llvm::StringRef cmd = args.GetRawPart();
1703e8d8bef9SDimitry Andric 
17040b57cec5SDimitry Andric     PlatformSP platform_sp(
17055ffd83dbSDimitry Andric         m_options.m_use_host_platform
17065ffd83dbSDimitry Andric             ? Platform::GetHostPlatform()
17075ffd83dbSDimitry Andric             : GetDebugger().GetPlatformList().GetSelectedPlatform());
17080b57cec5SDimitry Andric     Status error;
17090b57cec5SDimitry Andric     if (platform_sp) {
17100b57cec5SDimitry Andric       FileSpec working_dir{};
17110b57cec5SDimitry Andric       std::string output;
17120b57cec5SDimitry Andric       int status = -1;
17130b57cec5SDimitry Andric       int signo = -1;
1714e8d8bef9SDimitry Andric       error = (platform_sp->RunShellCommand(m_options.m_shell_interpreter, cmd,
1715e8d8bef9SDimitry Andric                                             working_dir, &status, &signo,
17165ffd83dbSDimitry Andric                                             &output, m_options.m_timeout));
17170b57cec5SDimitry Andric       if (!output.empty())
17180b57cec5SDimitry Andric         result.GetOutputStream().PutCString(output);
17190b57cec5SDimitry Andric       if (status > 0) {
17200b57cec5SDimitry Andric         if (signo > 0) {
17210b57cec5SDimitry Andric           const char *signo_cstr = Host::GetSignalAsCString(signo);
17220b57cec5SDimitry Andric           if (signo_cstr)
17230b57cec5SDimitry Andric             result.GetOutputStream().Printf(
17240b57cec5SDimitry Andric                 "error: command returned with status %i and signal %s\n",
17250b57cec5SDimitry Andric                 status, signo_cstr);
17260b57cec5SDimitry Andric           else
17270b57cec5SDimitry Andric             result.GetOutputStream().Printf(
17280b57cec5SDimitry Andric                 "error: command returned with status %i and signal %i\n",
17290b57cec5SDimitry Andric                 status, signo);
17300b57cec5SDimitry Andric         } else
17310b57cec5SDimitry Andric           result.GetOutputStream().Printf(
17320b57cec5SDimitry Andric               "error: command returned with status %i\n", status);
17330b57cec5SDimitry Andric       }
17340b57cec5SDimitry Andric     } else {
17350b57cec5SDimitry Andric       result.GetOutputStream().Printf(
17360b57cec5SDimitry Andric           "error: cannot run remote shell commands without a platform\n");
17370b57cec5SDimitry Andric       error.SetErrorString(
17380b57cec5SDimitry Andric           "error: cannot run remote shell commands without a platform");
17390b57cec5SDimitry Andric     }
17400b57cec5SDimitry Andric 
17410b57cec5SDimitry Andric     if (error.Fail()) {
17420b57cec5SDimitry Andric       result.AppendError(error.AsCString());
17430b57cec5SDimitry Andric     } else {
17440b57cec5SDimitry Andric       result.SetStatus(eReturnStatusSuccessFinishResult);
17450b57cec5SDimitry Andric     }
17460b57cec5SDimitry Andric   }
17470b57cec5SDimitry Andric 
17480b57cec5SDimitry Andric   CommandOptions m_options;
17490b57cec5SDimitry Andric };
17500b57cec5SDimitry Andric 
17510b57cec5SDimitry Andric // "platform install" - install a target to a remote end
17520b57cec5SDimitry Andric class CommandObjectPlatformInstall : public CommandObjectParsed {
17530b57cec5SDimitry Andric public:
17540b57cec5SDimitry Andric   CommandObjectPlatformInstall(CommandInterpreter &interpreter)
17550b57cec5SDimitry Andric       : CommandObjectParsed(
17560b57cec5SDimitry Andric             interpreter, "platform target-install",
17570b57cec5SDimitry Andric             "Install a target (bundle or executable file) to the remote end.",
175881ad6265SDimitry Andric             "platform target-install <local-thing> <remote-sandbox>", 0) {
175981ad6265SDimitry Andric     CommandArgumentData local_arg{eArgTypePath, eArgRepeatPlain};
1760*0fca6ea1SDimitry Andric     CommandArgumentData remote_arg{eArgTypeRemotePath, eArgRepeatPlain};
176181ad6265SDimitry Andric     m_arguments.push_back({local_arg});
176281ad6265SDimitry Andric     m_arguments.push_back({remote_arg});
176381ad6265SDimitry Andric   }
17640b57cec5SDimitry Andric 
17650b57cec5SDimitry Andric   ~CommandObjectPlatformInstall() override = default;
17660b57cec5SDimitry Andric 
1767e8d8bef9SDimitry Andric   void
1768e8d8bef9SDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
1769e8d8bef9SDimitry Andric                            OptionElementVector &opt_element_vector) override {
1770e8d8bef9SDimitry Andric     if (request.GetCursorIndex())
1771e8d8bef9SDimitry Andric       return;
177206c3fb27SDimitry Andric     lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
177306c3fb27SDimitry Andric         GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr);
1774e8d8bef9SDimitry Andric   }
1775e8d8bef9SDimitry Andric 
17765f757f3fSDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
17770b57cec5SDimitry Andric     if (args.GetArgumentCount() != 2) {
17780b57cec5SDimitry Andric       result.AppendError("platform target-install takes two arguments");
17795f757f3fSDimitry Andric       return;
17800b57cec5SDimitry Andric     }
17810b57cec5SDimitry Andric     // TODO: move the bulk of this code over to the platform itself
17820b57cec5SDimitry Andric     FileSpec src(args.GetArgumentAtIndex(0));
17830b57cec5SDimitry Andric     FileSystem::Instance().Resolve(src);
17840b57cec5SDimitry Andric     FileSpec dst(args.GetArgumentAtIndex(1));
17850b57cec5SDimitry Andric     if (!FileSystem::Instance().Exists(src)) {
17860b57cec5SDimitry Andric       result.AppendError("source location does not exist or is not accessible");
17875f757f3fSDimitry Andric       return;
17880b57cec5SDimitry Andric     }
17890b57cec5SDimitry Andric     PlatformSP platform_sp(
17900b57cec5SDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
17910b57cec5SDimitry Andric     if (!platform_sp) {
17920b57cec5SDimitry Andric       result.AppendError("no platform currently selected");
17935f757f3fSDimitry Andric       return;
17940b57cec5SDimitry Andric     }
17950b57cec5SDimitry Andric 
17960b57cec5SDimitry Andric     Status error = platform_sp->Install(src, dst);
17970b57cec5SDimitry Andric     if (error.Success()) {
17980b57cec5SDimitry Andric       result.SetStatus(eReturnStatusSuccessFinishNoResult);
17990b57cec5SDimitry Andric     } else {
18000b57cec5SDimitry Andric       result.AppendErrorWithFormat("install failed: %s", error.AsCString());
18010b57cec5SDimitry Andric     }
18020b57cec5SDimitry Andric   }
18030b57cec5SDimitry Andric };
18040b57cec5SDimitry Andric 
18050b57cec5SDimitry Andric CommandObjectPlatform::CommandObjectPlatform(CommandInterpreter &interpreter)
18060b57cec5SDimitry Andric     : CommandObjectMultiword(
18070b57cec5SDimitry Andric           interpreter, "platform", "Commands to manage and create platforms.",
18080b57cec5SDimitry Andric           "platform [connect|disconnect|info|list|status|select] ...") {
18090b57cec5SDimitry Andric   LoadSubCommand("select",
18100b57cec5SDimitry Andric                  CommandObjectSP(new CommandObjectPlatformSelect(interpreter)));
18110b57cec5SDimitry Andric   LoadSubCommand("list",
18120b57cec5SDimitry Andric                  CommandObjectSP(new CommandObjectPlatformList(interpreter)));
18130b57cec5SDimitry Andric   LoadSubCommand("status",
18140b57cec5SDimitry Andric                  CommandObjectSP(new CommandObjectPlatformStatus(interpreter)));
18150b57cec5SDimitry Andric   LoadSubCommand("connect", CommandObjectSP(
18160b57cec5SDimitry Andric                                 new CommandObjectPlatformConnect(interpreter)));
18170b57cec5SDimitry Andric   LoadSubCommand(
18180b57cec5SDimitry Andric       "disconnect",
18190b57cec5SDimitry Andric       CommandObjectSP(new CommandObjectPlatformDisconnect(interpreter)));
18200b57cec5SDimitry Andric   LoadSubCommand("settings", CommandObjectSP(new CommandObjectPlatformSettings(
18210b57cec5SDimitry Andric                                  interpreter)));
18220b57cec5SDimitry Andric   LoadSubCommand("mkdir",
18230b57cec5SDimitry Andric                  CommandObjectSP(new CommandObjectPlatformMkDir(interpreter)));
18240b57cec5SDimitry Andric   LoadSubCommand("file",
18250b57cec5SDimitry Andric                  CommandObjectSP(new CommandObjectPlatformFile(interpreter)));
1826349cc55cSDimitry Andric   LoadSubCommand("file-exists",
1827349cc55cSDimitry Andric       CommandObjectSP(new CommandObjectPlatformFileExists(interpreter)));
18280b57cec5SDimitry Andric   LoadSubCommand("get-file", CommandObjectSP(new CommandObjectPlatformGetFile(
18290b57cec5SDimitry Andric                                  interpreter)));
1830349cc55cSDimitry Andric   LoadSubCommand("get-permissions",
1831349cc55cSDimitry Andric       CommandObjectSP(new CommandObjectPlatformGetPermissions(interpreter)));
18320b57cec5SDimitry Andric   LoadSubCommand("get-size", CommandObjectSP(new CommandObjectPlatformGetSize(
18330b57cec5SDimitry Andric                                  interpreter)));
18340b57cec5SDimitry Andric   LoadSubCommand("put-file", CommandObjectSP(new CommandObjectPlatformPutFile(
18350b57cec5SDimitry Andric                                  interpreter)));
18360b57cec5SDimitry Andric   LoadSubCommand("process", CommandObjectSP(
18370b57cec5SDimitry Andric                                 new CommandObjectPlatformProcess(interpreter)));
18380b57cec5SDimitry Andric   LoadSubCommand("shell",
18390b57cec5SDimitry Andric                  CommandObjectSP(new CommandObjectPlatformShell(interpreter)));
18400b57cec5SDimitry Andric   LoadSubCommand(
18410b57cec5SDimitry Andric       "target-install",
18420b57cec5SDimitry Andric       CommandObjectSP(new CommandObjectPlatformInstall(interpreter)));
18430b57cec5SDimitry Andric }
18440b57cec5SDimitry Andric 
18450b57cec5SDimitry Andric CommandObjectPlatform::~CommandObjectPlatform() = default;
1846