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