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