xref: /llvm-project/lldb/source/Commands/CommandObjectProcess.cpp (revision 405fe67f1424284173459575b1081f42935c50fd)
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/Target/Process.h"
23 #include "lldb/Target/Target.h"
24 #include "lldb/Target/Thread.h"
25 
26 using namespace lldb;
27 using namespace lldb_private;
28 
29 //-------------------------------------------------------------------------
30 // CommandObjectProcessLaunch
31 //-------------------------------------------------------------------------
32 
33 class CommandObjectProcessLaunch : public CommandObject
34 {
35 public:
36 
37     class CommandOptions : public Options
38     {
39     public:
40 
41         CommandOptions () :
42             Options()
43         {
44             // Keep default values of all options in one place: ResetOptionValues ()
45             ResetOptionValues ();
46         }
47 
48         ~CommandOptions ()
49         {
50         }
51 
52         Error
53         SetOptionValue (int option_idx, const char *option_arg)
54         {
55             Error error;
56             char short_option = (char) m_getopt_table[option_idx].val;
57 
58             switch (short_option)
59             {
60                 case 's':   stop_at_entry = true;       break;
61                 case 'e':   stderr_path = option_arg;   break;
62                 case 'i':   stdin_path  = option_arg;   break;
63                 case 'o':   stdout_path = option_arg;   break;
64                 case 'p':   plugin_name = option_arg;   break;
65                 default:
66                     error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
67                     break;
68 
69             }
70             return error;
71         }
72 
73         void
74         ResetOptionValues ()
75         {
76             Options::ResetOptionValues();
77             stop_at_entry = false;
78             stdin_path.clear();
79             stdout_path.clear();
80             stderr_path.clear();
81             plugin_name.clear();
82         }
83 
84         const lldb::OptionDefinition*
85         GetDefinitions ()
86         {
87             return g_option_table;
88         }
89 
90         // Options table: Required for subclasses of Options.
91 
92         static lldb::OptionDefinition g_option_table[];
93 
94         // Instance variables to hold the values for command options.
95 
96         bool stop_at_entry;
97         std::string stderr_path;
98         std::string stdin_path;
99         std::string stdout_path;
100         std::string plugin_name;
101 
102     };
103 
104     CommandObjectProcessLaunch (CommandInterpreter &interpreter) :
105         CommandObject (interpreter,
106                        "process launch",
107                        "Launch the executable in the debugger.",
108                        NULL)
109     {
110         CommandArgumentEntry arg;
111         CommandArgumentData run_args_arg;
112 
113         // Define the first (and only) variant of this arg.
114         run_args_arg.arg_type = eArgTypeRunArgs;
115         run_args_arg.arg_repetition = eArgRepeatOptional;
116 
117         // There is only one variant this argument could be; put it into the argument entry.
118         arg.push_back (run_args_arg);
119 
120         // Push the data for the first argument into the m_arguments vector.
121         m_arguments.push_back (arg);
122     }
123 
124 
125     ~CommandObjectProcessLaunch ()
126     {
127     }
128 
129     Options *
130     GetOptions ()
131     {
132         return &m_options;
133     }
134 
135     bool
136     Execute (Args& launch_args,
137              CommandReturnObject &result)
138     {
139         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
140         bool synchronous_execution = m_interpreter.GetSynchronous ();
141     //    bool launched = false;
142     //    bool stopped_after_launch = false;
143 
144         if (target == NULL)
145         {
146             result.AppendError ("invalid target, set executable file using 'file' command");
147             result.SetStatus (eReturnStatusFailed);
148             return false;
149         }
150 
151         // If our listener is NULL, users aren't allows to launch
152         char filename[PATH_MAX];
153         Module *exe_module = target->GetExecutableModule().get();
154         exe_module->GetFileSpec().GetPath(filename, sizeof(filename));
155 
156         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
157         if (process && process->IsAlive())
158         {
159             result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before running again.\n",
160                                           process->GetID());
161             result.SetStatus (eReturnStatusFailed);
162             return false;
163         }
164 
165         const char *plugin_name;
166         if (!m_options.plugin_name.empty())
167             plugin_name = m_options.plugin_name.c_str();
168         else
169             plugin_name = NULL;
170 
171         process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
172 
173         if (process == NULL)
174         {
175             result.AppendErrorWithFormat ("Failed to find a process plugin for executable");
176             result.SetStatus (eReturnStatusFailed);
177             return false;
178         }
179 
180         // If no launch args were given on the command line, then use any that
181         // might have been set using the "run-args" set variable.
182         if (launch_args.GetArgumentCount() == 0)
183         {
184             if (process->GetRunArguments().GetArgumentCount() > 0)
185                 launch_args = process->GetRunArguments();
186         }
187 
188         Args environment;
189 
190         process->GetEnvironmentAsArgs (environment);
191 
192         uint32_t launch_flags = eLaunchFlagNone;
193 
194         if (process->GetDisableASLR())
195             launch_flags |= eLaunchFlagDisableASLR;
196 
197         const char *archname = exe_module->GetArchitecture().AsCString();
198 
199         const char * stdin_path = NULL;
200         const char * stdout_path = NULL;
201         const char * stderr_path = NULL;
202 
203         // Were any standard input/output/error paths given on the command line?
204         if (m_options.stdin_path.empty() &&
205             m_options.stdout_path.empty() &&
206             m_options.stderr_path.empty())
207         {
208             // No standard file handles were given on the command line, check
209             // with the process object in case they were give using "set settings"
210             stdin_path = process->GetStandardInputPath();
211             stdout_path = process->GetStandardOutputPath();
212             stderr_path = process->GetStandardErrorPath();
213         }
214         else
215         {
216             stdin_path = m_options.stdin_path.empty()  ? NULL : m_options.stdin_path.c_str();
217             stdout_path = m_options.stdout_path.empty() ? NULL : m_options.stdout_path.c_str();
218             stderr_path = m_options.stderr_path.empty() ? NULL : m_options.stderr_path.c_str();
219         }
220 
221         if (stdin_path == NULL)
222             stdin_path = "/dev/null";
223         if (stdout_path == NULL)
224             stdout_path = "/dev/null";
225         if (stderr_path == NULL)
226             stderr_path = "/dev/null";
227 
228         Error error (process->Launch (launch_args.GetArgumentCount() ? launch_args.GetConstArgumentVector() : NULL,
229                                       environment.GetArgumentCount() ? environment.GetConstArgumentVector() : NULL,
230                                       launch_flags,
231                                       stdin_path,
232                                       stdout_path,
233                                       stderr_path));
234 
235         if (error.Success())
236         {
237             result.AppendMessageWithFormat ("Launching '%s'  (%s)\n", filename, archname);
238             result.SetStatus (eReturnStatusSuccessContinuingNoResult);
239             if (m_options.stop_at_entry == false)
240             {
241                 StateType state = process->WaitForProcessToStop (NULL);
242 
243                 if (state == eStateStopped)
244                 {
245                     // Call continue_command.
246                     CommandReturnObject continue_result;
247                     m_interpreter.HandleCommand("process continue", false, continue_result);
248                 }
249 
250                 if (synchronous_execution)
251                 {
252                     result.SetDidChangeProcessState (true);
253                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
254                 }
255             }
256         }
257 
258         return result.Succeeded();
259     }
260 
261     virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
262     {
263         // No repeat for "process launch"...
264         return "";
265     }
266 
267 protected:
268 
269     CommandOptions m_options;
270 };
271 
272 
273 lldb::OptionDefinition
274 CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
275 {
276 { LLDB_OPT_SET_1, false, "stop-at-entry", 's', no_argument,       NULL, 0, eArgTypeNone,        "Stop at the entry point of the program when launching a process."},
277 { LLDB_OPT_SET_1, false, "stdin",         'i', required_argument, NULL, 0, eArgTypePath,    "Redirect stdin for the process to <path>."},
278 { LLDB_OPT_SET_1, false, "stdout",        'o', required_argument, NULL, 0, eArgTypePath,    "Redirect stdout for the process to <path>."},
279 { LLDB_OPT_SET_1, false, "stderr",        'e', required_argument, NULL, 0, eArgTypePath,    "Redirect stderr for the process to <path>."},
280 { LLDB_OPT_SET_1, false, "plugin",        'p', required_argument, NULL, 0, eArgTypePlugin,  "Name of the process plugin you want to use."},
281 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
282 };
283 
284 
285 //-------------------------------------------------------------------------
286 // CommandObjectProcessAttach
287 //-------------------------------------------------------------------------
288 
289 class CommandObjectProcessAttach : public CommandObject
290 {
291 public:
292 
293     class CommandOptions : public Options
294     {
295     public:
296 
297         CommandOptions () :
298             Options()
299         {
300             // Keep default values of all options in one place: ResetOptionValues ()
301             ResetOptionValues ();
302         }
303 
304         ~CommandOptions ()
305         {
306         }
307 
308         Error
309         SetOptionValue (int option_idx, const char *option_arg)
310         {
311             Error error;
312             char short_option = (char) m_getopt_table[option_idx].val;
313             bool success = false;
314             switch (short_option)
315             {
316                 case 'p':
317                     pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success);
318                     if (!success || pid == LLDB_INVALID_PROCESS_ID)
319                     {
320                         error.SetErrorStringWithFormat("Invalid process ID '%s'.\n", option_arg);
321                     }
322                     break;
323 
324                 case 'P':
325                     plugin_name = option_arg;
326                     break;
327 
328                 case 'n':
329                     name.assign(option_arg);
330                     break;
331 
332                 case 'w':
333                     waitfor = true;
334                     break;
335 
336                 default:
337                     error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
338                     break;
339             }
340             return error;
341         }
342 
343         void
344         ResetOptionValues ()
345         {
346             Options::ResetOptionValues();
347             pid = LLDB_INVALID_PROCESS_ID;
348             name.clear();
349             waitfor = false;
350         }
351 
352         const lldb::OptionDefinition*
353         GetDefinitions ()
354         {
355             return g_option_table;
356         }
357 
358         virtual bool
359         HandleOptionArgumentCompletion (CommandInterpreter &interpeter,
360                                         Args &input,
361                                         int cursor_index,
362                                         int char_pos,
363                                         OptionElementVector &opt_element_vector,
364                                         int opt_element_index,
365                                         int match_start_point,
366                                         int max_return_elements,
367                                         bool &word_complete,
368                                         StringList &matches)
369         {
370             int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
371             int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
372 
373             // We are only completing the name option for now...
374 
375             const lldb::OptionDefinition *opt_defs = GetDefinitions();
376             if (opt_defs[opt_defs_index].short_option == 'n')
377             {
378                 // Are we in the name?
379 
380                 // Look to see if there is a -P argument provided, and if so use that plugin, otherwise
381                 // use the default plugin.
382                 Process *process = interpeter.GetDebugger().GetExecutionContext().process;
383                 bool need_to_delete_process = false;
384 
385                 const char *partial_name = NULL;
386                 partial_name = input.GetArgumentAtIndex(opt_arg_pos);
387 
388                 if (process && process->IsAlive())
389                     return true;
390 
391                 Target *target = interpeter.GetDebugger().GetSelectedTarget().get();
392                 if (target == NULL)
393                 {
394                     // No target has been set yet, for now do host completion.  Otherwise I don't know how we would
395                     // figure out what the right target to use is...
396                     std::vector<lldb::pid_t> pids;
397                     Host::ListProcessesMatchingName (partial_name, matches, pids);
398                     return true;
399                 }
400                 if (!process)
401                 {
402                     process = target->CreateProcess (interpeter.GetDebugger().GetListener(), partial_name).get();
403                     need_to_delete_process = true;
404                 }
405 
406                 if (process)
407                 {
408                     matches.Clear();
409                     std::vector<lldb::pid_t> pids;
410                     process->ListProcessesMatchingName (NULL, matches, pids);
411                     if (need_to_delete_process)
412                         target->DeleteCurrentProcess();
413                     return true;
414                 }
415             }
416 
417             return false;
418         }
419 
420         // Options table: Required for subclasses of Options.
421 
422         static lldb::OptionDefinition g_option_table[];
423 
424         // Instance variables to hold the values for command options.
425 
426         lldb::pid_t pid;
427         std::string plugin_name;
428         std::string name;
429         bool waitfor;
430     };
431 
432     CommandObjectProcessAttach (CommandInterpreter &interpreter) :
433         CommandObject (interpreter,
434                        "process attach",
435                        "Attach to a process.",
436                        "process attach <cmd-options>")
437     {
438     }
439 
440     ~CommandObjectProcessAttach ()
441     {
442     }
443 
444     bool
445     Execute (Args& command,
446              CommandReturnObject &result)
447     {
448         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
449 
450         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
451         if (process)
452         {
453             if (process->IsAlive())
454             {
455                 result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before attaching.\n",
456                                               process->GetID());
457                 result.SetStatus (eReturnStatusFailed);
458                 return false;
459             }
460         }
461 
462         if (target == NULL)
463         {
464             // If there isn't a current target create one.
465             TargetSP new_target_sp;
466             FileSpec emptyFileSpec;
467             ArchSpec emptyArchSpec;
468             Error error;
469 
470             error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(),
471                                                                               emptyFileSpec,
472                                                                               emptyArchSpec,
473                                                                               NULL,
474                                                                               false,
475                                                                               new_target_sp);
476             target = new_target_sp.get();
477             if (target == NULL || error.Fail())
478             {
479                 result.AppendError(error.AsCString("Error creating empty target"));
480                 return false;
481             }
482             m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target);
483         }
484 
485         // Record the old executable module, we want to issue a warning if the process of attaching changed the
486         // current executable (like somebody said "file foo" then attached to a PID whose executable was bar.)
487 
488         ModuleSP old_exec_module_sp = target->GetExecutableModule();
489         ArchSpec old_arch_spec = target->GetArchitecture();
490 
491         if (command.GetArgumentCount())
492         {
493             result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
494             result.SetStatus (eReturnStatusFailed);
495         }
496         else
497         {
498             const char *plugin_name = NULL;
499 
500             if (!m_options.plugin_name.empty())
501                 plugin_name = m_options.plugin_name.c_str();
502 
503             process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
504 
505             if (process)
506             {
507                 Error error;
508                 int attach_pid = m_options.pid;
509 
510                 const char *wait_name = NULL;
511 
512                 if (m_options.name.empty())
513                 {
514                     if (old_exec_module_sp)
515                     {
516                         wait_name = old_exec_module_sp->GetFileSpec().GetFilename().AsCString();
517                     }
518                 }
519                 else
520                 {
521                     wait_name = m_options.name.c_str();
522                 }
523 
524                 // If we are waiting for a process with this name to show up, do that first.
525                 if (m_options.waitfor)
526                 {
527 
528                     if (wait_name == NULL)
529                     {
530                         result.AppendError("Invalid arguments: must have a file loaded or supply a process name with the waitfor option.\n");
531                         result.SetStatus (eReturnStatusFailed);
532                         return false;
533                     }
534 
535                     m_interpreter.GetDebugger().GetOutputStream().Printf("Waiting to attach to a process named \"%s\".\n", wait_name);
536                     error = process->Attach (wait_name, m_options.waitfor);
537                     if (error.Success())
538                     {
539                         result.SetStatus (eReturnStatusSuccessContinuingNoResult);
540                     }
541                     else
542                     {
543                         result.AppendErrorWithFormat ("Waiting for a process to launch named '%s': %s\n",
544                                                          wait_name,
545                                                          error.AsCString());
546                         result.SetStatus (eReturnStatusFailed);
547                         return false;
548                     }
549                 }
550                 else
551                 {
552                     // If the process was specified by name look it up, so we can warn if there are multiple
553                     // processes with this pid.
554 
555                     if (attach_pid == LLDB_INVALID_PROCESS_ID && wait_name != NULL)
556                     {
557                         std::vector<lldb::pid_t> pids;
558                         StringList matches;
559 
560                         process->ListProcessesMatchingName(wait_name, matches, pids);
561                         if (matches.GetSize() > 1)
562                         {
563                             result.AppendErrorWithFormat("More than one process named %s\n", wait_name);
564                             result.SetStatus (eReturnStatusFailed);
565                             return false;
566                         }
567                         else if (matches.GetSize() == 0)
568                         {
569                             result.AppendErrorWithFormat("Could not find a process named %s\n", wait_name);
570                             result.SetStatus (eReturnStatusFailed);
571                             return false;
572                         }
573                         else
574                         {
575                             attach_pid = pids[0];
576                         }
577 
578                     }
579 
580                     if (attach_pid != LLDB_INVALID_PROCESS_ID)
581                     {
582                         error = process->Attach (attach_pid);
583                         if (error.Success())
584                         {
585                             result.SetStatus (eReturnStatusSuccessContinuingNoResult);
586                         }
587                         else
588                         {
589                             result.AppendErrorWithFormat ("Attaching to process %i failed: %s.\n",
590                                                          attach_pid,
591                                                          error.AsCString());
592                             result.SetStatus (eReturnStatusFailed);
593                         }
594                     }
595                     else
596                     {
597                         result.AppendErrorWithFormat ("No PID specified for attach\n",
598                                                          attach_pid,
599                                                          error.AsCString());
600                         result.SetStatus (eReturnStatusFailed);
601 
602                     }
603                 }
604             }
605         }
606 
607         if (result.Succeeded())
608         {
609             // Okay, we're done.  Last step is to warn if the executable module has changed:
610             if (!old_exec_module_sp)
611             {
612                 char new_path[PATH_MAX + 1];
613                 target->GetExecutableModule()->GetFileSpec().GetPath(new_path, PATH_MAX);
614 
615                 result.AppendMessageWithFormat("Executable module set to \"%s\".\n",
616                     new_path);
617             }
618             else if (old_exec_module_sp->GetFileSpec() != target->GetExecutableModule()->GetFileSpec())
619             {
620                 char old_path[PATH_MAX + 1];
621                 char new_path[PATH_MAX + 1];
622 
623                 old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX);
624                 target->GetExecutableModule()->GetFileSpec().GetPath (new_path, PATH_MAX);
625 
626                 result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n",
627                                                     old_path, new_path);
628             }
629 
630             if (!old_arch_spec.IsValid())
631             {
632                 result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().AsCString());
633             }
634             else if (old_arch_spec != target->GetArchitecture())
635             {
636                 result.AppendWarningWithFormat("Architecture changed from %s to %s.\n",
637                                                 old_arch_spec.AsCString(), target->GetArchitecture().AsCString());
638             }
639         }
640         return result.Succeeded();
641     }
642 
643     Options *
644     GetOptions ()
645     {
646         return &m_options;
647     }
648 
649 protected:
650 
651     CommandOptions m_options;
652 };
653 
654 
655 lldb::OptionDefinition
656 CommandObjectProcessAttach::CommandOptions::g_option_table[] =
657 {
658 { LLDB_OPT_SET_ALL, false, "plugin", 'P', required_argument, NULL, 0, eArgTypePlugin,        "Name of the process plugin you want to use."},
659 { LLDB_OPT_SET_1,   false, "pid",    'p', required_argument, NULL, 0, eArgTypePid,           "The process ID of an existing process to attach to."},
660 { LLDB_OPT_SET_2,   false, "name",   'n', required_argument, NULL, 0, eArgTypeProcessName,  "The name of the process to attach to."},
661 { LLDB_OPT_SET_2,   false, "waitfor",'w', no_argument,       NULL, 0, eArgTypeNone,              "Wait for the the process with <process-name> to launch."},
662 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
663 };
664 
665 //-------------------------------------------------------------------------
666 // CommandObjectProcessContinue
667 //-------------------------------------------------------------------------
668 
669 class CommandObjectProcessContinue : public CommandObject
670 {
671 public:
672 
673     CommandObjectProcessContinue (CommandInterpreter &interpreter) :
674         CommandObject (interpreter,
675                        "process continue",
676                        "Continue execution of all threads in the current process.",
677                        "process continue",
678                        eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
679     {
680     }
681 
682 
683     ~CommandObjectProcessContinue ()
684     {
685     }
686 
687     bool
688     Execute (Args& command,
689              CommandReturnObject &result)
690     {
691         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
692         bool synchronous_execution = m_interpreter.GetSynchronous ();
693 
694         if (process == NULL)
695         {
696             result.AppendError ("no process to continue");
697             result.SetStatus (eReturnStatusFailed);
698             return false;
699          }
700 
701         StateType state = process->GetState();
702         if (state == eStateStopped)
703         {
704             if (command.GetArgumentCount() != 0)
705             {
706                 result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str());
707                 result.SetStatus (eReturnStatusFailed);
708                 return false;
709             }
710 
711             const uint32_t num_threads = process->GetThreadList().GetSize();
712 
713             // Set the actions that the threads should each take when resuming
714             for (uint32_t idx=0; idx<num_threads; ++idx)
715             {
716                 process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning);
717             }
718 
719             Error error(process->Resume());
720             if (error.Success())
721             {
722                 result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID());
723                 if (synchronous_execution)
724                 {
725                     state = process->WaitForProcessToStop (NULL);
726 
727                     result.SetDidChangeProcessState (true);
728                     result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
729                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
730                 }
731                 else
732                 {
733                     result.SetStatus (eReturnStatusSuccessContinuingNoResult);
734                 }
735             }
736             else
737             {
738                 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
739                 result.SetStatus (eReturnStatusFailed);
740             }
741         }
742         else
743         {
744             result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
745                                          StateAsCString(state));
746             result.SetStatus (eReturnStatusFailed);
747         }
748         return result.Succeeded();
749     }
750 };
751 
752 //-------------------------------------------------------------------------
753 // CommandObjectProcessDetach
754 //-------------------------------------------------------------------------
755 
756 class CommandObjectProcessDetach : public CommandObject
757 {
758 public:
759 
760     CommandObjectProcessDetach (CommandInterpreter &interpreter) :
761         CommandObject (interpreter,
762                        "process detach",
763                        "Detach from the current process being debugged.",
764                        "process detach",
765                        eFlagProcessMustBeLaunched)
766     {
767     }
768 
769     ~CommandObjectProcessDetach ()
770     {
771     }
772 
773     bool
774     Execute (Args& command,
775              CommandReturnObject &result)
776     {
777         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
778         if (process == NULL)
779         {
780             result.AppendError ("must have a valid process in order to detach");
781             result.SetStatus (eReturnStatusFailed);
782             return false;
783         }
784 
785         Error error (process->Detach());
786         if (error.Success())
787         {
788             result.SetStatus (eReturnStatusSuccessFinishResult);
789         }
790         else
791         {
792             result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString());
793             result.SetStatus (eReturnStatusFailed);
794             return false;
795         }
796         return result.Succeeded();
797     }
798 };
799 
800 //-------------------------------------------------------------------------
801 // CommandObjectProcessSignal
802 //-------------------------------------------------------------------------
803 
804 class CommandObjectProcessSignal : public CommandObject
805 {
806 public:
807 
808     CommandObjectProcessSignal (CommandInterpreter &interpreter) :
809         CommandObject (interpreter,
810                        "process signal",
811                        "Send a UNIX signal to the current process being debugged.",
812                        NULL)
813     {
814         CommandArgumentEntry arg;
815         CommandArgumentData signal_arg;
816 
817         // Define the first (and only) variant of this arg.
818         signal_arg.arg_type = eArgTypeUnixSignalNumber;
819         signal_arg.arg_repetition = eArgRepeatPlain;
820 
821         // There is only one variant this argument could be; put it into the argument entry.
822         arg.push_back (signal_arg);
823 
824         // Push the data for the first argument into the m_arguments vector.
825         m_arguments.push_back (arg);
826     }
827 
828     ~CommandObjectProcessSignal ()
829     {
830     }
831 
832     bool
833     Execute (Args& command,
834              CommandReturnObject &result)
835     {
836         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
837         if (process == NULL)
838         {
839             result.AppendError ("no process to signal");
840             result.SetStatus (eReturnStatusFailed);
841             return false;
842         }
843 
844         if (command.GetArgumentCount() == 1)
845         {
846             int signo = Args::StringToSInt32(command.GetArgumentAtIndex(0), -1, 0);
847             if (signo == -1)
848             {
849                 result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0));
850                 result.SetStatus (eReturnStatusFailed);
851             }
852             else
853             {
854                 Error error (process->Signal (signo));
855                 if (error.Success())
856                 {
857                     result.SetStatus (eReturnStatusSuccessFinishResult);
858                 }
859                 else
860                 {
861                     result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString());
862                     result.SetStatus (eReturnStatusFailed);
863                 }
864             }
865         }
866         else
867         {
868             result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: \n", m_cmd_name.c_str(),
869                                         m_cmd_syntax.c_str());
870             result.SetStatus (eReturnStatusFailed);
871         }
872         return result.Succeeded();
873     }
874 };
875 
876 
877 //-------------------------------------------------------------------------
878 // CommandObjectProcessInterrupt
879 //-------------------------------------------------------------------------
880 
881 class CommandObjectProcessInterrupt : public CommandObject
882 {
883 public:
884 
885 
886     CommandObjectProcessInterrupt (CommandInterpreter &interpreter) :
887     CommandObject (interpreter,
888                    "process interrupt",
889                    "Interrupt the current process being debugged.",
890                    "process interrupt",
891                    eFlagProcessMustBeLaunched)
892     {
893     }
894 
895     ~CommandObjectProcessInterrupt ()
896     {
897     }
898 
899     bool
900     Execute (Args& command,
901              CommandReturnObject &result)
902     {
903         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
904         if (process == NULL)
905         {
906             result.AppendError ("no process to halt");
907             result.SetStatus (eReturnStatusFailed);
908             return false;
909         }
910 
911         if (command.GetArgumentCount() == 0)
912         {
913             Error error(process->Halt ());
914             if (error.Success())
915             {
916                 result.SetStatus (eReturnStatusSuccessFinishResult);
917 
918                 // Maybe we should add a "SuspendThreadPlans so we
919                 // can halt, and keep in place all the current thread plans.
920                 process->GetThreadList().DiscardThreadPlans();
921             }
922             else
923             {
924                 result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString());
925                 result.SetStatus (eReturnStatusFailed);
926             }
927         }
928         else
929         {
930             result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
931                                         m_cmd_name.c_str(),
932                                         m_cmd_syntax.c_str());
933             result.SetStatus (eReturnStatusFailed);
934         }
935         return result.Succeeded();
936     }
937 };
938 
939 //-------------------------------------------------------------------------
940 // CommandObjectProcessKill
941 //-------------------------------------------------------------------------
942 
943 class CommandObjectProcessKill : public CommandObject
944 {
945 public:
946 
947     CommandObjectProcessKill (CommandInterpreter &interpreter) :
948     CommandObject (interpreter,
949                    "process kill",
950                    "Terminate the current process being debugged.",
951                    "process kill",
952                    eFlagProcessMustBeLaunched)
953     {
954     }
955 
956     ~CommandObjectProcessKill ()
957     {
958     }
959 
960     bool
961     Execute (Args& command,
962              CommandReturnObject &result)
963     {
964         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
965         if (process == NULL)
966         {
967             result.AppendError ("no process to kill");
968             result.SetStatus (eReturnStatusFailed);
969             return false;
970         }
971 
972         if (command.GetArgumentCount() == 0)
973         {
974             Error error (process->Destroy());
975             if (error.Success())
976             {
977                 result.SetStatus (eReturnStatusSuccessFinishResult);
978             }
979             else
980             {
981                 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString());
982                 result.SetStatus (eReturnStatusFailed);
983             }
984         }
985         else
986         {
987             result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
988                                         m_cmd_name.c_str(),
989                                         m_cmd_syntax.c_str());
990             result.SetStatus (eReturnStatusFailed);
991         }
992         return result.Succeeded();
993     }
994 };
995 
996 //-------------------------------------------------------------------------
997 // CommandObjectProcessStatus
998 //-------------------------------------------------------------------------
999 class CommandObjectProcessStatus : public CommandObject
1000 {
1001 public:
1002     CommandObjectProcessStatus (CommandInterpreter &interpreter) :
1003     CommandObject (interpreter,
1004                    "process status",
1005                    "Show the current status and location of executing process.",
1006                    "process status",
1007                    0)
1008     {
1009     }
1010 
1011     ~CommandObjectProcessStatus()
1012     {
1013     }
1014 
1015 
1016     bool
1017     Execute
1018     (
1019         Args& command,
1020         CommandReturnObject &result
1021     )
1022     {
1023         StreamString &output_stream = result.GetOutputStream();
1024         result.SetStatus (eReturnStatusSuccessFinishNoResult);
1025         ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
1026         if (exe_ctx.process)
1027         {
1028             const StateType state = exe_ctx.process->GetState();
1029             if (StateIsStoppedState(state))
1030             {
1031                 if (state == eStateExited)
1032                 {
1033                     int exit_status = exe_ctx.process->GetExitStatus();
1034                     const char *exit_description = exe_ctx.process->GetExitDescription();
1035                     output_stream.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n",
1036                                           exe_ctx.process->GetID(),
1037                                           exit_status,
1038                                           exit_status,
1039                                           exit_description ? exit_description : "");
1040                 }
1041                 else
1042                 {
1043                     output_stream.Printf ("Process %d %s\n", exe_ctx.process->GetID(), StateAsCString (state));
1044                     if (exe_ctx.thread == NULL)
1045                         exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
1046                     if (exe_ctx.thread != NULL)
1047                     {
1048                         DisplayThreadsInfo (m_interpreter, &exe_ctx, result, true, true);
1049                     }
1050                     else
1051                     {
1052                         result.AppendError ("No valid thread found in current process.");
1053                         result.SetStatus (eReturnStatusFailed);
1054                     }
1055                 }
1056             }
1057             else
1058             {
1059                 output_stream.Printf ("Process %d is running.\n",
1060                                           exe_ctx.process->GetID());
1061             }
1062         }
1063         else
1064         {
1065             result.AppendError ("No current location or status available.");
1066             result.SetStatus (eReturnStatusFailed);
1067         }
1068         return result.Succeeded();
1069     }
1070 };
1071 
1072 //-------------------------------------------------------------------------
1073 // CommandObjectMultiwordProcess
1074 //-------------------------------------------------------------------------
1075 
1076 CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter &interpreter) :
1077     CommandObjectMultiword (interpreter,
1078                             "process",
1079                             "A set of commands for operating on a process.",
1080                             "process <subcommand> [<subcommand-options>]")
1081 {
1082     LoadSubCommand ("attach",      CommandObjectSP (new CommandObjectProcessAttach (interpreter)));
1083     LoadSubCommand ("launch",      CommandObjectSP (new CommandObjectProcessLaunch (interpreter)));
1084     LoadSubCommand ("continue",    CommandObjectSP (new CommandObjectProcessContinue (interpreter)));
1085     LoadSubCommand ("detach",      CommandObjectSP (new CommandObjectProcessDetach (interpreter)));
1086     LoadSubCommand ("signal",      CommandObjectSP (new CommandObjectProcessSignal (interpreter)));
1087     LoadSubCommand ("status",      CommandObjectSP (new CommandObjectProcessStatus (interpreter)));
1088     LoadSubCommand ("interrupt",   CommandObjectSP (new CommandObjectProcessInterrupt (interpreter)));
1089     LoadSubCommand ("kill",        CommandObjectSP (new CommandObjectProcessKill (interpreter)));
1090 }
1091 
1092 CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess ()
1093 {
1094 }
1095 
1096