blob: 0a8487155d3577431dd90f2e6416a56f17a2a6ff [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- 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
Jim Ingham84cdc152010-06-15 19:49:27 +000016#include "lldb/Interpreter/Args.h"
17#include "lldb/Interpreter/Options.h"
Chris Lattner24943d22010-06-08 16:52:24 +000018#include "lldb/Core/State.h"
19#include "lldb/Interpreter/CommandInterpreter.h"
20#include "lldb/Interpreter/CommandReturnObject.h"
Jim Ingham41313fc2010-06-18 01:23:09 +000021#include "./CommandObjectThread.h"
Chris Lattner24943d22010-06-08 16:52:24 +000022#include "lldb/Target/Process.h"
23#include "lldb/Target/Target.h"
24#include "lldb/Target/Thread.h"
25
26using namespace lldb;
27using namespace lldb_private;
28
29//-------------------------------------------------------------------------
30// CommandObjectProcessLaunch
31//-------------------------------------------------------------------------
32
33class CommandObjectProcessLaunch : public CommandObject
34{
35public:
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 () :
105 CommandObject ("process launch",
106 "Launches the executable in the debugger.",
107 "process launch [<cmd-options>] [<arguments-for-running-the-program>]")
108 {
109 }
110
111
112 ~CommandObjectProcessLaunch ()
113 {
114 }
115
116 Options *
117 GetOptions ()
118 {
119 return &m_options;
120 }
121
122 bool
123 Execute (Args& launch_args,
124 CommandContext *context,
125 CommandInterpreter *interpreter,
126 CommandReturnObject &result)
127 {
128 Target *target = context->GetTarget();
129 bool synchronous_execution = interpreter->GetSynchronous ();
130 // bool launched = false;
131 // bool stopped_after_launch = false;
132
133 if (target == NULL)
134 {
135 result.AppendError ("invalid target, set executable file using 'file' command");
136 result.SetStatus (eReturnStatusFailed);
137 return false;
138 }
139
140 // If our listener is NULL, users aren't allows to launch
141 Listener *listener = interpreter->GetListener();
142 if (listener == NULL)
143 {
144 result.AppendError ("operation not allowed through the command interpreter");
145 result.SetStatus (eReturnStatusFailed);
146 return false;
147 }
148
149 char filename[PATH_MAX];
150 Module *exe_module = target->GetExecutableModule().get();
151 exe_module->GetFileSpec().GetPath(filename, sizeof(filename));
152
153 Process *process = context->GetExecutionContext().process;
154 if (process)
155 {
156 if (process->IsAlive())
157 {
158 result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before running again.\n",
159 process->GetID());
160 result.SetStatus (eReturnStatusFailed);
161 return false;
162 }
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 (*listener, plugin_name).get();
172
173 const Args *environment = interpreter->GetEnvironmentVariables();
174 const Args *run_args = interpreter->GetProgramArguments();
175
176 // There are two possible sources of args to be passed to the process upon launching: Those the user
177 // typed at the run command (launch_args); or those the user pre-set in the run-args variable (run_args).
178
179 // If launch_args is empty, use run_args.
180 if (launch_args.GetArgumentCount() == 0)
181 {
182 if (run_args != NULL)
183 launch_args.AppendArguments (*run_args);
184 }
185 else
186 {
187 // launch-args was not empty; use that, AND re-set run-args to contains launch-args values.
188 StateVariable *run_args_var = interpreter->GetStateVariable ("run-args");
189 if (run_args_var != NULL)
190 {
191 run_args_var->ArrayClearValues();
192 run_args_var->GetArgs().AppendArguments (launch_args);
193 }
194 }
195
196
197 if (process)
198 {
199 const char *archname = exe_module->GetArchitecture().AsCString();
200
201 const char * stdin_path = NULL;
202 const char * stdout_path = NULL;
203 const char * stderr_path = NULL;
204
205 if (!(m_options.stdin_path.empty() &&
206 m_options.stdout_path.empty() &&
207 m_options.stderr_path.empty()))
208 {
209 stdin_path = m_options.stdin_path.empty() ? "/dev/null" : m_options.stdin_path.c_str();
210 stdout_path = m_options.stdout_path.empty() ? "/dev/null" : m_options.stdout_path.c_str();
211 stderr_path = m_options.stderr_path.empty() ? "/dev/null" : m_options.stderr_path.c_str();
212 }
213
214 Error error (process->Launch (launch_args.GetConstArgumentVector(),
215 environment ? environment->GetConstArgumentVector() : NULL,
216 stdin_path,
217 stdout_path,
218 stderr_path));
219
220 if (error.Success())
221 {
222 result.AppendMessageWithFormat ("Launching '%s' (%s)\n", filename, archname);
223 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
224 if (m_options.stop_at_entry == false)
225 {
226 StateType state = process->WaitForProcessToStop (NULL);
227
228 if (state == eStateStopped)
229 {
230 // Call continue_command.
231 CommandReturnObject continue_result;
232 interpreter->HandleCommand("process continue", false, continue_result);
233 }
234
235 if (synchronous_execution)
236 {
237 result.SetDidChangeProcessState (true);
238 result.SetStatus (eReturnStatusSuccessFinishNoResult);
239 }
240 }
241 }
242 else
243 {
244 result.AppendErrorWithFormat ("Process launch failed: %s",
245 error.AsCString());
246 result.SetStatus (eReturnStatusFailed);
247 }
248 }
249 else
250 {
251 result.AppendErrorWithFormat ("Process launch failed: unable to create a process object.\n");
252 result.SetStatus (eReturnStatusFailed);
253 return false;
254 }
255
256 return result.Succeeded();
257 }
258
259protected:
260
261 CommandOptions m_options;
262};
263
264
265lldb::OptionDefinition
266CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
267{
Jim Ingham34e9a982010-06-15 18:47:14 +0000268{ LLDB_OPT_SET_1, false, "stop-at-entry", 's', no_argument, NULL, 0, NULL, "Stop at the entry point of the program when launching a process."},
269{ LLDB_OPT_SET_1, false, "stdin", 'i', required_argument, NULL, 0, "<path>", "Redirect stdin for the process to <path>."},
270{ LLDB_OPT_SET_1, false, "stdout", 'o', required_argument, NULL, 0, "<path>", "Redirect stdout for the process to <path>."},
271{ LLDB_OPT_SET_1, false, "stderr", 'e', required_argument, NULL, 0, "<path>", "Redirect stderr for the process to <path>."},
272{ LLDB_OPT_SET_1, false, "plugin", 'p', required_argument, NULL, 0, "<plugin>", "Name of the process plugin you want to use."},
Chris Lattner24943d22010-06-08 16:52:24 +0000273{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
274};
275
276
277//-------------------------------------------------------------------------
278// CommandObjectProcessAttach
279//-------------------------------------------------------------------------
280
281class CommandObjectProcessAttach : public CommandObject
282{
283public:
284
285 CommandObjectProcessAttach () :
286 CommandObject ("process attach",
287 "Attaches to a process.",
288 "process attach <cmd-options>")
289 {
290 SetHelpLong("Currently, you must set the executable file before you can attach "
291 "to a process.\n");
292 }
293
294 ~CommandObjectProcessAttach ()
295 {
296 }
297
298 bool
299 Execute (Args& command,
300 CommandContext *context,
301 CommandInterpreter *interpreter,
302 CommandReturnObject &result)
303 {
304 Target *target = context->GetTarget();
305 if (target == NULL)
306 {
307 result.AppendError ("invalid target, set executable file using 'file' command");
308 result.SetStatus (eReturnStatusFailed);
309 return false;
310 }
311
312 // If our listener is NULL, users aren't allows to launch
313 Listener *listener = interpreter->GetListener();
314 if (listener == NULL)
315 {
316 result.AppendError ("operation not allowed through the command interpreter");
317 result.SetStatus (eReturnStatusFailed);
318 return false;
319 }
320 Process *process = context->GetExecutionContext().process;
321 if (process)
322 {
323 if (process->IsAlive())
324 {
325 result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before attaching.\n", process->GetID());
326 result.SetStatus (eReturnStatusFailed);
327 return false;
328 }
329 }
330
331 if (command.GetArgumentCount())
332 {
333 result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
334 result.SetStatus (eReturnStatusFailed);
335 }
336 else
337 {
338 const char *plugin_name = NULL;
339
340 if (!m_options.plugin_name.empty())
341 plugin_name = m_options.plugin_name.c_str();
342
343 process = target->CreateProcess (*listener, plugin_name).get();
344
345 if (process)
346 {
347 Error error;
348 int attach_pid = m_options.pid;
349
350 if (attach_pid != LLDB_INVALID_PROCESS_ID)
351 {
352 error = process->Attach (attach_pid);
353 if (error.Success())
354 {
355 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
356 }
357 else
358 {
359 result.AppendErrorWithFormat ("Attaching to process %i failed: %s.\n",
360 attach_pid,
361 error.AsCString());
362 result.SetStatus (eReturnStatusFailed);
363 }
364 }
365 else if (!m_options.name.empty())
366 {
367 error = process->Attach (m_options.name.c_str(), m_options.waitfor);
368 if (error.Success())
369 {
370 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
371 }
372 else
373 {
374 if (m_options.waitfor)
375 result.AppendErrorWithFormat ("Waiting for a process to launch named '%s': %s\n",
376 m_options.name.c_str(),
377 error.AsCString());
378 else
379 result.AppendErrorWithFormat ("Failed to a process named '%s': %s\n",
380 m_options.name.c_str(),
381 error.AsCString());
382 result.SetStatus (eReturnStatusFailed);
383 }
384 }
385 }
386 }
387 return result.Succeeded();
388 }
389
390 Options *
391 GetOptions ()
392 {
393 return &m_options;
394 }
395
396 class CommandOptions : public Options
397 {
398 public:
399
400 CommandOptions () :
401 Options()
402 {
403 // Keep default values of all options in one place: ResetOptionValues ()
404 ResetOptionValues ();
405 }
406
407 ~CommandOptions ()
408 {
409 }
410
411 Error
412 SetOptionValue (int option_idx, const char *option_arg)
413 {
414 Error error;
415 char short_option = (char) m_getopt_table[option_idx].val;
416 bool success = false;
417 switch (short_option)
418 {
419 case 'p':
420 pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success);
421 if (!success || pid == LLDB_INVALID_PROCESS_ID)
422 {
423 error.SetErrorStringWithFormat("Invalid process ID '%s'.\n", option_arg);
424 }
425 break;
426
427 case 'P':
428 plugin_name = option_arg;
429 break;
430
431 case 'n':
432 name.assign(option_arg);
433 break;
434
435 case 'w':
436 waitfor = true;
437 break;
438
439 default:
440 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
441 break;
442 }
443 return error;
444 }
445
446 void
447 ResetOptionValues ()
448 {
449 Options::ResetOptionValues();
450 pid = LLDB_INVALID_PROCESS_ID;
451 name.clear();
452 waitfor = false;
453 }
454
455 const lldb::OptionDefinition*
456 GetDefinitions ()
457 {
458 return g_option_table;
459 }
460
461 // Options table: Required for subclasses of Options.
462
463 static lldb::OptionDefinition g_option_table[];
464
465 // Instance variables to hold the values for command options.
466
467 lldb::pid_t pid;
468 std::string plugin_name;
469 std::string name;
470 bool waitfor;
471 };
472
473protected:
474
475 CommandOptions m_options;
476};
477
478
479lldb::OptionDefinition
480CommandObjectProcessAttach::CommandOptions::g_option_table[] =
481{
Jim Ingham34e9a982010-06-15 18:47:14 +0000482{ LLDB_OPT_SET_ALL, false, "plugin", 'P', required_argument, NULL, 0, "<plugin>", "Name of the process plugin you want to use."},
483{ LLDB_OPT_SET_1, false, "pid", 'p', required_argument, NULL, 0, "<pid>", "The process ID of an existing process to attach to."},
484{ LLDB_OPT_SET_2, true, "name", 'n', required_argument, NULL, 0, "<process-name>", "The name of the process to attach to."},
485{ LLDB_OPT_SET_2, false, "waitfor", 'w', no_argument, NULL, 0, NULL, "Wait for the the process with <process-name> to launch."},
Chris Lattner24943d22010-06-08 16:52:24 +0000486{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
487};
488
489//-------------------------------------------------------------------------
490// CommandObjectProcessContinue
491//-------------------------------------------------------------------------
492
493class CommandObjectProcessContinue : public CommandObject
494{
495public:
496
497 CommandObjectProcessContinue () :
498 CommandObject ("process continue",
499 "Continues execution all threads in the current process.",
500 "process continue",
501 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
502 {
503 }
504
505
506 ~CommandObjectProcessContinue ()
507 {
508 }
509
510 bool
511 Execute (Args& command,
512 CommandContext *context,
513 CommandInterpreter *interpreter,
514 CommandReturnObject &result)
515 {
516 Process *process = context->GetExecutionContext().process;
517 bool synchronous_execution = interpreter->GetSynchronous ();
518
519 if (process == NULL)
520 {
521 result.AppendError ("no process to continue");
522 result.SetStatus (eReturnStatusFailed);
523 return false;
524 }
525
526 StateType state = process->GetState();
527 if (state == eStateStopped)
528 {
529 if (command.GetArgumentCount() != 0)
530 {
531 result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str());
532 result.SetStatus (eReturnStatusFailed);
533 return false;
534 }
535
536 const uint32_t num_threads = process->GetThreadList().GetSize();
537
538 // Set the actions that the threads should each take when resuming
539 for (uint32_t idx=0; idx<num_threads; ++idx)
540 {
541 process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning);
542 }
543
544 Error error(process->Resume());
545 if (error.Success())
546 {
547 result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID());
548 if (synchronous_execution)
549 {
550 StateType state = process->WaitForProcessToStop (NULL);
551
552 result.SetDidChangeProcessState (true);
553 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
554 result.SetStatus (eReturnStatusSuccessFinishNoResult);
555 }
556 else
557 {
558 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
559 }
560 }
561 else
562 {
563 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
564 result.SetStatus (eReturnStatusFailed);
565 }
566 }
567 else
568 {
569 result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
570 StateAsCString(state));
571 result.SetStatus (eReturnStatusFailed);
572 }
573 return result.Succeeded();
574 }
575};
576
577//-------------------------------------------------------------------------
578// CommandObjectProcessDetach
579//-------------------------------------------------------------------------
580
581class CommandObjectProcessDetach : public CommandObject
582{
583public:
584
585 CommandObjectProcessDetach () :
586 CommandObject ("process detach",
587 "Detaches from the current process being debugged.",
588 "process detach",
589 eFlagProcessMustBeLaunched)
590 {
591 }
592
593 ~CommandObjectProcessDetach ()
594 {
595 }
596
597 bool
598 Execute (Args& command,
599 CommandContext *context,
600 CommandInterpreter *interpreter,
601 CommandReturnObject &result)
602 {
603 Process *process = context->GetExecutionContext().process;
604 if (process == NULL)
605 {
606 result.AppendError ("must have a valid process in order to detach");
607 result.SetStatus (eReturnStatusFailed);
608 return false;
609 }
610
611 Error error (process->Detach());
612 if (error.Success())
613 {
614 result.SetStatus (eReturnStatusSuccessFinishResult);
615 }
616 else
617 {
618 result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString());
619 result.SetStatus (eReturnStatusFailed);
620 return false;
621 }
622 return result.Succeeded();
623 }
624};
625
626//-------------------------------------------------------------------------
627// CommandObjectProcessSignal
628//-------------------------------------------------------------------------
629
630class CommandObjectProcessSignal : public CommandObject
631{
632public:
633
634 CommandObjectProcessSignal () :
635 CommandObject ("process signal",
636 "Sends a UNIX signal to the current process being debugged.",
637 "process signal <unix-signal-number>")
638 {
639 }
640
641 ~CommandObjectProcessSignal ()
642 {
643 }
644
645 bool
646 Execute (Args& command,
647 CommandContext *context,
648 CommandInterpreter *interpreter,
649 CommandReturnObject &result)
650 {
651 Process *process = context->GetExecutionContext().process;
652 if (process == NULL)
653 {
654 result.AppendError ("no process to signal");
655 result.SetStatus (eReturnStatusFailed);
656 return false;
657 }
658
659 if (command.GetArgumentCount() == 1)
660 {
661 int signo = Args::StringToSInt32(command.GetArgumentAtIndex(0), -1, 0);
662 if (signo == -1)
663 {
664 result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0));
665 result.SetStatus (eReturnStatusFailed);
666 }
667 else
668 {
669 Error error (process->Signal (signo));
670 if (error.Success())
671 {
672 result.SetStatus (eReturnStatusSuccessFinishResult);
673 }
674 else
675 {
676 result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString());
677 result.SetStatus (eReturnStatusFailed);
678 }
679 }
680 }
681 else
682 {
683 result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: \n", m_cmd_name.c_str(),
684 m_cmd_syntax.c_str());
685 result.SetStatus (eReturnStatusFailed);
686 }
687 return result.Succeeded();
688 }
689};
690
691
692//-------------------------------------------------------------------------
693// CommandObjectProcessInterrupt
694//-------------------------------------------------------------------------
695
696class CommandObjectProcessInterrupt : public CommandObject
697{
698public:
699
700
701 CommandObjectProcessInterrupt () :
702 CommandObject ("process interrupt",
703 "Interrupts the current process being debugged.",
704 "process interrupt",
705 eFlagProcessMustBeLaunched)
706 {
707 }
708
709 ~CommandObjectProcessInterrupt ()
710 {
711 }
712
713 bool
714 Execute (Args& command,
715 CommandContext *context,
716 CommandInterpreter *interpreter,
717 CommandReturnObject &result)
718 {
719 Process *process = context->GetExecutionContext().process;
720 if (process == NULL)
721 {
722 result.AppendError ("no process to halt");
723 result.SetStatus (eReturnStatusFailed);
724 return false;
725 }
726
727 if (command.GetArgumentCount() == 0)
728 {
729 Error error(process->Halt ());
730 if (error.Success())
731 {
732 result.SetStatus (eReturnStatusSuccessFinishResult);
733
734 // Maybe we should add a "SuspendThreadPlans so we
735 // can halt, and keep in place all the current thread plans.
736 process->GetThreadList().DiscardThreadPlans();
737 }
738 else
739 {
740 result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString());
741 result.SetStatus (eReturnStatusFailed);
742 }
743 }
744 else
745 {
746 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
747 m_cmd_name.c_str(),
748 m_cmd_syntax.c_str());
749 result.SetStatus (eReturnStatusFailed);
750 }
751 return result.Succeeded();
752 }
753};
754
755//-------------------------------------------------------------------------
756// CommandObjectProcessKill
757//-------------------------------------------------------------------------
758
759class CommandObjectProcessKill : public CommandObject
760{
761public:
762
763 CommandObjectProcessKill () :
764 CommandObject ("process kill",
765 "Terminates the current process being debugged.",
766 "process kill",
767 eFlagProcessMustBeLaunched)
768 {
769 }
770
771 ~CommandObjectProcessKill ()
772 {
773 }
774
775 bool
776 Execute (Args& command,
777 CommandContext *context,
778 CommandInterpreter *interpreter,
779 CommandReturnObject &result)
780 {
781 Process *process = context->GetExecutionContext().process;
782 if (process == NULL)
783 {
784 result.AppendError ("no process to kill");
785 result.SetStatus (eReturnStatusFailed);
786 return false;
787 }
788
789 if (command.GetArgumentCount() == 0)
790 {
791 Error error (process->Destroy());
792 if (error.Success())
793 {
794 result.SetStatus (eReturnStatusSuccessFinishResult);
795 }
796 else
797 {
798 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString());
799 result.SetStatus (eReturnStatusFailed);
800 }
801 }
802 else
803 {
804 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
805 m_cmd_name.c_str(),
806 m_cmd_syntax.c_str());
807 result.SetStatus (eReturnStatusFailed);
808 }
809 return result.Succeeded();
810 }
811};
812
813//-------------------------------------------------------------------------
Jim Ingham41313fc2010-06-18 01:23:09 +0000814// CommandObjectProcessStatus
815//-------------------------------------------------------------------------
816class CommandObjectProcessStatus : public CommandObject
817{
818public:
819 CommandObjectProcessStatus () :
820 CommandObject ("status",
821 "Shows the current status and location of executing process.",
822 "status",
823 0)
824 {
825 }
826
827 ~CommandObjectProcessStatus()
828 {
829 }
830
831
832 bool
833 Execute
834 (
835 Args& command,
836 CommandContext *context,
837 CommandInterpreter *interpreter,
838 CommandReturnObject &result
839 )
840 {
841 StreamString &output_stream = result.GetOutputStream();
842 result.SetStatus (eReturnStatusSuccessFinishNoResult);
843 ExecutionContext exe_ctx(context->GetExecutionContext());
844 if (exe_ctx.process)
845 {
846 const StateType state = exe_ctx.process->GetState();
847 if (StateIsStoppedState(state))
848 {
849 if (state == eStateExited)
850 {
851 int exit_status = exe_ctx.process->GetExitStatus();
852 const char *exit_description = exe_ctx.process->GetExitDescription();
853 output_stream.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n",
854 exe_ctx.process->GetID(),
855 exit_status,
856 exit_status,
857 exit_description ? exit_description : "");
858 }
859 else
860 {
861 output_stream.Printf ("Process %d %s\n", exe_ctx.process->GetID(), StateAsCString (state));
862 if (exe_ctx.thread == NULL)
863 exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
864 if (exe_ctx.thread != NULL)
865 {
866 DisplayThreadsInfo (interpreter, &exe_ctx, result, true, true);
867 }
868 else
869 {
870 result.AppendError ("No valid thread found in current process.");
871 result.SetStatus (eReturnStatusFailed);
872 }
873 }
874 }
875 else
876 {
877 output_stream.Printf ("Process %d is running.\n",
878 exe_ctx.process->GetID());
879 }
880 }
881 else
882 {
883 result.AppendError ("No current location or status available.");
884 result.SetStatus (eReturnStatusFailed);
885 }
886 return result.Succeeded();
887 }
888};
889
890//-------------------------------------------------------------------------
Chris Lattner24943d22010-06-08 16:52:24 +0000891// CommandObjectMultiwordProcess
892//-------------------------------------------------------------------------
893
894CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter *interpreter) :
895 CommandObjectMultiword ("process",
896 "A set of commands for operating on a process.",
897 "process <subcommand> [<subcommand-options>]")
898{
899 LoadSubCommand (CommandObjectSP (new CommandObjectProcessAttach ()), "attach", interpreter);
900 LoadSubCommand (CommandObjectSP (new CommandObjectProcessLaunch ()), "launch", interpreter);
901 LoadSubCommand (CommandObjectSP (new CommandObjectProcessContinue ()), "continue", interpreter);
902 LoadSubCommand (CommandObjectSP (new CommandObjectProcessDetach ()), "detach", interpreter);
903 LoadSubCommand (CommandObjectSP (new CommandObjectProcessSignal ()), "signal", interpreter);
Jim Ingham41313fc2010-06-18 01:23:09 +0000904 LoadSubCommand (CommandObjectSP (new CommandObjectProcessStatus ()), "status", interpreter);
Chris Lattner24943d22010-06-08 16:52:24 +0000905 LoadSubCommand (CommandObjectSP (new CommandObjectProcessInterrupt ()), "interrupt", interpreter);
906 LoadSubCommand (CommandObjectSP (new CommandObjectProcessKill ()), "kill", interpreter);
907}
908
909CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess ()
910{
911}
912