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