1 //===-- 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"
22 #include "lldb/Interpreter/OptionGroupPlatform.h"
23 #include "lldb/Target/ExecutionContext.h"
24 #include "lldb/Target/Platform.h"
25 #include "lldb/Target/Process.h"
26 
27 using namespace lldb;
28 using namespace lldb_private;
29 
30 
31 //----------------------------------------------------------------------
32 // "platform select <platform-name>"
33 //----------------------------------------------------------------------
34 class CommandObjectPlatformSelect : public CommandObject
35 {
36 public:
37     CommandObjectPlatformSelect (CommandInterpreter &interpreter) :
38         CommandObject (interpreter,
39                        "platform select",
40                        "Create a platform if needed and select it as the current platform.",
41                        "platform select <platform-name>",
42                        0),
43         m_option_group (interpreter),
44         m_platform_options (false) // Don't include the "--platform" option by passing false
45     {
46         m_option_group.Append (&m_platform_options, LLDB_OPT_SET_ALL, 1);
47         m_option_group.Finalize();
48     }
49 
50     virtual
51     ~CommandObjectPlatformSelect ()
52     {
53     }
54 
55     virtual bool
56     Execute (Args& args, CommandReturnObject &result)
57     {
58         if (args.GetArgumentCount() == 1)
59         {
60             const char *platform_name = args.GetArgumentAtIndex (0);
61             if (platform_name && platform_name[0])
62             {
63                 const bool select = true;
64                 m_platform_options.SetPlatformName (platform_name);
65                 Error error;
66                 PlatformSP platform_sp (m_platform_options.CreatePlatformWithOptions (m_interpreter, select, error));
67                 if (platform_sp)
68                 {
69                     platform_sp->GetStatus (result.GetOutputStream());
70                     result.SetStatus (eReturnStatusSuccessFinishResult);
71                 }
72                 else
73                 {
74                     result.AppendError(error.AsCString());
75                     result.SetStatus (eReturnStatusFailed);
76                 }
77             }
78             else
79             {
80                 result.AppendError ("invalid platform name");
81                 result.SetStatus (eReturnStatusFailed);
82             }
83         }
84         else
85         {
86             result.AppendError ("platform create takes a platform name as an argument\n");
87             result.SetStatus (eReturnStatusFailed);
88         }
89         return result.Succeeded();
90     }
91 
92 
93     virtual int
94     HandleCompletion (Args &input,
95                       int &cursor_index,
96                       int &cursor_char_position,
97                       int match_start_point,
98                       int max_return_elements,
99                       bool &word_complete,
100                       StringList &matches)
101     {
102         std::string completion_str (input.GetArgumentAtIndex(cursor_index));
103         completion_str.erase (cursor_char_position);
104 
105         CommandCompletions::PlatformPluginNames (m_interpreter,
106                                                  completion_str.c_str(),
107                                                  match_start_point,
108                                                  max_return_elements,
109                                                  NULL,
110                                                  word_complete,
111                                                  matches);
112         return matches.GetSize();
113     }
114 
115     virtual Options *
116     GetOptions ()
117     {
118         return &m_option_group;
119     }
120 
121 protected:
122     OptionGroupOptions m_option_group;
123     OptionGroupPlatform m_platform_options;
124 };
125 
126 //----------------------------------------------------------------------
127 // "platform list"
128 //----------------------------------------------------------------------
129 class CommandObjectPlatformList : public CommandObject
130 {
131 public:
132     CommandObjectPlatformList (CommandInterpreter &interpreter) :
133         CommandObject (interpreter,
134                        "platform list",
135                        "List all platforms that are available.",
136                        NULL,
137                        0)
138     {
139     }
140 
141     virtual
142     ~CommandObjectPlatformList ()
143     {
144     }
145 
146     virtual bool
147     Execute (Args& args, CommandReturnObject &result)
148     {
149         Stream &ostrm = result.GetOutputStream();
150         ostrm.Printf("Available platforms:\n");
151 
152         PlatformSP host_platform_sp (Platform::GetDefaultPlatform());
153         ostrm.Printf ("%s: %s\n",
154                       host_platform_sp->GetShortPluginName(),
155                       host_platform_sp->GetDescription());
156 
157         uint32_t idx;
158         for (idx = 0; 1; ++idx)
159         {
160             const char *plugin_name = PluginManager::GetPlatformPluginNameAtIndex (idx);
161             if (plugin_name == NULL)
162                 break;
163             const char *plugin_desc = PluginManager::GetPlatformPluginDescriptionAtIndex (idx);
164             if (plugin_desc == NULL)
165                 break;
166             ostrm.Printf("%s: %s\n", plugin_name, plugin_desc);
167         }
168 
169         if (idx == 0)
170         {
171             result.AppendError ("no platforms are available\n");
172             result.SetStatus (eReturnStatusFailed);
173         }
174         else
175             result.SetStatus (eReturnStatusSuccessFinishResult);
176         return result.Succeeded();
177     }
178 };
179 
180 //----------------------------------------------------------------------
181 // "platform status"
182 //----------------------------------------------------------------------
183 class CommandObjectPlatformStatus : public CommandObject
184 {
185 public:
186     CommandObjectPlatformStatus (CommandInterpreter &interpreter) :
187         CommandObject (interpreter,
188                        "platform status",
189                        "Display status for the currently selected platform.",
190                        NULL,
191                        0)
192     {
193     }
194 
195     virtual
196     ~CommandObjectPlatformStatus ()
197     {
198     }
199 
200     virtual bool
201     Execute (Args& args, CommandReturnObject &result)
202     {
203         Stream &ostrm = result.GetOutputStream();
204 
205         PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
206         if (platform_sp)
207         {
208             platform_sp->GetStatus (ostrm);
209             result.SetStatus (eReturnStatusSuccessFinishResult);
210         }
211         else
212         {
213             result.AppendError ("no platform us currently selected\n");
214             result.SetStatus (eReturnStatusFailed);
215         }
216         return result.Succeeded();
217     }
218 };
219 
220 //----------------------------------------------------------------------
221 // "platform connect <connect-url>"
222 //----------------------------------------------------------------------
223 class CommandObjectPlatformConnect : public CommandObject
224 {
225 public:
226     CommandObjectPlatformConnect (CommandInterpreter &interpreter) :
227         CommandObject (interpreter,
228                        "platform connect",
229                        "Connect a platform by name to be the currently selected platform.",
230                        "platform connect <connect-url>",
231                        0)
232     {
233     }
234 
235     virtual
236     ~CommandObjectPlatformConnect ()
237     {
238     }
239 
240     virtual bool
241     Execute (Args& args, CommandReturnObject &result)
242     {
243         Stream &ostrm = result.GetOutputStream();
244 
245         PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
246         if (platform_sp)
247         {
248             Error error (platform_sp->ConnectRemote (args));
249             if (error.Success())
250             {
251                 platform_sp->GetStatus (ostrm);
252                 result.SetStatus (eReturnStatusSuccessFinishResult);
253             }
254             else
255             {
256                 result.AppendErrorWithFormat ("%s\n", error.AsCString());
257                 result.SetStatus (eReturnStatusFailed);
258             }
259         }
260         else
261         {
262             result.AppendError ("no platform us currently selected\n");
263             result.SetStatus (eReturnStatusFailed);
264         }
265         return result.Succeeded();
266     }
267 };
268 
269 //----------------------------------------------------------------------
270 // "platform disconnect"
271 //----------------------------------------------------------------------
272 class CommandObjectPlatformDisconnect : public CommandObject
273 {
274 public:
275     CommandObjectPlatformDisconnect (CommandInterpreter &interpreter) :
276         CommandObject (interpreter,
277                        "platform disconnect",
278                        "Disconnect a platform by name to be the currently selected platform.",
279                        "platform disconnect",
280                        0)
281     {
282     }
283 
284     virtual
285     ~CommandObjectPlatformDisconnect ()
286     {
287     }
288 
289     virtual bool
290     Execute (Args& args, CommandReturnObject &result)
291     {
292         PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
293         if (platform_sp)
294         {
295             if (args.GetArgumentCount() == 0)
296             {
297                 Error error;
298 
299                 if (platform_sp->IsConnected())
300                 {
301                     // Cache the instance name if there is one since we are
302                     // about to disconnect and the name might go with it.
303                     const char *hostname_cstr = platform_sp->GetHostname();
304                     std::string hostname;
305                     if (hostname_cstr)
306                         hostname.assign (hostname_cstr);
307 
308                     error = platform_sp->DisconnectRemote ();
309                     if (error.Success())
310                     {
311                         Stream &ostrm = result.GetOutputStream();
312                         if (hostname.empty())
313                             ostrm.Printf ("Disconnected from \"%s\"\n", platform_sp->GetShortPluginName());
314                         else
315                             ostrm.Printf ("Disconnected from \"%s\"\n", hostname.c_str());
316                         result.SetStatus (eReturnStatusSuccessFinishResult);
317                     }
318                     else
319                     {
320                         result.AppendErrorWithFormat ("%s", error.AsCString());
321                         result.SetStatus (eReturnStatusFailed);
322                     }
323                 }
324                 else
325                 {
326                     // Not connected...
327                     result.AppendErrorWithFormat ("not connected to '%s'", platform_sp->GetShortPluginName());
328                     result.SetStatus (eReturnStatusFailed);
329                 }
330             }
331             else
332             {
333                 // Bad args
334                 result.AppendError ("\"platform disconnect\" doesn't take any arguments");
335                 result.SetStatus (eReturnStatusFailed);
336             }
337         }
338         else
339         {
340             result.AppendError ("no platform is currently selected");
341             result.SetStatus (eReturnStatusFailed);
342         }
343         return result.Succeeded();
344     }
345 };
346 //----------------------------------------------------------------------
347 // "platform process launch"
348 //----------------------------------------------------------------------
349 class CommandObjectPlatformProcessLaunch : public CommandObject
350 {
351 public:
352     CommandObjectPlatformProcessLaunch (CommandInterpreter &interpreter) :
353         CommandObject (interpreter,
354                        "platform process launch",
355                        "Launch a new process on a remote platform.",
356                        "platform process launch program",
357                        0),
358         m_options (interpreter)
359     {
360     }
361 
362     virtual
363     ~CommandObjectPlatformProcessLaunch ()
364     {
365     }
366 
367     virtual bool
368     Execute (Args& args, CommandReturnObject &result)
369     {
370         PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
371 
372         if (platform_sp)
373         {
374             Error error;
375             const uint32_t argc = args.GetArgumentCount();
376             Target *target = m_interpreter.GetExecutionContext().target;
377             ModuleSP exe_module_sp;
378             if (target)
379             {
380                 exe_module_sp = target->GetExecutableModule();
381                 if (exe_module_sp)
382                 {
383                     m_options.launch_info.GetExecutableFile () = exe_module_sp->GetFileSpec();
384                     char exe_path[PATH_MAX];
385                     if (m_options.launch_info.GetExecutableFile ().GetPath (exe_path, sizeof(exe_path)))
386                         m_options.launch_info.GetArguments().AppendArgument (exe_path);
387                     m_options.launch_info.GetArchitecture() = exe_module_sp->GetArchitecture();
388                 }
389             }
390 
391             if (argc > 0)
392             {
393                 if (m_options.launch_info.GetExecutableFile ())
394                 {
395                     // We already have an executable file, so we will use this
396                     // and all arguments to this function are extra arguments
397                     m_options.launch_info.GetArguments().AppendArguments (args);
398                 }
399                 else
400                 {
401                     // We don't have any file yet, so the first argument is our
402                     // executable, and the rest are program arguments
403                     const bool first_arg_is_executable = true;
404                     m_options.launch_info.SetArgumentsFromArgs (args,
405                                                                 first_arg_is_executable,
406                                                                 first_arg_is_executable);
407                 }
408             }
409 
410             if (m_options.launch_info.GetExecutableFile ())
411             {
412                 Debugger &debugger = m_interpreter.GetDebugger();
413 
414                 if (argc == 0)
415                 {
416                     lldb::UserSettingsControllerSP process_usc_sp (Process::GetSettingsController ());
417                     if (process_usc_sp)
418                     {
419                         SettableVariableType type;
420                         StringList settings_args (process_usc_sp->GetVariable ("process.run-args",
421                                                                                type,
422                                                                                m_interpreter.GetDebugger().GetInstanceName().GetCString(),
423                                                                                error));
424                         if (error.Success())
425                         {
426                             const size_t num_settings_args = settings_args.GetSize();
427                             for (size_t i=0; i<num_settings_args; ++i)
428                                 m_options.launch_info.GetArguments().AppendArgument (settings_args.GetStringAtIndex(i));
429                         }
430                     }
431                 }
432 
433                 ProcessSP process_sp (platform_sp->DebugProcess (m_options.launch_info,
434                                                                  debugger,
435                                                                  target,
436                                                                  debugger.GetListener(),
437                                                                  error));
438                 if (process_sp && process_sp->IsAlive())
439                 {
440                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
441                     return true;
442                 }
443 
444                 if (error.Success())
445                     result.AppendError ("process launch failed");
446                 else
447                     result.AppendError (error.AsCString());
448                 result.SetStatus (eReturnStatusFailed);
449             }
450             else
451             {
452                 result.AppendError ("'platform process launch' uses the current target file and arguments, or the executable and its arguments can be specified in this command");
453                 result.SetStatus (eReturnStatusFailed);
454                 return false;
455             }
456         }
457         else
458         {
459             result.AppendError ("no platform is selected\n");
460         }
461         return result.Succeeded();
462     }
463 
464     virtual Options *
465     GetOptions ()
466     {
467         return &m_options;
468     }
469 
470 protected:
471     ProcessLaunchCommandOptions m_options;
472 };
473 
474 
475 
476 //----------------------------------------------------------------------
477 // "platform process list"
478 //----------------------------------------------------------------------
479 class CommandObjectPlatformProcessList : public CommandObject
480 {
481 public:
482     CommandObjectPlatformProcessList (CommandInterpreter &interpreter) :
483         CommandObject (interpreter,
484                        "platform process list",
485                        "List processes on a remote platform by name, pid, or many other matching attributes.",
486                        "platform process list",
487                        0),
488         m_options (interpreter)
489     {
490     }
491 
492     virtual
493     ~CommandObjectPlatformProcessList ()
494     {
495     }
496 
497     virtual bool
498     Execute (Args& args, CommandReturnObject &result)
499     {
500         PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
501 
502         if (platform_sp)
503         {
504             Error error;
505             if (args.GetArgumentCount() == 0)
506             {
507 
508                 if (platform_sp)
509                 {
510                     Stream &ostrm = result.GetOutputStream();
511 
512                     lldb::pid_t pid = m_options.match_info.GetProcessInfo().GetProcessID();
513                     if (pid != LLDB_INVALID_PROCESS_ID)
514                     {
515                         ProcessInstanceInfo proc_info;
516                         if (platform_sp->GetProcessInfo (pid, proc_info))
517                         {
518                             ProcessInstanceInfo::DumpTableHeader (ostrm, platform_sp.get(), m_options.show_args, m_options.verbose);
519                             proc_info.DumpAsTableRow(ostrm, platform_sp.get(), m_options.show_args, m_options.verbose);
520                             result.SetStatus (eReturnStatusSuccessFinishResult);
521                         }
522                         else
523                         {
524                             result.AppendErrorWithFormat ("no process found with pid = %i\n", pid);
525                             result.SetStatus (eReturnStatusFailed);
526                         }
527                     }
528                     else
529                     {
530                         ProcessInstanceInfoList proc_infos;
531                         const uint32_t matches = platform_sp->FindProcesses (m_options.match_info, proc_infos);
532                         const char *match_desc = NULL;
533                         const char *match_name = m_options.match_info.GetProcessInfo().GetName();
534                         if (match_name && match_name[0])
535                         {
536                             switch (m_options.match_info.GetNameMatchType())
537                             {
538                                 case eNameMatchIgnore: break;
539                                 case eNameMatchEquals: match_desc = "matched"; break;
540                                 case eNameMatchContains: match_desc = "contained"; break;
541                                 case eNameMatchStartsWith: match_desc = "started with"; break;
542                                 case eNameMatchEndsWith: match_desc = "ended with"; break;
543                                 case eNameMatchRegularExpression: match_desc = "matched the regular expression"; break;
544                             }
545                         }
546 
547                         if (matches == 0)
548                         {
549                             if (match_desc)
550                                 result.AppendErrorWithFormat ("no processes were found that %s \"%s\" on the \"%s\" platform\n",
551                                                               match_desc,
552                                                               match_name,
553                                                               platform_sp->GetShortPluginName());
554                             else
555                                 result.AppendErrorWithFormat ("no processes were found on the \"%s\" platform\n", platform_sp->GetShortPluginName());
556                             result.SetStatus (eReturnStatusFailed);
557                         }
558                         else
559                         {
560                             result.AppendMessageWithFormat ("%u matching process%s found on \"%s\"",
561                                                             matches,
562                                                             matches > 1 ? "es were" : " was",
563                                                             platform_sp->GetName());
564                             if (match_desc)
565                                 result.AppendMessageWithFormat (" whose name %s \"%s\"",
566                                                                 match_desc,
567                                                                 match_name);
568                             result.AppendMessageWithFormat ("\n");
569                             ProcessInstanceInfo::DumpTableHeader (ostrm, platform_sp.get(), m_options.show_args, m_options.verbose);
570                             for (uint32_t i=0; i<matches; ++i)
571                             {
572                                 proc_infos.GetProcessInfoAtIndex(i).DumpAsTableRow(ostrm, platform_sp.get(), m_options.show_args, m_options.verbose);
573                             }
574                         }
575                     }
576                 }
577             }
578             else
579             {
580                 result.AppendError ("invalid args: process list takes only options\n");
581                 result.SetStatus (eReturnStatusFailed);
582             }
583         }
584         else
585         {
586             result.AppendError ("no platform is selected\n");
587             result.SetStatus (eReturnStatusFailed);
588         }
589         return result.Succeeded();
590     }
591 
592     virtual Options *
593     GetOptions ()
594     {
595         return &m_options;
596     }
597 
598 protected:
599 
600     class CommandOptions : public Options
601     {
602     public:
603 
604         CommandOptions (CommandInterpreter &interpreter) :
605             Options (interpreter),
606             match_info ()
607         {
608         }
609 
610         virtual
611         ~CommandOptions ()
612         {
613         }
614 
615         virtual Error
616         SetOptionValue (uint32_t option_idx, const char *option_arg)
617         {
618             Error error;
619             char short_option = (char) m_getopt_table[option_idx].val;
620             bool success = false;
621 
622             switch (short_option)
623             {
624                 case 'p':
625                     match_info.GetProcessInfo().SetProcessID (Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success));
626                     if (!success)
627                         error.SetErrorStringWithFormat("invalid process ID string: '%s'", option_arg);
628                     break;
629 
630                 case 'P':
631                     match_info.GetProcessInfo().SetParentProcessID (Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success));
632                     if (!success)
633                         error.SetErrorStringWithFormat("invalid parent process ID string: '%s'", option_arg);
634                     break;
635 
636                 case 'u':
637                     match_info.GetProcessInfo().SetUserID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success));
638                     if (!success)
639                         error.SetErrorStringWithFormat("invalid user ID string: '%s'", option_arg);
640                     break;
641 
642                 case 'U':
643                     match_info.GetProcessInfo().SetEffectiveUserID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success));
644                     if (!success)
645                         error.SetErrorStringWithFormat("invalid effective user ID string: '%s'", option_arg);
646                     break;
647 
648                 case 'g':
649                     match_info.GetProcessInfo().SetGroupID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success));
650                     if (!success)
651                         error.SetErrorStringWithFormat("invalid group ID string: '%s'", option_arg);
652                     break;
653 
654                 case 'G':
655                     match_info.GetProcessInfo().SetEffectiveGroupID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success));
656                     if (!success)
657                         error.SetErrorStringWithFormat("invalid effective group ID string: '%s'", option_arg);
658                     break;
659 
660                 case 'a':
661                     match_info.GetProcessInfo().GetArchitecture().SetTriple (option_arg, m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform().get());
662                     break;
663 
664                 case 'n':
665                     match_info.GetProcessInfo().SetName (option_arg);
666                     match_info.SetNameMatchType (eNameMatchEquals);
667                     break;
668 
669                 case 'e':
670                     match_info.GetProcessInfo().SetName (option_arg);
671                     match_info.SetNameMatchType (eNameMatchEndsWith);
672                     break;
673 
674                 case 's':
675                     match_info.GetProcessInfo().SetName (option_arg);
676                     match_info.SetNameMatchType (eNameMatchStartsWith);
677                     break;
678 
679                 case 'c':
680                     match_info.GetProcessInfo().SetName (option_arg);
681                     match_info.SetNameMatchType (eNameMatchContains);
682                     break;
683 
684                 case 'r':
685                     match_info.GetProcessInfo().SetName (option_arg);
686                     match_info.SetNameMatchType (eNameMatchRegularExpression);
687                     break;
688 
689                 case 'A':
690                     show_args = true;
691                     break;
692 
693                 case 'v':
694                     verbose = true;
695                     break;
696 
697                 default:
698                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
699                     break;
700             }
701 
702             return error;
703         }
704 
705         void
706         OptionParsingStarting ()
707         {
708             match_info.Clear();
709             show_args = false;
710             verbose = false;
711         }
712 
713         const OptionDefinition*
714         GetDefinitions ()
715         {
716             return g_option_table;
717         }
718 
719         // Options table: Required for subclasses of Options.
720 
721         static OptionDefinition g_option_table[];
722 
723         // Instance variables to hold the values for command options.
724 
725         ProcessInstanceInfoMatch match_info;
726         bool show_args;
727         bool verbose;
728     };
729     CommandOptions m_options;
730 };
731 
732 OptionDefinition
733 CommandObjectPlatformProcessList::CommandOptions::g_option_table[] =
734 {
735 {   LLDB_OPT_SET_1, false, "pid"              , 'p', required_argument, NULL, 0, eArgTypePid          , "List the process info for a specific process ID." },
736 {   LLDB_OPT_SET_2, true , "name"             , 'n', required_argument, NULL, 0, eArgTypeProcessName  , "Find processes with executable basenames that match a string." },
737 {   LLDB_OPT_SET_3, true , "ends-with"        , 'e', required_argument, NULL, 0, eArgTypeNone         , "Find processes with executable basenames that end with a string." },
738 {   LLDB_OPT_SET_4, true , "starts-with"      , 's', required_argument, NULL, 0, eArgTypeNone         , "Find processes with executable basenames that start with a string." },
739 {   LLDB_OPT_SET_5, true , "contains"         , 'c', required_argument, NULL, 0, eArgTypeNone         , "Find processes with executable basenames that contain a string." },
740 {   LLDB_OPT_SET_6, true , "regex"            , 'r', required_argument, NULL, 0, eArgTypeNone         , "Find processes with executable basenames that match a regular expression." },
741 {  ~LLDB_OPT_SET_1, false, "parent"           , 'P', required_argument, NULL, 0, eArgTypePid          , "Find processes that have a matching parent process ID." },
742 {  ~LLDB_OPT_SET_1, false, "uid"              , 'u', required_argument, NULL, 0, eArgTypeNone         , "Find processes that have a matching user ID." },
743 {  ~LLDB_OPT_SET_1, false, "euid"             , 'U', required_argument, NULL, 0, eArgTypeNone         , "Find processes that have a matching effective user ID." },
744 {  ~LLDB_OPT_SET_1, false, "gid"              , 'g', required_argument, NULL, 0, eArgTypeNone         , "Find processes that have a matching group ID." },
745 {  ~LLDB_OPT_SET_1, false, "egid"             , 'G', required_argument, NULL, 0, eArgTypeNone         , "Find processes that have a matching effective group ID." },
746 {  ~LLDB_OPT_SET_1, false, "arch"             , 'a', required_argument, NULL, 0, eArgTypeArchitecture , "Find processes that have a matching architecture." },
747 { LLDB_OPT_SET_ALL, false, "show-args"        , 'A', no_argument      , NULL, 0, eArgTypeNone         , "Show process arguments instead of the process executable basename." },
748 { LLDB_OPT_SET_ALL, false, "verbose"          , 'v', no_argument      , NULL, 0, eArgTypeNone         , "Enable verbose output." },
749 {  0              , false, NULL               ,  0 , 0                , NULL, 0, eArgTypeNone         , NULL }
750 };
751 
752 //----------------------------------------------------------------------
753 // "platform process info"
754 //----------------------------------------------------------------------
755 class CommandObjectPlatformProcessInfo : public CommandObject
756 {
757 public:
758     CommandObjectPlatformProcessInfo (CommandInterpreter &interpreter) :
759     CommandObject (interpreter,
760                    "platform process info",
761                    "Get detailed information for one or more process by process ID.",
762                    "platform process info <pid> [<pid> <pid> ...]",
763                    0)
764     {
765         CommandArgumentEntry arg;
766         CommandArgumentData pid_args;
767 
768         // Define the first (and only) variant of this arg.
769         pid_args.arg_type = eArgTypePid;
770         pid_args.arg_repetition = eArgRepeatStar;
771 
772         // There is only one variant this argument could be; put it into the argument entry.
773         arg.push_back (pid_args);
774 
775         // Push the data for the first argument into the m_arguments vector.
776         m_arguments.push_back (arg);
777     }
778 
779     virtual
780     ~CommandObjectPlatformProcessInfo ()
781     {
782     }
783 
784     virtual bool
785     Execute (Args& args, CommandReturnObject &result)
786     {
787         PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
788         if (platform_sp)
789         {
790             const size_t argc = args.GetArgumentCount();
791             if (argc > 0)
792             {
793                 Error error;
794 
795                 if (platform_sp->IsConnected())
796                 {
797                     Stream &ostrm = result.GetOutputStream();
798                     bool success;
799                     for (size_t i=0; i<argc; ++ i)
800                     {
801                         const char *arg = args.GetArgumentAtIndex(i);
802                         lldb::pid_t pid = Args::StringToUInt32 (arg, LLDB_INVALID_PROCESS_ID, 0, &success);
803                         if (success)
804                         {
805                             ProcessInstanceInfo proc_info;
806                             if (platform_sp->GetProcessInfo (pid, proc_info))
807                             {
808                                 ostrm.Printf ("Process information for process %i:\n", pid);
809                                 proc_info.Dump (ostrm, platform_sp.get());
810                             }
811                             else
812                             {
813                                 ostrm.Printf ("error: no process information is available for process %i\n", pid);
814                             }
815                             ostrm.EOL();
816                         }
817                         else
818                         {
819                             result.AppendErrorWithFormat ("invalid process ID argument '%s'", arg);
820                             result.SetStatus (eReturnStatusFailed);
821                             break;
822                         }
823                     }
824                 }
825                 else
826                 {
827                     // Not connected...
828                     result.AppendErrorWithFormat ("not connected to '%s'", platform_sp->GetShortPluginName());
829                     result.SetStatus (eReturnStatusFailed);
830                 }
831             }
832             else
833             {
834                 // No args
835                 result.AppendError ("one or more process id(s) must be specified");
836                 result.SetStatus (eReturnStatusFailed);
837             }
838         }
839         else
840         {
841             result.AppendError ("no platform is currently selected");
842             result.SetStatus (eReturnStatusFailed);
843         }
844         return result.Succeeded();
845     }
846 };
847 
848 
849 
850 
851 class CommandObjectPlatformProcess : public CommandObjectMultiword
852 {
853 public:
854     //------------------------------------------------------------------
855     // Constructors and Destructors
856     //------------------------------------------------------------------
857      CommandObjectPlatformProcess (CommandInterpreter &interpreter) :
858         CommandObjectMultiword (interpreter,
859                                 "platform process",
860                                 "A set of commands to query, launch and attach to platform processes",
861                                 "platform process [attach|launch|list] ...")
862     {
863 //        LoadSubCommand ("attach", CommandObjectSP (new CommandObjectPlatformProcessAttach (interpreter)));
864         LoadSubCommand ("launch", CommandObjectSP (new CommandObjectPlatformProcessLaunch (interpreter)));
865         LoadSubCommand ("info"  , CommandObjectSP (new CommandObjectPlatformProcessInfo (interpreter)));
866         LoadSubCommand ("list"  , CommandObjectSP (new CommandObjectPlatformProcessList (interpreter)));
867 
868     }
869 
870     virtual
871     ~CommandObjectPlatformProcess ()
872     {
873     }
874 
875 private:
876     //------------------------------------------------------------------
877     // For CommandObjectPlatform only
878     //------------------------------------------------------------------
879     DISALLOW_COPY_AND_ASSIGN (CommandObjectPlatformProcess);
880 };
881 
882 //----------------------------------------------------------------------
883 // CommandObjectPlatform constructor
884 //----------------------------------------------------------------------
885 CommandObjectPlatform::CommandObjectPlatform(CommandInterpreter &interpreter) :
886     CommandObjectMultiword (interpreter,
887                             "platform",
888                             "A set of commands to manage and create platforms.",
889                             "platform [connect|disconnect|info|list|status|select] ...")
890 {
891     LoadSubCommand ("select", CommandObjectSP (new CommandObjectPlatformSelect  (interpreter)));
892     LoadSubCommand ("list"  , CommandObjectSP (new CommandObjectPlatformList    (interpreter)));
893     LoadSubCommand ("status", CommandObjectSP (new CommandObjectPlatformStatus  (interpreter)));
894     LoadSubCommand ("connect", CommandObjectSP (new CommandObjectPlatformConnect  (interpreter)));
895     LoadSubCommand ("disconnect", CommandObjectSP (new CommandObjectPlatformDisconnect  (interpreter)));
896     LoadSubCommand ("process", CommandObjectSP (new CommandObjectPlatformProcess  (interpreter)));
897 }
898 
899 
900 //----------------------------------------------------------------------
901 // Destructor
902 //----------------------------------------------------------------------
903 CommandObjectPlatform::~CommandObjectPlatform()
904 {
905 }
906