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"
10fe013be4SDimitry 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"
22fe013be4SDimitry 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"
27fe013be4SDimitry Andric #include "lldb/Utility/ScriptedMetadata.h"
28fe013be4SDimitry 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 
ParsePermissionString(llvm::StringRef permissions)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
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)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 
OptionParsingStarting(ExecutionContext * execution_context)1280b57cec5SDimitry Andric   void OptionParsingStarting(ExecutionContext *execution_context) override {
1290b57cec5SDimitry Andric     m_permissions = 0;
1300b57cec5SDimitry Andric   }
1310b57cec5SDimitry Andric 
GetDefinitions()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:
CommandObjectPlatformSelect(CommandInterpreter & interpreter)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();
15881ad6265SDimitry Andric     CommandArgumentData platform_arg{eArgTypePlatform, eArgRepeatPlain};
15981ad6265SDimitry Andric     m_arguments.push_back({platform_arg});
1600b57cec5SDimitry Andric   }
1610b57cec5SDimitry Andric 
1620b57cec5SDimitry Andric   ~CommandObjectPlatformSelect() override = default;
1630b57cec5SDimitry Andric 
HandleCompletion(CompletionRequest & request)1649dba64beSDimitry Andric   void HandleCompletion(CompletionRequest &request) override {
165fe013be4SDimitry Andric     lldb_private::CommandCompletions::PlatformPluginNames(
166fe013be4SDimitry Andric         GetCommandInterpreter(), request, nullptr);
1670b57cec5SDimitry Andric   }
1680b57cec5SDimitry Andric 
GetOptions()1690b57cec5SDimitry Andric   Options *GetOptions() override { return &m_option_group; }
1700b57cec5SDimitry Andric 
1710b57cec5SDimitry Andric protected:
DoExecute(Args & args,CommandReturnObject & result)172*c9157d92SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
1730b57cec5SDimitry Andric     if (args.GetArgumentCount() == 1) {
1740b57cec5SDimitry Andric       const char *platform_name = args.GetArgumentAtIndex(0);
1750b57cec5SDimitry Andric       if (platform_name && platform_name[0]) {
1760b57cec5SDimitry Andric         const bool select = true;
1770b57cec5SDimitry Andric         m_platform_options.SetPlatformName(platform_name);
1780b57cec5SDimitry Andric         Status error;
1790b57cec5SDimitry Andric         ArchSpec platform_arch;
1800b57cec5SDimitry Andric         PlatformSP platform_sp(m_platform_options.CreatePlatformWithOptions(
1810b57cec5SDimitry Andric             m_interpreter, ArchSpec(), select, error, platform_arch));
1820b57cec5SDimitry Andric         if (platform_sp) {
1830b57cec5SDimitry Andric           GetDebugger().GetPlatformList().SetSelectedPlatform(platform_sp);
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric           platform_sp->GetStatus(result.GetOutputStream());
1860b57cec5SDimitry Andric           result.SetStatus(eReturnStatusSuccessFinishResult);
1870b57cec5SDimitry Andric         } else {
1880b57cec5SDimitry Andric           result.AppendError(error.AsCString());
1890b57cec5SDimitry Andric         }
1900b57cec5SDimitry Andric       } else {
1910b57cec5SDimitry Andric         result.AppendError("invalid platform name");
1920b57cec5SDimitry Andric       }
1930b57cec5SDimitry Andric     } else {
1940b57cec5SDimitry Andric       result.AppendError(
1950b57cec5SDimitry Andric           "platform create takes a platform name as an argument\n");
1960b57cec5SDimitry Andric     }
1970b57cec5SDimitry Andric   }
1980b57cec5SDimitry Andric 
1990b57cec5SDimitry Andric   OptionGroupOptions m_option_group;
2000b57cec5SDimitry Andric   OptionGroupPlatform m_platform_options;
2010b57cec5SDimitry Andric };
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric // "platform list"
2040b57cec5SDimitry Andric class CommandObjectPlatformList : public CommandObjectParsed {
2050b57cec5SDimitry Andric public:
CommandObjectPlatformList(CommandInterpreter & interpreter)2060b57cec5SDimitry Andric   CommandObjectPlatformList(CommandInterpreter &interpreter)
2070b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "platform list",
2080b57cec5SDimitry Andric                             "List all platforms that are available.", nullptr,
2090b57cec5SDimitry Andric                             0) {}
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric   ~CommandObjectPlatformList() override = default;
2120b57cec5SDimitry Andric 
2130b57cec5SDimitry Andric protected:
DoExecute(Args & args,CommandReturnObject & result)214*c9157d92SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
2150b57cec5SDimitry Andric     Stream &ostrm = result.GetOutputStream();
2160b57cec5SDimitry Andric     ostrm.Printf("Available platforms:\n");
2170b57cec5SDimitry Andric 
2180b57cec5SDimitry Andric     PlatformSP host_platform_sp(Platform::GetHostPlatform());
219349cc55cSDimitry Andric     ostrm.Format("{0}: {1}\n", host_platform_sp->GetPluginName(),
2200b57cec5SDimitry Andric                  host_platform_sp->GetDescription());
2210b57cec5SDimitry Andric 
2220b57cec5SDimitry Andric     uint32_t idx;
2230b57cec5SDimitry Andric     for (idx = 0; true; ++idx) {
224349cc55cSDimitry Andric       llvm::StringRef plugin_name =
2250b57cec5SDimitry Andric           PluginManager::GetPlatformPluginNameAtIndex(idx);
226349cc55cSDimitry Andric       if (plugin_name.empty())
2270b57cec5SDimitry Andric         break;
228349cc55cSDimitry Andric       llvm::StringRef plugin_desc =
2290b57cec5SDimitry Andric           PluginManager::GetPlatformPluginDescriptionAtIndex(idx);
230349cc55cSDimitry Andric       ostrm.Format("{0}: {1}\n", plugin_name, plugin_desc);
2310b57cec5SDimitry Andric     }
2320b57cec5SDimitry Andric 
2330b57cec5SDimitry Andric     if (idx == 0) {
2340b57cec5SDimitry Andric       result.AppendError("no platforms are available\n");
2350b57cec5SDimitry Andric     } else
2360b57cec5SDimitry Andric       result.SetStatus(eReturnStatusSuccessFinishResult);
2370b57cec5SDimitry Andric   }
2380b57cec5SDimitry Andric };
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric // "platform status"
2410b57cec5SDimitry Andric class CommandObjectPlatformStatus : public CommandObjectParsed {
2420b57cec5SDimitry Andric public:
CommandObjectPlatformStatus(CommandInterpreter & interpreter)2430b57cec5SDimitry Andric   CommandObjectPlatformStatus(CommandInterpreter &interpreter)
2440b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "platform status",
2450b57cec5SDimitry Andric                             "Display status for the current platform.", nullptr,
2460b57cec5SDimitry Andric                             0) {}
2470b57cec5SDimitry Andric 
2480b57cec5SDimitry Andric   ~CommandObjectPlatformStatus() override = default;
2490b57cec5SDimitry Andric 
2500b57cec5SDimitry Andric protected:
DoExecute(Args & args,CommandReturnObject & result)251*c9157d92SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
2520b57cec5SDimitry Andric     Stream &ostrm = result.GetOutputStream();
2530b57cec5SDimitry Andric 
2540b57cec5SDimitry Andric     Target *target = GetDebugger().GetSelectedTarget().get();
2550b57cec5SDimitry Andric     PlatformSP platform_sp;
2560b57cec5SDimitry Andric     if (target) {
2570b57cec5SDimitry Andric       platform_sp = target->GetPlatform();
2580b57cec5SDimitry Andric     }
2590b57cec5SDimitry Andric     if (!platform_sp) {
2600b57cec5SDimitry Andric       platform_sp = GetDebugger().GetPlatformList().GetSelectedPlatform();
2610b57cec5SDimitry Andric     }
2620b57cec5SDimitry Andric     if (platform_sp) {
2630b57cec5SDimitry Andric       platform_sp->GetStatus(ostrm);
2640b57cec5SDimitry Andric       result.SetStatus(eReturnStatusSuccessFinishResult);
2650b57cec5SDimitry Andric     } else {
2660b57cec5SDimitry Andric       result.AppendError("no platform is currently selected\n");
2670b57cec5SDimitry Andric     }
2680b57cec5SDimitry Andric   }
2690b57cec5SDimitry Andric };
2700b57cec5SDimitry Andric 
2710b57cec5SDimitry Andric // "platform connect <connect-url>"
2720b57cec5SDimitry Andric class CommandObjectPlatformConnect : public CommandObjectParsed {
2730b57cec5SDimitry Andric public:
CommandObjectPlatformConnect(CommandInterpreter & interpreter)2740b57cec5SDimitry Andric   CommandObjectPlatformConnect(CommandInterpreter &interpreter)
2750b57cec5SDimitry Andric       : CommandObjectParsed(
2760b57cec5SDimitry Andric             interpreter, "platform connect",
2770b57cec5SDimitry Andric             "Select the current platform by providing a connection URL.",
27881ad6265SDimitry Andric             "platform connect <connect-url>", 0) {
27981ad6265SDimitry Andric     CommandArgumentData platform_arg{eArgTypeConnectURL, eArgRepeatPlain};
28081ad6265SDimitry Andric     m_arguments.push_back({platform_arg});
28181ad6265SDimitry Andric   }
2820b57cec5SDimitry Andric 
2830b57cec5SDimitry Andric   ~CommandObjectPlatformConnect() override = default;
2840b57cec5SDimitry Andric 
2850b57cec5SDimitry Andric protected:
DoExecute(Args & args,CommandReturnObject & result)286*c9157d92SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
2870b57cec5SDimitry Andric     Stream &ostrm = result.GetOutputStream();
2880b57cec5SDimitry Andric 
2890b57cec5SDimitry Andric     PlatformSP platform_sp(
2900b57cec5SDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
2910b57cec5SDimitry Andric     if (platform_sp) {
2920b57cec5SDimitry Andric       Status error(platform_sp->ConnectRemote(args));
2930b57cec5SDimitry Andric       if (error.Success()) {
2940b57cec5SDimitry Andric         platform_sp->GetStatus(ostrm);
2950b57cec5SDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishResult);
2960b57cec5SDimitry Andric 
2970b57cec5SDimitry Andric         platform_sp->ConnectToWaitingProcesses(GetDebugger(), error);
2980b57cec5SDimitry Andric         if (error.Fail()) {
2990b57cec5SDimitry Andric           result.AppendError(error.AsCString());
3000b57cec5SDimitry Andric         }
3010b57cec5SDimitry Andric       } else {
3020b57cec5SDimitry Andric         result.AppendErrorWithFormat("%s\n", error.AsCString());
3030b57cec5SDimitry Andric       }
3040b57cec5SDimitry Andric     } else {
3050b57cec5SDimitry Andric       result.AppendError("no platform is currently selected\n");
3060b57cec5SDimitry Andric     }
3070b57cec5SDimitry Andric   }
3080b57cec5SDimitry Andric 
GetOptions()3090b57cec5SDimitry Andric   Options *GetOptions() override {
3100b57cec5SDimitry Andric     PlatformSP platform_sp(
3110b57cec5SDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
3120b57cec5SDimitry Andric     OptionGroupOptions *m_platform_options = nullptr;
3130b57cec5SDimitry Andric     if (platform_sp) {
3140b57cec5SDimitry Andric       m_platform_options = platform_sp->GetConnectionOptions(m_interpreter);
3150b57cec5SDimitry Andric       if (m_platform_options != nullptr && !m_platform_options->m_did_finalize)
3160b57cec5SDimitry Andric         m_platform_options->Finalize();
3170b57cec5SDimitry Andric     }
3180b57cec5SDimitry Andric     return m_platform_options;
3190b57cec5SDimitry Andric   }
3200b57cec5SDimitry Andric };
3210b57cec5SDimitry Andric 
3220b57cec5SDimitry Andric // "platform disconnect"
3230b57cec5SDimitry Andric class CommandObjectPlatformDisconnect : public CommandObjectParsed {
3240b57cec5SDimitry Andric public:
CommandObjectPlatformDisconnect(CommandInterpreter & interpreter)3250b57cec5SDimitry Andric   CommandObjectPlatformDisconnect(CommandInterpreter &interpreter)
3260b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "platform disconnect",
3270b57cec5SDimitry Andric                             "Disconnect from the current platform.",
3280b57cec5SDimitry Andric                             "platform disconnect", 0) {}
3290b57cec5SDimitry Andric 
3300b57cec5SDimitry Andric   ~CommandObjectPlatformDisconnect() override = default;
3310b57cec5SDimitry Andric 
3320b57cec5SDimitry Andric protected:
DoExecute(Args & args,CommandReturnObject & result)333*c9157d92SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
3340b57cec5SDimitry Andric     PlatformSP platform_sp(
3350b57cec5SDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
3360b57cec5SDimitry Andric     if (platform_sp) {
3370b57cec5SDimitry Andric       if (args.GetArgumentCount() == 0) {
3380b57cec5SDimitry Andric         Status error;
3390b57cec5SDimitry Andric 
3400b57cec5SDimitry Andric         if (platform_sp->IsConnected()) {
3410b57cec5SDimitry Andric           // Cache the instance name if there is one since we are about to
3420b57cec5SDimitry Andric           // disconnect and the name might go with it.
3430b57cec5SDimitry Andric           const char *hostname_cstr = platform_sp->GetHostname();
3440b57cec5SDimitry Andric           std::string hostname;
3450b57cec5SDimitry Andric           if (hostname_cstr)
3460b57cec5SDimitry Andric             hostname.assign(hostname_cstr);
3470b57cec5SDimitry Andric 
3480b57cec5SDimitry Andric           error = platform_sp->DisconnectRemote();
3490b57cec5SDimitry Andric           if (error.Success()) {
3500b57cec5SDimitry Andric             Stream &ostrm = result.GetOutputStream();
3510b57cec5SDimitry Andric             if (hostname.empty())
352349cc55cSDimitry Andric               ostrm.Format("Disconnected from \"{0}\"\n",
353349cc55cSDimitry Andric                            platform_sp->GetPluginName());
3540b57cec5SDimitry Andric             else
3550b57cec5SDimitry Andric               ostrm.Printf("Disconnected from \"%s\"\n", hostname.c_str());
3560b57cec5SDimitry Andric             result.SetStatus(eReturnStatusSuccessFinishResult);
3570b57cec5SDimitry Andric           } else {
3580b57cec5SDimitry Andric             result.AppendErrorWithFormat("%s", error.AsCString());
3590b57cec5SDimitry Andric           }
3600b57cec5SDimitry Andric         } else {
3610b57cec5SDimitry Andric           // Not connected...
362349cc55cSDimitry Andric           result.AppendErrorWithFormatv("not connected to '{0}'",
363349cc55cSDimitry Andric                                         platform_sp->GetPluginName());
3640b57cec5SDimitry Andric         }
3650b57cec5SDimitry Andric       } else {
3660b57cec5SDimitry Andric         // Bad args
3670b57cec5SDimitry Andric         result.AppendError(
3680b57cec5SDimitry Andric             "\"platform disconnect\" doesn't take any arguments");
3690b57cec5SDimitry Andric       }
3700b57cec5SDimitry Andric     } else {
3710b57cec5SDimitry Andric       result.AppendError("no platform is currently selected");
3720b57cec5SDimitry Andric     }
3730b57cec5SDimitry Andric   }
3740b57cec5SDimitry Andric };
3750b57cec5SDimitry Andric 
3760b57cec5SDimitry Andric // "platform settings"
3770b57cec5SDimitry Andric class CommandObjectPlatformSettings : public CommandObjectParsed {
3780b57cec5SDimitry Andric public:
CommandObjectPlatformSettings(CommandInterpreter & interpreter)3790b57cec5SDimitry Andric   CommandObjectPlatformSettings(CommandInterpreter &interpreter)
3800b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "platform settings",
381bdd1243dSDimitry Andric                             "Set settings for the current target's platform.",
3820b57cec5SDimitry Andric                             "platform settings", 0),
383e8d8bef9SDimitry Andric         m_option_working_dir(LLDB_OPT_SET_1, false, "working-dir", 'w',
384fe013be4SDimitry Andric                              lldb::eRemoteDiskDirectoryCompletion, eArgTypePath,
3850b57cec5SDimitry Andric                              "The working directory for the platform.") {
3860b57cec5SDimitry Andric     m_options.Append(&m_option_working_dir, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
3870b57cec5SDimitry Andric   }
3880b57cec5SDimitry Andric 
3890b57cec5SDimitry Andric   ~CommandObjectPlatformSettings() override = default;
3900b57cec5SDimitry Andric 
3910b57cec5SDimitry Andric protected:
DoExecute(Args & args,CommandReturnObject & result)392*c9157d92SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
3930b57cec5SDimitry Andric     PlatformSP platform_sp(
3940b57cec5SDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
3950b57cec5SDimitry Andric     if (platform_sp) {
3960b57cec5SDimitry Andric       if (m_option_working_dir.GetOptionValue().OptionWasSet())
3970b57cec5SDimitry Andric         platform_sp->SetWorkingDirectory(
3980b57cec5SDimitry Andric             m_option_working_dir.GetOptionValue().GetCurrentValue());
3990b57cec5SDimitry Andric     } else {
4000b57cec5SDimitry Andric       result.AppendError("no platform is currently selected");
4010b57cec5SDimitry Andric     }
4020b57cec5SDimitry Andric   }
4030b57cec5SDimitry Andric 
GetOptions()4040b57cec5SDimitry Andric   Options *GetOptions() override {
4050b57cec5SDimitry Andric     if (!m_options.DidFinalize())
4060b57cec5SDimitry Andric       m_options.Finalize();
4070b57cec5SDimitry Andric     return &m_options;
4080b57cec5SDimitry Andric   }
4090b57cec5SDimitry Andric 
4100b57cec5SDimitry Andric   OptionGroupOptions m_options;
4110b57cec5SDimitry Andric   OptionGroupFile m_option_working_dir;
4120b57cec5SDimitry Andric };
4130b57cec5SDimitry Andric 
4140b57cec5SDimitry Andric // "platform mkdir"
4150b57cec5SDimitry Andric class CommandObjectPlatformMkDir : public CommandObjectParsed {
4160b57cec5SDimitry Andric public:
CommandObjectPlatformMkDir(CommandInterpreter & interpreter)4170b57cec5SDimitry Andric   CommandObjectPlatformMkDir(CommandInterpreter &interpreter)
4180b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "platform mkdir",
4190b57cec5SDimitry Andric                             "Make a new directory on the remote end.", nullptr,
42081ad6265SDimitry Andric                             0) {
42181ad6265SDimitry Andric     CommandArgumentData thread_arg{eArgTypePath, eArgRepeatPlain};
42281ad6265SDimitry Andric     m_arguments.push_back({thread_arg});
42381ad6265SDimitry Andric   }
4240b57cec5SDimitry Andric 
4250b57cec5SDimitry Andric   ~CommandObjectPlatformMkDir() override = default;
4260b57cec5SDimitry Andric 
DoExecute(Args & args,CommandReturnObject & result)427*c9157d92SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
4280b57cec5SDimitry Andric     PlatformSP platform_sp(
4290b57cec5SDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
4300b57cec5SDimitry Andric     if (platform_sp) {
4310b57cec5SDimitry Andric       std::string cmd_line;
4320b57cec5SDimitry Andric       args.GetCommandString(cmd_line);
4330b57cec5SDimitry Andric       uint32_t mode;
4340b57cec5SDimitry Andric       const OptionPermissions *options_permissions =
4350b57cec5SDimitry Andric           (const OptionPermissions *)m_options.GetGroupWithOption('r');
4360b57cec5SDimitry Andric       if (options_permissions)
4370b57cec5SDimitry Andric         mode = options_permissions->m_permissions;
4380b57cec5SDimitry Andric       else
4390b57cec5SDimitry Andric         mode = lldb::eFilePermissionsUserRWX | lldb::eFilePermissionsGroupRWX |
4400b57cec5SDimitry Andric                lldb::eFilePermissionsWorldRX;
4410b57cec5SDimitry Andric       Status error = platform_sp->MakeDirectory(FileSpec(cmd_line), mode);
4420b57cec5SDimitry Andric       if (error.Success()) {
4430b57cec5SDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishResult);
4440b57cec5SDimitry Andric       } else {
4450b57cec5SDimitry Andric         result.AppendError(error.AsCString());
4460b57cec5SDimitry Andric       }
4470b57cec5SDimitry Andric     } else {
4480b57cec5SDimitry Andric       result.AppendError("no platform currently selected\n");
4490b57cec5SDimitry Andric     }
4500b57cec5SDimitry Andric   }
4510b57cec5SDimitry Andric 
GetOptions()4520b57cec5SDimitry Andric   Options *GetOptions() override {
4530b57cec5SDimitry Andric     if (!m_options.DidFinalize()) {
454bdd1243dSDimitry Andric       m_options.Append(&m_option_permissions);
4550b57cec5SDimitry Andric       m_options.Finalize();
4560b57cec5SDimitry Andric     }
4570b57cec5SDimitry Andric     return &m_options;
4580b57cec5SDimitry Andric   }
4590b57cec5SDimitry Andric 
460bdd1243dSDimitry Andric   OptionPermissions m_option_permissions;
4610b57cec5SDimitry Andric   OptionGroupOptions m_options;
4620b57cec5SDimitry Andric };
4630b57cec5SDimitry Andric 
4640b57cec5SDimitry Andric // "platform fopen"
4650b57cec5SDimitry Andric class CommandObjectPlatformFOpen : public CommandObjectParsed {
4660b57cec5SDimitry Andric public:
CommandObjectPlatformFOpen(CommandInterpreter & interpreter)4670b57cec5SDimitry Andric   CommandObjectPlatformFOpen(CommandInterpreter &interpreter)
4680b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "platform file open",
46981ad6265SDimitry Andric                             "Open a file on the remote end.", nullptr, 0) {
47081ad6265SDimitry Andric     CommandArgumentData path_arg{eArgTypePath, eArgRepeatPlain};
47181ad6265SDimitry Andric     m_arguments.push_back({path_arg});
47281ad6265SDimitry Andric   }
4730b57cec5SDimitry Andric 
4740b57cec5SDimitry Andric   ~CommandObjectPlatformFOpen() override = default;
4750b57cec5SDimitry Andric 
476e8d8bef9SDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)477e8d8bef9SDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
478e8d8bef9SDimitry Andric                            OptionElementVector &opt_element_vector) override {
479e8d8bef9SDimitry Andric     if (request.GetCursorIndex() == 0)
480fe013be4SDimitry Andric       lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
481fe013be4SDimitry Andric           GetCommandInterpreter(), lldb::eRemoteDiskFileCompletion, request,
482fe013be4SDimitry Andric           nullptr);
483e8d8bef9SDimitry Andric   }
484e8d8bef9SDimitry Andric 
DoExecute(Args & args,CommandReturnObject & result)485*c9157d92SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
4860b57cec5SDimitry Andric     PlatformSP platform_sp(
4870b57cec5SDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
4880b57cec5SDimitry Andric     if (platform_sp) {
4890b57cec5SDimitry Andric       Status error;
4900b57cec5SDimitry Andric       std::string cmd_line;
4910b57cec5SDimitry Andric       args.GetCommandString(cmd_line);
4920b57cec5SDimitry Andric       mode_t perms;
4930b57cec5SDimitry Andric       const OptionPermissions *options_permissions =
4940b57cec5SDimitry Andric           (const OptionPermissions *)m_options.GetGroupWithOption('r');
4950b57cec5SDimitry Andric       if (options_permissions)
4960b57cec5SDimitry Andric         perms = options_permissions->m_permissions;
4970b57cec5SDimitry Andric       else
4980b57cec5SDimitry Andric         perms = lldb::eFilePermissionsUserRW | lldb::eFilePermissionsGroupRW |
4990b57cec5SDimitry Andric                 lldb::eFilePermissionsWorldRead;
5000b57cec5SDimitry Andric       lldb::user_id_t fd = platform_sp->OpenFile(
5010b57cec5SDimitry Andric           FileSpec(cmd_line),
502349cc55cSDimitry Andric           File::eOpenOptionReadWrite | File::eOpenOptionCanCreate,
5030b57cec5SDimitry Andric           perms, error);
5040b57cec5SDimitry Andric       if (error.Success()) {
5050b57cec5SDimitry Andric         result.AppendMessageWithFormat("File Descriptor = %" PRIu64 "\n", fd);
5060b57cec5SDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishResult);
5070b57cec5SDimitry Andric       } else {
5080b57cec5SDimitry Andric         result.AppendError(error.AsCString());
5090b57cec5SDimitry Andric       }
5100b57cec5SDimitry Andric     } else {
5110b57cec5SDimitry Andric       result.AppendError("no platform currently selected\n");
5120b57cec5SDimitry Andric     }
5130b57cec5SDimitry Andric   }
5140b57cec5SDimitry Andric 
GetOptions()5150b57cec5SDimitry Andric   Options *GetOptions() override {
5160b57cec5SDimitry Andric     if (!m_options.DidFinalize()) {
517bdd1243dSDimitry Andric       m_options.Append(&m_option_permissions);
5180b57cec5SDimitry Andric       m_options.Finalize();
5190b57cec5SDimitry Andric     }
5200b57cec5SDimitry Andric     return &m_options;
5210b57cec5SDimitry Andric   }
5220b57cec5SDimitry Andric 
523bdd1243dSDimitry Andric   OptionPermissions m_option_permissions;
5240b57cec5SDimitry Andric   OptionGroupOptions m_options;
5250b57cec5SDimitry Andric };
5260b57cec5SDimitry Andric 
5270b57cec5SDimitry Andric // "platform fclose"
5280b57cec5SDimitry Andric class CommandObjectPlatformFClose : public CommandObjectParsed {
5290b57cec5SDimitry Andric public:
CommandObjectPlatformFClose(CommandInterpreter & interpreter)5300b57cec5SDimitry Andric   CommandObjectPlatformFClose(CommandInterpreter &interpreter)
5310b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "platform file close",
53281ad6265SDimitry Andric                             "Close a file on the remote end.", nullptr, 0) {
53381ad6265SDimitry Andric     CommandArgumentData path_arg{eArgTypeUnsignedInteger, eArgRepeatPlain};
53481ad6265SDimitry Andric     m_arguments.push_back({path_arg});
53581ad6265SDimitry Andric   }
5360b57cec5SDimitry Andric 
5370b57cec5SDimitry Andric   ~CommandObjectPlatformFClose() override = default;
5380b57cec5SDimitry Andric 
DoExecute(Args & args,CommandReturnObject & result)539*c9157d92SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
5400b57cec5SDimitry Andric     PlatformSP platform_sp(
5410b57cec5SDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
5420b57cec5SDimitry Andric     if (platform_sp) {
5430b57cec5SDimitry Andric       std::string cmd_line;
5440b57cec5SDimitry Andric       args.GetCommandString(cmd_line);
5455ffd83dbSDimitry Andric       lldb::user_id_t fd;
5465ffd83dbSDimitry Andric       if (!llvm::to_integer(cmd_line, fd)) {
5475ffd83dbSDimitry Andric         result.AppendErrorWithFormatv("'{0}' is not a valid file descriptor.\n",
5485ffd83dbSDimitry Andric                                       cmd_line);
549*c9157d92SDimitry Andric         return;
5505ffd83dbSDimitry Andric       }
5510b57cec5SDimitry Andric       Status error;
5520b57cec5SDimitry Andric       bool success = platform_sp->CloseFile(fd, error);
5530b57cec5SDimitry Andric       if (success) {
5540b57cec5SDimitry Andric         result.AppendMessageWithFormat("file %" PRIu64 " closed.\n", fd);
5550b57cec5SDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishResult);
5560b57cec5SDimitry Andric       } else {
5570b57cec5SDimitry Andric         result.AppendError(error.AsCString());
5580b57cec5SDimitry Andric       }
5590b57cec5SDimitry Andric     } else {
5600b57cec5SDimitry Andric       result.AppendError("no platform currently selected\n");
5610b57cec5SDimitry Andric     }
5620b57cec5SDimitry Andric   }
5630b57cec5SDimitry Andric };
5640b57cec5SDimitry Andric 
5650b57cec5SDimitry Andric // "platform fread"
5660b57cec5SDimitry Andric 
5679dba64beSDimitry Andric #define LLDB_OPTIONS_platform_fread
5689dba64beSDimitry Andric #include "CommandOptions.inc"
5690b57cec5SDimitry Andric 
5700b57cec5SDimitry Andric class CommandObjectPlatformFRead : public CommandObjectParsed {
5710b57cec5SDimitry Andric public:
CommandObjectPlatformFRead(CommandInterpreter & interpreter)5720b57cec5SDimitry Andric   CommandObjectPlatformFRead(CommandInterpreter &interpreter)
5730b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "platform file read",
5740b57cec5SDimitry Andric                             "Read data from a file on the remote end.", nullptr,
57581ad6265SDimitry Andric                             0) {
57681ad6265SDimitry Andric     CommandArgumentData path_arg{eArgTypeUnsignedInteger, eArgRepeatPlain};
57781ad6265SDimitry Andric     m_arguments.push_back({path_arg});
57881ad6265SDimitry Andric   }
5790b57cec5SDimitry Andric 
5800b57cec5SDimitry Andric   ~CommandObjectPlatformFRead() override = default;
5810b57cec5SDimitry Andric 
DoExecute(Args & args,CommandReturnObject & result)582*c9157d92SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
5830b57cec5SDimitry Andric     PlatformSP platform_sp(
5840b57cec5SDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
5850b57cec5SDimitry Andric     if (platform_sp) {
5860b57cec5SDimitry Andric       std::string cmd_line;
5870b57cec5SDimitry Andric       args.GetCommandString(cmd_line);
5885ffd83dbSDimitry Andric       lldb::user_id_t fd;
5895ffd83dbSDimitry Andric       if (!llvm::to_integer(cmd_line, fd)) {
5905ffd83dbSDimitry Andric         result.AppendErrorWithFormatv("'{0}' is not a valid file descriptor.\n",
5915ffd83dbSDimitry Andric                                       cmd_line);
592*c9157d92SDimitry Andric         return;
5935ffd83dbSDimitry Andric       }
5940b57cec5SDimitry Andric       std::string buffer(m_options.m_count, 0);
5950b57cec5SDimitry Andric       Status error;
596349cc55cSDimitry Andric       uint64_t retcode = platform_sp->ReadFile(
5970b57cec5SDimitry Andric           fd, m_options.m_offset, &buffer[0], m_options.m_count, error);
598349cc55cSDimitry Andric       if (retcode != UINT64_MAX) {
599349cc55cSDimitry Andric         result.AppendMessageWithFormat("Return = %" PRIu64 "\n", retcode);
6000b57cec5SDimitry Andric         result.AppendMessageWithFormat("Data = \"%s\"\n", buffer.c_str());
6010b57cec5SDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishResult);
6020b57cec5SDimitry Andric       } else {
603349cc55cSDimitry Andric         result.AppendError(error.AsCString());
604349cc55cSDimitry Andric       }
605349cc55cSDimitry Andric     } else {
6060b57cec5SDimitry Andric       result.AppendError("no platform currently selected\n");
6070b57cec5SDimitry Andric     }
6080b57cec5SDimitry Andric   }
6090b57cec5SDimitry Andric 
GetOptions()6100b57cec5SDimitry Andric   Options *GetOptions() override { return &m_options; }
6110b57cec5SDimitry Andric 
6120b57cec5SDimitry Andric protected:
6130b57cec5SDimitry Andric   class CommandOptions : public Options {
6140b57cec5SDimitry Andric   public:
61581ad6265SDimitry Andric     CommandOptions() = default;
6160b57cec5SDimitry Andric 
6170b57cec5SDimitry Andric     ~CommandOptions() override = default;
6180b57cec5SDimitry Andric 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)6190b57cec5SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
6200b57cec5SDimitry Andric                           ExecutionContext *execution_context) override {
6210b57cec5SDimitry Andric       Status error;
6220b57cec5SDimitry Andric       char short_option = (char)m_getopt_table[option_idx].val;
6230b57cec5SDimitry Andric 
6240b57cec5SDimitry Andric       switch (short_option) {
6250b57cec5SDimitry Andric       case 'o':
6260b57cec5SDimitry Andric         if (option_arg.getAsInteger(0, m_offset))
6270b57cec5SDimitry Andric           error.SetErrorStringWithFormat("invalid offset: '%s'",
6280b57cec5SDimitry Andric                                          option_arg.str().c_str());
6290b57cec5SDimitry Andric         break;
6300b57cec5SDimitry Andric       case 'c':
6310b57cec5SDimitry Andric         if (option_arg.getAsInteger(0, m_count))
6320b57cec5SDimitry Andric           error.SetErrorStringWithFormat("invalid offset: '%s'",
6330b57cec5SDimitry Andric                                          option_arg.str().c_str());
6340b57cec5SDimitry Andric         break;
6350b57cec5SDimitry Andric       default:
6369dba64beSDimitry Andric         llvm_unreachable("Unimplemented option");
6370b57cec5SDimitry Andric       }
6380b57cec5SDimitry Andric 
6390b57cec5SDimitry Andric       return error;
6400b57cec5SDimitry Andric     }
6410b57cec5SDimitry Andric 
OptionParsingStarting(ExecutionContext * execution_context)6420b57cec5SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
6430b57cec5SDimitry Andric       m_offset = 0;
6440b57cec5SDimitry Andric       m_count = 1;
6450b57cec5SDimitry Andric     }
6460b57cec5SDimitry Andric 
GetDefinitions()6470b57cec5SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
648bdd1243dSDimitry Andric       return llvm::ArrayRef(g_platform_fread_options);
6490b57cec5SDimitry Andric     }
6500b57cec5SDimitry Andric 
6510b57cec5SDimitry Andric     // Instance variables to hold the values for command options.
6520b57cec5SDimitry Andric 
6530b57cec5SDimitry Andric     uint32_t m_offset;
6540b57cec5SDimitry Andric     uint32_t m_count;
6550b57cec5SDimitry Andric   };
6560b57cec5SDimitry Andric 
6570b57cec5SDimitry Andric   CommandOptions m_options;
6580b57cec5SDimitry Andric };
6590b57cec5SDimitry Andric 
6600b57cec5SDimitry Andric // "platform fwrite"
6610b57cec5SDimitry Andric 
6629dba64beSDimitry Andric #define LLDB_OPTIONS_platform_fwrite
6639dba64beSDimitry Andric #include "CommandOptions.inc"
6640b57cec5SDimitry Andric 
6650b57cec5SDimitry Andric class CommandObjectPlatformFWrite : public CommandObjectParsed {
6660b57cec5SDimitry Andric public:
CommandObjectPlatformFWrite(CommandInterpreter & interpreter)6670b57cec5SDimitry Andric   CommandObjectPlatformFWrite(CommandInterpreter &interpreter)
6680b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "platform file write",
6690b57cec5SDimitry Andric                             "Write data to a file on the remote end.", nullptr,
67081ad6265SDimitry Andric                             0) {
67181ad6265SDimitry Andric     CommandArgumentData path_arg{eArgTypeUnsignedInteger, eArgRepeatPlain};
67281ad6265SDimitry Andric     m_arguments.push_back({path_arg});
67381ad6265SDimitry Andric   }
6740b57cec5SDimitry Andric 
6750b57cec5SDimitry Andric   ~CommandObjectPlatformFWrite() override = default;
6760b57cec5SDimitry Andric 
DoExecute(Args & args,CommandReturnObject & result)677*c9157d92SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
6780b57cec5SDimitry Andric     PlatformSP platform_sp(
6790b57cec5SDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
6800b57cec5SDimitry Andric     if (platform_sp) {
6810b57cec5SDimitry Andric       std::string cmd_line;
6820b57cec5SDimitry Andric       args.GetCommandString(cmd_line);
6830b57cec5SDimitry Andric       Status error;
6845ffd83dbSDimitry Andric       lldb::user_id_t fd;
6855ffd83dbSDimitry Andric       if (!llvm::to_integer(cmd_line, fd)) {
6865ffd83dbSDimitry Andric         result.AppendErrorWithFormatv("'{0}' is not a valid file descriptor.",
6875ffd83dbSDimitry Andric                                       cmd_line);
688*c9157d92SDimitry Andric         return;
6895ffd83dbSDimitry Andric       }
690349cc55cSDimitry Andric       uint64_t retcode =
6910b57cec5SDimitry Andric           platform_sp->WriteFile(fd, m_options.m_offset, &m_options.m_data[0],
6920b57cec5SDimitry Andric                                  m_options.m_data.size(), error);
693349cc55cSDimitry Andric       if (retcode != UINT64_MAX) {
694349cc55cSDimitry Andric         result.AppendMessageWithFormat("Return = %" PRIu64 "\n", retcode);
6950b57cec5SDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishResult);
6960b57cec5SDimitry Andric       } else {
697349cc55cSDimitry Andric         result.AppendError(error.AsCString());
698349cc55cSDimitry Andric       }
699349cc55cSDimitry Andric     } else {
7000b57cec5SDimitry Andric       result.AppendError("no platform currently selected\n");
7010b57cec5SDimitry Andric     }
7020b57cec5SDimitry Andric   }
7030b57cec5SDimitry Andric 
GetOptions()7040b57cec5SDimitry Andric   Options *GetOptions() override { return &m_options; }
7050b57cec5SDimitry Andric 
7060b57cec5SDimitry Andric protected:
7070b57cec5SDimitry Andric   class CommandOptions : public Options {
7080b57cec5SDimitry Andric   public:
70981ad6265SDimitry Andric     CommandOptions() = default;
7100b57cec5SDimitry Andric 
7110b57cec5SDimitry Andric     ~CommandOptions() override = default;
7120b57cec5SDimitry Andric 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)7130b57cec5SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
7140b57cec5SDimitry Andric                           ExecutionContext *execution_context) override {
7150b57cec5SDimitry Andric       Status error;
7160b57cec5SDimitry Andric       char short_option = (char)m_getopt_table[option_idx].val;
7170b57cec5SDimitry Andric 
7180b57cec5SDimitry Andric       switch (short_option) {
7190b57cec5SDimitry Andric       case 'o':
7200b57cec5SDimitry Andric         if (option_arg.getAsInteger(0, m_offset))
7210b57cec5SDimitry Andric           error.SetErrorStringWithFormat("invalid offset: '%s'",
7220b57cec5SDimitry Andric                                          option_arg.str().c_str());
7230b57cec5SDimitry Andric         break;
7240b57cec5SDimitry Andric       case 'd':
7255ffd83dbSDimitry Andric         m_data.assign(std::string(option_arg));
7260b57cec5SDimitry Andric         break;
7270b57cec5SDimitry Andric       default:
7289dba64beSDimitry Andric         llvm_unreachable("Unimplemented option");
7290b57cec5SDimitry Andric       }
7300b57cec5SDimitry Andric 
7310b57cec5SDimitry Andric       return error;
7320b57cec5SDimitry Andric     }
7330b57cec5SDimitry Andric 
OptionParsingStarting(ExecutionContext * execution_context)7340b57cec5SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
7350b57cec5SDimitry Andric       m_offset = 0;
7360b57cec5SDimitry Andric       m_data.clear();
7370b57cec5SDimitry Andric     }
7380b57cec5SDimitry Andric 
GetDefinitions()7390b57cec5SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
740bdd1243dSDimitry Andric       return llvm::ArrayRef(g_platform_fwrite_options);
7410b57cec5SDimitry Andric     }
7420b57cec5SDimitry Andric 
7430b57cec5SDimitry Andric     // Instance variables to hold the values for command options.
7440b57cec5SDimitry Andric 
7450b57cec5SDimitry Andric     uint32_t m_offset;
7460b57cec5SDimitry Andric     std::string m_data;
7470b57cec5SDimitry Andric   };
7480b57cec5SDimitry Andric 
7490b57cec5SDimitry Andric   CommandOptions m_options;
7500b57cec5SDimitry Andric };
7510b57cec5SDimitry Andric 
7520b57cec5SDimitry Andric class CommandObjectPlatformFile : public CommandObjectMultiword {
7530b57cec5SDimitry Andric public:
7540b57cec5SDimitry Andric   // Constructors and Destructors
CommandObjectPlatformFile(CommandInterpreter & interpreter)7550b57cec5SDimitry Andric   CommandObjectPlatformFile(CommandInterpreter &interpreter)
7560b57cec5SDimitry Andric       : CommandObjectMultiword(
7570b57cec5SDimitry Andric             interpreter, "platform file",
7580b57cec5SDimitry Andric             "Commands to access files on the current platform.",
7590b57cec5SDimitry Andric             "platform file [open|close|read|write] ...") {
7600b57cec5SDimitry Andric     LoadSubCommand(
7610b57cec5SDimitry Andric         "open", CommandObjectSP(new CommandObjectPlatformFOpen(interpreter)));
7620b57cec5SDimitry Andric     LoadSubCommand(
7630b57cec5SDimitry Andric         "close", CommandObjectSP(new CommandObjectPlatformFClose(interpreter)));
7640b57cec5SDimitry Andric     LoadSubCommand(
7650b57cec5SDimitry Andric         "read", CommandObjectSP(new CommandObjectPlatformFRead(interpreter)));
7660b57cec5SDimitry Andric     LoadSubCommand(
7670b57cec5SDimitry Andric         "write", CommandObjectSP(new CommandObjectPlatformFWrite(interpreter)));
7680b57cec5SDimitry Andric   }
7690b57cec5SDimitry Andric 
7700b57cec5SDimitry Andric   ~CommandObjectPlatformFile() override = default;
7710b57cec5SDimitry Andric 
7720b57cec5SDimitry Andric private:
7730b57cec5SDimitry Andric   // For CommandObjectPlatform only
7745ffd83dbSDimitry Andric   CommandObjectPlatformFile(const CommandObjectPlatformFile &) = delete;
7755ffd83dbSDimitry Andric   const CommandObjectPlatformFile &
7765ffd83dbSDimitry Andric   operator=(const CommandObjectPlatformFile &) = delete;
7770b57cec5SDimitry Andric };
7780b57cec5SDimitry Andric 
7790b57cec5SDimitry Andric // "platform get-file remote-file-path host-file-path"
7800b57cec5SDimitry Andric class CommandObjectPlatformGetFile : public CommandObjectParsed {
7810b57cec5SDimitry Andric public:
CommandObjectPlatformGetFile(CommandInterpreter & interpreter)7820b57cec5SDimitry Andric   CommandObjectPlatformGetFile(CommandInterpreter &interpreter)
7830b57cec5SDimitry Andric       : CommandObjectParsed(
7840b57cec5SDimitry Andric             interpreter, "platform get-file",
7850b57cec5SDimitry Andric             "Transfer a file from the remote end to the local host.",
7860b57cec5SDimitry Andric             "platform get-file <remote-file-spec> <local-file-spec>", 0) {
7870b57cec5SDimitry Andric     SetHelpLong(
7880b57cec5SDimitry Andric         R"(Examples:
7890b57cec5SDimitry Andric 
7900b57cec5SDimitry Andric (lldb) platform get-file /the/remote/file/path /the/local/file/path
7910b57cec5SDimitry Andric 
7920b57cec5SDimitry Andric     Transfer a file from the remote end with file path /the/remote/file/path to the local host.)");
7930b57cec5SDimitry Andric 
7940b57cec5SDimitry Andric     CommandArgumentEntry arg1, arg2;
7950b57cec5SDimitry Andric     CommandArgumentData file_arg_remote, file_arg_host;
7960b57cec5SDimitry Andric 
7970b57cec5SDimitry Andric     // Define the first (and only) variant of this arg.
7980b57cec5SDimitry Andric     file_arg_remote.arg_type = eArgTypeFilename;
7990b57cec5SDimitry Andric     file_arg_remote.arg_repetition = eArgRepeatPlain;
8000b57cec5SDimitry Andric     // There is only one variant this argument could be; put it into the
8010b57cec5SDimitry Andric     // argument entry.
8020b57cec5SDimitry Andric     arg1.push_back(file_arg_remote);
8030b57cec5SDimitry Andric 
8040b57cec5SDimitry Andric     // Define the second (and only) variant of this arg.
8050b57cec5SDimitry Andric     file_arg_host.arg_type = eArgTypeFilename;
8060b57cec5SDimitry Andric     file_arg_host.arg_repetition = eArgRepeatPlain;
8070b57cec5SDimitry Andric     // There is only one variant this argument could be; put it into the
8080b57cec5SDimitry Andric     // argument entry.
8090b57cec5SDimitry Andric     arg2.push_back(file_arg_host);
8100b57cec5SDimitry Andric 
8110b57cec5SDimitry Andric     // Push the data for the first and the second arguments into the
8120b57cec5SDimitry Andric     // m_arguments vector.
8130b57cec5SDimitry Andric     m_arguments.push_back(arg1);
8140b57cec5SDimitry Andric     m_arguments.push_back(arg2);
8150b57cec5SDimitry Andric   }
8160b57cec5SDimitry Andric 
8170b57cec5SDimitry Andric   ~CommandObjectPlatformGetFile() override = default;
8180b57cec5SDimitry Andric 
819e8d8bef9SDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)820e8d8bef9SDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
821e8d8bef9SDimitry Andric                            OptionElementVector &opt_element_vector) override {
822e8d8bef9SDimitry Andric     if (request.GetCursorIndex() == 0)
823fe013be4SDimitry Andric       lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
824fe013be4SDimitry Andric           GetCommandInterpreter(), lldb::eRemoteDiskFileCompletion, request,
825fe013be4SDimitry Andric           nullptr);
826e8d8bef9SDimitry Andric     else if (request.GetCursorIndex() == 1)
827fe013be4SDimitry Andric       lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
828fe013be4SDimitry Andric           GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr);
829e8d8bef9SDimitry Andric   }
830e8d8bef9SDimitry Andric 
DoExecute(Args & args,CommandReturnObject & result)831*c9157d92SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
8320b57cec5SDimitry Andric     // If the number of arguments is incorrect, issue an error message.
8330b57cec5SDimitry Andric     if (args.GetArgumentCount() != 2) {
834fe6060f1SDimitry Andric       result.AppendError("required arguments missing; specify both the "
835fe6060f1SDimitry Andric                          "source and destination file paths");
836*c9157d92SDimitry Andric       return;
8370b57cec5SDimitry Andric     }
8380b57cec5SDimitry Andric 
8390b57cec5SDimitry Andric     PlatformSP platform_sp(
8400b57cec5SDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
8410b57cec5SDimitry Andric     if (platform_sp) {
8420b57cec5SDimitry Andric       const char *remote_file_path = args.GetArgumentAtIndex(0);
8430b57cec5SDimitry Andric       const char *local_file_path = args.GetArgumentAtIndex(1);
8440b57cec5SDimitry Andric       Status error = platform_sp->GetFile(FileSpec(remote_file_path),
8450b57cec5SDimitry Andric                                           FileSpec(local_file_path));
8460b57cec5SDimitry Andric       if (error.Success()) {
8470b57cec5SDimitry Andric         result.AppendMessageWithFormat(
8480b57cec5SDimitry Andric             "successfully get-file from %s (remote) to %s (host)\n",
8490b57cec5SDimitry Andric             remote_file_path, local_file_path);
8500b57cec5SDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishResult);
8510b57cec5SDimitry Andric       } else {
8520b57cec5SDimitry Andric         result.AppendMessageWithFormat("get-file failed: %s\n",
8530b57cec5SDimitry Andric                                        error.AsCString());
8540b57cec5SDimitry Andric       }
8550b57cec5SDimitry Andric     } else {
8560b57cec5SDimitry Andric       result.AppendError("no platform currently selected\n");
8570b57cec5SDimitry Andric     }
8580b57cec5SDimitry Andric   }
8590b57cec5SDimitry Andric };
8600b57cec5SDimitry Andric 
8610b57cec5SDimitry Andric // "platform get-size remote-file-path"
8620b57cec5SDimitry Andric class CommandObjectPlatformGetSize : public CommandObjectParsed {
8630b57cec5SDimitry Andric public:
CommandObjectPlatformGetSize(CommandInterpreter & interpreter)8640b57cec5SDimitry Andric   CommandObjectPlatformGetSize(CommandInterpreter &interpreter)
8650b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "platform get-size",
8660b57cec5SDimitry Andric                             "Get the file size from the remote end.",
8670b57cec5SDimitry Andric                             "platform get-size <remote-file-spec>", 0) {
8680b57cec5SDimitry Andric     SetHelpLong(
8690b57cec5SDimitry Andric         R"(Examples:
8700b57cec5SDimitry Andric 
8710b57cec5SDimitry Andric (lldb) platform get-size /the/remote/file/path
8720b57cec5SDimitry Andric 
8730b57cec5SDimitry Andric     Get the file size from the remote end with path /the/remote/file/path.)");
8740b57cec5SDimitry Andric 
8750b57cec5SDimitry Andric     CommandArgumentEntry arg1;
8760b57cec5SDimitry Andric     CommandArgumentData file_arg_remote;
8770b57cec5SDimitry Andric 
8780b57cec5SDimitry Andric     // Define the first (and only) variant of this arg.
8790b57cec5SDimitry Andric     file_arg_remote.arg_type = eArgTypeFilename;
8800b57cec5SDimitry Andric     file_arg_remote.arg_repetition = eArgRepeatPlain;
8810b57cec5SDimitry Andric     // There is only one variant this argument could be; put it into the
8820b57cec5SDimitry Andric     // argument entry.
8830b57cec5SDimitry Andric     arg1.push_back(file_arg_remote);
8840b57cec5SDimitry Andric 
8850b57cec5SDimitry Andric     // Push the data for the first argument into the m_arguments vector.
8860b57cec5SDimitry Andric     m_arguments.push_back(arg1);
8870b57cec5SDimitry Andric   }
8880b57cec5SDimitry Andric 
8890b57cec5SDimitry Andric   ~CommandObjectPlatformGetSize() override = default;
8900b57cec5SDimitry Andric 
891e8d8bef9SDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)892e8d8bef9SDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
893e8d8bef9SDimitry Andric                            OptionElementVector &opt_element_vector) override {
894e8d8bef9SDimitry Andric     if (request.GetCursorIndex() != 0)
895e8d8bef9SDimitry Andric       return;
896e8d8bef9SDimitry Andric 
897fe013be4SDimitry Andric     lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
898fe013be4SDimitry Andric         GetCommandInterpreter(), lldb::eRemoteDiskFileCompletion, request,
899fe013be4SDimitry Andric         nullptr);
900e8d8bef9SDimitry Andric   }
901e8d8bef9SDimitry Andric 
DoExecute(Args & args,CommandReturnObject & result)902*c9157d92SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
9030b57cec5SDimitry Andric     // If the number of arguments is incorrect, issue an error message.
9040b57cec5SDimitry Andric     if (args.GetArgumentCount() != 1) {
905fe6060f1SDimitry Andric       result.AppendError("required argument missing; specify the source file "
906fe6060f1SDimitry Andric                          "path as the only argument");
907*c9157d92SDimitry Andric       return;
9080b57cec5SDimitry Andric     }
9090b57cec5SDimitry Andric 
9100b57cec5SDimitry Andric     PlatformSP platform_sp(
9110b57cec5SDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
9120b57cec5SDimitry Andric     if (platform_sp) {
9130b57cec5SDimitry Andric       std::string remote_file_path(args.GetArgumentAtIndex(0));
9140b57cec5SDimitry Andric       user_id_t size = platform_sp->GetFileSize(FileSpec(remote_file_path));
9150b57cec5SDimitry Andric       if (size != UINT64_MAX) {
9160b57cec5SDimitry Andric         result.AppendMessageWithFormat("File size of %s (remote): %" PRIu64
9170b57cec5SDimitry Andric                                        "\n",
9180b57cec5SDimitry Andric                                        remote_file_path.c_str(), size);
9190b57cec5SDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishResult);
9200b57cec5SDimitry Andric       } else {
9210b57cec5SDimitry Andric         result.AppendMessageWithFormat(
9220b57cec5SDimitry Andric             "Error getting file size of %s (remote)\n",
9230b57cec5SDimitry Andric             remote_file_path.c_str());
9240b57cec5SDimitry Andric       }
9250b57cec5SDimitry Andric     } else {
9260b57cec5SDimitry Andric       result.AppendError("no platform currently selected\n");
9270b57cec5SDimitry Andric     }
9280b57cec5SDimitry Andric   }
9290b57cec5SDimitry Andric };
9300b57cec5SDimitry Andric 
931349cc55cSDimitry Andric // "platform get-permissions remote-file-path"
932349cc55cSDimitry Andric class CommandObjectPlatformGetPermissions : public CommandObjectParsed {
933349cc55cSDimitry Andric public:
CommandObjectPlatformGetPermissions(CommandInterpreter & interpreter)934349cc55cSDimitry Andric   CommandObjectPlatformGetPermissions(CommandInterpreter &interpreter)
935349cc55cSDimitry Andric       : CommandObjectParsed(interpreter, "platform get-permissions",
936349cc55cSDimitry Andric                             "Get the file permission bits from the remote end.",
937349cc55cSDimitry Andric                             "platform get-permissions <remote-file-spec>", 0) {
938349cc55cSDimitry Andric     SetHelpLong(
939349cc55cSDimitry Andric         R"(Examples:
940349cc55cSDimitry Andric 
941349cc55cSDimitry Andric (lldb) platform get-permissions /the/remote/file/path
942349cc55cSDimitry Andric 
943349cc55cSDimitry Andric     Get the file permissions from the remote end with path /the/remote/file/path.)");
944349cc55cSDimitry Andric 
945349cc55cSDimitry Andric     CommandArgumentEntry arg1;
946349cc55cSDimitry Andric     CommandArgumentData file_arg_remote;
947349cc55cSDimitry Andric 
948349cc55cSDimitry Andric     // Define the first (and only) variant of this arg.
949349cc55cSDimitry Andric     file_arg_remote.arg_type = eArgTypeFilename;
950349cc55cSDimitry Andric     file_arg_remote.arg_repetition = eArgRepeatPlain;
951349cc55cSDimitry Andric     // There is only one variant this argument could be; put it into the
952349cc55cSDimitry Andric     // argument entry.
953349cc55cSDimitry Andric     arg1.push_back(file_arg_remote);
954349cc55cSDimitry Andric 
955349cc55cSDimitry Andric     // Push the data for the first argument into the m_arguments vector.
956349cc55cSDimitry Andric     m_arguments.push_back(arg1);
957349cc55cSDimitry Andric   }
958349cc55cSDimitry Andric 
959349cc55cSDimitry Andric   ~CommandObjectPlatformGetPermissions() override = default;
960349cc55cSDimitry Andric 
961349cc55cSDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)962349cc55cSDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
963349cc55cSDimitry Andric                            OptionElementVector &opt_element_vector) override {
964349cc55cSDimitry Andric     if (request.GetCursorIndex() != 0)
965349cc55cSDimitry Andric       return;
966349cc55cSDimitry Andric 
967fe013be4SDimitry Andric     lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
968fe013be4SDimitry Andric         GetCommandInterpreter(), lldb::eRemoteDiskFileCompletion, request,
969fe013be4SDimitry Andric         nullptr);
970349cc55cSDimitry Andric   }
971349cc55cSDimitry Andric 
DoExecute(Args & args,CommandReturnObject & result)972*c9157d92SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
973349cc55cSDimitry Andric     // If the number of arguments is incorrect, issue an error message.
974349cc55cSDimitry Andric     if (args.GetArgumentCount() != 1) {
975349cc55cSDimitry Andric       result.AppendError("required argument missing; specify the source file "
976349cc55cSDimitry Andric                          "path as the only argument");
977*c9157d92SDimitry Andric       return;
978349cc55cSDimitry Andric     }
979349cc55cSDimitry Andric 
980349cc55cSDimitry Andric     PlatformSP platform_sp(
981349cc55cSDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
982349cc55cSDimitry Andric     if (platform_sp) {
983349cc55cSDimitry Andric       std::string remote_file_path(args.GetArgumentAtIndex(0));
984349cc55cSDimitry Andric       uint32_t permissions;
985349cc55cSDimitry Andric       Status error = platform_sp->GetFilePermissions(FileSpec(remote_file_path),
986349cc55cSDimitry Andric                                                      permissions);
987349cc55cSDimitry Andric       if (error.Success()) {
988349cc55cSDimitry Andric         result.AppendMessageWithFormat(
989349cc55cSDimitry Andric             "File permissions of %s (remote): 0o%04" PRIo32 "\n",
990349cc55cSDimitry Andric             remote_file_path.c_str(), permissions);
991349cc55cSDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishResult);
992349cc55cSDimitry Andric       } else
993349cc55cSDimitry Andric         result.AppendError(error.AsCString());
994349cc55cSDimitry Andric     } else {
995349cc55cSDimitry Andric       result.AppendError("no platform currently selected\n");
996349cc55cSDimitry Andric     }
997349cc55cSDimitry Andric   }
998349cc55cSDimitry Andric };
999349cc55cSDimitry Andric 
1000349cc55cSDimitry Andric // "platform file-exists remote-file-path"
1001349cc55cSDimitry Andric class CommandObjectPlatformFileExists : public CommandObjectParsed {
1002349cc55cSDimitry Andric public:
CommandObjectPlatformFileExists(CommandInterpreter & interpreter)1003349cc55cSDimitry Andric   CommandObjectPlatformFileExists(CommandInterpreter &interpreter)
1004349cc55cSDimitry Andric       : CommandObjectParsed(interpreter, "platform file-exists",
1005349cc55cSDimitry Andric                             "Check if the file exists on the remote end.",
1006349cc55cSDimitry Andric                             "platform file-exists <remote-file-spec>", 0) {
1007349cc55cSDimitry Andric     SetHelpLong(
1008349cc55cSDimitry Andric         R"(Examples:
1009349cc55cSDimitry Andric 
1010349cc55cSDimitry Andric (lldb) platform file-exists /the/remote/file/path
1011349cc55cSDimitry Andric 
1012349cc55cSDimitry Andric     Check if /the/remote/file/path exists on the remote end.)");
1013349cc55cSDimitry Andric 
1014349cc55cSDimitry Andric     CommandArgumentEntry arg1;
1015349cc55cSDimitry Andric     CommandArgumentData file_arg_remote;
1016349cc55cSDimitry Andric 
1017349cc55cSDimitry Andric     // Define the first (and only) variant of this arg.
1018349cc55cSDimitry Andric     file_arg_remote.arg_type = eArgTypeFilename;
1019349cc55cSDimitry Andric     file_arg_remote.arg_repetition = eArgRepeatPlain;
1020349cc55cSDimitry Andric     // There is only one variant this argument could be; put it into the
1021349cc55cSDimitry Andric     // argument entry.
1022349cc55cSDimitry Andric     arg1.push_back(file_arg_remote);
1023349cc55cSDimitry Andric 
1024349cc55cSDimitry Andric     // Push the data for the first argument into the m_arguments vector.
1025349cc55cSDimitry Andric     m_arguments.push_back(arg1);
1026349cc55cSDimitry Andric   }
1027349cc55cSDimitry Andric 
1028349cc55cSDimitry Andric   ~CommandObjectPlatformFileExists() override = default;
1029349cc55cSDimitry Andric 
1030349cc55cSDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)1031349cc55cSDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
1032349cc55cSDimitry Andric                            OptionElementVector &opt_element_vector) override {
1033349cc55cSDimitry Andric     if (request.GetCursorIndex() != 0)
1034349cc55cSDimitry Andric       return;
1035349cc55cSDimitry Andric 
1036fe013be4SDimitry Andric     lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1037fe013be4SDimitry Andric         GetCommandInterpreter(), lldb::eRemoteDiskFileCompletion, request,
1038fe013be4SDimitry Andric         nullptr);
1039349cc55cSDimitry Andric   }
1040349cc55cSDimitry Andric 
DoExecute(Args & args,CommandReturnObject & result)1041*c9157d92SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
1042349cc55cSDimitry Andric     // If the number of arguments is incorrect, issue an error message.
1043349cc55cSDimitry Andric     if (args.GetArgumentCount() != 1) {
1044349cc55cSDimitry Andric       result.AppendError("required argument missing; specify the source file "
1045349cc55cSDimitry Andric                          "path as the only argument");
1046*c9157d92SDimitry Andric       return;
1047349cc55cSDimitry Andric     }
1048349cc55cSDimitry Andric 
1049349cc55cSDimitry Andric     PlatformSP platform_sp(
1050349cc55cSDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
1051349cc55cSDimitry Andric     if (platform_sp) {
1052349cc55cSDimitry Andric       std::string remote_file_path(args.GetArgumentAtIndex(0));
1053349cc55cSDimitry Andric       bool exists = platform_sp->GetFileExists(FileSpec(remote_file_path));
1054349cc55cSDimitry Andric       result.AppendMessageWithFormat(
1055349cc55cSDimitry Andric           "File %s (remote) %s\n",
1056349cc55cSDimitry Andric           remote_file_path.c_str(), exists ? "exists" : "does not exist");
1057349cc55cSDimitry Andric       result.SetStatus(eReturnStatusSuccessFinishResult);
1058349cc55cSDimitry Andric     } else {
1059349cc55cSDimitry Andric       result.AppendError("no platform currently selected\n");
1060349cc55cSDimitry Andric     }
1061349cc55cSDimitry Andric   }
1062349cc55cSDimitry Andric };
1063349cc55cSDimitry Andric 
10640b57cec5SDimitry Andric // "platform put-file"
10650b57cec5SDimitry Andric class CommandObjectPlatformPutFile : public CommandObjectParsed {
10660b57cec5SDimitry Andric public:
CommandObjectPlatformPutFile(CommandInterpreter & interpreter)10670b57cec5SDimitry Andric   CommandObjectPlatformPutFile(CommandInterpreter &interpreter)
10680b57cec5SDimitry Andric       : CommandObjectParsed(
10690b57cec5SDimitry Andric             interpreter, "platform put-file",
1070349cc55cSDimitry Andric             "Transfer a file from this system to the remote end.",
1071349cc55cSDimitry Andric             "platform put-file <source> [<destination>]", 0) {
1072349cc55cSDimitry Andric     SetHelpLong(
1073349cc55cSDimitry Andric         R"(Examples:
1074349cc55cSDimitry Andric 
1075349cc55cSDimitry Andric (lldb) platform put-file /source/foo.txt /destination/bar.txt
1076349cc55cSDimitry Andric 
1077349cc55cSDimitry Andric (lldb) platform put-file /source/foo.txt
1078349cc55cSDimitry Andric 
1079349cc55cSDimitry Andric     Relative source file paths are resolved against lldb's local working directory.
1080349cc55cSDimitry Andric 
1081349cc55cSDimitry Andric     Omitting the destination places the file in the platform working directory.)");
108281ad6265SDimitry Andric     CommandArgumentData source_arg{eArgTypePath, eArgRepeatPlain};
108381ad6265SDimitry Andric     CommandArgumentData path_arg{eArgTypePath, eArgRepeatOptional};
108481ad6265SDimitry Andric     m_arguments.push_back({source_arg});
108581ad6265SDimitry Andric     m_arguments.push_back({path_arg});
10860b57cec5SDimitry Andric   }
10870b57cec5SDimitry Andric 
10880b57cec5SDimitry Andric   ~CommandObjectPlatformPutFile() override = default;
10890b57cec5SDimitry Andric 
1090e8d8bef9SDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)1091e8d8bef9SDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
1092e8d8bef9SDimitry Andric                            OptionElementVector &opt_element_vector) override {
1093e8d8bef9SDimitry Andric     if (request.GetCursorIndex() == 0)
1094fe013be4SDimitry Andric       lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1095fe013be4SDimitry Andric           GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr);
1096e8d8bef9SDimitry Andric     else if (request.GetCursorIndex() == 1)
1097fe013be4SDimitry Andric       lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1098fe013be4SDimitry Andric           GetCommandInterpreter(), lldb::eRemoteDiskFileCompletion, request,
1099fe013be4SDimitry Andric           nullptr);
1100e8d8bef9SDimitry Andric   }
1101e8d8bef9SDimitry Andric 
DoExecute(Args & args,CommandReturnObject & result)1102*c9157d92SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
11030b57cec5SDimitry Andric     const char *src = args.GetArgumentAtIndex(0);
11040b57cec5SDimitry Andric     const char *dst = args.GetArgumentAtIndex(1);
11050b57cec5SDimitry Andric 
11060b57cec5SDimitry Andric     FileSpec src_fs(src);
11070b57cec5SDimitry Andric     FileSystem::Instance().Resolve(src_fs);
11080b57cec5SDimitry Andric     FileSpec dst_fs(dst ? dst : src_fs.GetFilename().GetCString());
11090b57cec5SDimitry Andric 
11100b57cec5SDimitry Andric     PlatformSP platform_sp(
11110b57cec5SDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
11120b57cec5SDimitry Andric     if (platform_sp) {
11130b57cec5SDimitry Andric       Status error(platform_sp->PutFile(src_fs, dst_fs));
11140b57cec5SDimitry Andric       if (error.Success()) {
11150b57cec5SDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishNoResult);
11160b57cec5SDimitry Andric       } else {
11170b57cec5SDimitry Andric         result.AppendError(error.AsCString());
11180b57cec5SDimitry Andric       }
11190b57cec5SDimitry Andric     } else {
11200b57cec5SDimitry Andric       result.AppendError("no platform currently selected\n");
11210b57cec5SDimitry Andric     }
11220b57cec5SDimitry Andric   }
11230b57cec5SDimitry Andric };
11240b57cec5SDimitry Andric 
11250b57cec5SDimitry Andric // "platform process launch"
11260b57cec5SDimitry Andric class CommandObjectPlatformProcessLaunch : public CommandObjectParsed {
11270b57cec5SDimitry Andric public:
CommandObjectPlatformProcessLaunch(CommandInterpreter & interpreter)11280b57cec5SDimitry Andric   CommandObjectPlatformProcessLaunch(CommandInterpreter &interpreter)
11290b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "platform process launch",
11300b57cec5SDimitry Andric                             "Launch a new process on a remote platform.",
11310b57cec5SDimitry Andric                             "platform process launch program",
1132fe013be4SDimitry Andric                             eCommandRequiresTarget | eCommandTryTargetAPILock),
1133fe013be4SDimitry Andric         m_class_options("scripted process", true, 'C', 'k', 'v', 0) {
1134fe6060f1SDimitry Andric     m_all_options.Append(&m_options);
1135fe013be4SDimitry Andric     m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2,
1136fe013be4SDimitry Andric                          LLDB_OPT_SET_ALL);
1137fe6060f1SDimitry Andric     m_all_options.Finalize();
113881ad6265SDimitry Andric     CommandArgumentData run_arg_arg{eArgTypeRunArgs, eArgRepeatStar};
113981ad6265SDimitry Andric     m_arguments.push_back({run_arg_arg});
1140fe6060f1SDimitry Andric   }
11410b57cec5SDimitry Andric 
11420b57cec5SDimitry Andric   ~CommandObjectPlatformProcessLaunch() override = default;
11430b57cec5SDimitry Andric 
GetOptions()1144fe6060f1SDimitry Andric   Options *GetOptions() override { return &m_all_options; }
11450b57cec5SDimitry Andric 
11460b57cec5SDimitry Andric protected:
DoExecute(Args & args,CommandReturnObject & result)1147*c9157d92SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
11480b57cec5SDimitry Andric     Target *target = GetDebugger().GetSelectedTarget().get();
11490b57cec5SDimitry Andric     PlatformSP platform_sp;
11500b57cec5SDimitry Andric     if (target) {
11510b57cec5SDimitry Andric       platform_sp = target->GetPlatform();
11520b57cec5SDimitry Andric     }
11530b57cec5SDimitry Andric     if (!platform_sp) {
11540b57cec5SDimitry Andric       platform_sp = GetDebugger().GetPlatformList().GetSelectedPlatform();
11550b57cec5SDimitry Andric     }
11560b57cec5SDimitry Andric 
11570b57cec5SDimitry Andric     if (platform_sp) {
11580b57cec5SDimitry Andric       Status error;
11590b57cec5SDimitry Andric       const size_t argc = args.GetArgumentCount();
11600b57cec5SDimitry Andric       Target *target = m_exe_ctx.GetTargetPtr();
11610b57cec5SDimitry Andric       Module *exe_module = target->GetExecutableModulePointer();
11620b57cec5SDimitry Andric       if (exe_module) {
11630b57cec5SDimitry Andric         m_options.launch_info.GetExecutableFile() = exe_module->GetFileSpec();
11640b57cec5SDimitry Andric         llvm::SmallString<128> exe_path;
11650b57cec5SDimitry Andric         m_options.launch_info.GetExecutableFile().GetPath(exe_path);
11660b57cec5SDimitry Andric         if (!exe_path.empty())
11670b57cec5SDimitry Andric           m_options.launch_info.GetArguments().AppendArgument(exe_path);
11680b57cec5SDimitry Andric         m_options.launch_info.GetArchitecture() = exe_module->GetArchitecture();
11690b57cec5SDimitry Andric       }
11700b57cec5SDimitry Andric 
1171fe013be4SDimitry Andric       if (!m_class_options.GetName().empty()) {
1172fe013be4SDimitry Andric         m_options.launch_info.SetProcessPluginName("ScriptedProcess");
1173fe013be4SDimitry Andric         ScriptedMetadataSP metadata_sp = std::make_shared<ScriptedMetadata>(
1174fe013be4SDimitry Andric             m_class_options.GetName(), m_class_options.GetStructuredData());
1175fe013be4SDimitry Andric         m_options.launch_info.SetScriptedMetadata(metadata_sp);
1176fe013be4SDimitry Andric         target->SetProcessLaunchInfo(m_options.launch_info);
1177fe013be4SDimitry Andric       }
1178fe013be4SDimitry Andric 
11790b57cec5SDimitry Andric       if (argc > 0) {
11800b57cec5SDimitry Andric         if (m_options.launch_info.GetExecutableFile()) {
11810b57cec5SDimitry Andric           // We already have an executable file, so we will use this and all
11820b57cec5SDimitry Andric           // arguments to this function are extra arguments
11830b57cec5SDimitry Andric           m_options.launch_info.GetArguments().AppendArguments(args);
11840b57cec5SDimitry Andric         } else {
11850b57cec5SDimitry Andric           // We don't have any file yet, so the first argument is our
11860b57cec5SDimitry Andric           // executable, and the rest are program arguments
11870b57cec5SDimitry Andric           const bool first_arg_is_executable = true;
11880b57cec5SDimitry Andric           m_options.launch_info.SetArguments(args, first_arg_is_executable);
11890b57cec5SDimitry Andric         }
11900b57cec5SDimitry Andric       }
11910b57cec5SDimitry Andric 
11920b57cec5SDimitry Andric       if (m_options.launch_info.GetExecutableFile()) {
11930b57cec5SDimitry Andric         Debugger &debugger = GetDebugger();
11940b57cec5SDimitry Andric 
1195fe013be4SDimitry Andric         if (argc == 0) {
1196fe013be4SDimitry Andric           // If no arguments were given to the command, use target.run-args.
1197fe013be4SDimitry Andric           Args target_run_args;
1198fe013be4SDimitry Andric           target->GetRunArguments(target_run_args);
1199fe013be4SDimitry Andric           m_options.launch_info.GetArguments().AppendArguments(target_run_args);
1200fe013be4SDimitry Andric         }
12010b57cec5SDimitry Andric 
12020b57cec5SDimitry Andric         ProcessSP process_sp(platform_sp->DebugProcess(
1203349cc55cSDimitry Andric             m_options.launch_info, debugger, *target, error));
1204fe013be4SDimitry Andric 
1205fe013be4SDimitry Andric         if (!process_sp && error.Success()) {
1206fe013be4SDimitry Andric           result.AppendError("failed to launch or debug process");
1207*c9157d92SDimitry Andric           return;
1208fe013be4SDimitry Andric         } else if (!error.Success()) {
1209fe013be4SDimitry Andric           result.AppendError(error.AsCString());
1210*c9157d92SDimitry Andric           return;
1211fe013be4SDimitry Andric         }
1212fe013be4SDimitry Andric 
1213fe013be4SDimitry Andric         const bool synchronous_execution =
1214fe013be4SDimitry Andric             debugger.GetCommandInterpreter().GetSynchronous();
1215fe013be4SDimitry Andric         auto launch_info = m_options.launch_info;
1216fe013be4SDimitry Andric         bool rebroadcast_first_stop =
1217fe013be4SDimitry Andric             !synchronous_execution &&
1218fe013be4SDimitry Andric             launch_info.GetFlags().Test(eLaunchFlagStopAtEntry);
1219fe013be4SDimitry Andric 
1220fe013be4SDimitry Andric         EventSP first_stop_event_sp;
1221fe013be4SDimitry Andric         StateType state = process_sp->WaitForProcessToStop(
1222fe013be4SDimitry Andric             std::nullopt, &first_stop_event_sp, rebroadcast_first_stop,
1223fe013be4SDimitry Andric             launch_info.GetHijackListener());
1224fe013be4SDimitry Andric         process_sp->RestoreProcessEvents();
1225fe013be4SDimitry Andric 
1226fe013be4SDimitry Andric         if (rebroadcast_first_stop) {
1227fe013be4SDimitry Andric           assert(first_stop_event_sp);
1228fe013be4SDimitry Andric           process_sp->BroadcastEvent(first_stop_event_sp);
1229*c9157d92SDimitry Andric           return;
1230fe013be4SDimitry Andric         }
1231fe013be4SDimitry Andric 
1232fe013be4SDimitry Andric         switch (state) {
1233fe013be4SDimitry Andric         case eStateStopped: {
1234fe013be4SDimitry Andric           if (launch_info.GetFlags().Test(eLaunchFlagStopAtEntry))
1235fe013be4SDimitry Andric             break;
1236fe013be4SDimitry Andric           if (synchronous_execution) {
1237fe013be4SDimitry Andric             // Now we have handled the stop-from-attach, and we are just
1238fe013be4SDimitry Andric             // switching to a synchronous resume.  So we should switch to the
1239fe013be4SDimitry Andric             // SyncResume hijacker.
1240fe013be4SDimitry Andric             process_sp->ResumeSynchronous(&result.GetOutputStream());
1241fe013be4SDimitry Andric           } else {
1242fe013be4SDimitry Andric             error = process_sp->Resume();
1243fe013be4SDimitry Andric             if (!error.Success()) {
1244fe013be4SDimitry Andric               result.AppendErrorWithFormat(
1245fe013be4SDimitry Andric                   "process resume at entry point failed: %s",
1246fe013be4SDimitry Andric                   error.AsCString());
1247fe013be4SDimitry Andric             }
1248fe013be4SDimitry Andric           }
1249fe013be4SDimitry Andric         } break;
1250fe013be4SDimitry Andric         default:
1251fe013be4SDimitry Andric           result.AppendErrorWithFormat(
1252fe013be4SDimitry Andric               "initial process state wasn't stopped: %s",
1253fe013be4SDimitry Andric               StateAsCString(state));
1254fe013be4SDimitry Andric           break;
1255fe013be4SDimitry Andric         }
1256fe013be4SDimitry Andric 
12570b57cec5SDimitry Andric         if (process_sp && process_sp->IsAlive()) {
12580b57cec5SDimitry Andric           result.SetStatus(eReturnStatusSuccessFinishNoResult);
1259*c9157d92SDimitry Andric           return;
12600b57cec5SDimitry Andric         }
12610b57cec5SDimitry Andric       } else {
12620b57cec5SDimitry Andric         result.AppendError("'platform process launch' uses the current target "
12630b57cec5SDimitry Andric                            "file and arguments, or the executable and its "
12640b57cec5SDimitry Andric                            "arguments can be specified in this command");
1265*c9157d92SDimitry Andric         return;
12660b57cec5SDimitry Andric       }
12670b57cec5SDimitry Andric     } else {
12680b57cec5SDimitry Andric       result.AppendError("no platform is selected\n");
12690b57cec5SDimitry Andric     }
12700b57cec5SDimitry Andric   }
12710b57cec5SDimitry Andric 
1272e8d8bef9SDimitry Andric   CommandOptionsProcessLaunch m_options;
1273fe013be4SDimitry Andric   OptionGroupPythonClassWithDict m_class_options;
1274fe6060f1SDimitry Andric   OptionGroupOptions m_all_options;
12750b57cec5SDimitry Andric };
12760b57cec5SDimitry Andric 
12770b57cec5SDimitry Andric // "platform process list"
12780b57cec5SDimitry Andric 
12799dba64beSDimitry Andric static PosixPlatformCommandOptionValidator posix_validator;
12809dba64beSDimitry Andric #define LLDB_OPTIONS_platform_process_list
12819dba64beSDimitry Andric #include "CommandOptions.inc"
12820b57cec5SDimitry Andric 
12830b57cec5SDimitry Andric class CommandObjectPlatformProcessList : public CommandObjectParsed {
12840b57cec5SDimitry Andric public:
CommandObjectPlatformProcessList(CommandInterpreter & interpreter)12850b57cec5SDimitry Andric   CommandObjectPlatformProcessList(CommandInterpreter &interpreter)
12860b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "platform process list",
12870b57cec5SDimitry Andric                             "List processes on a remote platform by name, pid, "
12880b57cec5SDimitry Andric                             "or many other matching attributes.",
128904eeddc0SDimitry Andric                             "platform process list", 0) {}
12900b57cec5SDimitry Andric 
12910b57cec5SDimitry Andric   ~CommandObjectPlatformProcessList() override = default;
12920b57cec5SDimitry Andric 
GetOptions()12930b57cec5SDimitry Andric   Options *GetOptions() override { return &m_options; }
12940b57cec5SDimitry Andric 
12950b57cec5SDimitry Andric protected:
DoExecute(Args & args,CommandReturnObject & result)1296*c9157d92SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
12970b57cec5SDimitry Andric     Target *target = GetDebugger().GetSelectedTarget().get();
12980b57cec5SDimitry Andric     PlatformSP platform_sp;
12990b57cec5SDimitry Andric     if (target) {
13000b57cec5SDimitry Andric       platform_sp = target->GetPlatform();
13010b57cec5SDimitry Andric     }
13020b57cec5SDimitry Andric     if (!platform_sp) {
13030b57cec5SDimitry Andric       platform_sp = GetDebugger().GetPlatformList().GetSelectedPlatform();
13040b57cec5SDimitry Andric     }
13050b57cec5SDimitry Andric 
13060b57cec5SDimitry Andric     if (platform_sp) {
13070b57cec5SDimitry Andric       Status error;
13080b57cec5SDimitry Andric       if (platform_sp) {
13090b57cec5SDimitry Andric         Stream &ostrm = result.GetOutputStream();
13100b57cec5SDimitry Andric 
131181ad6265SDimitry Andric         lldb::pid_t pid = m_options.match_info.GetProcessInfo().GetProcessID();
13120b57cec5SDimitry Andric         if (pid != LLDB_INVALID_PROCESS_ID) {
13130b57cec5SDimitry Andric           ProcessInstanceInfo proc_info;
13140b57cec5SDimitry Andric           if (platform_sp->GetProcessInfo(pid, proc_info)) {
13150b57cec5SDimitry Andric             ProcessInstanceInfo::DumpTableHeader(ostrm, m_options.show_args,
13160b57cec5SDimitry Andric                                                  m_options.verbose);
13170b57cec5SDimitry Andric             proc_info.DumpAsTableRow(ostrm, platform_sp->GetUserIDResolver(),
13180b57cec5SDimitry Andric                                      m_options.show_args, m_options.verbose);
13190b57cec5SDimitry Andric             result.SetStatus(eReturnStatusSuccessFinishResult);
13200b57cec5SDimitry Andric           } else {
13210b57cec5SDimitry Andric             result.AppendErrorWithFormat(
13220b57cec5SDimitry Andric                 "no process found with pid = %" PRIu64 "\n", pid);
13230b57cec5SDimitry Andric           }
13240b57cec5SDimitry Andric         } else {
13250b57cec5SDimitry Andric           ProcessInstanceInfoList proc_infos;
13260b57cec5SDimitry Andric           const uint32_t matches =
13270b57cec5SDimitry Andric               platform_sp->FindProcesses(m_options.match_info, proc_infos);
13280b57cec5SDimitry Andric           const char *match_desc = nullptr;
13290b57cec5SDimitry Andric           const char *match_name =
13300b57cec5SDimitry Andric               m_options.match_info.GetProcessInfo().GetName();
13310b57cec5SDimitry Andric           if (match_name && match_name[0]) {
13320b57cec5SDimitry Andric             switch (m_options.match_info.GetNameMatchType()) {
13330b57cec5SDimitry Andric             case NameMatch::Ignore:
13340b57cec5SDimitry Andric               break;
13350b57cec5SDimitry Andric             case NameMatch::Equals:
13360b57cec5SDimitry Andric               match_desc = "matched";
13370b57cec5SDimitry Andric               break;
13380b57cec5SDimitry Andric             case NameMatch::Contains:
13390b57cec5SDimitry Andric               match_desc = "contained";
13400b57cec5SDimitry Andric               break;
13410b57cec5SDimitry Andric             case NameMatch::StartsWith:
13420b57cec5SDimitry Andric               match_desc = "started with";
13430b57cec5SDimitry Andric               break;
13440b57cec5SDimitry Andric             case NameMatch::EndsWith:
13450b57cec5SDimitry Andric               match_desc = "ended with";
13460b57cec5SDimitry Andric               break;
13470b57cec5SDimitry Andric             case NameMatch::RegularExpression:
13480b57cec5SDimitry Andric               match_desc = "matched the regular expression";
13490b57cec5SDimitry Andric               break;
13500b57cec5SDimitry Andric             }
13510b57cec5SDimitry Andric           }
13520b57cec5SDimitry Andric 
13530b57cec5SDimitry Andric           if (matches == 0) {
13540b57cec5SDimitry Andric             if (match_desc)
1355349cc55cSDimitry Andric               result.AppendErrorWithFormatv(
1356349cc55cSDimitry Andric                   "no processes were found that {0} \"{1}\" on the \"{2}\" "
13570b57cec5SDimitry Andric                   "platform\n",
135881ad6265SDimitry Andric                   match_desc, match_name, platform_sp->GetName());
13590b57cec5SDimitry Andric             else
1360349cc55cSDimitry Andric               result.AppendErrorWithFormatv(
1361349cc55cSDimitry Andric                   "no processes were found on the \"{0}\" platform\n",
136281ad6265SDimitry Andric                   platform_sp->GetName());
13630b57cec5SDimitry Andric           } else {
136481ad6265SDimitry Andric             result.AppendMessageWithFormatv(
136581ad6265SDimitry Andric                 "{0} matching process{1} found on \"{2}\"", matches,
136681ad6265SDimitry Andric                 matches > 1 ? "es were" : " was", platform_sp->GetName());
13670b57cec5SDimitry Andric             if (match_desc)
13680b57cec5SDimitry Andric               result.AppendMessageWithFormat(" whose name %s \"%s\"",
13690b57cec5SDimitry Andric                                              match_desc, match_name);
13700b57cec5SDimitry Andric             result.AppendMessageWithFormat("\n");
13710b57cec5SDimitry Andric             ProcessInstanceInfo::DumpTableHeader(ostrm, m_options.show_args,
13720b57cec5SDimitry Andric                                                  m_options.verbose);
13730b57cec5SDimitry Andric             for (uint32_t i = 0; i < matches; ++i) {
13745ffd83dbSDimitry Andric               proc_infos[i].DumpAsTableRow(
137581ad6265SDimitry Andric                   ostrm, platform_sp->GetUserIDResolver(), m_options.show_args,
137681ad6265SDimitry Andric                   m_options.verbose);
13770b57cec5SDimitry Andric             }
13780b57cec5SDimitry Andric           }
13790b57cec5SDimitry Andric         }
13800b57cec5SDimitry Andric       }
13810b57cec5SDimitry Andric     } else {
13820b57cec5SDimitry Andric       result.AppendError("no platform is selected\n");
13830b57cec5SDimitry Andric     }
13840b57cec5SDimitry Andric   }
13850b57cec5SDimitry Andric 
13860b57cec5SDimitry Andric   class CommandOptions : public Options {
13870b57cec5SDimitry Andric   public:
138881ad6265SDimitry Andric     CommandOptions() = default;
13890b57cec5SDimitry Andric 
13900b57cec5SDimitry Andric     ~CommandOptions() override = default;
13910b57cec5SDimitry Andric 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)13920b57cec5SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
13930b57cec5SDimitry Andric                           ExecutionContext *execution_context) override {
13940b57cec5SDimitry Andric       Status error;
13950b57cec5SDimitry Andric       const int short_option = m_getopt_table[option_idx].val;
13960b57cec5SDimitry Andric       bool success = false;
13970b57cec5SDimitry Andric 
13980b57cec5SDimitry Andric       uint32_t id = LLDB_INVALID_PROCESS_ID;
13990b57cec5SDimitry Andric       success = !option_arg.getAsInteger(0, id);
14000b57cec5SDimitry Andric       switch (short_option) {
14010b57cec5SDimitry Andric       case 'p': {
14020b57cec5SDimitry Andric         match_info.GetProcessInfo().SetProcessID(id);
14030b57cec5SDimitry Andric         if (!success)
14040b57cec5SDimitry Andric           error.SetErrorStringWithFormat("invalid process ID string: '%s'",
14050b57cec5SDimitry Andric                                          option_arg.str().c_str());
14060b57cec5SDimitry Andric         break;
14070b57cec5SDimitry Andric       }
14080b57cec5SDimitry Andric       case 'P':
14090b57cec5SDimitry Andric         match_info.GetProcessInfo().SetParentProcessID(id);
14100b57cec5SDimitry Andric         if (!success)
14110b57cec5SDimitry Andric           error.SetErrorStringWithFormat(
14120b57cec5SDimitry Andric               "invalid parent process ID string: '%s'",
14130b57cec5SDimitry Andric               option_arg.str().c_str());
14140b57cec5SDimitry Andric         break;
14150b57cec5SDimitry Andric 
14160b57cec5SDimitry Andric       case 'u':
14170b57cec5SDimitry Andric         match_info.GetProcessInfo().SetUserID(success ? id : UINT32_MAX);
14180b57cec5SDimitry Andric         if (!success)
14190b57cec5SDimitry Andric           error.SetErrorStringWithFormat("invalid user ID string: '%s'",
14200b57cec5SDimitry Andric                                          option_arg.str().c_str());
14210b57cec5SDimitry Andric         break;
14220b57cec5SDimitry Andric 
14230b57cec5SDimitry Andric       case 'U':
14240b57cec5SDimitry Andric         match_info.GetProcessInfo().SetEffectiveUserID(success ? id
14250b57cec5SDimitry Andric                                                                : UINT32_MAX);
14260b57cec5SDimitry Andric         if (!success)
14270b57cec5SDimitry Andric           error.SetErrorStringWithFormat(
14280b57cec5SDimitry Andric               "invalid effective user ID string: '%s'",
14290b57cec5SDimitry Andric               option_arg.str().c_str());
14300b57cec5SDimitry Andric         break;
14310b57cec5SDimitry Andric 
14320b57cec5SDimitry Andric       case 'g':
14330b57cec5SDimitry Andric         match_info.GetProcessInfo().SetGroupID(success ? id : UINT32_MAX);
14340b57cec5SDimitry Andric         if (!success)
14350b57cec5SDimitry Andric           error.SetErrorStringWithFormat("invalid group ID string: '%s'",
14360b57cec5SDimitry Andric                                          option_arg.str().c_str());
14370b57cec5SDimitry Andric         break;
14380b57cec5SDimitry Andric 
14390b57cec5SDimitry Andric       case 'G':
14400b57cec5SDimitry Andric         match_info.GetProcessInfo().SetEffectiveGroupID(success ? id
14410b57cec5SDimitry Andric                                                                 : UINT32_MAX);
14420b57cec5SDimitry Andric         if (!success)
14430b57cec5SDimitry Andric           error.SetErrorStringWithFormat(
14440b57cec5SDimitry Andric               "invalid effective group ID string: '%s'",
14450b57cec5SDimitry Andric               option_arg.str().c_str());
14460b57cec5SDimitry Andric         break;
14470b57cec5SDimitry Andric 
14480b57cec5SDimitry Andric       case 'a': {
14490b57cec5SDimitry Andric         TargetSP target_sp =
14500b57cec5SDimitry Andric             execution_context ? execution_context->GetTargetSP() : TargetSP();
14510b57cec5SDimitry Andric         DebuggerSP debugger_sp =
14520b57cec5SDimitry Andric             target_sp ? target_sp->GetDebugger().shared_from_this()
14530b57cec5SDimitry Andric                       : DebuggerSP();
14540b57cec5SDimitry Andric         PlatformSP platform_sp =
14550b57cec5SDimitry Andric             debugger_sp ? debugger_sp->GetPlatformList().GetSelectedPlatform()
14560b57cec5SDimitry Andric                         : PlatformSP();
14570b57cec5SDimitry Andric         match_info.GetProcessInfo().GetArchitecture() =
14580b57cec5SDimitry Andric             Platform::GetAugmentedArchSpec(platform_sp.get(), option_arg);
14590b57cec5SDimitry Andric       } break;
14600b57cec5SDimitry Andric 
14610b57cec5SDimitry Andric       case 'n':
14620b57cec5SDimitry Andric         match_info.GetProcessInfo().GetExecutableFile().SetFile(
14630b57cec5SDimitry Andric             option_arg, FileSpec::Style::native);
14640b57cec5SDimitry Andric         match_info.SetNameMatchType(NameMatch::Equals);
14650b57cec5SDimitry Andric         break;
14660b57cec5SDimitry Andric 
14670b57cec5SDimitry Andric       case 'e':
14680b57cec5SDimitry Andric         match_info.GetProcessInfo().GetExecutableFile().SetFile(
14690b57cec5SDimitry Andric             option_arg, FileSpec::Style::native);
14700b57cec5SDimitry Andric         match_info.SetNameMatchType(NameMatch::EndsWith);
14710b57cec5SDimitry Andric         break;
14720b57cec5SDimitry Andric 
14730b57cec5SDimitry Andric       case 's':
14740b57cec5SDimitry Andric         match_info.GetProcessInfo().GetExecutableFile().SetFile(
14750b57cec5SDimitry Andric             option_arg, FileSpec::Style::native);
14760b57cec5SDimitry Andric         match_info.SetNameMatchType(NameMatch::StartsWith);
14770b57cec5SDimitry Andric         break;
14780b57cec5SDimitry Andric 
14790b57cec5SDimitry Andric       case 'c':
14800b57cec5SDimitry Andric         match_info.GetProcessInfo().GetExecutableFile().SetFile(
14810b57cec5SDimitry Andric             option_arg, FileSpec::Style::native);
14820b57cec5SDimitry Andric         match_info.SetNameMatchType(NameMatch::Contains);
14830b57cec5SDimitry Andric         break;
14840b57cec5SDimitry Andric 
14850b57cec5SDimitry Andric       case 'r':
14860b57cec5SDimitry Andric         match_info.GetProcessInfo().GetExecutableFile().SetFile(
14870b57cec5SDimitry Andric             option_arg, FileSpec::Style::native);
14880b57cec5SDimitry Andric         match_info.SetNameMatchType(NameMatch::RegularExpression);
14890b57cec5SDimitry Andric         break;
14900b57cec5SDimitry Andric 
14910b57cec5SDimitry Andric       case 'A':
14920b57cec5SDimitry Andric         show_args = true;
14930b57cec5SDimitry Andric         break;
14940b57cec5SDimitry Andric 
14950b57cec5SDimitry Andric       case 'v':
14960b57cec5SDimitry Andric         verbose = true;
14970b57cec5SDimitry Andric         break;
14980b57cec5SDimitry Andric 
14999dba64beSDimitry Andric       case 'x':
15009dba64beSDimitry Andric         match_info.SetMatchAllUsers(true);
15010b57cec5SDimitry Andric         break;
15029dba64beSDimitry Andric 
15039dba64beSDimitry Andric       default:
15049dba64beSDimitry Andric         llvm_unreachable("Unimplemented option");
15050b57cec5SDimitry Andric       }
15060b57cec5SDimitry Andric 
15070b57cec5SDimitry Andric       return error;
15080b57cec5SDimitry Andric     }
15090b57cec5SDimitry Andric 
OptionParsingStarting(ExecutionContext * execution_context)15100b57cec5SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
15110b57cec5SDimitry Andric       match_info.Clear();
15120b57cec5SDimitry Andric       show_args = false;
15130b57cec5SDimitry Andric       verbose = false;
15140b57cec5SDimitry Andric     }
15150b57cec5SDimitry Andric 
GetDefinitions()15160b57cec5SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1517bdd1243dSDimitry Andric       return llvm::ArrayRef(g_platform_process_list_options);
15180b57cec5SDimitry Andric     }
15190b57cec5SDimitry Andric 
15200b57cec5SDimitry Andric     // Instance variables to hold the values for command options.
15210b57cec5SDimitry Andric 
15220b57cec5SDimitry Andric     ProcessInstanceInfoMatch match_info;
1523fe6060f1SDimitry Andric     bool show_args = false;
1524fe6060f1SDimitry Andric     bool verbose = false;
15250b57cec5SDimitry Andric   };
15260b57cec5SDimitry Andric 
15270b57cec5SDimitry Andric   CommandOptions m_options;
15280b57cec5SDimitry Andric };
15290b57cec5SDimitry Andric 
15300b57cec5SDimitry Andric // "platform process info"
15310b57cec5SDimitry Andric class CommandObjectPlatformProcessInfo : public CommandObjectParsed {
15320b57cec5SDimitry Andric public:
CommandObjectPlatformProcessInfo(CommandInterpreter & interpreter)15330b57cec5SDimitry Andric   CommandObjectPlatformProcessInfo(CommandInterpreter &interpreter)
15340b57cec5SDimitry Andric       : CommandObjectParsed(
15350b57cec5SDimitry Andric             interpreter, "platform process info",
15360b57cec5SDimitry Andric             "Get detailed information for one or more process by process ID.",
15370b57cec5SDimitry Andric             "platform process info <pid> [<pid> <pid> ...]", 0) {
15380b57cec5SDimitry Andric     CommandArgumentEntry arg;
15390b57cec5SDimitry Andric     CommandArgumentData pid_args;
15400b57cec5SDimitry Andric 
15410b57cec5SDimitry Andric     // Define the first (and only) variant of this arg.
15420b57cec5SDimitry Andric     pid_args.arg_type = eArgTypePid;
15430b57cec5SDimitry Andric     pid_args.arg_repetition = eArgRepeatStar;
15440b57cec5SDimitry Andric 
15450b57cec5SDimitry Andric     // There is only one variant this argument could be; put it into the
15460b57cec5SDimitry Andric     // argument entry.
15470b57cec5SDimitry Andric     arg.push_back(pid_args);
15480b57cec5SDimitry Andric 
15490b57cec5SDimitry Andric     // Push the data for the first argument into the m_arguments vector.
15500b57cec5SDimitry Andric     m_arguments.push_back(arg);
15510b57cec5SDimitry Andric   }
15520b57cec5SDimitry Andric 
15530b57cec5SDimitry Andric   ~CommandObjectPlatformProcessInfo() override = default;
15540b57cec5SDimitry Andric 
1555e8d8bef9SDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)1556e8d8bef9SDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
1557e8d8bef9SDimitry Andric                            OptionElementVector &opt_element_vector) override {
1558fe013be4SDimitry Andric     lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1559fe013be4SDimitry Andric         GetCommandInterpreter(), lldb::eProcessIDCompletion, request, nullptr);
1560e8d8bef9SDimitry Andric   }
1561e8d8bef9SDimitry Andric 
15620b57cec5SDimitry Andric protected:
DoExecute(Args & args,CommandReturnObject & result)1563*c9157d92SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
15640b57cec5SDimitry Andric     Target *target = GetDebugger().GetSelectedTarget().get();
15650b57cec5SDimitry Andric     PlatformSP platform_sp;
15660b57cec5SDimitry Andric     if (target) {
15670b57cec5SDimitry Andric       platform_sp = target->GetPlatform();
15680b57cec5SDimitry Andric     }
15690b57cec5SDimitry Andric     if (!platform_sp) {
15700b57cec5SDimitry Andric       platform_sp = GetDebugger().GetPlatformList().GetSelectedPlatform();
15710b57cec5SDimitry Andric     }
15720b57cec5SDimitry Andric 
15730b57cec5SDimitry Andric     if (platform_sp) {
15740b57cec5SDimitry Andric       const size_t argc = args.GetArgumentCount();
15750b57cec5SDimitry Andric       if (argc > 0) {
15760b57cec5SDimitry Andric         Status error;
15770b57cec5SDimitry Andric 
15780b57cec5SDimitry Andric         if (platform_sp->IsConnected()) {
15790b57cec5SDimitry Andric           Stream &ostrm = result.GetOutputStream();
15800b57cec5SDimitry Andric           for (auto &entry : args.entries()) {
15810b57cec5SDimitry Andric             lldb::pid_t pid;
15829dba64beSDimitry Andric             if (entry.ref().getAsInteger(0, pid)) {
15830b57cec5SDimitry Andric               result.AppendErrorWithFormat("invalid process ID argument '%s'",
15849dba64beSDimitry Andric                                            entry.ref().str().c_str());
15850b57cec5SDimitry Andric               break;
15860b57cec5SDimitry Andric             } else {
15870b57cec5SDimitry Andric               ProcessInstanceInfo proc_info;
15880b57cec5SDimitry Andric               if (platform_sp->GetProcessInfo(pid, proc_info)) {
15890b57cec5SDimitry Andric                 ostrm.Printf("Process information for process %" PRIu64 ":\n",
15900b57cec5SDimitry Andric                              pid);
15910b57cec5SDimitry Andric                 proc_info.Dump(ostrm, platform_sp->GetUserIDResolver());
15920b57cec5SDimitry Andric               } else {
15930b57cec5SDimitry Andric                 ostrm.Printf("error: no process information is available for "
15940b57cec5SDimitry Andric                              "process %" PRIu64 "\n",
15950b57cec5SDimitry Andric                              pid);
15960b57cec5SDimitry Andric               }
15970b57cec5SDimitry Andric               ostrm.EOL();
15980b57cec5SDimitry Andric             }
15990b57cec5SDimitry Andric           }
16000b57cec5SDimitry Andric         } else {
16010b57cec5SDimitry Andric           // Not connected...
1602349cc55cSDimitry Andric           result.AppendErrorWithFormatv("not connected to '{0}'",
1603349cc55cSDimitry Andric                                         platform_sp->GetPluginName());
16040b57cec5SDimitry Andric         }
16050b57cec5SDimitry Andric       } else {
16060b57cec5SDimitry Andric         // No args
16070b57cec5SDimitry Andric         result.AppendError("one or more process id(s) must be specified");
16080b57cec5SDimitry Andric       }
16090b57cec5SDimitry Andric     } else {
16100b57cec5SDimitry Andric       result.AppendError("no platform is currently selected");
16110b57cec5SDimitry Andric     }
16120b57cec5SDimitry Andric   }
16130b57cec5SDimitry Andric };
16140b57cec5SDimitry Andric 
16159dba64beSDimitry Andric #define LLDB_OPTIONS_platform_process_attach
16169dba64beSDimitry Andric #include "CommandOptions.inc"
16170b57cec5SDimitry Andric 
16180b57cec5SDimitry Andric class CommandObjectPlatformProcessAttach : public CommandObjectParsed {
16190b57cec5SDimitry Andric public:
CommandObjectPlatformProcessAttach(CommandInterpreter & interpreter)16200b57cec5SDimitry Andric   CommandObjectPlatformProcessAttach(CommandInterpreter &interpreter)
16210b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "platform process attach",
16220b57cec5SDimitry Andric                             "Attach to a process.",
1623fe013be4SDimitry Andric                             "platform process attach <cmd-options>"),
1624fe013be4SDimitry Andric         m_class_options("scripted process", true, 'C', 'k', 'v', 0) {
1625fe013be4SDimitry Andric     m_all_options.Append(&m_options);
1626fe013be4SDimitry Andric     m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2,
1627fe013be4SDimitry Andric                          LLDB_OPT_SET_ALL);
1628fe013be4SDimitry Andric     m_all_options.Finalize();
1629fe013be4SDimitry Andric   }
16300b57cec5SDimitry Andric 
16310b57cec5SDimitry Andric   ~CommandObjectPlatformProcessAttach() override = default;
16320b57cec5SDimitry Andric 
DoExecute(Args & command,CommandReturnObject & result)1633*c9157d92SDimitry Andric   void DoExecute(Args &command, CommandReturnObject &result) override {
16340b57cec5SDimitry Andric     PlatformSP platform_sp(
16350b57cec5SDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
16360b57cec5SDimitry Andric     if (platform_sp) {
1637fe013be4SDimitry Andric 
1638fe013be4SDimitry Andric       if (!m_class_options.GetName().empty()) {
1639fe013be4SDimitry Andric         m_options.attach_info.SetProcessPluginName("ScriptedProcess");
1640fe013be4SDimitry Andric         ScriptedMetadataSP metadata_sp = std::make_shared<ScriptedMetadata>(
1641fe013be4SDimitry Andric             m_class_options.GetName(), m_class_options.GetStructuredData());
1642fe013be4SDimitry Andric         m_options.attach_info.SetScriptedMetadata(metadata_sp);
1643fe013be4SDimitry Andric       }
1644fe013be4SDimitry Andric 
16450b57cec5SDimitry Andric       Status err;
16460b57cec5SDimitry Andric       ProcessSP remote_process_sp = platform_sp->Attach(
16470b57cec5SDimitry Andric           m_options.attach_info, GetDebugger(), nullptr, err);
16480b57cec5SDimitry Andric       if (err.Fail()) {
16490b57cec5SDimitry Andric         result.AppendError(err.AsCString());
16500b57cec5SDimitry Andric       } else if (!remote_process_sp) {
16510b57cec5SDimitry Andric         result.AppendError("could not attach: unknown reason");
16520b57cec5SDimitry Andric       } else
16530b57cec5SDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishResult);
16540b57cec5SDimitry Andric     } else {
16550b57cec5SDimitry Andric       result.AppendError("no platform is currently selected");
16560b57cec5SDimitry Andric     }
16570b57cec5SDimitry Andric   }
16580b57cec5SDimitry Andric 
GetOptions()1659fe013be4SDimitry Andric   Options *GetOptions() override { return &m_all_options; }
16600b57cec5SDimitry Andric 
16610b57cec5SDimitry Andric protected:
1662fe013be4SDimitry Andric   CommandOptionsProcessAttach m_options;
1663fe013be4SDimitry Andric   OptionGroupPythonClassWithDict m_class_options;
1664fe013be4SDimitry Andric   OptionGroupOptions m_all_options;
16650b57cec5SDimitry Andric };
16660b57cec5SDimitry Andric 
16670b57cec5SDimitry Andric class CommandObjectPlatformProcess : public CommandObjectMultiword {
16680b57cec5SDimitry Andric public:
16690b57cec5SDimitry Andric   // Constructors and Destructors
CommandObjectPlatformProcess(CommandInterpreter & interpreter)16700b57cec5SDimitry Andric   CommandObjectPlatformProcess(CommandInterpreter &interpreter)
16710b57cec5SDimitry Andric       : CommandObjectMultiword(interpreter, "platform process",
16720b57cec5SDimitry Andric                                "Commands to query, launch and attach to "
16730b57cec5SDimitry Andric                                "processes on the current platform.",
16740b57cec5SDimitry Andric                                "platform process [attach|launch|list] ...") {
16750b57cec5SDimitry Andric     LoadSubCommand(
16760b57cec5SDimitry Andric         "attach",
16770b57cec5SDimitry Andric         CommandObjectSP(new CommandObjectPlatformProcessAttach(interpreter)));
16780b57cec5SDimitry Andric     LoadSubCommand(
16790b57cec5SDimitry Andric         "launch",
16800b57cec5SDimitry Andric         CommandObjectSP(new CommandObjectPlatformProcessLaunch(interpreter)));
16810b57cec5SDimitry Andric     LoadSubCommand("info", CommandObjectSP(new CommandObjectPlatformProcessInfo(
16820b57cec5SDimitry Andric                                interpreter)));
16830b57cec5SDimitry Andric     LoadSubCommand("list", CommandObjectSP(new CommandObjectPlatformProcessList(
16840b57cec5SDimitry Andric                                interpreter)));
16850b57cec5SDimitry Andric   }
16860b57cec5SDimitry Andric 
16870b57cec5SDimitry Andric   ~CommandObjectPlatformProcess() override = default;
16880b57cec5SDimitry Andric 
16890b57cec5SDimitry Andric private:
16900b57cec5SDimitry Andric   // For CommandObjectPlatform only
16915ffd83dbSDimitry Andric   CommandObjectPlatformProcess(const CommandObjectPlatformProcess &) = delete;
16925ffd83dbSDimitry Andric   const CommandObjectPlatformProcess &
16935ffd83dbSDimitry Andric   operator=(const CommandObjectPlatformProcess &) = delete;
16940b57cec5SDimitry Andric };
16950b57cec5SDimitry Andric 
16960b57cec5SDimitry Andric // "platform shell"
16979dba64beSDimitry Andric #define LLDB_OPTIONS_platform_shell
16989dba64beSDimitry Andric #include "CommandOptions.inc"
16990b57cec5SDimitry Andric 
17000b57cec5SDimitry Andric class CommandObjectPlatformShell : public CommandObjectRaw {
17010b57cec5SDimitry Andric public:
17020b57cec5SDimitry Andric   class CommandOptions : public Options {
17030b57cec5SDimitry Andric   public:
170481ad6265SDimitry Andric     CommandOptions() = default;
17050b57cec5SDimitry Andric 
17060b57cec5SDimitry Andric     ~CommandOptions() override = default;
17070b57cec5SDimitry Andric 
GetDefinitions()17080b57cec5SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1709bdd1243dSDimitry Andric       return llvm::ArrayRef(g_platform_shell_options);
17100b57cec5SDimitry Andric     }
17110b57cec5SDimitry Andric 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)17120b57cec5SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
17130b57cec5SDimitry Andric                           ExecutionContext *execution_context) override {
17140b57cec5SDimitry Andric       Status error;
17150b57cec5SDimitry Andric 
17160b57cec5SDimitry Andric       const char short_option = (char)GetDefinitions()[option_idx].short_option;
17170b57cec5SDimitry Andric 
17180b57cec5SDimitry Andric       switch (short_option) {
17195ffd83dbSDimitry Andric       case 'h':
17205ffd83dbSDimitry Andric         m_use_host_platform = true;
17215ffd83dbSDimitry Andric         break;
17220b57cec5SDimitry Andric       case 't':
17230b57cec5SDimitry Andric         uint32_t timeout_sec;
17240b57cec5SDimitry Andric         if (option_arg.getAsInteger(10, timeout_sec))
17250b57cec5SDimitry Andric           error.SetErrorStringWithFormat(
17260b57cec5SDimitry Andric               "could not convert \"%s\" to a numeric value.",
17270b57cec5SDimitry Andric               option_arg.str().c_str());
17280b57cec5SDimitry Andric         else
17295ffd83dbSDimitry Andric           m_timeout = std::chrono::seconds(timeout_sec);
17300b57cec5SDimitry Andric         break;
1731e8d8bef9SDimitry Andric       case 's': {
1732e8d8bef9SDimitry Andric         if (option_arg.empty()) {
1733e8d8bef9SDimitry Andric           error.SetErrorStringWithFormat(
1734e8d8bef9SDimitry Andric               "missing shell interpreter path for option -i|--interpreter.");
1735e8d8bef9SDimitry Andric           return error;
1736e8d8bef9SDimitry Andric         }
1737e8d8bef9SDimitry Andric 
1738e8d8bef9SDimitry Andric         m_shell_interpreter = option_arg.str();
1739e8d8bef9SDimitry Andric         break;
1740e8d8bef9SDimitry Andric       }
17410b57cec5SDimitry Andric       default:
17429dba64beSDimitry Andric         llvm_unreachable("Unimplemented option");
17430b57cec5SDimitry Andric       }
17440b57cec5SDimitry Andric 
17450b57cec5SDimitry Andric       return error;
17460b57cec5SDimitry Andric     }
17470b57cec5SDimitry Andric 
OptionParsingStarting(ExecutionContext * execution_context)17485ffd83dbSDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
17495ffd83dbSDimitry Andric       m_timeout.reset();
17505ffd83dbSDimitry Andric       m_use_host_platform = false;
1751e8d8bef9SDimitry Andric       m_shell_interpreter.clear();
17525ffd83dbSDimitry Andric     }
17530b57cec5SDimitry Andric 
17545ffd83dbSDimitry Andric     Timeout<std::micro> m_timeout = std::chrono::seconds(10);
17555ffd83dbSDimitry Andric     bool m_use_host_platform;
1756e8d8bef9SDimitry Andric     std::string m_shell_interpreter;
17570b57cec5SDimitry Andric   };
17580b57cec5SDimitry Andric 
CommandObjectPlatformShell(CommandInterpreter & interpreter)17590b57cec5SDimitry Andric   CommandObjectPlatformShell(CommandInterpreter &interpreter)
17600b57cec5SDimitry Andric       : CommandObjectRaw(interpreter, "platform shell",
17610b57cec5SDimitry Andric                          "Run a shell command on the current platform.",
176281ad6265SDimitry Andric                          "platform shell <shell-command>", 0) {
176381ad6265SDimitry Andric     CommandArgumentData thread_arg{eArgTypeNone, eArgRepeatStar};
176481ad6265SDimitry Andric     m_arguments.push_back({thread_arg});
176581ad6265SDimitry Andric   }
17660b57cec5SDimitry Andric 
17670b57cec5SDimitry Andric   ~CommandObjectPlatformShell() override = default;
17680b57cec5SDimitry Andric 
GetOptions()17690b57cec5SDimitry Andric   Options *GetOptions() override { return &m_options; }
17700b57cec5SDimitry Andric 
DoExecute(llvm::StringRef raw_command_line,CommandReturnObject & result)1771*c9157d92SDimitry Andric   void DoExecute(llvm::StringRef raw_command_line,
17720b57cec5SDimitry Andric                  CommandReturnObject &result) override {
17730b57cec5SDimitry Andric     ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext();
17740b57cec5SDimitry Andric     m_options.NotifyOptionParsingStarting(&exe_ctx);
17750b57cec5SDimitry Andric 
17760b57cec5SDimitry Andric     // Print out an usage syntax on an empty command line.
17770b57cec5SDimitry Andric     if (raw_command_line.empty()) {
17780b57cec5SDimitry Andric       result.GetOutputStream().Printf("%s\n", this->GetSyntax().str().c_str());
1779*c9157d92SDimitry Andric       return;
17800b57cec5SDimitry Andric     }
17810b57cec5SDimitry Andric 
17825ffd83dbSDimitry Andric     const bool is_alias = !raw_command_line.contains("platform");
17830b57cec5SDimitry Andric     OptionsWithRaw args(raw_command_line);
17840b57cec5SDimitry Andric 
17850b57cec5SDimitry Andric     if (args.HasArgs())
17860b57cec5SDimitry Andric       if (!ParseOptions(args.GetArgs(), result))
1787*c9157d92SDimitry Andric         return;
17880b57cec5SDimitry Andric 
17895ffd83dbSDimitry Andric     if (args.GetRawPart().empty()) {
17905ffd83dbSDimitry Andric       result.GetOutputStream().Printf("%s <shell-command>\n",
17915ffd83dbSDimitry Andric                                       is_alias ? "shell" : "platform shell");
1792*c9157d92SDimitry Andric       return;
17935ffd83dbSDimitry Andric     }
17945ffd83dbSDimitry Andric 
1795e8d8bef9SDimitry Andric     llvm::StringRef cmd = args.GetRawPart();
1796e8d8bef9SDimitry Andric 
17970b57cec5SDimitry Andric     PlatformSP platform_sp(
17985ffd83dbSDimitry Andric         m_options.m_use_host_platform
17995ffd83dbSDimitry Andric             ? Platform::GetHostPlatform()
18005ffd83dbSDimitry Andric             : GetDebugger().GetPlatformList().GetSelectedPlatform());
18010b57cec5SDimitry Andric     Status error;
18020b57cec5SDimitry Andric     if (platform_sp) {
18030b57cec5SDimitry Andric       FileSpec working_dir{};
18040b57cec5SDimitry Andric       std::string output;
18050b57cec5SDimitry Andric       int status = -1;
18060b57cec5SDimitry Andric       int signo = -1;
1807e8d8bef9SDimitry Andric       error = (platform_sp->RunShellCommand(m_options.m_shell_interpreter, cmd,
1808e8d8bef9SDimitry Andric                                             working_dir, &status, &signo,
18095ffd83dbSDimitry Andric                                             &output, m_options.m_timeout));
18100b57cec5SDimitry Andric       if (!output.empty())
18110b57cec5SDimitry Andric         result.GetOutputStream().PutCString(output);
18120b57cec5SDimitry Andric       if (status > 0) {
18130b57cec5SDimitry Andric         if (signo > 0) {
18140b57cec5SDimitry Andric           const char *signo_cstr = Host::GetSignalAsCString(signo);
18150b57cec5SDimitry Andric           if (signo_cstr)
18160b57cec5SDimitry Andric             result.GetOutputStream().Printf(
18170b57cec5SDimitry Andric                 "error: command returned with status %i and signal %s\n",
18180b57cec5SDimitry Andric                 status, signo_cstr);
18190b57cec5SDimitry Andric           else
18200b57cec5SDimitry Andric             result.GetOutputStream().Printf(
18210b57cec5SDimitry Andric                 "error: command returned with status %i and signal %i\n",
18220b57cec5SDimitry Andric                 status, signo);
18230b57cec5SDimitry Andric         } else
18240b57cec5SDimitry Andric           result.GetOutputStream().Printf(
18250b57cec5SDimitry Andric               "error: command returned with status %i\n", status);
18260b57cec5SDimitry Andric       }
18270b57cec5SDimitry Andric     } else {
18280b57cec5SDimitry Andric       result.GetOutputStream().Printf(
18290b57cec5SDimitry Andric           "error: cannot run remote shell commands without a platform\n");
18300b57cec5SDimitry Andric       error.SetErrorString(
18310b57cec5SDimitry Andric           "error: cannot run remote shell commands without a platform");
18320b57cec5SDimitry Andric     }
18330b57cec5SDimitry Andric 
18340b57cec5SDimitry Andric     if (error.Fail()) {
18350b57cec5SDimitry Andric       result.AppendError(error.AsCString());
18360b57cec5SDimitry Andric     } else {
18370b57cec5SDimitry Andric       result.SetStatus(eReturnStatusSuccessFinishResult);
18380b57cec5SDimitry Andric     }
18390b57cec5SDimitry Andric   }
18400b57cec5SDimitry Andric 
18410b57cec5SDimitry Andric   CommandOptions m_options;
18420b57cec5SDimitry Andric };
18430b57cec5SDimitry Andric 
18440b57cec5SDimitry Andric // "platform install" - install a target to a remote end
18450b57cec5SDimitry Andric class CommandObjectPlatformInstall : public CommandObjectParsed {
18460b57cec5SDimitry Andric public:
CommandObjectPlatformInstall(CommandInterpreter & interpreter)18470b57cec5SDimitry Andric   CommandObjectPlatformInstall(CommandInterpreter &interpreter)
18480b57cec5SDimitry Andric       : CommandObjectParsed(
18490b57cec5SDimitry Andric             interpreter, "platform target-install",
18500b57cec5SDimitry Andric             "Install a target (bundle or executable file) to the remote end.",
185181ad6265SDimitry Andric             "platform target-install <local-thing> <remote-sandbox>", 0) {
185281ad6265SDimitry Andric     CommandArgumentData local_arg{eArgTypePath, eArgRepeatPlain};
185381ad6265SDimitry Andric     CommandArgumentData remote_arg{eArgTypePath, eArgRepeatPlain};
185481ad6265SDimitry Andric     m_arguments.push_back({local_arg});
185581ad6265SDimitry Andric     m_arguments.push_back({remote_arg});
185681ad6265SDimitry Andric   }
18570b57cec5SDimitry Andric 
18580b57cec5SDimitry Andric   ~CommandObjectPlatformInstall() override = default;
18590b57cec5SDimitry Andric 
1860e8d8bef9SDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)1861e8d8bef9SDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
1862e8d8bef9SDimitry Andric                            OptionElementVector &opt_element_vector) override {
1863e8d8bef9SDimitry Andric     if (request.GetCursorIndex())
1864e8d8bef9SDimitry Andric       return;
1865fe013be4SDimitry Andric     lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1866fe013be4SDimitry Andric         GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr);
1867e8d8bef9SDimitry Andric   }
1868e8d8bef9SDimitry Andric 
DoExecute(Args & args,CommandReturnObject & result)1869*c9157d92SDimitry Andric   void DoExecute(Args &args, CommandReturnObject &result) override {
18700b57cec5SDimitry Andric     if (args.GetArgumentCount() != 2) {
18710b57cec5SDimitry Andric       result.AppendError("platform target-install takes two arguments");
1872*c9157d92SDimitry Andric       return;
18730b57cec5SDimitry Andric     }
18740b57cec5SDimitry Andric     // TODO: move the bulk of this code over to the platform itself
18750b57cec5SDimitry Andric     FileSpec src(args.GetArgumentAtIndex(0));
18760b57cec5SDimitry Andric     FileSystem::Instance().Resolve(src);
18770b57cec5SDimitry Andric     FileSpec dst(args.GetArgumentAtIndex(1));
18780b57cec5SDimitry Andric     if (!FileSystem::Instance().Exists(src)) {
18790b57cec5SDimitry Andric       result.AppendError("source location does not exist or is not accessible");
1880*c9157d92SDimitry Andric       return;
18810b57cec5SDimitry Andric     }
18820b57cec5SDimitry Andric     PlatformSP platform_sp(
18830b57cec5SDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
18840b57cec5SDimitry Andric     if (!platform_sp) {
18850b57cec5SDimitry Andric       result.AppendError("no platform currently selected");
1886*c9157d92SDimitry Andric       return;
18870b57cec5SDimitry Andric     }
18880b57cec5SDimitry Andric 
18890b57cec5SDimitry Andric     Status error = platform_sp->Install(src, dst);
18900b57cec5SDimitry Andric     if (error.Success()) {
18910b57cec5SDimitry Andric       result.SetStatus(eReturnStatusSuccessFinishNoResult);
18920b57cec5SDimitry Andric     } else {
18930b57cec5SDimitry Andric       result.AppendErrorWithFormat("install failed: %s", error.AsCString());
18940b57cec5SDimitry Andric     }
18950b57cec5SDimitry Andric   }
18960b57cec5SDimitry Andric };
18970b57cec5SDimitry Andric 
CommandObjectPlatform(CommandInterpreter & interpreter)18980b57cec5SDimitry Andric CommandObjectPlatform::CommandObjectPlatform(CommandInterpreter &interpreter)
18990b57cec5SDimitry Andric     : CommandObjectMultiword(
19000b57cec5SDimitry Andric           interpreter, "platform", "Commands to manage and create platforms.",
19010b57cec5SDimitry Andric           "platform [connect|disconnect|info|list|status|select] ...") {
19020b57cec5SDimitry Andric   LoadSubCommand("select",
19030b57cec5SDimitry Andric                  CommandObjectSP(new CommandObjectPlatformSelect(interpreter)));
19040b57cec5SDimitry Andric   LoadSubCommand("list",
19050b57cec5SDimitry Andric                  CommandObjectSP(new CommandObjectPlatformList(interpreter)));
19060b57cec5SDimitry Andric   LoadSubCommand("status",
19070b57cec5SDimitry Andric                  CommandObjectSP(new CommandObjectPlatformStatus(interpreter)));
19080b57cec5SDimitry Andric   LoadSubCommand("connect", CommandObjectSP(
19090b57cec5SDimitry Andric                                 new CommandObjectPlatformConnect(interpreter)));
19100b57cec5SDimitry Andric   LoadSubCommand(
19110b57cec5SDimitry Andric       "disconnect",
19120b57cec5SDimitry Andric       CommandObjectSP(new CommandObjectPlatformDisconnect(interpreter)));
19130b57cec5SDimitry Andric   LoadSubCommand("settings", CommandObjectSP(new CommandObjectPlatformSettings(
19140b57cec5SDimitry Andric                                  interpreter)));
19150b57cec5SDimitry Andric   LoadSubCommand("mkdir",
19160b57cec5SDimitry Andric                  CommandObjectSP(new CommandObjectPlatformMkDir(interpreter)));
19170b57cec5SDimitry Andric   LoadSubCommand("file",
19180b57cec5SDimitry Andric                  CommandObjectSP(new CommandObjectPlatformFile(interpreter)));
1919349cc55cSDimitry Andric   LoadSubCommand("file-exists",
1920349cc55cSDimitry Andric       CommandObjectSP(new CommandObjectPlatformFileExists(interpreter)));
19210b57cec5SDimitry Andric   LoadSubCommand("get-file", CommandObjectSP(new CommandObjectPlatformGetFile(
19220b57cec5SDimitry Andric                                  interpreter)));
1923349cc55cSDimitry Andric   LoadSubCommand("get-permissions",
1924349cc55cSDimitry Andric       CommandObjectSP(new CommandObjectPlatformGetPermissions(interpreter)));
19250b57cec5SDimitry Andric   LoadSubCommand("get-size", CommandObjectSP(new CommandObjectPlatformGetSize(
19260b57cec5SDimitry Andric                                  interpreter)));
19270b57cec5SDimitry Andric   LoadSubCommand("put-file", CommandObjectSP(new CommandObjectPlatformPutFile(
19280b57cec5SDimitry Andric                                  interpreter)));
19290b57cec5SDimitry Andric   LoadSubCommand("process", CommandObjectSP(
19300b57cec5SDimitry Andric                                 new CommandObjectPlatformProcess(interpreter)));
19310b57cec5SDimitry Andric   LoadSubCommand("shell",
19320b57cec5SDimitry Andric                  CommandObjectSP(new CommandObjectPlatformShell(interpreter)));
19330b57cec5SDimitry Andric   LoadSubCommand(
19340b57cec5SDimitry Andric       "target-install",
19350b57cec5SDimitry Andric       CommandObjectSP(new CommandObjectPlatformInstall(interpreter)));
19360b57cec5SDimitry Andric }
19370b57cec5SDimitry Andric 
19380b57cec5SDimitry Andric CommandObjectPlatform::~CommandObjectPlatform() = default;
1939