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