blob: e4cd5a4d70e877f4f965aa7c94c7c947a13299dc [file] [log] [blame]
Greg Claytonded470d2011-03-19 01:12:21 +00001//===-- CommandObjectPlatform.cpp -------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Greg Claytonded470d2011-03-19 01:12:21 +000010// C Includes
11// C++ Includes
Greg Clayton1cf2aa82016-03-24 21:49:22 +000012#include <mutex>
Greg Claytonded470d2011-03-19 01:12:21 +000013// Other libraries and framework includes
14// Project includes
Eugene Zelenko435c2c92016-02-22 19:02:01 +000015#include "CommandObjectPlatform.h"
Greg Claytonded470d2011-03-19 01:12:21 +000016#include "lldb/Core/DataExtractor.h"
17#include "lldb/Core/Debugger.h"
Greg Clayton1f746072012-08-29 21:13:06 +000018#include "lldb/Core/Module.h"
Greg Claytonded470d2011-03-19 01:12:21 +000019#include "lldb/Core/PluginManager.h"
Vince Harron5275aaa2015-01-15 20:08:35 +000020#include "lldb/Host/StringConvert.h"
Greg Claytonded470d2011-03-19 01:12:21 +000021#include "lldb/Interpreter/Args.h"
22#include "lldb/Interpreter/CommandInterpreter.h"
Zachary Turnerd37221d2014-07-09 16:31:49 +000023#include "lldb/Interpreter/CommandOptionValidators.h"
Greg Claytonded470d2011-03-19 01:12:21 +000024#include "lldb/Interpreter/CommandReturnObject.h"
Greg Claytonfbb76342013-11-20 21:07:01 +000025#include "lldb/Interpreter/OptionGroupFile.h"
Greg Clayton7260f622011-04-18 08:33:37 +000026#include "lldb/Interpreter/OptionGroupPlatform.h"
Greg Claytonded470d2011-03-19 01:12:21 +000027#include "lldb/Target/ExecutionContext.h"
28#include "lldb/Target/Platform.h"
Greg Claytoneb0103f2011-04-07 22:46:35 +000029#include "lldb/Target/Process.h"
Daniel Maleae0f8f572013-08-26 23:57:52 +000030#include "lldb/Utility/Utils.h"
Greg Claytonded470d2011-03-19 01:12:21 +000031
Zachary Turnerecbb0bb2016-09-19 17:54:06 +000032#include "llvm/ADT/SmallString.h"
33
Greg Claytonded470d2011-03-19 01:12:21 +000034using namespace lldb;
35using namespace lldb_private;
36
Zachary Turner8cef4b02016-09-23 17:48:13 +000037static mode_t ParsePermissionString(const char *) = delete;
38
39static mode_t ParsePermissionString(llvm::StringRef permissions) {
40 if (permissions.size() != 9)
Kate Stoneb9c1b512016-09-06 20:57:50 +000041 return (mode_t)(-1);
42 bool user_r, user_w, user_x, group_r, group_w, group_x, world_r, world_w,
43 world_x;
44
45 user_r = (permissions[0] == 'r');
46 user_w = (permissions[1] == 'w');
47 user_x = (permissions[2] == 'x');
48
49 group_r = (permissions[3] == 'r');
50 group_w = (permissions[4] == 'w');
51 group_x = (permissions[5] == 'x');
52
53 world_r = (permissions[6] == 'r');
54 world_w = (permissions[7] == 'w');
55 world_x = (permissions[8] == 'x');
56
57 mode_t user, group, world;
58 user = (user_r ? 4 : 0) | (user_w ? 2 : 0) | (user_x ? 1 : 0);
59 group = (group_r ? 4 : 0) | (group_w ? 2 : 0) | (group_x ? 1 : 0);
60 world = (world_r ? 4 : 0) | (world_w ? 2 : 0) | (world_x ? 1 : 0);
61
62 return user | group | world;
Daniel Maleae0f8f572013-08-26 23:57:52 +000063}
64
Kate Stoneb9c1b512016-09-06 20:57:50 +000065static OptionDefinition g_permissions_options[] = {
66 // clang-format off
Kate Stoneac9c3a62016-08-26 23:28:47 +000067 {LLDB_OPT_SET_ALL, false, "permissions-value", 'v', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePermissionsNumber, "Give out the numeric value for permissions (e.g. 757)"},
68 {LLDB_OPT_SET_ALL, false, "permissions-string", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePermissionsString, "Give out the string value for permissions (e.g. rwxr-xr--)."},
69 {LLDB_OPT_SET_ALL, false, "user-read", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow user to read."},
70 {LLDB_OPT_SET_ALL, false, "user-write", 'w', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow user to write."},
71 {LLDB_OPT_SET_ALL, false, "user-exec", 'x', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow user to execute."},
72 {LLDB_OPT_SET_ALL, false, "group-read", 'R', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow group to read."},
73 {LLDB_OPT_SET_ALL, false, "group-write", 'W', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow group to write."},
74 {LLDB_OPT_SET_ALL, false, "group-exec", 'X', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow group to execute."},
75 {LLDB_OPT_SET_ALL, false, "world-read", 'd', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow world to read."},
76 {LLDB_OPT_SET_ALL, false, "world-write", 't', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow world to write."},
77 {LLDB_OPT_SET_ALL, false, "world-exec", 'e', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow world to execute."},
Kate Stoneb9c1b512016-09-06 20:57:50 +000078 // clang-format on
Daniel Maleae0f8f572013-08-26 23:57:52 +000079};
80
Zachary Turner8cef4b02016-09-23 17:48:13 +000081class OptionPermissions : public OptionGroup {
Daniel Maleae0f8f572013-08-26 23:57:52 +000082public:
Kate Stoneb9c1b512016-09-06 20:57:50 +000083 OptionPermissions() {}
84
85 ~OptionPermissions() override = default;
86
87 lldb_private::Error
Zachary Turner8cef4b02016-09-23 17:48:13 +000088 SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
Kate Stoneb9c1b512016-09-06 20:57:50 +000089 ExecutionContext *execution_context) override {
90 Error error;
91 char short_option = (char)GetDefinitions()[option_idx].short_option;
92 switch (short_option) {
93 case 'v': {
Zachary Turner8cef4b02016-09-23 17:48:13 +000094 if (option_arg.getAsInteger(8, m_permissions)) {
95 m_permissions = 0777;
Kate Stoneb9c1b512016-09-06 20:57:50 +000096 error.SetErrorStringWithFormat("invalid value for permissions: %s",
Zachary Turner8cef4b02016-09-23 17:48:13 +000097 option_arg.str().c_str());
98 }
99
Kate Stoneb9c1b512016-09-06 20:57:50 +0000100 } break;
101 case 's': {
102 mode_t perms = ParsePermissionString(option_arg);
103 if (perms == (mode_t)-1)
104 error.SetErrorStringWithFormat("invalid value for permissions: %s",
Zachary Turner8cef4b02016-09-23 17:48:13 +0000105 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000106 else
107 m_permissions = perms;
108 } break;
109 case 'r':
110 m_permissions |= lldb::eFilePermissionsUserRead;
111 break;
112 case 'w':
113 m_permissions |= lldb::eFilePermissionsUserWrite;
114 break;
115 case 'x':
116 m_permissions |= lldb::eFilePermissionsUserExecute;
117 break;
118 case 'R':
119 m_permissions |= lldb::eFilePermissionsGroupRead;
120 break;
121 case 'W':
122 m_permissions |= lldb::eFilePermissionsGroupWrite;
123 break;
124 case 'X':
125 m_permissions |= lldb::eFilePermissionsGroupExecute;
126 break;
127 case 'd':
128 m_permissions |= lldb::eFilePermissionsWorldRead;
129 break;
130 case 't':
131 m_permissions |= lldb::eFilePermissionsWorldWrite;
132 break;
133 case 'e':
134 m_permissions |= lldb::eFilePermissionsWorldExecute;
135 break;
136 default:
137 error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
138 break;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000139 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000140
Kate Stoneb9c1b512016-09-06 20:57:50 +0000141 return error;
142 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000143
Kate Stoneb9c1b512016-09-06 20:57:50 +0000144 void OptionParsingStarting(ExecutionContext *execution_context) override {
145 m_permissions = 0;
146 }
147
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000148 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +0000149 return llvm::makeArrayRef(g_permissions_options);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000150 }
151
152 // Instance variables to hold the values for command options.
153
154 uint32_t m_permissions;
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000155
Daniel Maleae0f8f572013-08-26 23:57:52 +0000156private:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000157 DISALLOW_COPY_AND_ASSIGN(OptionPermissions);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000158};
Greg Claytonf6b8b582011-04-13 00:18:08 +0000159
Greg Claytonded470d2011-03-19 01:12:21 +0000160//----------------------------------------------------------------------
Greg Clayton7260f622011-04-18 08:33:37 +0000161// "platform select <platform-name>"
Greg Claytonded470d2011-03-19 01:12:21 +0000162//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000163class CommandObjectPlatformSelect : public CommandObjectParsed {
Greg Claytonded470d2011-03-19 01:12:21 +0000164public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000165 CommandObjectPlatformSelect(CommandInterpreter &interpreter)
166 : CommandObjectParsed(interpreter, "platform select",
167 "Create a platform if needed and select it as the "
168 "current platform.",
169 "platform select <platform-name>", 0),
170 m_option_group(),
171 m_platform_options(
172 false) // Don't include the "--platform" option by passing false
173 {
174 m_option_group.Append(&m_platform_options, LLDB_OPT_SET_ALL, 1);
175 m_option_group.Finalize();
176 }
Greg Claytonded470d2011-03-19 01:12:21 +0000177
Kate Stoneb9c1b512016-09-06 20:57:50 +0000178 ~CommandObjectPlatformSelect() override = default;
Greg Claytonded470d2011-03-19 01:12:21 +0000179
Kate Stoneb9c1b512016-09-06 20:57:50 +0000180 int HandleCompletion(Args &input, int &cursor_index,
181 int &cursor_char_position, int match_start_point,
182 int max_return_elements, bool &word_complete,
183 StringList &matches) override {
184 std::string completion_str(input.GetArgumentAtIndex(cursor_index));
185 completion_str.erase(cursor_char_position);
Jim Ingham5a988412012-06-08 21:56:10 +0000186
Kate Stoneb9c1b512016-09-06 20:57:50 +0000187 CommandCompletions::PlatformPluginNames(
188 GetCommandInterpreter(), completion_str.c_str(), match_start_point,
189 max_return_elements, nullptr, word_complete, matches);
190 return matches.GetSize();
191 }
192
193 Options *GetOptions() override { return &m_option_group; }
Jim Ingham5a988412012-06-08 21:56:10 +0000194
195protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000196 bool DoExecute(Args &args, CommandReturnObject &result) override {
197 if (args.GetArgumentCount() == 1) {
198 const char *platform_name = args.GetArgumentAtIndex(0);
199 if (platform_name && platform_name[0]) {
200 const bool select = true;
201 m_platform_options.SetPlatformName(platform_name);
202 Error error;
203 ArchSpec platform_arch;
204 PlatformSP platform_sp(m_platform_options.CreatePlatformWithOptions(
205 m_interpreter, ArchSpec(), select, error, platform_arch));
206 if (platform_sp) {
207 m_interpreter.GetDebugger().GetPlatformList().SetSelectedPlatform(
208 platform_sp);
Vince Harron1b5a74e2015-01-21 22:42:49 +0000209
Kate Stoneb9c1b512016-09-06 20:57:50 +0000210 platform_sp->GetStatus(result.GetOutputStream());
211 result.SetStatus(eReturnStatusSuccessFinishResult);
212 } else {
213 result.AppendError(error.AsCString());
214 result.SetStatus(eReturnStatusFailed);
Greg Claytonded470d2011-03-19 01:12:21 +0000215 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000216 } else {
217 result.AppendError("invalid platform name");
218 result.SetStatus(eReturnStatusFailed);
219 }
220 } else {
221 result.AppendError(
222 "platform create takes a platform name as an argument\n");
223 result.SetStatus(eReturnStatusFailed);
Greg Claytonded470d2011-03-19 01:12:21 +0000224 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000225 return result.Succeeded();
226 }
Greg Clayton7260f622011-04-18 08:33:37 +0000227
Kate Stoneb9c1b512016-09-06 20:57:50 +0000228 OptionGroupOptions m_option_group;
229 OptionGroupPlatform m_platform_options;
Greg Claytonded470d2011-03-19 01:12:21 +0000230};
231
232//----------------------------------------------------------------------
233// "platform list"
234//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000235class CommandObjectPlatformList : public CommandObjectParsed {
Greg Claytonded470d2011-03-19 01:12:21 +0000236public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000237 CommandObjectPlatformList(CommandInterpreter &interpreter)
238 : CommandObjectParsed(interpreter, "platform list",
239 "List all platforms that are available.", nullptr,
240 0) {}
Greg Claytonded470d2011-03-19 01:12:21 +0000241
Kate Stoneb9c1b512016-09-06 20:57:50 +0000242 ~CommandObjectPlatformList() override = default;
Greg Claytonded470d2011-03-19 01:12:21 +0000243
Jim Ingham5a988412012-06-08 21:56:10 +0000244protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000245 bool DoExecute(Args &args, CommandReturnObject &result) override {
246 Stream &ostrm = result.GetOutputStream();
247 ostrm.Printf("Available platforms:\n");
Greg Claytonded470d2011-03-19 01:12:21 +0000248
Kate Stoneb9c1b512016-09-06 20:57:50 +0000249 PlatformSP host_platform_sp(Platform::GetHostPlatform());
250 ostrm.Printf("%s: %s\n", host_platform_sp->GetPluginName().GetCString(),
251 host_platform_sp->GetDescription());
252
253 uint32_t idx;
254 for (idx = 0; 1; ++idx) {
255 const char *plugin_name =
256 PluginManager::GetPlatformPluginNameAtIndex(idx);
257 if (plugin_name == nullptr)
258 break;
259 const char *plugin_desc =
260 PluginManager::GetPlatformPluginDescriptionAtIndex(idx);
261 if (plugin_desc == nullptr)
262 break;
263 ostrm.Printf("%s: %s\n", plugin_name, plugin_desc);
Greg Claytonded470d2011-03-19 01:12:21 +0000264 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000265
266 if (idx == 0) {
267 result.AppendError("no platforms are available\n");
268 result.SetStatus(eReturnStatusFailed);
269 } else
270 result.SetStatus(eReturnStatusSuccessFinishResult);
271 return result.Succeeded();
272 }
Greg Claytonded470d2011-03-19 01:12:21 +0000273};
274
275//----------------------------------------------------------------------
276// "platform status"
277//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000278class CommandObjectPlatformStatus : public CommandObjectParsed {
Greg Claytonded470d2011-03-19 01:12:21 +0000279public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000280 CommandObjectPlatformStatus(CommandInterpreter &interpreter)
281 : CommandObjectParsed(interpreter, "platform status",
282 "Display status for the current platform.", nullptr,
283 0) {}
Greg Claytonded470d2011-03-19 01:12:21 +0000284
Kate Stoneb9c1b512016-09-06 20:57:50 +0000285 ~CommandObjectPlatformStatus() override = default;
Greg Claytonded470d2011-03-19 01:12:21 +0000286
Jim Ingham5a988412012-06-08 21:56:10 +0000287protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000288 bool DoExecute(Args &args, CommandReturnObject &result) override {
289 Stream &ostrm = result.GetOutputStream();
290
291 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
292 PlatformSP platform_sp;
293 if (target) {
294 platform_sp = target->GetPlatform();
Greg Claytonded470d2011-03-19 01:12:21 +0000295 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000296 if (!platform_sp) {
297 platform_sp =
298 m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform();
299 }
300 if (platform_sp) {
301 platform_sp->GetStatus(ostrm);
302 result.SetStatus(eReturnStatusSuccessFinishResult);
303 } else {
304 result.AppendError("no platform us currently selected\n");
305 result.SetStatus(eReturnStatusFailed);
306 }
307 return result.Succeeded();
308 }
Greg Claytonded470d2011-03-19 01:12:21 +0000309};
310
Greg Claytond314e812011-03-23 00:09:55 +0000311//----------------------------------------------------------------------
312// "platform connect <connect-url>"
313//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000314class CommandObjectPlatformConnect : public CommandObjectParsed {
Greg Claytond314e812011-03-23 00:09:55 +0000315public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000316 CommandObjectPlatformConnect(CommandInterpreter &interpreter)
317 : CommandObjectParsed(
318 interpreter, "platform connect",
319 "Select the current platform by providing a connection URL.",
320 "platform connect <connect-url>", 0) {}
Greg Claytond314e812011-03-23 00:09:55 +0000321
Kate Stoneb9c1b512016-09-06 20:57:50 +0000322 ~CommandObjectPlatformConnect() override = default;
Greg Claytond314e812011-03-23 00:09:55 +0000323
Jim Ingham5a988412012-06-08 21:56:10 +0000324protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000325 bool DoExecute(Args &args, CommandReturnObject &result) override {
326 Stream &ostrm = result.GetOutputStream();
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000327
Kate Stoneb9c1b512016-09-06 20:57:50 +0000328 PlatformSP platform_sp(
329 m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
330 if (platform_sp) {
331 Error error(platform_sp->ConnectRemote(args));
332 if (error.Success()) {
333 platform_sp->GetStatus(ostrm);
334 result.SetStatus(eReturnStatusSuccessFinishResult);
335
336 platform_sp->ConnectToWaitingProcesses(m_interpreter.GetDebugger(),
337 error);
338 if (error.Fail()) {
339 result.AppendError(error.AsCString());
340 result.SetStatus(eReturnStatusFailed);
Greg Claytond314e812011-03-23 00:09:55 +0000341 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000342 } else {
343 result.AppendErrorWithFormat("%s\n", error.AsCString());
344 result.SetStatus(eReturnStatusFailed);
345 }
346 } else {
347 result.AppendError("no platform is currently selected\n");
348 result.SetStatus(eReturnStatusFailed);
Greg Claytond314e812011-03-23 00:09:55 +0000349 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000350 return result.Succeeded();
351 }
352
353 Options *GetOptions() override {
354 PlatformSP platform_sp(
355 m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
356 OptionGroupOptions *m_platform_options = nullptr;
357 if (platform_sp) {
358 m_platform_options = platform_sp->GetConnectionOptions(m_interpreter);
359 if (m_platform_options != nullptr && !m_platform_options->m_did_finalize)
360 m_platform_options->Finalize();
Daniel Maleae0f8f572013-08-26 23:57:52 +0000361 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000362 return m_platform_options;
363 }
Greg Claytond314e812011-03-23 00:09:55 +0000364};
365
366//----------------------------------------------------------------------
367// "platform disconnect"
368//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000369class CommandObjectPlatformDisconnect : public CommandObjectParsed {
Greg Claytond314e812011-03-23 00:09:55 +0000370public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000371 CommandObjectPlatformDisconnect(CommandInterpreter &interpreter)
372 : CommandObjectParsed(interpreter, "platform disconnect",
373 "Disconnect from the current platform.",
374 "platform disconnect", 0) {}
Greg Claytond314e812011-03-23 00:09:55 +0000375
Kate Stoneb9c1b512016-09-06 20:57:50 +0000376 ~CommandObjectPlatformDisconnect() override = default;
Greg Claytond314e812011-03-23 00:09:55 +0000377
Jim Ingham5a988412012-06-08 21:56:10 +0000378protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000379 bool DoExecute(Args &args, CommandReturnObject &result) override {
380 PlatformSP platform_sp(
381 m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
382 if (platform_sp) {
383 if (args.GetArgumentCount() == 0) {
384 Error error;
Greg Claytond314e812011-03-23 00:09:55 +0000385
Kate Stoneb9c1b512016-09-06 20:57:50 +0000386 if (platform_sp->IsConnected()) {
387 // Cache the instance name if there is one since we are
388 // about to disconnect and the name might go with it.
389 const char *hostname_cstr = platform_sp->GetHostname();
390 std::string hostname;
391 if (hostname_cstr)
392 hostname.assign(hostname_cstr);
393
394 error = platform_sp->DisconnectRemote();
395 if (error.Success()) {
396 Stream &ostrm = result.GetOutputStream();
397 if (hostname.empty())
398 ostrm.Printf("Disconnected from \"%s\"\n",
399 platform_sp->GetPluginName().GetCString());
Greg Claytond314e812011-03-23 00:09:55 +0000400 else
Kate Stoneb9c1b512016-09-06 20:57:50 +0000401 ostrm.Printf("Disconnected from \"%s\"\n", hostname.c_str());
402 result.SetStatus(eReturnStatusSuccessFinishResult);
403 } else {
404 result.AppendErrorWithFormat("%s", error.AsCString());
405 result.SetStatus(eReturnStatusFailed);
406 }
407 } else {
408 // Not connected...
409 result.AppendErrorWithFormat(
410 "not connected to '%s'",
411 platform_sp->GetPluginName().GetCString());
412 result.SetStatus(eReturnStatusFailed);
Greg Claytond314e812011-03-23 00:09:55 +0000413 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000414 } else {
415 // Bad args
416 result.AppendError(
417 "\"platform disconnect\" doesn't take any arguments");
418 result.SetStatus(eReturnStatusFailed);
419 }
420 } else {
421 result.AppendError("no platform is currently selected");
422 result.SetStatus(eReturnStatusFailed);
Greg Claytond314e812011-03-23 00:09:55 +0000423 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000424 return result.Succeeded();
425 }
Greg Claytond314e812011-03-23 00:09:55 +0000426};
Daniel Maleae0f8f572013-08-26 23:57:52 +0000427
428//----------------------------------------------------------------------
Greg Claytonfbb76342013-11-20 21:07:01 +0000429// "platform settings"
430//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000431class CommandObjectPlatformSettings : public CommandObjectParsed {
Greg Claytonfbb76342013-11-20 21:07:01 +0000432public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000433 CommandObjectPlatformSettings(CommandInterpreter &interpreter)
434 : CommandObjectParsed(interpreter, "platform settings",
435 "Set settings for the current target's platform, "
436 "or for a platform by name.",
437 "platform settings", 0),
Todd Fialae1cfbc72016-08-11 23:51:28 +0000438 m_options(),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000439 m_option_working_dir(LLDB_OPT_SET_1, false, "working-dir", 'w', 0,
440 eArgTypePath,
441 "The working directory for the platform.") {
442 m_options.Append(&m_option_working_dir, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
443 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000444
Kate Stoneb9c1b512016-09-06 20:57:50 +0000445 ~CommandObjectPlatformSettings() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000446
Greg Claytonfbb76342013-11-20 21:07:01 +0000447protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000448 bool DoExecute(Args &args, CommandReturnObject &result) override {
449 PlatformSP platform_sp(
450 m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
451 if (platform_sp) {
452 if (m_option_working_dir.GetOptionValue().OptionWasSet())
453 platform_sp->SetWorkingDirectory(
454 m_option_working_dir.GetOptionValue().GetCurrentValue());
455 } else {
456 result.AppendError("no platform is currently selected");
457 result.SetStatus(eReturnStatusFailed);
Greg Claytonfbb76342013-11-20 21:07:01 +0000458 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000459 return result.Succeeded();
460 }
461
462 Options *GetOptions() override {
463 if (!m_options.DidFinalize())
464 m_options.Finalize();
465 return &m_options;
466 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000467
Greg Claytonfbb76342013-11-20 21:07:01 +0000468protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000469 OptionGroupOptions m_options;
470 OptionGroupFile m_option_working_dir;
Greg Claytonfbb76342013-11-20 21:07:01 +0000471};
472
Greg Claytonfbb76342013-11-20 21:07:01 +0000473//----------------------------------------------------------------------
Daniel Maleae0f8f572013-08-26 23:57:52 +0000474// "platform mkdir"
475//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000476class CommandObjectPlatformMkDir : public CommandObjectParsed {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000477public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000478 CommandObjectPlatformMkDir(CommandInterpreter &interpreter)
479 : CommandObjectParsed(interpreter, "platform mkdir",
480 "Make a new directory on the remote end.", nullptr,
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000481 0),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000482 m_options() {}
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000483
Kate Stoneb9c1b512016-09-06 20:57:50 +0000484 ~CommandObjectPlatformMkDir() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000485
Kate Stoneb9c1b512016-09-06 20:57:50 +0000486 bool DoExecute(Args &args, CommandReturnObject &result) override {
487 PlatformSP platform_sp(
488 m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
489 if (platform_sp) {
490 std::string cmd_line;
491 args.GetCommandString(cmd_line);
492 uint32_t mode;
493 const OptionPermissions *options_permissions =
494 (const OptionPermissions *)m_options.GetGroupWithOption('r');
495 if (options_permissions)
496 mode = options_permissions->m_permissions;
497 else
498 mode = lldb::eFilePermissionsUserRWX | lldb::eFilePermissionsGroupRWX |
499 lldb::eFilePermissionsWorldRX;
500 Error error = platform_sp->MakeDirectory(FileSpec{cmd_line, false}, mode);
501 if (error.Success()) {
502 result.SetStatus(eReturnStatusSuccessFinishResult);
503 } else {
504 result.AppendError(error.AsCString());
505 result.SetStatus(eReturnStatusFailed);
506 }
507 } else {
508 result.AppendError("no platform currently selected\n");
509 result.SetStatus(eReturnStatusFailed);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000510 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000511 return result.Succeeded();
512 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000513
Kate Stoneb9c1b512016-09-06 20:57:50 +0000514 Options *GetOptions() override {
515 if (!m_options.DidFinalize()) {
516 m_options.Append(new OptionPermissions());
517 m_options.Finalize();
518 }
519 return &m_options;
520 }
521
522 OptionGroupOptions m_options;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000523};
524
525//----------------------------------------------------------------------
526// "platform fopen"
527//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000528class CommandObjectPlatformFOpen : public CommandObjectParsed {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000529public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000530 CommandObjectPlatformFOpen(CommandInterpreter &interpreter)
531 : CommandObjectParsed(interpreter, "platform file open",
532 "Open a file on the remote end.", nullptr, 0),
533 m_options() {}
534
535 ~CommandObjectPlatformFOpen() override = default;
536
537 bool DoExecute(Args &args, CommandReturnObject &result) override {
538 PlatformSP platform_sp(
539 m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
540 if (platform_sp) {
541 Error error;
542 std::string cmd_line;
543 args.GetCommandString(cmd_line);
544 mode_t perms;
545 const OptionPermissions *options_permissions =
546 (const OptionPermissions *)m_options.GetGroupWithOption('r');
547 if (options_permissions)
548 perms = options_permissions->m_permissions;
549 else
550 perms = lldb::eFilePermissionsUserRW | lldb::eFilePermissionsGroupRW |
551 lldb::eFilePermissionsWorldRead;
552 lldb::user_id_t fd = platform_sp->OpenFile(
553 FileSpec(cmd_line.c_str(), false),
554 File::eOpenOptionRead | File::eOpenOptionWrite |
555 File::eOpenOptionAppend | File::eOpenOptionCanCreate,
556 perms, error);
557 if (error.Success()) {
558 result.AppendMessageWithFormat("File Descriptor = %" PRIu64 "\n", fd);
559 result.SetStatus(eReturnStatusSuccessFinishResult);
560 } else {
561 result.AppendError(error.AsCString());
562 result.SetStatus(eReturnStatusFailed);
563 }
564 } else {
565 result.AppendError("no platform currently selected\n");
566 result.SetStatus(eReturnStatusFailed);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000567 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000568 return result.Succeeded();
569 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000570
Kate Stoneb9c1b512016-09-06 20:57:50 +0000571 Options *GetOptions() override {
572 if (!m_options.DidFinalize()) {
573 m_options.Append(new OptionPermissions());
574 m_options.Finalize();
Daniel Maleae0f8f572013-08-26 23:57:52 +0000575 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000576 return &m_options;
577 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000578
Kate Stoneb9c1b512016-09-06 20:57:50 +0000579 OptionGroupOptions m_options;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000580};
581
582//----------------------------------------------------------------------
583// "platform fclose"
584//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000585class CommandObjectPlatformFClose : public CommandObjectParsed {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000586public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000587 CommandObjectPlatformFClose(CommandInterpreter &interpreter)
588 : CommandObjectParsed(interpreter, "platform file close",
589 "Close a file on the remote end.", nullptr, 0) {}
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000590
Kate Stoneb9c1b512016-09-06 20:57:50 +0000591 ~CommandObjectPlatformFClose() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000592
Kate Stoneb9c1b512016-09-06 20:57:50 +0000593 bool DoExecute(Args &args, CommandReturnObject &result) override {
594 PlatformSP platform_sp(
595 m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
596 if (platform_sp) {
597 std::string cmd_line;
598 args.GetCommandString(cmd_line);
599 const lldb::user_id_t fd =
600 StringConvert::ToUInt64(cmd_line.c_str(), UINT64_MAX);
601 Error error;
602 bool success = platform_sp->CloseFile(fd, error);
603 if (success) {
604 result.AppendMessageWithFormat("file %" PRIu64 " closed.\n", fd);
605 result.SetStatus(eReturnStatusSuccessFinishResult);
606 } else {
607 result.AppendError(error.AsCString());
608 result.SetStatus(eReturnStatusFailed);
609 }
610 } else {
611 result.AppendError("no platform currently selected\n");
612 result.SetStatus(eReturnStatusFailed);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000613 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000614 return result.Succeeded();
615 }
Daniel Maleae0f8f572013-08-26 23:57:52 +0000616};
617
618//----------------------------------------------------------------------
619// "platform fread"
620//----------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000621
622static OptionDefinition g_platform_fread_options[] = {
623 // clang-format off
624 { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeIndex, "Offset into the file at which to start reading." },
625 { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "Number of bytes to read from the file." },
626 // clang-format on
627};
628
Kate Stoneb9c1b512016-09-06 20:57:50 +0000629class CommandObjectPlatformFRead : public CommandObjectParsed {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000630public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000631 CommandObjectPlatformFRead(CommandInterpreter &interpreter)
632 : CommandObjectParsed(interpreter, "platform file read",
633 "Read data from a file on the remote end.", nullptr,
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000634 0),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000635 m_options() {}
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000636
Kate Stoneb9c1b512016-09-06 20:57:50 +0000637 ~CommandObjectPlatformFRead() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000638
Kate Stoneb9c1b512016-09-06 20:57:50 +0000639 bool DoExecute(Args &args, CommandReturnObject &result) override {
640 PlatformSP platform_sp(
641 m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
642 if (platform_sp) {
643 std::string cmd_line;
644 args.GetCommandString(cmd_line);
645 const lldb::user_id_t fd =
646 StringConvert::ToUInt64(cmd_line.c_str(), UINT64_MAX);
647 std::string buffer(m_options.m_count, 0);
648 Error error;
649 uint32_t retcode = platform_sp->ReadFile(
650 fd, m_options.m_offset, &buffer[0], m_options.m_count, error);
651 result.AppendMessageWithFormat("Return = %d\n", retcode);
652 result.AppendMessageWithFormat("Data = \"%s\"\n", buffer.c_str());
653 result.SetStatus(eReturnStatusSuccessFinishResult);
654 } else {
655 result.AppendError("no platform currently selected\n");
656 result.SetStatus(eReturnStatusFailed);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000657 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000658 return result.Succeeded();
659 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000660
Kate Stoneb9c1b512016-09-06 20:57:50 +0000661 Options *GetOptions() override { return &m_options; }
662
Daniel Maleae0f8f572013-08-26 23:57:52 +0000663protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000664 class CommandOptions : public Options {
665 public:
666 CommandOptions() : Options() {}
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000667
Kate Stoneb9c1b512016-09-06 20:57:50 +0000668 ~CommandOptions() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000669
Kate Stoneb9c1b512016-09-06 20:57:50 +0000670 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
671 ExecutionContext *execution_context) override {
672 Error error;
673 char short_option = (char)m_getopt_table[option_idx].val;
674 bool success = false;
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000675
Kate Stoneb9c1b512016-09-06 20:57:50 +0000676 switch (short_option) {
677 case 'o':
678 m_offset = StringConvert::ToUInt32(option_arg, 0, 0, &success);
679 if (!success)
680 error.SetErrorStringWithFormat("invalid offset: '%s'", option_arg);
681 break;
682 case 'c':
683 m_count = StringConvert::ToUInt32(option_arg, 0, 0, &success);
684 if (!success)
685 error.SetErrorStringWithFormat("invalid offset: '%s'", option_arg);
686 break;
687 default:
688 error.SetErrorStringWithFormat("unrecognized option '%c'",
689 short_option);
690 break;
691 }
692
693 return error;
694 }
695
696 void OptionParsingStarting(ExecutionContext *execution_context) override {
697 m_offset = 0;
698 m_count = 1;
699 }
700
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000701 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +0000702 return llvm::makeArrayRef(g_platform_fread_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000703 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000704
705 // Instance variables to hold the values for command options.
706
707 uint32_t m_offset;
708 uint32_t m_count;
709 };
710
711 CommandOptions m_options;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000712};
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000713
Daniel Maleae0f8f572013-08-26 23:57:52 +0000714//----------------------------------------------------------------------
715// "platform fwrite"
716//----------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000717
718static OptionDefinition g_platform_fwrite_options[] = {
719 // clang-format off
720 { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeIndex, "Offset into the file at which to start reading." },
721 { LLDB_OPT_SET_1, false, "data", 'd', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeValue, "Text to write to the file." },
722 // clang-format on
723};
724
Kate Stoneb9c1b512016-09-06 20:57:50 +0000725class CommandObjectPlatformFWrite : public CommandObjectParsed {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000726public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000727 CommandObjectPlatformFWrite(CommandInterpreter &interpreter)
728 : CommandObjectParsed(interpreter, "platform file write",
729 "Write data to a file on the remote end.", nullptr,
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000730 0),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000731 m_options() {}
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000732
Kate Stoneb9c1b512016-09-06 20:57:50 +0000733 ~CommandObjectPlatformFWrite() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000734
Kate Stoneb9c1b512016-09-06 20:57:50 +0000735 bool DoExecute(Args &args, CommandReturnObject &result) override {
736 PlatformSP platform_sp(
737 m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
738 if (platform_sp) {
739 std::string cmd_line;
740 args.GetCommandString(cmd_line);
741 Error error;
742 const lldb::user_id_t fd =
743 StringConvert::ToUInt64(cmd_line.c_str(), UINT64_MAX);
744 uint32_t retcode =
745 platform_sp->WriteFile(fd, m_options.m_offset, &m_options.m_data[0],
746 m_options.m_data.size(), error);
747 result.AppendMessageWithFormat("Return = %d\n", retcode);
748 result.SetStatus(eReturnStatusSuccessFinishResult);
749 } else {
750 result.AppendError("no platform currently selected\n");
751 result.SetStatus(eReturnStatusFailed);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000752 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000753 return result.Succeeded();
754 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000755
Kate Stoneb9c1b512016-09-06 20:57:50 +0000756 Options *GetOptions() override { return &m_options; }
757
Daniel Maleae0f8f572013-08-26 23:57:52 +0000758protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000759 class CommandOptions : public Options {
760 public:
761 CommandOptions() : Options() {}
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000762
Kate Stoneb9c1b512016-09-06 20:57:50 +0000763 ~CommandOptions() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000764
Kate Stoneb9c1b512016-09-06 20:57:50 +0000765 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
766 ExecutionContext *execution_context) override {
767 Error error;
768 char short_option = (char)m_getopt_table[option_idx].val;
769 bool success = false;
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000770
Kate Stoneb9c1b512016-09-06 20:57:50 +0000771 switch (short_option) {
772 case 'o':
773 m_offset = StringConvert::ToUInt32(option_arg, 0, 0, &success);
774 if (!success)
775 error.SetErrorStringWithFormat("invalid offset: '%s'", option_arg);
776 break;
777 case 'd':
778 m_data.assign(option_arg);
779 break;
780 default:
781 error.SetErrorStringWithFormat("unrecognized option '%c'",
782 short_option);
783 break;
784 }
785
786 return error;
787 }
788
789 void OptionParsingStarting(ExecutionContext *execution_context) override {
790 m_offset = 0;
791 m_data.clear();
792 }
793
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000794 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +0000795 return llvm::makeArrayRef(g_platform_fwrite_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000796 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000797
798 // Instance variables to hold the values for command options.
799
800 uint32_t m_offset;
801 std::string m_data;
802 };
803
804 CommandOptions m_options;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000805};
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000806
Kate Stoneb9c1b512016-09-06 20:57:50 +0000807class CommandObjectPlatformFile : public CommandObjectMultiword {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000808public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000809 //------------------------------------------------------------------
810 // Constructors and Destructors
811 //------------------------------------------------------------------
812 CommandObjectPlatformFile(CommandInterpreter &interpreter)
813 : CommandObjectMultiword(
814 interpreter, "platform file",
815 "Commands to access files on the current platform.",
816 "platform file [open|close|read|write] ...") {
817 LoadSubCommand(
818 "open", CommandObjectSP(new CommandObjectPlatformFOpen(interpreter)));
819 LoadSubCommand(
820 "close", CommandObjectSP(new CommandObjectPlatformFClose(interpreter)));
821 LoadSubCommand(
822 "read", CommandObjectSP(new CommandObjectPlatformFRead(interpreter)));
823 LoadSubCommand(
824 "write", CommandObjectSP(new CommandObjectPlatformFWrite(interpreter)));
825 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000826
Kate Stoneb9c1b512016-09-06 20:57:50 +0000827 ~CommandObjectPlatformFile() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000828
Daniel Maleae0f8f572013-08-26 23:57:52 +0000829private:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000830 //------------------------------------------------------------------
831 // For CommandObjectPlatform only
832 //------------------------------------------------------------------
833 DISALLOW_COPY_AND_ASSIGN(CommandObjectPlatformFile);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000834};
835
836//----------------------------------------------------------------------
837// "platform get-file remote-file-path host-file-path"
838//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000839class CommandObjectPlatformGetFile : public CommandObjectParsed {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000840public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000841 CommandObjectPlatformGetFile(CommandInterpreter &interpreter)
842 : CommandObjectParsed(
843 interpreter, "platform get-file",
844 "Transfer a file from the remote end to the local host.",
845 "platform get-file <remote-file-spec> <local-file-spec>", 0) {
846 SetHelpLong(
847 R"(Examples:
Kate Stoneea671fb2015-07-14 05:48:36 +0000848
849(lldb) platform get-file /the/remote/file/path /the/local/file/path
850
Kate Stoneb9c1b512016-09-06 20:57:50 +0000851 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 +0000852
Kate Stoneb9c1b512016-09-06 20:57:50 +0000853 CommandArgumentEntry arg1, arg2;
854 CommandArgumentData file_arg_remote, file_arg_host;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000855
Kate Stoneb9c1b512016-09-06 20:57:50 +0000856 // Define the first (and only) variant of this arg.
857 file_arg_remote.arg_type = eArgTypeFilename;
858 file_arg_remote.arg_repetition = eArgRepeatPlain;
859 // There is only one variant this argument could be; put it into the
860 // argument entry.
861 arg1.push_back(file_arg_remote);
862
863 // Define the second (and only) variant of this arg.
864 file_arg_host.arg_type = eArgTypeFilename;
865 file_arg_host.arg_repetition = eArgRepeatPlain;
866 // There is only one variant this argument could be; put it into the
867 // argument entry.
868 arg2.push_back(file_arg_host);
869
870 // Push the data for the first and the second arguments into the m_arguments
871 // vector.
872 m_arguments.push_back(arg1);
873 m_arguments.push_back(arg2);
874 }
875
876 ~CommandObjectPlatformGetFile() override = default;
877
878 bool DoExecute(Args &args, CommandReturnObject &result) override {
879 // If the number of arguments is incorrect, issue an error message.
880 if (args.GetArgumentCount() != 2) {
881 result.GetErrorStream().Printf("error: required arguments missing; "
882 "specify both the source and destination "
883 "file paths\n");
884 result.SetStatus(eReturnStatusFailed);
885 return false;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000886 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000887
Kate Stoneb9c1b512016-09-06 20:57:50 +0000888 PlatformSP platform_sp(
889 m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
890 if (platform_sp) {
891 const char *remote_file_path = args.GetArgumentAtIndex(0);
892 const char *local_file_path = args.GetArgumentAtIndex(1);
893 Error error = platform_sp->GetFile(FileSpec(remote_file_path, false),
894 FileSpec(local_file_path, false));
895 if (error.Success()) {
896 result.AppendMessageWithFormat(
897 "successfully get-file from %s (remote) to %s (host)\n",
898 remote_file_path, local_file_path);
899 result.SetStatus(eReturnStatusSuccessFinishResult);
900 } else {
901 result.AppendMessageWithFormat("get-file failed: %s\n",
902 error.AsCString());
903 result.SetStatus(eReturnStatusFailed);
904 }
905 } else {
906 result.AppendError("no platform currently selected\n");
907 result.SetStatus(eReturnStatusFailed);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000908 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000909 return result.Succeeded();
910 }
Daniel Maleae0f8f572013-08-26 23:57:52 +0000911};
912
913//----------------------------------------------------------------------
914// "platform get-size remote-file-path"
915//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000916class CommandObjectPlatformGetSize : public CommandObjectParsed {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000917public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000918 CommandObjectPlatformGetSize(CommandInterpreter &interpreter)
919 : CommandObjectParsed(interpreter, "platform get-size",
920 "Get the file size from the remote end.",
921 "platform get-size <remote-file-spec>", 0) {
922 SetHelpLong(
923 R"(Examples:
Kate Stoneea671fb2015-07-14 05:48:36 +0000924
925(lldb) platform get-size /the/remote/file/path
926
Kate Stoneb9c1b512016-09-06 20:57:50 +0000927 Get the file size from the remote end with path /the/remote/file/path.)");
Daniel Maleae0f8f572013-08-26 23:57:52 +0000928
Kate Stoneb9c1b512016-09-06 20:57:50 +0000929 CommandArgumentEntry arg1;
930 CommandArgumentData file_arg_remote;
931
932 // Define the first (and only) variant of this arg.
933 file_arg_remote.arg_type = eArgTypeFilename;
934 file_arg_remote.arg_repetition = eArgRepeatPlain;
935 // There is only one variant this argument could be; put it into the
936 // argument entry.
937 arg1.push_back(file_arg_remote);
938
939 // Push the data for the first argument into the m_arguments vector.
940 m_arguments.push_back(arg1);
941 }
942
943 ~CommandObjectPlatformGetSize() override = default;
944
945 bool DoExecute(Args &args, CommandReturnObject &result) override {
946 // If the number of arguments is incorrect, issue an error message.
947 if (args.GetArgumentCount() != 1) {
948 result.GetErrorStream().Printf("error: required argument missing; "
949 "specify the source file path as the only "
950 "argument\n");
951 result.SetStatus(eReturnStatusFailed);
952 return false;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000953 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000954
Kate Stoneb9c1b512016-09-06 20:57:50 +0000955 PlatformSP platform_sp(
956 m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
957 if (platform_sp) {
958 std::string remote_file_path(args.GetArgumentAtIndex(0));
959 user_id_t size =
960 platform_sp->GetFileSize(FileSpec(remote_file_path.c_str(), false));
961 if (size != UINT64_MAX) {
962 result.AppendMessageWithFormat("File size of %s (remote): %" PRIu64
963 "\n",
964 remote_file_path.c_str(), size);
965 result.SetStatus(eReturnStatusSuccessFinishResult);
966 } else {
967 result.AppendMessageWithFormat(
968 "Error getting file size of %s (remote)\n",
969 remote_file_path.c_str());
970 result.SetStatus(eReturnStatusFailed);
971 }
972 } else {
973 result.AppendError("no platform currently selected\n");
974 result.SetStatus(eReturnStatusFailed);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000975 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000976 return result.Succeeded();
977 }
Daniel Maleae0f8f572013-08-26 23:57:52 +0000978};
979
980//----------------------------------------------------------------------
981// "platform put-file"
982//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000983class CommandObjectPlatformPutFile : public CommandObjectParsed {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000984public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000985 CommandObjectPlatformPutFile(CommandInterpreter &interpreter)
986 : CommandObjectParsed(
987 interpreter, "platform put-file",
988 "Transfer a file from this system to the remote end.", nullptr, 0) {
989 }
990
991 ~CommandObjectPlatformPutFile() override = default;
992
993 bool DoExecute(Args &args, CommandReturnObject &result) override {
994 const char *src = args.GetArgumentAtIndex(0);
995 const char *dst = args.GetArgumentAtIndex(1);
996
997 FileSpec src_fs(src, true);
998 FileSpec dst_fs(dst ? dst : src_fs.GetFilename().GetCString(), false);
999
1000 PlatformSP platform_sp(
1001 m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
1002 if (platform_sp) {
1003 Error error(platform_sp->PutFile(src_fs, dst_fs));
1004 if (error.Success()) {
1005 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1006 } else {
1007 result.AppendError(error.AsCString());
1008 result.SetStatus(eReturnStatusFailed);
1009 }
1010 } else {
1011 result.AppendError("no platform currently selected\n");
1012 result.SetStatus(eReturnStatusFailed);
Daniel Maleae0f8f572013-08-26 23:57:52 +00001013 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001014 return result.Succeeded();
1015 }
Daniel Maleae0f8f572013-08-26 23:57:52 +00001016};
1017
Greg Clayton8b82f082011-04-12 05:54:46 +00001018//----------------------------------------------------------------------
1019// "platform process launch"
1020//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +00001021class CommandObjectPlatformProcessLaunch : public CommandObjectParsed {
Greg Clayton8b82f082011-04-12 05:54:46 +00001022public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001023 CommandObjectPlatformProcessLaunch(CommandInterpreter &interpreter)
1024 : CommandObjectParsed(interpreter, "platform process launch",
1025 "Launch a new process on a remote platform.",
1026 "platform process launch program",
1027 eCommandRequiresTarget | eCommandTryTargetAPILock),
1028 m_options() {}
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001029
Kate Stoneb9c1b512016-09-06 20:57:50 +00001030 ~CommandObjectPlatformProcessLaunch() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001031
Kate Stoneb9c1b512016-09-06 20:57:50 +00001032 Options *GetOptions() override { return &m_options; }
1033
Jim Ingham5a988412012-06-08 21:56:10 +00001034protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001035 bool DoExecute(Args &args, CommandReturnObject &result) override {
1036 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1037 PlatformSP platform_sp;
1038 if (target) {
1039 platform_sp = target->GetPlatform();
1040 }
1041 if (!platform_sp) {
1042 platform_sp =
1043 m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform();
1044 }
Jason Molenda8c1157c2013-04-05 02:59:09 +00001045
Kate Stoneb9c1b512016-09-06 20:57:50 +00001046 if (platform_sp) {
1047 Error error;
1048 const size_t argc = args.GetArgumentCount();
1049 Target *target = m_exe_ctx.GetTargetPtr();
1050 Module *exe_module = target->GetExecutableModulePointer();
1051 if (exe_module) {
1052 m_options.launch_info.GetExecutableFile() = exe_module->GetFileSpec();
Zachary Turnerecbb0bb2016-09-19 17:54:06 +00001053 llvm::SmallString<PATH_MAX> exe_path;
1054 m_options.launch_info.GetExecutableFile().GetPath(exe_path);
1055 if (!exe_path.empty())
Kate Stoneb9c1b512016-09-06 20:57:50 +00001056 m_options.launch_info.GetArguments().AppendArgument(exe_path);
1057 m_options.launch_info.GetArchitecture() = exe_module->GetArchitecture();
1058 }
Greg Clayton8b82f082011-04-12 05:54:46 +00001059
Kate Stoneb9c1b512016-09-06 20:57:50 +00001060 if (argc > 0) {
1061 if (m_options.launch_info.GetExecutableFile()) {
1062 // We already have an executable file, so we will use this
1063 // and all arguments to this function are extra arguments
1064 m_options.launch_info.GetArguments().AppendArguments(args);
1065 } else {
1066 // We don't have any file yet, so the first argument is our
1067 // executable, and the rest are program arguments
1068 const bool first_arg_is_executable = true;
1069 m_options.launch_info.SetArguments(args, first_arg_is_executable);
Greg Clayton8b82f082011-04-12 05:54:46 +00001070 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001071 }
1072
1073 if (m_options.launch_info.GetExecutableFile()) {
1074 Debugger &debugger = m_interpreter.GetDebugger();
1075
1076 if (argc == 0)
1077 target->GetRunArguments(m_options.launch_info.GetArguments());
1078
1079 ProcessSP process_sp(platform_sp->DebugProcess(
1080 m_options.launch_info, debugger, target, error));
1081 if (process_sp && process_sp->IsAlive()) {
1082 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1083 return true;
1084 }
1085
1086 if (error.Success())
1087 result.AppendError("process launch failed");
Greg Clayton8b82f082011-04-12 05:54:46 +00001088 else
Kate Stoneb9c1b512016-09-06 20:57:50 +00001089 result.AppendError(error.AsCString());
1090 result.SetStatus(eReturnStatusFailed);
1091 } else {
1092 result.AppendError("'platform process launch' uses the current target "
1093 "file and arguments, or the executable and its "
1094 "arguments can be specified in this command");
1095 result.SetStatus(eReturnStatusFailed);
1096 return false;
1097 }
1098 } else {
1099 result.AppendError("no platform is selected\n");
Greg Clayton8b82f082011-04-12 05:54:46 +00001100 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001101 return result.Succeeded();
1102 }
1103
Greg Clayton8b82f082011-04-12 05:54:46 +00001104protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001105 ProcessLaunchCommandOptions m_options;
Greg Clayton8b82f082011-04-12 05:54:46 +00001106};
1107
Greg Clayton32e0a752011-03-30 18:16:51 +00001108//----------------------------------------------------------------------
1109// "platform process list"
1110//----------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001111
Zachary Turner70602432016-09-22 21:06:13 +00001112OptionDefinition g_platform_process_list_options[] = {
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001113 // clang-format off
1114 { LLDB_OPT_SET_1, false, "pid", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePid, "List the process info for a specific process ID." },
1115 { LLDB_OPT_SET_2, true, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeProcessName, "Find processes with executable basenames that match a string." },
1116 { LLDB_OPT_SET_3, true, "ends-with", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeProcessName, "Find processes with executable basenames that end with a string." },
1117 { LLDB_OPT_SET_4, true, "starts-with", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeProcessName, "Find processes with executable basenames that start with a string." },
1118 { LLDB_OPT_SET_5, true, "contains", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeProcessName, "Find processes with executable basenames that contain a string." },
1119 { LLDB_OPT_SET_6, true, "regex", 'r', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeRegularExpression, "Find processes with executable basenames that match a regular expression." },
1120 { LLDB_OPT_SET_FROM_TO(2, 6), false, "parent", 'P', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePid, "Find processes that have a matching parent process ID." },
1121 { LLDB_OPT_SET_FROM_TO(2, 6), false, "uid", 'u', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Find processes that have a matching user ID." },
1122 { LLDB_OPT_SET_FROM_TO(2, 6), false, "euid", 'U', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Find processes that have a matching effective user ID." },
1123 { LLDB_OPT_SET_FROM_TO(2, 6), false, "gid", 'g', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Find processes that have a matching group ID." },
1124 { LLDB_OPT_SET_FROM_TO(2, 6), false, "egid", 'G', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Find processes that have a matching effective group ID." },
1125 { LLDB_OPT_SET_FROM_TO(2, 6), false, "arch", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeArchitecture, "Find processes that have a matching architecture." },
1126 { LLDB_OPT_SET_FROM_TO(1, 6), false, "show-args", 'A', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Show process arguments instead of the process executable basename." },
1127 { LLDB_OPT_SET_FROM_TO(1, 6), false, "verbose", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable verbose output." },
1128 // clang-format on
1129};
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001130
Kate Stoneb9c1b512016-09-06 20:57:50 +00001131class CommandObjectPlatformProcessList : public CommandObjectParsed {
Greg Clayton32e0a752011-03-30 18:16:51 +00001132public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001133 CommandObjectPlatformProcessList(CommandInterpreter &interpreter)
1134 : CommandObjectParsed(interpreter, "platform process list",
1135 "List processes on a remote platform by name, pid, "
1136 "or many other matching attributes.",
1137 "platform process list", 0),
1138 m_options() {}
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001139
Kate Stoneb9c1b512016-09-06 20:57:50 +00001140 ~CommandObjectPlatformProcessList() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001141
Kate Stoneb9c1b512016-09-06 20:57:50 +00001142 Options *GetOptions() override { return &m_options; }
1143
Jim Ingham5a988412012-06-08 21:56:10 +00001144protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001145 bool DoExecute(Args &args, CommandReturnObject &result) override {
1146 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1147 PlatformSP platform_sp;
1148 if (target) {
1149 platform_sp = target->GetPlatform();
Greg Clayton32e0a752011-03-30 18:16:51 +00001150 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001151 if (!platform_sp) {
1152 platform_sp =
1153 m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform();
1154 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001155
Kate Stoneb9c1b512016-09-06 20:57:50 +00001156 if (platform_sp) {
1157 Error error;
1158 if (args.GetArgumentCount() == 0) {
1159 if (platform_sp) {
1160 Stream &ostrm = result.GetOutputStream();
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001161
Kate Stoneb9c1b512016-09-06 20:57:50 +00001162 lldb::pid_t pid =
1163 m_options.match_info.GetProcessInfo().GetProcessID();
1164 if (pid != LLDB_INVALID_PROCESS_ID) {
1165 ProcessInstanceInfo proc_info;
1166 if (platform_sp->GetProcessInfo(pid, proc_info)) {
1167 ProcessInstanceInfo::DumpTableHeader(ostrm, platform_sp.get(),
1168 m_options.show_args,
1169 m_options.verbose);
1170 proc_info.DumpAsTableRow(ostrm, platform_sp.get(),
1171 m_options.show_args, m_options.verbose);
1172 result.SetStatus(eReturnStatusSuccessFinishResult);
1173 } else {
1174 result.AppendErrorWithFormat(
1175 "no process found with pid = %" PRIu64 "\n", pid);
1176 result.SetStatus(eReturnStatusFailed);
Greg Clayton32e0a752011-03-30 18:16:51 +00001177 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001178 } else {
1179 ProcessInstanceInfoList proc_infos;
1180 const uint32_t matches =
1181 platform_sp->FindProcesses(m_options.match_info, proc_infos);
1182 const char *match_desc = nullptr;
1183 const char *match_name =
1184 m_options.match_info.GetProcessInfo().GetName();
1185 if (match_name && match_name[0]) {
1186 switch (m_options.match_info.GetNameMatchType()) {
1187 case eNameMatchIgnore:
1188 break;
1189 case eNameMatchEquals:
1190 match_desc = "matched";
1191 break;
1192 case eNameMatchContains:
1193 match_desc = "contained";
1194 break;
1195 case eNameMatchStartsWith:
1196 match_desc = "started with";
1197 break;
1198 case eNameMatchEndsWith:
1199 match_desc = "ended with";
1200 break;
1201 case eNameMatchRegularExpression:
1202 match_desc = "matched the regular expression";
1203 break;
1204 }
1205 }
Greg Clayton1cf2aa82016-03-24 21:49:22 +00001206
Kate Stoneb9c1b512016-09-06 20:57:50 +00001207 if (matches == 0) {
1208 if (match_desc)
1209 result.AppendErrorWithFormat(
1210 "no processes were found that %s \"%s\" on the \"%s\" "
1211 "platform\n",
1212 match_desc, match_name,
1213 platform_sp->GetPluginName().GetCString());
1214 else
1215 result.AppendErrorWithFormat(
1216 "no processes were found on the \"%s\" platform\n",
1217 platform_sp->GetPluginName().GetCString());
1218 result.SetStatus(eReturnStatusFailed);
1219 } else {
1220 result.AppendMessageWithFormat(
1221 "%u matching process%s found on \"%s\"", matches,
1222 matches > 1 ? "es were" : " was",
1223 platform_sp->GetName().GetCString());
1224 if (match_desc)
1225 result.AppendMessageWithFormat(" whose name %s \"%s\"",
1226 match_desc, match_name);
1227 result.AppendMessageWithFormat("\n");
1228 ProcessInstanceInfo::DumpTableHeader(ostrm, platform_sp.get(),
1229 m_options.show_args,
1230 m_options.verbose);
1231 for (uint32_t i = 0; i < matches; ++i) {
1232 proc_infos.GetProcessInfoAtIndex(i).DumpAsTableRow(
1233 ostrm, platform_sp.get(), m_options.show_args,
1234 m_options.verbose);
1235 }
1236 }
1237 }
1238 }
1239 } else {
1240 result.AppendError("invalid args: process list takes only options\n");
1241 result.SetStatus(eReturnStatusFailed);
1242 }
1243 } else {
1244 result.AppendError("no platform is selected\n");
1245 result.SetStatus(eReturnStatusFailed);
1246 }
1247 return result.Succeeded();
1248 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001249
Kate Stoneb9c1b512016-09-06 20:57:50 +00001250 class CommandOptions : public Options {
1251 public:
1252 CommandOptions()
1253 : Options(), match_info(), show_args(false), verbose(false) {
1254 static std::once_flag g_once_flag;
1255 std::call_once(g_once_flag, []() {
1256 PosixPlatformCommandOptionValidator *posix_validator =
1257 new PosixPlatformCommandOptionValidator();
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001258 for (auto &Option : g_platform_process_list_options) {
1259 switch (Option.short_option) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001260 case 'u':
1261 case 'U':
1262 case 'g':
1263 case 'G':
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001264 Option.validator = posix_validator;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001265 break;
1266 default:
1267 break;
1268 }
1269 }
1270 });
1271 }
1272
1273 ~CommandOptions() override = default;
1274
1275 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
1276 ExecutionContext *execution_context) override {
1277 Error error;
1278 const int short_option = m_getopt_table[option_idx].val;
1279 bool success = false;
1280
1281 switch (short_option) {
1282 case 'p':
1283 match_info.GetProcessInfo().SetProcessID(StringConvert::ToUInt32(
1284 option_arg, LLDB_INVALID_PROCESS_ID, 0, &success));
1285 if (!success)
1286 error.SetErrorStringWithFormat("invalid process ID string: '%s'",
1287 option_arg);
1288 break;
1289
1290 case 'P':
1291 match_info.GetProcessInfo().SetParentProcessID(StringConvert::ToUInt32(
1292 option_arg, LLDB_INVALID_PROCESS_ID, 0, &success));
1293 if (!success)
1294 error.SetErrorStringWithFormat(
1295 "invalid parent process ID string: '%s'", option_arg);
1296 break;
1297
1298 case 'u':
1299 match_info.GetProcessInfo().SetUserID(
1300 StringConvert::ToUInt32(option_arg, UINT32_MAX, 0, &success));
1301 if (!success)
1302 error.SetErrorStringWithFormat("invalid user ID string: '%s'",
1303 option_arg);
1304 break;
1305
1306 case 'U':
1307 match_info.GetProcessInfo().SetEffectiveUserID(
1308 StringConvert::ToUInt32(option_arg, UINT32_MAX, 0, &success));
1309 if (!success)
1310 error.SetErrorStringWithFormat(
1311 "invalid effective user ID string: '%s'", option_arg);
1312 break;
1313
1314 case 'g':
1315 match_info.GetProcessInfo().SetGroupID(
1316 StringConvert::ToUInt32(option_arg, UINT32_MAX, 0, &success));
1317 if (!success)
1318 error.SetErrorStringWithFormat("invalid group ID string: '%s'",
1319 option_arg);
1320 break;
1321
1322 case 'G':
1323 match_info.GetProcessInfo().SetEffectiveGroupID(
1324 StringConvert::ToUInt32(option_arg, UINT32_MAX, 0, &success));
1325 if (!success)
1326 error.SetErrorStringWithFormat(
1327 "invalid effective group ID string: '%s'", option_arg);
1328 break;
1329
1330 case 'a': {
1331 TargetSP target_sp =
1332 execution_context ? execution_context->GetTargetSP() : TargetSP();
1333 DebuggerSP debugger_sp =
1334 target_sp ? target_sp->GetDebugger().shared_from_this()
1335 : DebuggerSP();
1336 PlatformSP platform_sp =
1337 debugger_sp ? debugger_sp->GetPlatformList().GetSelectedPlatform()
1338 : PlatformSP();
1339 match_info.GetProcessInfo().GetArchitecture().SetTriple(
1340 option_arg, platform_sp.get());
1341 } break;
1342
1343 case 'n':
1344 match_info.GetProcessInfo().GetExecutableFile().SetFile(option_arg,
1345 false);
1346 match_info.SetNameMatchType(eNameMatchEquals);
1347 break;
1348
1349 case 'e':
1350 match_info.GetProcessInfo().GetExecutableFile().SetFile(option_arg,
1351 false);
1352 match_info.SetNameMatchType(eNameMatchEndsWith);
1353 break;
1354
1355 case 's':
1356 match_info.GetProcessInfo().GetExecutableFile().SetFile(option_arg,
1357 false);
1358 match_info.SetNameMatchType(eNameMatchStartsWith);
1359 break;
1360
1361 case 'c':
1362 match_info.GetProcessInfo().GetExecutableFile().SetFile(option_arg,
1363 false);
1364 match_info.SetNameMatchType(eNameMatchContains);
1365 break;
1366
1367 case 'r':
1368 match_info.GetProcessInfo().GetExecutableFile().SetFile(option_arg,
1369 false);
1370 match_info.SetNameMatchType(eNameMatchRegularExpression);
1371 break;
1372
1373 case 'A':
1374 show_args = true;
1375 break;
1376
1377 case 'v':
1378 verbose = true;
1379 break;
1380
1381 default:
1382 error.SetErrorStringWithFormat("unrecognized option '%c'",
1383 short_option);
1384 break;
1385 }
1386
1387 return error;
1388 }
1389
1390 void OptionParsingStarting(ExecutionContext *execution_context) override {
1391 match_info.Clear();
1392 show_args = false;
1393 verbose = false;
1394 }
1395
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001396 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001397 return llvm::makeArrayRef(g_platform_process_list_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001398 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001399
1400 // Instance variables to hold the values for command options.
1401
1402 ProcessInstanceInfoMatch match_info;
1403 bool show_args;
1404 bool verbose;
1405 };
1406
1407 CommandOptions m_options;
Greg Clayton32e0a752011-03-30 18:16:51 +00001408};
1409
Greg Clayton95bf0fd2011-04-01 00:29:43 +00001410//----------------------------------------------------------------------
1411// "platform process info"
1412//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +00001413class CommandObjectPlatformProcessInfo : public CommandObjectParsed {
Greg Clayton95bf0fd2011-04-01 00:29:43 +00001414public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001415 CommandObjectPlatformProcessInfo(CommandInterpreter &interpreter)
1416 : CommandObjectParsed(
1417 interpreter, "platform process info",
1418 "Get detailed information for one or more process by process ID.",
1419 "platform process info <pid> [<pid> <pid> ...]", 0) {
1420 CommandArgumentEntry arg;
1421 CommandArgumentData pid_args;
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001422
Kate Stoneb9c1b512016-09-06 20:57:50 +00001423 // Define the first (and only) variant of this arg.
1424 pid_args.arg_type = eArgTypePid;
1425 pid_args.arg_repetition = eArgRepeatStar;
1426
1427 // There is only one variant this argument could be; put it into the
1428 // argument entry.
1429 arg.push_back(pid_args);
1430
1431 // Push the data for the first argument into the m_arguments vector.
1432 m_arguments.push_back(arg);
1433 }
1434
1435 ~CommandObjectPlatformProcessInfo() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001436
Jim Ingham5a988412012-06-08 21:56:10 +00001437protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001438 bool DoExecute(Args &args, CommandReturnObject &result) override {
1439 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1440 PlatformSP platform_sp;
1441 if (target) {
1442 platform_sp = target->GetPlatform();
Greg Clayton95bf0fd2011-04-01 00:29:43 +00001443 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001444 if (!platform_sp) {
1445 platform_sp =
1446 m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform();
1447 }
1448
1449 if (platform_sp) {
1450 const size_t argc = args.GetArgumentCount();
1451 if (argc > 0) {
1452 Error error;
1453
1454 if (platform_sp->IsConnected()) {
1455 Stream &ostrm = result.GetOutputStream();
Zachary Turner97d2c402016-10-05 23:40:23 +00001456 for (auto &entry : args.entries()) {
1457 lldb::pid_t pid;
1458 if (entry.ref.getAsInteger(0, pid)) {
1459 result.AppendErrorWithFormat("invalid process ID argument '%s'",
1460 entry.ref.str().c_str());
1461 result.SetStatus(eReturnStatusFailed);
1462 break;
1463 } else {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001464 ProcessInstanceInfo proc_info;
1465 if (platform_sp->GetProcessInfo(pid, proc_info)) {
1466 ostrm.Printf("Process information for process %" PRIu64 ":\n",
1467 pid);
1468 proc_info.Dump(ostrm, platform_sp.get());
1469 } else {
1470 ostrm.Printf("error: no process information is available for "
1471 "process %" PRIu64 "\n",
1472 pid);
1473 }
1474 ostrm.EOL();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001475 }
1476 }
1477 } else {
1478 // Not connected...
1479 result.AppendErrorWithFormat(
1480 "not connected to '%s'",
1481 platform_sp->GetPluginName().GetCString());
1482 result.SetStatus(eReturnStatusFailed);
1483 }
1484 } else {
1485 // No args
1486 result.AppendError("one or more process id(s) must be specified");
1487 result.SetStatus(eReturnStatusFailed);
1488 }
1489 } else {
1490 result.AppendError("no platform is currently selected");
1491 result.SetStatus(eReturnStatusFailed);
1492 }
1493 return result.Succeeded();
1494 }
Greg Clayton95bf0fd2011-04-01 00:29:43 +00001495};
1496
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001497static OptionDefinition g_platform_process_attach_options[] = {
1498 // clang-format off
1499 { LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePlugin, "Name of the process plugin you want to use." },
1500 { LLDB_OPT_SET_1, false, "pid", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePid, "The process ID of an existing process to attach to." },
1501 { LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeProcessName, "The name of the process to attach to." },
1502 { LLDB_OPT_SET_2, false, "waitfor", 'w', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Wait for the process with <process-name> to launch." },
1503 // clang-format on
1504};
1505
Kate Stoneb9c1b512016-09-06 20:57:50 +00001506class CommandObjectPlatformProcessAttach : public CommandObjectParsed {
Daniel Maleae0f8f572013-08-26 23:57:52 +00001507public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001508 class CommandOptions : public Options {
1509 public:
1510 CommandOptions() : Options() {
1511 // Keep default values of all options in one place: OptionParsingStarting
1512 // ()
1513 OptionParsingStarting(nullptr);
Daniel Maleae0f8f572013-08-26 23:57:52 +00001514 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001515
Kate Stoneb9c1b512016-09-06 20:57:50 +00001516 ~CommandOptions() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001517
Kate Stoneb9c1b512016-09-06 20:57:50 +00001518 Error SetOptionValue(uint32_t option_idx, const char *option_arg,
1519 ExecutionContext *execution_context) override {
1520 Error error;
1521 char short_option = (char)m_getopt_table[option_idx].val;
1522 bool success = false;
1523 switch (short_option) {
1524 case 'p': {
1525 lldb::pid_t pid = StringConvert::ToUInt32(
1526 option_arg, LLDB_INVALID_PROCESS_ID, 0, &success);
1527 if (!success || pid == LLDB_INVALID_PROCESS_ID) {
1528 error.SetErrorStringWithFormat("invalid process ID '%s'", option_arg);
1529 } else {
1530 attach_info.SetProcessID(pid);
Daniel Maleae0f8f572013-08-26 23:57:52 +00001531 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001532 } break;
1533
1534 case 'P':
1535 attach_info.SetProcessPluginName(option_arg);
1536 break;
1537
1538 case 'n':
1539 attach_info.GetExecutableFile().SetFile(option_arg, false);
1540 break;
1541
1542 case 'w':
1543 attach_info.SetWaitForLaunch(true);
1544 break;
1545
1546 default:
1547 error.SetErrorStringWithFormat("invalid short option character '%c'",
1548 short_option);
1549 break;
1550 }
1551 return error;
1552 }
1553
1554 void OptionParsingStarting(ExecutionContext *execution_context) override {
1555 attach_info.Clear();
1556 }
1557
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001558 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001559 return llvm::makeArrayRef(g_platform_process_attach_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001560 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001561
1562 bool HandleOptionArgumentCompletion(
1563 Args &input, int cursor_index, int char_pos,
1564 OptionElementVector &opt_element_vector, int opt_element_index,
1565 int match_start_point, int max_return_elements,
1566 CommandInterpreter &interpreter, bool &word_complete,
1567 StringList &matches) override {
1568 int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
1569 int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
1570
1571 // We are only completing the name option for now...
1572
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001573 if (GetDefinitions()[opt_defs_index].short_option == 'n') {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001574 // Are we in the name?
1575
1576 // Look to see if there is a -P argument provided, and if so use that
1577 // plugin, otherwise
1578 // use the default plugin.
1579
1580 const char *partial_name = nullptr;
1581 partial_name = input.GetArgumentAtIndex(opt_arg_pos);
1582
1583 PlatformSP platform_sp(interpreter.GetPlatform(true));
1584 if (platform_sp) {
1585 ProcessInstanceInfoList process_infos;
1586 ProcessInstanceInfoMatch match_info;
1587 if (partial_name) {
1588 match_info.GetProcessInfo().GetExecutableFile().SetFile(
1589 partial_name, false);
1590 match_info.SetNameMatchType(eNameMatchStartsWith);
1591 }
1592 platform_sp->FindProcesses(match_info, process_infos);
1593 const uint32_t num_matches = process_infos.GetSize();
1594 if (num_matches > 0) {
1595 for (uint32_t i = 0; i < num_matches; ++i) {
1596 matches.AppendString(
1597 process_infos.GetProcessNameAtIndex(i),
1598 process_infos.GetProcessNameLengthAtIndex(i));
1599 }
1600 }
Daniel Maleae0f8f572013-08-26 23:57:52 +00001601 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001602 }
1603
1604 return false;
Daniel Maleae0f8f572013-08-26 23:57:52 +00001605 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001606
1607 // Options table: Required for subclasses of Options.
1608
1609 static OptionDefinition g_option_table[];
1610
1611 // Instance variables to hold the values for command options.
1612
1613 ProcessAttachInfo attach_info;
1614 };
1615
1616 CommandObjectPlatformProcessAttach(CommandInterpreter &interpreter)
1617 : CommandObjectParsed(interpreter, "platform process attach",
1618 "Attach to a process.",
1619 "platform process attach <cmd-options>"),
1620 m_options() {}
1621
1622 ~CommandObjectPlatformProcessAttach() override = default;
1623
1624 bool DoExecute(Args &command, CommandReturnObject &result) override {
1625 PlatformSP platform_sp(
1626 m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
1627 if (platform_sp) {
1628 Error err;
1629 ProcessSP remote_process_sp = platform_sp->Attach(
1630 m_options.attach_info, m_interpreter.GetDebugger(), nullptr, err);
1631 if (err.Fail()) {
1632 result.AppendError(err.AsCString());
1633 result.SetStatus(eReturnStatusFailed);
1634 } else if (!remote_process_sp) {
1635 result.AppendError("could not attach: unknown reason");
1636 result.SetStatus(eReturnStatusFailed);
1637 } else
1638 result.SetStatus(eReturnStatusSuccessFinishResult);
1639 } else {
1640 result.AppendError("no platform is currently selected");
1641 result.SetStatus(eReturnStatusFailed);
Daniel Maleae0f8f572013-08-26 23:57:52 +00001642 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001643 return result.Succeeded();
1644 }
1645
1646 Options *GetOptions() override { return &m_options; }
1647
Daniel Maleae0f8f572013-08-26 23:57:52 +00001648protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001649 CommandOptions m_options;
Daniel Maleae0f8f572013-08-26 23:57:52 +00001650};
Greg Clayton95bf0fd2011-04-01 00:29:43 +00001651
Kate Stoneb9c1b512016-09-06 20:57:50 +00001652class CommandObjectPlatformProcess : public CommandObjectMultiword {
Greg Clayton32e0a752011-03-30 18:16:51 +00001653public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001654 //------------------------------------------------------------------
1655 // Constructors and Destructors
1656 //------------------------------------------------------------------
1657 CommandObjectPlatformProcess(CommandInterpreter &interpreter)
1658 : CommandObjectMultiword(interpreter, "platform process",
1659 "Commands to query, launch and attach to "
1660 "processes on the current platform.",
1661 "platform process [attach|launch|list] ...") {
1662 LoadSubCommand(
1663 "attach",
1664 CommandObjectSP(new CommandObjectPlatformProcessAttach(interpreter)));
1665 LoadSubCommand(
1666 "launch",
1667 CommandObjectSP(new CommandObjectPlatformProcessLaunch(interpreter)));
1668 LoadSubCommand("info", CommandObjectSP(new CommandObjectPlatformProcessInfo(
1669 interpreter)));
1670 LoadSubCommand("list", CommandObjectSP(new CommandObjectPlatformProcessList(
1671 interpreter)));
1672 }
Greg Clayton32e0a752011-03-30 18:16:51 +00001673
Kate Stoneb9c1b512016-09-06 20:57:50 +00001674 ~CommandObjectPlatformProcess() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001675
Greg Clayton32e0a752011-03-30 18:16:51 +00001676private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001677 //------------------------------------------------------------------
1678 // For CommandObjectPlatform only
1679 //------------------------------------------------------------------
1680 DISALLOW_COPY_AND_ASSIGN(CommandObjectPlatformProcess);
Greg Clayton32e0a752011-03-30 18:16:51 +00001681};
Greg Claytonded470d2011-03-19 01:12:21 +00001682
Daniel Maleae0f8f572013-08-26 23:57:52 +00001683//----------------------------------------------------------------------
1684// "platform shell"
1685//----------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001686static OptionDefinition g_platform_shell_options[] = {
1687 // clang-format off
1688 { LLDB_OPT_SET_ALL, false, "timeout", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeValue, "Seconds to wait for the remote host to finish running the command." },
1689 // clang-format on
1690};
1691
Kate Stoneb9c1b512016-09-06 20:57:50 +00001692class CommandObjectPlatformShell : public CommandObjectRaw {
Greg Claytond1cf11a2012-04-14 01:42:46 +00001693public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001694 class CommandOptions : public Options {
1695 public:
1696 CommandOptions() : Options(), timeout(10) {}
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001697
Kate Stoneb9c1b512016-09-06 20:57:50 +00001698 ~CommandOptions() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001699
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001700 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001701 return llvm::makeArrayRef(g_platform_shell_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001702 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001703
1704 Error SetOptionValue(uint32_t option_idx, const char *option_value,
1705 ExecutionContext *execution_context) override {
1706 Error error;
1707
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001708 const char short_option = (char)GetDefinitions()[option_idx].short_option;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001709
1710 switch (short_option) {
1711 case 't': {
1712 bool success;
1713 timeout = StringConvert::ToUInt32(option_value, 10, 10, &success);
1714 if (!success)
1715 error.SetErrorStringWithFormat(
1716 "could not convert \"%s\" to a numeric value.", option_value);
1717 break;
1718 }
1719 default:
1720 error.SetErrorStringWithFormat("invalid short option character '%c'",
1721 short_option);
1722 break;
1723 }
1724
1725 return error;
Greg Claytond1cf11a2012-04-14 01:42:46 +00001726 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001727
Kate Stoneb9c1b512016-09-06 20:57:50 +00001728 void OptionParsingStarting(ExecutionContext *execution_context) override {}
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001729
Kate Stoneb9c1b512016-09-06 20:57:50 +00001730 uint32_t timeout;
1731 };
Daniel Maleae0f8f572013-08-26 23:57:52 +00001732
Kate Stoneb9c1b512016-09-06 20:57:50 +00001733 CommandObjectPlatformShell(CommandInterpreter &interpreter)
1734 : CommandObjectRaw(interpreter, "platform shell",
1735 "Run a shell command on the current platform.",
1736 "platform shell <shell-command>", 0),
1737 m_options() {}
Greg Claytond1cf11a2012-04-14 01:42:46 +00001738
Kate Stoneb9c1b512016-09-06 20:57:50 +00001739 ~CommandObjectPlatformShell() override = default;
1740
1741 Options *GetOptions() override { return &m_options; }
1742
1743 bool DoExecute(const char *raw_command_line,
1744 CommandReturnObject &result) override {
1745 ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext();
1746 m_options.NotifyOptionParsingStarting(&exe_ctx);
1747
1748 const char *expr = nullptr;
1749
1750 // Print out an usage syntax on an empty command line.
1751 if (raw_command_line[0] == '\0') {
1752 result.GetOutputStream().Printf("%s\n", this->GetSyntax());
1753 return true;
Greg Claytond1cf11a2012-04-14 01:42:46 +00001754 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001755
Kate Stoneb9c1b512016-09-06 20:57:50 +00001756 if (raw_command_line[0] == '-') {
1757 // We have some options and these options MUST end with --.
1758 const char *end_options = nullptr;
1759 const char *s = raw_command_line;
1760 while (s && s[0]) {
1761 end_options = ::strstr(s, "--");
1762 if (end_options) {
1763 end_options += 2; // Get past the "--"
1764 if (::isspace(end_options[0])) {
1765 expr = end_options;
1766 while (::isspace(*expr))
1767 ++expr;
1768 break;
1769 }
1770 }
1771 s = end_options;
1772 }
1773
1774 if (end_options) {
1775 Args args(
1776 llvm::StringRef(raw_command_line, end_options - raw_command_line));
1777 if (!ParseOptions(args, result))
1778 return false;
1779 }
1780 }
1781
1782 if (expr == nullptr)
1783 expr = raw_command_line;
1784
1785 PlatformSP platform_sp(
1786 m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
1787 Error error;
1788 if (platform_sp) {
1789 FileSpec working_dir{};
1790 std::string output;
1791 int status = -1;
1792 int signo = -1;
1793 error = (platform_sp->RunShellCommand(expr, working_dir, &status, &signo,
1794 &output, m_options.timeout));
1795 if (!output.empty())
1796 result.GetOutputStream().PutCString(output.c_str());
1797 if (status > 0) {
1798 if (signo > 0) {
1799 const char *signo_cstr = Host::GetSignalAsCString(signo);
1800 if (signo_cstr)
1801 result.GetOutputStream().Printf(
1802 "error: command returned with status %i and signal %s\n",
1803 status, signo_cstr);
1804 else
1805 result.GetOutputStream().Printf(
1806 "error: command returned with status %i and signal %i\n",
1807 status, signo);
1808 } else
1809 result.GetOutputStream().Printf(
1810 "error: command returned with status %i\n", status);
1811 }
1812 } else {
1813 result.GetOutputStream().Printf(
1814 "error: cannot run remote shell commands without a platform\n");
1815 error.SetErrorString(
1816 "error: cannot run remote shell commands without a platform");
1817 }
1818
1819 if (error.Fail()) {
1820 result.AppendError(error.AsCString());
1821 result.SetStatus(eReturnStatusFailed);
1822 } else {
1823 result.SetStatus(eReturnStatusSuccessFinishResult);
1824 }
1825 return true;
1826 }
1827
1828 CommandOptions m_options;
Daniel Maleae0f8f572013-08-26 23:57:52 +00001829};
1830
Daniel Maleae0f8f572013-08-26 23:57:52 +00001831//----------------------------------------------------------------------
1832// "platform install" - install a target to a remote end
1833//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +00001834class CommandObjectPlatformInstall : public CommandObjectParsed {
Daniel Maleae0f8f572013-08-26 23:57:52 +00001835public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001836 CommandObjectPlatformInstall(CommandInterpreter &interpreter)
1837 : CommandObjectParsed(
1838 interpreter, "platform target-install",
1839 "Install a target (bundle or executable file) to the remote end.",
1840 "platform target-install <local-thing> <remote-sandbox>", 0) {}
1841
1842 ~CommandObjectPlatformInstall() override = default;
1843
1844 bool DoExecute(Args &args, CommandReturnObject &result) override {
1845 if (args.GetArgumentCount() != 2) {
1846 result.AppendError("platform target-install takes two arguments");
1847 result.SetStatus(eReturnStatusFailed);
1848 return false;
1849 }
1850 // TODO: move the bulk of this code over to the platform itself
1851 FileSpec src(args.GetArgumentAtIndex(0), true);
1852 FileSpec dst(args.GetArgumentAtIndex(1), false);
1853 if (!src.Exists()) {
1854 result.AppendError("source location does not exist or is not accessible");
1855 result.SetStatus(eReturnStatusFailed);
1856 return false;
1857 }
1858 PlatformSP platform_sp(
1859 m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
1860 if (!platform_sp) {
1861 result.AppendError("no platform currently selected");
1862 result.SetStatus(eReturnStatusFailed);
1863 return false;
Daniel Maleae0f8f572013-08-26 23:57:52 +00001864 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001865
Kate Stoneb9c1b512016-09-06 20:57:50 +00001866 Error error = platform_sp->Install(src, dst);
1867 if (error.Success()) {
1868 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1869 } else {
1870 result.AppendErrorWithFormat("install failed: %s", error.AsCString());
1871 result.SetStatus(eReturnStatusFailed);
Daniel Maleae0f8f572013-08-26 23:57:52 +00001872 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001873 return result.Succeeded();
1874 }
Greg Claytond1cf11a2012-04-14 01:42:46 +00001875};
1876
Kate Stone7428a182016-07-14 22:03:10 +00001877CommandObjectPlatform::CommandObjectPlatform(CommandInterpreter &interpreter)
Kate Stoneb9c1b512016-09-06 20:57:50 +00001878 : CommandObjectMultiword(
1879 interpreter, "platform", "Commands to manage and create platforms.",
1880 "platform [connect|disconnect|info|list|status|select] ...") {
1881 LoadSubCommand("select",
1882 CommandObjectSP(new CommandObjectPlatformSelect(interpreter)));
1883 LoadSubCommand("list",
1884 CommandObjectSP(new CommandObjectPlatformList(interpreter)));
1885 LoadSubCommand("status",
1886 CommandObjectSP(new CommandObjectPlatformStatus(interpreter)));
1887 LoadSubCommand("connect", CommandObjectSP(
1888 new CommandObjectPlatformConnect(interpreter)));
1889 LoadSubCommand(
1890 "disconnect",
1891 CommandObjectSP(new CommandObjectPlatformDisconnect(interpreter)));
1892 LoadSubCommand("settings", CommandObjectSP(new CommandObjectPlatformSettings(
1893 interpreter)));
1894 LoadSubCommand("mkdir",
1895 CommandObjectSP(new CommandObjectPlatformMkDir(interpreter)));
1896 LoadSubCommand("file",
1897 CommandObjectSP(new CommandObjectPlatformFile(interpreter)));
1898 LoadSubCommand("get-file", CommandObjectSP(new CommandObjectPlatformGetFile(
1899 interpreter)));
1900 LoadSubCommand("get-size", CommandObjectSP(new CommandObjectPlatformGetSize(
1901 interpreter)));
1902 LoadSubCommand("put-file", CommandObjectSP(new CommandObjectPlatformPutFile(
1903 interpreter)));
1904 LoadSubCommand("process", CommandObjectSP(
1905 new CommandObjectPlatformProcess(interpreter)));
1906 LoadSubCommand("shell",
1907 CommandObjectSP(new CommandObjectPlatformShell(interpreter)));
1908 LoadSubCommand(
1909 "target-install",
1910 CommandObjectSP(new CommandObjectPlatformInstall(interpreter)));
Greg Claytonded470d2011-03-19 01:12:21 +00001911}
1912
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001913CommandObjectPlatform::~CommandObjectPlatform() = default;