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