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