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