blob: 8433fbdc985e96ea7a40bcc33b1f71013ecf7b53 [file] [log] [blame]
Greg Claytonded470d2011-03-19 01:12:21 +00001//===-- CommandObjectPlatform.cpp -------------------------------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Greg Claytonded470d2011-03-19 01:12:21 +00006//
7//===----------------------------------------------------------------------===//
8
Greg Clayton1cf2aa82016-03-24 21:49:22 +00009#include <mutex>
Eugene Zelenko435c2c92016-02-22 19:02:01 +000010#include "CommandObjectPlatform.h"
Greg Claytonded470d2011-03-19 01:12:21 +000011#include "lldb/Core/Debugger.h"
Greg Clayton1f746072012-08-29 21:13:06 +000012#include "lldb/Core/Module.h"
Greg Claytonded470d2011-03-19 01:12:21 +000013#include "lldb/Core/PluginManager.h"
Zachary Turner3eb2b442017-03-22 23:33:16 +000014#include "lldb/Host/OptionParser.h"
Vince Harron5275aaa2015-01-15 20:08:35 +000015#include "lldb/Host/StringConvert.h"
Greg Claytonded470d2011-03-19 01:12:21 +000016#include "lldb/Interpreter/CommandInterpreter.h"
Zachary Turnerd37221d2014-07-09 16:31:49 +000017#include "lldb/Interpreter/CommandOptionValidators.h"
Greg Claytonded470d2011-03-19 01:12:21 +000018#include "lldb/Interpreter/CommandReturnObject.h"
Greg Claytonfbb76342013-11-20 21:07:01 +000019#include "lldb/Interpreter/OptionGroupFile.h"
Greg Clayton7260f622011-04-18 08:33:37 +000020#include "lldb/Interpreter/OptionGroupPlatform.h"
Greg Claytonded470d2011-03-19 01:12:21 +000021#include "lldb/Target/ExecutionContext.h"
22#include "lldb/Target/Platform.h"
Greg Claytoneb0103f2011-04-07 22:46:35 +000023#include "lldb/Target/Process.h"
Pavel Labath145d95c2018-04-17 18:53:35 +000024#include "lldb/Utility/Args.h"
Zachary Turner666cc0b2017-03-04 01:30:05 +000025#include "lldb/Utility/DataExtractor.h"
Greg Claytonded470d2011-03-19 01:12:21 +000026
Zachary Turnerecbb0bb2016-09-19 17:54:06 +000027#include "llvm/ADT/SmallString.h"
Kamil Rytarowskic5f28e22017-02-06 17:55:02 +000028#include "llvm/Support/Threading.h"
Zachary Turnerecbb0bb2016-09-19 17:54:06 +000029
Greg Claytonded470d2011-03-19 01:12:21 +000030using namespace lldb;
31using namespace lldb_private;
32
Zachary Turner8cef4b02016-09-23 17:48:13 +000033static mode_t ParsePermissionString(const char *) = delete;
34
35static mode_t ParsePermissionString(llvm::StringRef permissions) {
36 if (permissions.size() != 9)
Kate Stoneb9c1b512016-09-06 20:57:50 +000037 return (mode_t)(-1);
38 bool user_r, user_w, user_x, group_r, group_w, group_x, world_r, world_w,
39 world_x;
40
41 user_r = (permissions[0] == 'r');
42 user_w = (permissions[1] == 'w');
43 user_x = (permissions[2] == 'x');
44
45 group_r = (permissions[3] == 'r');
46 group_w = (permissions[4] == 'w');
47 group_x = (permissions[5] == 'x');
48
49 world_r = (permissions[6] == 'r');
50 world_w = (permissions[7] == 'w');
51 world_x = (permissions[8] == 'x');
52
53 mode_t user, group, world;
54 user = (user_r ? 4 : 0) | (user_w ? 2 : 0) | (user_x ? 1 : 0);
55 group = (group_r ? 4 : 0) | (group_w ? 2 : 0) | (group_x ? 1 : 0);
56 world = (world_r ? 4 : 0) | (world_w ? 2 : 0) | (world_x ? 1 : 0);
57
58 return user | group | world;
Daniel Maleae0f8f572013-08-26 23:57:52 +000059}
60
Raphael Isemann2359fec2019-07-24 12:05:42 +000061#define LLDB_OPTIONS_permissions
Raphael Isemannaaad1a82019-07-24 12:08:08 +000062#include "CommandOptions.inc"
Daniel Maleae0f8f572013-08-26 23:57:52 +000063
Zachary Turner8cef4b02016-09-23 17:48:13 +000064class OptionPermissions : public OptionGroup {
Daniel Maleae0f8f572013-08-26 23:57:52 +000065public:
Kate Stoneb9c1b512016-09-06 20:57:50 +000066 OptionPermissions() {}
67
68 ~OptionPermissions() override = default;
69
Zachary Turner97206d52017-05-12 04:51:55 +000070 lldb_private::Status
Zachary Turner8cef4b02016-09-23 17:48:13 +000071 SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
Kate Stoneb9c1b512016-09-06 20:57:50 +000072 ExecutionContext *execution_context) override {
Zachary Turner97206d52017-05-12 04:51:55 +000073 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +000074 char short_option = (char)GetDefinitions()[option_idx].short_option;
75 switch (short_option) {
76 case 'v': {
Zachary Turner8cef4b02016-09-23 17:48:13 +000077 if (option_arg.getAsInteger(8, m_permissions)) {
78 m_permissions = 0777;
Kate Stoneb9c1b512016-09-06 20:57:50 +000079 error.SetErrorStringWithFormat("invalid value for permissions: %s",
Zachary Turner8cef4b02016-09-23 17:48:13 +000080 option_arg.str().c_str());
81 }
82
Kate Stoneb9c1b512016-09-06 20:57:50 +000083 } break;
84 case 's': {
85 mode_t perms = ParsePermissionString(option_arg);
86 if (perms == (mode_t)-1)
87 error.SetErrorStringWithFormat("invalid value for permissions: %s",
Zachary Turner8cef4b02016-09-23 17:48:13 +000088 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +000089 else
90 m_permissions = perms;
91 } break;
92 case 'r':
93 m_permissions |= lldb::eFilePermissionsUserRead;
94 break;
95 case 'w':
96 m_permissions |= lldb::eFilePermissionsUserWrite;
97 break;
98 case 'x':
99 m_permissions |= lldb::eFilePermissionsUserExecute;
100 break;
101 case 'R':
102 m_permissions |= lldb::eFilePermissionsGroupRead;
103 break;
104 case 'W':
105 m_permissions |= lldb::eFilePermissionsGroupWrite;
106 break;
107 case 'X':
108 m_permissions |= lldb::eFilePermissionsGroupExecute;
109 break;
110 case 'd':
111 m_permissions |= lldb::eFilePermissionsWorldRead;
112 break;
113 case 't':
114 m_permissions |= lldb::eFilePermissionsWorldWrite;
115 break;
116 case 'e':
117 m_permissions |= lldb::eFilePermissionsWorldExecute;
118 break;
119 default:
Raphael Isemann36162012019-08-22 08:08:05 +0000120 llvm_unreachable("Unimplemented option");
Daniel Maleae0f8f572013-08-26 23:57:52 +0000121 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000122
Kate Stoneb9c1b512016-09-06 20:57:50 +0000123 return error;
124 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000125
Kate Stoneb9c1b512016-09-06 20:57:50 +0000126 void OptionParsingStarting(ExecutionContext *execution_context) override {
127 m_permissions = 0;
128 }
129
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000130 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +0000131 return llvm::makeArrayRef(g_permissions_options);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000132 }
133
134 // Instance variables to hold the values for command options.
135
136 uint32_t m_permissions;
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000137
Daniel Maleae0f8f572013-08-26 23:57:52 +0000138private:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000139 DISALLOW_COPY_AND_ASSIGN(OptionPermissions);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000140};
Greg Claytonf6b8b582011-04-13 00:18:08 +0000141
Greg Clayton7260f622011-04-18 08:33:37 +0000142// "platform select <platform-name>"
Kate Stoneb9c1b512016-09-06 20:57:50 +0000143class CommandObjectPlatformSelect : public CommandObjectParsed {
Greg Claytonded470d2011-03-19 01:12:21 +0000144public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000145 CommandObjectPlatformSelect(CommandInterpreter &interpreter)
146 : CommandObjectParsed(interpreter, "platform select",
147 "Create a platform if needed and select it as the "
148 "current platform.",
149 "platform select <platform-name>", 0),
150 m_option_group(),
151 m_platform_options(
152 false) // Don't include the "--platform" option by passing false
153 {
154 m_option_group.Append(&m_platform_options, LLDB_OPT_SET_ALL, 1);
155 m_option_group.Finalize();
156 }
Greg Claytonded470d2011-03-19 01:12:21 +0000157
Kate Stoneb9c1b512016-09-06 20:57:50 +0000158 ~CommandObjectPlatformSelect() override = default;
Greg Claytonded470d2011-03-19 01:12:21 +0000159
Raphael Isemannae34ed22019-08-22 07:41:23 +0000160 void HandleCompletion(CompletionRequest &request) override {
Raphael Isemanna2e76c02018-07-13 18:28:14 +0000161 CommandCompletions::PlatformPluginNames(GetCommandInterpreter(), request,
162 nullptr);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000163 }
164
165 Options *GetOptions() override { return &m_option_group; }
Jim Ingham5a988412012-06-08 21:56:10 +0000166
167protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000168 bool DoExecute(Args &args, CommandReturnObject &result) override {
169 if (args.GetArgumentCount() == 1) {
170 const char *platform_name = args.GetArgumentAtIndex(0);
171 if (platform_name && platform_name[0]) {
172 const bool select = true;
173 m_platform_options.SetPlatformName(platform_name);
Zachary Turner97206d52017-05-12 04:51:55 +0000174 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000175 ArchSpec platform_arch;
176 PlatformSP platform_sp(m_platform_options.CreatePlatformWithOptions(
177 m_interpreter, ArchSpec(), select, error, platform_arch));
178 if (platform_sp) {
Jonas Devlieghere57179862019-04-27 06:19:42 +0000179 GetDebugger().GetPlatformList().SetSelectedPlatform(platform_sp);
Vince Harron1b5a74e2015-01-21 22:42:49 +0000180
Kate Stoneb9c1b512016-09-06 20:57:50 +0000181 platform_sp->GetStatus(result.GetOutputStream());
182 result.SetStatus(eReturnStatusSuccessFinishResult);
183 } else {
184 result.AppendError(error.AsCString());
185 result.SetStatus(eReturnStatusFailed);
Greg Claytonded470d2011-03-19 01:12:21 +0000186 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000187 } else {
188 result.AppendError("invalid platform name");
189 result.SetStatus(eReturnStatusFailed);
190 }
191 } else {
192 result.AppendError(
193 "platform create takes a platform name as an argument\n");
194 result.SetStatus(eReturnStatusFailed);
Greg Claytonded470d2011-03-19 01:12:21 +0000195 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000196 return result.Succeeded();
197 }
Greg Clayton7260f622011-04-18 08:33:37 +0000198
Kate Stoneb9c1b512016-09-06 20:57:50 +0000199 OptionGroupOptions m_option_group;
200 OptionGroupPlatform m_platform_options;
Greg Claytonded470d2011-03-19 01:12:21 +0000201};
202
Greg Claytonded470d2011-03-19 01:12:21 +0000203// "platform list"
Kate Stoneb9c1b512016-09-06 20:57:50 +0000204class CommandObjectPlatformList : public CommandObjectParsed {
Greg Claytonded470d2011-03-19 01:12:21 +0000205public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000206 CommandObjectPlatformList(CommandInterpreter &interpreter)
207 : CommandObjectParsed(interpreter, "platform list",
208 "List all platforms that are available.", nullptr,
209 0) {}
Greg Claytonded470d2011-03-19 01:12:21 +0000210
Kate Stoneb9c1b512016-09-06 20:57:50 +0000211 ~CommandObjectPlatformList() override = default;
Greg Claytonded470d2011-03-19 01:12:21 +0000212
Jim Ingham5a988412012-06-08 21:56:10 +0000213protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000214 bool DoExecute(Args &args, CommandReturnObject &result) override {
215 Stream &ostrm = result.GetOutputStream();
216 ostrm.Printf("Available platforms:\n");
Greg Claytonded470d2011-03-19 01:12:21 +0000217
Kate Stoneb9c1b512016-09-06 20:57:50 +0000218 PlatformSP host_platform_sp(Platform::GetHostPlatform());
219 ostrm.Printf("%s: %s\n", host_platform_sp->GetPluginName().GetCString(),
220 host_platform_sp->GetDescription());
221
222 uint32_t idx;
Jonas Devlieghere09ad8c82019-05-24 00:44:33 +0000223 for (idx = 0; true; ++idx) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000224 const char *plugin_name =
225 PluginManager::GetPlatformPluginNameAtIndex(idx);
226 if (plugin_name == nullptr)
227 break;
228 const char *plugin_desc =
229 PluginManager::GetPlatformPluginDescriptionAtIndex(idx);
230 if (plugin_desc == nullptr)
231 break;
232 ostrm.Printf("%s: %s\n", plugin_name, plugin_desc);
Greg Claytonded470d2011-03-19 01:12:21 +0000233 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000234
235 if (idx == 0) {
236 result.AppendError("no platforms are available\n");
237 result.SetStatus(eReturnStatusFailed);
238 } else
239 result.SetStatus(eReturnStatusSuccessFinishResult);
240 return result.Succeeded();
241 }
Greg Claytonded470d2011-03-19 01:12:21 +0000242};
243
Greg Claytonded470d2011-03-19 01:12:21 +0000244// "platform status"
Kate Stoneb9c1b512016-09-06 20:57:50 +0000245class CommandObjectPlatformStatus : public CommandObjectParsed {
Greg Claytonded470d2011-03-19 01:12:21 +0000246public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000247 CommandObjectPlatformStatus(CommandInterpreter &interpreter)
248 : CommandObjectParsed(interpreter, "platform status",
249 "Display status for the current platform.", nullptr,
250 0) {}
Greg Claytonded470d2011-03-19 01:12:21 +0000251
Kate Stoneb9c1b512016-09-06 20:57:50 +0000252 ~CommandObjectPlatformStatus() override = default;
Greg Claytonded470d2011-03-19 01:12:21 +0000253
Jim Ingham5a988412012-06-08 21:56:10 +0000254protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000255 bool DoExecute(Args &args, CommandReturnObject &result) override {
256 Stream &ostrm = result.GetOutputStream();
257
Jonas Devlieghere57179862019-04-27 06:19:42 +0000258 Target *target = GetDebugger().GetSelectedTarget().get();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000259 PlatformSP platform_sp;
260 if (target) {
261 platform_sp = target->GetPlatform();
Greg Claytonded470d2011-03-19 01:12:21 +0000262 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000263 if (!platform_sp) {
Jonas Devlieghere57179862019-04-27 06:19:42 +0000264 platform_sp = GetDebugger().GetPlatformList().GetSelectedPlatform();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000265 }
266 if (platform_sp) {
267 platform_sp->GetStatus(ostrm);
268 result.SetStatus(eReturnStatusSuccessFinishResult);
269 } else {
Bruce Mitchener2b139132017-07-21 07:08:20 +0000270 result.AppendError("no platform is currently selected\n");
Kate Stoneb9c1b512016-09-06 20:57:50 +0000271 result.SetStatus(eReturnStatusFailed);
272 }
273 return result.Succeeded();
274 }
Greg Claytonded470d2011-03-19 01:12:21 +0000275};
276
Greg Claytond314e812011-03-23 00:09:55 +0000277// "platform connect <connect-url>"
Kate Stoneb9c1b512016-09-06 20:57:50 +0000278class CommandObjectPlatformConnect : public CommandObjectParsed {
Greg Claytond314e812011-03-23 00:09:55 +0000279public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000280 CommandObjectPlatformConnect(CommandInterpreter &interpreter)
281 : CommandObjectParsed(
282 interpreter, "platform connect",
283 "Select the current platform by providing a connection URL.",
284 "platform connect <connect-url>", 0) {}
Greg Claytond314e812011-03-23 00:09:55 +0000285
Kate Stoneb9c1b512016-09-06 20:57:50 +0000286 ~CommandObjectPlatformConnect() override = default;
Greg Claytond314e812011-03-23 00:09:55 +0000287
Jim Ingham5a988412012-06-08 21:56:10 +0000288protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000289 bool DoExecute(Args &args, CommandReturnObject &result) override {
290 Stream &ostrm = result.GetOutputStream();
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000291
Kate Stoneb9c1b512016-09-06 20:57:50 +0000292 PlatformSP platform_sp(
Jonas Devlieghere57179862019-04-27 06:19:42 +0000293 GetDebugger().GetPlatformList().GetSelectedPlatform());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000294 if (platform_sp) {
Zachary Turner97206d52017-05-12 04:51:55 +0000295 Status error(platform_sp->ConnectRemote(args));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000296 if (error.Success()) {
297 platform_sp->GetStatus(ostrm);
298 result.SetStatus(eReturnStatusSuccessFinishResult);
299
Jonas Devlieghere57179862019-04-27 06:19:42 +0000300 platform_sp->ConnectToWaitingProcesses(GetDebugger(), error);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000301 if (error.Fail()) {
302 result.AppendError(error.AsCString());
303 result.SetStatus(eReturnStatusFailed);
Greg Claytond314e812011-03-23 00:09:55 +0000304 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000305 } else {
306 result.AppendErrorWithFormat("%s\n", error.AsCString());
307 result.SetStatus(eReturnStatusFailed);
308 }
309 } else {
310 result.AppendError("no platform is currently selected\n");
311 result.SetStatus(eReturnStatusFailed);
Greg Claytond314e812011-03-23 00:09:55 +0000312 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000313 return result.Succeeded();
314 }
315
316 Options *GetOptions() override {
317 PlatformSP platform_sp(
Jonas Devlieghere57179862019-04-27 06:19:42 +0000318 GetDebugger().GetPlatformList().GetSelectedPlatform());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000319 OptionGroupOptions *m_platform_options = nullptr;
320 if (platform_sp) {
321 m_platform_options = platform_sp->GetConnectionOptions(m_interpreter);
322 if (m_platform_options != nullptr && !m_platform_options->m_did_finalize)
323 m_platform_options->Finalize();
Daniel Maleae0f8f572013-08-26 23:57:52 +0000324 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000325 return m_platform_options;
326 }
Greg Claytond314e812011-03-23 00:09:55 +0000327};
328
Greg Claytond314e812011-03-23 00:09:55 +0000329// "platform disconnect"
Kate Stoneb9c1b512016-09-06 20:57:50 +0000330class CommandObjectPlatformDisconnect : public CommandObjectParsed {
Greg Claytond314e812011-03-23 00:09:55 +0000331public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000332 CommandObjectPlatformDisconnect(CommandInterpreter &interpreter)
333 : CommandObjectParsed(interpreter, "platform disconnect",
334 "Disconnect from the current platform.",
335 "platform disconnect", 0) {}
Greg Claytond314e812011-03-23 00:09:55 +0000336
Kate Stoneb9c1b512016-09-06 20:57:50 +0000337 ~CommandObjectPlatformDisconnect() override = default;
Greg Claytond314e812011-03-23 00:09:55 +0000338
Jim Ingham5a988412012-06-08 21:56:10 +0000339protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000340 bool DoExecute(Args &args, CommandReturnObject &result) override {
341 PlatformSP platform_sp(
Jonas Devlieghere57179862019-04-27 06:19:42 +0000342 GetDebugger().GetPlatformList().GetSelectedPlatform());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000343 if (platform_sp) {
344 if (args.GetArgumentCount() == 0) {
Zachary Turner97206d52017-05-12 04:51:55 +0000345 Status error;
Greg Claytond314e812011-03-23 00:09:55 +0000346
Kate Stoneb9c1b512016-09-06 20:57:50 +0000347 if (platform_sp->IsConnected()) {
Adrian Prantl05097242018-04-30 16:49:04 +0000348 // Cache the instance name if there is one since we are about to
349 // disconnect and the name might go with it.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000350 const char *hostname_cstr = platform_sp->GetHostname();
351 std::string hostname;
352 if (hostname_cstr)
353 hostname.assign(hostname_cstr);
354
355 error = platform_sp->DisconnectRemote();
356 if (error.Success()) {
357 Stream &ostrm = result.GetOutputStream();
358 if (hostname.empty())
359 ostrm.Printf("Disconnected from \"%s\"\n",
360 platform_sp->GetPluginName().GetCString());
Greg Claytond314e812011-03-23 00:09:55 +0000361 else
Kate Stoneb9c1b512016-09-06 20:57:50 +0000362 ostrm.Printf("Disconnected from \"%s\"\n", hostname.c_str());
363 result.SetStatus(eReturnStatusSuccessFinishResult);
364 } else {
365 result.AppendErrorWithFormat("%s", error.AsCString());
366 result.SetStatus(eReturnStatusFailed);
367 }
368 } else {
369 // Not connected...
370 result.AppendErrorWithFormat(
371 "not connected to '%s'",
372 platform_sp->GetPluginName().GetCString());
373 result.SetStatus(eReturnStatusFailed);
Greg Claytond314e812011-03-23 00:09:55 +0000374 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000375 } else {
376 // Bad args
377 result.AppendError(
378 "\"platform disconnect\" doesn't take any arguments");
379 result.SetStatus(eReturnStatusFailed);
380 }
381 } else {
382 result.AppendError("no platform is currently selected");
383 result.SetStatus(eReturnStatusFailed);
Greg Claytond314e812011-03-23 00:09:55 +0000384 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000385 return result.Succeeded();
386 }
Greg Claytond314e812011-03-23 00:09:55 +0000387};
Daniel Maleae0f8f572013-08-26 23:57:52 +0000388
Greg Claytonfbb76342013-11-20 21:07:01 +0000389// "platform settings"
Kate Stoneb9c1b512016-09-06 20:57:50 +0000390class CommandObjectPlatformSettings : public CommandObjectParsed {
Greg Claytonfbb76342013-11-20 21:07:01 +0000391public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000392 CommandObjectPlatformSettings(CommandInterpreter &interpreter)
393 : CommandObjectParsed(interpreter, "platform settings",
394 "Set settings for the current target's platform, "
395 "or for a platform by name.",
396 "platform settings", 0),
Todd Fialae1cfbc72016-08-11 23:51:28 +0000397 m_options(),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000398 m_option_working_dir(LLDB_OPT_SET_1, false, "working-dir", 'w', 0,
399 eArgTypePath,
400 "The working directory for the platform.") {
401 m_options.Append(&m_option_working_dir, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
402 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000403
Kate Stoneb9c1b512016-09-06 20:57:50 +0000404 ~CommandObjectPlatformSettings() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000405
Greg Claytonfbb76342013-11-20 21:07:01 +0000406protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000407 bool DoExecute(Args &args, CommandReturnObject &result) override {
408 PlatformSP platform_sp(
Jonas Devlieghere57179862019-04-27 06:19:42 +0000409 GetDebugger().GetPlatformList().GetSelectedPlatform());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000410 if (platform_sp) {
411 if (m_option_working_dir.GetOptionValue().OptionWasSet())
412 platform_sp->SetWorkingDirectory(
413 m_option_working_dir.GetOptionValue().GetCurrentValue());
414 } else {
415 result.AppendError("no platform is currently selected");
416 result.SetStatus(eReturnStatusFailed);
Greg Claytonfbb76342013-11-20 21:07:01 +0000417 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000418 return result.Succeeded();
419 }
420
421 Options *GetOptions() override {
422 if (!m_options.DidFinalize())
423 m_options.Finalize();
424 return &m_options;
425 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000426
Greg Claytonfbb76342013-11-20 21:07:01 +0000427protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000428 OptionGroupOptions m_options;
429 OptionGroupFile m_option_working_dir;
Greg Claytonfbb76342013-11-20 21:07:01 +0000430};
431
Daniel Maleae0f8f572013-08-26 23:57:52 +0000432// "platform mkdir"
Kate Stoneb9c1b512016-09-06 20:57:50 +0000433class CommandObjectPlatformMkDir : public CommandObjectParsed {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000434public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000435 CommandObjectPlatformMkDir(CommandInterpreter &interpreter)
436 : CommandObjectParsed(interpreter, "platform mkdir",
437 "Make a new directory on the remote end.", nullptr,
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000438 0),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000439 m_options() {}
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000440
Kate Stoneb9c1b512016-09-06 20:57:50 +0000441 ~CommandObjectPlatformMkDir() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000442
Kate Stoneb9c1b512016-09-06 20:57:50 +0000443 bool DoExecute(Args &args, CommandReturnObject &result) override {
444 PlatformSP platform_sp(
Jonas Devlieghere57179862019-04-27 06:19:42 +0000445 GetDebugger().GetPlatformList().GetSelectedPlatform());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000446 if (platform_sp) {
447 std::string cmd_line;
448 args.GetCommandString(cmd_line);
449 uint32_t mode;
450 const OptionPermissions *options_permissions =
451 (const OptionPermissions *)m_options.GetGroupWithOption('r');
452 if (options_permissions)
453 mode = options_permissions->m_permissions;
454 else
455 mode = lldb::eFilePermissionsUserRWX | lldb::eFilePermissionsGroupRWX |
456 lldb::eFilePermissionsWorldRX;
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000457 Status error = platform_sp->MakeDirectory(FileSpec(cmd_line), mode);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000458 if (error.Success()) {
459 result.SetStatus(eReturnStatusSuccessFinishResult);
460 } else {
461 result.AppendError(error.AsCString());
462 result.SetStatus(eReturnStatusFailed);
463 }
464 } else {
465 result.AppendError("no platform currently selected\n");
466 result.SetStatus(eReturnStatusFailed);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000467 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000468 return result.Succeeded();
469 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000470
Kate Stoneb9c1b512016-09-06 20:57:50 +0000471 Options *GetOptions() override {
472 if (!m_options.DidFinalize()) {
473 m_options.Append(new OptionPermissions());
474 m_options.Finalize();
475 }
476 return &m_options;
477 }
478
479 OptionGroupOptions m_options;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000480};
481
Daniel Maleae0f8f572013-08-26 23:57:52 +0000482// "platform fopen"
Kate Stoneb9c1b512016-09-06 20:57:50 +0000483class CommandObjectPlatformFOpen : public CommandObjectParsed {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000484public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000485 CommandObjectPlatformFOpen(CommandInterpreter &interpreter)
486 : CommandObjectParsed(interpreter, "platform file open",
487 "Open a file on the remote end.", nullptr, 0),
488 m_options() {}
489
490 ~CommandObjectPlatformFOpen() override = default;
491
492 bool DoExecute(Args &args, CommandReturnObject &result) override {
493 PlatformSP platform_sp(
Jonas Devlieghere57179862019-04-27 06:19:42 +0000494 GetDebugger().GetPlatformList().GetSelectedPlatform());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000495 if (platform_sp) {
Zachary Turner97206d52017-05-12 04:51:55 +0000496 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000497 std::string cmd_line;
498 args.GetCommandString(cmd_line);
499 mode_t perms;
500 const OptionPermissions *options_permissions =
501 (const OptionPermissions *)m_options.GetGroupWithOption('r');
502 if (options_permissions)
503 perms = options_permissions->m_permissions;
504 else
505 perms = lldb::eFilePermissionsUserRW | lldb::eFilePermissionsGroupRW |
506 lldb::eFilePermissionsWorldRead;
507 lldb::user_id_t fd = platform_sp->OpenFile(
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000508 FileSpec(cmd_line),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000509 File::eOpenOptionRead | File::eOpenOptionWrite |
510 File::eOpenOptionAppend | File::eOpenOptionCanCreate,
511 perms, error);
512 if (error.Success()) {
513 result.AppendMessageWithFormat("File Descriptor = %" PRIu64 "\n", fd);
514 result.SetStatus(eReturnStatusSuccessFinishResult);
515 } else {
516 result.AppendError(error.AsCString());
517 result.SetStatus(eReturnStatusFailed);
518 }
519 } else {
520 result.AppendError("no platform currently selected\n");
521 result.SetStatus(eReturnStatusFailed);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000522 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000523 return result.Succeeded();
524 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000525
Kate Stoneb9c1b512016-09-06 20:57:50 +0000526 Options *GetOptions() override {
527 if (!m_options.DidFinalize()) {
528 m_options.Append(new OptionPermissions());
529 m_options.Finalize();
Daniel Maleae0f8f572013-08-26 23:57:52 +0000530 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000531 return &m_options;
532 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000533
Kate Stoneb9c1b512016-09-06 20:57:50 +0000534 OptionGroupOptions m_options;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000535};
536
Daniel Maleae0f8f572013-08-26 23:57:52 +0000537// "platform fclose"
Kate Stoneb9c1b512016-09-06 20:57:50 +0000538class CommandObjectPlatformFClose : public CommandObjectParsed {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000539public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000540 CommandObjectPlatformFClose(CommandInterpreter &interpreter)
541 : CommandObjectParsed(interpreter, "platform file close",
542 "Close a file on the remote end.", nullptr, 0) {}
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000543
Kate Stoneb9c1b512016-09-06 20:57:50 +0000544 ~CommandObjectPlatformFClose() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000545
Kate Stoneb9c1b512016-09-06 20:57:50 +0000546 bool DoExecute(Args &args, CommandReturnObject &result) override {
547 PlatformSP platform_sp(
Jonas Devlieghere57179862019-04-27 06:19:42 +0000548 GetDebugger().GetPlatformList().GetSelectedPlatform());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000549 if (platform_sp) {
550 std::string cmd_line;
551 args.GetCommandString(cmd_line);
552 const lldb::user_id_t fd =
553 StringConvert::ToUInt64(cmd_line.c_str(), UINT64_MAX);
Zachary Turner97206d52017-05-12 04:51:55 +0000554 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000555 bool success = platform_sp->CloseFile(fd, error);
556 if (success) {
557 result.AppendMessageWithFormat("file %" PRIu64 " closed.\n", fd);
558 result.SetStatus(eReturnStatusSuccessFinishResult);
559 } else {
560 result.AppendError(error.AsCString());
561 result.SetStatus(eReturnStatusFailed);
562 }
563 } else {
564 result.AppendError("no platform currently selected\n");
565 result.SetStatus(eReturnStatusFailed);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000566 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000567 return result.Succeeded();
568 }
Daniel Maleae0f8f572013-08-26 23:57:52 +0000569};
570
Daniel Maleae0f8f572013-08-26 23:57:52 +0000571// "platform fread"
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000572
Raphael Isemann2359fec2019-07-24 12:05:42 +0000573#define LLDB_OPTIONS_platform_fread
574#include "CommandOptions.inc"
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000575
Kate Stoneb9c1b512016-09-06 20:57:50 +0000576class CommandObjectPlatformFRead : public CommandObjectParsed {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000577public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000578 CommandObjectPlatformFRead(CommandInterpreter &interpreter)
579 : CommandObjectParsed(interpreter, "platform file read",
580 "Read data from a file on the remote end.", nullptr,
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000581 0),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000582 m_options() {}
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000583
Kate Stoneb9c1b512016-09-06 20:57:50 +0000584 ~CommandObjectPlatformFRead() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000585
Kate Stoneb9c1b512016-09-06 20:57:50 +0000586 bool DoExecute(Args &args, CommandReturnObject &result) override {
587 PlatformSP platform_sp(
Jonas Devlieghere57179862019-04-27 06:19:42 +0000588 GetDebugger().GetPlatformList().GetSelectedPlatform());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000589 if (platform_sp) {
590 std::string cmd_line;
591 args.GetCommandString(cmd_line);
592 const lldb::user_id_t fd =
593 StringConvert::ToUInt64(cmd_line.c_str(), UINT64_MAX);
594 std::string buffer(m_options.m_count, 0);
Zachary Turner97206d52017-05-12 04:51:55 +0000595 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000596 uint32_t retcode = platform_sp->ReadFile(
597 fd, m_options.m_offset, &buffer[0], m_options.m_count, error);
598 result.AppendMessageWithFormat("Return = %d\n", retcode);
599 result.AppendMessageWithFormat("Data = \"%s\"\n", buffer.c_str());
600 result.SetStatus(eReturnStatusSuccessFinishResult);
601 } else {
602 result.AppendError("no platform currently selected\n");
603 result.SetStatus(eReturnStatusFailed);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000604 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000605 return result.Succeeded();
606 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000607
Kate Stoneb9c1b512016-09-06 20:57:50 +0000608 Options *GetOptions() override { return &m_options; }
609
Daniel Maleae0f8f572013-08-26 23:57:52 +0000610protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000611 class CommandOptions : public Options {
612 public:
613 CommandOptions() : Options() {}
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000614
Kate Stoneb9c1b512016-09-06 20:57:50 +0000615 ~CommandOptions() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000616
Zachary Turner97206d52017-05-12 04:51:55 +0000617 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
618 ExecutionContext *execution_context) override {
619 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000620 char short_option = (char)m_getopt_table[option_idx].val;
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000621
Kate Stoneb9c1b512016-09-06 20:57:50 +0000622 switch (short_option) {
623 case 'o':
Zachary Turnerfe114832016-11-12 16:56:47 +0000624 if (option_arg.getAsInteger(0, m_offset))
625 error.SetErrorStringWithFormat("invalid offset: '%s'",
626 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000627 break;
628 case 'c':
Zachary Turnerfe114832016-11-12 16:56:47 +0000629 if (option_arg.getAsInteger(0, m_count))
630 error.SetErrorStringWithFormat("invalid offset: '%s'",
631 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000632 break;
633 default:
Raphael Isemann36162012019-08-22 08:08:05 +0000634 llvm_unreachable("Unimplemented option");
Kate Stoneb9c1b512016-09-06 20:57:50 +0000635 }
636
637 return error;
638 }
639
640 void OptionParsingStarting(ExecutionContext *execution_context) override {
641 m_offset = 0;
642 m_count = 1;
643 }
644
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000645 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +0000646 return llvm::makeArrayRef(g_platform_fread_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000647 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000648
649 // Instance variables to hold the values for command options.
650
651 uint32_t m_offset;
652 uint32_t m_count;
653 };
654
655 CommandOptions m_options;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000656};
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000657
Daniel Maleae0f8f572013-08-26 23:57:52 +0000658// "platform fwrite"
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000659
Raphael Isemann2359fec2019-07-24 12:05:42 +0000660#define LLDB_OPTIONS_platform_fwrite
661#include "CommandOptions.inc"
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000662
Kate Stoneb9c1b512016-09-06 20:57:50 +0000663class CommandObjectPlatformFWrite : public CommandObjectParsed {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000664public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000665 CommandObjectPlatformFWrite(CommandInterpreter &interpreter)
666 : CommandObjectParsed(interpreter, "platform file write",
667 "Write data to a file on the remote end.", nullptr,
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000668 0),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000669 m_options() {}
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000670
Kate Stoneb9c1b512016-09-06 20:57:50 +0000671 ~CommandObjectPlatformFWrite() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000672
Kate Stoneb9c1b512016-09-06 20:57:50 +0000673 bool DoExecute(Args &args, CommandReturnObject &result) override {
674 PlatformSP platform_sp(
Jonas Devlieghere57179862019-04-27 06:19:42 +0000675 GetDebugger().GetPlatformList().GetSelectedPlatform());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000676 if (platform_sp) {
677 std::string cmd_line;
678 args.GetCommandString(cmd_line);
Zachary Turner97206d52017-05-12 04:51:55 +0000679 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000680 const lldb::user_id_t fd =
681 StringConvert::ToUInt64(cmd_line.c_str(), UINT64_MAX);
682 uint32_t retcode =
683 platform_sp->WriteFile(fd, m_options.m_offset, &m_options.m_data[0],
684 m_options.m_data.size(), error);
685 result.AppendMessageWithFormat("Return = %d\n", retcode);
686 result.SetStatus(eReturnStatusSuccessFinishResult);
687 } else {
688 result.AppendError("no platform currently selected\n");
689 result.SetStatus(eReturnStatusFailed);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000690 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000691 return result.Succeeded();
692 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000693
Kate Stoneb9c1b512016-09-06 20:57:50 +0000694 Options *GetOptions() override { return &m_options; }
695
Daniel Maleae0f8f572013-08-26 23:57:52 +0000696protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000697 class CommandOptions : public Options {
698 public:
699 CommandOptions() : Options() {}
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000700
Kate Stoneb9c1b512016-09-06 20:57:50 +0000701 ~CommandOptions() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000702
Zachary Turner97206d52017-05-12 04:51:55 +0000703 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
704 ExecutionContext *execution_context) override {
705 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000706 char short_option = (char)m_getopt_table[option_idx].val;
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000707
Kate Stoneb9c1b512016-09-06 20:57:50 +0000708 switch (short_option) {
709 case 'o':
Zachary Turnerfe114832016-11-12 16:56:47 +0000710 if (option_arg.getAsInteger(0, m_offset))
711 error.SetErrorStringWithFormat("invalid offset: '%s'",
712 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000713 break;
714 case 'd':
715 m_data.assign(option_arg);
716 break;
717 default:
Raphael Isemann36162012019-08-22 08:08:05 +0000718 llvm_unreachable("Unimplemented option");
Kate Stoneb9c1b512016-09-06 20:57:50 +0000719 }
720
721 return error;
722 }
723
724 void OptionParsingStarting(ExecutionContext *execution_context) override {
725 m_offset = 0;
726 m_data.clear();
727 }
728
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000729 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +0000730 return llvm::makeArrayRef(g_platform_fwrite_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000731 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000732
733 // Instance variables to hold the values for command options.
734
735 uint32_t m_offset;
736 std::string m_data;
737 };
738
739 CommandOptions m_options;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000740};
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000741
Kate Stoneb9c1b512016-09-06 20:57:50 +0000742class CommandObjectPlatformFile : public CommandObjectMultiword {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000743public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000744 // Constructors and Destructors
Kate Stoneb9c1b512016-09-06 20:57:50 +0000745 CommandObjectPlatformFile(CommandInterpreter &interpreter)
746 : CommandObjectMultiword(
747 interpreter, "platform file",
748 "Commands to access files on the current platform.",
749 "platform file [open|close|read|write] ...") {
750 LoadSubCommand(
751 "open", CommandObjectSP(new CommandObjectPlatformFOpen(interpreter)));
752 LoadSubCommand(
753 "close", CommandObjectSP(new CommandObjectPlatformFClose(interpreter)));
754 LoadSubCommand(
755 "read", CommandObjectSP(new CommandObjectPlatformFRead(interpreter)));
756 LoadSubCommand(
757 "write", CommandObjectSP(new CommandObjectPlatformFWrite(interpreter)));
758 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000759
Kate Stoneb9c1b512016-09-06 20:57:50 +0000760 ~CommandObjectPlatformFile() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000761
Daniel Maleae0f8f572013-08-26 23:57:52 +0000762private:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000763 // For CommandObjectPlatform only
Kate Stoneb9c1b512016-09-06 20:57:50 +0000764 DISALLOW_COPY_AND_ASSIGN(CommandObjectPlatformFile);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000765};
766
Daniel Maleae0f8f572013-08-26 23:57:52 +0000767// "platform get-file remote-file-path host-file-path"
Kate Stoneb9c1b512016-09-06 20:57:50 +0000768class CommandObjectPlatformGetFile : public CommandObjectParsed {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000769public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000770 CommandObjectPlatformGetFile(CommandInterpreter &interpreter)
771 : CommandObjectParsed(
772 interpreter, "platform get-file",
773 "Transfer a file from the remote end to the local host.",
774 "platform get-file <remote-file-spec> <local-file-spec>", 0) {
775 SetHelpLong(
776 R"(Examples:
Kate Stoneea671fb2015-07-14 05:48:36 +0000777
778(lldb) platform get-file /the/remote/file/path /the/local/file/path
779
Kate Stoneb9c1b512016-09-06 20:57:50 +0000780 Transfer a file from the remote end with file path /the/remote/file/path to the local host.)");
Daniel Maleae0f8f572013-08-26 23:57:52 +0000781
Kate Stoneb9c1b512016-09-06 20:57:50 +0000782 CommandArgumentEntry arg1, arg2;
783 CommandArgumentData file_arg_remote, file_arg_host;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000784
Kate Stoneb9c1b512016-09-06 20:57:50 +0000785 // Define the first (and only) variant of this arg.
786 file_arg_remote.arg_type = eArgTypeFilename;
787 file_arg_remote.arg_repetition = eArgRepeatPlain;
788 // There is only one variant this argument could be; put it into the
789 // argument entry.
790 arg1.push_back(file_arg_remote);
791
792 // Define the second (and only) variant of this arg.
793 file_arg_host.arg_type = eArgTypeFilename;
794 file_arg_host.arg_repetition = eArgRepeatPlain;
795 // There is only one variant this argument could be; put it into the
796 // argument entry.
797 arg2.push_back(file_arg_host);
798
Adrian Prantl05097242018-04-30 16:49:04 +0000799 // Push the data for the first and the second arguments into the
800 // m_arguments vector.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000801 m_arguments.push_back(arg1);
802 m_arguments.push_back(arg2);
803 }
804
805 ~CommandObjectPlatformGetFile() override = default;
806
807 bool DoExecute(Args &args, CommandReturnObject &result) override {
808 // If the number of arguments is incorrect, issue an error message.
809 if (args.GetArgumentCount() != 2) {
810 result.GetErrorStream().Printf("error: required arguments missing; "
811 "specify both the source and destination "
812 "file paths\n");
813 result.SetStatus(eReturnStatusFailed);
814 return false;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000815 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000816
Kate Stoneb9c1b512016-09-06 20:57:50 +0000817 PlatformSP platform_sp(
Jonas Devlieghere57179862019-04-27 06:19:42 +0000818 GetDebugger().GetPlatformList().GetSelectedPlatform());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000819 if (platform_sp) {
820 const char *remote_file_path = args.GetArgumentAtIndex(0);
821 const char *local_file_path = args.GetArgumentAtIndex(1);
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000822 Status error = platform_sp->GetFile(FileSpec(remote_file_path),
823 FileSpec(local_file_path));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000824 if (error.Success()) {
825 result.AppendMessageWithFormat(
826 "successfully get-file from %s (remote) to %s (host)\n",
827 remote_file_path, local_file_path);
828 result.SetStatus(eReturnStatusSuccessFinishResult);
829 } else {
830 result.AppendMessageWithFormat("get-file failed: %s\n",
831 error.AsCString());
832 result.SetStatus(eReturnStatusFailed);
833 }
834 } else {
835 result.AppendError("no platform currently selected\n");
836 result.SetStatus(eReturnStatusFailed);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000837 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000838 return result.Succeeded();
839 }
Daniel Maleae0f8f572013-08-26 23:57:52 +0000840};
841
Daniel Maleae0f8f572013-08-26 23:57:52 +0000842// "platform get-size remote-file-path"
Kate Stoneb9c1b512016-09-06 20:57:50 +0000843class CommandObjectPlatformGetSize : public CommandObjectParsed {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000844public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000845 CommandObjectPlatformGetSize(CommandInterpreter &interpreter)
846 : CommandObjectParsed(interpreter, "platform get-size",
847 "Get the file size from the remote end.",
848 "platform get-size <remote-file-spec>", 0) {
849 SetHelpLong(
850 R"(Examples:
Kate Stoneea671fb2015-07-14 05:48:36 +0000851
852(lldb) platform get-size /the/remote/file/path
853
Kate Stoneb9c1b512016-09-06 20:57:50 +0000854 Get the file size from the remote end with path /the/remote/file/path.)");
Daniel Maleae0f8f572013-08-26 23:57:52 +0000855
Kate Stoneb9c1b512016-09-06 20:57:50 +0000856 CommandArgumentEntry arg1;
857 CommandArgumentData file_arg_remote;
858
859 // Define the first (and only) variant of this arg.
860 file_arg_remote.arg_type = eArgTypeFilename;
861 file_arg_remote.arg_repetition = eArgRepeatPlain;
862 // There is only one variant this argument could be; put it into the
863 // argument entry.
864 arg1.push_back(file_arg_remote);
865
866 // Push the data for the first argument into the m_arguments vector.
867 m_arguments.push_back(arg1);
868 }
869
870 ~CommandObjectPlatformGetSize() override = default;
871
872 bool DoExecute(Args &args, CommandReturnObject &result) override {
873 // If the number of arguments is incorrect, issue an error message.
874 if (args.GetArgumentCount() != 1) {
875 result.GetErrorStream().Printf("error: required argument missing; "
876 "specify the source file path as the only "
877 "argument\n");
878 result.SetStatus(eReturnStatusFailed);
879 return false;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000880 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000881
Kate Stoneb9c1b512016-09-06 20:57:50 +0000882 PlatformSP platform_sp(
Jonas Devlieghere57179862019-04-27 06:19:42 +0000883 GetDebugger().GetPlatformList().GetSelectedPlatform());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000884 if (platform_sp) {
885 std::string remote_file_path(args.GetArgumentAtIndex(0));
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000886 user_id_t size = platform_sp->GetFileSize(FileSpec(remote_file_path));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000887 if (size != UINT64_MAX) {
888 result.AppendMessageWithFormat("File size of %s (remote): %" PRIu64
889 "\n",
890 remote_file_path.c_str(), size);
891 result.SetStatus(eReturnStatusSuccessFinishResult);
892 } else {
893 result.AppendMessageWithFormat(
894 "Error getting file size of %s (remote)\n",
895 remote_file_path.c_str());
896 result.SetStatus(eReturnStatusFailed);
897 }
898 } else {
899 result.AppendError("no platform currently selected\n");
900 result.SetStatus(eReturnStatusFailed);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000901 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000902 return result.Succeeded();
903 }
Daniel Maleae0f8f572013-08-26 23:57:52 +0000904};
905
Daniel Maleae0f8f572013-08-26 23:57:52 +0000906// "platform put-file"
Kate Stoneb9c1b512016-09-06 20:57:50 +0000907class CommandObjectPlatformPutFile : public CommandObjectParsed {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000908public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000909 CommandObjectPlatformPutFile(CommandInterpreter &interpreter)
910 : CommandObjectParsed(
911 interpreter, "platform put-file",
912 "Transfer a file from this system to the remote end.", nullptr, 0) {
913 }
914
915 ~CommandObjectPlatformPutFile() override = default;
916
917 bool DoExecute(Args &args, CommandReturnObject &result) override {
918 const char *src = args.GetArgumentAtIndex(0);
919 const char *dst = args.GetArgumentAtIndex(1);
920
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +0000921 FileSpec src_fs(src);
922 FileSystem::Instance().Resolve(src_fs);
923 FileSpec dst_fs(dst ? dst : src_fs.GetFilename().GetCString());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000924
925 PlatformSP platform_sp(
Jonas Devlieghere57179862019-04-27 06:19:42 +0000926 GetDebugger().GetPlatformList().GetSelectedPlatform());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000927 if (platform_sp) {
Zachary Turner97206d52017-05-12 04:51:55 +0000928 Status error(platform_sp->PutFile(src_fs, dst_fs));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000929 if (error.Success()) {
930 result.SetStatus(eReturnStatusSuccessFinishNoResult);
931 } else {
932 result.AppendError(error.AsCString());
933 result.SetStatus(eReturnStatusFailed);
934 }
935 } else {
936 result.AppendError("no platform currently selected\n");
937 result.SetStatus(eReturnStatusFailed);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000938 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000939 return result.Succeeded();
940 }
Daniel Maleae0f8f572013-08-26 23:57:52 +0000941};
942
Greg Clayton8b82f082011-04-12 05:54:46 +0000943// "platform process launch"
Kate Stoneb9c1b512016-09-06 20:57:50 +0000944class CommandObjectPlatformProcessLaunch : public CommandObjectParsed {
Greg Clayton8b82f082011-04-12 05:54:46 +0000945public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000946 CommandObjectPlatformProcessLaunch(CommandInterpreter &interpreter)
947 : CommandObjectParsed(interpreter, "platform process launch",
948 "Launch a new process on a remote platform.",
949 "platform process launch program",
950 eCommandRequiresTarget | eCommandTryTargetAPILock),
951 m_options() {}
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000952
Kate Stoneb9c1b512016-09-06 20:57:50 +0000953 ~CommandObjectPlatformProcessLaunch() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000954
Kate Stoneb9c1b512016-09-06 20:57:50 +0000955 Options *GetOptions() override { return &m_options; }
956
Jim Ingham5a988412012-06-08 21:56:10 +0000957protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000958 bool DoExecute(Args &args, CommandReturnObject &result) override {
Jonas Devlieghere57179862019-04-27 06:19:42 +0000959 Target *target = GetDebugger().GetSelectedTarget().get();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000960 PlatformSP platform_sp;
961 if (target) {
962 platform_sp = target->GetPlatform();
963 }
964 if (!platform_sp) {
Jonas Devlieghere57179862019-04-27 06:19:42 +0000965 platform_sp = GetDebugger().GetPlatformList().GetSelectedPlatform();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000966 }
Jason Molenda8c1157c2013-04-05 02:59:09 +0000967
Kate Stoneb9c1b512016-09-06 20:57:50 +0000968 if (platform_sp) {
Zachary Turner97206d52017-05-12 04:51:55 +0000969 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000970 const size_t argc = args.GetArgumentCount();
971 Target *target = m_exe_ctx.GetTargetPtr();
972 Module *exe_module = target->GetExecutableModulePointer();
973 if (exe_module) {
974 m_options.launch_info.GetExecutableFile() = exe_module->GetFileSpec();
Stella Stamenovab3f44ad2018-12-10 17:23:28 +0000975 llvm::SmallString<128> exe_path;
Zachary Turnerecbb0bb2016-09-19 17:54:06 +0000976 m_options.launch_info.GetExecutableFile().GetPath(exe_path);
977 if (!exe_path.empty())
Kate Stoneb9c1b512016-09-06 20:57:50 +0000978 m_options.launch_info.GetArguments().AppendArgument(exe_path);
979 m_options.launch_info.GetArchitecture() = exe_module->GetArchitecture();
980 }
Greg Clayton8b82f082011-04-12 05:54:46 +0000981
Kate Stoneb9c1b512016-09-06 20:57:50 +0000982 if (argc > 0) {
983 if (m_options.launch_info.GetExecutableFile()) {
Adrian Prantl05097242018-04-30 16:49:04 +0000984 // We already have an executable file, so we will use this and all
985 // arguments to this function are extra arguments
Kate Stoneb9c1b512016-09-06 20:57:50 +0000986 m_options.launch_info.GetArguments().AppendArguments(args);
987 } else {
988 // We don't have any file yet, so the first argument is our
989 // executable, and the rest are program arguments
990 const bool first_arg_is_executable = true;
991 m_options.launch_info.SetArguments(args, first_arg_is_executable);
Greg Clayton8b82f082011-04-12 05:54:46 +0000992 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000993 }
994
995 if (m_options.launch_info.GetExecutableFile()) {
Jonas Devlieghere57179862019-04-27 06:19:42 +0000996 Debugger &debugger = GetDebugger();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000997
998 if (argc == 0)
999 target->GetRunArguments(m_options.launch_info.GetArguments());
1000
1001 ProcessSP process_sp(platform_sp->DebugProcess(
1002 m_options.launch_info, debugger, target, error));
1003 if (process_sp && process_sp->IsAlive()) {
1004 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1005 return true;
1006 }
1007
1008 if (error.Success())
1009 result.AppendError("process launch failed");
Greg Clayton8b82f082011-04-12 05:54:46 +00001010 else
Kate Stoneb9c1b512016-09-06 20:57:50 +00001011 result.AppendError(error.AsCString());
1012 result.SetStatus(eReturnStatusFailed);
1013 } else {
1014 result.AppendError("'platform process launch' uses the current target "
1015 "file and arguments, or the executable and its "
1016 "arguments can be specified in this command");
1017 result.SetStatus(eReturnStatusFailed);
1018 return false;
1019 }
1020 } else {
1021 result.AppendError("no platform is selected\n");
Greg Clayton8b82f082011-04-12 05:54:46 +00001022 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001023 return result.Succeeded();
1024 }
1025
Greg Clayton8b82f082011-04-12 05:54:46 +00001026protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001027 ProcessLaunchCommandOptions m_options;
Greg Clayton8b82f082011-04-12 05:54:46 +00001028};
1029
Greg Clayton32e0a752011-03-30 18:16:51 +00001030// "platform process list"
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001031
Raphael Isemann0ab0bb92019-07-26 11:46:21 +00001032static PosixPlatformCommandOptionValidator posix_validator;
Raphael Isemann2359fec2019-07-24 12:05:42 +00001033#define LLDB_OPTIONS_platform_process_list
1034#include "CommandOptions.inc"
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001035
Kate Stoneb9c1b512016-09-06 20:57:50 +00001036class CommandObjectPlatformProcessList : public CommandObjectParsed {
Greg Clayton32e0a752011-03-30 18:16:51 +00001037public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001038 CommandObjectPlatformProcessList(CommandInterpreter &interpreter)
1039 : CommandObjectParsed(interpreter, "platform process list",
1040 "List processes on a remote platform by name, pid, "
1041 "or many other matching attributes.",
1042 "platform process list", 0),
1043 m_options() {}
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001044
Kate Stoneb9c1b512016-09-06 20:57:50 +00001045 ~CommandObjectPlatformProcessList() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001046
Kate Stoneb9c1b512016-09-06 20:57:50 +00001047 Options *GetOptions() override { return &m_options; }
1048
Jim Ingham5a988412012-06-08 21:56:10 +00001049protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001050 bool DoExecute(Args &args, CommandReturnObject &result) override {
Jonas Devlieghere57179862019-04-27 06:19:42 +00001051 Target *target = GetDebugger().GetSelectedTarget().get();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001052 PlatformSP platform_sp;
1053 if (target) {
1054 platform_sp = target->GetPlatform();
Greg Clayton32e0a752011-03-30 18:16:51 +00001055 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001056 if (!platform_sp) {
Jonas Devlieghere57179862019-04-27 06:19:42 +00001057 platform_sp = GetDebugger().GetPlatformList().GetSelectedPlatform();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001058 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001059
Kate Stoneb9c1b512016-09-06 20:57:50 +00001060 if (platform_sp) {
Zachary Turner97206d52017-05-12 04:51:55 +00001061 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001062 if (args.GetArgumentCount() == 0) {
1063 if (platform_sp) {
1064 Stream &ostrm = result.GetOutputStream();
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001065
Kate Stoneb9c1b512016-09-06 20:57:50 +00001066 lldb::pid_t pid =
1067 m_options.match_info.GetProcessInfo().GetProcessID();
1068 if (pid != LLDB_INVALID_PROCESS_ID) {
1069 ProcessInstanceInfo proc_info;
1070 if (platform_sp->GetProcessInfo(pid, proc_info)) {
Pavel Labathaa51e6a2019-03-04 18:48:00 +00001071 ProcessInstanceInfo::DumpTableHeader(ostrm, m_options.show_args,
Kate Stoneb9c1b512016-09-06 20:57:50 +00001072 m_options.verbose);
Pavel Labathaa51e6a2019-03-04 18:48:00 +00001073 proc_info.DumpAsTableRow(ostrm, platform_sp->GetUserIDResolver(),
Kate Stoneb9c1b512016-09-06 20:57:50 +00001074 m_options.show_args, m_options.verbose);
1075 result.SetStatus(eReturnStatusSuccessFinishResult);
1076 } else {
1077 result.AppendErrorWithFormat(
1078 "no process found with pid = %" PRIu64 "\n", pid);
1079 result.SetStatus(eReturnStatusFailed);
Greg Clayton32e0a752011-03-30 18:16:51 +00001080 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001081 } else {
1082 ProcessInstanceInfoList proc_infos;
1083 const uint32_t matches =
1084 platform_sp->FindProcesses(m_options.match_info, proc_infos);
1085 const char *match_desc = nullptr;
1086 const char *match_name =
1087 m_options.match_info.GetProcessInfo().GetName();
1088 if (match_name && match_name[0]) {
1089 switch (m_options.match_info.GetNameMatchType()) {
Pavel Labathc4a33952017-02-20 11:35:33 +00001090 case NameMatch::Ignore:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001091 break;
Pavel Labathc4a33952017-02-20 11:35:33 +00001092 case NameMatch::Equals:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001093 match_desc = "matched";
1094 break;
Pavel Labathc4a33952017-02-20 11:35:33 +00001095 case NameMatch::Contains:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001096 match_desc = "contained";
1097 break;
Pavel Labathc4a33952017-02-20 11:35:33 +00001098 case NameMatch::StartsWith:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001099 match_desc = "started with";
1100 break;
Pavel Labathc4a33952017-02-20 11:35:33 +00001101 case NameMatch::EndsWith:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001102 match_desc = "ended with";
1103 break;
Pavel Labathc4a33952017-02-20 11:35:33 +00001104 case NameMatch::RegularExpression:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001105 match_desc = "matched the regular expression";
1106 break;
1107 }
1108 }
Greg Clayton1cf2aa82016-03-24 21:49:22 +00001109
Kate Stoneb9c1b512016-09-06 20:57:50 +00001110 if (matches == 0) {
1111 if (match_desc)
1112 result.AppendErrorWithFormat(
1113 "no processes were found that %s \"%s\" on the \"%s\" "
1114 "platform\n",
1115 match_desc, match_name,
1116 platform_sp->GetPluginName().GetCString());
1117 else
1118 result.AppendErrorWithFormat(
1119 "no processes were found on the \"%s\" platform\n",
1120 platform_sp->GetPluginName().GetCString());
1121 result.SetStatus(eReturnStatusFailed);
1122 } else {
1123 result.AppendMessageWithFormat(
1124 "%u matching process%s found on \"%s\"", matches,
1125 matches > 1 ? "es were" : " was",
1126 platform_sp->GetName().GetCString());
1127 if (match_desc)
1128 result.AppendMessageWithFormat(" whose name %s \"%s\"",
1129 match_desc, match_name);
1130 result.AppendMessageWithFormat("\n");
Pavel Labathaa51e6a2019-03-04 18:48:00 +00001131 ProcessInstanceInfo::DumpTableHeader(ostrm, m_options.show_args,
Kate Stoneb9c1b512016-09-06 20:57:50 +00001132 m_options.verbose);
1133 for (uint32_t i = 0; i < matches; ++i) {
1134 proc_infos.GetProcessInfoAtIndex(i).DumpAsTableRow(
Pavel Labathaa51e6a2019-03-04 18:48:00 +00001135 ostrm, platform_sp->GetUserIDResolver(),
1136 m_options.show_args, m_options.verbose);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001137 }
1138 }
1139 }
1140 }
1141 } else {
1142 result.AppendError("invalid args: process list takes only options\n");
1143 result.SetStatus(eReturnStatusFailed);
1144 }
1145 } else {
1146 result.AppendError("no platform is selected\n");
1147 result.SetStatus(eReturnStatusFailed);
1148 }
1149 return result.Succeeded();
1150 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001151
Kate Stoneb9c1b512016-09-06 20:57:50 +00001152 class CommandOptions : public Options {
1153 public:
1154 CommandOptions()
1155 : Options(), match_info(), show_args(false), verbose(false) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001156 }
1157
1158 ~CommandOptions() override = default;
1159
Zachary Turner97206d52017-05-12 04:51:55 +00001160 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1161 ExecutionContext *execution_context) override {
1162 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001163 const int short_option = m_getopt_table[option_idx].val;
1164 bool success = false;
1165
Zachary Turnerfe114832016-11-12 16:56:47 +00001166 uint32_t id = LLDB_INVALID_PROCESS_ID;
1167 success = !option_arg.getAsInteger(0, id);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001168 switch (short_option) {
Zachary Turnerfe114832016-11-12 16:56:47 +00001169 case 'p': {
1170 match_info.GetProcessInfo().SetProcessID(id);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001171 if (!success)
1172 error.SetErrorStringWithFormat("invalid process ID string: '%s'",
Zachary Turnerfe114832016-11-12 16:56:47 +00001173 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001174 break;
Zachary Turnerfe114832016-11-12 16:56:47 +00001175 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001176 case 'P':
Zachary Turnerfe114832016-11-12 16:56:47 +00001177 match_info.GetProcessInfo().SetParentProcessID(id);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001178 if (!success)
1179 error.SetErrorStringWithFormat(
Zachary Turnerfe114832016-11-12 16:56:47 +00001180 "invalid parent process ID string: '%s'",
1181 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001182 break;
1183
1184 case 'u':
Zachary Turnerfe114832016-11-12 16:56:47 +00001185 match_info.GetProcessInfo().SetUserID(success ? id : UINT32_MAX);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001186 if (!success)
1187 error.SetErrorStringWithFormat("invalid user ID string: '%s'",
Zachary Turnerfe114832016-11-12 16:56:47 +00001188 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001189 break;
1190
1191 case 'U':
Zachary Turnerfe114832016-11-12 16:56:47 +00001192 match_info.GetProcessInfo().SetEffectiveUserID(success ? id
1193 : UINT32_MAX);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001194 if (!success)
1195 error.SetErrorStringWithFormat(
Zachary Turnerfe114832016-11-12 16:56:47 +00001196 "invalid effective user ID string: '%s'",
1197 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001198 break;
1199
1200 case 'g':
Zachary Turnerfe114832016-11-12 16:56:47 +00001201 match_info.GetProcessInfo().SetGroupID(success ? id : UINT32_MAX);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001202 if (!success)
1203 error.SetErrorStringWithFormat("invalid group ID string: '%s'",
Zachary Turnerfe114832016-11-12 16:56:47 +00001204 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001205 break;
1206
1207 case 'G':
Zachary Turnerfe114832016-11-12 16:56:47 +00001208 match_info.GetProcessInfo().SetEffectiveGroupID(success ? id
1209 : UINT32_MAX);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001210 if (!success)
1211 error.SetErrorStringWithFormat(
Zachary Turnerfe114832016-11-12 16:56:47 +00001212 "invalid effective group ID string: '%s'",
1213 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001214 break;
1215
1216 case 'a': {
1217 TargetSP target_sp =
1218 execution_context ? execution_context->GetTargetSP() : TargetSP();
1219 DebuggerSP debugger_sp =
1220 target_sp ? target_sp->GetDebugger().shared_from_this()
1221 : DebuggerSP();
1222 PlatformSP platform_sp =
1223 debugger_sp ? debugger_sp->GetPlatformList().GetSelectedPlatform()
1224 : PlatformSP();
Pavel Labath7263f1b2017-10-31 10:56:03 +00001225 match_info.GetProcessInfo().GetArchitecture() =
1226 Platform::GetAugmentedArchSpec(platform_sp.get(), option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001227 } break;
1228
1229 case 'n':
Jonas Devlieghere937348c2018-06-13 22:08:14 +00001230 match_info.GetProcessInfo().GetExecutableFile().SetFile(
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +00001231 option_arg, FileSpec::Style::native);
Pavel Labathc4a33952017-02-20 11:35:33 +00001232 match_info.SetNameMatchType(NameMatch::Equals);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001233 break;
1234
1235 case 'e':
Jonas Devlieghere937348c2018-06-13 22:08:14 +00001236 match_info.GetProcessInfo().GetExecutableFile().SetFile(
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +00001237 option_arg, FileSpec::Style::native);
Pavel Labathc4a33952017-02-20 11:35:33 +00001238 match_info.SetNameMatchType(NameMatch::EndsWith);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001239 break;
1240
1241 case 's':
Jonas Devlieghere937348c2018-06-13 22:08:14 +00001242 match_info.GetProcessInfo().GetExecutableFile().SetFile(
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +00001243 option_arg, FileSpec::Style::native);
Pavel Labathc4a33952017-02-20 11:35:33 +00001244 match_info.SetNameMatchType(NameMatch::StartsWith);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001245 break;
1246
1247 case 'c':
Jonas Devlieghere937348c2018-06-13 22:08:14 +00001248 match_info.GetProcessInfo().GetExecutableFile().SetFile(
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +00001249 option_arg, FileSpec::Style::native);
Pavel Labathc4a33952017-02-20 11:35:33 +00001250 match_info.SetNameMatchType(NameMatch::Contains);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001251 break;
1252
1253 case 'r':
Jonas Devlieghere937348c2018-06-13 22:08:14 +00001254 match_info.GetProcessInfo().GetExecutableFile().SetFile(
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +00001255 option_arg, FileSpec::Style::native);
Pavel Labathc4a33952017-02-20 11:35:33 +00001256 match_info.SetNameMatchType(NameMatch::RegularExpression);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001257 break;
1258
1259 case 'A':
1260 show_args = true;
1261 break;
1262
1263 case 'v':
1264 verbose = true;
1265 break;
1266
1267 default:
Raphael Isemann36162012019-08-22 08:08:05 +00001268 llvm_unreachable("Unimplemented option");
Kate Stoneb9c1b512016-09-06 20:57:50 +00001269 }
1270
1271 return error;
1272 }
1273
1274 void OptionParsingStarting(ExecutionContext *execution_context) override {
1275 match_info.Clear();
1276 show_args = false;
1277 verbose = false;
1278 }
1279
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001280 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001281 return llvm::makeArrayRef(g_platform_process_list_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001282 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001283
1284 // Instance variables to hold the values for command options.
1285
1286 ProcessInstanceInfoMatch match_info;
1287 bool show_args;
1288 bool verbose;
1289 };
1290
1291 CommandOptions m_options;
Greg Clayton32e0a752011-03-30 18:16:51 +00001292};
1293
Greg Clayton95bf0fd2011-04-01 00:29:43 +00001294// "platform process info"
Kate Stoneb9c1b512016-09-06 20:57:50 +00001295class CommandObjectPlatformProcessInfo : public CommandObjectParsed {
Greg Clayton95bf0fd2011-04-01 00:29:43 +00001296public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001297 CommandObjectPlatformProcessInfo(CommandInterpreter &interpreter)
1298 : CommandObjectParsed(
1299 interpreter, "platform process info",
1300 "Get detailed information for one or more process by process ID.",
1301 "platform process info <pid> [<pid> <pid> ...]", 0) {
1302 CommandArgumentEntry arg;
1303 CommandArgumentData pid_args;
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001304
Kate Stoneb9c1b512016-09-06 20:57:50 +00001305 // Define the first (and only) variant of this arg.
1306 pid_args.arg_type = eArgTypePid;
1307 pid_args.arg_repetition = eArgRepeatStar;
1308
1309 // There is only one variant this argument could be; put it into the
1310 // argument entry.
1311 arg.push_back(pid_args);
1312
1313 // Push the data for the first argument into the m_arguments vector.
1314 m_arguments.push_back(arg);
1315 }
1316
1317 ~CommandObjectPlatformProcessInfo() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001318
Jim Ingham5a988412012-06-08 21:56:10 +00001319protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001320 bool DoExecute(Args &args, CommandReturnObject &result) override {
Jonas Devlieghere57179862019-04-27 06:19:42 +00001321 Target *target = GetDebugger().GetSelectedTarget().get();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001322 PlatformSP platform_sp;
1323 if (target) {
1324 platform_sp = target->GetPlatform();
Greg Clayton95bf0fd2011-04-01 00:29:43 +00001325 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001326 if (!platform_sp) {
Jonas Devlieghere57179862019-04-27 06:19:42 +00001327 platform_sp = GetDebugger().GetPlatformList().GetSelectedPlatform();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001328 }
1329
1330 if (platform_sp) {
1331 const size_t argc = args.GetArgumentCount();
1332 if (argc > 0) {
Zachary Turner97206d52017-05-12 04:51:55 +00001333 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001334
1335 if (platform_sp->IsConnected()) {
1336 Stream &ostrm = result.GetOutputStream();
Zachary Turner97d2c402016-10-05 23:40:23 +00001337 for (auto &entry : args.entries()) {
1338 lldb::pid_t pid;
1339 if (entry.ref.getAsInteger(0, pid)) {
1340 result.AppendErrorWithFormat("invalid process ID argument '%s'",
1341 entry.ref.str().c_str());
1342 result.SetStatus(eReturnStatusFailed);
1343 break;
1344 } else {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001345 ProcessInstanceInfo proc_info;
1346 if (platform_sp->GetProcessInfo(pid, proc_info)) {
1347 ostrm.Printf("Process information for process %" PRIu64 ":\n",
1348 pid);
Pavel Labathaa51e6a2019-03-04 18:48:00 +00001349 proc_info.Dump(ostrm, platform_sp->GetUserIDResolver());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001350 } else {
1351 ostrm.Printf("error: no process information is available for "
1352 "process %" PRIu64 "\n",
1353 pid);
1354 }
1355 ostrm.EOL();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001356 }
1357 }
1358 } else {
1359 // Not connected...
1360 result.AppendErrorWithFormat(
1361 "not connected to '%s'",
1362 platform_sp->GetPluginName().GetCString());
1363 result.SetStatus(eReturnStatusFailed);
1364 }
1365 } else {
1366 // No args
1367 result.AppendError("one or more process id(s) must be specified");
1368 result.SetStatus(eReturnStatusFailed);
1369 }
1370 } else {
1371 result.AppendError("no platform is currently selected");
1372 result.SetStatus(eReturnStatusFailed);
1373 }
1374 return result.Succeeded();
1375 }
Greg Clayton95bf0fd2011-04-01 00:29:43 +00001376};
1377
Raphael Isemann2359fec2019-07-24 12:05:42 +00001378#define LLDB_OPTIONS_platform_process_attach
1379#include "CommandOptions.inc"
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001380
Kate Stoneb9c1b512016-09-06 20:57:50 +00001381class CommandObjectPlatformProcessAttach : public CommandObjectParsed {
Daniel Maleae0f8f572013-08-26 23:57:52 +00001382public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001383 class CommandOptions : public Options {
1384 public:
1385 CommandOptions() : Options() {
1386 // Keep default values of all options in one place: OptionParsingStarting
1387 // ()
1388 OptionParsingStarting(nullptr);
Daniel Maleae0f8f572013-08-26 23:57:52 +00001389 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001390
Kate Stoneb9c1b512016-09-06 20:57:50 +00001391 ~CommandOptions() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001392
Zachary Turner97206d52017-05-12 04:51:55 +00001393 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1394 ExecutionContext *execution_context) override {
1395 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001396 char short_option = (char)m_getopt_table[option_idx].val;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001397 switch (short_option) {
1398 case 'p': {
Zachary Turnerfe114832016-11-12 16:56:47 +00001399 lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
1400 if (option_arg.getAsInteger(0, pid)) {
1401 error.SetErrorStringWithFormat("invalid process ID '%s'",
1402 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001403 } else {
1404 attach_info.SetProcessID(pid);
Daniel Maleae0f8f572013-08-26 23:57:52 +00001405 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001406 } break;
1407
1408 case 'P':
1409 attach_info.SetProcessPluginName(option_arg);
1410 break;
1411
1412 case 'n':
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +00001413 attach_info.GetExecutableFile().SetFile(option_arg,
Jonas Devlieghere937348c2018-06-13 22:08:14 +00001414 FileSpec::Style::native);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001415 break;
1416
1417 case 'w':
1418 attach_info.SetWaitForLaunch(true);
1419 break;
1420
1421 default:
Raphael Isemann36162012019-08-22 08:08:05 +00001422 llvm_unreachable("Unimplemented option");
Kate Stoneb9c1b512016-09-06 20:57:50 +00001423 }
1424 return error;
1425 }
1426
1427 void OptionParsingStarting(ExecutionContext *execution_context) override {
1428 attach_info.Clear();
1429 }
1430
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001431 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001432 return llvm::makeArrayRef(g_platform_process_attach_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001433 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001434
1435 bool HandleOptionArgumentCompletion(
Raphael Isemanna2e76c02018-07-13 18:28:14 +00001436 CompletionRequest &request, OptionElementVector &opt_element_vector,
1437 int opt_element_index, CommandInterpreter &interpreter) override {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001438 int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
1439 int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
1440
1441 // We are only completing the name option for now...
1442
Raphael Isemann1153dc92019-08-22 09:02:54 +00001443 // Are we in the name?
1444 if (GetDefinitions()[opt_defs_index].short_option != 'n')
1445 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001446
Raphael Isemann1153dc92019-08-22 09:02:54 +00001447 // Look to see if there is a -P argument provided, and if so use that
1448 // plugin, otherwise use the default plugin.
Kate Stoneb9c1b512016-09-06 20:57:50 +00001449
Raphael Isemann1153dc92019-08-22 09:02:54 +00001450 const char *partial_name = nullptr;
1451 partial_name = request.GetParsedLine().GetArgumentAtIndex(opt_arg_pos);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001452
Raphael Isemann1153dc92019-08-22 09:02:54 +00001453 PlatformSP platform_sp(interpreter.GetPlatform(true));
1454 if (!platform_sp)
1455 return false;
1456
1457 ProcessInstanceInfoList process_infos;
1458 ProcessInstanceInfoMatch match_info;
1459 if (partial_name) {
1460 match_info.GetProcessInfo().GetExecutableFile().SetFile(
1461 partial_name, FileSpec::Style::native);
1462 match_info.SetNameMatchType(NameMatch::StartsWith);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001463 }
Raphael Isemann1153dc92019-08-22 09:02:54 +00001464 platform_sp->FindProcesses(match_info, process_infos);
1465 const uint32_t num_matches = process_infos.GetSize();
1466 if (num_matches == 0)
1467 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001468
Raphael Isemann1153dc92019-08-22 09:02:54 +00001469 for (uint32_t i = 0; i < num_matches; ++i) {
1470 request.AddCompletion(
1471 llvm::StringRef(process_infos.GetProcessNameAtIndex(i),
1472 process_infos.GetProcessNameLengthAtIndex(i)));
1473 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001474 return false;
Daniel Maleae0f8f572013-08-26 23:57:52 +00001475 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001476
1477 // Options table: Required for subclasses of Options.
1478
1479 static OptionDefinition g_option_table[];
1480
1481 // Instance variables to hold the values for command options.
1482
1483 ProcessAttachInfo attach_info;
1484 };
1485
1486 CommandObjectPlatformProcessAttach(CommandInterpreter &interpreter)
1487 : CommandObjectParsed(interpreter, "platform process attach",
1488 "Attach to a process.",
1489 "platform process attach <cmd-options>"),
1490 m_options() {}
1491
1492 ~CommandObjectPlatformProcessAttach() override = default;
1493
1494 bool DoExecute(Args &command, CommandReturnObject &result) override {
1495 PlatformSP platform_sp(
Jonas Devlieghere57179862019-04-27 06:19:42 +00001496 GetDebugger().GetPlatformList().GetSelectedPlatform());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001497 if (platform_sp) {
Zachary Turner97206d52017-05-12 04:51:55 +00001498 Status err;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001499 ProcessSP remote_process_sp = platform_sp->Attach(
Jonas Devlieghere57179862019-04-27 06:19:42 +00001500 m_options.attach_info, GetDebugger(), nullptr, err);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001501 if (err.Fail()) {
1502 result.AppendError(err.AsCString());
1503 result.SetStatus(eReturnStatusFailed);
1504 } else if (!remote_process_sp) {
1505 result.AppendError("could not attach: unknown reason");
1506 result.SetStatus(eReturnStatusFailed);
1507 } else
1508 result.SetStatus(eReturnStatusSuccessFinishResult);
1509 } else {
1510 result.AppendError("no platform is currently selected");
1511 result.SetStatus(eReturnStatusFailed);
Daniel Maleae0f8f572013-08-26 23:57:52 +00001512 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001513 return result.Succeeded();
1514 }
1515
1516 Options *GetOptions() override { return &m_options; }
1517
Daniel Maleae0f8f572013-08-26 23:57:52 +00001518protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001519 CommandOptions m_options;
Daniel Maleae0f8f572013-08-26 23:57:52 +00001520};
Greg Clayton95bf0fd2011-04-01 00:29:43 +00001521
Kate Stoneb9c1b512016-09-06 20:57:50 +00001522class CommandObjectPlatformProcess : public CommandObjectMultiword {
Greg Clayton32e0a752011-03-30 18:16:51 +00001523public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001524 // Constructors and Destructors
Kate Stoneb9c1b512016-09-06 20:57:50 +00001525 CommandObjectPlatformProcess(CommandInterpreter &interpreter)
1526 : CommandObjectMultiword(interpreter, "platform process",
1527 "Commands to query, launch and attach to "
1528 "processes on the current platform.",
1529 "platform process [attach|launch|list] ...") {
1530 LoadSubCommand(
1531 "attach",
1532 CommandObjectSP(new CommandObjectPlatformProcessAttach(interpreter)));
1533 LoadSubCommand(
1534 "launch",
1535 CommandObjectSP(new CommandObjectPlatformProcessLaunch(interpreter)));
1536 LoadSubCommand("info", CommandObjectSP(new CommandObjectPlatformProcessInfo(
1537 interpreter)));
1538 LoadSubCommand("list", CommandObjectSP(new CommandObjectPlatformProcessList(
1539 interpreter)));
1540 }
Greg Clayton32e0a752011-03-30 18:16:51 +00001541
Kate Stoneb9c1b512016-09-06 20:57:50 +00001542 ~CommandObjectPlatformProcess() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001543
Greg Clayton32e0a752011-03-30 18:16:51 +00001544private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001545 // For CommandObjectPlatform only
Kate Stoneb9c1b512016-09-06 20:57:50 +00001546 DISALLOW_COPY_AND_ASSIGN(CommandObjectPlatformProcess);
Greg Clayton32e0a752011-03-30 18:16:51 +00001547};
Greg Claytonded470d2011-03-19 01:12:21 +00001548
Daniel Maleae0f8f572013-08-26 23:57:52 +00001549// "platform shell"
Raphael Isemann2359fec2019-07-24 12:05:42 +00001550#define LLDB_OPTIONS_platform_shell
1551#include "CommandOptions.inc"
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001552
Kate Stoneb9c1b512016-09-06 20:57:50 +00001553class CommandObjectPlatformShell : public CommandObjectRaw {
Greg Claytond1cf11a2012-04-14 01:42:46 +00001554public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001555 class CommandOptions : public Options {
1556 public:
Pavel Labath19dd1a02018-05-10 10:46:03 +00001557 CommandOptions() : Options() {}
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001558
Kate Stoneb9c1b512016-09-06 20:57:50 +00001559 ~CommandOptions() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001560
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001561 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001562 return llvm::makeArrayRef(g_platform_shell_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001563 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001564
Zachary Turner97206d52017-05-12 04:51:55 +00001565 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1566 ExecutionContext *execution_context) override {
1567 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001568
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001569 const char short_option = (char)GetDefinitions()[option_idx].short_option;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001570
1571 switch (short_option) {
Zachary Turnerfe114832016-11-12 16:56:47 +00001572 case 't':
Pavel Labath19dd1a02018-05-10 10:46:03 +00001573 uint32_t timeout_sec;
1574 if (option_arg.getAsInteger(10, timeout_sec))
Kate Stoneb9c1b512016-09-06 20:57:50 +00001575 error.SetErrorStringWithFormat(
Zachary Turnerfe114832016-11-12 16:56:47 +00001576 "could not convert \"%s\" to a numeric value.",
1577 option_arg.str().c_str());
Pavel Labath19dd1a02018-05-10 10:46:03 +00001578 else
1579 timeout = std::chrono::seconds(timeout_sec);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001580 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001581 default:
Raphael Isemann36162012019-08-22 08:08:05 +00001582 llvm_unreachable("Unimplemented option");
Kate Stoneb9c1b512016-09-06 20:57:50 +00001583 }
1584
1585 return error;
Greg Claytond1cf11a2012-04-14 01:42:46 +00001586 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001587
Kate Stoneb9c1b512016-09-06 20:57:50 +00001588 void OptionParsingStarting(ExecutionContext *execution_context) override {}
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001589
Pavel Labath19dd1a02018-05-10 10:46:03 +00001590 Timeout<std::micro> timeout = std::chrono::seconds(10);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001591 };
Daniel Maleae0f8f572013-08-26 23:57:52 +00001592
Kate Stoneb9c1b512016-09-06 20:57:50 +00001593 CommandObjectPlatformShell(CommandInterpreter &interpreter)
1594 : CommandObjectRaw(interpreter, "platform shell",
1595 "Run a shell command on the current platform.",
1596 "platform shell <shell-command>", 0),
1597 m_options() {}
Greg Claytond1cf11a2012-04-14 01:42:46 +00001598
Kate Stoneb9c1b512016-09-06 20:57:50 +00001599 ~CommandObjectPlatformShell() override = default;
1600
1601 Options *GetOptions() override { return &m_options; }
1602
Raphael Isemann4d51a902018-07-12 22:28:52 +00001603 bool DoExecute(llvm::StringRef raw_command_line,
Kate Stoneb9c1b512016-09-06 20:57:50 +00001604 CommandReturnObject &result) override {
1605 ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext();
1606 m_options.NotifyOptionParsingStarting(&exe_ctx);
1607
Kate Stoneb9c1b512016-09-06 20:57:50 +00001608
1609 // Print out an usage syntax on an empty command line.
Raphael Isemann4d51a902018-07-12 22:28:52 +00001610 if (raw_command_line.empty()) {
Zachary Turner1e8016b2016-11-15 00:45:18 +00001611 result.GetOutputStream().Printf("%s\n", this->GetSyntax().str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001612 return true;
Greg Claytond1cf11a2012-04-14 01:42:46 +00001613 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001614
Raphael Isemann3a0e1272018-07-10 20:17:38 +00001615 OptionsWithRaw args(raw_command_line);
1616 const char *expr = args.GetRawPart().c_str();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001617
Raphael Isemann3a0e1272018-07-10 20:17:38 +00001618 if (args.HasArgs())
1619 if (!ParseOptions(args.GetArgs(), result))
1620 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001621
1622 PlatformSP platform_sp(
Jonas Devlieghere57179862019-04-27 06:19:42 +00001623 GetDebugger().GetPlatformList().GetSelectedPlatform());
Zachary Turner97206d52017-05-12 04:51:55 +00001624 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001625 if (platform_sp) {
1626 FileSpec working_dir{};
1627 std::string output;
1628 int status = -1;
1629 int signo = -1;
1630 error = (platform_sp->RunShellCommand(expr, working_dir, &status, &signo,
1631 &output, m_options.timeout));
1632 if (!output.empty())
Malcolm Parsons771ef6d2016-11-02 20:34:10 +00001633 result.GetOutputStream().PutCString(output);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001634 if (status > 0) {
1635 if (signo > 0) {
1636 const char *signo_cstr = Host::GetSignalAsCString(signo);
1637 if (signo_cstr)
1638 result.GetOutputStream().Printf(
1639 "error: command returned with status %i and signal %s\n",
1640 status, signo_cstr);
1641 else
1642 result.GetOutputStream().Printf(
1643 "error: command returned with status %i and signal %i\n",
1644 status, signo);
1645 } else
1646 result.GetOutputStream().Printf(
1647 "error: command returned with status %i\n", status);
1648 }
1649 } else {
1650 result.GetOutputStream().Printf(
1651 "error: cannot run remote shell commands without a platform\n");
1652 error.SetErrorString(
1653 "error: cannot run remote shell commands without a platform");
1654 }
1655
1656 if (error.Fail()) {
1657 result.AppendError(error.AsCString());
1658 result.SetStatus(eReturnStatusFailed);
1659 } else {
1660 result.SetStatus(eReturnStatusSuccessFinishResult);
1661 }
1662 return true;
1663 }
1664
1665 CommandOptions m_options;
Daniel Maleae0f8f572013-08-26 23:57:52 +00001666};
1667
Daniel Maleae0f8f572013-08-26 23:57:52 +00001668// "platform install" - install a target to a remote end
Kate Stoneb9c1b512016-09-06 20:57:50 +00001669class CommandObjectPlatformInstall : public CommandObjectParsed {
Daniel Maleae0f8f572013-08-26 23:57:52 +00001670public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001671 CommandObjectPlatformInstall(CommandInterpreter &interpreter)
1672 : CommandObjectParsed(
1673 interpreter, "platform target-install",
1674 "Install a target (bundle or executable file) to the remote end.",
1675 "platform target-install <local-thing> <remote-sandbox>", 0) {}
1676
1677 ~CommandObjectPlatformInstall() override = default;
1678
1679 bool DoExecute(Args &args, CommandReturnObject &result) override {
1680 if (args.GetArgumentCount() != 2) {
1681 result.AppendError("platform target-install takes two arguments");
1682 result.SetStatus(eReturnStatusFailed);
1683 return false;
1684 }
1685 // TODO: move the bulk of this code over to the platform itself
Jonas Devlieghere8f3be7a2018-11-01 21:05:36 +00001686 FileSpec src(args.GetArgumentAtIndex(0));
1687 FileSystem::Instance().Resolve(src);
1688 FileSpec dst(args.GetArgumentAtIndex(1));
Jonas Devliegheredbd7fab2018-11-01 17:09:25 +00001689 if (!FileSystem::Instance().Exists(src)) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001690 result.AppendError("source location does not exist or is not accessible");
1691 result.SetStatus(eReturnStatusFailed);
1692 return false;
1693 }
1694 PlatformSP platform_sp(
Jonas Devlieghere57179862019-04-27 06:19:42 +00001695 GetDebugger().GetPlatformList().GetSelectedPlatform());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001696 if (!platform_sp) {
1697 result.AppendError("no platform currently selected");
1698 result.SetStatus(eReturnStatusFailed);
1699 return false;
Daniel Maleae0f8f572013-08-26 23:57:52 +00001700 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001701
Zachary Turner97206d52017-05-12 04:51:55 +00001702 Status error = platform_sp->Install(src, dst);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001703 if (error.Success()) {
1704 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1705 } else {
1706 result.AppendErrorWithFormat("install failed: %s", error.AsCString());
1707 result.SetStatus(eReturnStatusFailed);
Daniel Maleae0f8f572013-08-26 23:57:52 +00001708 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001709 return result.Succeeded();
1710 }
Greg Claytond1cf11a2012-04-14 01:42:46 +00001711};
1712
Kate Stone7428a182016-07-14 22:03:10 +00001713CommandObjectPlatform::CommandObjectPlatform(CommandInterpreter &interpreter)
Kate Stoneb9c1b512016-09-06 20:57:50 +00001714 : CommandObjectMultiword(
1715 interpreter, "platform", "Commands to manage and create platforms.",
1716 "platform [connect|disconnect|info|list|status|select] ...") {
1717 LoadSubCommand("select",
1718 CommandObjectSP(new CommandObjectPlatformSelect(interpreter)));
1719 LoadSubCommand("list",
1720 CommandObjectSP(new CommandObjectPlatformList(interpreter)));
1721 LoadSubCommand("status",
1722 CommandObjectSP(new CommandObjectPlatformStatus(interpreter)));
1723 LoadSubCommand("connect", CommandObjectSP(
1724 new CommandObjectPlatformConnect(interpreter)));
1725 LoadSubCommand(
1726 "disconnect",
1727 CommandObjectSP(new CommandObjectPlatformDisconnect(interpreter)));
1728 LoadSubCommand("settings", CommandObjectSP(new CommandObjectPlatformSettings(
1729 interpreter)));
1730 LoadSubCommand("mkdir",
1731 CommandObjectSP(new CommandObjectPlatformMkDir(interpreter)));
1732 LoadSubCommand("file",
1733 CommandObjectSP(new CommandObjectPlatformFile(interpreter)));
1734 LoadSubCommand("get-file", CommandObjectSP(new CommandObjectPlatformGetFile(
1735 interpreter)));
1736 LoadSubCommand("get-size", CommandObjectSP(new CommandObjectPlatformGetSize(
1737 interpreter)));
1738 LoadSubCommand("put-file", CommandObjectSP(new CommandObjectPlatformPutFile(
1739 interpreter)));
1740 LoadSubCommand("process", CommandObjectSP(
1741 new CommandObjectPlatformProcess(interpreter)));
1742 LoadSubCommand("shell",
1743 CommandObjectSP(new CommandObjectPlatformShell(interpreter)));
1744 LoadSubCommand(
1745 "target-install",
1746 CommandObjectSP(new CommandObjectPlatformInstall(interpreter)));
Greg Claytonded470d2011-03-19 01:12:21 +00001747}
1748
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001749CommandObjectPlatform::~CommandObjectPlatform() = default;