xref: /llvm-project/lldb/source/Commands/CommandObjectProcess.cpp (revision cd16df9154d46bb4ff49ed8843df714a7376d072)
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                         result.SetStatus (eReturnStatusFailed);
570                         return false;
571                     }
572                 }
573             }
574         }
575 
576         if (result.Succeeded())
577         {
578             // Okay, we're done.  Last step is to warn if the executable module has changed:
579             char new_path[PATH_MAX];
580             ModuleSP new_exec_module_sp (target->GetExecutableModule());
581             if (!old_exec_module_sp)
582             {
583                 // We might not have a module if we attached to a raw pid...
584                 if (new_exec_module_sp)
585                 {
586                     new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX);
587                     result.AppendMessageWithFormat("Executable module set to \"%s\".\n", new_path);
588                 }
589             }
590             else if (old_exec_module_sp->GetFileSpec() != new_exec_module_sp->GetFileSpec())
591             {
592                 char old_path[PATH_MAX];
593 
594                 old_exec_module_sp->GetFileSpec().GetPath (old_path, PATH_MAX);
595                 new_exec_module_sp->GetFileSpec().GetPath (new_path, PATH_MAX);
596 
597                 result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n",
598                                                     old_path, new_path);
599             }
600 
601             if (!old_arch_spec.IsValid())
602             {
603                 result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().GetArchitectureName());
604             }
605             else if (old_arch_spec != target->GetArchitecture())
606             {
607                 result.AppendWarningWithFormat("Architecture changed from %s to %s.\n",
608                                                 old_arch_spec.GetArchitectureName(), target->GetArchitecture().GetArchitectureName());
609             }
610 
611             // This supports the use-case scenario of immediately continuing the process once attached.
612             if (m_options.attach_info.GetContinueOnceAttached())
613                 m_interpreter.HandleCommand("process continue", eLazyBoolNo, result);
614         }
615         return result.Succeeded();
616     }
617 
618     CommandOptions m_options;
619 };
620 
621 
622 OptionDefinition
623 CommandObjectProcessAttach::CommandOptions::g_option_table[] =
624 {
625 { LLDB_OPT_SET_ALL, false, "continue",'c', no_argument,         NULL, 0, eArgTypeNone,         "Immediately continue the process once attached."},
626 { LLDB_OPT_SET_ALL, false, "plugin",  'P', required_argument,   NULL, 0, eArgTypePlugin,       "Name of the process plugin you want to use."},
627 { LLDB_OPT_SET_1,   false, "pid",     'p', required_argument,   NULL, 0, eArgTypePid,          "The process ID of an existing process to attach to."},
628 { LLDB_OPT_SET_2,   false, "name",    'n', required_argument,   NULL, 0, eArgTypeProcessName,  "The name of the process to attach to."},
629 { LLDB_OPT_SET_2,   false, "include-existing", 'i', no_argument, NULL, 0, eArgTypeNone,         "Include existing processes when doing attach -w."},
630 { LLDB_OPT_SET_2,   false, "waitfor", 'w', no_argument,         NULL, 0, eArgTypeNone,         "Wait for the process with <process-name> to launch."},
631 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
632 };
633 
634 //-------------------------------------------------------------------------
635 // CommandObjectProcessContinue
636 //-------------------------------------------------------------------------
637 #pragma mark CommandObjectProcessContinue
638 
639 class CommandObjectProcessContinue : public CommandObjectParsed
640 {
641 public:
642 
643     CommandObjectProcessContinue (CommandInterpreter &interpreter) :
644         CommandObjectParsed (interpreter,
645                              "process continue",
646                              "Continue execution of all threads in the current process.",
647                              "process continue",
648                              eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
649     {
650     }
651 
652 
653     ~CommandObjectProcessContinue ()
654     {
655     }
656 
657 protected:
658     bool
659     DoExecute (Args& command,
660              CommandReturnObject &result)
661     {
662         Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
663         bool synchronous_execution = m_interpreter.GetSynchronous ();
664 
665         if (process == NULL)
666         {
667             result.AppendError ("no process to continue");
668             result.SetStatus (eReturnStatusFailed);
669             return false;
670          }
671 
672         StateType state = process->GetState();
673         if (state == eStateStopped)
674         {
675             if (command.GetArgumentCount() != 0)
676             {
677                 result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str());
678                 result.SetStatus (eReturnStatusFailed);
679                 return false;
680             }
681 
682             const uint32_t num_threads = process->GetThreadList().GetSize();
683 
684             // Set the actions that the threads should each take when resuming
685             for (uint32_t idx=0; idx<num_threads; ++idx)
686             {
687                 process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning);
688             }
689 
690             Error error(process->Resume());
691             if (error.Success())
692             {
693                 result.AppendMessageWithFormat ("Process %llu resuming\n", process->GetID());
694                 if (synchronous_execution)
695                 {
696                     state = process->WaitForProcessToStop (NULL);
697 
698                     result.SetDidChangeProcessState (true);
699                     result.AppendMessageWithFormat ("Process %llu %s\n", process->GetID(), StateAsCString (state));
700                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
701                 }
702                 else
703                 {
704                     result.SetStatus (eReturnStatusSuccessContinuingNoResult);
705                 }
706             }
707             else
708             {
709                 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
710                 result.SetStatus (eReturnStatusFailed);
711             }
712         }
713         else
714         {
715             result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
716                                          StateAsCString(state));
717             result.SetStatus (eReturnStatusFailed);
718         }
719         return result.Succeeded();
720     }
721 };
722 
723 //-------------------------------------------------------------------------
724 // CommandObjectProcessDetach
725 //-------------------------------------------------------------------------
726 #pragma mark CommandObjectProcessDetach
727 
728 class CommandObjectProcessDetach : public CommandObjectParsed
729 {
730 public:
731 
732     CommandObjectProcessDetach (CommandInterpreter &interpreter) :
733         CommandObjectParsed (interpreter,
734                              "process detach",
735                              "Detach from the current process being debugged.",
736                              "process detach",
737                              eFlagProcessMustBeLaunched)
738     {
739     }
740 
741     ~CommandObjectProcessDetach ()
742     {
743     }
744 
745 protected:
746     bool
747     DoExecute (Args& command,
748              CommandReturnObject &result)
749     {
750         Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
751         if (process == NULL)
752         {
753             result.AppendError ("must have a valid process in order to detach");
754             result.SetStatus (eReturnStatusFailed);
755             return false;
756         }
757 
758         result.AppendMessageWithFormat ("Detaching from process %llu\n", process->GetID());
759         Error error (process->Detach());
760         if (error.Success())
761         {
762             result.SetStatus (eReturnStatusSuccessFinishResult);
763         }
764         else
765         {
766             result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString());
767             result.SetStatus (eReturnStatusFailed);
768             return false;
769         }
770         return result.Succeeded();
771     }
772 };
773 
774 //-------------------------------------------------------------------------
775 // CommandObjectProcessConnect
776 //-------------------------------------------------------------------------
777 #pragma mark CommandObjectProcessConnect
778 
779 class CommandObjectProcessConnect : public CommandObjectParsed
780 {
781 public:
782 
783     class CommandOptions : public Options
784     {
785     public:
786 
787         CommandOptions (CommandInterpreter &interpreter) :
788             Options(interpreter)
789         {
790             // Keep default values of all options in one place: OptionParsingStarting ()
791             OptionParsingStarting ();
792         }
793 
794         ~CommandOptions ()
795         {
796         }
797 
798         Error
799         SetOptionValue (uint32_t option_idx, const char *option_arg)
800         {
801             Error error;
802             char short_option = (char) m_getopt_table[option_idx].val;
803 
804             switch (short_option)
805             {
806             case 'p':
807                 plugin_name.assign (option_arg);
808                 break;
809 
810             default:
811                 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
812                 break;
813             }
814             return error;
815         }
816 
817         void
818         OptionParsingStarting ()
819         {
820             plugin_name.clear();
821         }
822 
823         const OptionDefinition*
824         GetDefinitions ()
825         {
826             return g_option_table;
827         }
828 
829         // Options table: Required for subclasses of Options.
830 
831         static OptionDefinition g_option_table[];
832 
833         // Instance variables to hold the values for command options.
834 
835         std::string plugin_name;
836     };
837 
838     CommandObjectProcessConnect (CommandInterpreter &interpreter) :
839         CommandObjectParsed (interpreter,
840                              "process connect",
841                              "Connect to a remote debug service.",
842                              "process connect <remote-url>",
843                              0),
844         m_options (interpreter)
845     {
846     }
847 
848     ~CommandObjectProcessConnect ()
849     {
850     }
851 
852 
853     Options *
854     GetOptions ()
855     {
856         return &m_options;
857     }
858 
859 protected:
860     bool
861     DoExecute (Args& command,
862              CommandReturnObject &result)
863     {
864 
865         TargetSP target_sp (m_interpreter.GetDebugger().GetSelectedTarget());
866         Error error;
867         Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
868         if (process)
869         {
870             if (process->IsAlive())
871             {
872                 result.AppendErrorWithFormat ("Process %llu is currently being debugged, kill the process before connecting.\n",
873                                               process->GetID());
874                 result.SetStatus (eReturnStatusFailed);
875                 return false;
876             }
877         }
878 
879         if (!target_sp)
880         {
881             // If there isn't a current target create one.
882             FileSpec emptyFileSpec;
883 
884             error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(),
885                                                                               emptyFileSpec,
886                                                                               NULL,
887                                                                               false,
888                                                                               NULL, // No platform options
889                                                                               target_sp);
890             if (!target_sp || error.Fail())
891             {
892                 result.AppendError(error.AsCString("Error creating target"));
893                 result.SetStatus (eReturnStatusFailed);
894                 return false;
895             }
896             m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target_sp.get());
897         }
898 
899         if (command.GetArgumentCount() == 1)
900         {
901             const char *plugin_name = NULL;
902             if (!m_options.plugin_name.empty())
903                 plugin_name = m_options.plugin_name.c_str();
904 
905             const char *remote_url = command.GetArgumentAtIndex(0);
906             process = target_sp->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name, NULL).get();
907 
908             if (process)
909             {
910                 error = process->ConnectRemote (remote_url);
911 
912                 if (error.Fail())
913                 {
914                     result.AppendError(error.AsCString("Remote connect failed"));
915                     result.SetStatus (eReturnStatusFailed);
916                     target_sp->DeleteCurrentProcess();
917                     return false;
918                 }
919             }
920             else
921             {
922                 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",
923                                               m_cmd_name.c_str());
924                 result.SetStatus (eReturnStatusFailed);
925             }
926         }
927         else
928         {
929             result.AppendErrorWithFormat ("'%s' takes exactly one argument:\nUsage: %s\n",
930                                           m_cmd_name.c_str(),
931                                           m_cmd_syntax.c_str());
932             result.SetStatus (eReturnStatusFailed);
933         }
934         return result.Succeeded();
935     }
936 
937     CommandOptions m_options;
938 };
939 
940 
941 OptionDefinition
942 CommandObjectProcessConnect::CommandOptions::g_option_table[] =
943 {
944     { LLDB_OPT_SET_ALL, false, "plugin", 'p', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
945     { 0,                false, NULL,      0 , 0,                 NULL, 0, eArgTypeNone,   NULL }
946 };
947 
948 //-------------------------------------------------------------------------
949 // CommandObjectProcessLoad
950 //-------------------------------------------------------------------------
951 #pragma mark CommandObjectProcessLoad
952 
953 class CommandObjectProcessLoad : public CommandObjectParsed
954 {
955 public:
956 
957     CommandObjectProcessLoad (CommandInterpreter &interpreter) :
958         CommandObjectParsed (interpreter,
959                              "process load",
960                              "Load a shared library into the current process.",
961                              "process load <filename> [<filename> ...]",
962                              eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
963     {
964     }
965 
966     ~CommandObjectProcessLoad ()
967     {
968     }
969 
970 protected:
971     bool
972     DoExecute (Args& command,
973              CommandReturnObject &result)
974     {
975         Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
976         if (process == NULL)
977         {
978             result.AppendError ("must have a valid process in order to load a shared library");
979             result.SetStatus (eReturnStatusFailed);
980             return false;
981         }
982 
983         const uint32_t argc = command.GetArgumentCount();
984 
985         for (uint32_t i=0; i<argc; ++i)
986         {
987             Error error;
988             const char *image_path = command.GetArgumentAtIndex(i);
989             FileSpec image_spec (image_path, false);
990             process->GetTarget().GetPlatform()->ResolveRemotePath(image_spec, image_spec);
991             uint32_t image_token = process->LoadImage(image_spec, error);
992             if (image_token != LLDB_INVALID_IMAGE_TOKEN)
993             {
994                 result.AppendMessageWithFormat ("Loading \"%s\"...ok\nImage %u loaded.\n", image_path, image_token);
995                 result.SetStatus (eReturnStatusSuccessFinishResult);
996             }
997             else
998             {
999                 result.AppendErrorWithFormat ("failed to load '%s': %s", image_path, error.AsCString());
1000                 result.SetStatus (eReturnStatusFailed);
1001             }
1002         }
1003         return result.Succeeded();
1004     }
1005 };
1006 
1007 
1008 //-------------------------------------------------------------------------
1009 // CommandObjectProcessUnload
1010 //-------------------------------------------------------------------------
1011 #pragma mark CommandObjectProcessUnload
1012 
1013 class CommandObjectProcessUnload : public CommandObjectParsed
1014 {
1015 public:
1016 
1017     CommandObjectProcessUnload (CommandInterpreter &interpreter) :
1018         CommandObjectParsed (interpreter,
1019                              "process unload",
1020                              "Unload a shared library from the current process using the index returned by a previous call to \"process load\".",
1021                              "process unload <index>",
1022                              eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
1023     {
1024     }
1025 
1026     ~CommandObjectProcessUnload ()
1027     {
1028     }
1029 
1030 protected:
1031     bool
1032     DoExecute (Args& command,
1033              CommandReturnObject &result)
1034     {
1035         Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
1036         if (process == NULL)
1037         {
1038             result.AppendError ("must have a valid process in order to load a shared library");
1039             result.SetStatus (eReturnStatusFailed);
1040             return false;
1041         }
1042 
1043         const uint32_t argc = command.GetArgumentCount();
1044 
1045         for (uint32_t i=0; i<argc; ++i)
1046         {
1047             const char *image_token_cstr = command.GetArgumentAtIndex(i);
1048             uint32_t image_token = Args::StringToUInt32(image_token_cstr, LLDB_INVALID_IMAGE_TOKEN, 0);
1049             if (image_token == LLDB_INVALID_IMAGE_TOKEN)
1050             {
1051                 result.AppendErrorWithFormat ("invalid image index argument '%s'", image_token_cstr);
1052                 result.SetStatus (eReturnStatusFailed);
1053                 break;
1054             }
1055             else
1056             {
1057                 Error error (process->UnloadImage(image_token));
1058                 if (error.Success())
1059                 {
1060                     result.AppendMessageWithFormat ("Unloading shared library with index %u...ok\n", image_token);
1061                     result.SetStatus (eReturnStatusSuccessFinishResult);
1062                 }
1063                 else
1064                 {
1065                     result.AppendErrorWithFormat ("failed to unload image: %s", error.AsCString());
1066                     result.SetStatus (eReturnStatusFailed);
1067                     break;
1068                 }
1069             }
1070         }
1071         return result.Succeeded();
1072     }
1073 };
1074 
1075 //-------------------------------------------------------------------------
1076 // CommandObjectProcessSignal
1077 //-------------------------------------------------------------------------
1078 #pragma mark CommandObjectProcessSignal
1079 
1080 class CommandObjectProcessSignal : public CommandObjectParsed
1081 {
1082 public:
1083 
1084     CommandObjectProcessSignal (CommandInterpreter &interpreter) :
1085         CommandObjectParsed (interpreter,
1086                              "process signal",
1087                              "Send a UNIX signal to the current process being debugged.",
1088                              NULL)
1089     {
1090         CommandArgumentEntry arg;
1091         CommandArgumentData signal_arg;
1092 
1093         // Define the first (and only) variant of this arg.
1094         signal_arg.arg_type = eArgTypeUnixSignal;
1095         signal_arg.arg_repetition = eArgRepeatPlain;
1096 
1097         // There is only one variant this argument could be; put it into the argument entry.
1098         arg.push_back (signal_arg);
1099 
1100         // Push the data for the first argument into the m_arguments vector.
1101         m_arguments.push_back (arg);
1102     }
1103 
1104     ~CommandObjectProcessSignal ()
1105     {
1106     }
1107 
1108 protected:
1109     bool
1110     DoExecute (Args& command,
1111              CommandReturnObject &result)
1112     {
1113         Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
1114         if (process == NULL)
1115         {
1116             result.AppendError ("no process to signal");
1117             result.SetStatus (eReturnStatusFailed);
1118             return false;
1119         }
1120 
1121         if (command.GetArgumentCount() == 1)
1122         {
1123             int signo = LLDB_INVALID_SIGNAL_NUMBER;
1124 
1125             const char *signal_name = command.GetArgumentAtIndex(0);
1126             if (::isxdigit (signal_name[0]))
1127                 signo = Args::StringToSInt32(signal_name, LLDB_INVALID_SIGNAL_NUMBER, 0);
1128             else
1129                 signo = process->GetUnixSignals().GetSignalNumberFromName (signal_name);
1130 
1131             if (signo == LLDB_INVALID_SIGNAL_NUMBER)
1132             {
1133                 result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0));
1134                 result.SetStatus (eReturnStatusFailed);
1135             }
1136             else
1137             {
1138                 Error error (process->Signal (signo));
1139                 if (error.Success())
1140                 {
1141                     result.SetStatus (eReturnStatusSuccessFinishResult);
1142                 }
1143                 else
1144                 {
1145                     result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString());
1146                     result.SetStatus (eReturnStatusFailed);
1147                 }
1148             }
1149         }
1150         else
1151         {
1152             result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: %s\n", m_cmd_name.c_str(),
1153                                         m_cmd_syntax.c_str());
1154             result.SetStatus (eReturnStatusFailed);
1155         }
1156         return result.Succeeded();
1157     }
1158 };
1159 
1160 
1161 //-------------------------------------------------------------------------
1162 // CommandObjectProcessInterrupt
1163 //-------------------------------------------------------------------------
1164 #pragma mark CommandObjectProcessInterrupt
1165 
1166 class CommandObjectProcessInterrupt : public CommandObjectParsed
1167 {
1168 public:
1169 
1170 
1171     CommandObjectProcessInterrupt (CommandInterpreter &interpreter) :
1172         CommandObjectParsed (interpreter,
1173                              "process interrupt",
1174                              "Interrupt the current process being debugged.",
1175                              "process interrupt",
1176                              eFlagProcessMustBeLaunched)
1177     {
1178     }
1179 
1180     ~CommandObjectProcessInterrupt ()
1181     {
1182     }
1183 
1184 protected:
1185     bool
1186     DoExecute (Args& command,
1187              CommandReturnObject &result)
1188     {
1189         Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
1190         if (process == NULL)
1191         {
1192             result.AppendError ("no process to halt");
1193             result.SetStatus (eReturnStatusFailed);
1194             return false;
1195         }
1196 
1197         if (command.GetArgumentCount() == 0)
1198         {
1199             Error error(process->Halt ());
1200             if (error.Success())
1201             {
1202                 result.SetStatus (eReturnStatusSuccessFinishResult);
1203 
1204                 // Maybe we should add a "SuspendThreadPlans so we
1205                 // can halt, and keep in place all the current thread plans.
1206                 process->GetThreadList().DiscardThreadPlans();
1207             }
1208             else
1209             {
1210                 result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString());
1211                 result.SetStatus (eReturnStatusFailed);
1212             }
1213         }
1214         else
1215         {
1216             result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n",
1217                                         m_cmd_name.c_str(),
1218                                         m_cmd_syntax.c_str());
1219             result.SetStatus (eReturnStatusFailed);
1220         }
1221         return result.Succeeded();
1222     }
1223 };
1224 
1225 //-------------------------------------------------------------------------
1226 // CommandObjectProcessKill
1227 //-------------------------------------------------------------------------
1228 #pragma mark CommandObjectProcessKill
1229 
1230 class CommandObjectProcessKill : public CommandObjectParsed
1231 {
1232 public:
1233 
1234     CommandObjectProcessKill (CommandInterpreter &interpreter) :
1235         CommandObjectParsed (interpreter,
1236                              "process kill",
1237                              "Terminate the current process being debugged.",
1238                              "process kill",
1239                              eFlagProcessMustBeLaunched)
1240     {
1241     }
1242 
1243     ~CommandObjectProcessKill ()
1244     {
1245     }
1246 
1247 protected:
1248     bool
1249     DoExecute (Args& command,
1250              CommandReturnObject &result)
1251     {
1252         Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
1253         if (process == NULL)
1254         {
1255             result.AppendError ("no process to kill");
1256             result.SetStatus (eReturnStatusFailed);
1257             return false;
1258         }
1259 
1260         if (command.GetArgumentCount() == 0)
1261         {
1262             Error error (process->Destroy());
1263             if (error.Success())
1264             {
1265                 result.SetStatus (eReturnStatusSuccessFinishResult);
1266             }
1267             else
1268             {
1269                 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString());
1270                 result.SetStatus (eReturnStatusFailed);
1271             }
1272         }
1273         else
1274         {
1275             result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n",
1276                                         m_cmd_name.c_str(),
1277                                         m_cmd_syntax.c_str());
1278             result.SetStatus (eReturnStatusFailed);
1279         }
1280         return result.Succeeded();
1281     }
1282 };
1283 
1284 //-------------------------------------------------------------------------
1285 // CommandObjectProcessStatus
1286 //-------------------------------------------------------------------------
1287 #pragma mark CommandObjectProcessStatus
1288 
1289 class CommandObjectProcessStatus : public CommandObjectParsed
1290 {
1291 public:
1292     CommandObjectProcessStatus (CommandInterpreter &interpreter) :
1293         CommandObjectParsed (interpreter,
1294                              "process status",
1295                              "Show the current status and location of executing process.",
1296                              "process status",
1297                              0)
1298     {
1299     }
1300 
1301     ~CommandObjectProcessStatus()
1302     {
1303     }
1304 
1305 
1306     bool
1307     DoExecute (Args& command, CommandReturnObject &result)
1308     {
1309         Stream &strm = result.GetOutputStream();
1310         result.SetStatus (eReturnStatusSuccessFinishNoResult);
1311         ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
1312         Process *process = exe_ctx.GetProcessPtr();
1313         if (process)
1314         {
1315             const bool only_threads_with_stop_reason = true;
1316             const uint32_t start_frame = 0;
1317             const uint32_t num_frames = 1;
1318             const uint32_t num_frames_with_source = 1;
1319             process->GetStatus(strm);
1320             process->GetThreadStatus (strm,
1321                                       only_threads_with_stop_reason,
1322                                       start_frame,
1323                                       num_frames,
1324                                       num_frames_with_source);
1325 
1326         }
1327         else
1328         {
1329             result.AppendError ("No process.");
1330             result.SetStatus (eReturnStatusFailed);
1331         }
1332         return result.Succeeded();
1333     }
1334 };
1335 
1336 //-------------------------------------------------------------------------
1337 // CommandObjectProcessHandle
1338 //-------------------------------------------------------------------------
1339 #pragma mark CommandObjectProcessHandle
1340 
1341 class CommandObjectProcessHandle : public CommandObjectParsed
1342 {
1343 public:
1344 
1345     class CommandOptions : public Options
1346     {
1347     public:
1348 
1349         CommandOptions (CommandInterpreter &interpreter) :
1350             Options (interpreter)
1351         {
1352             OptionParsingStarting ();
1353         }
1354 
1355         ~CommandOptions ()
1356         {
1357         }
1358 
1359         Error
1360         SetOptionValue (uint32_t option_idx, const char *option_arg)
1361         {
1362             Error error;
1363             char short_option = (char) m_getopt_table[option_idx].val;
1364 
1365             switch (short_option)
1366             {
1367                 case 's':
1368                     stop = option_arg;
1369                     break;
1370                 case 'n':
1371                     notify = option_arg;
1372                     break;
1373                 case 'p':
1374                     pass = option_arg;
1375                     break;
1376                 default:
1377                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
1378                     break;
1379             }
1380             return error;
1381         }
1382 
1383         void
1384         OptionParsingStarting ()
1385         {
1386             stop.clear();
1387             notify.clear();
1388             pass.clear();
1389         }
1390 
1391         const OptionDefinition*
1392         GetDefinitions ()
1393         {
1394             return g_option_table;
1395         }
1396 
1397         // Options table: Required for subclasses of Options.
1398 
1399         static OptionDefinition g_option_table[];
1400 
1401         // Instance variables to hold the values for command options.
1402 
1403         std::string stop;
1404         std::string notify;
1405         std::string pass;
1406     };
1407 
1408 
1409     CommandObjectProcessHandle (CommandInterpreter &interpreter) :
1410         CommandObjectParsed (interpreter,
1411                              "process handle",
1412                              "Show or update what the process and debugger should do with various signals received from the OS.",
1413                              NULL),
1414         m_options (interpreter)
1415     {
1416         SetHelpLong ("If no signals are specified, update them all.  If no update option is specified, list the current values.\n");
1417         CommandArgumentEntry arg;
1418         CommandArgumentData signal_arg;
1419 
1420         signal_arg.arg_type = eArgTypeUnixSignal;
1421         signal_arg.arg_repetition = eArgRepeatStar;
1422 
1423         arg.push_back (signal_arg);
1424 
1425         m_arguments.push_back (arg);
1426     }
1427 
1428     ~CommandObjectProcessHandle ()
1429     {
1430     }
1431 
1432     Options *
1433     GetOptions ()
1434     {
1435         return &m_options;
1436     }
1437 
1438     bool
1439     VerifyCommandOptionValue (const std::string &option, int &real_value)
1440     {
1441         bool okay = true;
1442 
1443         bool success = false;
1444         bool tmp_value = Args::StringToBoolean (option.c_str(), false, &success);
1445 
1446         if (success && tmp_value)
1447             real_value = 1;
1448         else if (success && !tmp_value)
1449             real_value = 0;
1450         else
1451         {
1452             // If the value isn't 'true' or 'false', it had better be 0 or 1.
1453             real_value = Args::StringToUInt32 (option.c_str(), 3);
1454             if (real_value != 0 && real_value != 1)
1455                 okay = false;
1456         }
1457 
1458         return okay;
1459     }
1460 
1461     void
1462     PrintSignalHeader (Stream &str)
1463     {
1464         str.Printf ("NAME        PASS   STOP   NOTIFY\n");
1465         str.Printf ("==========  =====  =====  ======\n");
1466     }
1467 
1468     void
1469     PrintSignal (Stream &str, int32_t signo, const char *sig_name, UnixSignals &signals)
1470     {
1471         bool stop;
1472         bool suppress;
1473         bool notify;
1474 
1475         str.Printf ("%-10s  ", sig_name);
1476         if (signals.GetSignalInfo (signo, suppress, stop, notify))
1477         {
1478             bool pass = !suppress;
1479             str.Printf ("%s  %s  %s",
1480                         (pass ? "true " : "false"),
1481                         (stop ? "true " : "false"),
1482                         (notify ? "true " : "false"));
1483         }
1484         str.Printf ("\n");
1485     }
1486 
1487     void
1488     PrintSignalInformation (Stream &str, Args &signal_args, int num_valid_signals, UnixSignals &signals)
1489     {
1490         PrintSignalHeader (str);
1491 
1492         if (num_valid_signals > 0)
1493         {
1494             size_t num_args = signal_args.GetArgumentCount();
1495             for (size_t i = 0; i < num_args; ++i)
1496             {
1497                 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
1498                 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
1499                     PrintSignal (str, signo, signal_args.GetArgumentAtIndex (i), signals);
1500             }
1501         }
1502         else // Print info for ALL signals
1503         {
1504             int32_t signo = signals.GetFirstSignalNumber();
1505             while (signo != LLDB_INVALID_SIGNAL_NUMBER)
1506             {
1507                 PrintSignal (str, signo, signals.GetSignalAsCString (signo), signals);
1508                 signo = signals.GetNextSignalNumber (signo);
1509             }
1510         }
1511     }
1512 
1513 protected:
1514     bool
1515     DoExecute (Args &signal_args, CommandReturnObject &result)
1516     {
1517         TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
1518 
1519         if (!target_sp)
1520         {
1521             result.AppendError ("No current target;"
1522                                 " cannot handle signals until you have a valid target and process.\n");
1523             result.SetStatus (eReturnStatusFailed);
1524             return false;
1525         }
1526 
1527         ProcessSP process_sp = target_sp->GetProcessSP();
1528 
1529         if (!process_sp)
1530         {
1531             result.AppendError ("No current process; cannot handle signals until you have a valid process.\n");
1532             result.SetStatus (eReturnStatusFailed);
1533             return false;
1534         }
1535 
1536         int stop_action = -1;   // -1 means leave the current setting alone
1537         int pass_action = -1;   // -1 means leave the current setting alone
1538         int notify_action = -1; // -1 means leave the current setting alone
1539 
1540         if (! m_options.stop.empty()
1541             && ! VerifyCommandOptionValue (m_options.stop, stop_action))
1542         {
1543             result.AppendError ("Invalid argument for command option --stop; must be true or false.\n");
1544             result.SetStatus (eReturnStatusFailed);
1545             return false;
1546         }
1547 
1548         if (! m_options.notify.empty()
1549             && ! VerifyCommandOptionValue (m_options.notify, notify_action))
1550         {
1551             result.AppendError ("Invalid argument for command option --notify; must be true or false.\n");
1552             result.SetStatus (eReturnStatusFailed);
1553             return false;
1554         }
1555 
1556         if (! m_options.pass.empty()
1557             && ! VerifyCommandOptionValue (m_options.pass, pass_action))
1558         {
1559             result.AppendError ("Invalid argument for command option --pass; must be true or false.\n");
1560             result.SetStatus (eReturnStatusFailed);
1561             return false;
1562         }
1563 
1564         size_t num_args = signal_args.GetArgumentCount();
1565         UnixSignals &signals = process_sp->GetUnixSignals();
1566         int num_signals_set = 0;
1567 
1568         if (num_args > 0)
1569         {
1570             for (size_t i = 0; i < num_args; ++i)
1571             {
1572                 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
1573                 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
1574                 {
1575                     // Casting the actions as bools here should be okay, because VerifyCommandOptionValue guarantees
1576                     // the value is either 0 or 1.
1577                     if (stop_action != -1)
1578                         signals.SetShouldStop (signo, (bool) stop_action);
1579                     if (pass_action != -1)
1580                     {
1581                         bool suppress = ! ((bool) pass_action);
1582                         signals.SetShouldSuppress (signo, suppress);
1583                     }
1584                     if (notify_action != -1)
1585                         signals.SetShouldNotify (signo, (bool) notify_action);
1586                     ++num_signals_set;
1587                 }
1588                 else
1589                 {
1590                     result.AppendErrorWithFormat ("Invalid signal name '%s'\n", signal_args.GetArgumentAtIndex (i));
1591                 }
1592             }
1593         }
1594         else
1595         {
1596             // No signal specified, if any command options were specified, update ALL signals.
1597             if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1))
1598             {
1599                 if (m_interpreter.Confirm ("Do you really want to update all the signals?", false))
1600                 {
1601                     int32_t signo = signals.GetFirstSignalNumber();
1602                     while (signo != LLDB_INVALID_SIGNAL_NUMBER)
1603                     {
1604                         if (notify_action != -1)
1605                             signals.SetShouldNotify (signo, (bool) notify_action);
1606                         if (stop_action != -1)
1607                             signals.SetShouldStop (signo, (bool) stop_action);
1608                         if (pass_action != -1)
1609                         {
1610                             bool suppress = ! ((bool) pass_action);
1611                             signals.SetShouldSuppress (signo, suppress);
1612                         }
1613                         signo = signals.GetNextSignalNumber (signo);
1614                     }
1615                 }
1616             }
1617         }
1618 
1619         PrintSignalInformation (result.GetOutputStream(), signal_args, num_signals_set, signals);
1620 
1621         if (num_signals_set > 0)
1622             result.SetStatus (eReturnStatusSuccessFinishNoResult);
1623         else
1624             result.SetStatus (eReturnStatusFailed);
1625 
1626         return result.Succeeded();
1627     }
1628 
1629     CommandOptions m_options;
1630 };
1631 
1632 OptionDefinition
1633 CommandObjectProcessHandle::CommandOptions::g_option_table[] =
1634 {
1635 { 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." },
1636 { 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." },
1637 { LLDB_OPT_SET_1, false, "pass",  'p', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." },
1638 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1639 };
1640 
1641 //-------------------------------------------------------------------------
1642 // CommandObjectMultiwordProcess
1643 //-------------------------------------------------------------------------
1644 
1645 CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter &interpreter) :
1646     CommandObjectMultiword (interpreter,
1647                             "process",
1648                             "A set of commands for operating on a process.",
1649                             "process <subcommand> [<subcommand-options>]")
1650 {
1651     LoadSubCommand ("attach",      CommandObjectSP (new CommandObjectProcessAttach    (interpreter)));
1652     LoadSubCommand ("launch",      CommandObjectSP (new CommandObjectProcessLaunch    (interpreter)));
1653     LoadSubCommand ("continue",    CommandObjectSP (new CommandObjectProcessContinue  (interpreter)));
1654     LoadSubCommand ("connect",     CommandObjectSP (new CommandObjectProcessConnect   (interpreter)));
1655     LoadSubCommand ("detach",      CommandObjectSP (new CommandObjectProcessDetach    (interpreter)));
1656     LoadSubCommand ("load",        CommandObjectSP (new CommandObjectProcessLoad      (interpreter)));
1657     LoadSubCommand ("unload",      CommandObjectSP (new CommandObjectProcessUnload    (interpreter)));
1658     LoadSubCommand ("signal",      CommandObjectSP (new CommandObjectProcessSignal    (interpreter)));
1659     LoadSubCommand ("handle",      CommandObjectSP (new CommandObjectProcessHandle    (interpreter)));
1660     LoadSubCommand ("status",      CommandObjectSP (new CommandObjectProcessStatus    (interpreter)));
1661     LoadSubCommand ("interrupt",   CommandObjectSP (new CommandObjectProcessInterrupt (interpreter)));
1662     LoadSubCommand ("kill",        CommandObjectSP (new CommandObjectProcessKill      (interpreter)));
1663 }
1664 
1665 CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess ()
1666 {
1667 }
1668 
1669