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