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