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"
10af732203SDimitry Andric #include "CommandOptionsProcessLaunch.h"
110b57cec5SDimitry Andric #include "lldb/Core/Debugger.h"
120b57cec5SDimitry Andric #include "lldb/Core/Module.h"
130b57cec5SDimitry Andric #include "lldb/Core/PluginManager.h"
140b57cec5SDimitry Andric #include "lldb/Host/OptionParser.h"
150b57cec5SDimitry Andric #include "lldb/Interpreter/CommandInterpreter.h"
160b57cec5SDimitry Andric #include "lldb/Interpreter/CommandOptionValidators.h"
170b57cec5SDimitry Andric #include "lldb/Interpreter/CommandReturnObject.h"
180b57cec5SDimitry Andric #include "lldb/Interpreter/OptionGroupFile.h"
190b57cec5SDimitry Andric #include "lldb/Interpreter/OptionGroupPlatform.h"
200b57cec5SDimitry Andric #include "lldb/Target/ExecutionContext.h"
210b57cec5SDimitry Andric #include "lldb/Target/Platform.h"
220b57cec5SDimitry Andric #include "lldb/Target/Process.h"
230b57cec5SDimitry Andric #include "lldb/Utility/Args.h"
240b57cec5SDimitry Andric
250b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
260b57cec5SDimitry Andric
270b57cec5SDimitry Andric using namespace lldb;
280b57cec5SDimitry Andric using namespace lldb_private;
290b57cec5SDimitry Andric
300b57cec5SDimitry Andric static mode_t ParsePermissionString(const char *) = delete;
310b57cec5SDimitry Andric
ParsePermissionString(llvm::StringRef permissions)320b57cec5SDimitry Andric static mode_t ParsePermissionString(llvm::StringRef permissions) {
330b57cec5SDimitry Andric if (permissions.size() != 9)
340b57cec5SDimitry Andric return (mode_t)(-1);
350b57cec5SDimitry Andric bool user_r, user_w, user_x, group_r, group_w, group_x, world_r, world_w,
360b57cec5SDimitry Andric world_x;
370b57cec5SDimitry Andric
380b57cec5SDimitry Andric user_r = (permissions[0] == 'r');
390b57cec5SDimitry Andric user_w = (permissions[1] == 'w');
400b57cec5SDimitry Andric user_x = (permissions[2] == 'x');
410b57cec5SDimitry Andric
420b57cec5SDimitry Andric group_r = (permissions[3] == 'r');
430b57cec5SDimitry Andric group_w = (permissions[4] == 'w');
440b57cec5SDimitry Andric group_x = (permissions[5] == 'x');
450b57cec5SDimitry Andric
460b57cec5SDimitry Andric world_r = (permissions[6] == 'r');
470b57cec5SDimitry Andric world_w = (permissions[7] == 'w');
480b57cec5SDimitry Andric world_x = (permissions[8] == 'x');
490b57cec5SDimitry Andric
500b57cec5SDimitry Andric mode_t user, group, world;
510b57cec5SDimitry Andric user = (user_r ? 4 : 0) | (user_w ? 2 : 0) | (user_x ? 1 : 0);
520b57cec5SDimitry Andric group = (group_r ? 4 : 0) | (group_w ? 2 : 0) | (group_x ? 1 : 0);
530b57cec5SDimitry Andric world = (world_r ? 4 : 0) | (world_w ? 2 : 0) | (world_x ? 1 : 0);
540b57cec5SDimitry Andric
550b57cec5SDimitry Andric return user | group | world;
560b57cec5SDimitry Andric }
570b57cec5SDimitry Andric
589dba64beSDimitry Andric #define LLDB_OPTIONS_permissions
599dba64beSDimitry Andric #include "CommandOptions.inc"
600b57cec5SDimitry Andric
610b57cec5SDimitry Andric class OptionPermissions : public OptionGroup {
620b57cec5SDimitry Andric public:
63*5f7ddb14SDimitry Andric OptionPermissions() = default;
640b57cec5SDimitry Andric
650b57cec5SDimitry Andric ~OptionPermissions() override = default;
660b57cec5SDimitry Andric
670b57cec5SDimitry Andric lldb_private::Status
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)680b57cec5SDimitry Andric SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
690b57cec5SDimitry Andric ExecutionContext *execution_context) override {
700b57cec5SDimitry Andric Status error;
710b57cec5SDimitry Andric char short_option = (char)GetDefinitions()[option_idx].short_option;
720b57cec5SDimitry Andric switch (short_option) {
730b57cec5SDimitry Andric case 'v': {
740b57cec5SDimitry Andric if (option_arg.getAsInteger(8, m_permissions)) {
750b57cec5SDimitry Andric m_permissions = 0777;
760b57cec5SDimitry Andric error.SetErrorStringWithFormat("invalid value for permissions: %s",
770b57cec5SDimitry Andric option_arg.str().c_str());
780b57cec5SDimitry Andric }
790b57cec5SDimitry Andric
800b57cec5SDimitry Andric } break;
810b57cec5SDimitry Andric case 's': {
820b57cec5SDimitry Andric mode_t perms = ParsePermissionString(option_arg);
830b57cec5SDimitry Andric if (perms == (mode_t)-1)
840b57cec5SDimitry Andric error.SetErrorStringWithFormat("invalid value for permissions: %s",
850b57cec5SDimitry Andric option_arg.str().c_str());
860b57cec5SDimitry Andric else
870b57cec5SDimitry Andric m_permissions = perms;
880b57cec5SDimitry Andric } break;
890b57cec5SDimitry Andric case 'r':
900b57cec5SDimitry Andric m_permissions |= lldb::eFilePermissionsUserRead;
910b57cec5SDimitry Andric break;
920b57cec5SDimitry Andric case 'w':
930b57cec5SDimitry Andric m_permissions |= lldb::eFilePermissionsUserWrite;
940b57cec5SDimitry Andric break;
950b57cec5SDimitry Andric case 'x':
960b57cec5SDimitry Andric m_permissions |= lldb::eFilePermissionsUserExecute;
970b57cec5SDimitry Andric break;
980b57cec5SDimitry Andric case 'R':
990b57cec5SDimitry Andric m_permissions |= lldb::eFilePermissionsGroupRead;
1000b57cec5SDimitry Andric break;
1010b57cec5SDimitry Andric case 'W':
1020b57cec5SDimitry Andric m_permissions |= lldb::eFilePermissionsGroupWrite;
1030b57cec5SDimitry Andric break;
1040b57cec5SDimitry Andric case 'X':
1050b57cec5SDimitry Andric m_permissions |= lldb::eFilePermissionsGroupExecute;
1060b57cec5SDimitry Andric break;
1070b57cec5SDimitry Andric case 'd':
1080b57cec5SDimitry Andric m_permissions |= lldb::eFilePermissionsWorldRead;
1090b57cec5SDimitry Andric break;
1100b57cec5SDimitry Andric case 't':
1110b57cec5SDimitry Andric m_permissions |= lldb::eFilePermissionsWorldWrite;
1120b57cec5SDimitry Andric break;
1130b57cec5SDimitry Andric case 'e':
1140b57cec5SDimitry Andric m_permissions |= lldb::eFilePermissionsWorldExecute;
1150b57cec5SDimitry Andric break;
1160b57cec5SDimitry Andric default:
1179dba64beSDimitry Andric llvm_unreachable("Unimplemented option");
1180b57cec5SDimitry Andric }
1190b57cec5SDimitry Andric
1200b57cec5SDimitry Andric return error;
1210b57cec5SDimitry Andric }
1220b57cec5SDimitry Andric
OptionParsingStarting(ExecutionContext * execution_context)1230b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
1240b57cec5SDimitry Andric m_permissions = 0;
1250b57cec5SDimitry Andric }
1260b57cec5SDimitry Andric
GetDefinitions()1270b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1280b57cec5SDimitry Andric return llvm::makeArrayRef(g_permissions_options);
1290b57cec5SDimitry Andric }
1300b57cec5SDimitry Andric
1310b57cec5SDimitry Andric // Instance variables to hold the values for command options.
1320b57cec5SDimitry Andric
1330b57cec5SDimitry Andric uint32_t m_permissions;
1340b57cec5SDimitry Andric
1350b57cec5SDimitry Andric private:
1365ffd83dbSDimitry Andric OptionPermissions(const OptionPermissions &) = delete;
1375ffd83dbSDimitry Andric const OptionPermissions &operator=(const OptionPermissions &) = delete;
1380b57cec5SDimitry Andric };
1390b57cec5SDimitry Andric
1400b57cec5SDimitry Andric // "platform select <platform-name>"
1410b57cec5SDimitry Andric class CommandObjectPlatformSelect : public CommandObjectParsed {
1420b57cec5SDimitry Andric public:
CommandObjectPlatformSelect(CommandInterpreter & interpreter)1430b57cec5SDimitry Andric CommandObjectPlatformSelect(CommandInterpreter &interpreter)
1440b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "platform select",
1450b57cec5SDimitry Andric "Create a platform if needed and select it as the "
1460b57cec5SDimitry Andric "current platform.",
1470b57cec5SDimitry Andric "platform select <platform-name>", 0),
1480b57cec5SDimitry Andric m_option_group(),
1490b57cec5SDimitry Andric m_platform_options(
1500b57cec5SDimitry Andric false) // Don't include the "--platform" option by passing false
1510b57cec5SDimitry Andric {
1520b57cec5SDimitry Andric m_option_group.Append(&m_platform_options, LLDB_OPT_SET_ALL, 1);
1530b57cec5SDimitry Andric m_option_group.Finalize();
1540b57cec5SDimitry Andric }
1550b57cec5SDimitry Andric
1560b57cec5SDimitry Andric ~CommandObjectPlatformSelect() override = default;
1570b57cec5SDimitry Andric
HandleCompletion(CompletionRequest & request)1589dba64beSDimitry Andric void HandleCompletion(CompletionRequest &request) override {
1590b57cec5SDimitry Andric CommandCompletions::PlatformPluginNames(GetCommandInterpreter(), request,
1600b57cec5SDimitry Andric nullptr);
1610b57cec5SDimitry Andric }
1620b57cec5SDimitry Andric
GetOptions()1630b57cec5SDimitry Andric Options *GetOptions() override { return &m_option_group; }
1640b57cec5SDimitry Andric
1650b57cec5SDimitry Andric protected:
DoExecute(Args & args,CommandReturnObject & result)1660b57cec5SDimitry Andric bool DoExecute(Args &args, CommandReturnObject &result) override {
1670b57cec5SDimitry Andric if (args.GetArgumentCount() == 1) {
1680b57cec5SDimitry Andric const char *platform_name = args.GetArgumentAtIndex(0);
1690b57cec5SDimitry Andric if (platform_name && platform_name[0]) {
1700b57cec5SDimitry Andric const bool select = true;
1710b57cec5SDimitry Andric m_platform_options.SetPlatformName(platform_name);
1720b57cec5SDimitry Andric Status error;
1730b57cec5SDimitry Andric ArchSpec platform_arch;
1740b57cec5SDimitry Andric PlatformSP platform_sp(m_platform_options.CreatePlatformWithOptions(
1750b57cec5SDimitry Andric m_interpreter, ArchSpec(), select, error, platform_arch));
1760b57cec5SDimitry Andric if (platform_sp) {
1770b57cec5SDimitry Andric GetDebugger().GetPlatformList().SetSelectedPlatform(platform_sp);
1780b57cec5SDimitry Andric
1790b57cec5SDimitry Andric platform_sp->GetStatus(result.GetOutputStream());
1800b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult);
1810b57cec5SDimitry Andric } else {
1820b57cec5SDimitry Andric result.AppendError(error.AsCString());
1830b57cec5SDimitry Andric }
1840b57cec5SDimitry Andric } else {
1850b57cec5SDimitry Andric result.AppendError("invalid platform name");
1860b57cec5SDimitry Andric }
1870b57cec5SDimitry Andric } else {
1880b57cec5SDimitry Andric result.AppendError(
1890b57cec5SDimitry Andric "platform create takes a platform name as an argument\n");
1900b57cec5SDimitry Andric }
1910b57cec5SDimitry Andric return result.Succeeded();
1920b57cec5SDimitry Andric }
1930b57cec5SDimitry Andric
1940b57cec5SDimitry Andric OptionGroupOptions m_option_group;
1950b57cec5SDimitry Andric OptionGroupPlatform m_platform_options;
1960b57cec5SDimitry Andric };
1970b57cec5SDimitry Andric
1980b57cec5SDimitry Andric // "platform list"
1990b57cec5SDimitry Andric class CommandObjectPlatformList : public CommandObjectParsed {
2000b57cec5SDimitry Andric public:
CommandObjectPlatformList(CommandInterpreter & interpreter)2010b57cec5SDimitry Andric CommandObjectPlatformList(CommandInterpreter &interpreter)
2020b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "platform list",
2030b57cec5SDimitry Andric "List all platforms that are available.", nullptr,
2040b57cec5SDimitry Andric 0) {}
2050b57cec5SDimitry Andric
2060b57cec5SDimitry Andric ~CommandObjectPlatformList() override = default;
2070b57cec5SDimitry Andric
2080b57cec5SDimitry Andric protected:
DoExecute(Args & args,CommandReturnObject & result)2090b57cec5SDimitry Andric bool DoExecute(Args &args, CommandReturnObject &result) override {
2100b57cec5SDimitry Andric Stream &ostrm = result.GetOutputStream();
2110b57cec5SDimitry Andric ostrm.Printf("Available platforms:\n");
2120b57cec5SDimitry Andric
2130b57cec5SDimitry Andric PlatformSP host_platform_sp(Platform::GetHostPlatform());
2140b57cec5SDimitry Andric ostrm.Printf("%s: %s\n", host_platform_sp->GetPluginName().GetCString(),
2150b57cec5SDimitry Andric host_platform_sp->GetDescription());
2160b57cec5SDimitry Andric
2170b57cec5SDimitry Andric uint32_t idx;
2180b57cec5SDimitry Andric for (idx = 0; true; ++idx) {
2190b57cec5SDimitry Andric const char *plugin_name =
2200b57cec5SDimitry Andric PluginManager::GetPlatformPluginNameAtIndex(idx);
2210b57cec5SDimitry Andric if (plugin_name == nullptr)
2220b57cec5SDimitry Andric break;
2230b57cec5SDimitry Andric const char *plugin_desc =
2240b57cec5SDimitry Andric PluginManager::GetPlatformPluginDescriptionAtIndex(idx);
2250b57cec5SDimitry Andric if (plugin_desc == nullptr)
2260b57cec5SDimitry Andric break;
2270b57cec5SDimitry Andric ostrm.Printf("%s: %s\n", plugin_name, plugin_desc);
2280b57cec5SDimitry Andric }
2290b57cec5SDimitry Andric
2300b57cec5SDimitry Andric if (idx == 0) {
2310b57cec5SDimitry Andric result.AppendError("no platforms are available\n");
2320b57cec5SDimitry Andric } else
2330b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult);
2340b57cec5SDimitry Andric return result.Succeeded();
2350b57cec5SDimitry Andric }
2360b57cec5SDimitry Andric };
2370b57cec5SDimitry Andric
2380b57cec5SDimitry Andric // "platform status"
2390b57cec5SDimitry Andric class CommandObjectPlatformStatus : public CommandObjectParsed {
2400b57cec5SDimitry Andric public:
CommandObjectPlatformStatus(CommandInterpreter & interpreter)2410b57cec5SDimitry Andric CommandObjectPlatformStatus(CommandInterpreter &interpreter)
2420b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "platform status",
2430b57cec5SDimitry Andric "Display status for the current platform.", nullptr,
2440b57cec5SDimitry Andric 0) {}
2450b57cec5SDimitry Andric
2460b57cec5SDimitry Andric ~CommandObjectPlatformStatus() override = default;
2470b57cec5SDimitry Andric
2480b57cec5SDimitry Andric protected:
DoExecute(Args & args,CommandReturnObject & result)2490b57cec5SDimitry Andric bool DoExecute(Args &args, CommandReturnObject &result) override {
2500b57cec5SDimitry Andric Stream &ostrm = result.GetOutputStream();
2510b57cec5SDimitry Andric
2520b57cec5SDimitry Andric Target *target = GetDebugger().GetSelectedTarget().get();
2530b57cec5SDimitry Andric PlatformSP platform_sp;
2540b57cec5SDimitry Andric if (target) {
2550b57cec5SDimitry Andric platform_sp = target->GetPlatform();
2560b57cec5SDimitry Andric }
2570b57cec5SDimitry Andric if (!platform_sp) {
2580b57cec5SDimitry Andric platform_sp = GetDebugger().GetPlatformList().GetSelectedPlatform();
2590b57cec5SDimitry Andric }
2600b57cec5SDimitry Andric if (platform_sp) {
2610b57cec5SDimitry Andric platform_sp->GetStatus(ostrm);
2620b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult);
2630b57cec5SDimitry Andric } else {
2640b57cec5SDimitry Andric result.AppendError("no platform is currently selected\n");
2650b57cec5SDimitry Andric }
2660b57cec5SDimitry Andric return result.Succeeded();
2670b57cec5SDimitry Andric }
2680b57cec5SDimitry Andric };
2690b57cec5SDimitry Andric
2700b57cec5SDimitry Andric // "platform connect <connect-url>"
2710b57cec5SDimitry Andric class CommandObjectPlatformConnect : public CommandObjectParsed {
2720b57cec5SDimitry Andric public:
CommandObjectPlatformConnect(CommandInterpreter & interpreter)2730b57cec5SDimitry Andric CommandObjectPlatformConnect(CommandInterpreter &interpreter)
2740b57cec5SDimitry Andric : CommandObjectParsed(
2750b57cec5SDimitry Andric interpreter, "platform connect",
2760b57cec5SDimitry Andric "Select the current platform by providing a connection URL.",
2770b57cec5SDimitry Andric "platform connect <connect-url>", 0) {}
2780b57cec5SDimitry Andric
2790b57cec5SDimitry Andric ~CommandObjectPlatformConnect() override = default;
2800b57cec5SDimitry Andric
2810b57cec5SDimitry Andric protected:
DoExecute(Args & args,CommandReturnObject & result)2820b57cec5SDimitry Andric bool DoExecute(Args &args, CommandReturnObject &result) override {
2830b57cec5SDimitry Andric Stream &ostrm = result.GetOutputStream();
2840b57cec5SDimitry Andric
2850b57cec5SDimitry Andric PlatformSP platform_sp(
2860b57cec5SDimitry Andric GetDebugger().GetPlatformList().GetSelectedPlatform());
2870b57cec5SDimitry Andric if (platform_sp) {
2880b57cec5SDimitry Andric Status error(platform_sp->ConnectRemote(args));
2890b57cec5SDimitry Andric if (error.Success()) {
2900b57cec5SDimitry Andric platform_sp->GetStatus(ostrm);
2910b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult);
2920b57cec5SDimitry Andric
2930b57cec5SDimitry Andric platform_sp->ConnectToWaitingProcesses(GetDebugger(), error);
2940b57cec5SDimitry Andric if (error.Fail()) {
2950b57cec5SDimitry Andric result.AppendError(error.AsCString());
2960b57cec5SDimitry Andric }
2970b57cec5SDimitry Andric } else {
2980b57cec5SDimitry Andric result.AppendErrorWithFormat("%s\n", error.AsCString());
2990b57cec5SDimitry Andric }
3000b57cec5SDimitry Andric } else {
3010b57cec5SDimitry Andric result.AppendError("no platform is currently selected\n");
3020b57cec5SDimitry Andric }
3030b57cec5SDimitry Andric return result.Succeeded();
3040b57cec5SDimitry Andric }
3050b57cec5SDimitry Andric
GetOptions()3060b57cec5SDimitry Andric Options *GetOptions() override {
3070b57cec5SDimitry Andric PlatformSP platform_sp(
3080b57cec5SDimitry Andric GetDebugger().GetPlatformList().GetSelectedPlatform());
3090b57cec5SDimitry Andric OptionGroupOptions *m_platform_options = nullptr;
3100b57cec5SDimitry Andric if (platform_sp) {
3110b57cec5SDimitry Andric m_platform_options = platform_sp->GetConnectionOptions(m_interpreter);
3120b57cec5SDimitry Andric if (m_platform_options != nullptr && !m_platform_options->m_did_finalize)
3130b57cec5SDimitry Andric m_platform_options->Finalize();
3140b57cec5SDimitry Andric }
3150b57cec5SDimitry Andric return m_platform_options;
3160b57cec5SDimitry Andric }
3170b57cec5SDimitry Andric };
3180b57cec5SDimitry Andric
3190b57cec5SDimitry Andric // "platform disconnect"
3200b57cec5SDimitry Andric class CommandObjectPlatformDisconnect : public CommandObjectParsed {
3210b57cec5SDimitry Andric public:
CommandObjectPlatformDisconnect(CommandInterpreter & interpreter)3220b57cec5SDimitry Andric CommandObjectPlatformDisconnect(CommandInterpreter &interpreter)
3230b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "platform disconnect",
3240b57cec5SDimitry Andric "Disconnect from the current platform.",
3250b57cec5SDimitry Andric "platform disconnect", 0) {}
3260b57cec5SDimitry Andric
3270b57cec5SDimitry Andric ~CommandObjectPlatformDisconnect() override = default;
3280b57cec5SDimitry Andric
3290b57cec5SDimitry Andric protected:
DoExecute(Args & args,CommandReturnObject & result)3300b57cec5SDimitry Andric bool DoExecute(Args &args, CommandReturnObject &result) override {
3310b57cec5SDimitry Andric PlatformSP platform_sp(
3320b57cec5SDimitry Andric GetDebugger().GetPlatformList().GetSelectedPlatform());
3330b57cec5SDimitry Andric if (platform_sp) {
3340b57cec5SDimitry Andric if (args.GetArgumentCount() == 0) {
3350b57cec5SDimitry Andric Status error;
3360b57cec5SDimitry Andric
3370b57cec5SDimitry Andric if (platform_sp->IsConnected()) {
3380b57cec5SDimitry Andric // Cache the instance name if there is one since we are about to
3390b57cec5SDimitry Andric // disconnect and the name might go with it.
3400b57cec5SDimitry Andric const char *hostname_cstr = platform_sp->GetHostname();
3410b57cec5SDimitry Andric std::string hostname;
3420b57cec5SDimitry Andric if (hostname_cstr)
3430b57cec5SDimitry Andric hostname.assign(hostname_cstr);
3440b57cec5SDimitry Andric
3450b57cec5SDimitry Andric error = platform_sp->DisconnectRemote();
3460b57cec5SDimitry Andric if (error.Success()) {
3470b57cec5SDimitry Andric Stream &ostrm = result.GetOutputStream();
3480b57cec5SDimitry Andric if (hostname.empty())
3490b57cec5SDimitry Andric ostrm.Printf("Disconnected from \"%s\"\n",
3500b57cec5SDimitry Andric platform_sp->GetPluginName().GetCString());
3510b57cec5SDimitry Andric else
3520b57cec5SDimitry Andric ostrm.Printf("Disconnected from \"%s\"\n", hostname.c_str());
3530b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult);
3540b57cec5SDimitry Andric } else {
3550b57cec5SDimitry Andric result.AppendErrorWithFormat("%s", error.AsCString());
3560b57cec5SDimitry Andric }
3570b57cec5SDimitry Andric } else {
3580b57cec5SDimitry Andric // Not connected...
3590b57cec5SDimitry Andric result.AppendErrorWithFormat(
3600b57cec5SDimitry Andric "not connected to '%s'",
3610b57cec5SDimitry Andric platform_sp->GetPluginName().GetCString());
3620b57cec5SDimitry Andric }
3630b57cec5SDimitry Andric } else {
3640b57cec5SDimitry Andric // Bad args
3650b57cec5SDimitry Andric result.AppendError(
3660b57cec5SDimitry Andric "\"platform disconnect\" doesn't take any arguments");
3670b57cec5SDimitry Andric }
3680b57cec5SDimitry Andric } else {
3690b57cec5SDimitry Andric result.AppendError("no platform is currently selected");
3700b57cec5SDimitry Andric }
3710b57cec5SDimitry Andric return result.Succeeded();
3720b57cec5SDimitry Andric }
3730b57cec5SDimitry Andric };
3740b57cec5SDimitry Andric
3750b57cec5SDimitry Andric // "platform settings"
3760b57cec5SDimitry Andric class CommandObjectPlatformSettings : public CommandObjectParsed {
3770b57cec5SDimitry Andric public:
CommandObjectPlatformSettings(CommandInterpreter & interpreter)3780b57cec5SDimitry Andric CommandObjectPlatformSettings(CommandInterpreter &interpreter)
3790b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "platform settings",
3800b57cec5SDimitry Andric "Set settings for the current target's platform, "
3810b57cec5SDimitry Andric "or for a platform by name.",
3820b57cec5SDimitry Andric "platform settings", 0),
3830b57cec5SDimitry Andric m_options(),
384af732203SDimitry Andric m_option_working_dir(LLDB_OPT_SET_1, false, "working-dir", 'w',
385af732203SDimitry Andric CommandCompletions::eRemoteDiskDirectoryCompletion,
3860b57cec5SDimitry Andric eArgTypePath,
3870b57cec5SDimitry Andric "The working directory for the platform.") {
3880b57cec5SDimitry Andric m_options.Append(&m_option_working_dir, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
3890b57cec5SDimitry Andric }
3900b57cec5SDimitry Andric
3910b57cec5SDimitry Andric ~CommandObjectPlatformSettings() override = default;
3920b57cec5SDimitry Andric
3930b57cec5SDimitry Andric protected:
DoExecute(Args & args,CommandReturnObject & result)3940b57cec5SDimitry Andric bool DoExecute(Args &args, CommandReturnObject &result) override {
3950b57cec5SDimitry Andric PlatformSP platform_sp(
3960b57cec5SDimitry Andric GetDebugger().GetPlatformList().GetSelectedPlatform());
3970b57cec5SDimitry Andric if (platform_sp) {
3980b57cec5SDimitry Andric if (m_option_working_dir.GetOptionValue().OptionWasSet())
3990b57cec5SDimitry Andric platform_sp->SetWorkingDirectory(
4000b57cec5SDimitry Andric m_option_working_dir.GetOptionValue().GetCurrentValue());
4010b57cec5SDimitry Andric } else {
4020b57cec5SDimitry Andric result.AppendError("no platform is currently selected");
4030b57cec5SDimitry Andric }
4040b57cec5SDimitry Andric return result.Succeeded();
4050b57cec5SDimitry Andric }
4060b57cec5SDimitry Andric
GetOptions()4070b57cec5SDimitry Andric Options *GetOptions() override {
4080b57cec5SDimitry Andric if (!m_options.DidFinalize())
4090b57cec5SDimitry Andric m_options.Finalize();
4100b57cec5SDimitry Andric return &m_options;
4110b57cec5SDimitry Andric }
4120b57cec5SDimitry Andric
4130b57cec5SDimitry Andric OptionGroupOptions m_options;
4140b57cec5SDimitry Andric OptionGroupFile m_option_working_dir;
4150b57cec5SDimitry Andric };
4160b57cec5SDimitry Andric
4170b57cec5SDimitry Andric // "platform mkdir"
4180b57cec5SDimitry Andric class CommandObjectPlatformMkDir : public CommandObjectParsed {
4190b57cec5SDimitry Andric public:
CommandObjectPlatformMkDir(CommandInterpreter & interpreter)4200b57cec5SDimitry Andric CommandObjectPlatformMkDir(CommandInterpreter &interpreter)
4210b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "platform mkdir",
4220b57cec5SDimitry Andric "Make a new directory on the remote end.", nullptr,
4230b57cec5SDimitry Andric 0),
4240b57cec5SDimitry Andric m_options() {}
4250b57cec5SDimitry Andric
4260b57cec5SDimitry Andric ~CommandObjectPlatformMkDir() override = default;
4270b57cec5SDimitry Andric
DoExecute(Args & args,CommandReturnObject & result)4280b57cec5SDimitry Andric bool DoExecute(Args &args, CommandReturnObject &result) override {
4290b57cec5SDimitry Andric PlatformSP platform_sp(
4300b57cec5SDimitry Andric GetDebugger().GetPlatformList().GetSelectedPlatform());
4310b57cec5SDimitry Andric if (platform_sp) {
4320b57cec5SDimitry Andric std::string cmd_line;
4330b57cec5SDimitry Andric args.GetCommandString(cmd_line);
4340b57cec5SDimitry Andric uint32_t mode;
4350b57cec5SDimitry Andric const OptionPermissions *options_permissions =
4360b57cec5SDimitry Andric (const OptionPermissions *)m_options.GetGroupWithOption('r');
4370b57cec5SDimitry Andric if (options_permissions)
4380b57cec5SDimitry Andric mode = options_permissions->m_permissions;
4390b57cec5SDimitry Andric else
4400b57cec5SDimitry Andric mode = lldb::eFilePermissionsUserRWX | lldb::eFilePermissionsGroupRWX |
4410b57cec5SDimitry Andric lldb::eFilePermissionsWorldRX;
4420b57cec5SDimitry Andric Status error = platform_sp->MakeDirectory(FileSpec(cmd_line), mode);
4430b57cec5SDimitry Andric if (error.Success()) {
4440b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult);
4450b57cec5SDimitry Andric } else {
4460b57cec5SDimitry Andric result.AppendError(error.AsCString());
4470b57cec5SDimitry Andric }
4480b57cec5SDimitry Andric } else {
4490b57cec5SDimitry Andric result.AppendError("no platform currently selected\n");
4500b57cec5SDimitry Andric }
4510b57cec5SDimitry Andric return result.Succeeded();
4520b57cec5SDimitry Andric }
4530b57cec5SDimitry Andric
GetOptions()4540b57cec5SDimitry Andric Options *GetOptions() override {
4550b57cec5SDimitry Andric if (!m_options.DidFinalize()) {
4560b57cec5SDimitry Andric m_options.Append(new OptionPermissions());
4570b57cec5SDimitry Andric m_options.Finalize();
4580b57cec5SDimitry Andric }
4590b57cec5SDimitry Andric return &m_options;
4600b57cec5SDimitry Andric }
4610b57cec5SDimitry Andric
4620b57cec5SDimitry Andric OptionGroupOptions m_options;
4630b57cec5SDimitry Andric };
4640b57cec5SDimitry Andric
4650b57cec5SDimitry Andric // "platform fopen"
4660b57cec5SDimitry Andric class CommandObjectPlatformFOpen : public CommandObjectParsed {
4670b57cec5SDimitry Andric public:
CommandObjectPlatformFOpen(CommandInterpreter & interpreter)4680b57cec5SDimitry Andric CommandObjectPlatformFOpen(CommandInterpreter &interpreter)
4690b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "platform file open",
4700b57cec5SDimitry Andric "Open a file on the remote end.", nullptr, 0),
4710b57cec5SDimitry Andric m_options() {}
4720b57cec5SDimitry Andric
4730b57cec5SDimitry Andric ~CommandObjectPlatformFOpen() override = default;
4740b57cec5SDimitry Andric
475af732203SDimitry Andric void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)476af732203SDimitry Andric HandleArgumentCompletion(CompletionRequest &request,
477af732203SDimitry Andric OptionElementVector &opt_element_vector) override {
478af732203SDimitry Andric if (request.GetCursorIndex() == 0)
479af732203SDimitry Andric CommandCompletions::InvokeCommonCompletionCallbacks(
480af732203SDimitry Andric GetCommandInterpreter(),
481af732203SDimitry Andric CommandCompletions::eRemoteDiskFileCompletion, request, nullptr);
482af732203SDimitry Andric }
483af732203SDimitry Andric
DoExecute(Args & args,CommandReturnObject & result)4840b57cec5SDimitry Andric bool DoExecute(Args &args, CommandReturnObject &result) override {
4850b57cec5SDimitry Andric PlatformSP platform_sp(
4860b57cec5SDimitry Andric GetDebugger().GetPlatformList().GetSelectedPlatform());
4870b57cec5SDimitry Andric if (platform_sp) {
4880b57cec5SDimitry Andric Status error;
4890b57cec5SDimitry Andric std::string cmd_line;
4900b57cec5SDimitry Andric args.GetCommandString(cmd_line);
4910b57cec5SDimitry Andric mode_t perms;
4920b57cec5SDimitry Andric const OptionPermissions *options_permissions =
4930b57cec5SDimitry Andric (const OptionPermissions *)m_options.GetGroupWithOption('r');
4940b57cec5SDimitry Andric if (options_permissions)
4950b57cec5SDimitry Andric perms = options_permissions->m_permissions;
4960b57cec5SDimitry Andric else
4970b57cec5SDimitry Andric perms = lldb::eFilePermissionsUserRW | lldb::eFilePermissionsGroupRW |
4980b57cec5SDimitry Andric lldb::eFilePermissionsWorldRead;
4990b57cec5SDimitry Andric lldb::user_id_t fd = platform_sp->OpenFile(
5000b57cec5SDimitry Andric FileSpec(cmd_line),
5010b57cec5SDimitry Andric File::eOpenOptionRead | File::eOpenOptionWrite |
5020b57cec5SDimitry Andric File::eOpenOptionAppend | 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 return result.Succeeded();
5140b57cec5SDimitry Andric }
5150b57cec5SDimitry Andric
GetOptions()5160b57cec5SDimitry Andric Options *GetOptions() override {
5170b57cec5SDimitry Andric if (!m_options.DidFinalize()) {
5180b57cec5SDimitry Andric m_options.Append(new OptionPermissions());
5190b57cec5SDimitry Andric m_options.Finalize();
5200b57cec5SDimitry Andric }
5210b57cec5SDimitry Andric return &m_options;
5220b57cec5SDimitry Andric }
5230b57cec5SDimitry Andric
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",
5320b57cec5SDimitry Andric "Close a file on the remote end.", nullptr, 0) {}
5330b57cec5SDimitry Andric
5340b57cec5SDimitry Andric ~CommandObjectPlatformFClose() override = default;
5350b57cec5SDimitry Andric
DoExecute(Args & args,CommandReturnObject & result)5360b57cec5SDimitry Andric bool DoExecute(Args &args, CommandReturnObject &result) override {
5370b57cec5SDimitry Andric PlatformSP platform_sp(
5380b57cec5SDimitry Andric GetDebugger().GetPlatformList().GetSelectedPlatform());
5390b57cec5SDimitry Andric if (platform_sp) {
5400b57cec5SDimitry Andric std::string cmd_line;
5410b57cec5SDimitry Andric args.GetCommandString(cmd_line);
5425ffd83dbSDimitry Andric lldb::user_id_t fd;
5435ffd83dbSDimitry Andric if (!llvm::to_integer(cmd_line, fd)) {
5445ffd83dbSDimitry Andric result.AppendErrorWithFormatv("'{0}' is not a valid file descriptor.\n",
5455ffd83dbSDimitry Andric cmd_line);
5465ffd83dbSDimitry Andric return result.Succeeded();
5475ffd83dbSDimitry Andric }
5480b57cec5SDimitry Andric Status error;
5490b57cec5SDimitry Andric bool success = platform_sp->CloseFile(fd, error);
5500b57cec5SDimitry Andric if (success) {
5510b57cec5SDimitry Andric result.AppendMessageWithFormat("file %" PRIu64 " closed.\n", fd);
5520b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult);
5530b57cec5SDimitry Andric } else {
5540b57cec5SDimitry Andric result.AppendError(error.AsCString());
5550b57cec5SDimitry Andric }
5560b57cec5SDimitry Andric } else {
5570b57cec5SDimitry Andric result.AppendError("no platform currently selected\n");
5580b57cec5SDimitry Andric }
5590b57cec5SDimitry Andric return result.Succeeded();
5600b57cec5SDimitry Andric }
5610b57cec5SDimitry Andric };
5620b57cec5SDimitry Andric
5630b57cec5SDimitry Andric // "platform fread"
5640b57cec5SDimitry Andric
5659dba64beSDimitry Andric #define LLDB_OPTIONS_platform_fread
5669dba64beSDimitry Andric #include "CommandOptions.inc"
5670b57cec5SDimitry Andric
5680b57cec5SDimitry Andric class CommandObjectPlatformFRead : public CommandObjectParsed {
5690b57cec5SDimitry Andric public:
CommandObjectPlatformFRead(CommandInterpreter & interpreter)5700b57cec5SDimitry Andric CommandObjectPlatformFRead(CommandInterpreter &interpreter)
5710b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "platform file read",
5720b57cec5SDimitry Andric "Read data from a file on the remote end.", nullptr,
5730b57cec5SDimitry Andric 0),
5740b57cec5SDimitry Andric m_options() {}
5750b57cec5SDimitry Andric
5760b57cec5SDimitry Andric ~CommandObjectPlatformFRead() override = default;
5770b57cec5SDimitry Andric
DoExecute(Args & args,CommandReturnObject & result)5780b57cec5SDimitry Andric bool DoExecute(Args &args, CommandReturnObject &result) override {
5790b57cec5SDimitry Andric PlatformSP platform_sp(
5800b57cec5SDimitry Andric GetDebugger().GetPlatformList().GetSelectedPlatform());
5810b57cec5SDimitry Andric if (platform_sp) {
5820b57cec5SDimitry Andric std::string cmd_line;
5830b57cec5SDimitry Andric args.GetCommandString(cmd_line);
5845ffd83dbSDimitry Andric lldb::user_id_t fd;
5855ffd83dbSDimitry Andric if (!llvm::to_integer(cmd_line, fd)) {
5865ffd83dbSDimitry Andric result.AppendErrorWithFormatv("'{0}' is not a valid file descriptor.\n",
5875ffd83dbSDimitry Andric cmd_line);
5885ffd83dbSDimitry Andric return result.Succeeded();
5895ffd83dbSDimitry Andric }
5900b57cec5SDimitry Andric std::string buffer(m_options.m_count, 0);
5910b57cec5SDimitry Andric Status error;
5920b57cec5SDimitry Andric uint32_t retcode = platform_sp->ReadFile(
5930b57cec5SDimitry Andric fd, m_options.m_offset, &buffer[0], m_options.m_count, error);
5940b57cec5SDimitry Andric result.AppendMessageWithFormat("Return = %d\n", retcode);
5950b57cec5SDimitry Andric result.AppendMessageWithFormat("Data = \"%s\"\n", buffer.c_str());
5960b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult);
5970b57cec5SDimitry Andric } else {
5980b57cec5SDimitry Andric result.AppendError("no platform currently selected\n");
5990b57cec5SDimitry Andric }
6000b57cec5SDimitry Andric return result.Succeeded();
6010b57cec5SDimitry Andric }
6020b57cec5SDimitry Andric
GetOptions()6030b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; }
6040b57cec5SDimitry Andric
6050b57cec5SDimitry Andric protected:
6060b57cec5SDimitry Andric class CommandOptions : public Options {
6070b57cec5SDimitry Andric public:
CommandOptions()6080b57cec5SDimitry Andric CommandOptions() : Options() {}
6090b57cec5SDimitry Andric
6100b57cec5SDimitry Andric ~CommandOptions() override = default;
6110b57cec5SDimitry Andric
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)6120b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
6130b57cec5SDimitry Andric ExecutionContext *execution_context) override {
6140b57cec5SDimitry Andric Status error;
6150b57cec5SDimitry Andric char short_option = (char)m_getopt_table[option_idx].val;
6160b57cec5SDimitry Andric
6170b57cec5SDimitry Andric switch (short_option) {
6180b57cec5SDimitry Andric case 'o':
6190b57cec5SDimitry Andric if (option_arg.getAsInteger(0, m_offset))
6200b57cec5SDimitry Andric error.SetErrorStringWithFormat("invalid offset: '%s'",
6210b57cec5SDimitry Andric option_arg.str().c_str());
6220b57cec5SDimitry Andric break;
6230b57cec5SDimitry Andric case 'c':
6240b57cec5SDimitry Andric if (option_arg.getAsInteger(0, m_count))
6250b57cec5SDimitry Andric error.SetErrorStringWithFormat("invalid offset: '%s'",
6260b57cec5SDimitry Andric option_arg.str().c_str());
6270b57cec5SDimitry Andric break;
6280b57cec5SDimitry Andric default:
6299dba64beSDimitry Andric llvm_unreachable("Unimplemented option");
6300b57cec5SDimitry Andric }
6310b57cec5SDimitry Andric
6320b57cec5SDimitry Andric return error;
6330b57cec5SDimitry Andric }
6340b57cec5SDimitry Andric
OptionParsingStarting(ExecutionContext * execution_context)6350b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
6360b57cec5SDimitry Andric m_offset = 0;
6370b57cec5SDimitry Andric m_count = 1;
6380b57cec5SDimitry Andric }
6390b57cec5SDimitry Andric
GetDefinitions()6400b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
6410b57cec5SDimitry Andric return llvm::makeArrayRef(g_platform_fread_options);
6420b57cec5SDimitry Andric }
6430b57cec5SDimitry Andric
6440b57cec5SDimitry Andric // Instance variables to hold the values for command options.
6450b57cec5SDimitry Andric
6460b57cec5SDimitry Andric uint32_t m_offset;
6470b57cec5SDimitry Andric uint32_t m_count;
6480b57cec5SDimitry Andric };
6490b57cec5SDimitry Andric
6500b57cec5SDimitry Andric CommandOptions m_options;
6510b57cec5SDimitry Andric };
6520b57cec5SDimitry Andric
6530b57cec5SDimitry Andric // "platform fwrite"
6540b57cec5SDimitry Andric
6559dba64beSDimitry Andric #define LLDB_OPTIONS_platform_fwrite
6569dba64beSDimitry Andric #include "CommandOptions.inc"
6570b57cec5SDimitry Andric
6580b57cec5SDimitry Andric class CommandObjectPlatformFWrite : public CommandObjectParsed {
6590b57cec5SDimitry Andric public:
CommandObjectPlatformFWrite(CommandInterpreter & interpreter)6600b57cec5SDimitry Andric CommandObjectPlatformFWrite(CommandInterpreter &interpreter)
6610b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "platform file write",
6620b57cec5SDimitry Andric "Write data to a file on the remote end.", nullptr,
6630b57cec5SDimitry Andric 0),
6640b57cec5SDimitry Andric m_options() {}
6650b57cec5SDimitry Andric
6660b57cec5SDimitry Andric ~CommandObjectPlatformFWrite() override = default;
6670b57cec5SDimitry Andric
DoExecute(Args & args,CommandReturnObject & result)6680b57cec5SDimitry Andric bool DoExecute(Args &args, CommandReturnObject &result) override {
6690b57cec5SDimitry Andric PlatformSP platform_sp(
6700b57cec5SDimitry Andric GetDebugger().GetPlatformList().GetSelectedPlatform());
6710b57cec5SDimitry Andric if (platform_sp) {
6720b57cec5SDimitry Andric std::string cmd_line;
6730b57cec5SDimitry Andric args.GetCommandString(cmd_line);
6740b57cec5SDimitry Andric Status error;
6755ffd83dbSDimitry Andric lldb::user_id_t fd;
6765ffd83dbSDimitry Andric if (!llvm::to_integer(cmd_line, fd)) {
6775ffd83dbSDimitry Andric result.AppendErrorWithFormatv("'{0}' is not a valid file descriptor.",
6785ffd83dbSDimitry Andric cmd_line);
6795ffd83dbSDimitry Andric return result.Succeeded();
6805ffd83dbSDimitry Andric }
6810b57cec5SDimitry Andric uint32_t retcode =
6820b57cec5SDimitry Andric platform_sp->WriteFile(fd, m_options.m_offset, &m_options.m_data[0],
6830b57cec5SDimitry Andric m_options.m_data.size(), error);
6840b57cec5SDimitry Andric result.AppendMessageWithFormat("Return = %d\n", retcode);
6850b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult);
6860b57cec5SDimitry Andric } else {
6870b57cec5SDimitry Andric result.AppendError("no platform currently selected\n");
6880b57cec5SDimitry Andric }
6890b57cec5SDimitry Andric return result.Succeeded();
6900b57cec5SDimitry Andric }
6910b57cec5SDimitry Andric
GetOptions()6920b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; }
6930b57cec5SDimitry Andric
6940b57cec5SDimitry Andric protected:
6950b57cec5SDimitry Andric class CommandOptions : public Options {
6960b57cec5SDimitry Andric public:
CommandOptions()6970b57cec5SDimitry Andric CommandOptions() : Options() {}
6980b57cec5SDimitry Andric
6990b57cec5SDimitry Andric ~CommandOptions() override = default;
7000b57cec5SDimitry Andric
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)7010b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
7020b57cec5SDimitry Andric ExecutionContext *execution_context) override {
7030b57cec5SDimitry Andric Status error;
7040b57cec5SDimitry Andric char short_option = (char)m_getopt_table[option_idx].val;
7050b57cec5SDimitry Andric
7060b57cec5SDimitry Andric switch (short_option) {
7070b57cec5SDimitry Andric case 'o':
7080b57cec5SDimitry Andric if (option_arg.getAsInteger(0, m_offset))
7090b57cec5SDimitry Andric error.SetErrorStringWithFormat("invalid offset: '%s'",
7100b57cec5SDimitry Andric option_arg.str().c_str());
7110b57cec5SDimitry Andric break;
7120b57cec5SDimitry Andric case 'd':
7135ffd83dbSDimitry Andric m_data.assign(std::string(option_arg));
7140b57cec5SDimitry Andric break;
7150b57cec5SDimitry Andric default:
7169dba64beSDimitry Andric llvm_unreachable("Unimplemented option");
7170b57cec5SDimitry Andric }
7180b57cec5SDimitry Andric
7190b57cec5SDimitry Andric return error;
7200b57cec5SDimitry Andric }
7210b57cec5SDimitry Andric
OptionParsingStarting(ExecutionContext * execution_context)7220b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
7230b57cec5SDimitry Andric m_offset = 0;
7240b57cec5SDimitry Andric m_data.clear();
7250b57cec5SDimitry Andric }
7260b57cec5SDimitry Andric
GetDefinitions()7270b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
7280b57cec5SDimitry Andric return llvm::makeArrayRef(g_platform_fwrite_options);
7290b57cec5SDimitry Andric }
7300b57cec5SDimitry Andric
7310b57cec5SDimitry Andric // Instance variables to hold the values for command options.
7320b57cec5SDimitry Andric
7330b57cec5SDimitry Andric uint32_t m_offset;
7340b57cec5SDimitry Andric std::string m_data;
7350b57cec5SDimitry Andric };
7360b57cec5SDimitry Andric
7370b57cec5SDimitry Andric CommandOptions m_options;
7380b57cec5SDimitry Andric };
7390b57cec5SDimitry Andric
7400b57cec5SDimitry Andric class CommandObjectPlatformFile : public CommandObjectMultiword {
7410b57cec5SDimitry Andric public:
7420b57cec5SDimitry Andric // Constructors and Destructors
CommandObjectPlatformFile(CommandInterpreter & interpreter)7430b57cec5SDimitry Andric CommandObjectPlatformFile(CommandInterpreter &interpreter)
7440b57cec5SDimitry Andric : CommandObjectMultiword(
7450b57cec5SDimitry Andric interpreter, "platform file",
7460b57cec5SDimitry Andric "Commands to access files on the current platform.",
7470b57cec5SDimitry Andric "platform file [open|close|read|write] ...") {
7480b57cec5SDimitry Andric LoadSubCommand(
7490b57cec5SDimitry Andric "open", CommandObjectSP(new CommandObjectPlatformFOpen(interpreter)));
7500b57cec5SDimitry Andric LoadSubCommand(
7510b57cec5SDimitry Andric "close", CommandObjectSP(new CommandObjectPlatformFClose(interpreter)));
7520b57cec5SDimitry Andric LoadSubCommand(
7530b57cec5SDimitry Andric "read", CommandObjectSP(new CommandObjectPlatformFRead(interpreter)));
7540b57cec5SDimitry Andric LoadSubCommand(
7550b57cec5SDimitry Andric "write", CommandObjectSP(new CommandObjectPlatformFWrite(interpreter)));
7560b57cec5SDimitry Andric }
7570b57cec5SDimitry Andric
7580b57cec5SDimitry Andric ~CommandObjectPlatformFile() override = default;
7590b57cec5SDimitry Andric
7600b57cec5SDimitry Andric private:
7610b57cec5SDimitry Andric // For CommandObjectPlatform only
7625ffd83dbSDimitry Andric CommandObjectPlatformFile(const CommandObjectPlatformFile &) = delete;
7635ffd83dbSDimitry Andric const CommandObjectPlatformFile &
7645ffd83dbSDimitry Andric operator=(const CommandObjectPlatformFile &) = delete;
7650b57cec5SDimitry Andric };
7660b57cec5SDimitry Andric
7670b57cec5SDimitry Andric // "platform get-file remote-file-path host-file-path"
7680b57cec5SDimitry Andric class CommandObjectPlatformGetFile : public CommandObjectParsed {
7690b57cec5SDimitry Andric public:
CommandObjectPlatformGetFile(CommandInterpreter & interpreter)7700b57cec5SDimitry Andric CommandObjectPlatformGetFile(CommandInterpreter &interpreter)
7710b57cec5SDimitry Andric : CommandObjectParsed(
7720b57cec5SDimitry Andric interpreter, "platform get-file",
7730b57cec5SDimitry Andric "Transfer a file from the remote end to the local host.",
7740b57cec5SDimitry Andric "platform get-file <remote-file-spec> <local-file-spec>", 0) {
7750b57cec5SDimitry Andric SetHelpLong(
7760b57cec5SDimitry Andric R"(Examples:
7770b57cec5SDimitry Andric
7780b57cec5SDimitry Andric (lldb) platform get-file /the/remote/file/path /the/local/file/path
7790b57cec5SDimitry Andric
7800b57cec5SDimitry Andric Transfer a file from the remote end with file path /the/remote/file/path to the local host.)");
7810b57cec5SDimitry Andric
7820b57cec5SDimitry Andric CommandArgumentEntry arg1, arg2;
7830b57cec5SDimitry Andric CommandArgumentData file_arg_remote, file_arg_host;
7840b57cec5SDimitry Andric
7850b57cec5SDimitry Andric // Define the first (and only) variant of this arg.
7860b57cec5SDimitry Andric file_arg_remote.arg_type = eArgTypeFilename;
7870b57cec5SDimitry Andric file_arg_remote.arg_repetition = eArgRepeatPlain;
7880b57cec5SDimitry Andric // There is only one variant this argument could be; put it into the
7890b57cec5SDimitry Andric // argument entry.
7900b57cec5SDimitry Andric arg1.push_back(file_arg_remote);
7910b57cec5SDimitry Andric
7920b57cec5SDimitry Andric // Define the second (and only) variant of this arg.
7930b57cec5SDimitry Andric file_arg_host.arg_type = eArgTypeFilename;
7940b57cec5SDimitry Andric file_arg_host.arg_repetition = eArgRepeatPlain;
7950b57cec5SDimitry Andric // There is only one variant this argument could be; put it into the
7960b57cec5SDimitry Andric // argument entry.
7970b57cec5SDimitry Andric arg2.push_back(file_arg_host);
7980b57cec5SDimitry Andric
7990b57cec5SDimitry Andric // Push the data for the first and the second arguments into the
8000b57cec5SDimitry Andric // m_arguments vector.
8010b57cec5SDimitry Andric m_arguments.push_back(arg1);
8020b57cec5SDimitry Andric m_arguments.push_back(arg2);
8030b57cec5SDimitry Andric }
8040b57cec5SDimitry Andric
8050b57cec5SDimitry Andric ~CommandObjectPlatformGetFile() override = default;
8060b57cec5SDimitry Andric
807af732203SDimitry Andric void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)808af732203SDimitry Andric HandleArgumentCompletion(CompletionRequest &request,
809af732203SDimitry Andric OptionElementVector &opt_element_vector) override {
810af732203SDimitry Andric if (request.GetCursorIndex() == 0)
811af732203SDimitry Andric CommandCompletions::InvokeCommonCompletionCallbacks(
812af732203SDimitry Andric GetCommandInterpreter(),
813af732203SDimitry Andric CommandCompletions::eRemoteDiskFileCompletion, request, nullptr);
814af732203SDimitry Andric else if (request.GetCursorIndex() == 1)
815af732203SDimitry Andric CommandCompletions::InvokeCommonCompletionCallbacks(
816af732203SDimitry Andric GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
817af732203SDimitry Andric request, nullptr);
818af732203SDimitry Andric }
819af732203SDimitry Andric
DoExecute(Args & args,CommandReturnObject & result)8200b57cec5SDimitry Andric bool DoExecute(Args &args, CommandReturnObject &result) override {
8210b57cec5SDimitry Andric // If the number of arguments is incorrect, issue an error message.
8220b57cec5SDimitry Andric if (args.GetArgumentCount() != 2) {
823*5f7ddb14SDimitry Andric result.AppendError("required arguments missing; specify both the "
824*5f7ddb14SDimitry Andric "source and destination file paths");
8250b57cec5SDimitry Andric return false;
8260b57cec5SDimitry Andric }
8270b57cec5SDimitry Andric
8280b57cec5SDimitry Andric PlatformSP platform_sp(
8290b57cec5SDimitry Andric GetDebugger().GetPlatformList().GetSelectedPlatform());
8300b57cec5SDimitry Andric if (platform_sp) {
8310b57cec5SDimitry Andric const char *remote_file_path = args.GetArgumentAtIndex(0);
8320b57cec5SDimitry Andric const char *local_file_path = args.GetArgumentAtIndex(1);
8330b57cec5SDimitry Andric Status error = platform_sp->GetFile(FileSpec(remote_file_path),
8340b57cec5SDimitry Andric FileSpec(local_file_path));
8350b57cec5SDimitry Andric if (error.Success()) {
8360b57cec5SDimitry Andric result.AppendMessageWithFormat(
8370b57cec5SDimitry Andric "successfully get-file from %s (remote) to %s (host)\n",
8380b57cec5SDimitry Andric remote_file_path, local_file_path);
8390b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult);
8400b57cec5SDimitry Andric } else {
8410b57cec5SDimitry Andric result.AppendMessageWithFormat("get-file failed: %s\n",
8420b57cec5SDimitry Andric error.AsCString());
8430b57cec5SDimitry Andric }
8440b57cec5SDimitry Andric } else {
8450b57cec5SDimitry Andric result.AppendError("no platform currently selected\n");
8460b57cec5SDimitry Andric }
8470b57cec5SDimitry Andric return result.Succeeded();
8480b57cec5SDimitry Andric }
8490b57cec5SDimitry Andric };
8500b57cec5SDimitry Andric
8510b57cec5SDimitry Andric // "platform get-size remote-file-path"
8520b57cec5SDimitry Andric class CommandObjectPlatformGetSize : public CommandObjectParsed {
8530b57cec5SDimitry Andric public:
CommandObjectPlatformGetSize(CommandInterpreter & interpreter)8540b57cec5SDimitry Andric CommandObjectPlatformGetSize(CommandInterpreter &interpreter)
8550b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "platform get-size",
8560b57cec5SDimitry Andric "Get the file size from the remote end.",
8570b57cec5SDimitry Andric "platform get-size <remote-file-spec>", 0) {
8580b57cec5SDimitry Andric SetHelpLong(
8590b57cec5SDimitry Andric R"(Examples:
8600b57cec5SDimitry Andric
8610b57cec5SDimitry Andric (lldb) platform get-size /the/remote/file/path
8620b57cec5SDimitry Andric
8630b57cec5SDimitry Andric Get the file size from the remote end with path /the/remote/file/path.)");
8640b57cec5SDimitry Andric
8650b57cec5SDimitry Andric CommandArgumentEntry arg1;
8660b57cec5SDimitry Andric CommandArgumentData file_arg_remote;
8670b57cec5SDimitry Andric
8680b57cec5SDimitry Andric // Define the first (and only) variant of this arg.
8690b57cec5SDimitry Andric file_arg_remote.arg_type = eArgTypeFilename;
8700b57cec5SDimitry Andric file_arg_remote.arg_repetition = eArgRepeatPlain;
8710b57cec5SDimitry Andric // There is only one variant this argument could be; put it into the
8720b57cec5SDimitry Andric // argument entry.
8730b57cec5SDimitry Andric arg1.push_back(file_arg_remote);
8740b57cec5SDimitry Andric
8750b57cec5SDimitry Andric // Push the data for the first argument into the m_arguments vector.
8760b57cec5SDimitry Andric m_arguments.push_back(arg1);
8770b57cec5SDimitry Andric }
8780b57cec5SDimitry Andric
8790b57cec5SDimitry Andric ~CommandObjectPlatformGetSize() override = default;
8800b57cec5SDimitry Andric
881af732203SDimitry Andric void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)882af732203SDimitry Andric HandleArgumentCompletion(CompletionRequest &request,
883af732203SDimitry Andric OptionElementVector &opt_element_vector) override {
884af732203SDimitry Andric if (request.GetCursorIndex() != 0)
885af732203SDimitry Andric return;
886af732203SDimitry Andric
887af732203SDimitry Andric CommandCompletions::InvokeCommonCompletionCallbacks(
888af732203SDimitry Andric GetCommandInterpreter(), CommandCompletions::eRemoteDiskFileCompletion,
889af732203SDimitry Andric request, nullptr);
890af732203SDimitry Andric }
891af732203SDimitry Andric
DoExecute(Args & args,CommandReturnObject & result)8920b57cec5SDimitry Andric bool DoExecute(Args &args, CommandReturnObject &result) override {
8930b57cec5SDimitry Andric // If the number of arguments is incorrect, issue an error message.
8940b57cec5SDimitry Andric if (args.GetArgumentCount() != 1) {
895*5f7ddb14SDimitry Andric result.AppendError("required argument missing; specify the source file "
896*5f7ddb14SDimitry Andric "path as the only argument");
8970b57cec5SDimitry Andric return false;
8980b57cec5SDimitry Andric }
8990b57cec5SDimitry Andric
9000b57cec5SDimitry Andric PlatformSP platform_sp(
9010b57cec5SDimitry Andric GetDebugger().GetPlatformList().GetSelectedPlatform());
9020b57cec5SDimitry Andric if (platform_sp) {
9030b57cec5SDimitry Andric std::string remote_file_path(args.GetArgumentAtIndex(0));
9040b57cec5SDimitry Andric user_id_t size = platform_sp->GetFileSize(FileSpec(remote_file_path));
9050b57cec5SDimitry Andric if (size != UINT64_MAX) {
9060b57cec5SDimitry Andric result.AppendMessageWithFormat("File size of %s (remote): %" PRIu64
9070b57cec5SDimitry Andric "\n",
9080b57cec5SDimitry Andric remote_file_path.c_str(), size);
9090b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult);
9100b57cec5SDimitry Andric } else {
9110b57cec5SDimitry Andric result.AppendMessageWithFormat(
9120b57cec5SDimitry Andric "Error getting file size of %s (remote)\n",
9130b57cec5SDimitry Andric remote_file_path.c_str());
9140b57cec5SDimitry Andric }
9150b57cec5SDimitry Andric } else {
9160b57cec5SDimitry Andric result.AppendError("no platform currently selected\n");
9170b57cec5SDimitry Andric }
9180b57cec5SDimitry Andric return result.Succeeded();
9190b57cec5SDimitry Andric }
9200b57cec5SDimitry Andric };
9210b57cec5SDimitry Andric
9220b57cec5SDimitry Andric // "platform put-file"
9230b57cec5SDimitry Andric class CommandObjectPlatformPutFile : public CommandObjectParsed {
9240b57cec5SDimitry Andric public:
CommandObjectPlatformPutFile(CommandInterpreter & interpreter)9250b57cec5SDimitry Andric CommandObjectPlatformPutFile(CommandInterpreter &interpreter)
9260b57cec5SDimitry Andric : CommandObjectParsed(
9270b57cec5SDimitry Andric interpreter, "platform put-file",
9280b57cec5SDimitry Andric "Transfer a file from this system to the remote end.", nullptr, 0) {
9290b57cec5SDimitry Andric }
9300b57cec5SDimitry Andric
9310b57cec5SDimitry Andric ~CommandObjectPlatformPutFile() override = default;
9320b57cec5SDimitry Andric
933af732203SDimitry Andric void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)934af732203SDimitry Andric HandleArgumentCompletion(CompletionRequest &request,
935af732203SDimitry Andric OptionElementVector &opt_element_vector) override {
936af732203SDimitry Andric if (request.GetCursorIndex() == 0)
937af732203SDimitry Andric CommandCompletions::InvokeCommonCompletionCallbacks(
938af732203SDimitry Andric GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
939af732203SDimitry Andric request, nullptr);
940af732203SDimitry Andric else if (request.GetCursorIndex() == 1)
941af732203SDimitry Andric CommandCompletions::InvokeCommonCompletionCallbacks(
942af732203SDimitry Andric GetCommandInterpreter(),
943af732203SDimitry Andric CommandCompletions::eRemoteDiskFileCompletion, request, nullptr);
944af732203SDimitry Andric }
945af732203SDimitry Andric
DoExecute(Args & args,CommandReturnObject & result)9460b57cec5SDimitry Andric bool DoExecute(Args &args, CommandReturnObject &result) override {
9470b57cec5SDimitry Andric const char *src = args.GetArgumentAtIndex(0);
9480b57cec5SDimitry Andric const char *dst = args.GetArgumentAtIndex(1);
9490b57cec5SDimitry Andric
9500b57cec5SDimitry Andric FileSpec src_fs(src);
9510b57cec5SDimitry Andric FileSystem::Instance().Resolve(src_fs);
9520b57cec5SDimitry Andric FileSpec dst_fs(dst ? dst : src_fs.GetFilename().GetCString());
9530b57cec5SDimitry Andric
9540b57cec5SDimitry Andric PlatformSP platform_sp(
9550b57cec5SDimitry Andric GetDebugger().GetPlatformList().GetSelectedPlatform());
9560b57cec5SDimitry Andric if (platform_sp) {
9570b57cec5SDimitry Andric Status error(platform_sp->PutFile(src_fs, dst_fs));
9580b57cec5SDimitry Andric if (error.Success()) {
9590b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult);
9600b57cec5SDimitry Andric } else {
9610b57cec5SDimitry Andric result.AppendError(error.AsCString());
9620b57cec5SDimitry Andric }
9630b57cec5SDimitry Andric } else {
9640b57cec5SDimitry Andric result.AppendError("no platform currently selected\n");
9650b57cec5SDimitry Andric }
9660b57cec5SDimitry Andric return result.Succeeded();
9670b57cec5SDimitry Andric }
9680b57cec5SDimitry Andric };
9690b57cec5SDimitry Andric
9700b57cec5SDimitry Andric // "platform process launch"
9710b57cec5SDimitry Andric class CommandObjectPlatformProcessLaunch : public CommandObjectParsed {
9720b57cec5SDimitry Andric public:
CommandObjectPlatformProcessLaunch(CommandInterpreter & interpreter)9730b57cec5SDimitry Andric CommandObjectPlatformProcessLaunch(CommandInterpreter &interpreter)
9740b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "platform process launch",
9750b57cec5SDimitry Andric "Launch a new process on a remote platform.",
9760b57cec5SDimitry Andric "platform process launch program",
9770b57cec5SDimitry Andric eCommandRequiresTarget | eCommandTryTargetAPILock),
978*5f7ddb14SDimitry Andric m_options(), m_all_options() {
979*5f7ddb14SDimitry Andric m_all_options.Append(&m_options);
980*5f7ddb14SDimitry Andric m_all_options.Finalize();
981*5f7ddb14SDimitry Andric }
9820b57cec5SDimitry Andric
9830b57cec5SDimitry Andric ~CommandObjectPlatformProcessLaunch() override = default;
9840b57cec5SDimitry Andric
GetOptions()985*5f7ddb14SDimitry Andric Options *GetOptions() override { return &m_all_options; }
9860b57cec5SDimitry Andric
9870b57cec5SDimitry Andric protected:
DoExecute(Args & args,CommandReturnObject & result)9880b57cec5SDimitry Andric bool DoExecute(Args &args, CommandReturnObject &result) override {
9890b57cec5SDimitry Andric Target *target = GetDebugger().GetSelectedTarget().get();
9900b57cec5SDimitry Andric PlatformSP platform_sp;
9910b57cec5SDimitry Andric if (target) {
9920b57cec5SDimitry Andric platform_sp = target->GetPlatform();
9930b57cec5SDimitry Andric }
9940b57cec5SDimitry Andric if (!platform_sp) {
9950b57cec5SDimitry Andric platform_sp = GetDebugger().GetPlatformList().GetSelectedPlatform();
9960b57cec5SDimitry Andric }
9970b57cec5SDimitry Andric
9980b57cec5SDimitry Andric if (platform_sp) {
9990b57cec5SDimitry Andric Status error;
10000b57cec5SDimitry Andric const size_t argc = args.GetArgumentCount();
10010b57cec5SDimitry Andric Target *target = m_exe_ctx.GetTargetPtr();
10020b57cec5SDimitry Andric Module *exe_module = target->GetExecutableModulePointer();
10030b57cec5SDimitry Andric if (exe_module) {
10040b57cec5SDimitry Andric m_options.launch_info.GetExecutableFile() = exe_module->GetFileSpec();
10050b57cec5SDimitry Andric llvm::SmallString<128> exe_path;
10060b57cec5SDimitry Andric m_options.launch_info.GetExecutableFile().GetPath(exe_path);
10070b57cec5SDimitry Andric if (!exe_path.empty())
10080b57cec5SDimitry Andric m_options.launch_info.GetArguments().AppendArgument(exe_path);
10090b57cec5SDimitry Andric m_options.launch_info.GetArchitecture() = exe_module->GetArchitecture();
10100b57cec5SDimitry Andric }
10110b57cec5SDimitry Andric
10120b57cec5SDimitry Andric if (argc > 0) {
10130b57cec5SDimitry Andric if (m_options.launch_info.GetExecutableFile()) {
10140b57cec5SDimitry Andric // We already have an executable file, so we will use this and all
10150b57cec5SDimitry Andric // arguments to this function are extra arguments
10160b57cec5SDimitry Andric m_options.launch_info.GetArguments().AppendArguments(args);
10170b57cec5SDimitry Andric } else {
10180b57cec5SDimitry Andric // We don't have any file yet, so the first argument is our
10190b57cec5SDimitry Andric // executable, and the rest are program arguments
10200b57cec5SDimitry Andric const bool first_arg_is_executable = true;
10210b57cec5SDimitry Andric m_options.launch_info.SetArguments(args, first_arg_is_executable);
10220b57cec5SDimitry Andric }
10230b57cec5SDimitry Andric }
10240b57cec5SDimitry Andric
10250b57cec5SDimitry Andric if (m_options.launch_info.GetExecutableFile()) {
10260b57cec5SDimitry Andric Debugger &debugger = GetDebugger();
10270b57cec5SDimitry Andric
10280b57cec5SDimitry Andric if (argc == 0)
10290b57cec5SDimitry Andric target->GetRunArguments(m_options.launch_info.GetArguments());
10300b57cec5SDimitry Andric
10310b57cec5SDimitry Andric ProcessSP process_sp(platform_sp->DebugProcess(
10320b57cec5SDimitry Andric m_options.launch_info, debugger, target, error));
10330b57cec5SDimitry Andric if (process_sp && process_sp->IsAlive()) {
10340b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult);
10350b57cec5SDimitry Andric return true;
10360b57cec5SDimitry Andric }
10370b57cec5SDimitry Andric
10380b57cec5SDimitry Andric if (error.Success())
10390b57cec5SDimitry Andric result.AppendError("process launch failed");
10400b57cec5SDimitry Andric else
10410b57cec5SDimitry Andric result.AppendError(error.AsCString());
10420b57cec5SDimitry Andric } else {
10430b57cec5SDimitry Andric result.AppendError("'platform process launch' uses the current target "
10440b57cec5SDimitry Andric "file and arguments, or the executable and its "
10450b57cec5SDimitry Andric "arguments can be specified in this command");
10460b57cec5SDimitry Andric return false;
10470b57cec5SDimitry Andric }
10480b57cec5SDimitry Andric } else {
10490b57cec5SDimitry Andric result.AppendError("no platform is selected\n");
10500b57cec5SDimitry Andric }
10510b57cec5SDimitry Andric return result.Succeeded();
10520b57cec5SDimitry Andric }
10530b57cec5SDimitry Andric
1054af732203SDimitry Andric CommandOptionsProcessLaunch m_options;
1055*5f7ddb14SDimitry Andric OptionGroupOptions m_all_options;
10560b57cec5SDimitry Andric };
10570b57cec5SDimitry Andric
10580b57cec5SDimitry Andric // "platform process list"
10590b57cec5SDimitry Andric
10609dba64beSDimitry Andric static PosixPlatformCommandOptionValidator posix_validator;
10619dba64beSDimitry Andric #define LLDB_OPTIONS_platform_process_list
10629dba64beSDimitry Andric #include "CommandOptions.inc"
10630b57cec5SDimitry Andric
10640b57cec5SDimitry Andric class CommandObjectPlatformProcessList : public CommandObjectParsed {
10650b57cec5SDimitry Andric public:
CommandObjectPlatformProcessList(CommandInterpreter & interpreter)10660b57cec5SDimitry Andric CommandObjectPlatformProcessList(CommandInterpreter &interpreter)
10670b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "platform process list",
10680b57cec5SDimitry Andric "List processes on a remote platform by name, pid, "
10690b57cec5SDimitry Andric "or many other matching attributes.",
10700b57cec5SDimitry Andric "platform process list", 0),
10710b57cec5SDimitry Andric m_options() {}
10720b57cec5SDimitry Andric
10730b57cec5SDimitry Andric ~CommandObjectPlatformProcessList() override = default;
10740b57cec5SDimitry Andric
GetOptions()10750b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; }
10760b57cec5SDimitry Andric
10770b57cec5SDimitry Andric protected:
DoExecute(Args & args,CommandReturnObject & result)10780b57cec5SDimitry Andric bool DoExecute(Args &args, CommandReturnObject &result) override {
10790b57cec5SDimitry Andric Target *target = GetDebugger().GetSelectedTarget().get();
10800b57cec5SDimitry Andric PlatformSP platform_sp;
10810b57cec5SDimitry Andric if (target) {
10820b57cec5SDimitry Andric platform_sp = target->GetPlatform();
10830b57cec5SDimitry Andric }
10840b57cec5SDimitry Andric if (!platform_sp) {
10850b57cec5SDimitry Andric platform_sp = GetDebugger().GetPlatformList().GetSelectedPlatform();
10860b57cec5SDimitry Andric }
10870b57cec5SDimitry Andric
10880b57cec5SDimitry Andric if (platform_sp) {
10890b57cec5SDimitry Andric Status error;
10900b57cec5SDimitry Andric if (args.GetArgumentCount() == 0) {
10910b57cec5SDimitry Andric if (platform_sp) {
10920b57cec5SDimitry Andric Stream &ostrm = result.GetOutputStream();
10930b57cec5SDimitry Andric
10940b57cec5SDimitry Andric lldb::pid_t pid =
10950b57cec5SDimitry Andric m_options.match_info.GetProcessInfo().GetProcessID();
10960b57cec5SDimitry Andric if (pid != LLDB_INVALID_PROCESS_ID) {
10970b57cec5SDimitry Andric ProcessInstanceInfo proc_info;
10980b57cec5SDimitry Andric if (platform_sp->GetProcessInfo(pid, proc_info)) {
10990b57cec5SDimitry Andric ProcessInstanceInfo::DumpTableHeader(ostrm, m_options.show_args,
11000b57cec5SDimitry Andric m_options.verbose);
11010b57cec5SDimitry Andric proc_info.DumpAsTableRow(ostrm, platform_sp->GetUserIDResolver(),
11020b57cec5SDimitry Andric m_options.show_args, m_options.verbose);
11030b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult);
11040b57cec5SDimitry Andric } else {
11050b57cec5SDimitry Andric result.AppendErrorWithFormat(
11060b57cec5SDimitry Andric "no process found with pid = %" PRIu64 "\n", pid);
11070b57cec5SDimitry Andric }
11080b57cec5SDimitry Andric } else {
11090b57cec5SDimitry Andric ProcessInstanceInfoList proc_infos;
11100b57cec5SDimitry Andric const uint32_t matches =
11110b57cec5SDimitry Andric platform_sp->FindProcesses(m_options.match_info, proc_infos);
11120b57cec5SDimitry Andric const char *match_desc = nullptr;
11130b57cec5SDimitry Andric const char *match_name =
11140b57cec5SDimitry Andric m_options.match_info.GetProcessInfo().GetName();
11150b57cec5SDimitry Andric if (match_name && match_name[0]) {
11160b57cec5SDimitry Andric switch (m_options.match_info.GetNameMatchType()) {
11170b57cec5SDimitry Andric case NameMatch::Ignore:
11180b57cec5SDimitry Andric break;
11190b57cec5SDimitry Andric case NameMatch::Equals:
11200b57cec5SDimitry Andric match_desc = "matched";
11210b57cec5SDimitry Andric break;
11220b57cec5SDimitry Andric case NameMatch::Contains:
11230b57cec5SDimitry Andric match_desc = "contained";
11240b57cec5SDimitry Andric break;
11250b57cec5SDimitry Andric case NameMatch::StartsWith:
11260b57cec5SDimitry Andric match_desc = "started with";
11270b57cec5SDimitry Andric break;
11280b57cec5SDimitry Andric case NameMatch::EndsWith:
11290b57cec5SDimitry Andric match_desc = "ended with";
11300b57cec5SDimitry Andric break;
11310b57cec5SDimitry Andric case NameMatch::RegularExpression:
11320b57cec5SDimitry Andric match_desc = "matched the regular expression";
11330b57cec5SDimitry Andric break;
11340b57cec5SDimitry Andric }
11350b57cec5SDimitry Andric }
11360b57cec5SDimitry Andric
11370b57cec5SDimitry Andric if (matches == 0) {
11380b57cec5SDimitry Andric if (match_desc)
11390b57cec5SDimitry Andric result.AppendErrorWithFormat(
11400b57cec5SDimitry Andric "no processes were found that %s \"%s\" on the \"%s\" "
11410b57cec5SDimitry Andric "platform\n",
11420b57cec5SDimitry Andric match_desc, match_name,
11430b57cec5SDimitry Andric platform_sp->GetPluginName().GetCString());
11440b57cec5SDimitry Andric else
11450b57cec5SDimitry Andric result.AppendErrorWithFormat(
11460b57cec5SDimitry Andric "no processes were found on the \"%s\" platform\n",
11470b57cec5SDimitry Andric platform_sp->GetPluginName().GetCString());
11480b57cec5SDimitry Andric } else {
11490b57cec5SDimitry Andric result.AppendMessageWithFormat(
11500b57cec5SDimitry Andric "%u matching process%s found on \"%s\"", matches,
11510b57cec5SDimitry Andric matches > 1 ? "es were" : " was",
11520b57cec5SDimitry Andric platform_sp->GetName().GetCString());
11530b57cec5SDimitry Andric if (match_desc)
11540b57cec5SDimitry Andric result.AppendMessageWithFormat(" whose name %s \"%s\"",
11550b57cec5SDimitry Andric match_desc, match_name);
11560b57cec5SDimitry Andric result.AppendMessageWithFormat("\n");
11570b57cec5SDimitry Andric ProcessInstanceInfo::DumpTableHeader(ostrm, m_options.show_args,
11580b57cec5SDimitry Andric m_options.verbose);
11590b57cec5SDimitry Andric for (uint32_t i = 0; i < matches; ++i) {
11605ffd83dbSDimitry Andric proc_infos[i].DumpAsTableRow(
11610b57cec5SDimitry Andric ostrm, platform_sp->GetUserIDResolver(),
11620b57cec5SDimitry Andric m_options.show_args, m_options.verbose);
11630b57cec5SDimitry Andric }
11640b57cec5SDimitry Andric }
11650b57cec5SDimitry Andric }
11660b57cec5SDimitry Andric }
11670b57cec5SDimitry Andric } else {
11680b57cec5SDimitry Andric result.AppendError("invalid args: process list takes only options\n");
11690b57cec5SDimitry Andric }
11700b57cec5SDimitry Andric } else {
11710b57cec5SDimitry Andric result.AppendError("no platform is selected\n");
11720b57cec5SDimitry Andric }
11730b57cec5SDimitry Andric return result.Succeeded();
11740b57cec5SDimitry Andric }
11750b57cec5SDimitry Andric
11760b57cec5SDimitry Andric class CommandOptions : public Options {
11770b57cec5SDimitry Andric public:
CommandOptions()1178*5f7ddb14SDimitry Andric CommandOptions() : Options(), match_info() {}
11790b57cec5SDimitry Andric
11800b57cec5SDimitry Andric ~CommandOptions() override = default;
11810b57cec5SDimitry Andric
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)11820b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
11830b57cec5SDimitry Andric ExecutionContext *execution_context) override {
11840b57cec5SDimitry Andric Status error;
11850b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val;
11860b57cec5SDimitry Andric bool success = false;
11870b57cec5SDimitry Andric
11880b57cec5SDimitry Andric uint32_t id = LLDB_INVALID_PROCESS_ID;
11890b57cec5SDimitry Andric success = !option_arg.getAsInteger(0, id);
11900b57cec5SDimitry Andric switch (short_option) {
11910b57cec5SDimitry Andric case 'p': {
11920b57cec5SDimitry Andric match_info.GetProcessInfo().SetProcessID(id);
11930b57cec5SDimitry Andric if (!success)
11940b57cec5SDimitry Andric error.SetErrorStringWithFormat("invalid process ID string: '%s'",
11950b57cec5SDimitry Andric option_arg.str().c_str());
11960b57cec5SDimitry Andric break;
11970b57cec5SDimitry Andric }
11980b57cec5SDimitry Andric case 'P':
11990b57cec5SDimitry Andric match_info.GetProcessInfo().SetParentProcessID(id);
12000b57cec5SDimitry Andric if (!success)
12010b57cec5SDimitry Andric error.SetErrorStringWithFormat(
12020b57cec5SDimitry Andric "invalid parent process ID string: '%s'",
12030b57cec5SDimitry Andric option_arg.str().c_str());
12040b57cec5SDimitry Andric break;
12050b57cec5SDimitry Andric
12060b57cec5SDimitry Andric case 'u':
12070b57cec5SDimitry Andric match_info.GetProcessInfo().SetUserID(success ? id : UINT32_MAX);
12080b57cec5SDimitry Andric if (!success)
12090b57cec5SDimitry Andric error.SetErrorStringWithFormat("invalid user ID string: '%s'",
12100b57cec5SDimitry Andric option_arg.str().c_str());
12110b57cec5SDimitry Andric break;
12120b57cec5SDimitry Andric
12130b57cec5SDimitry Andric case 'U':
12140b57cec5SDimitry Andric match_info.GetProcessInfo().SetEffectiveUserID(success ? id
12150b57cec5SDimitry Andric : UINT32_MAX);
12160b57cec5SDimitry Andric if (!success)
12170b57cec5SDimitry Andric error.SetErrorStringWithFormat(
12180b57cec5SDimitry Andric "invalid effective user ID string: '%s'",
12190b57cec5SDimitry Andric option_arg.str().c_str());
12200b57cec5SDimitry Andric break;
12210b57cec5SDimitry Andric
12220b57cec5SDimitry Andric case 'g':
12230b57cec5SDimitry Andric match_info.GetProcessInfo().SetGroupID(success ? id : UINT32_MAX);
12240b57cec5SDimitry Andric if (!success)
12250b57cec5SDimitry Andric error.SetErrorStringWithFormat("invalid group ID string: '%s'",
12260b57cec5SDimitry Andric option_arg.str().c_str());
12270b57cec5SDimitry Andric break;
12280b57cec5SDimitry Andric
12290b57cec5SDimitry Andric case 'G':
12300b57cec5SDimitry Andric match_info.GetProcessInfo().SetEffectiveGroupID(success ? id
12310b57cec5SDimitry Andric : UINT32_MAX);
12320b57cec5SDimitry Andric if (!success)
12330b57cec5SDimitry Andric error.SetErrorStringWithFormat(
12340b57cec5SDimitry Andric "invalid effective group ID string: '%s'",
12350b57cec5SDimitry Andric option_arg.str().c_str());
12360b57cec5SDimitry Andric break;
12370b57cec5SDimitry Andric
12380b57cec5SDimitry Andric case 'a': {
12390b57cec5SDimitry Andric TargetSP target_sp =
12400b57cec5SDimitry Andric execution_context ? execution_context->GetTargetSP() : TargetSP();
12410b57cec5SDimitry Andric DebuggerSP debugger_sp =
12420b57cec5SDimitry Andric target_sp ? target_sp->GetDebugger().shared_from_this()
12430b57cec5SDimitry Andric : DebuggerSP();
12440b57cec5SDimitry Andric PlatformSP platform_sp =
12450b57cec5SDimitry Andric debugger_sp ? debugger_sp->GetPlatformList().GetSelectedPlatform()
12460b57cec5SDimitry Andric : PlatformSP();
12470b57cec5SDimitry Andric match_info.GetProcessInfo().GetArchitecture() =
12480b57cec5SDimitry Andric Platform::GetAugmentedArchSpec(platform_sp.get(), option_arg);
12490b57cec5SDimitry Andric } break;
12500b57cec5SDimitry Andric
12510b57cec5SDimitry Andric case 'n':
12520b57cec5SDimitry Andric match_info.GetProcessInfo().GetExecutableFile().SetFile(
12530b57cec5SDimitry Andric option_arg, FileSpec::Style::native);
12540b57cec5SDimitry Andric match_info.SetNameMatchType(NameMatch::Equals);
12550b57cec5SDimitry Andric break;
12560b57cec5SDimitry Andric
12570b57cec5SDimitry Andric case 'e':
12580b57cec5SDimitry Andric match_info.GetProcessInfo().GetExecutableFile().SetFile(
12590b57cec5SDimitry Andric option_arg, FileSpec::Style::native);
12600b57cec5SDimitry Andric match_info.SetNameMatchType(NameMatch::EndsWith);
12610b57cec5SDimitry Andric break;
12620b57cec5SDimitry Andric
12630b57cec5SDimitry Andric case 's':
12640b57cec5SDimitry Andric match_info.GetProcessInfo().GetExecutableFile().SetFile(
12650b57cec5SDimitry Andric option_arg, FileSpec::Style::native);
12660b57cec5SDimitry Andric match_info.SetNameMatchType(NameMatch::StartsWith);
12670b57cec5SDimitry Andric break;
12680b57cec5SDimitry Andric
12690b57cec5SDimitry Andric case 'c':
12700b57cec5SDimitry Andric match_info.GetProcessInfo().GetExecutableFile().SetFile(
12710b57cec5SDimitry Andric option_arg, FileSpec::Style::native);
12720b57cec5SDimitry Andric match_info.SetNameMatchType(NameMatch::Contains);
12730b57cec5SDimitry Andric break;
12740b57cec5SDimitry Andric
12750b57cec5SDimitry Andric case 'r':
12760b57cec5SDimitry Andric match_info.GetProcessInfo().GetExecutableFile().SetFile(
12770b57cec5SDimitry Andric option_arg, FileSpec::Style::native);
12780b57cec5SDimitry Andric match_info.SetNameMatchType(NameMatch::RegularExpression);
12790b57cec5SDimitry Andric break;
12800b57cec5SDimitry Andric
12810b57cec5SDimitry Andric case 'A':
12820b57cec5SDimitry Andric show_args = true;
12830b57cec5SDimitry Andric break;
12840b57cec5SDimitry Andric
12850b57cec5SDimitry Andric case 'v':
12860b57cec5SDimitry Andric verbose = true;
12870b57cec5SDimitry Andric break;
12880b57cec5SDimitry Andric
12899dba64beSDimitry Andric case 'x':
12909dba64beSDimitry Andric match_info.SetMatchAllUsers(true);
12910b57cec5SDimitry Andric break;
12929dba64beSDimitry Andric
12939dba64beSDimitry Andric default:
12949dba64beSDimitry Andric llvm_unreachable("Unimplemented option");
12950b57cec5SDimitry Andric }
12960b57cec5SDimitry Andric
12970b57cec5SDimitry Andric return error;
12980b57cec5SDimitry Andric }
12990b57cec5SDimitry Andric
OptionParsingStarting(ExecutionContext * execution_context)13000b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
13010b57cec5SDimitry Andric match_info.Clear();
13020b57cec5SDimitry Andric show_args = false;
13030b57cec5SDimitry Andric verbose = false;
13040b57cec5SDimitry Andric }
13050b57cec5SDimitry Andric
GetDefinitions()13060b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
13070b57cec5SDimitry Andric return llvm::makeArrayRef(g_platform_process_list_options);
13080b57cec5SDimitry Andric }
13090b57cec5SDimitry Andric
13100b57cec5SDimitry Andric // Instance variables to hold the values for command options.
13110b57cec5SDimitry Andric
13120b57cec5SDimitry Andric ProcessInstanceInfoMatch match_info;
1313*5f7ddb14SDimitry Andric bool show_args = false;
1314*5f7ddb14SDimitry Andric bool verbose = false;
13150b57cec5SDimitry Andric };
13160b57cec5SDimitry Andric
13170b57cec5SDimitry Andric CommandOptions m_options;
13180b57cec5SDimitry Andric };
13190b57cec5SDimitry Andric
13200b57cec5SDimitry Andric // "platform process info"
13210b57cec5SDimitry Andric class CommandObjectPlatformProcessInfo : public CommandObjectParsed {
13220b57cec5SDimitry Andric public:
CommandObjectPlatformProcessInfo(CommandInterpreter & interpreter)13230b57cec5SDimitry Andric CommandObjectPlatformProcessInfo(CommandInterpreter &interpreter)
13240b57cec5SDimitry Andric : CommandObjectParsed(
13250b57cec5SDimitry Andric interpreter, "platform process info",
13260b57cec5SDimitry Andric "Get detailed information for one or more process by process ID.",
13270b57cec5SDimitry Andric "platform process info <pid> [<pid> <pid> ...]", 0) {
13280b57cec5SDimitry Andric CommandArgumentEntry arg;
13290b57cec5SDimitry Andric CommandArgumentData pid_args;
13300b57cec5SDimitry Andric
13310b57cec5SDimitry Andric // Define the first (and only) variant of this arg.
13320b57cec5SDimitry Andric pid_args.arg_type = eArgTypePid;
13330b57cec5SDimitry Andric pid_args.arg_repetition = eArgRepeatStar;
13340b57cec5SDimitry Andric
13350b57cec5SDimitry Andric // There is only one variant this argument could be; put it into the
13360b57cec5SDimitry Andric // argument entry.
13370b57cec5SDimitry Andric arg.push_back(pid_args);
13380b57cec5SDimitry Andric
13390b57cec5SDimitry Andric // Push the data for the first argument into the m_arguments vector.
13400b57cec5SDimitry Andric m_arguments.push_back(arg);
13410b57cec5SDimitry Andric }
13420b57cec5SDimitry Andric
13430b57cec5SDimitry Andric ~CommandObjectPlatformProcessInfo() override = default;
13440b57cec5SDimitry Andric
1345af732203SDimitry Andric void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)1346af732203SDimitry Andric HandleArgumentCompletion(CompletionRequest &request,
1347af732203SDimitry Andric OptionElementVector &opt_element_vector) override {
1348af732203SDimitry Andric CommandCompletions::InvokeCommonCompletionCallbacks(
1349af732203SDimitry Andric GetCommandInterpreter(), CommandCompletions::eProcessIDCompletion,
1350af732203SDimitry Andric request, nullptr);
1351af732203SDimitry Andric }
1352af732203SDimitry Andric
13530b57cec5SDimitry Andric protected:
DoExecute(Args & args,CommandReturnObject & result)13540b57cec5SDimitry Andric bool DoExecute(Args &args, CommandReturnObject &result) override {
13550b57cec5SDimitry Andric Target *target = GetDebugger().GetSelectedTarget().get();
13560b57cec5SDimitry Andric PlatformSP platform_sp;
13570b57cec5SDimitry Andric if (target) {
13580b57cec5SDimitry Andric platform_sp = target->GetPlatform();
13590b57cec5SDimitry Andric }
13600b57cec5SDimitry Andric if (!platform_sp) {
13610b57cec5SDimitry Andric platform_sp = GetDebugger().GetPlatformList().GetSelectedPlatform();
13620b57cec5SDimitry Andric }
13630b57cec5SDimitry Andric
13640b57cec5SDimitry Andric if (platform_sp) {
13650b57cec5SDimitry Andric const size_t argc = args.GetArgumentCount();
13660b57cec5SDimitry Andric if (argc > 0) {
13670b57cec5SDimitry Andric Status error;
13680b57cec5SDimitry Andric
13690b57cec5SDimitry Andric if (platform_sp->IsConnected()) {
13700b57cec5SDimitry Andric Stream &ostrm = result.GetOutputStream();
13710b57cec5SDimitry Andric for (auto &entry : args.entries()) {
13720b57cec5SDimitry Andric lldb::pid_t pid;
13739dba64beSDimitry Andric if (entry.ref().getAsInteger(0, pid)) {
13740b57cec5SDimitry Andric result.AppendErrorWithFormat("invalid process ID argument '%s'",
13759dba64beSDimitry Andric entry.ref().str().c_str());
13760b57cec5SDimitry Andric break;
13770b57cec5SDimitry Andric } else {
13780b57cec5SDimitry Andric ProcessInstanceInfo proc_info;
13790b57cec5SDimitry Andric if (platform_sp->GetProcessInfo(pid, proc_info)) {
13800b57cec5SDimitry Andric ostrm.Printf("Process information for process %" PRIu64 ":\n",
13810b57cec5SDimitry Andric pid);
13820b57cec5SDimitry Andric proc_info.Dump(ostrm, platform_sp->GetUserIDResolver());
13830b57cec5SDimitry Andric } else {
13840b57cec5SDimitry Andric ostrm.Printf("error: no process information is available for "
13850b57cec5SDimitry Andric "process %" PRIu64 "\n",
13860b57cec5SDimitry Andric pid);
13870b57cec5SDimitry Andric }
13880b57cec5SDimitry Andric ostrm.EOL();
13890b57cec5SDimitry Andric }
13900b57cec5SDimitry Andric }
13910b57cec5SDimitry Andric } else {
13920b57cec5SDimitry Andric // Not connected...
13930b57cec5SDimitry Andric result.AppendErrorWithFormat(
13940b57cec5SDimitry Andric "not connected to '%s'",
13950b57cec5SDimitry Andric platform_sp->GetPluginName().GetCString());
13960b57cec5SDimitry Andric }
13970b57cec5SDimitry Andric } else {
13980b57cec5SDimitry Andric // No args
13990b57cec5SDimitry Andric result.AppendError("one or more process id(s) must be specified");
14000b57cec5SDimitry Andric }
14010b57cec5SDimitry Andric } else {
14020b57cec5SDimitry Andric result.AppendError("no platform is currently selected");
14030b57cec5SDimitry Andric }
14040b57cec5SDimitry Andric return result.Succeeded();
14050b57cec5SDimitry Andric }
14060b57cec5SDimitry Andric };
14070b57cec5SDimitry Andric
14089dba64beSDimitry Andric #define LLDB_OPTIONS_platform_process_attach
14099dba64beSDimitry Andric #include "CommandOptions.inc"
14100b57cec5SDimitry Andric
14110b57cec5SDimitry Andric class CommandObjectPlatformProcessAttach : public CommandObjectParsed {
14120b57cec5SDimitry Andric public:
14130b57cec5SDimitry Andric class CommandOptions : public Options {
14140b57cec5SDimitry Andric public:
CommandOptions()14150b57cec5SDimitry Andric CommandOptions() : Options() {
14160b57cec5SDimitry Andric // Keep default values of all options in one place: OptionParsingStarting
14170b57cec5SDimitry Andric // ()
14180b57cec5SDimitry Andric OptionParsingStarting(nullptr);
14190b57cec5SDimitry Andric }
14200b57cec5SDimitry Andric
14210b57cec5SDimitry Andric ~CommandOptions() override = default;
14220b57cec5SDimitry Andric
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)14230b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
14240b57cec5SDimitry Andric ExecutionContext *execution_context) override {
14250b57cec5SDimitry Andric Status error;
14260b57cec5SDimitry Andric char short_option = (char)m_getopt_table[option_idx].val;
14270b57cec5SDimitry Andric switch (short_option) {
14280b57cec5SDimitry Andric case 'p': {
14290b57cec5SDimitry Andric lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
14300b57cec5SDimitry Andric if (option_arg.getAsInteger(0, pid)) {
14310b57cec5SDimitry Andric error.SetErrorStringWithFormat("invalid process ID '%s'",
14320b57cec5SDimitry Andric option_arg.str().c_str());
14330b57cec5SDimitry Andric } else {
14340b57cec5SDimitry Andric attach_info.SetProcessID(pid);
14350b57cec5SDimitry Andric }
14360b57cec5SDimitry Andric } break;
14370b57cec5SDimitry Andric
14380b57cec5SDimitry Andric case 'P':
14390b57cec5SDimitry Andric attach_info.SetProcessPluginName(option_arg);
14400b57cec5SDimitry Andric break;
14410b57cec5SDimitry Andric
14420b57cec5SDimitry Andric case 'n':
14430b57cec5SDimitry Andric attach_info.GetExecutableFile().SetFile(option_arg,
14440b57cec5SDimitry Andric FileSpec::Style::native);
14450b57cec5SDimitry Andric break;
14460b57cec5SDimitry Andric
14470b57cec5SDimitry Andric case 'w':
14480b57cec5SDimitry Andric attach_info.SetWaitForLaunch(true);
14490b57cec5SDimitry Andric break;
14500b57cec5SDimitry Andric
14510b57cec5SDimitry Andric default:
14529dba64beSDimitry Andric llvm_unreachable("Unimplemented option");
14530b57cec5SDimitry Andric }
14540b57cec5SDimitry Andric return error;
14550b57cec5SDimitry Andric }
14560b57cec5SDimitry Andric
OptionParsingStarting(ExecutionContext * execution_context)14570b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
14580b57cec5SDimitry Andric attach_info.Clear();
14590b57cec5SDimitry Andric }
14600b57cec5SDimitry Andric
GetDefinitions()14610b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
14620b57cec5SDimitry Andric return llvm::makeArrayRef(g_platform_process_attach_options);
14630b57cec5SDimitry Andric }
14640b57cec5SDimitry Andric
14650b57cec5SDimitry Andric // Options table: Required for subclasses of Options.
14660b57cec5SDimitry Andric
14670b57cec5SDimitry Andric static OptionDefinition g_option_table[];
14680b57cec5SDimitry Andric
14690b57cec5SDimitry Andric // Instance variables to hold the values for command options.
14700b57cec5SDimitry Andric
14710b57cec5SDimitry Andric ProcessAttachInfo attach_info;
14720b57cec5SDimitry Andric };
14730b57cec5SDimitry Andric
CommandObjectPlatformProcessAttach(CommandInterpreter & interpreter)14740b57cec5SDimitry Andric CommandObjectPlatformProcessAttach(CommandInterpreter &interpreter)
14750b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "platform process attach",
14760b57cec5SDimitry Andric "Attach to a process.",
14770b57cec5SDimitry Andric "platform process attach <cmd-options>"),
14780b57cec5SDimitry Andric m_options() {}
14790b57cec5SDimitry Andric
14800b57cec5SDimitry Andric ~CommandObjectPlatformProcessAttach() override = default;
14810b57cec5SDimitry Andric
DoExecute(Args & command,CommandReturnObject & result)14820b57cec5SDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override {
14830b57cec5SDimitry Andric PlatformSP platform_sp(
14840b57cec5SDimitry Andric GetDebugger().GetPlatformList().GetSelectedPlatform());
14850b57cec5SDimitry Andric if (platform_sp) {
14860b57cec5SDimitry Andric Status err;
14870b57cec5SDimitry Andric ProcessSP remote_process_sp = platform_sp->Attach(
14880b57cec5SDimitry Andric m_options.attach_info, GetDebugger(), nullptr, err);
14890b57cec5SDimitry Andric if (err.Fail()) {
14900b57cec5SDimitry Andric result.AppendError(err.AsCString());
14910b57cec5SDimitry Andric } else if (!remote_process_sp) {
14920b57cec5SDimitry Andric result.AppendError("could not attach: unknown reason");
14930b57cec5SDimitry Andric } else
14940b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult);
14950b57cec5SDimitry Andric } else {
14960b57cec5SDimitry Andric result.AppendError("no platform is currently selected");
14970b57cec5SDimitry Andric }
14980b57cec5SDimitry Andric return result.Succeeded();
14990b57cec5SDimitry Andric }
15000b57cec5SDimitry Andric
GetOptions()15010b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; }
15020b57cec5SDimitry Andric
15030b57cec5SDimitry Andric protected:
15040b57cec5SDimitry Andric CommandOptions m_options;
15050b57cec5SDimitry Andric };
15060b57cec5SDimitry Andric
15070b57cec5SDimitry Andric class CommandObjectPlatformProcess : public CommandObjectMultiword {
15080b57cec5SDimitry Andric public:
15090b57cec5SDimitry Andric // Constructors and Destructors
CommandObjectPlatformProcess(CommandInterpreter & interpreter)15100b57cec5SDimitry Andric CommandObjectPlatformProcess(CommandInterpreter &interpreter)
15110b57cec5SDimitry Andric : CommandObjectMultiword(interpreter, "platform process",
15120b57cec5SDimitry Andric "Commands to query, launch and attach to "
15130b57cec5SDimitry Andric "processes on the current platform.",
15140b57cec5SDimitry Andric "platform process [attach|launch|list] ...") {
15150b57cec5SDimitry Andric LoadSubCommand(
15160b57cec5SDimitry Andric "attach",
15170b57cec5SDimitry Andric CommandObjectSP(new CommandObjectPlatformProcessAttach(interpreter)));
15180b57cec5SDimitry Andric LoadSubCommand(
15190b57cec5SDimitry Andric "launch",
15200b57cec5SDimitry Andric CommandObjectSP(new CommandObjectPlatformProcessLaunch(interpreter)));
15210b57cec5SDimitry Andric LoadSubCommand("info", CommandObjectSP(new CommandObjectPlatformProcessInfo(
15220b57cec5SDimitry Andric interpreter)));
15230b57cec5SDimitry Andric LoadSubCommand("list", CommandObjectSP(new CommandObjectPlatformProcessList(
15240b57cec5SDimitry Andric interpreter)));
15250b57cec5SDimitry Andric }
15260b57cec5SDimitry Andric
15270b57cec5SDimitry Andric ~CommandObjectPlatformProcess() override = default;
15280b57cec5SDimitry Andric
15290b57cec5SDimitry Andric private:
15300b57cec5SDimitry Andric // For CommandObjectPlatform only
15315ffd83dbSDimitry Andric CommandObjectPlatformProcess(const CommandObjectPlatformProcess &) = delete;
15325ffd83dbSDimitry Andric const CommandObjectPlatformProcess &
15335ffd83dbSDimitry Andric operator=(const CommandObjectPlatformProcess &) = delete;
15340b57cec5SDimitry Andric };
15350b57cec5SDimitry Andric
15360b57cec5SDimitry Andric // "platform shell"
15379dba64beSDimitry Andric #define LLDB_OPTIONS_platform_shell
15389dba64beSDimitry Andric #include "CommandOptions.inc"
15390b57cec5SDimitry Andric
15400b57cec5SDimitry Andric class CommandObjectPlatformShell : public CommandObjectRaw {
15410b57cec5SDimitry Andric public:
15420b57cec5SDimitry Andric class CommandOptions : public Options {
15430b57cec5SDimitry Andric public:
CommandOptions()15440b57cec5SDimitry Andric CommandOptions() : Options() {}
15450b57cec5SDimitry Andric
15460b57cec5SDimitry Andric ~CommandOptions() override = default;
15470b57cec5SDimitry Andric
GetDefinitions()15480b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
15490b57cec5SDimitry Andric return llvm::makeArrayRef(g_platform_shell_options);
15500b57cec5SDimitry Andric }
15510b57cec5SDimitry Andric
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)15520b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
15530b57cec5SDimitry Andric ExecutionContext *execution_context) override {
15540b57cec5SDimitry Andric Status error;
15550b57cec5SDimitry Andric
15560b57cec5SDimitry Andric const char short_option = (char)GetDefinitions()[option_idx].short_option;
15570b57cec5SDimitry Andric
15580b57cec5SDimitry Andric switch (short_option) {
15595ffd83dbSDimitry Andric case 'h':
15605ffd83dbSDimitry Andric m_use_host_platform = true;
15615ffd83dbSDimitry Andric break;
15620b57cec5SDimitry Andric case 't':
15630b57cec5SDimitry Andric uint32_t timeout_sec;
15640b57cec5SDimitry Andric if (option_arg.getAsInteger(10, timeout_sec))
15650b57cec5SDimitry Andric error.SetErrorStringWithFormat(
15660b57cec5SDimitry Andric "could not convert \"%s\" to a numeric value.",
15670b57cec5SDimitry Andric option_arg.str().c_str());
15680b57cec5SDimitry Andric else
15695ffd83dbSDimitry Andric m_timeout = std::chrono::seconds(timeout_sec);
15700b57cec5SDimitry Andric break;
1571af732203SDimitry Andric case 's': {
1572af732203SDimitry Andric if (option_arg.empty()) {
1573af732203SDimitry Andric error.SetErrorStringWithFormat(
1574af732203SDimitry Andric "missing shell interpreter path for option -i|--interpreter.");
1575af732203SDimitry Andric return error;
1576af732203SDimitry Andric }
1577af732203SDimitry Andric
1578af732203SDimitry Andric m_shell_interpreter = option_arg.str();
1579af732203SDimitry Andric break;
1580af732203SDimitry Andric }
15810b57cec5SDimitry Andric default:
15829dba64beSDimitry Andric llvm_unreachable("Unimplemented option");
15830b57cec5SDimitry Andric }
15840b57cec5SDimitry Andric
15850b57cec5SDimitry Andric return error;
15860b57cec5SDimitry Andric }
15870b57cec5SDimitry Andric
OptionParsingStarting(ExecutionContext * execution_context)15885ffd83dbSDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
15895ffd83dbSDimitry Andric m_timeout.reset();
15905ffd83dbSDimitry Andric m_use_host_platform = false;
1591af732203SDimitry Andric m_shell_interpreter.clear();
15925ffd83dbSDimitry Andric }
15930b57cec5SDimitry Andric
15945ffd83dbSDimitry Andric Timeout<std::micro> m_timeout = std::chrono::seconds(10);
15955ffd83dbSDimitry Andric bool m_use_host_platform;
1596af732203SDimitry Andric std::string m_shell_interpreter;
15970b57cec5SDimitry Andric };
15980b57cec5SDimitry Andric
CommandObjectPlatformShell(CommandInterpreter & interpreter)15990b57cec5SDimitry Andric CommandObjectPlatformShell(CommandInterpreter &interpreter)
16000b57cec5SDimitry Andric : CommandObjectRaw(interpreter, "platform shell",
16010b57cec5SDimitry Andric "Run a shell command on the current platform.",
16020b57cec5SDimitry Andric "platform shell <shell-command>", 0),
16030b57cec5SDimitry Andric m_options() {}
16040b57cec5SDimitry Andric
16050b57cec5SDimitry Andric ~CommandObjectPlatformShell() override = default;
16060b57cec5SDimitry Andric
GetOptions()16070b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; }
16080b57cec5SDimitry Andric
DoExecute(llvm::StringRef raw_command_line,CommandReturnObject & result)16090b57cec5SDimitry Andric bool DoExecute(llvm::StringRef raw_command_line,
16100b57cec5SDimitry Andric CommandReturnObject &result) override {
16110b57cec5SDimitry Andric ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext();
16120b57cec5SDimitry Andric m_options.NotifyOptionParsingStarting(&exe_ctx);
16130b57cec5SDimitry Andric
16140b57cec5SDimitry Andric // Print out an usage syntax on an empty command line.
16150b57cec5SDimitry Andric if (raw_command_line.empty()) {
16160b57cec5SDimitry Andric result.GetOutputStream().Printf("%s\n", this->GetSyntax().str().c_str());
16170b57cec5SDimitry Andric return true;
16180b57cec5SDimitry Andric }
16190b57cec5SDimitry Andric
16205ffd83dbSDimitry Andric const bool is_alias = !raw_command_line.contains("platform");
16210b57cec5SDimitry Andric OptionsWithRaw args(raw_command_line);
16220b57cec5SDimitry Andric
16230b57cec5SDimitry Andric if (args.HasArgs())
16240b57cec5SDimitry Andric if (!ParseOptions(args.GetArgs(), result))
16250b57cec5SDimitry Andric return false;
16260b57cec5SDimitry Andric
16275ffd83dbSDimitry Andric if (args.GetRawPart().empty()) {
16285ffd83dbSDimitry Andric result.GetOutputStream().Printf("%s <shell-command>\n",
16295ffd83dbSDimitry Andric is_alias ? "shell" : "platform shell");
16305ffd83dbSDimitry Andric return false;
16315ffd83dbSDimitry Andric }
16325ffd83dbSDimitry Andric
1633af732203SDimitry Andric llvm::StringRef cmd = args.GetRawPart();
1634af732203SDimitry Andric
16350b57cec5SDimitry Andric PlatformSP platform_sp(
16365ffd83dbSDimitry Andric m_options.m_use_host_platform
16375ffd83dbSDimitry Andric ? Platform::GetHostPlatform()
16385ffd83dbSDimitry Andric : GetDebugger().GetPlatformList().GetSelectedPlatform());
16390b57cec5SDimitry Andric Status error;
16400b57cec5SDimitry Andric if (platform_sp) {
16410b57cec5SDimitry Andric FileSpec working_dir{};
16420b57cec5SDimitry Andric std::string output;
16430b57cec5SDimitry Andric int status = -1;
16440b57cec5SDimitry Andric int signo = -1;
1645af732203SDimitry Andric error = (platform_sp->RunShellCommand(m_options.m_shell_interpreter, cmd,
1646af732203SDimitry Andric working_dir, &status, &signo,
16475ffd83dbSDimitry Andric &output, m_options.m_timeout));
16480b57cec5SDimitry Andric if (!output.empty())
16490b57cec5SDimitry Andric result.GetOutputStream().PutCString(output);
16500b57cec5SDimitry Andric if (status > 0) {
16510b57cec5SDimitry Andric if (signo > 0) {
16520b57cec5SDimitry Andric const char *signo_cstr = Host::GetSignalAsCString(signo);
16530b57cec5SDimitry Andric if (signo_cstr)
16540b57cec5SDimitry Andric result.GetOutputStream().Printf(
16550b57cec5SDimitry Andric "error: command returned with status %i and signal %s\n",
16560b57cec5SDimitry Andric status, signo_cstr);
16570b57cec5SDimitry Andric else
16580b57cec5SDimitry Andric result.GetOutputStream().Printf(
16590b57cec5SDimitry Andric "error: command returned with status %i and signal %i\n",
16600b57cec5SDimitry Andric status, signo);
16610b57cec5SDimitry Andric } else
16620b57cec5SDimitry Andric result.GetOutputStream().Printf(
16630b57cec5SDimitry Andric "error: command returned with status %i\n", status);
16640b57cec5SDimitry Andric }
16650b57cec5SDimitry Andric } else {
16660b57cec5SDimitry Andric result.GetOutputStream().Printf(
16670b57cec5SDimitry Andric "error: cannot run remote shell commands without a platform\n");
16680b57cec5SDimitry Andric error.SetErrorString(
16690b57cec5SDimitry Andric "error: cannot run remote shell commands without a platform");
16700b57cec5SDimitry Andric }
16710b57cec5SDimitry Andric
16720b57cec5SDimitry Andric if (error.Fail()) {
16730b57cec5SDimitry Andric result.AppendError(error.AsCString());
16740b57cec5SDimitry Andric } else {
16750b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult);
16760b57cec5SDimitry Andric }
16770b57cec5SDimitry Andric return true;
16780b57cec5SDimitry Andric }
16790b57cec5SDimitry Andric
16800b57cec5SDimitry Andric CommandOptions m_options;
16810b57cec5SDimitry Andric };
16820b57cec5SDimitry Andric
16830b57cec5SDimitry Andric // "platform install" - install a target to a remote end
16840b57cec5SDimitry Andric class CommandObjectPlatformInstall : public CommandObjectParsed {
16850b57cec5SDimitry Andric public:
CommandObjectPlatformInstall(CommandInterpreter & interpreter)16860b57cec5SDimitry Andric CommandObjectPlatformInstall(CommandInterpreter &interpreter)
16870b57cec5SDimitry Andric : CommandObjectParsed(
16880b57cec5SDimitry Andric interpreter, "platform target-install",
16890b57cec5SDimitry Andric "Install a target (bundle or executable file) to the remote end.",
16900b57cec5SDimitry Andric "platform target-install <local-thing> <remote-sandbox>", 0) {}
16910b57cec5SDimitry Andric
16920b57cec5SDimitry Andric ~CommandObjectPlatformInstall() override = default;
16930b57cec5SDimitry Andric
1694af732203SDimitry Andric void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)1695af732203SDimitry Andric HandleArgumentCompletion(CompletionRequest &request,
1696af732203SDimitry Andric OptionElementVector &opt_element_vector) override {
1697af732203SDimitry Andric if (request.GetCursorIndex())
1698af732203SDimitry Andric return;
1699af732203SDimitry Andric CommandCompletions::InvokeCommonCompletionCallbacks(
1700af732203SDimitry Andric GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
1701af732203SDimitry Andric request, nullptr);
1702af732203SDimitry Andric }
1703af732203SDimitry Andric
DoExecute(Args & args,CommandReturnObject & result)17040b57cec5SDimitry Andric bool DoExecute(Args &args, CommandReturnObject &result) override {
17050b57cec5SDimitry Andric if (args.GetArgumentCount() != 2) {
17060b57cec5SDimitry Andric result.AppendError("platform target-install takes two arguments");
17070b57cec5SDimitry Andric return false;
17080b57cec5SDimitry Andric }
17090b57cec5SDimitry Andric // TODO: move the bulk of this code over to the platform itself
17100b57cec5SDimitry Andric FileSpec src(args.GetArgumentAtIndex(0));
17110b57cec5SDimitry Andric FileSystem::Instance().Resolve(src);
17120b57cec5SDimitry Andric FileSpec dst(args.GetArgumentAtIndex(1));
17130b57cec5SDimitry Andric if (!FileSystem::Instance().Exists(src)) {
17140b57cec5SDimitry Andric result.AppendError("source location does not exist or is not accessible");
17150b57cec5SDimitry Andric return false;
17160b57cec5SDimitry Andric }
17170b57cec5SDimitry Andric PlatformSP platform_sp(
17180b57cec5SDimitry Andric GetDebugger().GetPlatformList().GetSelectedPlatform());
17190b57cec5SDimitry Andric if (!platform_sp) {
17200b57cec5SDimitry Andric result.AppendError("no platform currently selected");
17210b57cec5SDimitry Andric return false;
17220b57cec5SDimitry Andric }
17230b57cec5SDimitry Andric
17240b57cec5SDimitry Andric Status error = platform_sp->Install(src, dst);
17250b57cec5SDimitry Andric if (error.Success()) {
17260b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult);
17270b57cec5SDimitry Andric } else {
17280b57cec5SDimitry Andric result.AppendErrorWithFormat("install failed: %s", error.AsCString());
17290b57cec5SDimitry Andric }
17300b57cec5SDimitry Andric return result.Succeeded();
17310b57cec5SDimitry Andric }
17320b57cec5SDimitry Andric };
17330b57cec5SDimitry Andric
CommandObjectPlatform(CommandInterpreter & interpreter)17340b57cec5SDimitry Andric CommandObjectPlatform::CommandObjectPlatform(CommandInterpreter &interpreter)
17350b57cec5SDimitry Andric : CommandObjectMultiword(
17360b57cec5SDimitry Andric interpreter, "platform", "Commands to manage and create platforms.",
17370b57cec5SDimitry Andric "platform [connect|disconnect|info|list|status|select] ...") {
17380b57cec5SDimitry Andric LoadSubCommand("select",
17390b57cec5SDimitry Andric CommandObjectSP(new CommandObjectPlatformSelect(interpreter)));
17400b57cec5SDimitry Andric LoadSubCommand("list",
17410b57cec5SDimitry Andric CommandObjectSP(new CommandObjectPlatformList(interpreter)));
17420b57cec5SDimitry Andric LoadSubCommand("status",
17430b57cec5SDimitry Andric CommandObjectSP(new CommandObjectPlatformStatus(interpreter)));
17440b57cec5SDimitry Andric LoadSubCommand("connect", CommandObjectSP(
17450b57cec5SDimitry Andric new CommandObjectPlatformConnect(interpreter)));
17460b57cec5SDimitry Andric LoadSubCommand(
17470b57cec5SDimitry Andric "disconnect",
17480b57cec5SDimitry Andric CommandObjectSP(new CommandObjectPlatformDisconnect(interpreter)));
17490b57cec5SDimitry Andric LoadSubCommand("settings", CommandObjectSP(new CommandObjectPlatformSettings(
17500b57cec5SDimitry Andric interpreter)));
17510b57cec5SDimitry Andric LoadSubCommand("mkdir",
17520b57cec5SDimitry Andric CommandObjectSP(new CommandObjectPlatformMkDir(interpreter)));
17530b57cec5SDimitry Andric LoadSubCommand("file",
17540b57cec5SDimitry Andric CommandObjectSP(new CommandObjectPlatformFile(interpreter)));
17550b57cec5SDimitry Andric LoadSubCommand("get-file", CommandObjectSP(new CommandObjectPlatformGetFile(
17560b57cec5SDimitry Andric interpreter)));
17570b57cec5SDimitry Andric LoadSubCommand("get-size", CommandObjectSP(new CommandObjectPlatformGetSize(
17580b57cec5SDimitry Andric interpreter)));
17590b57cec5SDimitry Andric LoadSubCommand("put-file", CommandObjectSP(new CommandObjectPlatformPutFile(
17600b57cec5SDimitry Andric interpreter)));
17610b57cec5SDimitry Andric LoadSubCommand("process", CommandObjectSP(
17620b57cec5SDimitry Andric new CommandObjectPlatformProcess(interpreter)));
17630b57cec5SDimitry Andric LoadSubCommand("shell",
17640b57cec5SDimitry Andric CommandObjectSP(new CommandObjectPlatformShell(interpreter)));
17650b57cec5SDimitry Andric LoadSubCommand(
17660b57cec5SDimitry Andric "target-install",
17670b57cec5SDimitry Andric CommandObjectSP(new CommandObjectPlatformInstall(interpreter)));
17680b57cec5SDimitry Andric }
17690b57cec5SDimitry Andric
17700b57cec5SDimitry Andric CommandObjectPlatform::~CommandObjectPlatform() = default;
1771