blob: 7d99e71454613b14a2d041dcc3fffa20e9299ebf [file] [log] [blame]
Greg Claytonb1888f22011-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
10#include "CommandObjectPlatform.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
16#include "lldb/Core/DataExtractor.h"
17#include "lldb/Core/Debugger.h"
18#include "lldb/Core/PluginManager.h"
19#include "lldb/Interpreter/Args.h"
20#include "lldb/Interpreter/CommandInterpreter.h"
21#include "lldb/Interpreter/CommandReturnObject.h"
Greg Claytonabe0fed2011-04-18 08:33:37 +000022#include "lldb/Interpreter/OptionGroupPlatform.h"
Greg Claytonb1888f22011-03-19 01:12:21 +000023#include "lldb/Target/ExecutionContext.h"
24#include "lldb/Target/Platform.h"
Greg Claytonf15996e2011-04-07 22:46:35 +000025#include "lldb/Target/Process.h"
Greg Claytonb1888f22011-03-19 01:12:21 +000026
27using namespace lldb;
28using namespace lldb_private;
29
Greg Clayton143fcc32011-04-13 00:18:08 +000030
Greg Claytonb1888f22011-03-19 01:12:21 +000031//----------------------------------------------------------------------
Greg Claytonabe0fed2011-04-18 08:33:37 +000032// "platform select <platform-name>"
Greg Claytonb1888f22011-03-19 01:12:21 +000033//----------------------------------------------------------------------
Greg Clayton143fcc32011-04-13 00:18:08 +000034class CommandObjectPlatformSelect : public CommandObject
Greg Claytonb1888f22011-03-19 01:12:21 +000035{
36public:
Greg Clayton143fcc32011-04-13 00:18:08 +000037 CommandObjectPlatformSelect (CommandInterpreter &interpreter) :
Greg Claytonb1888f22011-03-19 01:12:21 +000038 CommandObject (interpreter,
Greg Clayton143fcc32011-04-13 00:18:08 +000039 "platform select",
40 "Create a platform if needed and select it as the current platform.",
41 "platform select <platform-name>",
Greg Claytonf15996e2011-04-07 22:46:35 +000042 0),
Greg Clayton143fcc32011-04-13 00:18:08 +000043 m_option_group (interpreter),
44 m_platform_options (false) // Don't include the "--platform" option by passing false
Greg Claytonb1888f22011-03-19 01:12:21 +000045 {
Greg Clayton5e342f52011-04-13 22:47:15 +000046 m_option_group.Append (&m_platform_options, LLDB_OPT_SET_ALL, 1);
Greg Clayton143fcc32011-04-13 00:18:08 +000047 m_option_group.Finalize();
Greg Claytonb1888f22011-03-19 01:12:21 +000048 }
49
50 virtual
Greg Clayton143fcc32011-04-13 00:18:08 +000051 ~CommandObjectPlatformSelect ()
Greg Claytonb1888f22011-03-19 01:12:21 +000052 {
53 }
54
55 virtual bool
56 Execute (Args& args, CommandReturnObject &result)
57 {
Greg Claytonb1888f22011-03-19 01:12:21 +000058 if (args.GetArgumentCount() == 1)
59 {
Greg Clayton5e342f52011-04-13 22:47:15 +000060 const char *platform_name = args.GetArgumentAtIndex (0);
61 if (platform_name && platform_name[0])
62 {
63 const bool select = true;
Greg Claytonabe0fed2011-04-18 08:33:37 +000064 m_platform_options.SetPlatformName (platform_name);
Greg Clayton5e342f52011-04-13 22:47:15 +000065 Error error;
Greg Claytonb170aee2012-05-08 01:45:38 +000066 ArchSpec platform_arch;
67 PlatformSP platform_sp (m_platform_options.CreatePlatformWithOptions (m_interpreter, ArchSpec(), select, error, platform_arch));
Greg Clayton5e342f52011-04-13 22:47:15 +000068 if (platform_sp)
69 {
70 platform_sp->GetStatus (result.GetOutputStream());
71 result.SetStatus (eReturnStatusSuccessFinishResult);
72 }
73 else
74 {
75 result.AppendError(error.AsCString());
76 result.SetStatus (eReturnStatusFailed);
77 }
78 }
79 else
80 {
81 result.AppendError ("invalid platform name");
82 result.SetStatus (eReturnStatusFailed);
83 }
Greg Claytonb1888f22011-03-19 01:12:21 +000084 }
85 else
86 {
Greg Clayton24bc5d92011-03-30 18:16:51 +000087 result.AppendError ("platform create takes a platform name as an argument\n");
Greg Claytonb1888f22011-03-19 01:12:21 +000088 result.SetStatus (eReturnStatusFailed);
89 }
90 return result.Succeeded();
91 }
92
Greg Claytonabe0fed2011-04-18 08:33:37 +000093
94 virtual int
95 HandleCompletion (Args &input,
96 int &cursor_index,
97 int &cursor_char_position,
98 int match_start_point,
99 int max_return_elements,
100 bool &word_complete,
101 StringList &matches)
102 {
103 std::string completion_str (input.GetArgumentAtIndex(cursor_index));
104 completion_str.erase (cursor_char_position);
105
106 CommandCompletions::PlatformPluginNames (m_interpreter,
107 completion_str.c_str(),
108 match_start_point,
109 max_return_elements,
110 NULL,
111 word_complete,
112 matches);
113 return matches.GetSize();
114 }
115
Greg Claytonb1888f22011-03-19 01:12:21 +0000116 virtual Options *
117 GetOptions ()
118 {
Greg Clayton143fcc32011-04-13 00:18:08 +0000119 return &m_option_group;
Greg Claytonb1888f22011-03-19 01:12:21 +0000120 }
121
122protected:
Greg Clayton143fcc32011-04-13 00:18:08 +0000123 OptionGroupOptions m_option_group;
Greg Claytonabe0fed2011-04-18 08:33:37 +0000124 OptionGroupPlatform m_platform_options;
Greg Claytonb1888f22011-03-19 01:12:21 +0000125};
126
127//----------------------------------------------------------------------
128// "platform list"
129//----------------------------------------------------------------------
130class CommandObjectPlatformList : public CommandObject
131{
132public:
133 CommandObjectPlatformList (CommandInterpreter &interpreter) :
134 CommandObject (interpreter,
135 "platform list",
136 "List all platforms that are available.",
137 NULL,
138 0)
139 {
140 }
141
142 virtual
143 ~CommandObjectPlatformList ()
144 {
145 }
146
147 virtual bool
148 Execute (Args& args, CommandReturnObject &result)
149 {
150 Stream &ostrm = result.GetOutputStream();
151 ostrm.Printf("Available platforms:\n");
152
153 PlatformSP host_platform_sp (Platform::GetDefaultPlatform());
154 ostrm.Printf ("%s: %s\n",
155 host_platform_sp->GetShortPluginName(),
156 host_platform_sp->GetDescription());
157
158 uint32_t idx;
159 for (idx = 0; 1; ++idx)
160 {
161 const char *plugin_name = PluginManager::GetPlatformPluginNameAtIndex (idx);
162 if (plugin_name == NULL)
163 break;
164 const char *plugin_desc = PluginManager::GetPlatformPluginDescriptionAtIndex (idx);
165 if (plugin_desc == NULL)
166 break;
167 ostrm.Printf("%s: %s\n", plugin_name, plugin_desc);
168 }
169
170 if (idx == 0)
171 {
Greg Clayton58e26e02011-03-24 04:28:38 +0000172 result.AppendError ("no platforms are available\n");
Greg Claytonb1888f22011-03-19 01:12:21 +0000173 result.SetStatus (eReturnStatusFailed);
174 }
Johnny Chen08150312011-03-30 21:19:59 +0000175 else
176 result.SetStatus (eReturnStatusSuccessFinishResult);
Greg Claytonb1888f22011-03-19 01:12:21 +0000177 return result.Succeeded();
178 }
179};
180
181//----------------------------------------------------------------------
182// "platform status"
183//----------------------------------------------------------------------
184class CommandObjectPlatformStatus : public CommandObject
185{
186public:
187 CommandObjectPlatformStatus (CommandInterpreter &interpreter) :
188 CommandObject (interpreter,
189 "platform status",
190 "Display status for the currently selected platform.",
191 NULL,
192 0)
193 {
194 }
195
196 virtual
197 ~CommandObjectPlatformStatus ()
198 {
199 }
200
201 virtual bool
202 Execute (Args& args, CommandReturnObject &result)
203 {
204 Stream &ostrm = result.GetOutputStream();
205
Greg Claytonff39f742011-04-01 00:29:43 +0000206 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
207 if (platform_sp)
Greg Claytonb1888f22011-03-19 01:12:21 +0000208 {
Greg Claytonff39f742011-04-01 00:29:43 +0000209 platform_sp->GetStatus (ostrm);
Greg Claytonb1888f22011-03-19 01:12:21 +0000210 result.SetStatus (eReturnStatusSuccessFinishResult);
211 }
212 else
213 {
Greg Clayton58e26e02011-03-24 04:28:38 +0000214 result.AppendError ("no platform us currently selected\n");
Greg Claytonb1888f22011-03-19 01:12:21 +0000215 result.SetStatus (eReturnStatusFailed);
216 }
217 return result.Succeeded();
218 }
219};
220
Greg Claytoncb8977d2011-03-23 00:09:55 +0000221//----------------------------------------------------------------------
222// "platform connect <connect-url>"
223//----------------------------------------------------------------------
224class CommandObjectPlatformConnect : public CommandObject
225{
226public:
227 CommandObjectPlatformConnect (CommandInterpreter &interpreter) :
228 CommandObject (interpreter,
229 "platform connect",
230 "Connect a platform by name to be the currently selected platform.",
231 "platform connect <connect-url>",
232 0)
233 {
234 }
235
236 virtual
237 ~CommandObjectPlatformConnect ()
238 {
239 }
240
241 virtual bool
242 Execute (Args& args, CommandReturnObject &result)
243 {
244 Stream &ostrm = result.GetOutputStream();
245
Greg Claytonff39f742011-04-01 00:29:43 +0000246 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
247 if (platform_sp)
Greg Claytoncb8977d2011-03-23 00:09:55 +0000248 {
Greg Claytonff39f742011-04-01 00:29:43 +0000249 Error error (platform_sp->ConnectRemote (args));
Greg Claytoncb8977d2011-03-23 00:09:55 +0000250 if (error.Success())
251 {
Greg Claytonff39f742011-04-01 00:29:43 +0000252 platform_sp->GetStatus (ostrm);
Greg Claytoncb8977d2011-03-23 00:09:55 +0000253 result.SetStatus (eReturnStatusSuccessFinishResult);
254 }
255 else
256 {
Greg Clayton58e26e02011-03-24 04:28:38 +0000257 result.AppendErrorWithFormat ("%s\n", error.AsCString());
Greg Claytoncb8977d2011-03-23 00:09:55 +0000258 result.SetStatus (eReturnStatusFailed);
259 }
260 }
261 else
262 {
Greg Clayton58e26e02011-03-24 04:28:38 +0000263 result.AppendError ("no platform us currently selected\n");
Greg Claytoncb8977d2011-03-23 00:09:55 +0000264 result.SetStatus (eReturnStatusFailed);
265 }
266 return result.Succeeded();
267 }
268};
269
270//----------------------------------------------------------------------
271// "platform disconnect"
272//----------------------------------------------------------------------
273class CommandObjectPlatformDisconnect : public CommandObject
274{
275public:
276 CommandObjectPlatformDisconnect (CommandInterpreter &interpreter) :
277 CommandObject (interpreter,
278 "platform disconnect",
279 "Disconnect a platform by name to be the currently selected platform.",
280 "platform disconnect",
281 0)
282 {
283 }
284
285 virtual
286 ~CommandObjectPlatformDisconnect ()
287 {
288 }
289
290 virtual bool
291 Execute (Args& args, CommandReturnObject &result)
292 {
Greg Claytonff39f742011-04-01 00:29:43 +0000293 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
294 if (platform_sp)
Greg Claytoncb8977d2011-03-23 00:09:55 +0000295 {
296 if (args.GetArgumentCount() == 0)
297 {
298 Error error;
299
Greg Claytonff39f742011-04-01 00:29:43 +0000300 if (platform_sp->IsConnected())
Greg Claytoncb8977d2011-03-23 00:09:55 +0000301 {
302 // Cache the instance name if there is one since we are
303 // about to disconnect and the name might go with it.
Greg Claytonff39f742011-04-01 00:29:43 +0000304 const char *hostname_cstr = platform_sp->GetHostname();
Greg Clayton58e26e02011-03-24 04:28:38 +0000305 std::string hostname;
306 if (hostname_cstr)
307 hostname.assign (hostname_cstr);
Greg Claytoncb8977d2011-03-23 00:09:55 +0000308
Greg Claytonff39f742011-04-01 00:29:43 +0000309 error = platform_sp->DisconnectRemote ();
Greg Claytoncb8977d2011-03-23 00:09:55 +0000310 if (error.Success())
311 {
312 Stream &ostrm = result.GetOutputStream();
Greg Clayton58e26e02011-03-24 04:28:38 +0000313 if (hostname.empty())
Greg Claytonff39f742011-04-01 00:29:43 +0000314 ostrm.Printf ("Disconnected from \"%s\"\n", platform_sp->GetShortPluginName());
Greg Claytoncb8977d2011-03-23 00:09:55 +0000315 else
Greg Clayton58e26e02011-03-24 04:28:38 +0000316 ostrm.Printf ("Disconnected from \"%s\"\n", hostname.c_str());
Greg Claytoncb8977d2011-03-23 00:09:55 +0000317 result.SetStatus (eReturnStatusSuccessFinishResult);
318 }
319 else
320 {
Greg Clayton58e26e02011-03-24 04:28:38 +0000321 result.AppendErrorWithFormat ("%s", error.AsCString());
Greg Claytoncb8977d2011-03-23 00:09:55 +0000322 result.SetStatus (eReturnStatusFailed);
323 }
324 }
325 else
326 {
327 // Not connected...
Greg Claytonff39f742011-04-01 00:29:43 +0000328 result.AppendErrorWithFormat ("not connected to '%s'", platform_sp->GetShortPluginName());
Greg Claytoncb8977d2011-03-23 00:09:55 +0000329 result.SetStatus (eReturnStatusFailed);
330 }
331 }
332 else
333 {
334 // Bad args
335 result.AppendError ("\"platform disconnect\" doesn't take any arguments");
336 result.SetStatus (eReturnStatusFailed);
337 }
338 }
339 else
340 {
Greg Clayton58e26e02011-03-24 04:28:38 +0000341 result.AppendError ("no platform is currently selected");
Greg Claytoncb8977d2011-03-23 00:09:55 +0000342 result.SetStatus (eReturnStatusFailed);
343 }
344 return result.Succeeded();
345 }
346};
Greg Claytonb72d0f02011-04-12 05:54:46 +0000347//----------------------------------------------------------------------
348// "platform process launch"
349//----------------------------------------------------------------------
350class CommandObjectPlatformProcessLaunch : public CommandObject
351{
352public:
353 CommandObjectPlatformProcessLaunch (CommandInterpreter &interpreter) :
354 CommandObject (interpreter,
355 "platform process launch",
356 "Launch a new process on a remote platform.",
357 "platform process launch program",
358 0),
359 m_options (interpreter)
360 {
361 }
362
363 virtual
364 ~CommandObjectPlatformProcessLaunch ()
365 {
366 }
367
368 virtual bool
369 Execute (Args& args, CommandReturnObject &result)
370 {
371 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
372
373 if (platform_sp)
374 {
375 Error error;
376 const uint32_t argc = args.GetArgumentCount();
Greg Clayton567e7f32011-09-22 04:58:26 +0000377 Target *target = m_interpreter.GetExecutionContext().GetTargetPtr();
Greg Claytonabb33022011-11-08 02:43:13 +0000378 if (target == NULL)
Greg Claytonb72d0f02011-04-12 05:54:46 +0000379 {
Greg Claytonabb33022011-11-08 02:43:13 +0000380 result.AppendError ("invalid target, create a debug target using the 'target create' command");
381 result.SetStatus (eReturnStatusFailed);
382 return false;
383 }
384
385 Module *exe_module = target->GetExecutableModulePointer();
386 if (exe_module)
387 {
388 m_options.launch_info.GetExecutableFile () = exe_module->GetFileSpec();
389 char exe_path[PATH_MAX];
390 if (m_options.launch_info.GetExecutableFile ().GetPath (exe_path, sizeof(exe_path)))
391 m_options.launch_info.GetArguments().AppendArgument (exe_path);
392 m_options.launch_info.GetArchitecture() = exe_module->GetArchitecture();
Greg Claytonb72d0f02011-04-12 05:54:46 +0000393 }
394
395 if (argc > 0)
396 {
397 if (m_options.launch_info.GetExecutableFile ())
398 {
399 // We already have an executable file, so we will use this
400 // and all arguments to this function are extra arguments
401 m_options.launch_info.GetArguments().AppendArguments (args);
402 }
403 else
404 {
405 // We don't have any file yet, so the first argument is our
406 // executable, and the rest are program arguments
407 const bool first_arg_is_executable = true;
Greg Clayton36bc5ea2011-11-03 21:22:33 +0000408 m_options.launch_info.SetArguments (args,
409 first_arg_is_executable,
410 first_arg_is_executable);
Greg Claytonb72d0f02011-04-12 05:54:46 +0000411 }
412 }
413
414 if (m_options.launch_info.GetExecutableFile ())
415 {
416 Debugger &debugger = m_interpreter.GetDebugger();
417
418 if (argc == 0)
419 {
Greg Claytonabb33022011-11-08 02:43:13 +0000420 const Args &target_settings_args = target->GetRunArguments();
421 if (target_settings_args.GetArgumentCount())
422 m_options.launch_info.GetArguments() = target_settings_args;
Greg Claytonb72d0f02011-04-12 05:54:46 +0000423 }
424
425 ProcessSP process_sp (platform_sp->DebugProcess (m_options.launch_info,
426 debugger,
427 target,
428 debugger.GetListener(),
429 error));
430 if (process_sp && process_sp->IsAlive())
431 {
432 result.SetStatus (eReturnStatusSuccessFinishNoResult);
433 return true;
434 }
435
436 if (error.Success())
437 result.AppendError ("process launch failed");
438 else
439 result.AppendError (error.AsCString());
440 result.SetStatus (eReturnStatusFailed);
441 }
442 else
443 {
444 result.AppendError ("'platform process launch' uses the current target file and arguments, or the executable and its arguments can be specified in this command");
445 result.SetStatus (eReturnStatusFailed);
446 return false;
447 }
448 }
449 else
450 {
451 result.AppendError ("no platform is selected\n");
452 }
453 return result.Succeeded();
454 }
455
456 virtual Options *
457 GetOptions ()
458 {
459 return &m_options;
460 }
461
462protected:
463 ProcessLaunchCommandOptions m_options;
464};
465
Greg Claytoncb8977d2011-03-23 00:09:55 +0000466
467
Greg Clayton24bc5d92011-03-30 18:16:51 +0000468//----------------------------------------------------------------------
469// "platform process list"
470//----------------------------------------------------------------------
471class CommandObjectPlatformProcessList : public CommandObject
472{
473public:
474 CommandObjectPlatformProcessList (CommandInterpreter &interpreter) :
Greg Claytonf15996e2011-04-07 22:46:35 +0000475 CommandObject (interpreter,
476 "platform process list",
477 "List processes on a remote platform by name, pid, or many other matching attributes.",
478 "platform process list",
479 0),
480 m_options (interpreter)
Greg Clayton24bc5d92011-03-30 18:16:51 +0000481 {
482 }
483
484 virtual
485 ~CommandObjectPlatformProcessList ()
486 {
487 }
488
489 virtual bool
490 Execute (Args& args, CommandReturnObject &result)
491 {
492 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
493
494 if (platform_sp)
495 {
496 Error error;
497 if (args.GetArgumentCount() == 0)
498 {
499
500 if (platform_sp)
501 {
Greg Claytonff39f742011-04-01 00:29:43 +0000502 Stream &ostrm = result.GetOutputStream();
503
Greg Clayton24bc5d92011-03-30 18:16:51 +0000504 lldb::pid_t pid = m_options.match_info.GetProcessInfo().GetProcessID();
505 if (pid != LLDB_INVALID_PROCESS_ID)
506 {
Greg Claytonb72d0f02011-04-12 05:54:46 +0000507 ProcessInstanceInfo proc_info;
Greg Clayton24bc5d92011-03-30 18:16:51 +0000508 if (platform_sp->GetProcessInfo (pid, proc_info))
509 {
Greg Claytonb72d0f02011-04-12 05:54:46 +0000510 ProcessInstanceInfo::DumpTableHeader (ostrm, platform_sp.get(), m_options.show_args, m_options.verbose);
511 proc_info.DumpAsTableRow(ostrm, platform_sp.get(), m_options.show_args, m_options.verbose);
Greg Clayton24bc5d92011-03-30 18:16:51 +0000512 result.SetStatus (eReturnStatusSuccessFinishResult);
513 }
514 else
515 {
Greg Claytond9919d32011-12-01 23:28:38 +0000516 result.AppendErrorWithFormat ("no process found with pid = %llu\n", pid);
Greg Clayton24bc5d92011-03-30 18:16:51 +0000517 result.SetStatus (eReturnStatusFailed);
518 }
519 }
520 else
521 {
Greg Claytonb72d0f02011-04-12 05:54:46 +0000522 ProcessInstanceInfoList proc_infos;
Greg Clayton24bc5d92011-03-30 18:16:51 +0000523 const uint32_t matches = platform_sp->FindProcesses (m_options.match_info, proc_infos);
Greg Claytonb72d0f02011-04-12 05:54:46 +0000524 const char *match_desc = NULL;
525 const char *match_name = m_options.match_info.GetProcessInfo().GetName();
526 if (match_name && match_name[0])
527 {
528 switch (m_options.match_info.GetNameMatchType())
529 {
530 case eNameMatchIgnore: break;
531 case eNameMatchEquals: match_desc = "matched"; break;
532 case eNameMatchContains: match_desc = "contained"; break;
533 case eNameMatchStartsWith: match_desc = "started with"; break;
534 case eNameMatchEndsWith: match_desc = "ended with"; break;
535 case eNameMatchRegularExpression: match_desc = "matched the regular expression"; break;
536 }
537 }
538
Greg Clayton24bc5d92011-03-30 18:16:51 +0000539 if (matches == 0)
540 {
Greg Clayton24bc5d92011-03-30 18:16:51 +0000541 if (match_desc)
542 result.AppendErrorWithFormat ("no processes were found that %s \"%s\" on the \"%s\" platform\n",
543 match_desc,
544 match_name,
545 platform_sp->GetShortPluginName());
546 else
547 result.AppendErrorWithFormat ("no processes were found on the \"%s\" platform\n", platform_sp->GetShortPluginName());
548 result.SetStatus (eReturnStatusFailed);
549 }
550 else
551 {
Greg Claytonb72d0f02011-04-12 05:54:46 +0000552 result.AppendMessageWithFormat ("%u matching process%s found on \"%s\"",
553 matches,
554 matches > 1 ? "es were" : " was",
555 platform_sp->GetName());
556 if (match_desc)
557 result.AppendMessageWithFormat (" whose name %s \"%s\"",
558 match_desc,
559 match_name);
560 result.AppendMessageWithFormat ("\n");
561 ProcessInstanceInfo::DumpTableHeader (ostrm, platform_sp.get(), m_options.show_args, m_options.verbose);
Greg Clayton24bc5d92011-03-30 18:16:51 +0000562 for (uint32_t i=0; i<matches; ++i)
563 {
Greg Claytonb72d0f02011-04-12 05:54:46 +0000564 proc_infos.GetProcessInfoAtIndex(i).DumpAsTableRow(ostrm, platform_sp.get(), m_options.show_args, m_options.verbose);
Greg Clayton24bc5d92011-03-30 18:16:51 +0000565 }
566 }
567 }
568 }
569 }
570 else
571 {
572 result.AppendError ("invalid args: process list takes only options\n");
573 result.SetStatus (eReturnStatusFailed);
574 }
575 }
576 else
577 {
578 result.AppendError ("no platform is selected\n");
579 result.SetStatus (eReturnStatusFailed);
580 }
581 return result.Succeeded();
582 }
583
584 virtual Options *
585 GetOptions ()
586 {
587 return &m_options;
588 }
589
590protected:
591
592 class CommandOptions : public Options
593 {
594 public:
595
Greg Claytonf15996e2011-04-07 22:46:35 +0000596 CommandOptions (CommandInterpreter &interpreter) :
597 Options (interpreter),
Greg Clayton24bc5d92011-03-30 18:16:51 +0000598 match_info ()
599 {
600 }
601
602 virtual
603 ~CommandOptions ()
604 {
605 }
606
607 virtual Error
Greg Clayton143fcc32011-04-13 00:18:08 +0000608 SetOptionValue (uint32_t option_idx, const char *option_arg)
Greg Clayton24bc5d92011-03-30 18:16:51 +0000609 {
610 Error error;
611 char short_option = (char) m_getopt_table[option_idx].val;
612 bool success = false;
613
614 switch (short_option)
615 {
616 case 'p':
617 match_info.GetProcessInfo().SetProcessID (Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success));
618 if (!success)
619 error.SetErrorStringWithFormat("invalid process ID string: '%s'", option_arg);
620 break;
621
622 case 'P':
623 match_info.GetProcessInfo().SetParentProcessID (Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success));
624 if (!success)
625 error.SetErrorStringWithFormat("invalid parent process ID string: '%s'", option_arg);
626 break;
627
628 case 'u':
Greg Claytonb72d0f02011-04-12 05:54:46 +0000629 match_info.GetProcessInfo().SetUserID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success));
Greg Clayton24bc5d92011-03-30 18:16:51 +0000630 if (!success)
631 error.SetErrorStringWithFormat("invalid user ID string: '%s'", option_arg);
632 break;
633
634 case 'U':
635 match_info.GetProcessInfo().SetEffectiveUserID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success));
636 if (!success)
637 error.SetErrorStringWithFormat("invalid effective user ID string: '%s'", option_arg);
638 break;
639
640 case 'g':
Greg Claytonb72d0f02011-04-12 05:54:46 +0000641 match_info.GetProcessInfo().SetGroupID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success));
Greg Clayton24bc5d92011-03-30 18:16:51 +0000642 if (!success)
643 error.SetErrorStringWithFormat("invalid group ID string: '%s'", option_arg);
644 break;
645
646 case 'G':
647 match_info.GetProcessInfo().SetEffectiveGroupID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success));
648 if (!success)
649 error.SetErrorStringWithFormat("invalid effective group ID string: '%s'", option_arg);
650 break;
651
652 case 'a':
Greg Claytonf15996e2011-04-07 22:46:35 +0000653 match_info.GetProcessInfo().GetArchitecture().SetTriple (option_arg, m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform().get());
Greg Clayton24bc5d92011-03-30 18:16:51 +0000654 break;
655
656 case 'n':
Greg Clayton527154d2011-11-15 03:53:30 +0000657 match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false);
Greg Claytonb72d0f02011-04-12 05:54:46 +0000658 match_info.SetNameMatchType (eNameMatchEquals);
Greg Clayton24bc5d92011-03-30 18:16:51 +0000659 break;
660
661 case 'e':
Greg Clayton527154d2011-11-15 03:53:30 +0000662 match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false);
Greg Clayton24bc5d92011-03-30 18:16:51 +0000663 match_info.SetNameMatchType (eNameMatchEndsWith);
664 break;
665
666 case 's':
Greg Clayton527154d2011-11-15 03:53:30 +0000667 match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false);
Greg Clayton24bc5d92011-03-30 18:16:51 +0000668 match_info.SetNameMatchType (eNameMatchStartsWith);
669 break;
670
671 case 'c':
Greg Clayton527154d2011-11-15 03:53:30 +0000672 match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false);
Greg Clayton24bc5d92011-03-30 18:16:51 +0000673 match_info.SetNameMatchType (eNameMatchContains);
674 break;
675
676 case 'r':
Greg Clayton527154d2011-11-15 03:53:30 +0000677 match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false);
Greg Clayton24bc5d92011-03-30 18:16:51 +0000678 match_info.SetNameMatchType (eNameMatchRegularExpression);
679 break;
680
Greg Claytonb72d0f02011-04-12 05:54:46 +0000681 case 'A':
682 show_args = true;
683 break;
684
685 case 'v':
686 verbose = true;
687 break;
688
Greg Clayton24bc5d92011-03-30 18:16:51 +0000689 default:
690 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
691 break;
692 }
693
694 return error;
695 }
696
697 void
Greg Clayton143fcc32011-04-13 00:18:08 +0000698 OptionParsingStarting ()
Greg Clayton24bc5d92011-03-30 18:16:51 +0000699 {
700 match_info.Clear();
Greg Claytonb72d0f02011-04-12 05:54:46 +0000701 show_args = false;
702 verbose = false;
Greg Clayton24bc5d92011-03-30 18:16:51 +0000703 }
704
705 const OptionDefinition*
706 GetDefinitions ()
707 {
708 return g_option_table;
709 }
710
711 // Options table: Required for subclasses of Options.
712
713 static OptionDefinition g_option_table[];
714
715 // Instance variables to hold the values for command options.
716
Greg Claytonb72d0f02011-04-12 05:54:46 +0000717 ProcessInstanceInfoMatch match_info;
718 bool show_args;
719 bool verbose;
Greg Clayton24bc5d92011-03-30 18:16:51 +0000720 };
721 CommandOptions m_options;
722};
723
724OptionDefinition
725CommandObjectPlatformProcessList::CommandOptions::g_option_table[] =
726{
Greg Claytonb72d0f02011-04-12 05:54:46 +0000727{ LLDB_OPT_SET_1, false, "pid" , 'p', required_argument, NULL, 0, eArgTypePid , "List the process info for a specific process ID." },
728{ LLDB_OPT_SET_2, true , "name" , 'n', required_argument, NULL, 0, eArgTypeProcessName , "Find processes with executable basenames that match a string." },
729{ LLDB_OPT_SET_3, true , "ends-with" , 'e', required_argument, NULL, 0, eArgTypeNone , "Find processes with executable basenames that end with a string." },
730{ LLDB_OPT_SET_4, true , "starts-with" , 's', required_argument, NULL, 0, eArgTypeNone , "Find processes with executable basenames that start with a string." },
731{ LLDB_OPT_SET_5, true , "contains" , 'c', required_argument, NULL, 0, eArgTypeNone , "Find processes with executable basenames that contain a string." },
732{ LLDB_OPT_SET_6, true , "regex" , 'r', required_argument, NULL, 0, eArgTypeNone , "Find processes with executable basenames that match a regular expression." },
733{ ~LLDB_OPT_SET_1, false, "parent" , 'P', required_argument, NULL, 0, eArgTypePid , "Find processes that have a matching parent process ID." },
734{ ~LLDB_OPT_SET_1, false, "uid" , 'u', required_argument, NULL, 0, eArgTypeNone , "Find processes that have a matching user ID." },
735{ ~LLDB_OPT_SET_1, false, "euid" , 'U', required_argument, NULL, 0, eArgTypeNone , "Find processes that have a matching effective user ID." },
736{ ~LLDB_OPT_SET_1, false, "gid" , 'g', required_argument, NULL, 0, eArgTypeNone , "Find processes that have a matching group ID." },
737{ ~LLDB_OPT_SET_1, false, "egid" , 'G', required_argument, NULL, 0, eArgTypeNone , "Find processes that have a matching effective group ID." },
738{ ~LLDB_OPT_SET_1, false, "arch" , 'a', required_argument, NULL, 0, eArgTypeArchitecture , "Find processes that have a matching architecture." },
739{ LLDB_OPT_SET_ALL, false, "show-args" , 'A', no_argument , NULL, 0, eArgTypeNone , "Show process arguments instead of the process executable basename." },
740{ LLDB_OPT_SET_ALL, false, "verbose" , 'v', no_argument , NULL, 0, eArgTypeNone , "Enable verbose output." },
741{ 0 , false, NULL , 0 , 0 , NULL, 0, eArgTypeNone , NULL }
Greg Clayton24bc5d92011-03-30 18:16:51 +0000742};
743
Greg Claytonff39f742011-04-01 00:29:43 +0000744//----------------------------------------------------------------------
745// "platform process info"
746//----------------------------------------------------------------------
747class CommandObjectPlatformProcessInfo : public CommandObject
748{
749public:
750 CommandObjectPlatformProcessInfo (CommandInterpreter &interpreter) :
751 CommandObject (interpreter,
752 "platform process info",
753 "Get detailed information for one or more process by process ID.",
754 "platform process info <pid> [<pid> <pid> ...]",
755 0)
756 {
757 CommandArgumentEntry arg;
758 CommandArgumentData pid_args;
759
760 // Define the first (and only) variant of this arg.
761 pid_args.arg_type = eArgTypePid;
762 pid_args.arg_repetition = eArgRepeatStar;
763
764 // There is only one variant this argument could be; put it into the argument entry.
765 arg.push_back (pid_args);
766
767 // Push the data for the first argument into the m_arguments vector.
768 m_arguments.push_back (arg);
769 }
770
771 virtual
772 ~CommandObjectPlatformProcessInfo ()
773 {
774 }
775
776 virtual bool
777 Execute (Args& args, CommandReturnObject &result)
778 {
779 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
780 if (platform_sp)
781 {
782 const size_t argc = args.GetArgumentCount();
783 if (argc > 0)
784 {
785 Error error;
786
787 if (platform_sp->IsConnected())
788 {
789 Stream &ostrm = result.GetOutputStream();
790 bool success;
791 for (size_t i=0; i<argc; ++ i)
792 {
793 const char *arg = args.GetArgumentAtIndex(i);
794 lldb::pid_t pid = Args::StringToUInt32 (arg, LLDB_INVALID_PROCESS_ID, 0, &success);
795 if (success)
796 {
Greg Claytonb72d0f02011-04-12 05:54:46 +0000797 ProcessInstanceInfo proc_info;
Greg Claytonff39f742011-04-01 00:29:43 +0000798 if (platform_sp->GetProcessInfo (pid, proc_info))
799 {
Greg Claytond9919d32011-12-01 23:28:38 +0000800 ostrm.Printf ("Process information for process %llu:\n", pid);
Greg Claytonff39f742011-04-01 00:29:43 +0000801 proc_info.Dump (ostrm, platform_sp.get());
802 }
803 else
804 {
Greg Claytond9919d32011-12-01 23:28:38 +0000805 ostrm.Printf ("error: no process information is available for process %llu\n", pid);
Greg Claytonff39f742011-04-01 00:29:43 +0000806 }
807 ostrm.EOL();
808 }
809 else
810 {
811 result.AppendErrorWithFormat ("invalid process ID argument '%s'", arg);
812 result.SetStatus (eReturnStatusFailed);
813 break;
814 }
815 }
816 }
817 else
818 {
819 // Not connected...
820 result.AppendErrorWithFormat ("not connected to '%s'", platform_sp->GetShortPluginName());
821 result.SetStatus (eReturnStatusFailed);
822 }
823 }
824 else
825 {
Johnny Chen1736fef2011-05-09 19:05:46 +0000826 // No args
827 result.AppendError ("one or more process id(s) must be specified");
Greg Claytonff39f742011-04-01 00:29:43 +0000828 result.SetStatus (eReturnStatusFailed);
829 }
830 }
831 else
832 {
833 result.AppendError ("no platform is currently selected");
834 result.SetStatus (eReturnStatusFailed);
835 }
836 return result.Succeeded();
837 }
838};
839
840
841
842
Greg Clayton24bc5d92011-03-30 18:16:51 +0000843class CommandObjectPlatformProcess : public CommandObjectMultiword
844{
845public:
846 //------------------------------------------------------------------
847 // Constructors and Destructors
848 //------------------------------------------------------------------
849 CommandObjectPlatformProcess (CommandInterpreter &interpreter) :
850 CommandObjectMultiword (interpreter,
851 "platform process",
852 "A set of commands to query, launch and attach to platform processes",
853 "platform process [attach|launch|list] ...")
854 {
855// LoadSubCommand ("attach", CommandObjectSP (new CommandObjectPlatformProcessAttach (interpreter)));
Greg Claytonb72d0f02011-04-12 05:54:46 +0000856 LoadSubCommand ("launch", CommandObjectSP (new CommandObjectPlatformProcessLaunch (interpreter)));
Greg Claytonff39f742011-04-01 00:29:43 +0000857 LoadSubCommand ("info" , CommandObjectSP (new CommandObjectPlatformProcessInfo (interpreter)));
Greg Clayton24bc5d92011-03-30 18:16:51 +0000858 LoadSubCommand ("list" , CommandObjectSP (new CommandObjectPlatformProcessList (interpreter)));
859
860 }
861
862 virtual
863 ~CommandObjectPlatformProcess ()
864 {
865 }
866
867private:
868 //------------------------------------------------------------------
869 // For CommandObjectPlatform only
870 //------------------------------------------------------------------
871 DISALLOW_COPY_AND_ASSIGN (CommandObjectPlatformProcess);
872};
Greg Claytonb1888f22011-03-19 01:12:21 +0000873
Greg Clayton97471182012-04-14 01:42:46 +0000874
875class CommandObjectPlatformShell : public CommandObject
876{
877public:
878 CommandObjectPlatformShell (CommandInterpreter &interpreter) :
879 CommandObject (interpreter,
880 "platform shell",
881 "Run a shell command on a the selected platform.",
882 "platform shell <shell-command>",
883 0)
884 {
885 }
886
887 virtual
888 ~CommandObjectPlatformShell ()
889 {
890 }
891
892 virtual bool
893 Execute (Args& command,
894 CommandReturnObject &result)
895 {
896 return false;
897 }
898
899 virtual bool
900 WantsRawCommandString() { return true; }
901
902 bool
903 ExecuteRawCommandString (const char *raw_command_line, CommandReturnObject &result)
904 {
905 // TODO: Implement "Platform::RunShellCommand()" and switch over to using
906 // the current platform when it is in the interface.
907 const char *working_dir = NULL;
908 std::string output;
909 int status = -1;
910 int signo = -1;
911 Error error (Host::RunShellCommand (raw_command_line, working_dir, &status, &signo, &output, 10));
912 if (!output.empty())
913 result.GetOutputStream().PutCString(output.c_str());
914 if (status > 0)
915 {
916 if (signo > 0)
917 {
918 const char *signo_cstr = Host::GetSignalAsCString(signo);
919 if (signo_cstr)
920 result.GetOutputStream().Printf("error: command returned with status %i and signal %s\n", status, signo_cstr);
921 else
922 result.GetOutputStream().Printf("error: command returned with status %i and signal %i\n", status, signo);
923 }
924 else
925 result.GetOutputStream().Printf("error: command returned with status %i\n", status);
926 }
927
928 if (error.Fail())
929 {
930 result.AppendError(error.AsCString());
931 result.SetStatus (eReturnStatusFailed);
932 }
933 else
934 {
935 result.SetStatus (eReturnStatusSuccessFinishResult);
936 }
937 return true;
938 }
939
940protected:
941};
942
Greg Claytonb1888f22011-03-19 01:12:21 +0000943//----------------------------------------------------------------------
944// CommandObjectPlatform constructor
945//----------------------------------------------------------------------
946CommandObjectPlatform::CommandObjectPlatform(CommandInterpreter &interpreter) :
947 CommandObjectMultiword (interpreter,
948 "platform",
949 "A set of commands to manage and create platforms.",
Greg Clayton143fcc32011-04-13 00:18:08 +0000950 "platform [connect|disconnect|info|list|status|select] ...")
Greg Claytonb1888f22011-03-19 01:12:21 +0000951{
Greg Claytonb1888f22011-03-19 01:12:21 +0000952 LoadSubCommand ("select", CommandObjectSP (new CommandObjectPlatformSelect (interpreter)));
Greg Clayton143fcc32011-04-13 00:18:08 +0000953 LoadSubCommand ("list" , CommandObjectSP (new CommandObjectPlatformList (interpreter)));
Greg Claytonb1888f22011-03-19 01:12:21 +0000954 LoadSubCommand ("status", CommandObjectSP (new CommandObjectPlatformStatus (interpreter)));
Greg Claytoncb8977d2011-03-23 00:09:55 +0000955 LoadSubCommand ("connect", CommandObjectSP (new CommandObjectPlatformConnect (interpreter)));
956 LoadSubCommand ("disconnect", CommandObjectSP (new CommandObjectPlatformDisconnect (interpreter)));
Greg Clayton24bc5d92011-03-30 18:16:51 +0000957 LoadSubCommand ("process", CommandObjectSP (new CommandObjectPlatformProcess (interpreter)));
Greg Clayton97471182012-04-14 01:42:46 +0000958 LoadSubCommand ("shell", CommandObjectSP (new CommandObjectPlatformShell (interpreter)));
Greg Claytonb1888f22011-03-19 01:12:21 +0000959}
960
961
962//----------------------------------------------------------------------
963// Destructor
964//----------------------------------------------------------------------
965CommandObjectPlatform::~CommandObjectPlatform()
966{
967}