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