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