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