CommandObjectProcess.cpp revision 527154d8e532f27f25af226c9e1dac607c48b5d1
1//===-- CommandObjectProcess.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 "CommandObjectProcess.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
16#include "lldb/Interpreter/Args.h"
17#include "lldb/Interpreter/Options.h"
18#include "lldb/Core/State.h"
19#include "lldb/Host/Host.h"
20#include "lldb/Interpreter/CommandInterpreter.h"
21#include "lldb/Interpreter/CommandReturnObject.h"
22#include "lldb/Target/Platform.h"
23#include "lldb/Target/Process.h"
24#include "lldb/Target/Target.h"
25#include "lldb/Target/Thread.h"
26
27using namespace lldb;
28using namespace lldb_private;
29
30//-------------------------------------------------------------------------
31// CommandObjectProcessLaunch
32//-------------------------------------------------------------------------
33#pragma mark CommandObjectProjectLaunch
34class CommandObjectProcessLaunch : public CommandObject
35{
36public:
37
38//    class CommandOptions : public Options
39//    {
40//    public:
41//
42//        CommandOptions (CommandInterpreter &interpreter) :
43//            Options(interpreter)
44//        {
45//            // Keep default values of all options in one place: OptionParsingStarting ()
46//            OptionParsingStarting ();
47//        }
48//
49//        ~CommandOptions ()
50//        {
51//        }
52//
53//        Error
54//        SetOptionValue (uint32_t option_idx, const char *option_arg)
55//        {
56//            Error error;
57//            char short_option = (char) m_getopt_table[option_idx].val;
58//
59//            switch (short_option)
60//            {
61//                case 's':   stop_at_entry = true;               break;
62//                case 'e':   stderr_path.assign (option_arg);    break;
63//                case 'i':   stdin_path.assign (option_arg);     break;
64//                case 'o':   stdout_path.assign (option_arg);    break;
65//                case 'p':   plugin_name.assign (option_arg);    break;
66//                case 'n':   no_stdio = true;                    break;
67//                case 'w':   working_dir.assign (option_arg);    break;
68//                case 't':
69//                    if (option_arg && option_arg[0])
70//                        tty_name.assign (option_arg);
71//                    in_new_tty = true;
72//                    break;
73//                default:
74//                    error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
75//                    break;
76//
77//            }
78//            return error;
79//        }
80//
81//        void
82//        OptionParsingStarting ()
83//        {
84//            stop_at_entry = false;
85//            in_new_tty = false;
86//            tty_name.clear();
87//            stdin_path.clear();
88//            stdout_path.clear();
89//            stderr_path.clear();
90//            plugin_name.clear();
91//            working_dir.clear();
92//            no_stdio = false;
93//        }
94//
95//        const OptionDefinition*
96//        GetDefinitions ()
97//        {
98//            return g_option_table;
99//        }
100//
101//        // Options table: Required for subclasses of Options.
102//
103//        static OptionDefinition g_option_table[];
104//
105//        // Instance variables to hold the values for command options.
106//
107//        bool stop_at_entry;
108//        bool in_new_tty;
109//        bool no_stdio;
110//        std::string tty_name;
111//        std::string stderr_path;
112//        std::string stdin_path;
113//        std::string stdout_path;
114//        std::string plugin_name;
115//        std::string working_dir;
116//
117//    };
118
119    CommandObjectProcessLaunch (CommandInterpreter &interpreter) :
120        CommandObject (interpreter,
121                       "process launch",
122                       "Launch the executable in the debugger.",
123                       NULL),
124        m_options (interpreter)
125    {
126        CommandArgumentEntry arg;
127        CommandArgumentData run_args_arg;
128
129        // Define the first (and only) variant of this arg.
130        run_args_arg.arg_type = eArgTypeRunArgs;
131        run_args_arg.arg_repetition = eArgRepeatOptional;
132
133        // There is only one variant this argument could be; put it into the argument entry.
134        arg.push_back (run_args_arg);
135
136        // Push the data for the first argument into the m_arguments vector.
137        m_arguments.push_back (arg);
138    }
139
140
141    ~CommandObjectProcessLaunch ()
142    {
143    }
144
145    Options *
146    GetOptions ()
147    {
148        return &m_options;
149    }
150
151    bool
152    Execute (Args& launch_args, CommandReturnObject &result)
153    {
154        Debugger &debugger = m_interpreter.GetDebugger();
155        Target *target = debugger.GetSelectedTarget().get();
156        Error error;
157
158        if (target == NULL)
159        {
160            result.AppendError ("invalid target, create a debug target using the 'target create' command");
161            result.SetStatus (eReturnStatusFailed);
162            return false;
163        }
164        // If our listener is NULL, users aren't allows to launch
165        char filename[PATH_MAX];
166        const Module *exe_module = target->GetExecutableModulePointer();
167
168        if (exe_module == NULL)
169        {
170            result.AppendError ("no file in target, create a debug target using the 'target create' command");
171            result.SetStatus (eReturnStatusFailed);
172            return false;
173        }
174
175        exe_module->GetFileSpec().GetPath (filename, sizeof(filename));
176
177        const bool add_exe_file_as_first_arg = true;
178        m_options.launch_info.SetExecutableFile(exe_module->GetFileSpec(), add_exe_file_as_first_arg);
179
180        StateType state = eStateInvalid;
181        Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
182        if (process)
183        {
184            state = process->GetState();
185
186            if (process->IsAlive() && state != eStateConnected)
187            {
188                char message[1024];
189                if (process->GetState() == eStateAttaching)
190                    ::strncpy (message, "There is a pending attach, abort it and launch a new process?", sizeof(message));
191                else
192                    ::strncpy (message, "There is a running process, kill it and restart?", sizeof(message));
193
194                if (!m_interpreter.Confirm (message, true))
195                {
196                    result.SetStatus (eReturnStatusFailed);
197                    return false;
198                }
199                else
200                {
201                    Error destroy_error (process->Destroy());
202                    if (destroy_error.Success())
203                    {
204                        result.SetStatus (eReturnStatusSuccessFinishResult);
205                    }
206                    else
207                    {
208                        result.AppendErrorWithFormat ("Failed to kill process: %s\n", destroy_error.AsCString());
209                        result.SetStatus (eReturnStatusFailed);
210                    }
211                }
212            }
213        }
214
215        if (launch_args.GetArgumentCount() == 0)
216        {
217            const Args &process_args = target->GetRunArguments();
218            if (process_args.GetArgumentCount() > 0)
219                m_options.launch_info.GetArguments().AppendArguments (process_args);
220        }
221        else
222        {
223            m_options.launch_info.GetArguments().AppendArguments (launch_args);
224        }
225
226        if (target->GetDisableASLR())
227            m_options.launch_info.GetFlags().Set (eLaunchFlagDisableASLR);
228
229        if (target->GetDisableSTDIO())
230            m_options.launch_info.GetFlags().Set (eLaunchFlagDisableSTDIO);
231
232        m_options.launch_info.GetFlags().Set (eLaunchFlagDebug);
233
234        Args environment;
235        target->GetEnvironmentAsArgs (environment);
236        if (environment.GetArgumentCount() > 0)
237            m_options.launch_info.GetEnvironmentEntries ().AppendArguments (environment);
238
239        m_options.launch_info.FinalizeFileActions (target);
240
241        if (state == eStateConnected)
242        {
243            if (m_options.launch_info.GetFlags().Test (eLaunchFlagLaunchInTTY))
244            {
245                result.AppendWarning("can't launch in tty when launching through a remote connection");
246                m_options.launch_info.GetFlags().Clear (eLaunchFlagLaunchInTTY);
247            }
248        }
249        else
250        {
251            if (!m_options.launch_info.GetArchitecture().IsValid())
252                m_options.launch_info.GetArchitecture() = target->GetArchitecture();
253
254            process = target->GetPlatform()->DebugProcess (m_options.launch_info,
255                                                           debugger,
256                                                           target,
257                                                           debugger.GetListener(),
258                                                           error).get();
259
260            if (process == NULL)
261            {
262                result.SetError (error, "failed to launch or debug process");
263                return false;
264            }
265        }
266
267        if (error.Success())
268        {
269            const char *archname = exe_module->GetArchitecture().GetArchitectureName();
270
271            result.AppendMessageWithFormat ("Process %llu launched: '%s' (%s)\n", process->GetID(), filename, archname);
272            result.SetDidChangeProcessState (true);
273            if (m_options.launch_info.GetFlags().Test(eLaunchFlagStopAtEntry) == false)
274            {
275                result.SetStatus (eReturnStatusSuccessContinuingNoResult);
276                StateType state = process->WaitForProcessToStop (NULL);
277
278                if (state == eStateStopped)
279                {
280                    error = process->Resume();
281                    if (error.Success())
282                    {
283                        bool synchronous_execution = m_interpreter.GetSynchronous ();
284                        if (synchronous_execution)
285                        {
286                            state = process->WaitForProcessToStop (NULL);
287                            if (!StateIsStoppedState(state))
288                            {
289                                result.AppendErrorWithFormat ("process isn't stopped: %s", StateAsCString(state));
290                            }
291                            result.SetDidChangeProcessState (true);
292                            result.SetStatus (eReturnStatusSuccessFinishResult);
293                        }
294                        else
295                        {
296                            result.SetStatus (eReturnStatusSuccessContinuingNoResult);
297                        }
298                    }
299                    else
300                    {
301                        result.AppendErrorWithFormat ("process resume at entry point failed: %s", error.AsCString());
302                        result.SetStatus (eReturnStatusFailed);
303                    }
304                }
305                else
306                {
307                    result.AppendErrorWithFormat ("initial process state wasn't stopped: %s", StateAsCString(state));
308                    result.SetStatus (eReturnStatusFailed);
309                }
310            }
311        }
312        else
313        {
314            result.AppendErrorWithFormat ("process launch failed: %s", error.AsCString());
315            result.SetStatus (eReturnStatusFailed);
316        }
317
318        return result.Succeeded();
319    }
320
321    virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
322    {
323        // No repeat for "process launch"...
324        return "";
325    }
326
327protected:
328    ProcessLaunchCommandOptions m_options;
329};
330
331
332//#define SET1 LLDB_OPT_SET_1
333//#define SET2 LLDB_OPT_SET_2
334//#define SET3 LLDB_OPT_SET_3
335//
336//OptionDefinition
337//CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
338//{
339//{ SET1 | SET2 | SET3, false, "stop-at-entry", 's', no_argument,       NULL, 0, eArgTypeNone,    "Stop at the entry point of the program when launching a process."},
340//{ SET1              , false, "stdin",         'i', required_argument, NULL, 0, eArgTypePath,    "Redirect stdin for the process to <path>."},
341//{ SET1              , false, "stdout",        'o', required_argument, NULL, 0, eArgTypePath,    "Redirect stdout for the process to <path>."},
342//{ SET1              , false, "stderr",        'e', required_argument, NULL, 0, eArgTypePath,    "Redirect stderr for the process to <path>."},
343//{ SET1 | SET2 | SET3, false, "plugin",        'p', required_argument, NULL, 0, eArgTypePlugin,  "Name of the process plugin you want to use."},
344//{        SET2       , false, "tty",           't', optional_argument, NULL, 0, eArgTypePath,    "Start the process in a terminal. If <path> is specified, look for a terminal whose name contains <path>, else start the process in a new terminal."},
345//{               SET3, false, "no-stdio",      'n', no_argument,       NULL, 0, eArgTypeNone,    "Do not set up for terminal I/O to go to running process."},
346//{ SET1 | SET2 | SET3, false, "working-dir",   'w', required_argument, NULL, 0, eArgTypePath,    "Set the current working directory to <path> when running the inferior."},
347//{ 0,                  false, NULL,             0,  0,                 NULL, 0, eArgTypeNone,    NULL }
348//};
349//
350//#undef SET1
351//#undef SET2
352//#undef SET3
353
354//-------------------------------------------------------------------------
355// CommandObjectProcessAttach
356//-------------------------------------------------------------------------
357#pragma mark CommandObjectProcessAttach
358class CommandObjectProcessAttach : public CommandObject
359{
360public:
361
362    class CommandOptions : public Options
363    {
364    public:
365
366        CommandOptions (CommandInterpreter &interpreter) :
367            Options(interpreter)
368        {
369            // Keep default values of all options in one place: OptionParsingStarting ()
370            OptionParsingStarting ();
371        }
372
373        ~CommandOptions ()
374        {
375        }
376
377        Error
378        SetOptionValue (uint32_t option_idx, const char *option_arg)
379        {
380            Error error;
381            char short_option = (char) m_getopt_table[option_idx].val;
382            bool success = false;
383            switch (short_option)
384            {
385                case 'p':
386                    {
387                        lldb::pid_t pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success);
388                        if (!success || pid == LLDB_INVALID_PROCESS_ID)
389                        {
390                            error.SetErrorStringWithFormat("invalid process ID '%s'", option_arg);
391                        }
392                        else
393                        {
394                            attach_info.SetProcessID (pid);
395                        }
396                    }
397                    break;
398
399                case 'P':
400                    attach_info.SetProcessPluginName (option_arg);
401                    break;
402
403                case 'n':
404                    attach_info.GetExecutableFile().SetFile(option_arg, false);
405                    break;
406
407                case 'w':
408                    attach_info.SetWaitForLaunch(true);
409                    break;
410
411                default:
412                    error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
413                    break;
414            }
415            return error;
416        }
417
418        void
419        OptionParsingStarting ()
420        {
421            attach_info.Clear();
422        }
423
424        const OptionDefinition*
425        GetDefinitions ()
426        {
427            return g_option_table;
428        }
429
430        virtual bool
431        HandleOptionArgumentCompletion (Args &input,
432                                        int cursor_index,
433                                        int char_pos,
434                                        OptionElementVector &opt_element_vector,
435                                        int opt_element_index,
436                                        int match_start_point,
437                                        int max_return_elements,
438                                        bool &word_complete,
439                                        StringList &matches)
440        {
441            int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
442            int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
443
444            // We are only completing the name option for now...
445
446            const OptionDefinition *opt_defs = GetDefinitions();
447            if (opt_defs[opt_defs_index].short_option == 'n')
448            {
449                // Are we in the name?
450
451                // Look to see if there is a -P argument provided, and if so use that plugin, otherwise
452                // use the default plugin.
453
454                const char *partial_name = NULL;
455                partial_name = input.GetArgumentAtIndex(opt_arg_pos);
456
457                PlatformSP platform_sp (m_interpreter.GetPlatform (true));
458                if (platform_sp)
459                {
460                    ProcessInstanceInfoList process_infos;
461                    ProcessInstanceInfoMatch match_info;
462                    if (partial_name)
463                    {
464                        match_info.GetProcessInfo().GetExecutableFile().SetFile(partial_name, false);
465                        match_info.SetNameMatchType(eNameMatchStartsWith);
466                    }
467                    platform_sp->FindProcesses (match_info, process_infos);
468                    const uint32_t num_matches = process_infos.GetSize();
469                    if (num_matches > 0)
470                    {
471                        for (uint32_t i=0; i<num_matches; ++i)
472                        {
473                            matches.AppendString (process_infos.GetProcessNameAtIndex(i),
474                                                  process_infos.GetProcessNameLengthAtIndex(i));
475                        }
476                    }
477                }
478            }
479
480            return false;
481        }
482
483        // Options table: Required for subclasses of Options.
484
485        static OptionDefinition g_option_table[];
486
487        // Instance variables to hold the values for command options.
488
489        ProcessAttachInfo attach_info;
490    };
491
492    CommandObjectProcessAttach (CommandInterpreter &interpreter) :
493        CommandObject (interpreter,
494                       "process attach",
495                       "Attach to a process.",
496                       "process attach <cmd-options>"),
497        m_options (interpreter)
498    {
499    }
500
501    ~CommandObjectProcessAttach ()
502    {
503    }
504
505    bool
506    Execute (Args& command,
507             CommandReturnObject &result)
508    {
509        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
510        // N.B. The attach should be synchronous.  It doesn't help much to get the prompt back between initiating the attach
511        // and the target actually stopping.  So even if the interpreter is set to be asynchronous, we wait for the stop
512        // ourselves here.
513
514        Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
515        StateType state = eStateInvalid;
516        if (process)
517        {
518            state = process->GetState();
519            if (process->IsAlive() && state != eStateConnected)
520            {
521                result.AppendErrorWithFormat ("Process %llu is currently being debugged, kill the process before attaching.\n",
522                                              process->GetID());
523                result.SetStatus (eReturnStatusFailed);
524                return false;
525            }
526        }
527
528        if (target == NULL)
529        {
530            // If there isn't a current target create one.
531            TargetSP new_target_sp;
532            FileSpec emptyFileSpec;
533            Error error;
534
535            error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(),
536                                                                              emptyFileSpec,
537                                                                              NULL,
538                                                                              false,
539                                                                              NULL, // No platform options
540                                                                              new_target_sp);
541            target = new_target_sp.get();
542            if (target == NULL || error.Fail())
543            {
544                result.AppendError(error.AsCString("Error creating target"));
545                return false;
546            }
547            m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target);
548        }
549
550        // Record the old executable module, we want to issue a warning if the process of attaching changed the
551        // current executable (like somebody said "file foo" then attached to a PID whose executable was bar.)
552
553        ModuleSP old_exec_module_sp = target->GetExecutableModule();
554        ArchSpec old_arch_spec = target->GetArchitecture();
555
556        if (command.GetArgumentCount())
557        {
558            result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: %s\n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
559            result.SetStatus (eReturnStatusFailed);
560        }
561        else
562        {
563            if (state != eStateConnected)
564            {
565                const char *plugin_name = m_options.attach_info.GetProcessPluginName();
566                process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
567            }
568
569            if (process)
570            {
571                Error error;
572                // If no process info was specified, then use the target executable
573                // name as the process to attach to by default
574                if (!m_options.attach_info.ProcessInfoSpecified ())
575                {
576                    if (old_exec_module_sp)
577                        m_options.attach_info.GetExecutableFile().GetFilename() = old_exec_module_sp->GetFileSpec().GetFilename();
578
579                    if (!m_options.attach_info.ProcessInfoSpecified ())
580                    {
581                        error.SetErrorString ("no process specified, create a target with a file, or specify the --pid or --name command option");
582                    }
583                }
584
585                if (error.Success())
586                {
587                    error = process->Attach (m_options.attach_info);
588
589                    if (error.Success())
590                    {
591                        result.SetStatus (eReturnStatusSuccessContinuingNoResult);
592                    }
593                    else
594                    {
595                        result.AppendErrorWithFormat ("attach failed: %s\n", error.AsCString());
596                        result.SetStatus (eReturnStatusFailed);
597                        return false;
598                    }
599                    // If we're synchronous, wait for the stopped event and report that.
600                    // Otherwise just return.
601                    // FIXME: in the async case it will now be possible to get to the command
602                    // interpreter with a state eStateAttaching.  Make sure we handle that correctly.
603                    StateType state = process->WaitForProcessToStop (NULL);
604
605                    result.SetDidChangeProcessState (true);
606                    result.AppendMessageWithFormat ("Process %llu %s\n", process->GetID(), StateAsCString (state));
607                    result.SetStatus (eReturnStatusSuccessFinishNoResult);
608                }
609            }
610        }
611
612        if (result.Succeeded())
613        {
614            // Okay, we're done.  Last step is to warn if the executable module has changed:
615            char new_path[PATH_MAX];
616            ModuleSP new_exec_module_sp (target->GetExecutableModule());
617            if (!old_exec_module_sp)
618            {
619                // We might not have a module if we attached to a raw pid...
620                if (new_exec_module_sp)
621                {
622                    new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX);
623                    result.AppendMessageWithFormat("Executable module set to \"%s\".\n", new_path);
624                }
625            }
626            else if (old_exec_module_sp->GetFileSpec() != new_exec_module_sp->GetFileSpec())
627            {
628                char old_path[PATH_MAX];
629
630                old_exec_module_sp->GetFileSpec().GetPath (old_path, PATH_MAX);
631                new_exec_module_sp->GetFileSpec().GetPath (new_path, PATH_MAX);
632
633                result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n",
634                                                    old_path, new_path);
635            }
636
637            if (!old_arch_spec.IsValid())
638            {
639                result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().GetArchitectureName());
640            }
641            else if (old_arch_spec != target->GetArchitecture())
642            {
643                result.AppendWarningWithFormat("Architecture changed from %s to %s.\n",
644                                                old_arch_spec.GetArchitectureName(), target->GetArchitecture().GetArchitectureName());
645            }
646        }
647        return result.Succeeded();
648    }
649
650    Options *
651    GetOptions ()
652    {
653        return &m_options;
654    }
655
656protected:
657
658    CommandOptions m_options;
659};
660
661
662OptionDefinition
663CommandObjectProcessAttach::CommandOptions::g_option_table[] =
664{
665{ LLDB_OPT_SET_ALL, false, "plugin", 'P', required_argument, NULL, 0, eArgTypePlugin,        "Name of the process plugin you want to use."},
666{ LLDB_OPT_SET_1,   false, "pid",    'p', required_argument, NULL, 0, eArgTypePid,           "The process ID of an existing process to attach to."},
667{ LLDB_OPT_SET_2,   false, "name",   'n', required_argument, NULL, 0, eArgTypeProcessName,  "The name of the process to attach to."},
668{ LLDB_OPT_SET_2,   false, "waitfor",'w', no_argument,       NULL, 0, eArgTypeNone,              "Wait for the the process with <process-name> to launch."},
669{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
670};
671
672//-------------------------------------------------------------------------
673// CommandObjectProcessContinue
674//-------------------------------------------------------------------------
675#pragma mark CommandObjectProcessContinue
676
677class CommandObjectProcessContinue : public CommandObject
678{
679public:
680
681    CommandObjectProcessContinue (CommandInterpreter &interpreter) :
682        CommandObject (interpreter,
683                       "process continue",
684                       "Continue execution of all threads in the current process.",
685                       "process continue",
686                       eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
687    {
688    }
689
690
691    ~CommandObjectProcessContinue ()
692    {
693    }
694
695    bool
696    Execute (Args& command,
697             CommandReturnObject &result)
698    {
699        Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
700        bool synchronous_execution = m_interpreter.GetSynchronous ();
701
702        if (process == NULL)
703        {
704            result.AppendError ("no process to continue");
705            result.SetStatus (eReturnStatusFailed);
706            return false;
707         }
708
709        StateType state = process->GetState();
710        if (state == eStateStopped)
711        {
712            if (command.GetArgumentCount() != 0)
713            {
714                result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str());
715                result.SetStatus (eReturnStatusFailed);
716                return false;
717            }
718
719            const uint32_t num_threads = process->GetThreadList().GetSize();
720
721            // Set the actions that the threads should each take when resuming
722            for (uint32_t idx=0; idx<num_threads; ++idx)
723            {
724                process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning);
725            }
726
727            Error error(process->Resume());
728            if (error.Success())
729            {
730                result.AppendMessageWithFormat ("Process %llu resuming\n", process->GetID());
731                if (synchronous_execution)
732                {
733                    state = process->WaitForProcessToStop (NULL);
734
735                    result.SetDidChangeProcessState (true);
736                    result.AppendMessageWithFormat ("Process %llu %s\n", process->GetID(), StateAsCString (state));
737                    result.SetStatus (eReturnStatusSuccessFinishNoResult);
738                }
739                else
740                {
741                    result.SetStatus (eReturnStatusSuccessContinuingNoResult);
742                }
743            }
744            else
745            {
746                result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
747                result.SetStatus (eReturnStatusFailed);
748            }
749        }
750        else
751        {
752            result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
753                                         StateAsCString(state));
754            result.SetStatus (eReturnStatusFailed);
755        }
756        return result.Succeeded();
757    }
758};
759
760//-------------------------------------------------------------------------
761// CommandObjectProcessDetach
762//-------------------------------------------------------------------------
763#pragma mark CommandObjectProcessDetach
764
765class CommandObjectProcessDetach : public CommandObject
766{
767public:
768
769    CommandObjectProcessDetach (CommandInterpreter &interpreter) :
770        CommandObject (interpreter,
771                       "process detach",
772                       "Detach from the current process being debugged.",
773                       "process detach",
774                       eFlagProcessMustBeLaunched)
775    {
776    }
777
778    ~CommandObjectProcessDetach ()
779    {
780    }
781
782    bool
783    Execute (Args& command,
784             CommandReturnObject &result)
785    {
786        Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
787        if (process == NULL)
788        {
789            result.AppendError ("must have a valid process in order to detach");
790            result.SetStatus (eReturnStatusFailed);
791            return false;
792        }
793
794        result.AppendMessageWithFormat ("Detaching from process %llu\n", process->GetID());
795        Error error (process->Detach());
796        if (error.Success())
797        {
798            result.SetStatus (eReturnStatusSuccessFinishResult);
799        }
800        else
801        {
802            result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString());
803            result.SetStatus (eReturnStatusFailed);
804            return false;
805        }
806        return result.Succeeded();
807    }
808};
809
810//-------------------------------------------------------------------------
811// CommandObjectProcessConnect
812//-------------------------------------------------------------------------
813#pragma mark CommandObjectProcessConnect
814
815class CommandObjectProcessConnect : public CommandObject
816{
817public:
818
819    class CommandOptions : public Options
820    {
821    public:
822
823        CommandOptions (CommandInterpreter &interpreter) :
824            Options(interpreter)
825        {
826            // Keep default values of all options in one place: OptionParsingStarting ()
827            OptionParsingStarting ();
828        }
829
830        ~CommandOptions ()
831        {
832        }
833
834        Error
835        SetOptionValue (uint32_t option_idx, const char *option_arg)
836        {
837            Error error;
838            char short_option = (char) m_getopt_table[option_idx].val;
839
840            switch (short_option)
841            {
842            case 'p':
843                plugin_name.assign (option_arg);
844                break;
845
846            default:
847                error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
848                break;
849            }
850            return error;
851        }
852
853        void
854        OptionParsingStarting ()
855        {
856            plugin_name.clear();
857        }
858
859        const OptionDefinition*
860        GetDefinitions ()
861        {
862            return g_option_table;
863        }
864
865        // Options table: Required for subclasses of Options.
866
867        static OptionDefinition g_option_table[];
868
869        // Instance variables to hold the values for command options.
870
871        std::string plugin_name;
872    };
873
874    CommandObjectProcessConnect (CommandInterpreter &interpreter) :
875        CommandObject (interpreter,
876                       "process connect",
877                       "Connect to a remote debug service.",
878                       "process connect <remote-url>",
879                       0),
880        m_options (interpreter)
881    {
882    }
883
884    ~CommandObjectProcessConnect ()
885    {
886    }
887
888
889    bool
890    Execute (Args& command,
891             CommandReturnObject &result)
892    {
893
894        TargetSP target_sp (m_interpreter.GetDebugger().GetSelectedTarget());
895        Error error;
896        Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
897        if (process)
898        {
899            if (process->IsAlive())
900            {
901                result.AppendErrorWithFormat ("Process %llu is currently being debugged, kill the process before connecting.\n",
902                                              process->GetID());
903                result.SetStatus (eReturnStatusFailed);
904                return false;
905            }
906        }
907
908        if (!target_sp)
909        {
910            // If there isn't a current target create one.
911            FileSpec emptyFileSpec;
912
913            error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(),
914                                                                              emptyFileSpec,
915                                                                              NULL,
916                                                                              false,
917                                                                              NULL, // No platform options
918                                                                              target_sp);
919            if (!target_sp || error.Fail())
920            {
921                result.AppendError(error.AsCString("Error creating target"));
922                result.SetStatus (eReturnStatusFailed);
923                return false;
924            }
925            m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target_sp.get());
926        }
927
928        if (command.GetArgumentCount() == 1)
929        {
930            const char *plugin_name = NULL;
931            if (!m_options.plugin_name.empty())
932                plugin_name = m_options.plugin_name.c_str();
933
934            const char *remote_url = command.GetArgumentAtIndex(0);
935            process = target_sp->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
936
937            if (process)
938            {
939                error = process->ConnectRemote (remote_url);
940
941                if (error.Fail())
942                {
943                    result.AppendError(error.AsCString("Remote connect failed"));
944                    result.SetStatus (eReturnStatusFailed);
945                    return false;
946                }
947            }
948            else
949            {
950                result.AppendErrorWithFormat ("Unable to find process plug-in for remote URL '%s'.\nPlease specify a process plug-in name with the --plugin option, or specify an object file using the \"file\" command.\n",
951                                              m_cmd_name.c_str());
952                result.SetStatus (eReturnStatusFailed);
953            }
954        }
955        else
956        {
957            result.AppendErrorWithFormat ("'%s' takes exactly one argument:\nUsage: %s\n",
958                                          m_cmd_name.c_str(),
959                                          m_cmd_syntax.c_str());
960            result.SetStatus (eReturnStatusFailed);
961        }
962        return result.Succeeded();
963    }
964
965    Options *
966    GetOptions ()
967    {
968        return &m_options;
969    }
970
971protected:
972
973    CommandOptions m_options;
974};
975
976
977OptionDefinition
978CommandObjectProcessConnect::CommandOptions::g_option_table[] =
979{
980    { LLDB_OPT_SET_ALL, false, "plugin", 'p', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
981    { 0,                false, NULL,      0 , 0,                 NULL, 0, eArgTypeNone,   NULL }
982};
983
984//-------------------------------------------------------------------------
985// CommandObjectProcessLoad
986//-------------------------------------------------------------------------
987#pragma mark CommandObjectProcessLoad
988
989class CommandObjectProcessLoad : public CommandObject
990{
991public:
992
993    CommandObjectProcessLoad (CommandInterpreter &interpreter) :
994        CommandObject (interpreter,
995                       "process load",
996                       "Load a shared library into the current process.",
997                       "process load <filename> [<filename> ...]",
998                       eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
999    {
1000    }
1001
1002    ~CommandObjectProcessLoad ()
1003    {
1004    }
1005
1006    bool
1007    Execute (Args& command,
1008             CommandReturnObject &result)
1009    {
1010        Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
1011        if (process == NULL)
1012        {
1013            result.AppendError ("must have a valid process in order to load a shared library");
1014            result.SetStatus (eReturnStatusFailed);
1015            return false;
1016        }
1017
1018        const uint32_t argc = command.GetArgumentCount();
1019
1020        for (uint32_t i=0; i<argc; ++i)
1021        {
1022            Error error;
1023            const char *image_path = command.GetArgumentAtIndex(i);
1024            FileSpec image_spec (image_path, false);
1025            process->GetTarget().GetPlatform()->ResolveRemotePath(image_spec, image_spec);
1026            uint32_t image_token = process->LoadImage(image_spec, error);
1027            if (image_token != LLDB_INVALID_IMAGE_TOKEN)
1028            {
1029                result.AppendMessageWithFormat ("Loading \"%s\"...ok\nImage %u loaded.\n", image_path, image_token);
1030                result.SetStatus (eReturnStatusSuccessFinishResult);
1031            }
1032            else
1033            {
1034                result.AppendErrorWithFormat ("failed to load '%s': %s", image_path, error.AsCString());
1035                result.SetStatus (eReturnStatusFailed);
1036            }
1037        }
1038        return result.Succeeded();
1039    }
1040};
1041
1042
1043//-------------------------------------------------------------------------
1044// CommandObjectProcessUnload
1045//-------------------------------------------------------------------------
1046#pragma mark CommandObjectProcessUnload
1047
1048class CommandObjectProcessUnload : public CommandObject
1049{
1050public:
1051
1052    CommandObjectProcessUnload (CommandInterpreter &interpreter) :
1053        CommandObject (interpreter,
1054                       "process unload",
1055                       "Unload a shared library from the current process using the index returned by a previous call to \"process load\".",
1056                       "process unload <index>",
1057                       eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
1058    {
1059    }
1060
1061    ~CommandObjectProcessUnload ()
1062    {
1063    }
1064
1065    bool
1066    Execute (Args& command,
1067             CommandReturnObject &result)
1068    {
1069        Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
1070        if (process == NULL)
1071        {
1072            result.AppendError ("must have a valid process in order to load a shared library");
1073            result.SetStatus (eReturnStatusFailed);
1074            return false;
1075        }
1076
1077        const uint32_t argc = command.GetArgumentCount();
1078
1079        for (uint32_t i=0; i<argc; ++i)
1080        {
1081            const char *image_token_cstr = command.GetArgumentAtIndex(i);
1082            uint32_t image_token = Args::StringToUInt32(image_token_cstr, LLDB_INVALID_IMAGE_TOKEN, 0);
1083            if (image_token == LLDB_INVALID_IMAGE_TOKEN)
1084            {
1085                result.AppendErrorWithFormat ("invalid image index argument '%s'", image_token_cstr);
1086                result.SetStatus (eReturnStatusFailed);
1087                break;
1088            }
1089            else
1090            {
1091                Error error (process->UnloadImage(image_token));
1092                if (error.Success())
1093                {
1094                    result.AppendMessageWithFormat ("Unloading shared library with index %u...ok\n", image_token);
1095                    result.SetStatus (eReturnStatusSuccessFinishResult);
1096                }
1097                else
1098                {
1099                    result.AppendErrorWithFormat ("failed to unload image: %s", error.AsCString());
1100                    result.SetStatus (eReturnStatusFailed);
1101                    break;
1102                }
1103            }
1104        }
1105        return result.Succeeded();
1106    }
1107};
1108
1109//-------------------------------------------------------------------------
1110// CommandObjectProcessSignal
1111//-------------------------------------------------------------------------
1112#pragma mark CommandObjectProcessSignal
1113
1114class CommandObjectProcessSignal : public CommandObject
1115{
1116public:
1117
1118    CommandObjectProcessSignal (CommandInterpreter &interpreter) :
1119        CommandObject (interpreter,
1120                       "process signal",
1121                       "Send a UNIX signal to the current process being debugged.",
1122                       NULL)
1123    {
1124        CommandArgumentEntry arg;
1125        CommandArgumentData signal_arg;
1126
1127        // Define the first (and only) variant of this arg.
1128        signal_arg.arg_type = eArgTypeUnixSignal;
1129        signal_arg.arg_repetition = eArgRepeatPlain;
1130
1131        // There is only one variant this argument could be; put it into the argument entry.
1132        arg.push_back (signal_arg);
1133
1134        // Push the data for the first argument into the m_arguments vector.
1135        m_arguments.push_back (arg);
1136    }
1137
1138    ~CommandObjectProcessSignal ()
1139    {
1140    }
1141
1142    bool
1143    Execute (Args& command,
1144             CommandReturnObject &result)
1145    {
1146        Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
1147        if (process == NULL)
1148        {
1149            result.AppendError ("no process to signal");
1150            result.SetStatus (eReturnStatusFailed);
1151            return false;
1152        }
1153
1154        if (command.GetArgumentCount() == 1)
1155        {
1156            int signo = LLDB_INVALID_SIGNAL_NUMBER;
1157
1158            const char *signal_name = command.GetArgumentAtIndex(0);
1159            if (::isxdigit (signal_name[0]))
1160                signo = Args::StringToSInt32(signal_name, LLDB_INVALID_SIGNAL_NUMBER, 0);
1161            else
1162                signo = process->GetUnixSignals().GetSignalNumberFromName (signal_name);
1163
1164            if (signo == LLDB_INVALID_SIGNAL_NUMBER)
1165            {
1166                result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0));
1167                result.SetStatus (eReturnStatusFailed);
1168            }
1169            else
1170            {
1171                Error error (process->Signal (signo));
1172                if (error.Success())
1173                {
1174                    result.SetStatus (eReturnStatusSuccessFinishResult);
1175                }
1176                else
1177                {
1178                    result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString());
1179                    result.SetStatus (eReturnStatusFailed);
1180                }
1181            }
1182        }
1183        else
1184        {
1185            result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: %s\n", m_cmd_name.c_str(),
1186                                        m_cmd_syntax.c_str());
1187            result.SetStatus (eReturnStatusFailed);
1188        }
1189        return result.Succeeded();
1190    }
1191};
1192
1193
1194//-------------------------------------------------------------------------
1195// CommandObjectProcessInterrupt
1196//-------------------------------------------------------------------------
1197#pragma mark CommandObjectProcessInterrupt
1198
1199class CommandObjectProcessInterrupt : public CommandObject
1200{
1201public:
1202
1203
1204    CommandObjectProcessInterrupt (CommandInterpreter &interpreter) :
1205    CommandObject (interpreter,
1206                   "process interrupt",
1207                   "Interrupt the current process being debugged.",
1208                   "process interrupt",
1209                   eFlagProcessMustBeLaunched)
1210    {
1211    }
1212
1213    ~CommandObjectProcessInterrupt ()
1214    {
1215    }
1216
1217    bool
1218    Execute (Args& command,
1219             CommandReturnObject &result)
1220    {
1221        Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
1222        if (process == NULL)
1223        {
1224            result.AppendError ("no process to halt");
1225            result.SetStatus (eReturnStatusFailed);
1226            return false;
1227        }
1228
1229        if (command.GetArgumentCount() == 0)
1230        {
1231            Error error(process->Halt ());
1232            if (error.Success())
1233            {
1234                result.SetStatus (eReturnStatusSuccessFinishResult);
1235
1236                // Maybe we should add a "SuspendThreadPlans so we
1237                // can halt, and keep in place all the current thread plans.
1238                process->GetThreadList().DiscardThreadPlans();
1239            }
1240            else
1241            {
1242                result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString());
1243                result.SetStatus (eReturnStatusFailed);
1244            }
1245        }
1246        else
1247        {
1248            result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n",
1249                                        m_cmd_name.c_str(),
1250                                        m_cmd_syntax.c_str());
1251            result.SetStatus (eReturnStatusFailed);
1252        }
1253        return result.Succeeded();
1254    }
1255};
1256
1257//-------------------------------------------------------------------------
1258// CommandObjectProcessKill
1259//-------------------------------------------------------------------------
1260#pragma mark CommandObjectProcessKill
1261
1262class CommandObjectProcessKill : public CommandObject
1263{
1264public:
1265
1266    CommandObjectProcessKill (CommandInterpreter &interpreter) :
1267    CommandObject (interpreter,
1268                   "process kill",
1269                   "Terminate the current process being debugged.",
1270                   "process kill",
1271                   eFlagProcessMustBeLaunched)
1272    {
1273    }
1274
1275    ~CommandObjectProcessKill ()
1276    {
1277    }
1278
1279    bool
1280    Execute (Args& command,
1281             CommandReturnObject &result)
1282    {
1283        Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
1284        if (process == NULL)
1285        {
1286            result.AppendError ("no process to kill");
1287            result.SetStatus (eReturnStatusFailed);
1288            return false;
1289        }
1290
1291        if (command.GetArgumentCount() == 0)
1292        {
1293            Error error (process->Destroy());
1294            if (error.Success())
1295            {
1296                result.SetStatus (eReturnStatusSuccessFinishResult);
1297            }
1298            else
1299            {
1300                result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString());
1301                result.SetStatus (eReturnStatusFailed);
1302            }
1303        }
1304        else
1305        {
1306            result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n",
1307                                        m_cmd_name.c_str(),
1308                                        m_cmd_syntax.c_str());
1309            result.SetStatus (eReturnStatusFailed);
1310        }
1311        return result.Succeeded();
1312    }
1313};
1314
1315//-------------------------------------------------------------------------
1316// CommandObjectProcessStatus
1317//-------------------------------------------------------------------------
1318#pragma mark CommandObjectProcessStatus
1319
1320class CommandObjectProcessStatus : public CommandObject
1321{
1322public:
1323    CommandObjectProcessStatus (CommandInterpreter &interpreter) :
1324    CommandObject (interpreter,
1325                   "process status",
1326                   "Show the current status and location of executing process.",
1327                   "process status",
1328                   0)
1329    {
1330    }
1331
1332    ~CommandObjectProcessStatus()
1333    {
1334    }
1335
1336
1337    bool
1338    Execute
1339    (
1340        Args& command,
1341        CommandReturnObject &result
1342    )
1343    {
1344        Stream &strm = result.GetOutputStream();
1345        result.SetStatus (eReturnStatusSuccessFinishNoResult);
1346        ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
1347        Process *process = exe_ctx.GetProcessPtr();
1348        if (process)
1349        {
1350            const bool only_threads_with_stop_reason = true;
1351            const uint32_t start_frame = 0;
1352            const uint32_t num_frames = 1;
1353            const uint32_t num_frames_with_source = 1;
1354            process->GetStatus(strm);
1355            process->GetThreadStatus (strm,
1356                                      only_threads_with_stop_reason,
1357                                      start_frame,
1358                                      num_frames,
1359                                      num_frames_with_source);
1360
1361        }
1362        else
1363        {
1364            result.AppendError ("No process.");
1365            result.SetStatus (eReturnStatusFailed);
1366        }
1367        return result.Succeeded();
1368    }
1369};
1370
1371//-------------------------------------------------------------------------
1372// CommandObjectProcessHandle
1373//-------------------------------------------------------------------------
1374#pragma mark CommandObjectProcessHandle
1375
1376class CommandObjectProcessHandle : public CommandObject
1377{
1378public:
1379
1380    class CommandOptions : public Options
1381    {
1382    public:
1383
1384        CommandOptions (CommandInterpreter &interpreter) :
1385            Options (interpreter)
1386        {
1387            OptionParsingStarting ();
1388        }
1389
1390        ~CommandOptions ()
1391        {
1392        }
1393
1394        Error
1395        SetOptionValue (uint32_t option_idx, const char *option_arg)
1396        {
1397            Error error;
1398            char short_option = (char) m_getopt_table[option_idx].val;
1399
1400            switch (short_option)
1401            {
1402                case 's':
1403                    stop = option_arg;
1404                    break;
1405                case 'n':
1406                    notify = option_arg;
1407                    break;
1408                case 'p':
1409                    pass = option_arg;
1410                    break;
1411                default:
1412                    error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
1413                    break;
1414            }
1415            return error;
1416        }
1417
1418        void
1419        OptionParsingStarting ()
1420        {
1421            stop.clear();
1422            notify.clear();
1423            pass.clear();
1424        }
1425
1426        const OptionDefinition*
1427        GetDefinitions ()
1428        {
1429            return g_option_table;
1430        }
1431
1432        // Options table: Required for subclasses of Options.
1433
1434        static OptionDefinition g_option_table[];
1435
1436        // Instance variables to hold the values for command options.
1437
1438        std::string stop;
1439        std::string notify;
1440        std::string pass;
1441    };
1442
1443
1444    CommandObjectProcessHandle (CommandInterpreter &interpreter) :
1445        CommandObject (interpreter,
1446                       "process handle",
1447                       "Show or update what the process and debugger should do with various signals received from the OS.",
1448                       NULL),
1449        m_options (interpreter)
1450    {
1451        SetHelpLong ("If no signals are specified, update them all.  If no update option is specified, list the current values.\n");
1452        CommandArgumentEntry arg;
1453        CommandArgumentData signal_arg;
1454
1455        signal_arg.arg_type = eArgTypeUnixSignal;
1456        signal_arg.arg_repetition = eArgRepeatStar;
1457
1458        arg.push_back (signal_arg);
1459
1460        m_arguments.push_back (arg);
1461    }
1462
1463    ~CommandObjectProcessHandle ()
1464    {
1465    }
1466
1467    Options *
1468    GetOptions ()
1469    {
1470        return &m_options;
1471    }
1472
1473    bool
1474    VerifyCommandOptionValue (const std::string &option, int &real_value)
1475    {
1476        bool okay = true;
1477
1478        bool success = false;
1479        bool tmp_value = Args::StringToBoolean (option.c_str(), false, &success);
1480
1481        if (success && tmp_value)
1482            real_value = 1;
1483        else if (success && !tmp_value)
1484            real_value = 0;
1485        else
1486        {
1487            // If the value isn't 'true' or 'false', it had better be 0 or 1.
1488            real_value = Args::StringToUInt32 (option.c_str(), 3);
1489            if (real_value != 0 && real_value != 1)
1490                okay = false;
1491        }
1492
1493        return okay;
1494    }
1495
1496    void
1497    PrintSignalHeader (Stream &str)
1498    {
1499        str.Printf ("NAME        PASS   STOP   NOTIFY\n");
1500        str.Printf ("==========  =====  =====  ======\n");
1501    }
1502
1503    void
1504    PrintSignal (Stream &str, int32_t signo, const char *sig_name, UnixSignals &signals)
1505    {
1506        bool stop;
1507        bool suppress;
1508        bool notify;
1509
1510        str.Printf ("%-10s  ", sig_name);
1511        if (signals.GetSignalInfo (signo, suppress, stop, notify))
1512        {
1513            bool pass = !suppress;
1514            str.Printf ("%s  %s  %s",
1515                        (pass ? "true " : "false"),
1516                        (stop ? "true " : "false"),
1517                        (notify ? "true " : "false"));
1518        }
1519        str.Printf ("\n");
1520    }
1521
1522    void
1523    PrintSignalInformation (Stream &str, Args &signal_args, int num_valid_signals, UnixSignals &signals)
1524    {
1525        PrintSignalHeader (str);
1526
1527        if (num_valid_signals > 0)
1528        {
1529            size_t num_args = signal_args.GetArgumentCount();
1530            for (size_t i = 0; i < num_args; ++i)
1531            {
1532                int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
1533                if (signo != LLDB_INVALID_SIGNAL_NUMBER)
1534                    PrintSignal (str, signo, signal_args.GetArgumentAtIndex (i), signals);
1535            }
1536        }
1537        else // Print info for ALL signals
1538        {
1539            int32_t signo = signals.GetFirstSignalNumber();
1540            while (signo != LLDB_INVALID_SIGNAL_NUMBER)
1541            {
1542                PrintSignal (str, signo, signals.GetSignalAsCString (signo), signals);
1543                signo = signals.GetNextSignalNumber (signo);
1544            }
1545        }
1546    }
1547
1548    bool
1549    Execute (Args &signal_args, CommandReturnObject &result)
1550    {
1551        TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
1552
1553        if (!target_sp)
1554        {
1555            result.AppendError ("No current target;"
1556                                " cannot handle signals until you have a valid target and process.\n");
1557            result.SetStatus (eReturnStatusFailed);
1558            return false;
1559        }
1560
1561        ProcessSP process_sp = target_sp->GetProcessSP();
1562
1563        if (!process_sp)
1564        {
1565            result.AppendError ("No current process; cannot handle signals until you have a valid process.\n");
1566            result.SetStatus (eReturnStatusFailed);
1567            return false;
1568        }
1569
1570        int stop_action = -1;   // -1 means leave the current setting alone
1571        int pass_action = -1;   // -1 means leave the current setting alone
1572        int notify_action = -1; // -1 means leave the current setting alone
1573
1574        if (! m_options.stop.empty()
1575            && ! VerifyCommandOptionValue (m_options.stop, stop_action))
1576        {
1577            result.AppendError ("Invalid argument for command option --stop; must be true or false.\n");
1578            result.SetStatus (eReturnStatusFailed);
1579            return false;
1580        }
1581
1582        if (! m_options.notify.empty()
1583            && ! VerifyCommandOptionValue (m_options.notify, notify_action))
1584        {
1585            result.AppendError ("Invalid argument for command option --notify; must be true or false.\n");
1586            result.SetStatus (eReturnStatusFailed);
1587            return false;
1588        }
1589
1590        if (! m_options.pass.empty()
1591            && ! VerifyCommandOptionValue (m_options.pass, pass_action))
1592        {
1593            result.AppendError ("Invalid argument for command option --pass; must be true or false.\n");
1594            result.SetStatus (eReturnStatusFailed);
1595            return false;
1596        }
1597
1598        size_t num_args = signal_args.GetArgumentCount();
1599        UnixSignals &signals = process_sp->GetUnixSignals();
1600        int num_signals_set = 0;
1601
1602        if (num_args > 0)
1603        {
1604            for (size_t i = 0; i < num_args; ++i)
1605            {
1606                int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
1607                if (signo != LLDB_INVALID_SIGNAL_NUMBER)
1608                {
1609                    // Casting the actions as bools here should be okay, because VerifyCommandOptionValue guarantees
1610                    // the value is either 0 or 1.
1611                    if (stop_action != -1)
1612                        signals.SetShouldStop (signo, (bool) stop_action);
1613                    if (pass_action != -1)
1614                    {
1615                        bool suppress = ! ((bool) pass_action);
1616                        signals.SetShouldSuppress (signo, suppress);
1617                    }
1618                    if (notify_action != -1)
1619                        signals.SetShouldNotify (signo, (bool) notify_action);
1620                    ++num_signals_set;
1621                }
1622                else
1623                {
1624                    result.AppendErrorWithFormat ("Invalid signal name '%s'\n", signal_args.GetArgumentAtIndex (i));
1625                }
1626            }
1627        }
1628        else
1629        {
1630            // No signal specified, if any command options were specified, update ALL signals.
1631            if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1))
1632            {
1633                if (m_interpreter.Confirm ("Do you really want to update all the signals?", false))
1634                {
1635                    int32_t signo = signals.GetFirstSignalNumber();
1636                    while (signo != LLDB_INVALID_SIGNAL_NUMBER)
1637                    {
1638                        if (notify_action != -1)
1639                            signals.SetShouldNotify (signo, (bool) notify_action);
1640                        if (stop_action != -1)
1641                            signals.SetShouldStop (signo, (bool) stop_action);
1642                        if (pass_action != -1)
1643                        {
1644                            bool suppress = ! ((bool) pass_action);
1645                            signals.SetShouldSuppress (signo, suppress);
1646                        }
1647                        signo = signals.GetNextSignalNumber (signo);
1648                    }
1649                }
1650            }
1651        }
1652
1653        PrintSignalInformation (result.GetOutputStream(), signal_args, num_signals_set, signals);
1654
1655        if (num_signals_set > 0)
1656            result.SetStatus (eReturnStatusSuccessFinishNoResult);
1657        else
1658            result.SetStatus (eReturnStatusFailed);
1659
1660        return result.Succeeded();
1661    }
1662
1663protected:
1664
1665    CommandOptions m_options;
1666};
1667
1668OptionDefinition
1669CommandObjectProcessHandle::CommandOptions::g_option_table[] =
1670{
1671{ LLDB_OPT_SET_1, false, "stop",   's', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the process should be stopped if the signal is received." },
1672{ LLDB_OPT_SET_1, false, "notify", 'n', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the debugger should notify the user if the signal is received." },
1673{ LLDB_OPT_SET_1, false, "pass",  'p', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." },
1674{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1675};
1676
1677//-------------------------------------------------------------------------
1678// CommandObjectMultiwordProcess
1679//-------------------------------------------------------------------------
1680
1681CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter &interpreter) :
1682    CommandObjectMultiword (interpreter,
1683                            "process",
1684                            "A set of commands for operating on a process.",
1685                            "process <subcommand> [<subcommand-options>]")
1686{
1687    LoadSubCommand ("attach",      CommandObjectSP (new CommandObjectProcessAttach    (interpreter)));
1688    LoadSubCommand ("launch",      CommandObjectSP (new CommandObjectProcessLaunch    (interpreter)));
1689    LoadSubCommand ("continue",    CommandObjectSP (new CommandObjectProcessContinue  (interpreter)));
1690    LoadSubCommand ("connect",     CommandObjectSP (new CommandObjectProcessConnect   (interpreter)));
1691    LoadSubCommand ("detach",      CommandObjectSP (new CommandObjectProcessDetach    (interpreter)));
1692    LoadSubCommand ("load",        CommandObjectSP (new CommandObjectProcessLoad      (interpreter)));
1693    LoadSubCommand ("unload",      CommandObjectSP (new CommandObjectProcessUnload    (interpreter)));
1694    LoadSubCommand ("signal",      CommandObjectSP (new CommandObjectProcessSignal    (interpreter)));
1695    LoadSubCommand ("handle",      CommandObjectSP (new CommandObjectProcessHandle    (interpreter)));
1696    LoadSubCommand ("status",      CommandObjectSP (new CommandObjectProcessStatus    (interpreter)));
1697    LoadSubCommand ("interrupt",   CommandObjectSP (new CommandObjectProcessInterrupt (interpreter)));
1698    LoadSubCommand ("kill",        CommandObjectSP (new CommandObjectProcessKill      (interpreter)));
1699}
1700
1701CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess ()
1702{
1703}
1704
1705