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