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/Host/StringConvert.h"
23 #include "lldb/Interpreter/Args.h"
24 #include "lldb/Interpreter/CommandInterpreter.h"
25 #include "lldb/Interpreter/CommandOptionValidators.h"
26 #include "lldb/Interpreter/CommandReturnObject.h"
27 #include "lldb/Interpreter/OptionGroupFile.h"
28 #include "lldb/Interpreter/OptionGroupPlatform.h"
29 #include "lldb/Target/ExecutionContext.h"
30 #include "lldb/Target/Platform.h"
31 #include "lldb/Target/Process.h"
32 #include "lldb/Utility/Utils.h"
33 
34 using namespace lldb;
35 using namespace lldb_private;
36 
37 static mode_t
38 ParsePermissionString(const char* permissions)
39 {
40     if (strlen(permissions) != 9)
41         return (mode_t)(-1);
42     bool user_r,user_w,user_x,
43     group_r,group_w,group_x,
44     world_r,world_w,world_x;
45 
46     user_r = (permissions[0] == 'r');
47     user_w = (permissions[1] == 'w');
48     user_x = (permissions[2] == 'x');
49 
50     group_r = (permissions[3] == 'r');
51     group_w = (permissions[4] == 'w');
52     group_x = (permissions[5] == 'x');
53 
54     world_r = (permissions[6] == 'r');
55     world_w = (permissions[7] == 'w');
56     world_x = (permissions[8] == 'x');
57 
58     mode_t user,group,world;
59     user = (user_r ? 4 : 0) | (user_w ? 2 : 0) | (user_x ? 1 : 0);
60     group = (group_r ? 4 : 0) | (group_w ? 2 : 0) | (group_x ? 1 : 0);
61     world = (world_r ? 4 : 0) | (world_w ? 2 : 0) | (world_x ? 1 : 0);
62 
63     return user | group | world;
64 }
65 
66 static OptionDefinition
67 g_permissions_options[] =
68 {
69     {   LLDB_OPT_SET_ALL, false, "permissions-value",   'v', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePermissionsNumber         , "Give out the numeric value for permissions (e.g. 757)" },
70     {   LLDB_OPT_SET_ALL, false, "permissions-string",  's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePermissionsString  , "Give out the string value for permissions (e.g. rwxr-xr--)." },
71     {   LLDB_OPT_SET_ALL, false, "user-read",           'r', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Allow user to read." },
72     {   LLDB_OPT_SET_ALL, false, "user-write",          'w', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Allow user to write." },
73     {   LLDB_OPT_SET_ALL, false, "user-exec",           'x', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Allow user to execute." },
74 
75     {   LLDB_OPT_SET_ALL, false, "group-read",          'R', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Allow group to read." },
76     {   LLDB_OPT_SET_ALL, false, "group-write",         'W', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Allow group to write." },
77     {   LLDB_OPT_SET_ALL, false, "group-exec",          'X', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Allow group to execute." },
78 
79     {   LLDB_OPT_SET_ALL, false, "world-read",          'd', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Allow world to read." },
80     {   LLDB_OPT_SET_ALL, false, "world-write",         't', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Allow world to write." },
81     {   LLDB_OPT_SET_ALL, false, "world-exec",          'e', OptionParser::eNoArgument,       NULL, NULL, 0, eArgTypeNone         , "Allow world to execute." },
82 };
83 
84 class OptionPermissions : public lldb_private::OptionGroup
85 {
86 public:
87     OptionPermissions ()
88     {
89     }
90 
91     virtual
92     ~OptionPermissions ()
93     {
94     }
95 
96     virtual lldb_private::Error
97     SetOptionValue (CommandInterpreter &interpreter,
98                     uint32_t option_idx,
99                     const char *option_arg)
100     {
101         Error error;
102         char short_option = (char) GetDefinitions()[option_idx].short_option;
103         switch (short_option)
104         {
105             case 'v':
106             {
107                 bool ok;
108                 uint32_t perms = StringConvert::ToUInt32(option_arg, 777, 8, &ok);
109                 if (!ok)
110                     error.SetErrorStringWithFormat("invalid value for permissions: %s", option_arg);
111                 else
112                     m_permissions = perms;
113             }
114                 break;
115             case 's':
116             {
117                 mode_t perms = ParsePermissionString(option_arg);
118                 if (perms == (mode_t)-1)
119                     error.SetErrorStringWithFormat("invalid value for permissions: %s", option_arg);
120                 else
121                     m_permissions = perms;
122             }
123             case 'r':
124                 m_permissions |= lldb::eFilePermissionsUserRead;
125                 break;
126             case 'w':
127                 m_permissions |= lldb::eFilePermissionsUserWrite;
128                 break;
129             case 'x':
130                 m_permissions |= lldb::eFilePermissionsUserExecute;
131                 break;
132             case 'R':
133                 m_permissions |= lldb::eFilePermissionsGroupRead;
134                 break;
135             case 'W':
136                 m_permissions |= lldb::eFilePermissionsGroupWrite;
137                 break;
138             case 'X':
139                 m_permissions |= lldb::eFilePermissionsGroupExecute;
140                 break;
141             case 'd':
142                 m_permissions |= lldb::eFilePermissionsWorldRead;
143                 break;
144             case 't':
145                 m_permissions |= lldb::eFilePermissionsWorldWrite;
146                 break;
147             case 'e':
148                 m_permissions |= lldb::eFilePermissionsWorldExecute;
149                 break;
150 
151             default:
152                 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
153                 break;
154         }
155 
156         return error;
157     }
158 
159     void
160     OptionParsingStarting (CommandInterpreter &interpreter)
161     {
162         m_permissions = 0;
163     }
164 
165     virtual uint32_t
166     GetNumDefinitions ()
167     {
168         return llvm::array_lengthof(g_permissions_options);
169     }
170 
171     const lldb_private::OptionDefinition*
172     GetDefinitions ()
173     {
174         return g_permissions_options;
175     }
176 
177     // Instance variables to hold the values for command options.
178 
179     uint32_t m_permissions;
180 private:
181     DISALLOW_COPY_AND_ASSIGN(OptionPermissions);
182 };
183 
184 //----------------------------------------------------------------------
185 // "platform select <platform-name>"
186 //----------------------------------------------------------------------
187 class CommandObjectPlatformSelect : public CommandObjectParsed
188 {
189 public:
190     CommandObjectPlatformSelect (CommandInterpreter &interpreter) :
191         CommandObjectParsed (interpreter,
192                              "platform select",
193                              "Create a platform if needed and select it as the current platform.",
194                              "platform select <platform-name>",
195                              0),
196         m_option_group (interpreter),
197         m_platform_options (false) // Don't include the "--platform" option by passing false
198     {
199         m_option_group.Append (&m_platform_options, LLDB_OPT_SET_ALL, 1);
200         m_option_group.Finalize();
201     }
202 
203     virtual
204     ~CommandObjectPlatformSelect ()
205     {
206     }
207 
208     virtual int
209     HandleCompletion (Args &input,
210                       int &cursor_index,
211                       int &cursor_char_position,
212                       int match_start_point,
213                       int max_return_elements,
214                       bool &word_complete,
215                       StringList &matches)
216     {
217         std::string completion_str (input.GetArgumentAtIndex(cursor_index));
218         completion_str.erase (cursor_char_position);
219 
220         CommandCompletions::PlatformPluginNames (m_interpreter,
221                                                  completion_str.c_str(),
222                                                  match_start_point,
223                                                  max_return_elements,
224                                                  NULL,
225                                                  word_complete,
226                                                  matches);
227         return matches.GetSize();
228     }
229 
230     virtual Options *
231     GetOptions ()
232     {
233         return &m_option_group;
234     }
235 
236 protected:
237     virtual bool
238     DoExecute (Args& args, CommandReturnObject &result)
239     {
240         if (args.GetArgumentCount() == 1)
241         {
242             const char *platform_name = args.GetArgumentAtIndex (0);
243             if (platform_name && platform_name[0])
244             {
245                 const bool select = true;
246                 m_platform_options.SetPlatformName (platform_name);
247                 Error error;
248                 ArchSpec platform_arch;
249                 PlatformSP platform_sp (m_platform_options.CreatePlatformWithOptions (m_interpreter, ArchSpec(), select, error, platform_arch));
250                 if (platform_sp)
251                 {
252                     m_interpreter.GetDebugger().GetPlatformList().SetSelectedPlatform(platform_sp);
253 
254                     platform_sp->GetStatus (result.GetOutputStream());
255                     result.SetStatus (eReturnStatusSuccessFinishResult);
256                 }
257                 else
258                 {
259                     result.AppendError(error.AsCString());
260                     result.SetStatus (eReturnStatusFailed);
261                 }
262             }
263             else
264             {
265                 result.AppendError ("invalid platform name");
266                 result.SetStatus (eReturnStatusFailed);
267             }
268         }
269         else
270         {
271             result.AppendError ("platform create takes a platform name as an argument\n");
272             result.SetStatus (eReturnStatusFailed);
273         }
274         return result.Succeeded();
275     }
276 
277     OptionGroupOptions m_option_group;
278     OptionGroupPlatform m_platform_options;
279 };
280 
281 //----------------------------------------------------------------------
282 // "platform list"
283 //----------------------------------------------------------------------
284 class CommandObjectPlatformList : public CommandObjectParsed
285 {
286 public:
287     CommandObjectPlatformList (CommandInterpreter &interpreter) :
288         CommandObjectParsed (interpreter,
289                              "platform list",
290                              "List all platforms that are available.",
291                              NULL,
292                              0)
293     {
294     }
295 
296     virtual
297     ~CommandObjectPlatformList ()
298     {
299     }
300 
301 protected:
302     virtual bool
303     DoExecute (Args& args, CommandReturnObject &result)
304     {
305         Stream &ostrm = result.GetOutputStream();
306         ostrm.Printf("Available platforms:\n");
307 
308         PlatformSP host_platform_sp (Platform::GetHostPlatform());
309         ostrm.Printf ("%s: %s\n",
310                       host_platform_sp->GetPluginName().GetCString(),
311                       host_platform_sp->GetDescription());
312 
313         uint32_t idx;
314         for (idx = 0; 1; ++idx)
315         {
316             const char *plugin_name = PluginManager::GetPlatformPluginNameAtIndex (idx);
317             if (plugin_name == NULL)
318                 break;
319             const char *plugin_desc = PluginManager::GetPlatformPluginDescriptionAtIndex (idx);
320             if (plugin_desc == NULL)
321                 break;
322             ostrm.Printf("%s: %s\n", plugin_name, plugin_desc);
323         }
324 
325         if (idx == 0)
326         {
327             result.AppendError ("no platforms are available\n");
328             result.SetStatus (eReturnStatusFailed);
329         }
330         else
331             result.SetStatus (eReturnStatusSuccessFinishResult);
332         return result.Succeeded();
333     }
334 };
335 
336 //----------------------------------------------------------------------
337 // "platform status"
338 //----------------------------------------------------------------------
339 class CommandObjectPlatformStatus : public CommandObjectParsed
340 {
341 public:
342     CommandObjectPlatformStatus (CommandInterpreter &interpreter) :
343         CommandObjectParsed (interpreter,
344                              "platform status",
345                              "Display status for the currently selected platform.",
346                              NULL,
347                              0)
348     {
349     }
350 
351     virtual
352     ~CommandObjectPlatformStatus ()
353     {
354     }
355 
356 protected:
357     virtual bool
358     DoExecute (Args& args, CommandReturnObject &result)
359     {
360         Stream &ostrm = result.GetOutputStream();
361 
362         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
363         PlatformSP platform_sp;
364         if (target)
365         {
366             platform_sp = target->GetPlatform();
367         }
368         if (!platform_sp)
369         {
370             platform_sp = m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform();
371         }
372         if (platform_sp)
373         {
374             platform_sp->GetStatus (ostrm);
375             result.SetStatus (eReturnStatusSuccessFinishResult);
376         }
377         else
378         {
379             result.AppendError ("no platform us currently selected\n");
380             result.SetStatus (eReturnStatusFailed);
381         }
382         return result.Succeeded();
383     }
384 };
385 
386 //----------------------------------------------------------------------
387 // "platform connect <connect-url>"
388 //----------------------------------------------------------------------
389 class CommandObjectPlatformConnect : public CommandObjectParsed
390 {
391 public:
392     CommandObjectPlatformConnect (CommandInterpreter &interpreter) :
393         CommandObjectParsed (interpreter,
394                              "platform connect",
395                              "Connect a platform by name to be the currently selected platform.",
396                              "platform connect <connect-url>",
397                              0)
398     {
399     }
400 
401     virtual
402     ~CommandObjectPlatformConnect ()
403     {
404     }
405 
406 protected:
407     virtual bool
408     DoExecute (Args& args, CommandReturnObject &result)
409     {
410         Stream &ostrm = result.GetOutputStream();
411 
412         PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
413         if (platform_sp)
414         {
415             Error error (platform_sp->ConnectRemote (args));
416             if (error.Success())
417             {
418                 platform_sp->GetStatus (ostrm);
419                 result.SetStatus (eReturnStatusSuccessFinishResult);
420             }
421             else
422             {
423                 result.AppendErrorWithFormat ("%s\n", error.AsCString());
424                 result.SetStatus (eReturnStatusFailed);
425             }
426         }
427         else
428         {
429             result.AppendError ("no platform is currently selected\n");
430             result.SetStatus (eReturnStatusFailed);
431         }
432         return result.Succeeded();
433     }
434 
435     virtual Options *
436     GetOptions ()
437     {
438         PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
439         OptionGroupOptions* m_platform_options = NULL;
440         if (platform_sp)
441         {
442             m_platform_options = platform_sp->GetConnectionOptions(m_interpreter);
443             if (m_platform_options != NULL && !m_platform_options->m_did_finalize)
444                 m_platform_options->Finalize();
445         }
446         return m_platform_options;
447     }
448 
449 };
450 
451 //----------------------------------------------------------------------
452 // "platform disconnect"
453 //----------------------------------------------------------------------
454 class CommandObjectPlatformDisconnect : public CommandObjectParsed
455 {
456 public:
457     CommandObjectPlatformDisconnect (CommandInterpreter &interpreter) :
458         CommandObjectParsed (interpreter,
459                              "platform disconnect",
460                              "Disconnect a platform by name to be the currently selected platform.",
461                              "platform disconnect",
462                              0)
463     {
464     }
465 
466     virtual
467     ~CommandObjectPlatformDisconnect ()
468     {
469     }
470 
471 protected:
472     virtual bool
473     DoExecute (Args& args, CommandReturnObject &result)
474     {
475         PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
476         if (platform_sp)
477         {
478             if (args.GetArgumentCount() == 0)
479             {
480                 Error error;
481 
482                 if (platform_sp->IsConnected())
483                 {
484                     // Cache the instance name if there is one since we are
485                     // about to disconnect and the name might go with it.
486                     const char *hostname_cstr = platform_sp->GetHostname();
487                     std::string hostname;
488                     if (hostname_cstr)
489                         hostname.assign (hostname_cstr);
490 
491                     error = platform_sp->DisconnectRemote ();
492                     if (error.Success())
493                     {
494                         Stream &ostrm = result.GetOutputStream();
495                         if (hostname.empty())
496                             ostrm.Printf ("Disconnected from \"%s\"\n", platform_sp->GetPluginName().GetCString());
497                         else
498                             ostrm.Printf ("Disconnected from \"%s\"\n", hostname.c_str());
499                         result.SetStatus (eReturnStatusSuccessFinishResult);
500                     }
501                     else
502                     {
503                         result.AppendErrorWithFormat ("%s", error.AsCString());
504                         result.SetStatus (eReturnStatusFailed);
505                     }
506                 }
507                 else
508                 {
509                     // Not connected...
510                     result.AppendErrorWithFormat ("not connected to '%s'", platform_sp->GetPluginName().GetCString());
511                     result.SetStatus (eReturnStatusFailed);
512                 }
513             }
514             else
515             {
516                 // Bad args
517                 result.AppendError ("\"platform disconnect\" doesn't take any arguments");
518                 result.SetStatus (eReturnStatusFailed);
519             }
520         }
521         else
522         {
523             result.AppendError ("no platform is currently selected");
524             result.SetStatus (eReturnStatusFailed);
525         }
526         return result.Succeeded();
527     }
528 };
529 
530 //----------------------------------------------------------------------
531 // "platform settings"
532 //----------------------------------------------------------------------
533 class CommandObjectPlatformSettings : public CommandObjectParsed
534 {
535 public:
536     CommandObjectPlatformSettings (CommandInterpreter &interpreter) :
537         CommandObjectParsed (interpreter,
538                              "platform settings",
539                              "Set settings for the current target's platform, or for a platform by name.",
540                              "platform settings",
541                              0),
542         m_options (interpreter),
543         m_option_working_dir (LLDB_OPT_SET_1, false, "working-dir", 'w', 0, eArgTypePath, "The working directory for the platform.")
544     {
545         m_options.Append (&m_option_working_dir, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
546     }
547 
548     virtual
549     ~CommandObjectPlatformSettings ()
550     {
551     }
552 
553 protected:
554     virtual bool
555     DoExecute (Args& args, CommandReturnObject &result)
556     {
557         PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
558         if (platform_sp)
559         {
560             if (m_option_working_dir.GetOptionValue().OptionWasSet())
561                 platform_sp->SetWorkingDirectory (ConstString(m_option_working_dir.GetOptionValue().GetCurrentValue().GetPath().c_str()));
562         }
563         else
564         {
565             result.AppendError ("no platform is currently selected");
566             result.SetStatus (eReturnStatusFailed);
567         }
568         return result.Succeeded();
569     }
570 
571     virtual Options *
572     GetOptions ()
573     {
574         if (m_options.DidFinalize() == false)
575             m_options.Finalize();
576         return &m_options;
577     }
578 protected:
579 
580     OptionGroupOptions m_options;
581     OptionGroupFile m_option_working_dir;
582 
583 };
584 
585 
586 //----------------------------------------------------------------------
587 // "platform mkdir"
588 //----------------------------------------------------------------------
589 class CommandObjectPlatformMkDir : public CommandObjectParsed
590 {
591 public:
592     CommandObjectPlatformMkDir (CommandInterpreter &interpreter) :
593     CommandObjectParsed (interpreter,
594                          "platform mkdir",
595                          "Make a new directory on the remote end.",
596                          NULL,
597                          0),
598     m_options(interpreter)
599     {
600     }
601 
602     virtual
603     ~CommandObjectPlatformMkDir ()
604     {
605     }
606 
607     virtual bool
608     DoExecute (Args& args, CommandReturnObject &result)
609     {
610         PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
611         if (platform_sp)
612         {
613             std::string cmd_line;
614             args.GetCommandString(cmd_line);
615             uint32_t mode;
616             const OptionPermissions* options_permissions = (const OptionPermissions*)m_options.GetGroupWithOption('r');
617             if (options_permissions)
618                 mode = options_permissions->m_permissions;
619             else
620                 mode = lldb::eFilePermissionsUserRWX | lldb::eFilePermissionsGroupRWX | lldb::eFilePermissionsWorldRX;
621             Error error = platform_sp->MakeDirectory(cmd_line.c_str(), mode);
622             if (error.Success())
623             {
624                 result.SetStatus (eReturnStatusSuccessFinishResult);
625             }
626             else
627             {
628                 result.AppendError(error.AsCString());
629                 result.SetStatus (eReturnStatusFailed);
630             }
631         }
632         else
633         {
634             result.AppendError ("no platform currently selected\n");
635             result.SetStatus (eReturnStatusFailed);
636         }
637         return result.Succeeded();
638     }
639 
640     virtual Options *
641     GetOptions ()
642     {
643         if (m_options.DidFinalize() == false)
644         {
645             m_options.Append(new OptionPermissions());
646             m_options.Finalize();
647         }
648         return &m_options;
649     }
650     OptionGroupOptions m_options;
651 
652 };
653 
654 //----------------------------------------------------------------------
655 // "platform fopen"
656 //----------------------------------------------------------------------
657 class CommandObjectPlatformFOpen : public CommandObjectParsed
658 {
659 public:
660     CommandObjectPlatformFOpen (CommandInterpreter &interpreter) :
661     CommandObjectParsed (interpreter,
662                          "platform file open",
663                          "Open a file on the remote end.",
664                          NULL,
665                          0),
666     m_options(interpreter)
667     {
668     }
669 
670     virtual
671     ~CommandObjectPlatformFOpen ()
672     {
673     }
674 
675     virtual bool
676     DoExecute (Args& args, CommandReturnObject &result)
677     {
678         PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
679         if (platform_sp)
680         {
681             Error error;
682             std::string cmd_line;
683             args.GetCommandString(cmd_line);
684             mode_t perms;
685             const OptionPermissions* options_permissions = (const OptionPermissions*)m_options.GetGroupWithOption('r');
686             if (options_permissions)
687                 perms = options_permissions->m_permissions;
688             else
689                 perms = lldb::eFilePermissionsUserRW | lldb::eFilePermissionsGroupRW | lldb::eFilePermissionsWorldRead;
690             lldb::user_id_t fd = platform_sp->OpenFile(FileSpec(cmd_line.c_str(),false),
691                                                        File::eOpenOptionRead | File::eOpenOptionWrite |
692                                                        File::eOpenOptionAppend | File::eOpenOptionCanCreate,
693                                                        perms,
694                                                        error);
695             if (error.Success())
696             {
697                 result.AppendMessageWithFormat("File Descriptor = %" PRIu64 "\n",fd);
698                 result.SetStatus (eReturnStatusSuccessFinishResult);
699             }
700             else
701             {
702                 result.AppendError(error.AsCString());
703                 result.SetStatus (eReturnStatusFailed);
704             }
705         }
706         else
707         {
708             result.AppendError ("no platform currently selected\n");
709             result.SetStatus (eReturnStatusFailed);
710         }
711         return result.Succeeded();
712     }
713     virtual Options *
714     GetOptions ()
715     {
716         if (m_options.DidFinalize() == false)
717         {
718             m_options.Append(new OptionPermissions());
719             m_options.Finalize();
720         }
721         return &m_options;
722     }
723     OptionGroupOptions m_options;
724 };
725 
726 //----------------------------------------------------------------------
727 // "platform fclose"
728 //----------------------------------------------------------------------
729 class CommandObjectPlatformFClose : public CommandObjectParsed
730 {
731 public:
732     CommandObjectPlatformFClose (CommandInterpreter &interpreter) :
733     CommandObjectParsed (interpreter,
734                          "platform file close",
735                          "Close a file on the remote end.",
736                          NULL,
737                          0)
738     {
739     }
740 
741     virtual
742     ~CommandObjectPlatformFClose ()
743     {
744     }
745 
746     virtual bool
747     DoExecute (Args& args, CommandReturnObject &result)
748     {
749         PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
750         if (platform_sp)
751         {
752             std::string cmd_line;
753             args.GetCommandString(cmd_line);
754             const lldb::user_id_t fd = StringConvert::ToUInt64(cmd_line.c_str(), UINT64_MAX);
755             Error error;
756             bool success = platform_sp->CloseFile(fd, error);
757             if (success)
758             {
759                 result.AppendMessageWithFormat("file %" PRIu64 " closed.\n", fd);
760                 result.SetStatus (eReturnStatusSuccessFinishResult);
761             }
762             else
763             {
764                 result.AppendError(error.AsCString());
765                 result.SetStatus (eReturnStatusFailed);
766             }
767         }
768         else
769         {
770             result.AppendError ("no platform currently selected\n");
771             result.SetStatus (eReturnStatusFailed);
772         }
773         return result.Succeeded();
774     }
775 };
776 
777 //----------------------------------------------------------------------
778 // "platform fread"
779 //----------------------------------------------------------------------
780 class CommandObjectPlatformFRead : public CommandObjectParsed
781 {
782 public:
783     CommandObjectPlatformFRead (CommandInterpreter &interpreter) :
784     CommandObjectParsed (interpreter,
785                          "platform file read",
786                          "Read data from a file on the remote end.",
787                          NULL,
788                          0),
789     m_options (interpreter)
790     {
791     }
792 
793     virtual
794     ~CommandObjectPlatformFRead ()
795     {
796     }
797 
798     virtual bool
799     DoExecute (Args& args, CommandReturnObject &result)
800     {
801         PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
802         if (platform_sp)
803         {
804             std::string cmd_line;
805             args.GetCommandString(cmd_line);
806             const lldb::user_id_t fd = StringConvert::ToUInt64(cmd_line.c_str(), UINT64_MAX);
807             std::string buffer(m_options.m_count,0);
808             Error error;
809             uint32_t retcode = platform_sp->ReadFile(fd, m_options.m_offset, &buffer[0], m_options.m_count, error);
810             result.AppendMessageWithFormat("Return = %d\n",retcode);
811             result.AppendMessageWithFormat("Data = \"%s\"\n",buffer.c_str());
812             result.SetStatus (eReturnStatusSuccessFinishResult);
813         }
814         else
815         {
816             result.AppendError ("no platform currently selected\n");
817             result.SetStatus (eReturnStatusFailed);
818         }
819         return result.Succeeded();
820     }
821     virtual Options *
822     GetOptions ()
823     {
824         return &m_options;
825     }
826 
827 protected:
828     class CommandOptions : public Options
829     {
830     public:
831 
832         CommandOptions (CommandInterpreter &interpreter) :
833         Options (interpreter)
834         {
835         }
836 
837         virtual
838         ~CommandOptions ()
839         {
840         }
841 
842         virtual Error
843         SetOptionValue (uint32_t option_idx, const char *option_arg)
844         {
845             Error error;
846             char short_option = (char) m_getopt_table[option_idx].val;
847             bool success = false;
848 
849             switch (short_option)
850             {
851                 case 'o':
852                     m_offset = StringConvert::ToUInt32(option_arg, 0, 0, &success);
853                     if (!success)
854                         error.SetErrorStringWithFormat("invalid offset: '%s'", option_arg);
855                     break;
856                 case 'c':
857                     m_count = StringConvert::ToUInt32(option_arg, 0, 0, &success);
858                     if (!success)
859                         error.SetErrorStringWithFormat("invalid offset: '%s'", option_arg);
860                     break;
861 
862                 default:
863                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
864                     break;
865             }
866 
867             return error;
868         }
869 
870         void
871         OptionParsingStarting ()
872         {
873             m_offset = 0;
874             m_count = 1;
875         }
876 
877         const OptionDefinition*
878         GetDefinitions ()
879         {
880             return g_option_table;
881         }
882 
883         // Options table: Required for subclasses of Options.
884 
885         static OptionDefinition g_option_table[];
886 
887         // Instance variables to hold the values for command options.
888 
889         uint32_t m_offset;
890         uint32_t m_count;
891     };
892     CommandOptions m_options;
893 };
894 OptionDefinition
895 CommandObjectPlatformFRead::CommandOptions::g_option_table[] =
896 {
897     {   LLDB_OPT_SET_1, false, "offset"           , 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeIndex        , "Offset into the file at which to start reading." },
898     {   LLDB_OPT_SET_1, false, "count"            , 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCount        , "Number of bytes to read from the file." },
899     {  0              , false, NULL               ,  0 , 0                              , NULL, NULL, 0, eArgTypeNone         , NULL }
900 };
901 
902 
903 //----------------------------------------------------------------------
904 // "platform fwrite"
905 //----------------------------------------------------------------------
906 class CommandObjectPlatformFWrite : public CommandObjectParsed
907 {
908 public:
909     CommandObjectPlatformFWrite (CommandInterpreter &interpreter) :
910     CommandObjectParsed (interpreter,
911                          "platform file write",
912                          "Write data to a file on the remote end.",
913                          NULL,
914                          0),
915     m_options (interpreter)
916     {
917     }
918 
919     virtual
920     ~CommandObjectPlatformFWrite ()
921     {
922     }
923 
924     virtual bool
925     DoExecute (Args& args, CommandReturnObject &result)
926     {
927         PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
928         if (platform_sp)
929         {
930             std::string cmd_line;
931             args.GetCommandString(cmd_line);
932             Error error;
933             const lldb::user_id_t fd = StringConvert::ToUInt64(cmd_line.c_str(), UINT64_MAX);
934             uint32_t retcode = platform_sp->WriteFile (fd,
935                                                        m_options.m_offset,
936                                                        &m_options.m_data[0],
937                                                        m_options.m_data.size(),
938                                                        error);
939             result.AppendMessageWithFormat("Return = %d\n",retcode);
940             result.SetStatus (eReturnStatusSuccessFinishResult);
941         }
942         else
943         {
944             result.AppendError ("no platform currently selected\n");
945             result.SetStatus (eReturnStatusFailed);
946         }
947         return result.Succeeded();
948     }
949     virtual Options *
950     GetOptions ()
951     {
952         return &m_options;
953     }
954 
955 protected:
956     class CommandOptions : public Options
957     {
958     public:
959 
960         CommandOptions (CommandInterpreter &interpreter) :
961         Options (interpreter)
962         {
963         }
964 
965         virtual
966         ~CommandOptions ()
967         {
968         }
969 
970         virtual Error
971         SetOptionValue (uint32_t option_idx, const char *option_arg)
972         {
973             Error error;
974             char short_option = (char) m_getopt_table[option_idx].val;
975             bool success = false;
976 
977             switch (short_option)
978             {
979                 case 'o':
980                     m_offset = StringConvert::ToUInt32(option_arg, 0, 0, &success);
981                     if (!success)
982                         error.SetErrorStringWithFormat("invalid offset: '%s'", option_arg);
983                     break;
984                 case 'd':
985                     m_data.assign(option_arg);
986                     break;
987 
988                 default:
989                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
990                     break;
991             }
992 
993             return error;
994         }
995 
996         void
997         OptionParsingStarting ()
998         {
999             m_offset = 0;
1000             m_data.clear();
1001         }
1002 
1003         const OptionDefinition*
1004         GetDefinitions ()
1005         {
1006             return g_option_table;
1007         }
1008 
1009         // Options table: Required for subclasses of Options.
1010 
1011         static OptionDefinition g_option_table[];
1012 
1013         // Instance variables to hold the values for command options.
1014 
1015         uint32_t m_offset;
1016         std::string m_data;
1017     };
1018     CommandOptions m_options;
1019 };
1020 OptionDefinition
1021 CommandObjectPlatformFWrite::CommandOptions::g_option_table[] =
1022 {
1023     {   LLDB_OPT_SET_1, false, "offset"           , 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeIndex        , "Offset into the file at which to start reading." },
1024     {   LLDB_OPT_SET_1, false, "data"            , 'd', OptionParser::eRequiredArgument , NULL, NULL, 0, eArgTypeValue        , "Text to write to the file." },
1025     {  0              , false, NULL               ,  0 , 0                              , NULL, NULL, 0, eArgTypeNone         , NULL }
1026 };
1027 
1028 class CommandObjectPlatformFile : public CommandObjectMultiword
1029 {
1030 public:
1031     //------------------------------------------------------------------
1032     // Constructors and Destructors
1033     //------------------------------------------------------------------
1034     CommandObjectPlatformFile (CommandInterpreter &interpreter) :
1035     CommandObjectMultiword (interpreter,
1036                             "platform file",
1037                             "A set of commands to manage file access through a platform",
1038                             "platform file [open|close|read|write] ...")
1039     {
1040         LoadSubCommand ("open", CommandObjectSP (new CommandObjectPlatformFOpen  (interpreter)));
1041         LoadSubCommand ("close", CommandObjectSP (new CommandObjectPlatformFClose  (interpreter)));
1042         LoadSubCommand ("read", CommandObjectSP (new CommandObjectPlatformFRead  (interpreter)));
1043         LoadSubCommand ("write", CommandObjectSP (new CommandObjectPlatformFWrite  (interpreter)));
1044     }
1045 
1046     virtual
1047     ~CommandObjectPlatformFile ()
1048     {
1049     }
1050 
1051 private:
1052     //------------------------------------------------------------------
1053     // For CommandObjectPlatform only
1054     //------------------------------------------------------------------
1055     DISALLOW_COPY_AND_ASSIGN (CommandObjectPlatformFile);
1056 };
1057 
1058 //----------------------------------------------------------------------
1059 // "platform get-file remote-file-path host-file-path"
1060 //----------------------------------------------------------------------
1061 class CommandObjectPlatformGetFile : public CommandObjectParsed
1062 {
1063 public:
1064     CommandObjectPlatformGetFile (CommandInterpreter &interpreter) :
1065     CommandObjectParsed (interpreter,
1066                          "platform get-file",
1067                          "Transfer a file from the remote end to the local host.",
1068                          "platform get-file <remote-file-spec> <local-file-spec>",
1069                          0)
1070     {
1071         SetHelpLong(
1072 "Examples: \n\
1073 \n\
1074     platform get-file /the/remote/file/path /the/local/file/path\n\
1075     # Transfer a file from the remote end with file path /the/remote/file/path to the local host.\n");
1076 
1077         CommandArgumentEntry arg1, arg2;
1078         CommandArgumentData file_arg_remote, file_arg_host;
1079 
1080         // Define the first (and only) variant of this arg.
1081         file_arg_remote.arg_type = eArgTypeFilename;
1082         file_arg_remote.arg_repetition = eArgRepeatPlain;
1083         // There is only one variant this argument could be; put it into the argument entry.
1084         arg1.push_back (file_arg_remote);
1085 
1086         // Define the second (and only) variant of this arg.
1087         file_arg_host.arg_type = eArgTypeFilename;
1088         file_arg_host.arg_repetition = eArgRepeatPlain;
1089         // There is only one variant this argument could be; put it into the argument entry.
1090         arg2.push_back (file_arg_host);
1091 
1092         // Push the data for the first and the second arguments into the m_arguments vector.
1093         m_arguments.push_back (arg1);
1094         m_arguments.push_back (arg2);
1095     }
1096 
1097     virtual
1098     ~CommandObjectPlatformGetFile ()
1099     {
1100     }
1101 
1102     virtual bool
1103     DoExecute (Args& args, CommandReturnObject &result)
1104     {
1105         // If the number of arguments is incorrect, issue an error message.
1106         if (args.GetArgumentCount() != 2)
1107         {
1108             result.GetErrorStream().Printf("error: required arguments missing; specify both the source and destination file paths\n");
1109             result.SetStatus(eReturnStatusFailed);
1110             return false;
1111         }
1112 
1113         PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
1114         if (platform_sp)
1115         {
1116             const char *remote_file_path = args.GetArgumentAtIndex(0);
1117             const char *local_file_path = args.GetArgumentAtIndex(1);
1118             Error error = platform_sp->GetFile(FileSpec(remote_file_path, false),
1119                                                FileSpec(local_file_path, false));
1120             if (error.Success())
1121             {
1122                 result.AppendMessageWithFormat("successfully get-file from %s (remote) to %s (host)\n",
1123                                                remote_file_path, local_file_path);
1124                 result.SetStatus (eReturnStatusSuccessFinishResult);
1125             }
1126             else
1127             {
1128                 result.AppendMessageWithFormat("get-file failed: %s\n", error.AsCString());
1129                 result.SetStatus (eReturnStatusFailed);
1130             }
1131         }
1132         else
1133         {
1134             result.AppendError ("no platform currently selected\n");
1135             result.SetStatus (eReturnStatusFailed);
1136         }
1137         return result.Succeeded();
1138     }
1139 };
1140 
1141 //----------------------------------------------------------------------
1142 // "platform get-size remote-file-path"
1143 //----------------------------------------------------------------------
1144 class CommandObjectPlatformGetSize : public CommandObjectParsed
1145 {
1146 public:
1147     CommandObjectPlatformGetSize (CommandInterpreter &interpreter) :
1148     CommandObjectParsed (interpreter,
1149                          "platform get-size",
1150                          "Get the file size from the remote end.",
1151                          "platform get-size <remote-file-spec>",
1152                          0)
1153     {
1154         SetHelpLong(
1155 "Examples: \n\
1156 \n\
1157     platform get-size /the/remote/file/path\n\
1158     # Get the file size from the remote end with path /the/remote/file/path.\n");
1159 
1160         CommandArgumentEntry arg1;
1161         CommandArgumentData file_arg_remote;
1162 
1163         // Define the first (and only) variant of this arg.
1164         file_arg_remote.arg_type = eArgTypeFilename;
1165         file_arg_remote.arg_repetition = eArgRepeatPlain;
1166         // There is only one variant this argument could be; put it into the argument entry.
1167         arg1.push_back (file_arg_remote);
1168 
1169         // Push the data for the first argument into the m_arguments vector.
1170         m_arguments.push_back (arg1);
1171     }
1172 
1173     virtual
1174     ~CommandObjectPlatformGetSize ()
1175     {
1176     }
1177 
1178     virtual bool
1179     DoExecute (Args& args, CommandReturnObject &result)
1180     {
1181         // If the number of arguments is incorrect, issue an error message.
1182         if (args.GetArgumentCount() != 1)
1183         {
1184             result.GetErrorStream().Printf("error: required argument missing; specify the source file path as the only argument\n");
1185             result.SetStatus(eReturnStatusFailed);
1186             return false;
1187         }
1188 
1189         PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
1190         if (platform_sp)
1191         {
1192             std::string remote_file_path(args.GetArgumentAtIndex(0));
1193             user_id_t size = platform_sp->GetFileSize(FileSpec(remote_file_path.c_str(), false));
1194             if (size != UINT64_MAX)
1195             {
1196                 result.AppendMessageWithFormat("File size of %s (remote): %" PRIu64 "\n", remote_file_path.c_str(), size);
1197                 result.SetStatus (eReturnStatusSuccessFinishResult);
1198             }
1199             else
1200             {
1201                 result.AppendMessageWithFormat("Eroor getting file size of %s (remote)\n", remote_file_path.c_str());
1202                 result.SetStatus (eReturnStatusFailed);
1203             }
1204         }
1205         else
1206         {
1207             result.AppendError ("no platform currently selected\n");
1208             result.SetStatus (eReturnStatusFailed);
1209         }
1210         return result.Succeeded();
1211     }
1212 };
1213 
1214 //----------------------------------------------------------------------
1215 // "platform put-file"
1216 //----------------------------------------------------------------------
1217 class CommandObjectPlatformPutFile : public CommandObjectParsed
1218 {
1219 public:
1220     CommandObjectPlatformPutFile (CommandInterpreter &interpreter) :
1221     CommandObjectParsed (interpreter,
1222                          "platform put-file",
1223                          "Transfer a file from this system to the remote end.",
1224                          NULL,
1225                          0)
1226     {
1227     }
1228 
1229     virtual
1230     ~CommandObjectPlatformPutFile ()
1231     {
1232     }
1233 
1234     virtual bool
1235     DoExecute (Args& args, CommandReturnObject &result)
1236     {
1237         const char* src = args.GetArgumentAtIndex(0);
1238         const char* dst = args.GetArgumentAtIndex(1);
1239 
1240         FileSpec src_fs(src, true);
1241         FileSpec dst_fs(dst ? dst : src_fs.GetFilename().GetCString(), false);
1242 
1243         PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
1244         if (platform_sp)
1245         {
1246             Error error (platform_sp->PutFile(src_fs, dst_fs));
1247             if (error.Success())
1248             {
1249                 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1250             }
1251             else
1252             {
1253                 result.AppendError (error.AsCString());
1254                 result.SetStatus (eReturnStatusFailed);
1255             }
1256         }
1257         else
1258         {
1259             result.AppendError ("no platform currently selected\n");
1260             result.SetStatus (eReturnStatusFailed);
1261         }
1262         return result.Succeeded();
1263     }
1264 };
1265 
1266 //----------------------------------------------------------------------
1267 // "platform process launch"
1268 //----------------------------------------------------------------------
1269 class CommandObjectPlatformProcessLaunch : public CommandObjectParsed
1270 {
1271 public:
1272     CommandObjectPlatformProcessLaunch (CommandInterpreter &interpreter) :
1273         CommandObjectParsed (interpreter,
1274                              "platform process launch",
1275                              "Launch a new process on a remote platform.",
1276                              "platform process launch program",
1277                              eFlagRequiresTarget | eFlagTryTargetAPILock),
1278         m_options (interpreter)
1279     {
1280     }
1281 
1282     virtual
1283     ~CommandObjectPlatformProcessLaunch ()
1284     {
1285     }
1286 
1287     virtual Options *
1288     GetOptions ()
1289     {
1290         return &m_options;
1291     }
1292 
1293 protected:
1294     virtual bool
1295     DoExecute (Args& args, CommandReturnObject &result)
1296     {
1297         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1298         PlatformSP platform_sp;
1299         if (target)
1300         {
1301             platform_sp = target->GetPlatform();
1302         }
1303         if (!platform_sp)
1304         {
1305             platform_sp = m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform();
1306         }
1307 
1308         if (platform_sp)
1309         {
1310             Error error;
1311             const size_t argc = args.GetArgumentCount();
1312             Target *target = m_exe_ctx.GetTargetPtr();
1313             Module *exe_module = target->GetExecutableModulePointer();
1314             if (exe_module)
1315             {
1316                 m_options.launch_info.GetExecutableFile () = exe_module->GetFileSpec();
1317                 char exe_path[PATH_MAX];
1318                 if (m_options.launch_info.GetExecutableFile ().GetPath (exe_path, sizeof(exe_path)))
1319                     m_options.launch_info.GetArguments().AppendArgument (exe_path);
1320                 m_options.launch_info.GetArchitecture() = exe_module->GetArchitecture();
1321             }
1322 
1323             if (argc > 0)
1324             {
1325                 if (m_options.launch_info.GetExecutableFile ())
1326                 {
1327                     // We already have an executable file, so we will use this
1328                     // and all arguments to this function are extra arguments
1329                     m_options.launch_info.GetArguments().AppendArguments (args);
1330                 }
1331                 else
1332                 {
1333                     // We don't have any file yet, so the first argument is our
1334                     // executable, and the rest are program arguments
1335                     const bool first_arg_is_executable = true;
1336                     m_options.launch_info.SetArguments (args, first_arg_is_executable);
1337                 }
1338             }
1339 
1340             if (m_options.launch_info.GetExecutableFile ())
1341             {
1342                 Debugger &debugger = m_interpreter.GetDebugger();
1343 
1344                 if (argc == 0)
1345                     target->GetRunArguments(m_options.launch_info.GetArguments());
1346 
1347                 ProcessSP process_sp (platform_sp->DebugProcess (m_options.launch_info,
1348                                                                  debugger,
1349                                                                  target,
1350                                                                  error));
1351                 if (process_sp && process_sp->IsAlive())
1352                 {
1353                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
1354                     return true;
1355                 }
1356 
1357                 if (error.Success())
1358                     result.AppendError ("process launch failed");
1359                 else
1360                     result.AppendError (error.AsCString());
1361                 result.SetStatus (eReturnStatusFailed);
1362             }
1363             else
1364             {
1365                 result.AppendError ("'platform process launch' uses the current target file and arguments, or the executable and its arguments can be specified in this command");
1366                 result.SetStatus (eReturnStatusFailed);
1367                 return false;
1368             }
1369         }
1370         else
1371         {
1372             result.AppendError ("no platform is selected\n");
1373         }
1374         return result.Succeeded();
1375     }
1376 
1377 protected:
1378     ProcessLaunchCommandOptions m_options;
1379 };
1380 
1381 
1382 
1383 //----------------------------------------------------------------------
1384 // "platform process list"
1385 //----------------------------------------------------------------------
1386 class CommandObjectPlatformProcessList : public CommandObjectParsed
1387 {
1388 public:
1389     CommandObjectPlatformProcessList (CommandInterpreter &interpreter) :
1390         CommandObjectParsed (interpreter,
1391                              "platform process list",
1392                              "List processes on a remote platform by name, pid, or many other matching attributes.",
1393                              "platform process list",
1394                              0),
1395         m_options (interpreter)
1396     {
1397     }
1398 
1399     virtual
1400     ~CommandObjectPlatformProcessList ()
1401     {
1402     }
1403 
1404     virtual Options *
1405     GetOptions ()
1406     {
1407         return &m_options;
1408     }
1409 
1410 protected:
1411     virtual bool
1412     DoExecute (Args& args, CommandReturnObject &result)
1413     {
1414         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1415         PlatformSP platform_sp;
1416         if (target)
1417         {
1418             platform_sp = target->GetPlatform();
1419         }
1420         if (!platform_sp)
1421         {
1422             platform_sp = m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform();
1423         }
1424 
1425         if (platform_sp)
1426         {
1427             Error error;
1428             if (args.GetArgumentCount() == 0)
1429             {
1430 
1431                 if (platform_sp)
1432                 {
1433                     Stream &ostrm = result.GetOutputStream();
1434 
1435                     lldb::pid_t pid = m_options.match_info.GetProcessInfo().GetProcessID();
1436                     if (pid != LLDB_INVALID_PROCESS_ID)
1437                     {
1438                         ProcessInstanceInfo proc_info;
1439                         if (platform_sp->GetProcessInfo (pid, proc_info))
1440                         {
1441                             ProcessInstanceInfo::DumpTableHeader (ostrm, platform_sp.get(), m_options.show_args, m_options.verbose);
1442                             proc_info.DumpAsTableRow(ostrm, platform_sp.get(), m_options.show_args, m_options.verbose);
1443                             result.SetStatus (eReturnStatusSuccessFinishResult);
1444                         }
1445                         else
1446                         {
1447                             result.AppendErrorWithFormat ("no process found with pid = %" PRIu64 "\n", pid);
1448                             result.SetStatus (eReturnStatusFailed);
1449                         }
1450                     }
1451                     else
1452                     {
1453                         ProcessInstanceInfoList proc_infos;
1454                         const uint32_t matches = platform_sp->FindProcesses (m_options.match_info, proc_infos);
1455                         const char *match_desc = NULL;
1456                         const char *match_name = m_options.match_info.GetProcessInfo().GetName();
1457                         if (match_name && match_name[0])
1458                         {
1459                             switch (m_options.match_info.GetNameMatchType())
1460                             {
1461                                 case eNameMatchIgnore: break;
1462                                 case eNameMatchEquals: match_desc = "matched"; break;
1463                                 case eNameMatchContains: match_desc = "contained"; break;
1464                                 case eNameMatchStartsWith: match_desc = "started with"; break;
1465                                 case eNameMatchEndsWith: match_desc = "ended with"; break;
1466                                 case eNameMatchRegularExpression: match_desc = "matched the regular expression"; break;
1467                             }
1468                         }
1469 
1470                         if (matches == 0)
1471                         {
1472                             if (match_desc)
1473                                 result.AppendErrorWithFormat ("no processes were found that %s \"%s\" on the \"%s\" platform\n",
1474                                                               match_desc,
1475                                                               match_name,
1476                                                               platform_sp->GetPluginName().GetCString());
1477                             else
1478                                 result.AppendErrorWithFormat ("no processes were found on the \"%s\" platform\n", platform_sp->GetPluginName().GetCString());
1479                             result.SetStatus (eReturnStatusFailed);
1480                         }
1481                         else
1482                         {
1483                             result.AppendMessageWithFormat ("%u matching process%s found on \"%s\"",
1484                                                             matches,
1485                                                             matches > 1 ? "es were" : " was",
1486                                                             platform_sp->GetName().GetCString());
1487                             if (match_desc)
1488                                 result.AppendMessageWithFormat (" whose name %s \"%s\"",
1489                                                                 match_desc,
1490                                                                 match_name);
1491                             result.AppendMessageWithFormat ("\n");
1492                             ProcessInstanceInfo::DumpTableHeader (ostrm, platform_sp.get(), m_options.show_args, m_options.verbose);
1493                             for (uint32_t i=0; i<matches; ++i)
1494                             {
1495                                 proc_infos.GetProcessInfoAtIndex(i).DumpAsTableRow(ostrm, platform_sp.get(), m_options.show_args, m_options.verbose);
1496                             }
1497                         }
1498                     }
1499                 }
1500             }
1501             else
1502             {
1503                 result.AppendError ("invalid args: process list takes only options\n");
1504                 result.SetStatus (eReturnStatusFailed);
1505             }
1506         }
1507         else
1508         {
1509             result.AppendError ("no platform is selected\n");
1510             result.SetStatus (eReturnStatusFailed);
1511         }
1512         return result.Succeeded();
1513     }
1514 
1515     class CommandOptions : public Options
1516     {
1517     public:
1518 
1519         CommandOptions (CommandInterpreter &interpreter) :
1520             Options (interpreter),
1521             match_info ()
1522         {
1523         }
1524 
1525         virtual
1526         ~CommandOptions ()
1527         {
1528         }
1529 
1530         virtual Error
1531         SetOptionValue (uint32_t option_idx, const char *option_arg)
1532         {
1533             Error error;
1534             const int short_option = m_getopt_table[option_idx].val;
1535             bool success = false;
1536 
1537             switch (short_option)
1538             {
1539                 case 'p':
1540                     match_info.GetProcessInfo().SetProcessID (StringConvert::ToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success));
1541                     if (!success)
1542                         error.SetErrorStringWithFormat("invalid process ID string: '%s'", option_arg);
1543                     break;
1544 
1545                 case 'P':
1546                     match_info.GetProcessInfo().SetParentProcessID (StringConvert::ToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success));
1547                     if (!success)
1548                         error.SetErrorStringWithFormat("invalid parent process ID string: '%s'", option_arg);
1549                     break;
1550 
1551                 case 'u':
1552                     match_info.GetProcessInfo().SetUserID (StringConvert::ToUInt32 (option_arg, UINT32_MAX, 0, &success));
1553                     if (!success)
1554                         error.SetErrorStringWithFormat("invalid user ID string: '%s'", option_arg);
1555                     break;
1556 
1557                 case 'U':
1558                     match_info.GetProcessInfo().SetEffectiveUserID (StringConvert::ToUInt32 (option_arg, UINT32_MAX, 0, &success));
1559                     if (!success)
1560                         error.SetErrorStringWithFormat("invalid effective user ID string: '%s'", option_arg);
1561                     break;
1562 
1563                 case 'g':
1564                     match_info.GetProcessInfo().SetGroupID (StringConvert::ToUInt32 (option_arg, UINT32_MAX, 0, &success));
1565                     if (!success)
1566                         error.SetErrorStringWithFormat("invalid group ID string: '%s'", option_arg);
1567                     break;
1568 
1569                 case 'G':
1570                     match_info.GetProcessInfo().SetEffectiveGroupID (StringConvert::ToUInt32 (option_arg, UINT32_MAX, 0, &success));
1571                     if (!success)
1572                         error.SetErrorStringWithFormat("invalid effective group ID string: '%s'", option_arg);
1573                     break;
1574 
1575                 case 'a':
1576                     match_info.GetProcessInfo().GetArchitecture().SetTriple (option_arg, m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform().get());
1577                     break;
1578 
1579                 case 'n':
1580                     match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false);
1581                     match_info.SetNameMatchType (eNameMatchEquals);
1582                     break;
1583 
1584                 case 'e':
1585                     match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false);
1586                     match_info.SetNameMatchType (eNameMatchEndsWith);
1587                     break;
1588 
1589                 case 's':
1590                     match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false);
1591                     match_info.SetNameMatchType (eNameMatchStartsWith);
1592                     break;
1593 
1594                 case 'c':
1595                     match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false);
1596                     match_info.SetNameMatchType (eNameMatchContains);
1597                     break;
1598 
1599                 case 'r':
1600                     match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false);
1601                     match_info.SetNameMatchType (eNameMatchRegularExpression);
1602                     break;
1603 
1604                 case 'A':
1605                     show_args = true;
1606                     break;
1607 
1608                 case 'v':
1609                     verbose = true;
1610                     break;
1611 
1612                 default:
1613                     error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
1614                     break;
1615             }
1616 
1617             return error;
1618         }
1619 
1620         void
1621         OptionParsingStarting ()
1622         {
1623             match_info.Clear();
1624             show_args = false;
1625             verbose = false;
1626         }
1627 
1628         const OptionDefinition*
1629         GetDefinitions ()
1630         {
1631             return g_option_table;
1632         }
1633 
1634         // Options table: Required for subclasses of Options.
1635 
1636         static OptionDefinition g_option_table[];
1637 
1638         // Instance variables to hold the values for command options.
1639 
1640         ProcessInstanceInfoMatch match_info;
1641         bool show_args;
1642         bool verbose;
1643     };
1644     CommandOptions m_options;
1645 };
1646 
1647 namespace
1648 {
1649     PosixPlatformCommandOptionValidator g_posix_validator;
1650 }
1651 
1652 OptionDefinition
1653 CommandObjectPlatformProcessList::CommandOptions::g_option_table[] =
1654 {
1655 { LLDB_OPT_SET_1            , false, "pid"        , 'p', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePid              , "List the process info for a specific process ID." },
1656 { LLDB_OPT_SET_2            , true , "name"       , 'n', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeProcessName      , "Find processes with executable basenames that match a string." },
1657 { LLDB_OPT_SET_3            , true , "ends-with"  , 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeProcessName      , "Find processes with executable basenames that end with a string." },
1658 { LLDB_OPT_SET_4            , true , "starts-with", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeProcessName      , "Find processes with executable basenames that start with a string." },
1659 { LLDB_OPT_SET_5            , true , "contains"   , 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeProcessName      , "Find processes with executable basenames that contain a string." },
1660 { LLDB_OPT_SET_6            , true , "regex"      , 'r', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeRegularExpression, "Find processes with executable basenames that match a regular expression." },
1661 { LLDB_OPT_SET_FROM_TO(2, 6), false, "parent"     , 'P', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePid              , "Find processes that have a matching parent process ID." },
1662 { LLDB_OPT_SET_FROM_TO(2, 6), false, "uid"        , 'u', OptionParser::eRequiredArgument, &g_posix_validator, NULL, 0, eArgTypeUnsignedInteger  , "Find processes that have a matching user ID." },
1663 { LLDB_OPT_SET_FROM_TO(2, 6), false, "euid"       , 'U', OptionParser::eRequiredArgument, &g_posix_validator, NULL, 0, eArgTypeUnsignedInteger  , "Find processes that have a matching effective user ID." },
1664 { LLDB_OPT_SET_FROM_TO(2, 6), false, "gid"        , 'g', OptionParser::eRequiredArgument, &g_posix_validator, NULL, 0, eArgTypeUnsignedInteger  , "Find processes that have a matching group ID." },
1665 { LLDB_OPT_SET_FROM_TO(2, 6), false, "egid"       , 'G', OptionParser::eRequiredArgument, &g_posix_validator, NULL, 0, eArgTypeUnsignedInteger  , "Find processes that have a matching effective group ID." },
1666 { LLDB_OPT_SET_FROM_TO(2, 6), false, "arch"       , 'a', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeArchitecture     , "Find processes that have a matching architecture." },
1667 { LLDB_OPT_SET_FROM_TO(1, 6), false, "show-args"  , 'A', OptionParser::eNoArgument      , NULL, NULL, 0, eArgTypeNone             , "Show process arguments instead of the process executable basename." },
1668 { LLDB_OPT_SET_FROM_TO(1, 6), false, "verbose"    , 'v', OptionParser::eNoArgument      , NULL, NULL, 0, eArgTypeNone             , "Enable verbose output." },
1669 { 0                         , false, NULL         ,  0 , 0                              , NULL, NULL, 0, eArgTypeNone             , NULL }
1670 };
1671 
1672 //----------------------------------------------------------------------
1673 // "platform process info"
1674 //----------------------------------------------------------------------
1675 class CommandObjectPlatformProcessInfo : public CommandObjectParsed
1676 {
1677 public:
1678     CommandObjectPlatformProcessInfo (CommandInterpreter &interpreter) :
1679     CommandObjectParsed (interpreter,
1680                          "platform process info",
1681                          "Get detailed information for one or more process by process ID.",
1682                          "platform process info <pid> [<pid> <pid> ...]",
1683                          0)
1684     {
1685         CommandArgumentEntry arg;
1686         CommandArgumentData pid_args;
1687 
1688         // Define the first (and only) variant of this arg.
1689         pid_args.arg_type = eArgTypePid;
1690         pid_args.arg_repetition = eArgRepeatStar;
1691 
1692         // There is only one variant this argument could be; put it into the argument entry.
1693         arg.push_back (pid_args);
1694 
1695         // Push the data for the first argument into the m_arguments vector.
1696         m_arguments.push_back (arg);
1697     }
1698 
1699     virtual
1700     ~CommandObjectPlatformProcessInfo ()
1701     {
1702     }
1703 
1704 protected:
1705     virtual bool
1706     DoExecute (Args& args, CommandReturnObject &result)
1707     {
1708         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1709         PlatformSP platform_sp;
1710         if (target)
1711         {
1712             platform_sp = target->GetPlatform();
1713         }
1714         if (!platform_sp)
1715         {
1716             platform_sp = m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform();
1717         }
1718 
1719         if (platform_sp)
1720         {
1721             const size_t argc = args.GetArgumentCount();
1722             if (argc > 0)
1723             {
1724                 Error error;
1725 
1726                 if (platform_sp->IsConnected())
1727                 {
1728                     Stream &ostrm = result.GetOutputStream();
1729                     bool success;
1730                     for (size_t i=0; i<argc; ++ i)
1731                     {
1732                         const char *arg = args.GetArgumentAtIndex(i);
1733                         lldb::pid_t pid = StringConvert::ToUInt32 (arg, LLDB_INVALID_PROCESS_ID, 0, &success);
1734                         if (success)
1735                         {
1736                             ProcessInstanceInfo proc_info;
1737                             if (platform_sp->GetProcessInfo (pid, proc_info))
1738                             {
1739                                 ostrm.Printf ("Process information for process %" PRIu64 ":\n", pid);
1740                                 proc_info.Dump (ostrm, platform_sp.get());
1741                             }
1742                             else
1743                             {
1744                                 ostrm.Printf ("error: no process information is available for process %" PRIu64 "\n", pid);
1745                             }
1746                             ostrm.EOL();
1747                         }
1748                         else
1749                         {
1750                             result.AppendErrorWithFormat ("invalid process ID argument '%s'", arg);
1751                             result.SetStatus (eReturnStatusFailed);
1752                             break;
1753                         }
1754                     }
1755                 }
1756                 else
1757                 {
1758                     // Not connected...
1759                     result.AppendErrorWithFormat ("not connected to '%s'", platform_sp->GetPluginName().GetCString());
1760                     result.SetStatus (eReturnStatusFailed);
1761                 }
1762             }
1763             else
1764             {
1765                 // No args
1766                 result.AppendError ("one or more process id(s) must be specified");
1767                 result.SetStatus (eReturnStatusFailed);
1768             }
1769         }
1770         else
1771         {
1772             result.AppendError ("no platform is currently selected");
1773             result.SetStatus (eReturnStatusFailed);
1774         }
1775         return result.Succeeded();
1776     }
1777 };
1778 
1779 class CommandObjectPlatformProcessAttach : public CommandObjectParsed
1780 {
1781 public:
1782 
1783     class CommandOptions : public Options
1784     {
1785     public:
1786 
1787         CommandOptions (CommandInterpreter &interpreter) :
1788         Options(interpreter)
1789         {
1790             // Keep default values of all options in one place: OptionParsingStarting ()
1791             OptionParsingStarting ();
1792         }
1793 
1794         ~CommandOptions ()
1795         {
1796         }
1797 
1798         Error
1799         SetOptionValue (uint32_t option_idx, const char *option_arg)
1800         {
1801             Error error;
1802             char short_option = (char) m_getopt_table[option_idx].val;
1803             bool success = false;
1804             switch (short_option)
1805             {
1806                 case 'p':
1807                 {
1808                     lldb::pid_t pid = StringConvert::ToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success);
1809                     if (!success || pid == LLDB_INVALID_PROCESS_ID)
1810                     {
1811                         error.SetErrorStringWithFormat("invalid process ID '%s'", option_arg);
1812                     }
1813                     else
1814                     {
1815                         attach_info.SetProcessID (pid);
1816                     }
1817                 }
1818                     break;
1819 
1820                 case 'P':
1821                     attach_info.SetProcessPluginName (option_arg);
1822                     break;
1823 
1824                 case 'n':
1825                     attach_info.GetExecutableFile().SetFile(option_arg, false);
1826                     break;
1827 
1828                 case 'w':
1829                     attach_info.SetWaitForLaunch(true);
1830                     break;
1831 
1832                 default:
1833                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
1834                     break;
1835             }
1836             return error;
1837         }
1838 
1839         void
1840         OptionParsingStarting ()
1841         {
1842             attach_info.Clear();
1843         }
1844 
1845         const OptionDefinition*
1846         GetDefinitions ()
1847         {
1848             return g_option_table;
1849         }
1850 
1851         virtual bool
1852         HandleOptionArgumentCompletion (Args &input,
1853                                         int cursor_index,
1854                                         int char_pos,
1855                                         OptionElementVector &opt_element_vector,
1856                                         int opt_element_index,
1857                                         int match_start_point,
1858                                         int max_return_elements,
1859                                         bool &word_complete,
1860                                         StringList &matches)
1861         {
1862             int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
1863             int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
1864 
1865             // We are only completing the name option for now...
1866 
1867             const OptionDefinition *opt_defs = GetDefinitions();
1868             if (opt_defs[opt_defs_index].short_option == 'n')
1869             {
1870                 // Are we in the name?
1871 
1872                 // Look to see if there is a -P argument provided, and if so use that plugin, otherwise
1873                 // use the default plugin.
1874 
1875                 const char *partial_name = NULL;
1876                 partial_name = input.GetArgumentAtIndex(opt_arg_pos);
1877 
1878                 PlatformSP platform_sp (m_interpreter.GetPlatform (true));
1879                 if (platform_sp)
1880                 {
1881                     ProcessInstanceInfoList process_infos;
1882                     ProcessInstanceInfoMatch match_info;
1883                     if (partial_name)
1884                     {
1885                         match_info.GetProcessInfo().GetExecutableFile().SetFile(partial_name, false);
1886                         match_info.SetNameMatchType(eNameMatchStartsWith);
1887                     }
1888                     platform_sp->FindProcesses (match_info, process_infos);
1889                     const uint32_t num_matches = process_infos.GetSize();
1890                     if (num_matches > 0)
1891                     {
1892                         for (uint32_t i=0; i<num_matches; ++i)
1893                         {
1894                             matches.AppendString (process_infos.GetProcessNameAtIndex(i),
1895                                                   process_infos.GetProcessNameLengthAtIndex(i));
1896                         }
1897                     }
1898                 }
1899             }
1900 
1901             return false;
1902         }
1903 
1904         // Options table: Required for subclasses of Options.
1905 
1906         static OptionDefinition g_option_table[];
1907 
1908         // Instance variables to hold the values for command options.
1909 
1910         ProcessAttachInfo attach_info;
1911     };
1912 
1913     CommandObjectPlatformProcessAttach (CommandInterpreter &interpreter) :
1914     CommandObjectParsed (interpreter,
1915                          "platform process attach",
1916                          "Attach to a process.",
1917                          "platform process attach <cmd-options>"),
1918     m_options (interpreter)
1919     {
1920     }
1921 
1922     ~CommandObjectPlatformProcessAttach ()
1923     {
1924     }
1925 
1926     bool
1927     DoExecute (Args& command,
1928              CommandReturnObject &result)
1929     {
1930         PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
1931         if (platform_sp)
1932         {
1933             Error err;
1934             ProcessSP remote_process_sp =
1935             platform_sp->Attach(m_options.attach_info, m_interpreter.GetDebugger(), NULL, err);
1936             if (err.Fail())
1937             {
1938                 result.AppendError(err.AsCString());
1939                 result.SetStatus (eReturnStatusFailed);
1940             }
1941             else if (remote_process_sp.get() == NULL)
1942             {
1943                 result.AppendError("could not attach: unknown reason");
1944                 result.SetStatus (eReturnStatusFailed);
1945             }
1946             else
1947                 result.SetStatus (eReturnStatusSuccessFinishResult);
1948         }
1949         else
1950         {
1951             result.AppendError ("no platform is currently selected");
1952             result.SetStatus (eReturnStatusFailed);
1953         }
1954         return result.Succeeded();
1955     }
1956 
1957     Options *
1958     GetOptions ()
1959     {
1960         return &m_options;
1961     }
1962 
1963 protected:
1964 
1965     CommandOptions m_options;
1966 };
1967 
1968 
1969 OptionDefinition
1970 CommandObjectPlatformProcessAttach::CommandOptions::g_option_table[] =
1971 {
1972     { LLDB_OPT_SET_ALL, false, "plugin",  'P'  , OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePlugin,        "Name of the process plugin you want to use."},
1973     { LLDB_OPT_SET_1,   false, "pid",     'p'  , OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypePid,           "The process ID of an existing process to attach to."},
1974     { LLDB_OPT_SET_2,   false, "name",    'n'  , OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeProcessName,  "The name of the process to attach to."},
1975     { LLDB_OPT_SET_2,   false, "waitfor", 'w'  , OptionParser::eNoArgument      , NULL, NULL, 0, eArgTypeNone,              "Wait for the the process with <process-name> to launch."},
1976     { 0,                false, NULL     , 0    , 0                              , NULL, NULL, 0, eArgTypeNone, NULL }
1977 };
1978 
1979 
1980 class CommandObjectPlatformProcess : public CommandObjectMultiword
1981 {
1982 public:
1983     //------------------------------------------------------------------
1984     // Constructors and Destructors
1985     //------------------------------------------------------------------
1986      CommandObjectPlatformProcess (CommandInterpreter &interpreter) :
1987         CommandObjectMultiword (interpreter,
1988                                 "platform process",
1989                                 "A set of commands to query, launch and attach to platform processes",
1990                                 "platform process [attach|launch|list] ...")
1991     {
1992         LoadSubCommand ("attach", CommandObjectSP (new CommandObjectPlatformProcessAttach (interpreter)));
1993         LoadSubCommand ("launch", CommandObjectSP (new CommandObjectPlatformProcessLaunch (interpreter)));
1994         LoadSubCommand ("info"  , CommandObjectSP (new CommandObjectPlatformProcessInfo (interpreter)));
1995         LoadSubCommand ("list"  , CommandObjectSP (new CommandObjectPlatformProcessList (interpreter)));
1996 
1997     }
1998 
1999     virtual
2000     ~CommandObjectPlatformProcess ()
2001     {
2002     }
2003 
2004 private:
2005     //------------------------------------------------------------------
2006     // For CommandObjectPlatform only
2007     //------------------------------------------------------------------
2008     DISALLOW_COPY_AND_ASSIGN (CommandObjectPlatformProcess);
2009 };
2010 
2011 //----------------------------------------------------------------------
2012 // "platform shell"
2013 //----------------------------------------------------------------------
2014 class CommandObjectPlatformShell : public CommandObjectRaw
2015 {
2016 public:
2017 
2018     class CommandOptions : public Options
2019     {
2020     public:
2021 
2022         CommandOptions (CommandInterpreter &interpreter) :
2023         Options(interpreter),
2024         timeout(10)
2025         {
2026         }
2027 
2028         virtual
2029         ~CommandOptions ()
2030         {
2031         }
2032 
2033         virtual uint32_t
2034         GetNumDefinitions ()
2035         {
2036             return 1;
2037         }
2038 
2039         virtual const OptionDefinition*
2040         GetDefinitions ()
2041         {
2042             return g_option_table;
2043         }
2044 
2045         virtual Error
2046         SetOptionValue (uint32_t option_idx,
2047                         const char *option_value)
2048         {
2049             Error error;
2050 
2051             const char short_option = (char) g_option_table[option_idx].short_option;
2052 
2053             switch (short_option)
2054             {
2055                 case 't':
2056                 {
2057                     bool success;
2058                     timeout = StringConvert::ToUInt32(option_value, 10, 10, &success);
2059                     if (!success)
2060                         error.SetErrorStringWithFormat("could not convert \"%s\" to a numeric value.", option_value);
2061                     break;
2062                 }
2063                 default:
2064                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
2065                     break;
2066             }
2067 
2068             return error;
2069         }
2070 
2071         virtual void
2072         OptionParsingStarting ()
2073         {
2074         }
2075 
2076         // Options table: Required for subclasses of Options.
2077 
2078         static OptionDefinition g_option_table[];
2079         uint32_t timeout;
2080     };
2081 
2082     CommandObjectPlatformShell (CommandInterpreter &interpreter) :
2083     CommandObjectRaw (interpreter,
2084                       "platform shell",
2085                       "Run a shell command on a the selected platform.",
2086                       "platform shell <shell-command>",
2087                       0),
2088     m_options(interpreter)
2089     {
2090     }
2091 
2092     virtual
2093     ~CommandObjectPlatformShell ()
2094     {
2095     }
2096 
2097     virtual
2098     Options *
2099     GetOptions ()
2100     {
2101         return &m_options;
2102     }
2103 
2104     virtual bool
2105     DoExecute (const char *raw_command_line, CommandReturnObject &result)
2106     {
2107         m_options.NotifyOptionParsingStarting();
2108 
2109         const char* expr = NULL;
2110 
2111         // Print out an usage syntax on an empty command line.
2112         if (raw_command_line[0] == '\0')
2113         {
2114             result.GetOutputStream().Printf("%s\n", this->GetSyntax());
2115             return true;
2116         }
2117 
2118         if (raw_command_line[0] == '-')
2119         {
2120             // We have some options and these options MUST end with --.
2121             const char *end_options = NULL;
2122             const char *s = raw_command_line;
2123             while (s && s[0])
2124             {
2125                 end_options = ::strstr (s, "--");
2126                 if (end_options)
2127                 {
2128                     end_options += 2; // Get past the "--"
2129                     if (::isspace (end_options[0]))
2130                     {
2131                         expr = end_options;
2132                         while (::isspace (*expr))
2133                             ++expr;
2134                         break;
2135                     }
2136                 }
2137                 s = end_options;
2138             }
2139 
2140             if (end_options)
2141             {
2142                 Args args (llvm::StringRef(raw_command_line, end_options - raw_command_line));
2143                 if (!ParseOptions (args, result))
2144                     return false;
2145             }
2146         }
2147 
2148         if (expr == NULL)
2149             expr = raw_command_line;
2150 
2151         PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
2152         Error error;
2153         if (platform_sp)
2154         {
2155             const char *working_dir = NULL;
2156             std::string output;
2157             int status = -1;
2158             int signo = -1;
2159             error = (platform_sp->RunShellCommand (expr, working_dir, &status, &signo, &output, m_options.timeout));
2160             if (!output.empty())
2161                 result.GetOutputStream().PutCString(output.c_str());
2162             if (status > 0)
2163             {
2164                 if (signo > 0)
2165                 {
2166                     const char *signo_cstr = Host::GetSignalAsCString(signo);
2167                     if (signo_cstr)
2168                         result.GetOutputStream().Printf("error: command returned with status %i and signal %s\n", status, signo_cstr);
2169                     else
2170                         result.GetOutputStream().Printf("error: command returned with status %i and signal %i\n", status, signo);
2171                 }
2172                 else
2173                     result.GetOutputStream().Printf("error: command returned with status %i\n", status);
2174             }
2175         }
2176         else
2177         {
2178             result.GetOutputStream().Printf("error: cannot run remote shell commands without a platform\n");
2179             error.SetErrorString("error: cannot run remote shell commands without a platform");
2180         }
2181 
2182         if (error.Fail())
2183         {
2184             result.AppendError(error.AsCString());
2185             result.SetStatus (eReturnStatusFailed);
2186         }
2187         else
2188         {
2189             result.SetStatus (eReturnStatusSuccessFinishResult);
2190         }
2191         return true;
2192     }
2193     CommandOptions m_options;
2194 };
2195 
2196 OptionDefinition
2197 CommandObjectPlatformShell::CommandOptions::g_option_table[] =
2198 {
2199     { LLDB_OPT_SET_ALL, false, "timeout",      't', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeValue,    "Seconds to wait for the remote host to finish running the command."},
2200     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
2201 };
2202 
2203 
2204 //----------------------------------------------------------------------
2205 // "platform install" - install a target to a remote end
2206 //----------------------------------------------------------------------
2207 class CommandObjectPlatformInstall : public CommandObjectParsed
2208 {
2209 public:
2210     CommandObjectPlatformInstall (CommandInterpreter &interpreter) :
2211     CommandObjectParsed (interpreter,
2212                          "platform target-install",
2213                          "Install a target (bundle or executable file) to the remote end.",
2214                          "platform target-install <local-thing> <remote-sandbox>",
2215                          0)
2216     {
2217     }
2218 
2219     virtual
2220     ~CommandObjectPlatformInstall ()
2221     {
2222     }
2223 
2224     virtual bool
2225     DoExecute (Args& args, CommandReturnObject &result)
2226     {
2227         if (args.GetArgumentCount() != 2)
2228         {
2229             result.AppendError("platform target-install takes two arguments");
2230             result.SetStatus(eReturnStatusFailed);
2231             return false;
2232         }
2233         // TODO: move the bulk of this code over to the platform itself
2234         FileSpec src(args.GetArgumentAtIndex(0), true);
2235         FileSpec dst(args.GetArgumentAtIndex(1), false);
2236         if (src.Exists() == false)
2237         {
2238             result.AppendError("source location does not exist or is not accessible");
2239             result.SetStatus(eReturnStatusFailed);
2240             return false;
2241         }
2242         PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
2243         if (!platform_sp)
2244         {
2245             result.AppendError ("no platform currently selected");
2246             result.SetStatus (eReturnStatusFailed);
2247             return false;
2248         }
2249 
2250         Error error = platform_sp->Install(src, dst);
2251         if (error.Success())
2252         {
2253             result.SetStatus(eReturnStatusSuccessFinishNoResult);
2254         }
2255         else
2256         {
2257             result.AppendErrorWithFormat("install failed: %s", error.AsCString());
2258             result.SetStatus(eReturnStatusFailed);
2259         }
2260         return result.Succeeded();
2261     }
2262 private:
2263 
2264 };
2265 
2266 //----------------------------------------------------------------------
2267 // CommandObjectPlatform constructor
2268 //----------------------------------------------------------------------
2269 CommandObjectPlatform::CommandObjectPlatform(CommandInterpreter &interpreter) :
2270     CommandObjectMultiword (interpreter,
2271                             "platform",
2272                             "A set of commands to manage and create platforms.",
2273                             "platform [connect|disconnect|info|list|status|select] ...")
2274 {
2275     LoadSubCommand ("select", CommandObjectSP (new CommandObjectPlatformSelect (interpreter)));
2276     LoadSubCommand ("list"  , CommandObjectSP (new CommandObjectPlatformList (interpreter)));
2277     LoadSubCommand ("status", CommandObjectSP (new CommandObjectPlatformStatus (interpreter)));
2278     LoadSubCommand ("connect", CommandObjectSP (new CommandObjectPlatformConnect (interpreter)));
2279     LoadSubCommand ("disconnect", CommandObjectSP (new CommandObjectPlatformDisconnect (interpreter)));
2280     LoadSubCommand ("settings", CommandObjectSP (new CommandObjectPlatformSettings (interpreter)));
2281     LoadSubCommand ("mkdir", CommandObjectSP (new CommandObjectPlatformMkDir (interpreter)));
2282     LoadSubCommand ("file", CommandObjectSP (new CommandObjectPlatformFile (interpreter)));
2283     LoadSubCommand ("get-file", CommandObjectSP (new CommandObjectPlatformGetFile (interpreter)));
2284     LoadSubCommand ("get-size", CommandObjectSP (new CommandObjectPlatformGetSize (interpreter)));
2285     LoadSubCommand ("put-file", CommandObjectSP (new CommandObjectPlatformPutFile (interpreter)));
2286     LoadSubCommand ("process", CommandObjectSP (new CommandObjectPlatformProcess (interpreter)));
2287     LoadSubCommand ("shell", CommandObjectSP (new CommandObjectPlatformShell (interpreter)));
2288     LoadSubCommand ("target-install", CommandObjectSP (new CommandObjectPlatformInstall (interpreter)));
2289 }
2290 
2291 //----------------------------------------------------------------------
2292 // Destructor
2293 //----------------------------------------------------------------------
2294 CommandObjectPlatform::~CommandObjectPlatform()
2295 {
2296 }
2297