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