1//===-- CommandObjectPlatform.cpp -------------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/lldb-python.h"
11
12#include "CommandObjectPlatform.h"
13
14// C Includes
15// C++ Includes
16// Other libraries and framework includes
17// Project includes
18#include "lldb/Core/DataExtractor.h"
19#include "lldb/Core/Debugger.h"
20#include "lldb/Core/Module.h"
21#include "lldb/Core/PluginManager.h"
22#include "lldb/Interpreter/Args.h"
23#include "lldb/Interpreter/CommandInterpreter.h"
24#include "lldb/Interpreter/CommandReturnObject.h"
25#include "lldb/Interpreter/OptionGroupFile.h"
26#include "lldb/Interpreter/OptionGroupPlatform.h"
27#include "lldb/Target/ExecutionContext.h"
28#include "lldb/Target/Platform.h"
29#include "lldb/Target/Process.h"
30#include "lldb/Utility/Utils.h"
31
32using namespace lldb;
33using namespace lldb_private;
34
35static mode_t
36ParsePermissionString(const char* permissions)
37{
38    if (strlen(permissions) != 9)
39        return (mode_t)(-1);
40    bool user_r,user_w,user_x,
41    group_r,group_w,group_x,
42    world_r,world_w,world_x;
43
44    user_r = (permissions[0] == 'r');
45    user_w = (permissions[1] == 'w');
46    user_x = (permissions[2] == 'x');
47
48    group_r = (permissions[3] == 'r');
49    group_w = (permissions[4] == 'w');
50    group_x = (permissions[5] == 'x');
51
52    world_r = (permissions[6] == 'r');
53    world_w = (permissions[7] == 'w');
54    world_x = (permissions[8] == 'x');
55
56    mode_t user,group,world;
57    user = (user_r ? 4 : 0) | (user_w ? 2 : 0) | (user_x ? 1 : 0);
58    group = (group_r ? 4 : 0) | (group_w ? 2 : 0) | (group_x ? 1 : 0);
59    world = (world_r ? 4 : 0) | (world_w ? 2 : 0) | (world_x ? 1 : 0);
60
61    return user | group | world;
62}
63
64static OptionDefinition
65g_permissions_options[] =
66{
67    {   LLDB_OPT_SET_ALL, false, "permissions-value", 'v', OptionParser::eRequiredArgument,       NULL, 0, eArgTypePermissionsNumber         , "Give out the numeric value for permissions (e.g. 757)" },
68    {   LLDB_OPT_SET_ALL, false, "permissions-string",'s', OptionParser::eRequiredArgument, NULL, 0, eArgTypePermissionsString  , "Give out the string value for permissions (e.g. rwxr-xr--)." },
69    {   LLDB_OPT_SET_ALL, false, "user-read", 'r', OptionParser::eNoArgument,       NULL, 0, eArgTypeNone         , "Allow user to read." },
70    {   LLDB_OPT_SET_ALL, false, "user-write", 'w', OptionParser::eNoArgument,       NULL, 0, eArgTypeNone         , "Allow user to write." },
71    {   LLDB_OPT_SET_ALL, false, "user-exec", 'x', OptionParser::eNoArgument,       NULL, 0, eArgTypeNone         , "Allow user to execute." },
72
73    {   LLDB_OPT_SET_ALL, false, "group-read", 'R', OptionParser::eNoArgument,       NULL, 0, eArgTypeNone         , "Allow group to read." },
74    {   LLDB_OPT_SET_ALL, false, "group-write", 'W', OptionParser::eNoArgument,       NULL, 0, eArgTypeNone         , "Allow group to write." },
75    {   LLDB_OPT_SET_ALL, false, "group-exec", 'X', OptionParser::eNoArgument,       NULL, 0, eArgTypeNone         , "Allow group to execute." },
76
77    {   LLDB_OPT_SET_ALL, false, "world-read", 'd', OptionParser::eNoArgument,       NULL, 0, eArgTypeNone         , "Allow world to read." },
78    {   LLDB_OPT_SET_ALL, false, "world-write", 't', OptionParser::eNoArgument,       NULL, 0, eArgTypeNone         , "Allow world to write." },
79    {   LLDB_OPT_SET_ALL, false, "world-exec", 'e', OptionParser::eNoArgument,       NULL, 0, eArgTypeNone         , "Allow world to execute." },
80
81};
82
83class OptionPermissions : public lldb_private::OptionGroup
84{
85public:
86    OptionPermissions ()
87    {
88    }
89
90    virtual
91    ~OptionPermissions ()
92    {
93    }
94
95    virtual lldb_private::Error
96    SetOptionValue (CommandInterpreter &interpreter,
97                    uint32_t option_idx,
98                    const char *option_arg)
99    {
100        Error error;
101        char short_option = (char) GetDefinitions()[option_idx].short_option;
102        switch (short_option)
103        {
104            case 'v':
105            {
106                bool ok;
107                uint32_t perms = Args::StringToUInt32(option_arg, 777, 8, &ok);
108                if (!ok)
109                    error.SetErrorStringWithFormat("invalid value for permissions: %s", option_arg);
110                else
111                    m_permissions = perms;
112            }
113                break;
114            case 's':
115            {
116                mode_t perms = ParsePermissionString(option_arg);
117                if (perms == (mode_t)-1)
118                    error.SetErrorStringWithFormat("invalid value for permissions: %s", option_arg);
119                else
120                    m_permissions = perms;
121            }
122            case 'r':
123                m_permissions |= lldb::eFilePermissionsUserRead;
124                break;
125            case 'w':
126                m_permissions |= lldb::eFilePermissionsUserWrite;
127                break;
128            case 'x':
129                m_permissions |= lldb::eFilePermissionsUserExecute;
130                break;
131            case 'R':
132                m_permissions |= lldb::eFilePermissionsGroupRead;
133                break;
134            case 'W':
135                m_permissions |= lldb::eFilePermissionsGroupWrite;
136                break;
137            case 'X':
138                m_permissions |= lldb::eFilePermissionsGroupExecute;
139                break;
140            case 'd':
141                m_permissions |= lldb::eFilePermissionsWorldRead;
142                break;
143            case 't':
144                m_permissions |= lldb::eFilePermissionsWorldWrite;
145                break;
146            case 'e':
147                m_permissions |= lldb::eFilePermissionsWorldExecute;
148                break;
149
150            default:
151                error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
152                break;
153        }
154
155        return error;
156    }
157
158    void
159    OptionParsingStarting (CommandInterpreter &interpreter)
160    {
161        m_permissions = 0;
162    }
163
164    virtual uint32_t
165    GetNumDefinitions ()
166    {
167        return llvm::array_lengthof(g_permissions_options);
168    }
169
170    const lldb_private::OptionDefinition*
171    GetDefinitions ()
172    {
173        return g_permissions_options;
174    }
175
176    // Instance variables to hold the values for command options.
177
178    uint32_t m_permissions;
179private:
180    DISALLOW_COPY_AND_ASSIGN(OptionPermissions);
181};
182
183//----------------------------------------------------------------------
184// "platform select <platform-name>"
185//----------------------------------------------------------------------
186class CommandObjectPlatformSelect : public CommandObjectParsed
187{
188public:
189    CommandObjectPlatformSelect (CommandInterpreter &interpreter) :
190        CommandObjectParsed (interpreter,
191                             "platform select",
192                             "Create a platform if needed and select it as the current platform.",
193                             "platform select <platform-name>",
194                             0),
195        m_option_group (interpreter),
196        m_platform_options (false) // Don't include the "--platform" option by passing false
197    {
198        m_option_group.Append (&m_platform_options, LLDB_OPT_SET_ALL, 1);
199        m_option_group.Finalize();
200    }
201
202    virtual
203    ~CommandObjectPlatformSelect ()
204    {
205    }
206
207    virtual int
208    HandleCompletion (Args &input,
209                      int &cursor_index,
210                      int &cursor_char_position,
211                      int match_start_point,
212                      int max_return_elements,
213                      bool &word_complete,
214                      StringList &matches)
215    {
216        std::string completion_str (input.GetArgumentAtIndex(cursor_index));
217        completion_str.erase (cursor_char_position);
218
219        CommandCompletions::PlatformPluginNames (m_interpreter,
220                                                 completion_str.c_str(),
221                                                 match_start_point,
222                                                 max_return_elements,
223                                                 NULL,
224                                                 word_complete,
225                                                 matches);
226        return matches.GetSize();
227    }
228
229    virtual Options *
230    GetOptions ()
231    {
232        return &m_option_group;
233    }
234
235protected:
236    virtual bool
237    DoExecute (Args& args, CommandReturnObject &result)
238    {
239        if (args.GetArgumentCount() == 1)
240        {
241            const char *platform_name = args.GetArgumentAtIndex (0);
242            if (platform_name && platform_name[0])
243            {
244                const bool select = true;
245                m_platform_options.SetPlatformName (platform_name);
246                Error error;
247                ArchSpec platform_arch;
248                PlatformSP platform_sp (m_platform_options.CreatePlatformWithOptions (m_interpreter, ArchSpec(), select, error, platform_arch));
249                if (platform_sp)
250                {
251                    platform_sp->GetStatus (result.GetOutputStream());
252                    result.SetStatus (eReturnStatusSuccessFinishResult);
253                }
254                else
255                {
256                    result.AppendError(error.AsCString());
257                    result.SetStatus (eReturnStatusFailed);
258                }
259            }
260            else
261            {
262                result.AppendError ("invalid platform name");
263                result.SetStatus (eReturnStatusFailed);
264            }
265        }
266        else
267        {
268            result.AppendError ("platform create takes a platform name as an argument\n");
269            result.SetStatus (eReturnStatusFailed);
270        }
271        return result.Succeeded();
272    }
273
274    OptionGroupOptions m_option_group;
275    OptionGroupPlatform m_platform_options;
276};
277
278//----------------------------------------------------------------------
279// "platform list"
280//----------------------------------------------------------------------
281class CommandObjectPlatformList : public CommandObjectParsed
282{
283public:
284    CommandObjectPlatformList (CommandInterpreter &interpreter) :
285        CommandObjectParsed (interpreter,
286                             "platform list",
287                             "List all platforms that are available.",
288                             NULL,
289                             0)
290    {
291    }
292
293    virtual
294    ~CommandObjectPlatformList ()
295    {
296    }
297
298protected:
299    virtual bool
300    DoExecute (Args& args, CommandReturnObject &result)
301    {
302        Stream &ostrm = result.GetOutputStream();
303        ostrm.Printf("Available platforms:\n");
304
305        PlatformSP host_platform_sp (Platform::GetDefaultPlatform());
306        ostrm.Printf ("%s: %s\n",
307                      host_platform_sp->GetPluginName().GetCString(),
308                      host_platform_sp->GetDescription());
309
310        uint32_t idx;
311        for (idx = 0; 1; ++idx)
312        {
313            const char *plugin_name = PluginManager::GetPlatformPluginNameAtIndex (idx);
314            if (plugin_name == NULL)
315                break;
316            const char *plugin_desc = PluginManager::GetPlatformPluginDescriptionAtIndex (idx);
317            if (plugin_desc == NULL)
318                break;
319            ostrm.Printf("%s: %s\n", plugin_name, plugin_desc);
320        }
321
322        if (idx == 0)
323        {
324            result.AppendError ("no platforms are available\n");
325            result.SetStatus (eReturnStatusFailed);
326        }
327        else
328            result.SetStatus (eReturnStatusSuccessFinishResult);
329        return result.Succeeded();
330    }
331};
332
333//----------------------------------------------------------------------
334// "platform status"
335//----------------------------------------------------------------------
336class CommandObjectPlatformStatus : public CommandObjectParsed
337{
338public:
339    CommandObjectPlatformStatus (CommandInterpreter &interpreter) :
340        CommandObjectParsed (interpreter,
341                             "platform status",
342                             "Display status for the currently selected platform.",
343                             NULL,
344                             0)
345    {
346    }
347
348    virtual
349    ~CommandObjectPlatformStatus ()
350    {
351    }
352
353protected:
354    virtual bool
355    DoExecute (Args& args, CommandReturnObject &result)
356    {
357        Stream &ostrm = result.GetOutputStream();
358
359        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
360        PlatformSP platform_sp;
361        if (target)
362        {
363            platform_sp = target->GetPlatform();
364        }
365        if (!platform_sp)
366        {
367            platform_sp = m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform();
368        }
369        if (platform_sp)
370        {
371            platform_sp->GetStatus (ostrm);
372            result.SetStatus (eReturnStatusSuccessFinishResult);
373        }
374        else
375        {
376            result.AppendError ("no platform us currently selected\n");
377            result.SetStatus (eReturnStatusFailed);
378        }
379        return result.Succeeded();
380    }
381};
382
383//----------------------------------------------------------------------
384// "platform connect <connect-url>"
385//----------------------------------------------------------------------
386class CommandObjectPlatformConnect : public CommandObjectParsed
387{
388public:
389    CommandObjectPlatformConnect (CommandInterpreter &interpreter) :
390        CommandObjectParsed (interpreter,
391                             "platform connect",
392                             "Connect a platform by name to be the currently selected platform.",
393                             "platform connect <connect-url>",
394                             0)
395    {
396    }
397
398    virtual
399    ~CommandObjectPlatformConnect ()
400    {
401    }
402
403protected:
404    virtual bool
405    DoExecute (Args& args, CommandReturnObject &result)
406    {
407        Stream &ostrm = result.GetOutputStream();
408
409        PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
410        if (platform_sp)
411        {
412            Error error (platform_sp->ConnectRemote (args));
413            if (error.Success())
414            {
415                platform_sp->GetStatus (ostrm);
416                result.SetStatus (eReturnStatusSuccessFinishResult);
417            }
418            else
419            {
420                result.AppendErrorWithFormat ("%s\n", error.AsCString());
421                result.SetStatus (eReturnStatusFailed);
422            }
423        }
424        else
425        {
426            result.AppendError ("no platform is currently selected\n");
427            result.SetStatus (eReturnStatusFailed);
428        }
429        return result.Succeeded();
430    }
431
432    virtual Options *
433    GetOptions ()
434    {
435        PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
436        OptionGroupOptions* m_platform_options = NULL;
437        if (platform_sp)
438        {
439            m_platform_options = platform_sp->GetConnectionOptions(m_interpreter);
440            if (m_platform_options != NULL && !m_platform_options->m_did_finalize)
441                m_platform_options->Finalize();
442        }
443        return m_platform_options;
444    }
445
446};
447
448//----------------------------------------------------------------------
449// "platform disconnect"
450//----------------------------------------------------------------------
451class CommandObjectPlatformDisconnect : public CommandObjectParsed
452{
453public:
454    CommandObjectPlatformDisconnect (CommandInterpreter &interpreter) :
455        CommandObjectParsed (interpreter,
456                             "platform disconnect",
457                             "Disconnect a platform by name to be the currently selected platform.",
458                             "platform disconnect",
459                             0)
460    {
461    }
462
463    virtual
464    ~CommandObjectPlatformDisconnect ()
465    {
466    }
467
468protected:
469    virtual bool
470    DoExecute (Args& args, CommandReturnObject &result)
471    {
472        PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
473        if (platform_sp)
474        {
475            if (args.GetArgumentCount() == 0)
476            {
477                Error error;
478
479                if (platform_sp->IsConnected())
480                {
481                    // Cache the instance name if there is one since we are
482                    // about to disconnect and the name might go with it.
483                    const char *hostname_cstr = platform_sp->GetHostname();
484                    std::string hostname;
485                    if (hostname_cstr)
486                        hostname.assign (hostname_cstr);
487
488                    error = platform_sp->DisconnectRemote ();
489                    if (error.Success())
490                    {
491                        Stream &ostrm = result.GetOutputStream();
492                        if (hostname.empty())
493                            ostrm.Printf ("Disconnected from \"%s\"\n", platform_sp->GetPluginName().GetCString());
494                        else
495                            ostrm.Printf ("Disconnected from \"%s\"\n", hostname.c_str());
496                        result.SetStatus (eReturnStatusSuccessFinishResult);
497                    }
498                    else
499                    {
500                        result.AppendErrorWithFormat ("%s", error.AsCString());
501                        result.SetStatus (eReturnStatusFailed);
502                    }
503                }
504                else
505                {
506                    // Not connected...
507                    result.AppendErrorWithFormat ("not connected to '%s'", platform_sp->GetPluginName().GetCString());
508                    result.SetStatus (eReturnStatusFailed);
509                }
510            }
511            else
512            {
513                // Bad args
514                result.AppendError ("\"platform disconnect\" doesn't take any arguments");
515                result.SetStatus (eReturnStatusFailed);
516            }
517        }
518        else
519        {
520            result.AppendError ("no platform is currently selected");
521            result.SetStatus (eReturnStatusFailed);
522        }
523        return result.Succeeded();
524    }
525};
526
527//----------------------------------------------------------------------
528// "platform settings"
529//----------------------------------------------------------------------
530class CommandObjectPlatformSettings : public CommandObjectParsed
531{
532public:
533    CommandObjectPlatformSettings (CommandInterpreter &interpreter) :
534        CommandObjectParsed (interpreter,
535                             "platform settings",
536                             "Set settings for the current target's platform, or for a platform by name.",
537                             "platform settings",
538                             0),
539        m_options (interpreter),
540        m_option_working_dir (LLDB_OPT_SET_1, false, "working-dir", 'w', 0, eArgTypePath, "The working directory for the platform.")
541    {
542        m_options.Append (&m_option_working_dir, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
543    }
544
545    virtual
546    ~CommandObjectPlatformSettings ()
547    {
548    }
549
550protected:
551    virtual bool
552    DoExecute (Args& args, CommandReturnObject &result)
553    {
554        PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
555        if (platform_sp)
556        {
557            if (m_option_working_dir.GetOptionValue().OptionWasSet())
558                platform_sp->SetWorkingDirectory (ConstString(m_option_working_dir.GetOptionValue().GetCurrentValue().GetPath().c_str()));
559        }
560        else
561        {
562            result.AppendError ("no platform is currently selected");
563            result.SetStatus (eReturnStatusFailed);
564        }
565        return result.Succeeded();
566    }
567
568    virtual Options *
569    GetOptions ()
570    {
571        if (m_options.DidFinalize() == false)
572        {
573            m_options.Append(new OptionPermissions());
574            m_options.Finalize();
575        }
576        return &m_options;
577    }
578protected:
579
580    OptionGroupOptions m_options;
581    OptionGroupFile m_option_working_dir;
582
583};
584
585
586//----------------------------------------------------------------------
587// "platform mkdir"
588//----------------------------------------------------------------------
589class CommandObjectPlatformMkDir : public CommandObjectParsed
590{
591public:
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 = (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//----------------------------------------------------------------------
657class CommandObjectPlatformFOpen : public CommandObjectParsed
658{
659public:
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 = (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//----------------------------------------------------------------------
729class CommandObjectPlatformFClose : public CommandObjectParsed
730{
731public:
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 = Args::StringToUInt64(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//----------------------------------------------------------------------
780class CommandObjectPlatformFRead : public CommandObjectParsed
781{
782public:
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 = Args::StringToUInt64(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
827protected:
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 = Args::StringToUInt32(option_arg, 0, 0, &success);
853                    if (!success)
854                        error.SetErrorStringWithFormat("invalid offset: '%s'", option_arg);
855                    break;
856                case 'c':
857                    m_count = Args::StringToUInt32(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};
894OptionDefinition
895CommandObjectPlatformFRead::CommandOptions::g_option_table[] =
896{
897    {   LLDB_OPT_SET_1, false, "offset"           , 'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypeIndex        , "Offset into the file at which to start reading." },
898    {   LLDB_OPT_SET_1, false, "count"            , 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCount        , "Number of bytes to read from the file." },
899    {  0              , false, NULL               ,  0 , 0                , NULL, 0, eArgTypeNone         , NULL }
900};
901
902
903//----------------------------------------------------------------------
904// "platform fwrite"
905//----------------------------------------------------------------------
906class CommandObjectPlatformFWrite : public CommandObjectParsed
907{
908public:
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 = Args::StringToUInt64(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
955protected:
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 = Args::StringToUInt32(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};
1020OptionDefinition
1021CommandObjectPlatformFWrite::CommandOptions::g_option_table[] =
1022{
1023    {   LLDB_OPT_SET_1, false, "offset"           , 'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypeIndex        , "Offset into the file at which to start reading." },
1024    {   LLDB_OPT_SET_1, false, "data"            , 'd', OptionParser::eRequiredArgument, NULL, 0, eArgTypeValue        , "Text to write to the file." },
1025    {  0              , false, NULL               ,  0 , 0                , NULL, 0, eArgTypeNone         , NULL }
1026};
1027
1028class CommandObjectPlatformFile : public CommandObjectMultiword
1029{
1030public:
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
1051private:
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//----------------------------------------------------------------------
1061class CommandObjectPlatformGetFile : public CommandObjectParsed
1062{
1063public:
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//----------------------------------------------------------------------
1144class CommandObjectPlatformGetSize : public CommandObjectParsed
1145{
1146public:
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//----------------------------------------------------------------------
1217class CommandObjectPlatformPutFile : public CommandObjectParsed
1218{
1219public:
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, 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//----------------------------------------------------------------------
1269class CommandObjectPlatformProcessLaunch : public CommandObjectParsed
1270{
1271public:
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
1293protected:
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                                                                 debugger.GetListener(),
1351                                                                 error));
1352                if (process_sp && process_sp->IsAlive())
1353                {
1354                    result.SetStatus (eReturnStatusSuccessFinishNoResult);
1355                    return true;
1356                }
1357
1358                if (error.Success())
1359                    result.AppendError ("process launch failed");
1360                else
1361                    result.AppendError (error.AsCString());
1362                result.SetStatus (eReturnStatusFailed);
1363            }
1364            else
1365            {
1366                result.AppendError ("'platform process launch' uses the current target file and arguments, or the executable and its arguments can be specified in this command");
1367                result.SetStatus (eReturnStatusFailed);
1368                return false;
1369            }
1370        }
1371        else
1372        {
1373            result.AppendError ("no platform is selected\n");
1374        }
1375        return result.Succeeded();
1376    }
1377
1378protected:
1379    ProcessLaunchCommandOptions m_options;
1380};
1381
1382
1383
1384//----------------------------------------------------------------------
1385// "platform process list"
1386//----------------------------------------------------------------------
1387class CommandObjectPlatformProcessList : public CommandObjectParsed
1388{
1389public:
1390    CommandObjectPlatformProcessList (CommandInterpreter &interpreter) :
1391        CommandObjectParsed (interpreter,
1392                             "platform process list",
1393                             "List processes on a remote platform by name, pid, or many other matching attributes.",
1394                             "platform process list",
1395                             0),
1396        m_options (interpreter)
1397    {
1398    }
1399
1400    virtual
1401    ~CommandObjectPlatformProcessList ()
1402    {
1403    }
1404
1405    virtual Options *
1406    GetOptions ()
1407    {
1408        return &m_options;
1409    }
1410
1411protected:
1412    virtual bool
1413    DoExecute (Args& args, CommandReturnObject &result)
1414    {
1415        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1416        PlatformSP platform_sp;
1417        if (target)
1418        {
1419            platform_sp = target->GetPlatform();
1420        }
1421        if (!platform_sp)
1422        {
1423            platform_sp = m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform();
1424        }
1425
1426        if (platform_sp)
1427        {
1428            Error error;
1429            if (args.GetArgumentCount() == 0)
1430            {
1431
1432                if (platform_sp)
1433                {
1434                    Stream &ostrm = result.GetOutputStream();
1435
1436                    lldb::pid_t pid = m_options.match_info.GetProcessInfo().GetProcessID();
1437                    if (pid != LLDB_INVALID_PROCESS_ID)
1438                    {
1439                        ProcessInstanceInfo proc_info;
1440                        if (platform_sp->GetProcessInfo (pid, proc_info))
1441                        {
1442                            ProcessInstanceInfo::DumpTableHeader (ostrm, platform_sp.get(), m_options.show_args, m_options.verbose);
1443                            proc_info.DumpAsTableRow(ostrm, platform_sp.get(), m_options.show_args, m_options.verbose);
1444                            result.SetStatus (eReturnStatusSuccessFinishResult);
1445                        }
1446                        else
1447                        {
1448                            result.AppendErrorWithFormat ("no process found with pid = %" PRIu64 "\n", pid);
1449                            result.SetStatus (eReturnStatusFailed);
1450                        }
1451                    }
1452                    else
1453                    {
1454                        ProcessInstanceInfoList proc_infos;
1455                        const uint32_t matches = platform_sp->FindProcesses (m_options.match_info, proc_infos);
1456                        const char *match_desc = NULL;
1457                        const char *match_name = m_options.match_info.GetProcessInfo().GetName();
1458                        if (match_name && match_name[0])
1459                        {
1460                            switch (m_options.match_info.GetNameMatchType())
1461                            {
1462                                case eNameMatchIgnore: break;
1463                                case eNameMatchEquals: match_desc = "matched"; break;
1464                                case eNameMatchContains: match_desc = "contained"; break;
1465                                case eNameMatchStartsWith: match_desc = "started with"; break;
1466                                case eNameMatchEndsWith: match_desc = "ended with"; break;
1467                                case eNameMatchRegularExpression: match_desc = "matched the regular expression"; break;
1468                            }
1469                        }
1470
1471                        if (matches == 0)
1472                        {
1473                            if (match_desc)
1474                                result.AppendErrorWithFormat ("no processes were found that %s \"%s\" on the \"%s\" platform\n",
1475                                                              match_desc,
1476                                                              match_name,
1477                                                              platform_sp->GetPluginName().GetCString());
1478                            else
1479                                result.AppendErrorWithFormat ("no processes were found on the \"%s\" platform\n", platform_sp->GetPluginName().GetCString());
1480                            result.SetStatus (eReturnStatusFailed);
1481                        }
1482                        else
1483                        {
1484                            result.AppendMessageWithFormat ("%u matching process%s found on \"%s\"",
1485                                                            matches,
1486                                                            matches > 1 ? "es were" : " was",
1487                                                            platform_sp->GetName().GetCString());
1488                            if (match_desc)
1489                                result.AppendMessageWithFormat (" whose name %s \"%s\"",
1490                                                                match_desc,
1491                                                                match_name);
1492                            result.AppendMessageWithFormat ("\n");
1493                            ProcessInstanceInfo::DumpTableHeader (ostrm, platform_sp.get(), m_options.show_args, m_options.verbose);
1494                            for (uint32_t i=0; i<matches; ++i)
1495                            {
1496                                proc_infos.GetProcessInfoAtIndex(i).DumpAsTableRow(ostrm, platform_sp.get(), m_options.show_args, m_options.verbose);
1497                            }
1498                        }
1499                    }
1500                }
1501            }
1502            else
1503            {
1504                result.AppendError ("invalid args: process list takes only options\n");
1505                result.SetStatus (eReturnStatusFailed);
1506            }
1507        }
1508        else
1509        {
1510            result.AppendError ("no platform is selected\n");
1511            result.SetStatus (eReturnStatusFailed);
1512        }
1513        return result.Succeeded();
1514    }
1515
1516    class CommandOptions : public Options
1517    {
1518    public:
1519
1520        CommandOptions (CommandInterpreter &interpreter) :
1521            Options (interpreter),
1522            match_info ()
1523        {
1524        }
1525
1526        virtual
1527        ~CommandOptions ()
1528        {
1529        }
1530
1531        virtual Error
1532        SetOptionValue (uint32_t option_idx, const char *option_arg)
1533        {
1534            Error error;
1535            const int short_option = m_getopt_table[option_idx].val;
1536            bool success = false;
1537
1538            switch (short_option)
1539            {
1540                case 'p':
1541                    match_info.GetProcessInfo().SetProcessID (Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success));
1542                    if (!success)
1543                        error.SetErrorStringWithFormat("invalid process ID string: '%s'", option_arg);
1544                    break;
1545
1546                case 'P':
1547                    match_info.GetProcessInfo().SetParentProcessID (Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success));
1548                    if (!success)
1549                        error.SetErrorStringWithFormat("invalid parent process ID string: '%s'", option_arg);
1550                    break;
1551
1552                case 'u':
1553                    match_info.GetProcessInfo().SetUserID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success));
1554                    if (!success)
1555                        error.SetErrorStringWithFormat("invalid user ID string: '%s'", option_arg);
1556                    break;
1557
1558                case 'U':
1559                    match_info.GetProcessInfo().SetEffectiveUserID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success));
1560                    if (!success)
1561                        error.SetErrorStringWithFormat("invalid effective user ID string: '%s'", option_arg);
1562                    break;
1563
1564                case 'g':
1565                    match_info.GetProcessInfo().SetGroupID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success));
1566                    if (!success)
1567                        error.SetErrorStringWithFormat("invalid group ID string: '%s'", option_arg);
1568                    break;
1569
1570                case 'G':
1571                    match_info.GetProcessInfo().SetEffectiveGroupID (Args::StringToUInt32 (option_arg, UINT32_MAX, 0, &success));
1572                    if (!success)
1573                        error.SetErrorStringWithFormat("invalid effective group ID string: '%s'", option_arg);
1574                    break;
1575
1576                case 'a':
1577                    match_info.GetProcessInfo().GetArchitecture().SetTriple (option_arg, m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform().get());
1578                    break;
1579
1580                case 'n':
1581                    match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false);
1582                    match_info.SetNameMatchType (eNameMatchEquals);
1583                    break;
1584
1585                case 'e':
1586                    match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false);
1587                    match_info.SetNameMatchType (eNameMatchEndsWith);
1588                    break;
1589
1590                case 's':
1591                    match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false);
1592                    match_info.SetNameMatchType (eNameMatchStartsWith);
1593                    break;
1594
1595                case 'c':
1596                    match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false);
1597                    match_info.SetNameMatchType (eNameMatchContains);
1598                    break;
1599
1600                case 'r':
1601                    match_info.GetProcessInfo().GetExecutableFile().SetFile (option_arg, false);
1602                    match_info.SetNameMatchType (eNameMatchRegularExpression);
1603                    break;
1604
1605                case 'A':
1606                    show_args = true;
1607                    break;
1608
1609                case 'v':
1610                    verbose = true;
1611                    break;
1612
1613                default:
1614                    error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option);
1615                    break;
1616            }
1617
1618            return error;
1619        }
1620
1621        void
1622        OptionParsingStarting ()
1623        {
1624            match_info.Clear();
1625            show_args = false;
1626            verbose = false;
1627        }
1628
1629        const OptionDefinition*
1630        GetDefinitions ()
1631        {
1632            return g_option_table;
1633        }
1634
1635        // Options table: Required for subclasses of Options.
1636
1637        static OptionDefinition g_option_table[];
1638
1639        // Instance variables to hold the values for command options.
1640
1641        ProcessInstanceInfoMatch match_info;
1642        bool show_args;
1643        bool verbose;
1644    };
1645    CommandOptions m_options;
1646};
1647
1648OptionDefinition
1649CommandObjectPlatformProcessList::CommandOptions::g_option_table[] =
1650{
1651{ LLDB_OPT_SET_1            , false, "pid"        , 'p', OptionParser::eRequiredArgument, NULL, 0, eArgTypePid              , "List the process info for a specific process ID." },
1652{ LLDB_OPT_SET_2            , true , "name"       , 'n', OptionParser::eRequiredArgument, NULL, 0, eArgTypeProcessName      , "Find processes with executable basenames that match a string." },
1653{ LLDB_OPT_SET_3            , true , "ends-with"  , 'e', OptionParser::eRequiredArgument, NULL, 0, eArgTypeProcessName      , "Find processes with executable basenames that end with a string." },
1654{ LLDB_OPT_SET_4            , true , "starts-with", 's', OptionParser::eRequiredArgument, NULL, 0, eArgTypeProcessName      , "Find processes with executable basenames that start with a string." },
1655{ LLDB_OPT_SET_5            , true , "contains"   , 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypeProcessName      , "Find processes with executable basenames that contain a string." },
1656{ LLDB_OPT_SET_6            , true , "regex"      , 'r', OptionParser::eRequiredArgument, NULL, 0, eArgTypeRegularExpression, "Find processes with executable basenames that match a regular expression." },
1657{ LLDB_OPT_SET_FROM_TO(2, 6), false, "parent"     , 'P', OptionParser::eRequiredArgument, NULL, 0, eArgTypePid              , "Find processes that have a matching parent process ID." },
1658{ LLDB_OPT_SET_FROM_TO(2, 6), false, "uid"        , 'u', OptionParser::eRequiredArgument, NULL, 0, eArgTypeUnsignedInteger  , "Find processes that have a matching user ID." },
1659{ LLDB_OPT_SET_FROM_TO(2, 6), false, "euid"       , 'U', OptionParser::eRequiredArgument, NULL, 0, eArgTypeUnsignedInteger  , "Find processes that have a matching effective user ID." },
1660{ LLDB_OPT_SET_FROM_TO(2, 6), false, "gid"        , 'g', OptionParser::eRequiredArgument, NULL, 0, eArgTypeUnsignedInteger  , "Find processes that have a matching group ID." },
1661{ LLDB_OPT_SET_FROM_TO(2, 6), false, "egid"       , 'G', OptionParser::eRequiredArgument, NULL, 0, eArgTypeUnsignedInteger  , "Find processes that have a matching effective group ID." },
1662{ LLDB_OPT_SET_FROM_TO(2, 6), false, "arch"       , 'a', OptionParser::eRequiredArgument, NULL, 0, eArgTypeArchitecture     , "Find processes that have a matching architecture." },
1663{ LLDB_OPT_SET_FROM_TO(1, 6), false, "show-args"  , 'A', OptionParser::eNoArgument      , NULL, 0, eArgTypeNone             , "Show process arguments instead of the process executable basename." },
1664{ LLDB_OPT_SET_FROM_TO(1, 6), false, "verbose"    , 'v', OptionParser::eNoArgument      , NULL, 0, eArgTypeNone             , "Enable verbose output." },
1665{ 0                         , false, NULL         ,  0 , 0                , NULL, 0, eArgTypeNone             , NULL }
1666};
1667
1668//----------------------------------------------------------------------
1669// "platform process info"
1670//----------------------------------------------------------------------
1671class CommandObjectPlatformProcessInfo : public CommandObjectParsed
1672{
1673public:
1674    CommandObjectPlatformProcessInfo (CommandInterpreter &interpreter) :
1675    CommandObjectParsed (interpreter,
1676                         "platform process info",
1677                         "Get detailed information for one or more process by process ID.",
1678                         "platform process info <pid> [<pid> <pid> ...]",
1679                         0)
1680    {
1681        CommandArgumentEntry arg;
1682        CommandArgumentData pid_args;
1683
1684        // Define the first (and only) variant of this arg.
1685        pid_args.arg_type = eArgTypePid;
1686        pid_args.arg_repetition = eArgRepeatStar;
1687
1688        // There is only one variant this argument could be; put it into the argument entry.
1689        arg.push_back (pid_args);
1690
1691        // Push the data for the first argument into the m_arguments vector.
1692        m_arguments.push_back (arg);
1693    }
1694
1695    virtual
1696    ~CommandObjectPlatformProcessInfo ()
1697    {
1698    }
1699
1700protected:
1701    virtual bool
1702    DoExecute (Args& args, CommandReturnObject &result)
1703    {
1704        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
1705        PlatformSP platform_sp;
1706        if (target)
1707        {
1708            platform_sp = target->GetPlatform();
1709        }
1710        if (!platform_sp)
1711        {
1712            platform_sp = m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform();
1713        }
1714
1715        if (platform_sp)
1716        {
1717            const size_t argc = args.GetArgumentCount();
1718            if (argc > 0)
1719            {
1720                Error error;
1721
1722                if (platform_sp->IsConnected())
1723                {
1724                    Stream &ostrm = result.GetOutputStream();
1725                    bool success;
1726                    for (size_t i=0; i<argc; ++ i)
1727                    {
1728                        const char *arg = args.GetArgumentAtIndex(i);
1729                        lldb::pid_t pid = Args::StringToUInt32 (arg, LLDB_INVALID_PROCESS_ID, 0, &success);
1730                        if (success)
1731                        {
1732                            ProcessInstanceInfo proc_info;
1733                            if (platform_sp->GetProcessInfo (pid, proc_info))
1734                            {
1735                                ostrm.Printf ("Process information for process %" PRIu64 ":\n", pid);
1736                                proc_info.Dump (ostrm, platform_sp.get());
1737                            }
1738                            else
1739                            {
1740                                ostrm.Printf ("error: no process information is available for process %" PRIu64 "\n", pid);
1741                            }
1742                            ostrm.EOL();
1743                        }
1744                        else
1745                        {
1746                            result.AppendErrorWithFormat ("invalid process ID argument '%s'", arg);
1747                            result.SetStatus (eReturnStatusFailed);
1748                            break;
1749                        }
1750                    }
1751                }
1752                else
1753                {
1754                    // Not connected...
1755                    result.AppendErrorWithFormat ("not connected to '%s'", platform_sp->GetPluginName().GetCString());
1756                    result.SetStatus (eReturnStatusFailed);
1757                }
1758            }
1759            else
1760            {
1761                // No args
1762                result.AppendError ("one or more process id(s) must be specified");
1763                result.SetStatus (eReturnStatusFailed);
1764            }
1765        }
1766        else
1767        {
1768            result.AppendError ("no platform is currently selected");
1769            result.SetStatus (eReturnStatusFailed);
1770        }
1771        return result.Succeeded();
1772    }
1773};
1774
1775class CommandObjectPlatformProcessAttach : public CommandObjectParsed
1776{
1777public:
1778
1779    class CommandOptions : public Options
1780    {
1781    public:
1782
1783        CommandOptions (CommandInterpreter &interpreter) :
1784        Options(interpreter)
1785        {
1786            // Keep default values of all options in one place: OptionParsingStarting ()
1787            OptionParsingStarting ();
1788        }
1789
1790        ~CommandOptions ()
1791        {
1792        }
1793
1794        Error
1795        SetOptionValue (uint32_t option_idx, const char *option_arg)
1796        {
1797            Error error;
1798            char short_option = (char) m_getopt_table[option_idx].val;
1799            bool success = false;
1800            switch (short_option)
1801            {
1802                case 'p':
1803                {
1804                    lldb::pid_t pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success);
1805                    if (!success || pid == LLDB_INVALID_PROCESS_ID)
1806                    {
1807                        error.SetErrorStringWithFormat("invalid process ID '%s'", option_arg);
1808                    }
1809                    else
1810                    {
1811                        attach_info.SetProcessID (pid);
1812                    }
1813                }
1814                    break;
1815
1816                case 'P':
1817                    attach_info.SetProcessPluginName (option_arg);
1818                    break;
1819
1820                case 'n':
1821                    attach_info.GetExecutableFile().SetFile(option_arg, false);
1822                    break;
1823
1824                case 'w':
1825                    attach_info.SetWaitForLaunch(true);
1826                    break;
1827
1828                default:
1829                    error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
1830                    break;
1831            }
1832            return error;
1833        }
1834
1835        void
1836        OptionParsingStarting ()
1837        {
1838            attach_info.Clear();
1839        }
1840
1841        const OptionDefinition*
1842        GetDefinitions ()
1843        {
1844            return g_option_table;
1845        }
1846
1847        virtual bool
1848        HandleOptionArgumentCompletion (Args &input,
1849                                        int cursor_index,
1850                                        int char_pos,
1851                                        OptionElementVector &opt_element_vector,
1852                                        int opt_element_index,
1853                                        int match_start_point,
1854                                        int max_return_elements,
1855                                        bool &word_complete,
1856                                        StringList &matches)
1857        {
1858            int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
1859            int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
1860
1861            // We are only completing the name option for now...
1862
1863            const OptionDefinition *opt_defs = GetDefinitions();
1864            if (opt_defs[opt_defs_index].short_option == 'n')
1865            {
1866                // Are we in the name?
1867
1868                // Look to see if there is a -P argument provided, and if so use that plugin, otherwise
1869                // use the default plugin.
1870
1871                const char *partial_name = NULL;
1872                partial_name = input.GetArgumentAtIndex(opt_arg_pos);
1873
1874                PlatformSP platform_sp (m_interpreter.GetPlatform (true));
1875                if (platform_sp)
1876                {
1877                    ProcessInstanceInfoList process_infos;
1878                    ProcessInstanceInfoMatch match_info;
1879                    if (partial_name)
1880                    {
1881                        match_info.GetProcessInfo().GetExecutableFile().SetFile(partial_name, false);
1882                        match_info.SetNameMatchType(eNameMatchStartsWith);
1883                    }
1884                    platform_sp->FindProcesses (match_info, process_infos);
1885                    const uint32_t num_matches = process_infos.GetSize();
1886                    if (num_matches > 0)
1887                    {
1888                        for (uint32_t i=0; i<num_matches; ++i)
1889                        {
1890                            matches.AppendString (process_infos.GetProcessNameAtIndex(i),
1891                                                  process_infos.GetProcessNameLengthAtIndex(i));
1892                        }
1893                    }
1894                }
1895            }
1896
1897            return false;
1898        }
1899
1900        // Options table: Required for subclasses of Options.
1901
1902        static OptionDefinition g_option_table[];
1903
1904        // Instance variables to hold the values for command options.
1905
1906        ProcessAttachInfo attach_info;
1907    };
1908
1909    CommandObjectPlatformProcessAttach (CommandInterpreter &interpreter) :
1910    CommandObjectParsed (interpreter,
1911                         "platform process attach",
1912                         "Attach to a process.",
1913                         "platform process attach <cmd-options>"),
1914    m_options (interpreter)
1915    {
1916    }
1917
1918    ~CommandObjectPlatformProcessAttach ()
1919    {
1920    }
1921
1922    bool
1923    DoExecute (Args& command,
1924             CommandReturnObject &result)
1925    {
1926        PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
1927        if (platform_sp)
1928        {
1929            Error err;
1930            ProcessSP remote_process_sp =
1931            platform_sp->Attach(m_options.attach_info, m_interpreter.GetDebugger(), NULL, m_interpreter.GetDebugger().GetListener(), err);
1932            if (err.Fail())
1933            {
1934                result.AppendError(err.AsCString());
1935                result.SetStatus (eReturnStatusFailed);
1936            }
1937            else if (remote_process_sp.get() == NULL)
1938            {
1939                result.AppendError("could not attach: unknown reason");
1940                result.SetStatus (eReturnStatusFailed);
1941            }
1942            else
1943                result.SetStatus (eReturnStatusSuccessFinishResult);
1944        }
1945        else
1946        {
1947            result.AppendError ("no platform is currently selected");
1948            result.SetStatus (eReturnStatusFailed);
1949        }
1950        return result.Succeeded();
1951    }
1952
1953    Options *
1954    GetOptions ()
1955    {
1956        return &m_options;
1957    }
1958
1959protected:
1960
1961    CommandOptions m_options;
1962};
1963
1964
1965OptionDefinition
1966CommandObjectPlatformProcessAttach::CommandOptions::g_option_table[] =
1967{
1968    { LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, NULL, 0, eArgTypePlugin,        "Name of the process plugin you want to use."},
1969    { LLDB_OPT_SET_1,   false, "pid",    'p', OptionParser::eRequiredArgument, NULL, 0, eArgTypePid,           "The process ID of an existing process to attach to."},
1970    { LLDB_OPT_SET_2,   false, "name",   'n', OptionParser::eRequiredArgument, NULL, 0, eArgTypeProcessName,  "The name of the process to attach to."},
1971    { LLDB_OPT_SET_2,   false, "waitfor",'w', OptionParser::eNoArgument,       NULL, 0, eArgTypeNone,              "Wait for the the process with <process-name> to launch."},
1972    { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1973};
1974
1975
1976class CommandObjectPlatformProcess : public CommandObjectMultiword
1977{
1978public:
1979    //------------------------------------------------------------------
1980    // Constructors and Destructors
1981    //------------------------------------------------------------------
1982     CommandObjectPlatformProcess (CommandInterpreter &interpreter) :
1983        CommandObjectMultiword (interpreter,
1984                                "platform process",
1985                                "A set of commands to query, launch and attach to platform processes",
1986                                "platform process [attach|launch|list] ...")
1987    {
1988        LoadSubCommand ("attach", CommandObjectSP (new CommandObjectPlatformProcessAttach (interpreter)));
1989        LoadSubCommand ("launch", CommandObjectSP (new CommandObjectPlatformProcessLaunch (interpreter)));
1990        LoadSubCommand ("info"  , CommandObjectSP (new CommandObjectPlatformProcessInfo (interpreter)));
1991        LoadSubCommand ("list"  , CommandObjectSP (new CommandObjectPlatformProcessList (interpreter)));
1992
1993    }
1994
1995    virtual
1996    ~CommandObjectPlatformProcess ()
1997    {
1998    }
1999
2000private:
2001    //------------------------------------------------------------------
2002    // For CommandObjectPlatform only
2003    //------------------------------------------------------------------
2004    DISALLOW_COPY_AND_ASSIGN (CommandObjectPlatformProcess);
2005};
2006
2007//----------------------------------------------------------------------
2008// "platform shell"
2009//----------------------------------------------------------------------
2010class CommandObjectPlatformShell : public CommandObjectRaw
2011{
2012public:
2013
2014    class CommandOptions : public Options
2015    {
2016    public:
2017
2018        CommandOptions (CommandInterpreter &interpreter) :
2019        Options(interpreter),
2020        timeout(10)
2021        {
2022        }
2023
2024        virtual
2025        ~CommandOptions ()
2026        {
2027        }
2028
2029        virtual uint32_t
2030        GetNumDefinitions ()
2031        {
2032            return 1;
2033        }
2034
2035        virtual const OptionDefinition*
2036        GetDefinitions ()
2037        {
2038            return g_option_table;
2039        }
2040
2041        virtual Error
2042        SetOptionValue (uint32_t option_idx,
2043                        const char *option_value)
2044        {
2045            Error error;
2046
2047            const char short_option = (char) g_option_table[option_idx].short_option;
2048
2049            switch (short_option)
2050            {
2051                case 't':
2052                {
2053                    bool success;
2054                    timeout = Args::StringToUInt32(option_value, 10, 10, &success);
2055                    if (!success)
2056                        error.SetErrorStringWithFormat("could not convert \"%s\" to a numeric value.", option_value);
2057                    break;
2058                }
2059                default:
2060                    error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
2061                    break;
2062            }
2063
2064            return error;
2065        }
2066
2067        virtual void
2068        OptionParsingStarting ()
2069        {
2070        }
2071
2072        // Options table: Required for subclasses of Options.
2073
2074        static OptionDefinition g_option_table[];
2075        uint32_t timeout;
2076    };
2077
2078    CommandObjectPlatformShell (CommandInterpreter &interpreter) :
2079    CommandObjectRaw (interpreter,
2080                      "platform shell",
2081                      "Run a shell command on a the selected platform.",
2082                      "platform shell <shell-command>",
2083                      0),
2084    m_options(interpreter)
2085    {
2086    }
2087
2088    virtual
2089    ~CommandObjectPlatformShell ()
2090    {
2091    }
2092
2093    virtual
2094    Options *
2095    GetOptions ()
2096    {
2097        return &m_options;
2098    }
2099
2100    virtual bool
2101    DoExecute (const char *raw_command_line, CommandReturnObject &result)
2102    {
2103        m_options.NotifyOptionParsingStarting();
2104
2105        const char* expr = NULL;
2106
2107        // Print out an usage syntax on an empty command line.
2108        if (raw_command_line[0] == '\0')
2109        {
2110            result.GetOutputStream().Printf("%s\n", this->GetSyntax());
2111            return true;
2112        }
2113
2114        if (raw_command_line[0] == '-')
2115        {
2116            // We have some options and these options MUST end with --.
2117            const char *end_options = NULL;
2118            const char *s = raw_command_line;
2119            while (s && s[0])
2120            {
2121                end_options = ::strstr (s, "--");
2122                if (end_options)
2123                {
2124                    end_options += 2; // Get past the "--"
2125                    if (::isspace (end_options[0]))
2126                    {
2127                        expr = end_options;
2128                        while (::isspace (*expr))
2129                            ++expr;
2130                        break;
2131                    }
2132                }
2133                s = end_options;
2134            }
2135
2136            if (end_options)
2137            {
2138                Args args (raw_command_line, end_options - raw_command_line);
2139                if (!ParseOptions (args, result))
2140                    return false;
2141            }
2142        }
2143
2144        if (expr == NULL)
2145            expr = raw_command_line;
2146
2147        PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
2148        Error error;
2149        if (platform_sp)
2150        {
2151            const char *working_dir = NULL;
2152            std::string output;
2153            int status = -1;
2154            int signo = -1;
2155            error = (platform_sp->RunShellCommand (expr, working_dir, &status, &signo, &output, m_options.timeout));
2156            if (!output.empty())
2157                result.GetOutputStream().PutCString(output.c_str());
2158            if (status > 0)
2159            {
2160                if (signo > 0)
2161                {
2162                    const char *signo_cstr = Host::GetSignalAsCString(signo);
2163                    if (signo_cstr)
2164                        result.GetOutputStream().Printf("error: command returned with status %i and signal %s\n", status, signo_cstr);
2165                    else
2166                        result.GetOutputStream().Printf("error: command returned with status %i and signal %i\n", status, signo);
2167                }
2168                else
2169                    result.GetOutputStream().Printf("error: command returned with status %i\n", status);
2170            }
2171        }
2172        else
2173        {
2174            result.GetOutputStream().Printf("error: cannot run remote shell commands without a platform\n");
2175            error.SetErrorString("error: cannot run remote shell commands without a platform");
2176        }
2177
2178        if (error.Fail())
2179        {
2180            result.AppendError(error.AsCString());
2181            result.SetStatus (eReturnStatusFailed);
2182        }
2183        else
2184        {
2185            result.SetStatus (eReturnStatusSuccessFinishResult);
2186        }
2187        return true;
2188    }
2189    CommandOptions m_options;
2190};
2191
2192OptionDefinition
2193CommandObjectPlatformShell::CommandOptions::g_option_table[] =
2194{
2195    { LLDB_OPT_SET_ALL, false, "timeout",      't', OptionParser::eRequiredArgument, NULL, 0, eArgTypeValue,    "Seconds to wait for the remote host to finish running the command."},
2196    { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
2197};
2198
2199
2200//----------------------------------------------------------------------
2201// "platform install" - install a target to a remote end
2202//----------------------------------------------------------------------
2203class CommandObjectPlatformInstall : public CommandObjectParsed
2204{
2205public:
2206    CommandObjectPlatformInstall (CommandInterpreter &interpreter) :
2207    CommandObjectParsed (interpreter,
2208                         "platform target-install",
2209                         "Install a target (bundle or executable file) to the remote end.",
2210                         "platform target-install <local-thing> <remote-sandbox>",
2211                         0)
2212    {
2213    }
2214
2215    virtual
2216    ~CommandObjectPlatformInstall ()
2217    {
2218    }
2219
2220    virtual bool
2221    DoExecute (Args& args, CommandReturnObject &result)
2222    {
2223        if (args.GetArgumentCount() != 2)
2224        {
2225            result.AppendError("platform target-install takes two arguments");
2226            result.SetStatus(eReturnStatusFailed);
2227            return false;
2228        }
2229        // TODO: move the bulk of this code over to the platform itself
2230        FileSpec src(args.GetArgumentAtIndex(0), true);
2231        FileSpec dst(args.GetArgumentAtIndex(1), false);
2232        if (src.Exists() == false)
2233        {
2234            result.AppendError("source location does not exist or is not accessible");
2235            result.SetStatus(eReturnStatusFailed);
2236            return false;
2237        }
2238        PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
2239        if (!platform_sp)
2240        {
2241            result.AppendError ("no platform currently selected");
2242            result.SetStatus (eReturnStatusFailed);
2243            return false;
2244        }
2245
2246        Error error = platform_sp->Install(src, dst);
2247        if (error.Success())
2248        {
2249            result.SetStatus(eReturnStatusSuccessFinishNoResult);
2250        }
2251        else
2252        {
2253            result.AppendErrorWithFormat("install failed: %s", error.AsCString());
2254            result.SetStatus(eReturnStatusFailed);
2255        }
2256        return result.Succeeded();
2257    }
2258private:
2259
2260};
2261
2262//----------------------------------------------------------------------
2263// CommandObjectPlatform constructor
2264//----------------------------------------------------------------------
2265CommandObjectPlatform::CommandObjectPlatform(CommandInterpreter &interpreter) :
2266    CommandObjectMultiword (interpreter,
2267                            "platform",
2268                            "A set of commands to manage and create platforms.",
2269                            "platform [connect|disconnect|info|list|status|select] ...")
2270{
2271    LoadSubCommand ("select", CommandObjectSP (new CommandObjectPlatformSelect (interpreter)));
2272    LoadSubCommand ("list"  , CommandObjectSP (new CommandObjectPlatformList (interpreter)));
2273    LoadSubCommand ("status", CommandObjectSP (new CommandObjectPlatformStatus (interpreter)));
2274    LoadSubCommand ("connect", CommandObjectSP (new CommandObjectPlatformConnect (interpreter)));
2275    LoadSubCommand ("disconnect", CommandObjectSP (new CommandObjectPlatformDisconnect (interpreter)));
2276    LoadSubCommand ("settings", CommandObjectSP (new CommandObjectPlatformSettings (interpreter)));
2277#ifdef LLDB_CONFIGURATION_DEBUG
2278    LoadSubCommand ("mkdir", CommandObjectSP (new CommandObjectPlatformMkDir (interpreter)));
2279    LoadSubCommand ("file", CommandObjectSP (new CommandObjectPlatformFile (interpreter)));
2280    LoadSubCommand ("get-file", CommandObjectSP (new CommandObjectPlatformGetFile (interpreter)));
2281    LoadSubCommand ("get-size", CommandObjectSP (new CommandObjectPlatformGetSize (interpreter)));
2282    LoadSubCommand ("put-file", CommandObjectSP (new CommandObjectPlatformPutFile (interpreter)));
2283#endif
2284    LoadSubCommand ("process", CommandObjectSP (new CommandObjectPlatformProcess (interpreter)));
2285    LoadSubCommand ("shell", CommandObjectSP (new CommandObjectPlatformShell (interpreter)));
2286    LoadSubCommand ("target-install", CommandObjectSP (new CommandObjectPlatformInstall (interpreter)));
2287}
2288
2289
2290//----------------------------------------------------------------------
2291// Destructor
2292//----------------------------------------------------------------------
2293CommandObjectPlatform::~CommandObjectPlatform()
2294{
2295}
2296