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