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