blob: 22a9a169c7c8ac476b3f8b281d6651fc1395490e [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/Debugger.h"
Greg Clayton1f746072012-08-29 21:13:06 +000017#include "lldb/Core/Module.h"
Greg Claytonded470d2011-03-19 01:12:21 +000018#include "lldb/Core/PluginManager.h"
Zachary Turner3eb2b442017-03-22 23:33:16 +000019#include "lldb/Host/OptionParser.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/CommandInterpreter.h"
Zachary Turnerd37221d2014-07-09 16:31:49 +000022#include "lldb/Interpreter/CommandOptionValidators.h"
Greg Claytonded470d2011-03-19 01:12:21 +000023#include "lldb/Interpreter/CommandReturnObject.h"
Greg Claytonfbb76342013-11-20 21:07:01 +000024#include "lldb/Interpreter/OptionGroupFile.h"
Greg Clayton7260f622011-04-18 08:33:37 +000025#include "lldb/Interpreter/OptionGroupPlatform.h"
Greg Claytonded470d2011-03-19 01:12:21 +000026#include "lldb/Target/ExecutionContext.h"
27#include "lldb/Target/Platform.h"
Greg Claytoneb0103f2011-04-07 22:46:35 +000028#include "lldb/Target/Process.h"
Pavel Labath145d95c2018-04-17 18:53:35 +000029#include "lldb/Utility/Args.h"
Zachary Turner666cc0b2017-03-04 01:30:05 +000030#include "lldb/Utility/DataExtractor.h"
Greg Claytonded470d2011-03-19 01:12:21 +000031
Zachary Turnerecbb0bb2016-09-19 17:54:06 +000032#include "llvm/ADT/SmallString.h"
Kamil Rytarowskic5f28e22017-02-06 17:55:02 +000033#include "llvm/Support/Threading.h"
Zachary Turnerecbb0bb2016-09-19 17:54:06 +000034
Greg Claytonded470d2011-03-19 01:12:21 +000035using namespace lldb;
36using namespace lldb_private;
37
Zachary Turner8cef4b02016-09-23 17:48:13 +000038static mode_t ParsePermissionString(const char *) = delete;
39
40static mode_t ParsePermissionString(llvm::StringRef permissions) {
41 if (permissions.size() != 9)
Kate Stoneb9c1b512016-09-06 20:57:50 +000042 return (mode_t)(-1);
43 bool user_r, user_w, user_x, group_r, group_w, group_x, world_r, world_w,
44 world_x;
45
46 user_r = (permissions[0] == 'r');
47 user_w = (permissions[1] == 'w');
48 user_x = (permissions[2] == 'x');
49
50 group_r = (permissions[3] == 'r');
51 group_w = (permissions[4] == 'w');
52 group_x = (permissions[5] == 'x');
53
54 world_r = (permissions[6] == 'r');
55 world_w = (permissions[7] == 'w');
56 world_x = (permissions[8] == 'x');
57
58 mode_t user, group, world;
59 user = (user_r ? 4 : 0) | (user_w ? 2 : 0) | (user_x ? 1 : 0);
60 group = (group_r ? 4 : 0) | (group_w ? 2 : 0) | (group_x ? 1 : 0);
61 world = (world_r ? 4 : 0) | (world_w ? 2 : 0) | (world_x ? 1 : 0);
62
63 return user | group | world;
Daniel Maleae0f8f572013-08-26 23:57:52 +000064}
65
Kate Stoneb9c1b512016-09-06 20:57:50 +000066static OptionDefinition g_permissions_options[] = {
67 // clang-format off
Kate Stoneac9c3a62016-08-26 23:28:47 +000068 {LLDB_OPT_SET_ALL, false, "permissions-value", 'v', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePermissionsNumber, "Give out the numeric value for permissions (e.g. 757)"},
69 {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--)."},
70 {LLDB_OPT_SET_ALL, false, "user-read", 'r', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow user to read."},
71 {LLDB_OPT_SET_ALL, false, "user-write", 'w', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow user to write."},
72 {LLDB_OPT_SET_ALL, false, "user-exec", 'x', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow user to execute."},
73 {LLDB_OPT_SET_ALL, false, "group-read", 'R', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow group to read."},
74 {LLDB_OPT_SET_ALL, false, "group-write", 'W', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow group to write."},
75 {LLDB_OPT_SET_ALL, false, "group-exec", 'X', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow group to execute."},
76 {LLDB_OPT_SET_ALL, false, "world-read", 'd', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow world to read."},
77 {LLDB_OPT_SET_ALL, false, "world-write", 't', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Allow world to write."},
78 {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 +000079 // clang-format on
Daniel Maleae0f8f572013-08-26 23:57:52 +000080};
81
Zachary Turner8cef4b02016-09-23 17:48:13 +000082class OptionPermissions : public OptionGroup {
Daniel Maleae0f8f572013-08-26 23:57:52 +000083public:
Kate Stoneb9c1b512016-09-06 20:57:50 +000084 OptionPermissions() {}
85
86 ~OptionPermissions() override = default;
87
Zachary Turner97206d52017-05-12 04:51:55 +000088 lldb_private::Status
Zachary Turner8cef4b02016-09-23 17:48:13 +000089 SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
Kate Stoneb9c1b512016-09-06 20:57:50 +000090 ExecutionContext *execution_context) override {
Zachary Turner97206d52017-05-12 04:51:55 +000091 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +000092 char short_option = (char)GetDefinitions()[option_idx].short_option;
93 switch (short_option) {
94 case 'v': {
Zachary Turner8cef4b02016-09-23 17:48:13 +000095 if (option_arg.getAsInteger(8, m_permissions)) {
96 m_permissions = 0777;
Kate Stoneb9c1b512016-09-06 20:57:50 +000097 error.SetErrorStringWithFormat("invalid value for permissions: %s",
Zachary Turner8cef4b02016-09-23 17:48:13 +000098 option_arg.str().c_str());
99 }
100
Kate Stoneb9c1b512016-09-06 20:57:50 +0000101 } break;
102 case 's': {
103 mode_t perms = ParsePermissionString(option_arg);
104 if (perms == (mode_t)-1)
105 error.SetErrorStringWithFormat("invalid value for permissions: %s",
Zachary Turner8cef4b02016-09-23 17:48:13 +0000106 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000107 else
108 m_permissions = perms;
109 } break;
110 case 'r':
111 m_permissions |= lldb::eFilePermissionsUserRead;
112 break;
113 case 'w':
114 m_permissions |= lldb::eFilePermissionsUserWrite;
115 break;
116 case 'x':
117 m_permissions |= lldb::eFilePermissionsUserExecute;
118 break;
119 case 'R':
120 m_permissions |= lldb::eFilePermissionsGroupRead;
121 break;
122 case 'W':
123 m_permissions |= lldb::eFilePermissionsGroupWrite;
124 break;
125 case 'X':
126 m_permissions |= lldb::eFilePermissionsGroupExecute;
127 break;
128 case 'd':
129 m_permissions |= lldb::eFilePermissionsWorldRead;
130 break;
131 case 't':
132 m_permissions |= lldb::eFilePermissionsWorldWrite;
133 break;
134 case 'e':
135 m_permissions |= lldb::eFilePermissionsWorldExecute;
136 break;
137 default:
138 error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
139 break;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000140 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000141
Kate Stoneb9c1b512016-09-06 20:57:50 +0000142 return error;
143 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000144
Kate Stoneb9c1b512016-09-06 20:57:50 +0000145 void OptionParsingStarting(ExecutionContext *execution_context) override {
146 m_permissions = 0;
147 }
148
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000149 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +0000150 return llvm::makeArrayRef(g_permissions_options);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000151 }
152
153 // Instance variables to hold the values for command options.
154
155 uint32_t m_permissions;
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000156
Daniel Maleae0f8f572013-08-26 23:57:52 +0000157private:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000158 DISALLOW_COPY_AND_ASSIGN(OptionPermissions);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000159};
Greg Claytonf6b8b582011-04-13 00:18:08 +0000160
Greg Claytonded470d2011-03-19 01:12:21 +0000161//----------------------------------------------------------------------
Greg Clayton7260f622011-04-18 08:33:37 +0000162// "platform select <platform-name>"
Greg Claytonded470d2011-03-19 01:12:21 +0000163//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000164class CommandObjectPlatformSelect : public CommandObjectParsed {
Greg Claytonded470d2011-03-19 01:12:21 +0000165public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000166 CommandObjectPlatformSelect(CommandInterpreter &interpreter)
167 : CommandObjectParsed(interpreter, "platform select",
168 "Create a platform if needed and select it as the "
169 "current platform.",
170 "platform select <platform-name>", 0),
171 m_option_group(),
172 m_platform_options(
173 false) // Don't include the "--platform" option by passing false
174 {
175 m_option_group.Append(&m_platform_options, LLDB_OPT_SET_ALL, 1);
176 m_option_group.Finalize();
177 }
Greg Claytonded470d2011-03-19 01:12:21 +0000178
Kate Stoneb9c1b512016-09-06 20:57:50 +0000179 ~CommandObjectPlatformSelect() override = default;
Greg Claytonded470d2011-03-19 01:12:21 +0000180
Raphael Isemann2443bbd2018-07-02 21:29:56 +0000181 int HandleCompletion(CompletionRequest &request) override {
Raphael Isemanna2e76c02018-07-13 18:28:14 +0000182 CommandCompletions::PlatformPluginNames(GetCommandInterpreter(), request,
183 nullptr);
Raphael Isemann1a6d7ab2018-07-27 18:42:46 +0000184 return request.GetNumberOfMatches();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000185 }
186
187 Options *GetOptions() override { return &m_option_group; }
Jim Ingham5a988412012-06-08 21:56:10 +0000188
189protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000190 bool DoExecute(Args &args, CommandReturnObject &result) override {
191 if (args.GetArgumentCount() == 1) {
192 const char *platform_name = args.GetArgumentAtIndex(0);
193 if (platform_name && platform_name[0]) {
194 const bool select = true;
195 m_platform_options.SetPlatformName(platform_name);
Zachary Turner97206d52017-05-12 04:51:55 +0000196 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000197 ArchSpec platform_arch;
198 PlatformSP platform_sp(m_platform_options.CreatePlatformWithOptions(
199 m_interpreter, ArchSpec(), select, error, platform_arch));
200 if (platform_sp) {
201 m_interpreter.GetDebugger().GetPlatformList().SetSelectedPlatform(
202 platform_sp);
Vince Harron1b5a74e2015-01-21 22:42:49 +0000203
Kate Stoneb9c1b512016-09-06 20:57:50 +0000204 platform_sp->GetStatus(result.GetOutputStream());
205 result.SetStatus(eReturnStatusSuccessFinishResult);
206 } else {
207 result.AppendError(error.AsCString());
208 result.SetStatus(eReturnStatusFailed);
Greg Claytonded470d2011-03-19 01:12:21 +0000209 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000210 } else {
211 result.AppendError("invalid platform name");
212 result.SetStatus(eReturnStatusFailed);
213 }
214 } else {
215 result.AppendError(
216 "platform create takes a platform name as an argument\n");
217 result.SetStatus(eReturnStatusFailed);
Greg Claytonded470d2011-03-19 01:12:21 +0000218 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000219 return result.Succeeded();
220 }
Greg Clayton7260f622011-04-18 08:33:37 +0000221
Kate Stoneb9c1b512016-09-06 20:57:50 +0000222 OptionGroupOptions m_option_group;
223 OptionGroupPlatform m_platform_options;
Greg Claytonded470d2011-03-19 01:12:21 +0000224};
225
226//----------------------------------------------------------------------
227// "platform list"
228//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000229class CommandObjectPlatformList : public CommandObjectParsed {
Greg Claytonded470d2011-03-19 01:12:21 +0000230public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000231 CommandObjectPlatformList(CommandInterpreter &interpreter)
232 : CommandObjectParsed(interpreter, "platform list",
233 "List all platforms that are available.", nullptr,
234 0) {}
Greg Claytonded470d2011-03-19 01:12:21 +0000235
Kate Stoneb9c1b512016-09-06 20:57:50 +0000236 ~CommandObjectPlatformList() override = default;
Greg Claytonded470d2011-03-19 01:12:21 +0000237
Jim Ingham5a988412012-06-08 21:56:10 +0000238protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000239 bool DoExecute(Args &args, CommandReturnObject &result) override {
240 Stream &ostrm = result.GetOutputStream();
241 ostrm.Printf("Available platforms:\n");
Greg Claytonded470d2011-03-19 01:12:21 +0000242
Kate Stoneb9c1b512016-09-06 20:57:50 +0000243 PlatformSP host_platform_sp(Platform::GetHostPlatform());
244 ostrm.Printf("%s: %s\n", host_platform_sp->GetPluginName().GetCString(),
245 host_platform_sp->GetDescription());
246
247 uint32_t idx;
248 for (idx = 0; 1; ++idx) {
249 const char *plugin_name =
250 PluginManager::GetPlatformPluginNameAtIndex(idx);
251 if (plugin_name == nullptr)
252 break;
253 const char *plugin_desc =
254 PluginManager::GetPlatformPluginDescriptionAtIndex(idx);
255 if (plugin_desc == nullptr)
256 break;
257 ostrm.Printf("%s: %s\n", plugin_name, plugin_desc);
Greg Claytonded470d2011-03-19 01:12:21 +0000258 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000259
260 if (idx == 0) {
261 result.AppendError("no platforms are available\n");
262 result.SetStatus(eReturnStatusFailed);
263 } else
264 result.SetStatus(eReturnStatusSuccessFinishResult);
265 return result.Succeeded();
266 }
Greg Claytonded470d2011-03-19 01:12:21 +0000267};
268
269//----------------------------------------------------------------------
270// "platform status"
271//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000272class CommandObjectPlatformStatus : public CommandObjectParsed {
Greg Claytonded470d2011-03-19 01:12:21 +0000273public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000274 CommandObjectPlatformStatus(CommandInterpreter &interpreter)
275 : CommandObjectParsed(interpreter, "platform status",
276 "Display status for the current platform.", nullptr,
277 0) {}
Greg Claytonded470d2011-03-19 01:12:21 +0000278
Kate Stoneb9c1b512016-09-06 20:57:50 +0000279 ~CommandObjectPlatformStatus() override = default;
Greg Claytonded470d2011-03-19 01:12:21 +0000280
Jim Ingham5a988412012-06-08 21:56:10 +0000281protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000282 bool DoExecute(Args &args, CommandReturnObject &result) override {
283 Stream &ostrm = result.GetOutputStream();
284
285 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
286 PlatformSP platform_sp;
287 if (target) {
288 platform_sp = target->GetPlatform();
Greg Claytonded470d2011-03-19 01:12:21 +0000289 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000290 if (!platform_sp) {
291 platform_sp =
292 m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform();
293 }
294 if (platform_sp) {
295 platform_sp->GetStatus(ostrm);
296 result.SetStatus(eReturnStatusSuccessFinishResult);
297 } else {
Bruce Mitchener2b139132017-07-21 07:08:20 +0000298 result.AppendError("no platform is currently selected\n");
Kate Stoneb9c1b512016-09-06 20:57:50 +0000299 result.SetStatus(eReturnStatusFailed);
300 }
301 return result.Succeeded();
302 }
Greg Claytonded470d2011-03-19 01:12:21 +0000303};
304
Greg Claytond314e812011-03-23 00:09:55 +0000305//----------------------------------------------------------------------
306// "platform connect <connect-url>"
307//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000308class CommandObjectPlatformConnect : public CommandObjectParsed {
Greg Claytond314e812011-03-23 00:09:55 +0000309public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000310 CommandObjectPlatformConnect(CommandInterpreter &interpreter)
311 : CommandObjectParsed(
312 interpreter, "platform connect",
313 "Select the current platform by providing a connection URL.",
314 "platform connect <connect-url>", 0) {}
Greg Claytond314e812011-03-23 00:09:55 +0000315
Kate Stoneb9c1b512016-09-06 20:57:50 +0000316 ~CommandObjectPlatformConnect() override = default;
Greg Claytond314e812011-03-23 00:09:55 +0000317
Jim Ingham5a988412012-06-08 21:56:10 +0000318protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000319 bool DoExecute(Args &args, CommandReturnObject &result) override {
320 Stream &ostrm = result.GetOutputStream();
Tamas Berghammerccd6cff2015-12-08 14:08:19 +0000321
Kate Stoneb9c1b512016-09-06 20:57:50 +0000322 PlatformSP platform_sp(
323 m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
324 if (platform_sp) {
Zachary Turner97206d52017-05-12 04:51:55 +0000325 Status error(platform_sp->ConnectRemote(args));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000326 if (error.Success()) {
327 platform_sp->GetStatus(ostrm);
328 result.SetStatus(eReturnStatusSuccessFinishResult);
329
330 platform_sp->ConnectToWaitingProcesses(m_interpreter.GetDebugger(),
331 error);
332 if (error.Fail()) {
333 result.AppendError(error.AsCString());
334 result.SetStatus(eReturnStatusFailed);
Greg Claytond314e812011-03-23 00:09:55 +0000335 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000336 } else {
337 result.AppendErrorWithFormat("%s\n", error.AsCString());
338 result.SetStatus(eReturnStatusFailed);
339 }
340 } else {
341 result.AppendError("no platform is currently selected\n");
342 result.SetStatus(eReturnStatusFailed);
Greg Claytond314e812011-03-23 00:09:55 +0000343 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000344 return result.Succeeded();
345 }
346
347 Options *GetOptions() override {
348 PlatformSP platform_sp(
349 m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
350 OptionGroupOptions *m_platform_options = nullptr;
351 if (platform_sp) {
352 m_platform_options = platform_sp->GetConnectionOptions(m_interpreter);
353 if (m_platform_options != nullptr && !m_platform_options->m_did_finalize)
354 m_platform_options->Finalize();
Daniel Maleae0f8f572013-08-26 23:57:52 +0000355 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000356 return m_platform_options;
357 }
Greg Claytond314e812011-03-23 00:09:55 +0000358};
359
360//----------------------------------------------------------------------
361// "platform disconnect"
362//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000363class CommandObjectPlatformDisconnect : public CommandObjectParsed {
Greg Claytond314e812011-03-23 00:09:55 +0000364public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000365 CommandObjectPlatformDisconnect(CommandInterpreter &interpreter)
366 : CommandObjectParsed(interpreter, "platform disconnect",
367 "Disconnect from the current platform.",
368 "platform disconnect", 0) {}
Greg Claytond314e812011-03-23 00:09:55 +0000369
Kate Stoneb9c1b512016-09-06 20:57:50 +0000370 ~CommandObjectPlatformDisconnect() override = default;
Greg Claytond314e812011-03-23 00:09:55 +0000371
Jim Ingham5a988412012-06-08 21:56:10 +0000372protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000373 bool DoExecute(Args &args, CommandReturnObject &result) override {
374 PlatformSP platform_sp(
375 m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
376 if (platform_sp) {
377 if (args.GetArgumentCount() == 0) {
Zachary Turner97206d52017-05-12 04:51:55 +0000378 Status error;
Greg Claytond314e812011-03-23 00:09:55 +0000379
Kate Stoneb9c1b512016-09-06 20:57:50 +0000380 if (platform_sp->IsConnected()) {
Adrian Prantl05097242018-04-30 16:49:04 +0000381 // Cache the instance name if there is one since we are about to
382 // disconnect and the name might go with it.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000383 const char *hostname_cstr = platform_sp->GetHostname();
384 std::string hostname;
385 if (hostname_cstr)
386 hostname.assign(hostname_cstr);
387
388 error = platform_sp->DisconnectRemote();
389 if (error.Success()) {
390 Stream &ostrm = result.GetOutputStream();
391 if (hostname.empty())
392 ostrm.Printf("Disconnected from \"%s\"\n",
393 platform_sp->GetPluginName().GetCString());
Greg Claytond314e812011-03-23 00:09:55 +0000394 else
Kate Stoneb9c1b512016-09-06 20:57:50 +0000395 ostrm.Printf("Disconnected from \"%s\"\n", hostname.c_str());
396 result.SetStatus(eReturnStatusSuccessFinishResult);
397 } else {
398 result.AppendErrorWithFormat("%s", error.AsCString());
399 result.SetStatus(eReturnStatusFailed);
400 }
401 } else {
402 // Not connected...
403 result.AppendErrorWithFormat(
404 "not connected to '%s'",
405 platform_sp->GetPluginName().GetCString());
406 result.SetStatus(eReturnStatusFailed);
Greg Claytond314e812011-03-23 00:09:55 +0000407 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000408 } else {
409 // Bad args
410 result.AppendError(
411 "\"platform disconnect\" doesn't take any arguments");
412 result.SetStatus(eReturnStatusFailed);
413 }
414 } else {
415 result.AppendError("no platform is currently selected");
416 result.SetStatus(eReturnStatusFailed);
Greg Claytond314e812011-03-23 00:09:55 +0000417 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000418 return result.Succeeded();
419 }
Greg Claytond314e812011-03-23 00:09:55 +0000420};
Daniel Maleae0f8f572013-08-26 23:57:52 +0000421
422//----------------------------------------------------------------------
Greg Claytonfbb76342013-11-20 21:07:01 +0000423// "platform settings"
424//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000425class CommandObjectPlatformSettings : public CommandObjectParsed {
Greg Claytonfbb76342013-11-20 21:07:01 +0000426public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000427 CommandObjectPlatformSettings(CommandInterpreter &interpreter)
428 : CommandObjectParsed(interpreter, "platform settings",
429 "Set settings for the current target's platform, "
430 "or for a platform by name.",
431 "platform settings", 0),
Todd Fialae1cfbc72016-08-11 23:51:28 +0000432 m_options(),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000433 m_option_working_dir(LLDB_OPT_SET_1, false, "working-dir", 'w', 0,
434 eArgTypePath,
435 "The working directory for the platform.") {
436 m_options.Append(&m_option_working_dir, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
437 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000438
Kate Stoneb9c1b512016-09-06 20:57:50 +0000439 ~CommandObjectPlatformSettings() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000440
Greg Claytonfbb76342013-11-20 21:07:01 +0000441protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000442 bool DoExecute(Args &args, CommandReturnObject &result) override {
443 PlatformSP platform_sp(
444 m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
445 if (platform_sp) {
446 if (m_option_working_dir.GetOptionValue().OptionWasSet())
447 platform_sp->SetWorkingDirectory(
448 m_option_working_dir.GetOptionValue().GetCurrentValue());
449 } else {
450 result.AppendError("no platform is currently selected");
451 result.SetStatus(eReturnStatusFailed);
Greg Claytonfbb76342013-11-20 21:07:01 +0000452 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000453 return result.Succeeded();
454 }
455
456 Options *GetOptions() override {
457 if (!m_options.DidFinalize())
458 m_options.Finalize();
459 return &m_options;
460 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000461
Greg Claytonfbb76342013-11-20 21:07:01 +0000462protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000463 OptionGroupOptions m_options;
464 OptionGroupFile m_option_working_dir;
Greg Claytonfbb76342013-11-20 21:07:01 +0000465};
466
Greg Claytonfbb76342013-11-20 21:07:01 +0000467//----------------------------------------------------------------------
Daniel Maleae0f8f572013-08-26 23:57:52 +0000468// "platform mkdir"
469//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000470class CommandObjectPlatformMkDir : public CommandObjectParsed {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000471public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000472 CommandObjectPlatformMkDir(CommandInterpreter &interpreter)
473 : CommandObjectParsed(interpreter, "platform mkdir",
474 "Make a new directory on the remote end.", nullptr,
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000475 0),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000476 m_options() {}
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000477
Kate Stoneb9c1b512016-09-06 20:57:50 +0000478 ~CommandObjectPlatformMkDir() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000479
Kate Stoneb9c1b512016-09-06 20:57:50 +0000480 bool DoExecute(Args &args, CommandReturnObject &result) override {
481 PlatformSP platform_sp(
482 m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
483 if (platform_sp) {
484 std::string cmd_line;
485 args.GetCommandString(cmd_line);
486 uint32_t mode;
487 const OptionPermissions *options_permissions =
488 (const OptionPermissions *)m_options.GetGroupWithOption('r');
489 if (options_permissions)
490 mode = options_permissions->m_permissions;
491 else
492 mode = lldb::eFilePermissionsUserRWX | lldb::eFilePermissionsGroupRWX |
493 lldb::eFilePermissionsWorldRX;
Zachary Turner97206d52017-05-12 04:51:55 +0000494 Status error =
495 platform_sp->MakeDirectory(FileSpec{cmd_line, false}, mode);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000496 if (error.Success()) {
497 result.SetStatus(eReturnStatusSuccessFinishResult);
498 } else {
499 result.AppendError(error.AsCString());
500 result.SetStatus(eReturnStatusFailed);
501 }
502 } else {
503 result.AppendError("no platform currently selected\n");
504 result.SetStatus(eReturnStatusFailed);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000505 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000506 return result.Succeeded();
507 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000508
Kate Stoneb9c1b512016-09-06 20:57:50 +0000509 Options *GetOptions() override {
510 if (!m_options.DidFinalize()) {
511 m_options.Append(new OptionPermissions());
512 m_options.Finalize();
513 }
514 return &m_options;
515 }
516
517 OptionGroupOptions m_options;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000518};
519
520//----------------------------------------------------------------------
521// "platform fopen"
522//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000523class CommandObjectPlatformFOpen : public CommandObjectParsed {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000524public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000525 CommandObjectPlatformFOpen(CommandInterpreter &interpreter)
526 : CommandObjectParsed(interpreter, "platform file open",
527 "Open a file on the remote end.", nullptr, 0),
528 m_options() {}
529
530 ~CommandObjectPlatformFOpen() override = default;
531
532 bool DoExecute(Args &args, CommandReturnObject &result) override {
533 PlatformSP platform_sp(
534 m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
535 if (platform_sp) {
Zachary Turner97206d52017-05-12 04:51:55 +0000536 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000537 std::string cmd_line;
538 args.GetCommandString(cmd_line);
539 mode_t perms;
540 const OptionPermissions *options_permissions =
541 (const OptionPermissions *)m_options.GetGroupWithOption('r');
542 if (options_permissions)
543 perms = options_permissions->m_permissions;
544 else
545 perms = lldb::eFilePermissionsUserRW | lldb::eFilePermissionsGroupRW |
546 lldb::eFilePermissionsWorldRead;
547 lldb::user_id_t fd = platform_sp->OpenFile(
Malcolm Parsons771ef6d2016-11-02 20:34:10 +0000548 FileSpec(cmd_line, false),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000549 File::eOpenOptionRead | File::eOpenOptionWrite |
550 File::eOpenOptionAppend | File::eOpenOptionCanCreate,
551 perms, error);
552 if (error.Success()) {
553 result.AppendMessageWithFormat("File Descriptor = %" PRIu64 "\n", fd);
554 result.SetStatus(eReturnStatusSuccessFinishResult);
555 } else {
556 result.AppendError(error.AsCString());
557 result.SetStatus(eReturnStatusFailed);
558 }
559 } else {
560 result.AppendError("no platform currently selected\n");
561 result.SetStatus(eReturnStatusFailed);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000562 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000563 return result.Succeeded();
564 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000565
Kate Stoneb9c1b512016-09-06 20:57:50 +0000566 Options *GetOptions() override {
567 if (!m_options.DidFinalize()) {
568 m_options.Append(new OptionPermissions());
569 m_options.Finalize();
Daniel Maleae0f8f572013-08-26 23:57:52 +0000570 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000571 return &m_options;
572 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000573
Kate Stoneb9c1b512016-09-06 20:57:50 +0000574 OptionGroupOptions m_options;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000575};
576
577//----------------------------------------------------------------------
578// "platform fclose"
579//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000580class CommandObjectPlatformFClose : public CommandObjectParsed {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000581public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000582 CommandObjectPlatformFClose(CommandInterpreter &interpreter)
583 : CommandObjectParsed(interpreter, "platform file close",
584 "Close a file on the remote end.", nullptr, 0) {}
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000585
Kate Stoneb9c1b512016-09-06 20:57:50 +0000586 ~CommandObjectPlatformFClose() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000587
Kate Stoneb9c1b512016-09-06 20:57:50 +0000588 bool DoExecute(Args &args, CommandReturnObject &result) override {
589 PlatformSP platform_sp(
590 m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
591 if (platform_sp) {
592 std::string cmd_line;
593 args.GetCommandString(cmd_line);
594 const lldb::user_id_t fd =
595 StringConvert::ToUInt64(cmd_line.c_str(), UINT64_MAX);
Zachary Turner97206d52017-05-12 04:51:55 +0000596 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000597 bool success = platform_sp->CloseFile(fd, error);
598 if (success) {
599 result.AppendMessageWithFormat("file %" PRIu64 " closed.\n", fd);
600 result.SetStatus(eReturnStatusSuccessFinishResult);
601 } else {
602 result.AppendError(error.AsCString());
603 result.SetStatus(eReturnStatusFailed);
604 }
605 } else {
606 result.AppendError("no platform currently selected\n");
607 result.SetStatus(eReturnStatusFailed);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000608 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000609 return result.Succeeded();
610 }
Daniel Maleae0f8f572013-08-26 23:57:52 +0000611};
612
613//----------------------------------------------------------------------
614// "platform fread"
615//----------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000616
617static OptionDefinition g_platform_fread_options[] = {
618 // clang-format off
619 { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeIndex, "Offset into the file at which to start reading." },
620 { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "Number of bytes to read from the file." },
621 // clang-format on
622};
623
Kate Stoneb9c1b512016-09-06 20:57:50 +0000624class CommandObjectPlatformFRead : public CommandObjectParsed {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000625public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000626 CommandObjectPlatformFRead(CommandInterpreter &interpreter)
627 : CommandObjectParsed(interpreter, "platform file read",
628 "Read data from a file on the remote end.", nullptr,
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000629 0),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000630 m_options() {}
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000631
Kate Stoneb9c1b512016-09-06 20:57:50 +0000632 ~CommandObjectPlatformFRead() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000633
Kate Stoneb9c1b512016-09-06 20:57:50 +0000634 bool DoExecute(Args &args, CommandReturnObject &result) override {
635 PlatformSP platform_sp(
636 m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
637 if (platform_sp) {
638 std::string cmd_line;
639 args.GetCommandString(cmd_line);
640 const lldb::user_id_t fd =
641 StringConvert::ToUInt64(cmd_line.c_str(), UINT64_MAX);
642 std::string buffer(m_options.m_count, 0);
Zachary Turner97206d52017-05-12 04:51:55 +0000643 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000644 uint32_t retcode = platform_sp->ReadFile(
645 fd, m_options.m_offset, &buffer[0], m_options.m_count, error);
646 result.AppendMessageWithFormat("Return = %d\n", retcode);
647 result.AppendMessageWithFormat("Data = \"%s\"\n", buffer.c_str());
648 result.SetStatus(eReturnStatusSuccessFinishResult);
649 } else {
650 result.AppendError("no platform currently selected\n");
651 result.SetStatus(eReturnStatusFailed);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000652 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000653 return result.Succeeded();
654 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000655
Kate Stoneb9c1b512016-09-06 20:57:50 +0000656 Options *GetOptions() override { return &m_options; }
657
Daniel Maleae0f8f572013-08-26 23:57:52 +0000658protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000659 class CommandOptions : public Options {
660 public:
661 CommandOptions() : Options() {}
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000662
Kate Stoneb9c1b512016-09-06 20:57:50 +0000663 ~CommandOptions() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000664
Zachary Turner97206d52017-05-12 04:51:55 +0000665 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
666 ExecutionContext *execution_context) override {
667 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000668 char short_option = (char)m_getopt_table[option_idx].val;
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000669
Kate Stoneb9c1b512016-09-06 20:57:50 +0000670 switch (short_option) {
671 case 'o':
Zachary Turnerfe114832016-11-12 16:56:47 +0000672 if (option_arg.getAsInteger(0, m_offset))
673 error.SetErrorStringWithFormat("invalid offset: '%s'",
674 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000675 break;
676 case 'c':
Zachary Turnerfe114832016-11-12 16:56:47 +0000677 if (option_arg.getAsInteger(0, m_count))
678 error.SetErrorStringWithFormat("invalid offset: '%s'",
679 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000680 break;
681 default:
682 error.SetErrorStringWithFormat("unrecognized option '%c'",
683 short_option);
684 break;
685 }
686
687 return error;
688 }
689
690 void OptionParsingStarting(ExecutionContext *execution_context) override {
691 m_offset = 0;
692 m_count = 1;
693 }
694
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000695 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +0000696 return llvm::makeArrayRef(g_platform_fread_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000697 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000698
699 // Instance variables to hold the values for command options.
700
701 uint32_t m_offset;
702 uint32_t m_count;
703 };
704
705 CommandOptions m_options;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000706};
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000707
Daniel Maleae0f8f572013-08-26 23:57:52 +0000708//----------------------------------------------------------------------
709// "platform fwrite"
710//----------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000711
712static OptionDefinition g_platform_fwrite_options[] = {
713 // clang-format off
714 { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeIndex, "Offset into the file at which to start reading." },
715 { LLDB_OPT_SET_1, false, "data", 'd', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeValue, "Text to write to the file." },
716 // clang-format on
717};
718
Kate Stoneb9c1b512016-09-06 20:57:50 +0000719class CommandObjectPlatformFWrite : public CommandObjectParsed {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000720public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000721 CommandObjectPlatformFWrite(CommandInterpreter &interpreter)
722 : CommandObjectParsed(interpreter, "platform file write",
723 "Write data to a file on the remote end.", nullptr,
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000724 0),
Kate Stoneb9c1b512016-09-06 20:57:50 +0000725 m_options() {}
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000726
Kate Stoneb9c1b512016-09-06 20:57:50 +0000727 ~CommandObjectPlatformFWrite() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000728
Kate Stoneb9c1b512016-09-06 20:57:50 +0000729 bool DoExecute(Args &args, CommandReturnObject &result) override {
730 PlatformSP platform_sp(
731 m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
732 if (platform_sp) {
733 std::string cmd_line;
734 args.GetCommandString(cmd_line);
Zachary Turner97206d52017-05-12 04:51:55 +0000735 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000736 const lldb::user_id_t fd =
737 StringConvert::ToUInt64(cmd_line.c_str(), UINT64_MAX);
738 uint32_t retcode =
739 platform_sp->WriteFile(fd, m_options.m_offset, &m_options.m_data[0],
740 m_options.m_data.size(), error);
741 result.AppendMessageWithFormat("Return = %d\n", retcode);
742 result.SetStatus(eReturnStatusSuccessFinishResult);
743 } else {
744 result.AppendError("no platform currently selected\n");
745 result.SetStatus(eReturnStatusFailed);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000746 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000747 return result.Succeeded();
748 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000749
Kate Stoneb9c1b512016-09-06 20:57:50 +0000750 Options *GetOptions() override { return &m_options; }
751
Daniel Maleae0f8f572013-08-26 23:57:52 +0000752protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000753 class CommandOptions : public Options {
754 public:
755 CommandOptions() : Options() {}
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000756
Kate Stoneb9c1b512016-09-06 20:57:50 +0000757 ~CommandOptions() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000758
Zachary Turner97206d52017-05-12 04:51:55 +0000759 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
760 ExecutionContext *execution_context) override {
761 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000762 char short_option = (char)m_getopt_table[option_idx].val;
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000763
Kate Stoneb9c1b512016-09-06 20:57:50 +0000764 switch (short_option) {
765 case 'o':
Zachary Turnerfe114832016-11-12 16:56:47 +0000766 if (option_arg.getAsInteger(0, m_offset))
767 error.SetErrorStringWithFormat("invalid offset: '%s'",
768 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +0000769 break;
770 case 'd':
771 m_data.assign(option_arg);
772 break;
773 default:
774 error.SetErrorStringWithFormat("unrecognized option '%c'",
775 short_option);
776 break;
777 }
778
779 return error;
780 }
781
782 void OptionParsingStarting(ExecutionContext *execution_context) override {
783 m_offset = 0;
784 m_data.clear();
785 }
786
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000787 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +0000788 return llvm::makeArrayRef(g_platform_fwrite_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +0000789 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000790
791 // Instance variables to hold the values for command options.
792
793 uint32_t m_offset;
794 std::string m_data;
795 };
796
797 CommandOptions m_options;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000798};
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000799
Kate Stoneb9c1b512016-09-06 20:57:50 +0000800class CommandObjectPlatformFile : public CommandObjectMultiword {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000801public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000802 //------------------------------------------------------------------
803 // Constructors and Destructors
804 //------------------------------------------------------------------
805 CommandObjectPlatformFile(CommandInterpreter &interpreter)
806 : CommandObjectMultiword(
807 interpreter, "platform file",
808 "Commands to access files on the current platform.",
809 "platform file [open|close|read|write] ...") {
810 LoadSubCommand(
811 "open", CommandObjectSP(new CommandObjectPlatformFOpen(interpreter)));
812 LoadSubCommand(
813 "close", CommandObjectSP(new CommandObjectPlatformFClose(interpreter)));
814 LoadSubCommand(
815 "read", CommandObjectSP(new CommandObjectPlatformFRead(interpreter)));
816 LoadSubCommand(
817 "write", CommandObjectSP(new CommandObjectPlatformFWrite(interpreter)));
818 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000819
Kate Stoneb9c1b512016-09-06 20:57:50 +0000820 ~CommandObjectPlatformFile() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000821
Daniel Maleae0f8f572013-08-26 23:57:52 +0000822private:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000823 //------------------------------------------------------------------
824 // For CommandObjectPlatform only
825 //------------------------------------------------------------------
826 DISALLOW_COPY_AND_ASSIGN(CommandObjectPlatformFile);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000827};
828
829//----------------------------------------------------------------------
830// "platform get-file remote-file-path host-file-path"
831//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000832class CommandObjectPlatformGetFile : public CommandObjectParsed {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000833public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000834 CommandObjectPlatformGetFile(CommandInterpreter &interpreter)
835 : CommandObjectParsed(
836 interpreter, "platform get-file",
837 "Transfer a file from the remote end to the local host.",
838 "platform get-file <remote-file-spec> <local-file-spec>", 0) {
839 SetHelpLong(
840 R"(Examples:
Kate Stoneea671fb2015-07-14 05:48:36 +0000841
842(lldb) platform get-file /the/remote/file/path /the/local/file/path
843
Kate Stoneb9c1b512016-09-06 20:57:50 +0000844 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 +0000845
Kate Stoneb9c1b512016-09-06 20:57:50 +0000846 CommandArgumentEntry arg1, arg2;
847 CommandArgumentData file_arg_remote, file_arg_host;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000848
Kate Stoneb9c1b512016-09-06 20:57:50 +0000849 // Define the first (and only) variant of this arg.
850 file_arg_remote.arg_type = eArgTypeFilename;
851 file_arg_remote.arg_repetition = eArgRepeatPlain;
852 // There is only one variant this argument could be; put it into the
853 // argument entry.
854 arg1.push_back(file_arg_remote);
855
856 // Define the second (and only) variant of this arg.
857 file_arg_host.arg_type = eArgTypeFilename;
858 file_arg_host.arg_repetition = eArgRepeatPlain;
859 // There is only one variant this argument could be; put it into the
860 // argument entry.
861 arg2.push_back(file_arg_host);
862
Adrian Prantl05097242018-04-30 16:49:04 +0000863 // Push the data for the first and the second arguments into the
864 // m_arguments vector.
Kate Stoneb9c1b512016-09-06 20:57:50 +0000865 m_arguments.push_back(arg1);
866 m_arguments.push_back(arg2);
867 }
868
869 ~CommandObjectPlatformGetFile() override = default;
870
871 bool DoExecute(Args &args, CommandReturnObject &result) override {
872 // If the number of arguments is incorrect, issue an error message.
873 if (args.GetArgumentCount() != 2) {
874 result.GetErrorStream().Printf("error: required arguments missing; "
875 "specify both the source and destination "
876 "file paths\n");
877 result.SetStatus(eReturnStatusFailed);
878 return false;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000879 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000880
Kate Stoneb9c1b512016-09-06 20:57:50 +0000881 PlatformSP platform_sp(
882 m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
883 if (platform_sp) {
884 const char *remote_file_path = args.GetArgumentAtIndex(0);
885 const char *local_file_path = args.GetArgumentAtIndex(1);
Zachary Turner97206d52017-05-12 04:51:55 +0000886 Status error = platform_sp->GetFile(FileSpec(remote_file_path, false),
887 FileSpec(local_file_path, false));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000888 if (error.Success()) {
889 result.AppendMessageWithFormat(
890 "successfully get-file from %s (remote) to %s (host)\n",
891 remote_file_path, local_file_path);
892 result.SetStatus(eReturnStatusSuccessFinishResult);
893 } else {
894 result.AppendMessageWithFormat("get-file failed: %s\n",
895 error.AsCString());
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
906//----------------------------------------------------------------------
907// "platform get-size remote-file-path"
908//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000909class CommandObjectPlatformGetSize : public CommandObjectParsed {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000910public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000911 CommandObjectPlatformGetSize(CommandInterpreter &interpreter)
912 : CommandObjectParsed(interpreter, "platform get-size",
913 "Get the file size from the remote end.",
914 "platform get-size <remote-file-spec>", 0) {
915 SetHelpLong(
916 R"(Examples:
Kate Stoneea671fb2015-07-14 05:48:36 +0000917
918(lldb) platform get-size /the/remote/file/path
919
Kate Stoneb9c1b512016-09-06 20:57:50 +0000920 Get the file size from the remote end with path /the/remote/file/path.)");
Daniel Maleae0f8f572013-08-26 23:57:52 +0000921
Kate Stoneb9c1b512016-09-06 20:57:50 +0000922 CommandArgumentEntry arg1;
923 CommandArgumentData file_arg_remote;
924
925 // Define the first (and only) variant of this arg.
926 file_arg_remote.arg_type = eArgTypeFilename;
927 file_arg_remote.arg_repetition = eArgRepeatPlain;
928 // There is only one variant this argument could be; put it into the
929 // argument entry.
930 arg1.push_back(file_arg_remote);
931
932 // Push the data for the first argument into the m_arguments vector.
933 m_arguments.push_back(arg1);
934 }
935
936 ~CommandObjectPlatformGetSize() override = default;
937
938 bool DoExecute(Args &args, CommandReturnObject &result) override {
939 // If the number of arguments is incorrect, issue an error message.
940 if (args.GetArgumentCount() != 1) {
941 result.GetErrorStream().Printf("error: required argument missing; "
942 "specify the source file path as the only "
943 "argument\n");
944 result.SetStatus(eReturnStatusFailed);
945 return false;
Daniel Maleae0f8f572013-08-26 23:57:52 +0000946 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +0000947
Kate Stoneb9c1b512016-09-06 20:57:50 +0000948 PlatformSP platform_sp(
949 m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
950 if (platform_sp) {
951 std::string remote_file_path(args.GetArgumentAtIndex(0));
952 user_id_t size =
Malcolm Parsons771ef6d2016-11-02 20:34:10 +0000953 platform_sp->GetFileSize(FileSpec(remote_file_path, false));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000954 if (size != UINT64_MAX) {
955 result.AppendMessageWithFormat("File size of %s (remote): %" PRIu64
956 "\n",
957 remote_file_path.c_str(), size);
958 result.SetStatus(eReturnStatusSuccessFinishResult);
959 } else {
960 result.AppendMessageWithFormat(
961 "Error getting file size of %s (remote)\n",
962 remote_file_path.c_str());
963 result.SetStatus(eReturnStatusFailed);
964 }
965 } else {
966 result.AppendError("no platform currently selected\n");
967 result.SetStatus(eReturnStatusFailed);
Daniel Maleae0f8f572013-08-26 23:57:52 +0000968 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000969 return result.Succeeded();
970 }
Daniel Maleae0f8f572013-08-26 23:57:52 +0000971};
972
973//----------------------------------------------------------------------
974// "platform put-file"
975//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000976class CommandObjectPlatformPutFile : public CommandObjectParsed {
Daniel Maleae0f8f572013-08-26 23:57:52 +0000977public:
Kate Stoneb9c1b512016-09-06 20:57:50 +0000978 CommandObjectPlatformPutFile(CommandInterpreter &interpreter)
979 : CommandObjectParsed(
980 interpreter, "platform put-file",
981 "Transfer a file from this system to the remote end.", nullptr, 0) {
982 }
983
984 ~CommandObjectPlatformPutFile() override = default;
985
986 bool DoExecute(Args &args, CommandReturnObject &result) override {
987 const char *src = args.GetArgumentAtIndex(0);
988 const char *dst = args.GetArgumentAtIndex(1);
989
990 FileSpec src_fs(src, true);
991 FileSpec dst_fs(dst ? dst : src_fs.GetFilename().GetCString(), false);
992
993 PlatformSP platform_sp(
994 m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
995 if (platform_sp) {
Zachary Turner97206d52017-05-12 04:51:55 +0000996 Status error(platform_sp->PutFile(src_fs, dst_fs));
Kate Stoneb9c1b512016-09-06 20:57:50 +0000997 if (error.Success()) {
998 result.SetStatus(eReturnStatusSuccessFinishNoResult);
999 } else {
1000 result.AppendError(error.AsCString());
1001 result.SetStatus(eReturnStatusFailed);
1002 }
1003 } else {
1004 result.AppendError("no platform currently selected\n");
1005 result.SetStatus(eReturnStatusFailed);
Daniel Maleae0f8f572013-08-26 23:57:52 +00001006 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001007 return result.Succeeded();
1008 }
Daniel Maleae0f8f572013-08-26 23:57:52 +00001009};
1010
Greg Clayton8b82f082011-04-12 05:54:46 +00001011//----------------------------------------------------------------------
1012// "platform process launch"
1013//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +00001014class CommandObjectPlatformProcessLaunch : public CommandObjectParsed {
Greg Clayton8b82f082011-04-12 05:54:46 +00001015public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001016 CommandObjectPlatformProcessLaunch(CommandInterpreter &interpreter)
1017 : CommandObjectParsed(interpreter, "platform process launch",
1018 "Launch a new process on a remote platform.",
1019 "platform process launch program",
1020 eCommandRequiresTarget | eCommandTryTargetAPILock),
1021 m_options() {}
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001022
Kate Stoneb9c1b512016-09-06 20:57:50 +00001023 ~CommandObjectPlatformProcessLaunch() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001024
Kate Stoneb9c1b512016-09-06 20:57:50 +00001025 Options *GetOptions() override { return &m_options; }
1026
Jim Ingham5a988412012-06-08 21:56:10 +00001027protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001028 bool DoExecute(Args &args, CommandReturnObject &result) override {
1029 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1030 PlatformSP platform_sp;
1031 if (target) {
1032 platform_sp = target->GetPlatform();
1033 }
1034 if (!platform_sp) {
1035 platform_sp =
1036 m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform();
1037 }
Jason Molenda8c1157c2013-04-05 02:59:09 +00001038
Kate Stoneb9c1b512016-09-06 20:57:50 +00001039 if (platform_sp) {
Zachary Turner97206d52017-05-12 04:51:55 +00001040 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001041 const size_t argc = args.GetArgumentCount();
1042 Target *target = m_exe_ctx.GetTargetPtr();
1043 Module *exe_module = target->GetExecutableModulePointer();
1044 if (exe_module) {
1045 m_options.launch_info.GetExecutableFile() = exe_module->GetFileSpec();
Zachary Turnerecbb0bb2016-09-19 17:54:06 +00001046 llvm::SmallString<PATH_MAX> exe_path;
1047 m_options.launch_info.GetExecutableFile().GetPath(exe_path);
1048 if (!exe_path.empty())
Kate Stoneb9c1b512016-09-06 20:57:50 +00001049 m_options.launch_info.GetArguments().AppendArgument(exe_path);
1050 m_options.launch_info.GetArchitecture() = exe_module->GetArchitecture();
1051 }
Greg Clayton8b82f082011-04-12 05:54:46 +00001052
Kate Stoneb9c1b512016-09-06 20:57:50 +00001053 if (argc > 0) {
1054 if (m_options.launch_info.GetExecutableFile()) {
Adrian Prantl05097242018-04-30 16:49:04 +00001055 // We already have an executable file, so we will use this and all
1056 // arguments to this function are extra arguments
Kate Stoneb9c1b512016-09-06 20:57:50 +00001057 m_options.launch_info.GetArguments().AppendArguments(args);
1058 } else {
1059 // We don't have any file yet, so the first argument is our
1060 // executable, and the rest are program arguments
1061 const bool first_arg_is_executable = true;
1062 m_options.launch_info.SetArguments(args, first_arg_is_executable);
Greg Clayton8b82f082011-04-12 05:54:46 +00001063 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001064 }
1065
1066 if (m_options.launch_info.GetExecutableFile()) {
1067 Debugger &debugger = m_interpreter.GetDebugger();
1068
1069 if (argc == 0)
1070 target->GetRunArguments(m_options.launch_info.GetArguments());
1071
1072 ProcessSP process_sp(platform_sp->DebugProcess(
1073 m_options.launch_info, debugger, target, error));
1074 if (process_sp && process_sp->IsAlive()) {
1075 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1076 return true;
1077 }
1078
1079 if (error.Success())
1080 result.AppendError("process launch failed");
Greg Clayton8b82f082011-04-12 05:54:46 +00001081 else
Kate Stoneb9c1b512016-09-06 20:57:50 +00001082 result.AppendError(error.AsCString());
1083 result.SetStatus(eReturnStatusFailed);
1084 } else {
1085 result.AppendError("'platform process launch' uses the current target "
1086 "file and arguments, or the executable and its "
1087 "arguments can be specified in this command");
1088 result.SetStatus(eReturnStatusFailed);
1089 return false;
1090 }
1091 } else {
1092 result.AppendError("no platform is selected\n");
Greg Clayton8b82f082011-04-12 05:54:46 +00001093 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001094 return result.Succeeded();
1095 }
1096
Greg Clayton8b82f082011-04-12 05:54:46 +00001097protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001098 ProcessLaunchCommandOptions m_options;
Greg Clayton8b82f082011-04-12 05:54:46 +00001099};
1100
Greg Clayton32e0a752011-03-30 18:16:51 +00001101//----------------------------------------------------------------------
1102// "platform process list"
1103//----------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001104
Zachary Turner70602432016-09-22 21:06:13 +00001105OptionDefinition g_platform_process_list_options[] = {
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001106 // clang-format off
1107 { LLDB_OPT_SET_1, false, "pid", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePid, "List the process info for a specific process ID." },
1108 { LLDB_OPT_SET_2, true, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeProcessName, "Find processes with executable basenames that match a string." },
1109 { LLDB_OPT_SET_3, true, "ends-with", 'e', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeProcessName, "Find processes with executable basenames that end with a string." },
1110 { LLDB_OPT_SET_4, true, "starts-with", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeProcessName, "Find processes with executable basenames that start with a string." },
1111 { LLDB_OPT_SET_5, true, "contains", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeProcessName, "Find processes with executable basenames that contain a string." },
1112 { LLDB_OPT_SET_6, true, "regex", 'r', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeRegularExpression, "Find processes with executable basenames that match a regular expression." },
1113 { 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." },
1114 { LLDB_OPT_SET_FROM_TO(2, 6), false, "uid", 'u', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Find processes that have a matching user ID." },
1115 { 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." },
1116 { LLDB_OPT_SET_FROM_TO(2, 6), false, "gid", 'g', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Find processes that have a matching group ID." },
1117 { 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." },
1118 { LLDB_OPT_SET_FROM_TO(2, 6), false, "arch", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeArchitecture, "Find processes that have a matching architecture." },
1119 { 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." },
1120 { LLDB_OPT_SET_FROM_TO(1, 6), false, "verbose", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable verbose output." },
1121 // clang-format on
1122};
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001123
Kate Stoneb9c1b512016-09-06 20:57:50 +00001124class CommandObjectPlatformProcessList : public CommandObjectParsed {
Greg Clayton32e0a752011-03-30 18:16:51 +00001125public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001126 CommandObjectPlatformProcessList(CommandInterpreter &interpreter)
1127 : CommandObjectParsed(interpreter, "platform process list",
1128 "List processes on a remote platform by name, pid, "
1129 "or many other matching attributes.",
1130 "platform process list", 0),
1131 m_options() {}
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001132
Kate Stoneb9c1b512016-09-06 20:57:50 +00001133 ~CommandObjectPlatformProcessList() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001134
Kate Stoneb9c1b512016-09-06 20:57:50 +00001135 Options *GetOptions() override { return &m_options; }
1136
Jim Ingham5a988412012-06-08 21:56:10 +00001137protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001138 bool DoExecute(Args &args, CommandReturnObject &result) override {
1139 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1140 PlatformSP platform_sp;
1141 if (target) {
1142 platform_sp = target->GetPlatform();
Greg Clayton32e0a752011-03-30 18:16:51 +00001143 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001144 if (!platform_sp) {
1145 platform_sp =
1146 m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform();
1147 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001148
Kate Stoneb9c1b512016-09-06 20:57:50 +00001149 if (platform_sp) {
Zachary Turner97206d52017-05-12 04:51:55 +00001150 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001151 if (args.GetArgumentCount() == 0) {
1152 if (platform_sp) {
1153 Stream &ostrm = result.GetOutputStream();
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001154
Kate Stoneb9c1b512016-09-06 20:57:50 +00001155 lldb::pid_t pid =
1156 m_options.match_info.GetProcessInfo().GetProcessID();
1157 if (pid != LLDB_INVALID_PROCESS_ID) {
1158 ProcessInstanceInfo proc_info;
1159 if (platform_sp->GetProcessInfo(pid, proc_info)) {
1160 ProcessInstanceInfo::DumpTableHeader(ostrm, platform_sp.get(),
1161 m_options.show_args,
1162 m_options.verbose);
1163 proc_info.DumpAsTableRow(ostrm, platform_sp.get(),
1164 m_options.show_args, m_options.verbose);
1165 result.SetStatus(eReturnStatusSuccessFinishResult);
1166 } else {
1167 result.AppendErrorWithFormat(
1168 "no process found with pid = %" PRIu64 "\n", pid);
1169 result.SetStatus(eReturnStatusFailed);
Greg Clayton32e0a752011-03-30 18:16:51 +00001170 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001171 } else {
1172 ProcessInstanceInfoList proc_infos;
1173 const uint32_t matches =
1174 platform_sp->FindProcesses(m_options.match_info, proc_infos);
1175 const char *match_desc = nullptr;
1176 const char *match_name =
1177 m_options.match_info.GetProcessInfo().GetName();
1178 if (match_name && match_name[0]) {
1179 switch (m_options.match_info.GetNameMatchType()) {
Pavel Labathc4a33952017-02-20 11:35:33 +00001180 case NameMatch::Ignore:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001181 break;
Pavel Labathc4a33952017-02-20 11:35:33 +00001182 case NameMatch::Equals:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001183 match_desc = "matched";
1184 break;
Pavel Labathc4a33952017-02-20 11:35:33 +00001185 case NameMatch::Contains:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001186 match_desc = "contained";
1187 break;
Pavel Labathc4a33952017-02-20 11:35:33 +00001188 case NameMatch::StartsWith:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001189 match_desc = "started with";
1190 break;
Pavel Labathc4a33952017-02-20 11:35:33 +00001191 case NameMatch::EndsWith:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001192 match_desc = "ended with";
1193 break;
Pavel Labathc4a33952017-02-20 11:35:33 +00001194 case NameMatch::RegularExpression:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001195 match_desc = "matched the regular expression";
1196 break;
1197 }
1198 }
Greg Clayton1cf2aa82016-03-24 21:49:22 +00001199
Kate Stoneb9c1b512016-09-06 20:57:50 +00001200 if (matches == 0) {
1201 if (match_desc)
1202 result.AppendErrorWithFormat(
1203 "no processes were found that %s \"%s\" on the \"%s\" "
1204 "platform\n",
1205 match_desc, match_name,
1206 platform_sp->GetPluginName().GetCString());
1207 else
1208 result.AppendErrorWithFormat(
1209 "no processes were found on the \"%s\" platform\n",
1210 platform_sp->GetPluginName().GetCString());
1211 result.SetStatus(eReturnStatusFailed);
1212 } else {
1213 result.AppendMessageWithFormat(
1214 "%u matching process%s found on \"%s\"", matches,
1215 matches > 1 ? "es were" : " was",
1216 platform_sp->GetName().GetCString());
1217 if (match_desc)
1218 result.AppendMessageWithFormat(" whose name %s \"%s\"",
1219 match_desc, match_name);
1220 result.AppendMessageWithFormat("\n");
1221 ProcessInstanceInfo::DumpTableHeader(ostrm, platform_sp.get(),
1222 m_options.show_args,
1223 m_options.verbose);
1224 for (uint32_t i = 0; i < matches; ++i) {
1225 proc_infos.GetProcessInfoAtIndex(i).DumpAsTableRow(
1226 ostrm, platform_sp.get(), m_options.show_args,
1227 m_options.verbose);
1228 }
1229 }
1230 }
1231 }
1232 } else {
1233 result.AppendError("invalid args: process list takes only options\n");
1234 result.SetStatus(eReturnStatusFailed);
1235 }
1236 } else {
1237 result.AppendError("no platform is selected\n");
1238 result.SetStatus(eReturnStatusFailed);
1239 }
1240 return result.Succeeded();
1241 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001242
Kate Stoneb9c1b512016-09-06 20:57:50 +00001243 class CommandOptions : public Options {
1244 public:
1245 CommandOptions()
1246 : Options(), match_info(), show_args(false), verbose(false) {
Kamil Rytarowskic5f28e22017-02-06 17:55:02 +00001247 static llvm::once_flag g_once_flag;
1248 llvm::call_once(g_once_flag, []() {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001249 PosixPlatformCommandOptionValidator *posix_validator =
1250 new PosixPlatformCommandOptionValidator();
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001251 for (auto &Option : g_platform_process_list_options) {
1252 switch (Option.short_option) {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001253 case 'u':
1254 case 'U':
1255 case 'g':
1256 case 'G':
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001257 Option.validator = posix_validator;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001258 break;
1259 default:
1260 break;
1261 }
1262 }
1263 });
1264 }
1265
1266 ~CommandOptions() override = default;
1267
Zachary Turner97206d52017-05-12 04:51:55 +00001268 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1269 ExecutionContext *execution_context) override {
1270 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001271 const int short_option = m_getopt_table[option_idx].val;
1272 bool success = false;
1273
Zachary Turnerfe114832016-11-12 16:56:47 +00001274 uint32_t id = LLDB_INVALID_PROCESS_ID;
1275 success = !option_arg.getAsInteger(0, id);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001276 switch (short_option) {
Zachary Turnerfe114832016-11-12 16:56:47 +00001277 case 'p': {
1278 match_info.GetProcessInfo().SetProcessID(id);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001279 if (!success)
1280 error.SetErrorStringWithFormat("invalid process ID string: '%s'",
Zachary Turnerfe114832016-11-12 16:56:47 +00001281 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001282 break;
Zachary Turnerfe114832016-11-12 16:56:47 +00001283 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001284 case 'P':
Zachary Turnerfe114832016-11-12 16:56:47 +00001285 match_info.GetProcessInfo().SetParentProcessID(id);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001286 if (!success)
1287 error.SetErrorStringWithFormat(
Zachary Turnerfe114832016-11-12 16:56:47 +00001288 "invalid parent process ID string: '%s'",
1289 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001290 break;
1291
1292 case 'u':
Zachary Turnerfe114832016-11-12 16:56:47 +00001293 match_info.GetProcessInfo().SetUserID(success ? id : UINT32_MAX);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001294 if (!success)
1295 error.SetErrorStringWithFormat("invalid user ID string: '%s'",
Zachary Turnerfe114832016-11-12 16:56:47 +00001296 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001297 break;
1298
1299 case 'U':
Zachary Turnerfe114832016-11-12 16:56:47 +00001300 match_info.GetProcessInfo().SetEffectiveUserID(success ? id
1301 : UINT32_MAX);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001302 if (!success)
1303 error.SetErrorStringWithFormat(
Zachary Turnerfe114832016-11-12 16:56:47 +00001304 "invalid effective user ID string: '%s'",
1305 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001306 break;
1307
1308 case 'g':
Zachary Turnerfe114832016-11-12 16:56:47 +00001309 match_info.GetProcessInfo().SetGroupID(success ? id : UINT32_MAX);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001310 if (!success)
1311 error.SetErrorStringWithFormat("invalid group ID string: '%s'",
Zachary Turnerfe114832016-11-12 16:56:47 +00001312 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001313 break;
1314
1315 case 'G':
Zachary Turnerfe114832016-11-12 16:56:47 +00001316 match_info.GetProcessInfo().SetEffectiveGroupID(success ? id
1317 : UINT32_MAX);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001318 if (!success)
1319 error.SetErrorStringWithFormat(
Zachary Turnerfe114832016-11-12 16:56:47 +00001320 "invalid effective group ID string: '%s'",
1321 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001322 break;
1323
1324 case 'a': {
1325 TargetSP target_sp =
1326 execution_context ? execution_context->GetTargetSP() : TargetSP();
1327 DebuggerSP debugger_sp =
1328 target_sp ? target_sp->GetDebugger().shared_from_this()
1329 : DebuggerSP();
1330 PlatformSP platform_sp =
1331 debugger_sp ? debugger_sp->GetPlatformList().GetSelectedPlatform()
1332 : PlatformSP();
Pavel Labath7263f1b2017-10-31 10:56:03 +00001333 match_info.GetProcessInfo().GetArchitecture() =
1334 Platform::GetAugmentedArchSpec(platform_sp.get(), option_arg);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001335 } break;
1336
1337 case 'n':
Jonas Devlieghere937348c2018-06-13 22:08:14 +00001338 match_info.GetProcessInfo().GetExecutableFile().SetFile(
1339 option_arg, false, FileSpec::Style::native);
Pavel Labathc4a33952017-02-20 11:35:33 +00001340 match_info.SetNameMatchType(NameMatch::Equals);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001341 break;
1342
1343 case 'e':
Jonas Devlieghere937348c2018-06-13 22:08:14 +00001344 match_info.GetProcessInfo().GetExecutableFile().SetFile(
1345 option_arg, false, FileSpec::Style::native);
Pavel Labathc4a33952017-02-20 11:35:33 +00001346 match_info.SetNameMatchType(NameMatch::EndsWith);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001347 break;
1348
1349 case 's':
Jonas Devlieghere937348c2018-06-13 22:08:14 +00001350 match_info.GetProcessInfo().GetExecutableFile().SetFile(
1351 option_arg, false, FileSpec::Style::native);
Pavel Labathc4a33952017-02-20 11:35:33 +00001352 match_info.SetNameMatchType(NameMatch::StartsWith);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001353 break;
1354
1355 case 'c':
Jonas Devlieghere937348c2018-06-13 22:08:14 +00001356 match_info.GetProcessInfo().GetExecutableFile().SetFile(
1357 option_arg, false, FileSpec::Style::native);
Pavel Labathc4a33952017-02-20 11:35:33 +00001358 match_info.SetNameMatchType(NameMatch::Contains);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001359 break;
1360
1361 case 'r':
Jonas Devlieghere937348c2018-06-13 22:08:14 +00001362 match_info.GetProcessInfo().GetExecutableFile().SetFile(
1363 option_arg, false, FileSpec::Style::native);
Pavel Labathc4a33952017-02-20 11:35:33 +00001364 match_info.SetNameMatchType(NameMatch::RegularExpression);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001365 break;
1366
1367 case 'A':
1368 show_args = true;
1369 break;
1370
1371 case 'v':
1372 verbose = true;
1373 break;
1374
1375 default:
1376 error.SetErrorStringWithFormat("unrecognized option '%c'",
1377 short_option);
1378 break;
1379 }
1380
1381 return error;
1382 }
1383
1384 void OptionParsingStarting(ExecutionContext *execution_context) override {
1385 match_info.Clear();
1386 show_args = false;
1387 verbose = false;
1388 }
1389
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001390 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001391 return llvm::makeArrayRef(g_platform_process_list_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001392 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001393
1394 // Instance variables to hold the values for command options.
1395
1396 ProcessInstanceInfoMatch match_info;
1397 bool show_args;
1398 bool verbose;
1399 };
1400
1401 CommandOptions m_options;
Greg Clayton32e0a752011-03-30 18:16:51 +00001402};
1403
Greg Clayton95bf0fd2011-04-01 00:29:43 +00001404//----------------------------------------------------------------------
1405// "platform process info"
1406//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +00001407class CommandObjectPlatformProcessInfo : public CommandObjectParsed {
Greg Clayton95bf0fd2011-04-01 00:29:43 +00001408public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001409 CommandObjectPlatformProcessInfo(CommandInterpreter &interpreter)
1410 : CommandObjectParsed(
1411 interpreter, "platform process info",
1412 "Get detailed information for one or more process by process ID.",
1413 "platform process info <pid> [<pid> <pid> ...]", 0) {
1414 CommandArgumentEntry arg;
1415 CommandArgumentData pid_args;
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001416
Kate Stoneb9c1b512016-09-06 20:57:50 +00001417 // Define the first (and only) variant of this arg.
1418 pid_args.arg_type = eArgTypePid;
1419 pid_args.arg_repetition = eArgRepeatStar;
1420
1421 // There is only one variant this argument could be; put it into the
1422 // argument entry.
1423 arg.push_back(pid_args);
1424
1425 // Push the data for the first argument into the m_arguments vector.
1426 m_arguments.push_back(arg);
1427 }
1428
1429 ~CommandObjectPlatformProcessInfo() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001430
Jim Ingham5a988412012-06-08 21:56:10 +00001431protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001432 bool DoExecute(Args &args, CommandReturnObject &result) override {
1433 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1434 PlatformSP platform_sp;
1435 if (target) {
1436 platform_sp = target->GetPlatform();
Greg Clayton95bf0fd2011-04-01 00:29:43 +00001437 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001438 if (!platform_sp) {
1439 platform_sp =
1440 m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform();
1441 }
1442
1443 if (platform_sp) {
1444 const size_t argc = args.GetArgumentCount();
1445 if (argc > 0) {
Zachary Turner97206d52017-05-12 04:51:55 +00001446 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001447
1448 if (platform_sp->IsConnected()) {
1449 Stream &ostrm = result.GetOutputStream();
Zachary Turner97d2c402016-10-05 23:40:23 +00001450 for (auto &entry : args.entries()) {
1451 lldb::pid_t pid;
1452 if (entry.ref.getAsInteger(0, pid)) {
1453 result.AppendErrorWithFormat("invalid process ID argument '%s'",
1454 entry.ref.str().c_str());
1455 result.SetStatus(eReturnStatusFailed);
1456 break;
1457 } else {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001458 ProcessInstanceInfo proc_info;
1459 if (platform_sp->GetProcessInfo(pid, proc_info)) {
1460 ostrm.Printf("Process information for process %" PRIu64 ":\n",
1461 pid);
1462 proc_info.Dump(ostrm, platform_sp.get());
1463 } else {
1464 ostrm.Printf("error: no process information is available for "
1465 "process %" PRIu64 "\n",
1466 pid);
1467 }
1468 ostrm.EOL();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001469 }
1470 }
1471 } else {
1472 // Not connected...
1473 result.AppendErrorWithFormat(
1474 "not connected to '%s'",
1475 platform_sp->GetPluginName().GetCString());
1476 result.SetStatus(eReturnStatusFailed);
1477 }
1478 } else {
1479 // No args
1480 result.AppendError("one or more process id(s) must be specified");
1481 result.SetStatus(eReturnStatusFailed);
1482 }
1483 } else {
1484 result.AppendError("no platform is currently selected");
1485 result.SetStatus(eReturnStatusFailed);
1486 }
1487 return result.Succeeded();
1488 }
Greg Clayton95bf0fd2011-04-01 00:29:43 +00001489};
1490
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001491static OptionDefinition g_platform_process_attach_options[] = {
1492 // clang-format off
1493 { LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePlugin, "Name of the process plugin you want to use." },
1494 { LLDB_OPT_SET_1, false, "pid", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePid, "The process ID of an existing process to attach to." },
1495 { LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeProcessName, "The name of the process to attach to." },
1496 { LLDB_OPT_SET_2, false, "waitfor", 'w', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Wait for the process with <process-name> to launch." },
1497 // clang-format on
1498};
1499
Kate Stoneb9c1b512016-09-06 20:57:50 +00001500class CommandObjectPlatformProcessAttach : public CommandObjectParsed {
Daniel Maleae0f8f572013-08-26 23:57:52 +00001501public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001502 class CommandOptions : public Options {
1503 public:
1504 CommandOptions() : Options() {
1505 // Keep default values of all options in one place: OptionParsingStarting
1506 // ()
1507 OptionParsingStarting(nullptr);
Daniel Maleae0f8f572013-08-26 23:57:52 +00001508 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001509
Kate Stoneb9c1b512016-09-06 20:57:50 +00001510 ~CommandOptions() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001511
Zachary Turner97206d52017-05-12 04:51:55 +00001512 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1513 ExecutionContext *execution_context) override {
1514 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001515 char short_option = (char)m_getopt_table[option_idx].val;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001516 switch (short_option) {
1517 case 'p': {
Zachary Turnerfe114832016-11-12 16:56:47 +00001518 lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
1519 if (option_arg.getAsInteger(0, pid)) {
1520 error.SetErrorStringWithFormat("invalid process ID '%s'",
1521 option_arg.str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001522 } else {
1523 attach_info.SetProcessID(pid);
Daniel Maleae0f8f572013-08-26 23:57:52 +00001524 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001525 } break;
1526
1527 case 'P':
1528 attach_info.SetProcessPluginName(option_arg);
1529 break;
1530
1531 case 'n':
Jonas Devlieghere937348c2018-06-13 22:08:14 +00001532 attach_info.GetExecutableFile().SetFile(option_arg, false,
1533 FileSpec::Style::native);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001534 break;
1535
1536 case 'w':
1537 attach_info.SetWaitForLaunch(true);
1538 break;
1539
1540 default:
1541 error.SetErrorStringWithFormat("invalid short option character '%c'",
1542 short_option);
1543 break;
1544 }
1545 return error;
1546 }
1547
1548 void OptionParsingStarting(ExecutionContext *execution_context) override {
1549 attach_info.Clear();
1550 }
1551
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001552 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001553 return llvm::makeArrayRef(g_platform_process_attach_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001554 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001555
1556 bool HandleOptionArgumentCompletion(
Raphael Isemanna2e76c02018-07-13 18:28:14 +00001557 CompletionRequest &request, OptionElementVector &opt_element_vector,
1558 int opt_element_index, CommandInterpreter &interpreter) override {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001559 int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
1560 int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
1561
1562 // We are only completing the name option for now...
1563
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001564 if (GetDefinitions()[opt_defs_index].short_option == 'n') {
Kate Stoneb9c1b512016-09-06 20:57:50 +00001565 // Are we in the name?
1566
1567 // Look to see if there is a -P argument provided, and if so use that
Adrian Prantl05097242018-04-30 16:49:04 +00001568 // plugin, otherwise use the default plugin.
Kate Stoneb9c1b512016-09-06 20:57:50 +00001569
1570 const char *partial_name = nullptr;
Raphael Isemanna2e76c02018-07-13 18:28:14 +00001571 partial_name = request.GetParsedLine().GetArgumentAtIndex(opt_arg_pos);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001572
1573 PlatformSP platform_sp(interpreter.GetPlatform(true));
1574 if (platform_sp) {
1575 ProcessInstanceInfoList process_infos;
1576 ProcessInstanceInfoMatch match_info;
1577 if (partial_name) {
1578 match_info.GetProcessInfo().GetExecutableFile().SetFile(
Jonas Devlieghere937348c2018-06-13 22:08:14 +00001579 partial_name, false, FileSpec::Style::native);
Pavel Labathc4a33952017-02-20 11:35:33 +00001580 match_info.SetNameMatchType(NameMatch::StartsWith);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001581 }
1582 platform_sp->FindProcesses(match_info, process_infos);
1583 const uint32_t num_matches = process_infos.GetSize();
1584 if (num_matches > 0) {
1585 for (uint32_t i = 0; i < num_matches; ++i) {
Raphael Isemann1a6d7ab2018-07-27 18:42:46 +00001586 request.AddCompletion(llvm::StringRef(
Kate Stoneb9c1b512016-09-06 20:57:50 +00001587 process_infos.GetProcessNameAtIndex(i),
Raphael Isemann1a6d7ab2018-07-27 18:42:46 +00001588 process_infos.GetProcessNameLengthAtIndex(i)));
Kate Stoneb9c1b512016-09-06 20:57:50 +00001589 }
1590 }
Daniel Maleae0f8f572013-08-26 23:57:52 +00001591 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001592 }
1593
1594 return false;
Daniel Maleae0f8f572013-08-26 23:57:52 +00001595 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001596
1597 // Options table: Required for subclasses of Options.
1598
1599 static OptionDefinition g_option_table[];
1600
1601 // Instance variables to hold the values for command options.
1602
1603 ProcessAttachInfo attach_info;
1604 };
1605
1606 CommandObjectPlatformProcessAttach(CommandInterpreter &interpreter)
1607 : CommandObjectParsed(interpreter, "platform process attach",
1608 "Attach to a process.",
1609 "platform process attach <cmd-options>"),
1610 m_options() {}
1611
1612 ~CommandObjectPlatformProcessAttach() override = default;
1613
1614 bool DoExecute(Args &command, CommandReturnObject &result) override {
1615 PlatformSP platform_sp(
1616 m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
1617 if (platform_sp) {
Zachary Turner97206d52017-05-12 04:51:55 +00001618 Status err;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001619 ProcessSP remote_process_sp = platform_sp->Attach(
1620 m_options.attach_info, m_interpreter.GetDebugger(), nullptr, err);
1621 if (err.Fail()) {
1622 result.AppendError(err.AsCString());
1623 result.SetStatus(eReturnStatusFailed);
1624 } else if (!remote_process_sp) {
1625 result.AppendError("could not attach: unknown reason");
1626 result.SetStatus(eReturnStatusFailed);
1627 } else
1628 result.SetStatus(eReturnStatusSuccessFinishResult);
1629 } else {
1630 result.AppendError("no platform is currently selected");
1631 result.SetStatus(eReturnStatusFailed);
Daniel Maleae0f8f572013-08-26 23:57:52 +00001632 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001633 return result.Succeeded();
1634 }
1635
1636 Options *GetOptions() override { return &m_options; }
1637
Daniel Maleae0f8f572013-08-26 23:57:52 +00001638protected:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001639 CommandOptions m_options;
Daniel Maleae0f8f572013-08-26 23:57:52 +00001640};
Greg Clayton95bf0fd2011-04-01 00:29:43 +00001641
Kate Stoneb9c1b512016-09-06 20:57:50 +00001642class CommandObjectPlatformProcess : public CommandObjectMultiword {
Greg Clayton32e0a752011-03-30 18:16:51 +00001643public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001644 //------------------------------------------------------------------
1645 // Constructors and Destructors
1646 //------------------------------------------------------------------
1647 CommandObjectPlatformProcess(CommandInterpreter &interpreter)
1648 : CommandObjectMultiword(interpreter, "platform process",
1649 "Commands to query, launch and attach to "
1650 "processes on the current platform.",
1651 "platform process [attach|launch|list] ...") {
1652 LoadSubCommand(
1653 "attach",
1654 CommandObjectSP(new CommandObjectPlatformProcessAttach(interpreter)));
1655 LoadSubCommand(
1656 "launch",
1657 CommandObjectSP(new CommandObjectPlatformProcessLaunch(interpreter)));
1658 LoadSubCommand("info", CommandObjectSP(new CommandObjectPlatformProcessInfo(
1659 interpreter)));
1660 LoadSubCommand("list", CommandObjectSP(new CommandObjectPlatformProcessList(
1661 interpreter)));
1662 }
Greg Clayton32e0a752011-03-30 18:16:51 +00001663
Kate Stoneb9c1b512016-09-06 20:57:50 +00001664 ~CommandObjectPlatformProcess() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001665
Greg Clayton32e0a752011-03-30 18:16:51 +00001666private:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001667 //------------------------------------------------------------------
1668 // For CommandObjectPlatform only
1669 //------------------------------------------------------------------
1670 DISALLOW_COPY_AND_ASSIGN(CommandObjectPlatformProcess);
Greg Clayton32e0a752011-03-30 18:16:51 +00001671};
Greg Claytonded470d2011-03-19 01:12:21 +00001672
Daniel Maleae0f8f572013-08-26 23:57:52 +00001673//----------------------------------------------------------------------
1674// "platform shell"
1675//----------------------------------------------------------------------
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001676static OptionDefinition g_platform_shell_options[] = {
1677 // clang-format off
1678 { 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." },
1679 // clang-format on
1680};
1681
Kate Stoneb9c1b512016-09-06 20:57:50 +00001682class CommandObjectPlatformShell : public CommandObjectRaw {
Greg Claytond1cf11a2012-04-14 01:42:46 +00001683public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001684 class CommandOptions : public Options {
1685 public:
Pavel Labath19dd1a02018-05-10 10:46:03 +00001686 CommandOptions() : Options() {}
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001687
Kate Stoneb9c1b512016-09-06 20:57:50 +00001688 ~CommandOptions() override = default;
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001689
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001690 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
Zachary Turner70602432016-09-22 21:06:13 +00001691 return llvm::makeArrayRef(g_platform_shell_options);
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001692 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001693
Zachary Turner97206d52017-05-12 04:51:55 +00001694 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1695 ExecutionContext *execution_context) override {
1696 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001697
Zachary Turner1f0f5b52016-09-22 20:22:55 +00001698 const char short_option = (char)GetDefinitions()[option_idx].short_option;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001699
1700 switch (short_option) {
Zachary Turnerfe114832016-11-12 16:56:47 +00001701 case 't':
Pavel Labath19dd1a02018-05-10 10:46:03 +00001702 uint32_t timeout_sec;
1703 if (option_arg.getAsInteger(10, timeout_sec))
Kate Stoneb9c1b512016-09-06 20:57:50 +00001704 error.SetErrorStringWithFormat(
Zachary Turnerfe114832016-11-12 16:56:47 +00001705 "could not convert \"%s\" to a numeric value.",
1706 option_arg.str().c_str());
Pavel Labath19dd1a02018-05-10 10:46:03 +00001707 else
1708 timeout = std::chrono::seconds(timeout_sec);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001709 break;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001710 default:
1711 error.SetErrorStringWithFormat("invalid short option character '%c'",
1712 short_option);
1713 break;
1714 }
1715
1716 return error;
Greg Claytond1cf11a2012-04-14 01:42:46 +00001717 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001718
Kate Stoneb9c1b512016-09-06 20:57:50 +00001719 void OptionParsingStarting(ExecutionContext *execution_context) override {}
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001720
Pavel Labath19dd1a02018-05-10 10:46:03 +00001721 Timeout<std::micro> timeout = std::chrono::seconds(10);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001722 };
Daniel Maleae0f8f572013-08-26 23:57:52 +00001723
Kate Stoneb9c1b512016-09-06 20:57:50 +00001724 CommandObjectPlatformShell(CommandInterpreter &interpreter)
1725 : CommandObjectRaw(interpreter, "platform shell",
1726 "Run a shell command on the current platform.",
1727 "platform shell <shell-command>", 0),
1728 m_options() {}
Greg Claytond1cf11a2012-04-14 01:42:46 +00001729
Kate Stoneb9c1b512016-09-06 20:57:50 +00001730 ~CommandObjectPlatformShell() override = default;
1731
1732 Options *GetOptions() override { return &m_options; }
1733
Raphael Isemann4d51a902018-07-12 22:28:52 +00001734 bool DoExecute(llvm::StringRef raw_command_line,
Kate Stoneb9c1b512016-09-06 20:57:50 +00001735 CommandReturnObject &result) override {
1736 ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext();
1737 m_options.NotifyOptionParsingStarting(&exe_ctx);
1738
Kate Stoneb9c1b512016-09-06 20:57:50 +00001739
1740 // Print out an usage syntax on an empty command line.
Raphael Isemann4d51a902018-07-12 22:28:52 +00001741 if (raw_command_line.empty()) {
Zachary Turner1e8016b2016-11-15 00:45:18 +00001742 result.GetOutputStream().Printf("%s\n", this->GetSyntax().str().c_str());
Kate Stoneb9c1b512016-09-06 20:57:50 +00001743 return true;
Greg Claytond1cf11a2012-04-14 01:42:46 +00001744 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001745
Raphael Isemann3a0e1272018-07-10 20:17:38 +00001746 OptionsWithRaw args(raw_command_line);
1747 const char *expr = args.GetRawPart().c_str();
Kate Stoneb9c1b512016-09-06 20:57:50 +00001748
Raphael Isemann3a0e1272018-07-10 20:17:38 +00001749 if (args.HasArgs())
1750 if (!ParseOptions(args.GetArgs(), result))
1751 return false;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001752
1753 PlatformSP platform_sp(
1754 m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
Zachary Turner97206d52017-05-12 04:51:55 +00001755 Status error;
Kate Stoneb9c1b512016-09-06 20:57:50 +00001756 if (platform_sp) {
1757 FileSpec working_dir{};
1758 std::string output;
1759 int status = -1;
1760 int signo = -1;
1761 error = (platform_sp->RunShellCommand(expr, working_dir, &status, &signo,
1762 &output, m_options.timeout));
1763 if (!output.empty())
Malcolm Parsons771ef6d2016-11-02 20:34:10 +00001764 result.GetOutputStream().PutCString(output);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001765 if (status > 0) {
1766 if (signo > 0) {
1767 const char *signo_cstr = Host::GetSignalAsCString(signo);
1768 if (signo_cstr)
1769 result.GetOutputStream().Printf(
1770 "error: command returned with status %i and signal %s\n",
1771 status, signo_cstr);
1772 else
1773 result.GetOutputStream().Printf(
1774 "error: command returned with status %i and signal %i\n",
1775 status, signo);
1776 } else
1777 result.GetOutputStream().Printf(
1778 "error: command returned with status %i\n", status);
1779 }
1780 } else {
1781 result.GetOutputStream().Printf(
1782 "error: cannot run remote shell commands without a platform\n");
1783 error.SetErrorString(
1784 "error: cannot run remote shell commands without a platform");
1785 }
1786
1787 if (error.Fail()) {
1788 result.AppendError(error.AsCString());
1789 result.SetStatus(eReturnStatusFailed);
1790 } else {
1791 result.SetStatus(eReturnStatusSuccessFinishResult);
1792 }
1793 return true;
1794 }
1795
1796 CommandOptions m_options;
Daniel Maleae0f8f572013-08-26 23:57:52 +00001797};
1798
Daniel Maleae0f8f572013-08-26 23:57:52 +00001799//----------------------------------------------------------------------
1800// "platform install" - install a target to a remote end
1801//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +00001802class CommandObjectPlatformInstall : public CommandObjectParsed {
Daniel Maleae0f8f572013-08-26 23:57:52 +00001803public:
Kate Stoneb9c1b512016-09-06 20:57:50 +00001804 CommandObjectPlatformInstall(CommandInterpreter &interpreter)
1805 : CommandObjectParsed(
1806 interpreter, "platform target-install",
1807 "Install a target (bundle or executable file) to the remote end.",
1808 "platform target-install <local-thing> <remote-sandbox>", 0) {}
1809
1810 ~CommandObjectPlatformInstall() override = default;
1811
1812 bool DoExecute(Args &args, CommandReturnObject &result) override {
1813 if (args.GetArgumentCount() != 2) {
1814 result.AppendError("platform target-install takes two arguments");
1815 result.SetStatus(eReturnStatusFailed);
1816 return false;
1817 }
1818 // TODO: move the bulk of this code over to the platform itself
1819 FileSpec src(args.GetArgumentAtIndex(0), true);
1820 FileSpec dst(args.GetArgumentAtIndex(1), false);
1821 if (!src.Exists()) {
1822 result.AppendError("source location does not exist or is not accessible");
1823 result.SetStatus(eReturnStatusFailed);
1824 return false;
1825 }
1826 PlatformSP platform_sp(
1827 m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
1828 if (!platform_sp) {
1829 result.AppendError("no platform currently selected");
1830 result.SetStatus(eReturnStatusFailed);
1831 return false;
Daniel Maleae0f8f572013-08-26 23:57:52 +00001832 }
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001833
Zachary Turner97206d52017-05-12 04:51:55 +00001834 Status error = platform_sp->Install(src, dst);
Kate Stoneb9c1b512016-09-06 20:57:50 +00001835 if (error.Success()) {
1836 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1837 } else {
1838 result.AppendErrorWithFormat("install failed: %s", error.AsCString());
1839 result.SetStatus(eReturnStatusFailed);
Daniel Maleae0f8f572013-08-26 23:57:52 +00001840 }
Kate Stoneb9c1b512016-09-06 20:57:50 +00001841 return result.Succeeded();
1842 }
Greg Claytond1cf11a2012-04-14 01:42:46 +00001843};
1844
Kate Stone7428a182016-07-14 22:03:10 +00001845CommandObjectPlatform::CommandObjectPlatform(CommandInterpreter &interpreter)
Kate Stoneb9c1b512016-09-06 20:57:50 +00001846 : CommandObjectMultiword(
1847 interpreter, "platform", "Commands to manage and create platforms.",
1848 "platform [connect|disconnect|info|list|status|select] ...") {
1849 LoadSubCommand("select",
1850 CommandObjectSP(new CommandObjectPlatformSelect(interpreter)));
1851 LoadSubCommand("list",
1852 CommandObjectSP(new CommandObjectPlatformList(interpreter)));
1853 LoadSubCommand("status",
1854 CommandObjectSP(new CommandObjectPlatformStatus(interpreter)));
1855 LoadSubCommand("connect", CommandObjectSP(
1856 new CommandObjectPlatformConnect(interpreter)));
1857 LoadSubCommand(
1858 "disconnect",
1859 CommandObjectSP(new CommandObjectPlatformDisconnect(interpreter)));
1860 LoadSubCommand("settings", CommandObjectSP(new CommandObjectPlatformSettings(
1861 interpreter)));
1862 LoadSubCommand("mkdir",
1863 CommandObjectSP(new CommandObjectPlatformMkDir(interpreter)));
1864 LoadSubCommand("file",
1865 CommandObjectSP(new CommandObjectPlatformFile(interpreter)));
1866 LoadSubCommand("get-file", CommandObjectSP(new CommandObjectPlatformGetFile(
1867 interpreter)));
1868 LoadSubCommand("get-size", CommandObjectSP(new CommandObjectPlatformGetSize(
1869 interpreter)));
1870 LoadSubCommand("put-file", CommandObjectSP(new CommandObjectPlatformPutFile(
1871 interpreter)));
1872 LoadSubCommand("process", CommandObjectSP(
1873 new CommandObjectPlatformProcess(interpreter)));
1874 LoadSubCommand("shell",
1875 CommandObjectSP(new CommandObjectPlatformShell(interpreter)));
1876 LoadSubCommand(
1877 "target-install",
1878 CommandObjectSP(new CommandObjectPlatformInstall(interpreter)));
Greg Claytonded470d2011-03-19 01:12:21 +00001879}
1880
Eugene Zelenko435c2c92016-02-22 19:02:01 +00001881CommandObjectPlatform::~CommandObjectPlatform() = default;