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