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