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