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