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