blob: 20b008ff5a5c1349cb6f4ffd7e1b85474d506e19 [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
Jim Ingham767af882010-07-07 03:36:20 +0000250 virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
251 {
252 // No repeat for "process launch"...
253 return "";
254 }
255
Chris Lattner24943d22010-06-08 16:52:24 +0000256protected:
257
258 CommandOptions m_options;
259};
260
261
262lldb::OptionDefinition
263CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
264{
Jim Ingham34e9a982010-06-15 18:47:14 +0000265{ 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."},
266{ LLDB_OPT_SET_1, false, "stdin", 'i', required_argument, NULL, 0, "<path>", "Redirect stdin for the process to <path>."},
267{ LLDB_OPT_SET_1, false, "stdout", 'o', required_argument, NULL, 0, "<path>", "Redirect stdout for the process to <path>."},
268{ LLDB_OPT_SET_1, false, "stderr", 'e', required_argument, NULL, 0, "<path>", "Redirect stderr for the process to <path>."},
269{ 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 +0000270{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
271};
272
273
274//-------------------------------------------------------------------------
275// CommandObjectProcessAttach
276//-------------------------------------------------------------------------
277
278class CommandObjectProcessAttach : public CommandObject
279{
280public:
281
282 CommandObjectProcessAttach () :
283 CommandObject ("process attach",
284 "Attaches to a process.",
285 "process attach <cmd-options>")
286 {
287 SetHelpLong("Currently, you must set the executable file before you can attach "
288 "to a process.\n");
289 }
290
291 ~CommandObjectProcessAttach ()
292 {
293 }
294
295 bool
Greg Clayton63094e02010-06-23 01:19:29 +0000296 Execute (CommandInterpreter &interpreter,
297 Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000298 CommandReturnObject &result)
299 {
Greg Clayton63094e02010-06-23 01:19:29 +0000300 Target *target = interpreter.GetDebugger().GetCurrentTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000301 if (target == NULL)
302 {
303 result.AppendError ("invalid target, set executable file using 'file' command");
304 result.SetStatus (eReturnStatusFailed);
305 return false;
306 }
307
308 // If our listener is NULL, users aren't allows to launch
Greg Clayton63094e02010-06-23 01:19:29 +0000309
310 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000311 if (process)
312 {
313 if (process->IsAlive())
314 {
315 result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before attaching.\n", process->GetID());
316 result.SetStatus (eReturnStatusFailed);
317 return false;
318 }
319 }
320
321 if (command.GetArgumentCount())
322 {
323 result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
324 result.SetStatus (eReturnStatusFailed);
325 }
326 else
327 {
328 const char *plugin_name = NULL;
329
330 if (!m_options.plugin_name.empty())
331 plugin_name = m_options.plugin_name.c_str();
332
Greg Clayton63094e02010-06-23 01:19:29 +0000333 process = target->CreateProcess (interpreter.GetDebugger().GetListener(), plugin_name).get();
Chris Lattner24943d22010-06-08 16:52:24 +0000334
335 if (process)
336 {
337 Error error;
338 int attach_pid = m_options.pid;
339
340 if (attach_pid != LLDB_INVALID_PROCESS_ID)
341 {
342 error = process->Attach (attach_pid);
343 if (error.Success())
344 {
345 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
346 }
347 else
348 {
349 result.AppendErrorWithFormat ("Attaching to process %i failed: %s.\n",
350 attach_pid,
351 error.AsCString());
352 result.SetStatus (eReturnStatusFailed);
353 }
354 }
355 else if (!m_options.name.empty())
356 {
357 error = process->Attach (m_options.name.c_str(), m_options.waitfor);
358 if (error.Success())
359 {
360 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
361 }
362 else
363 {
364 if (m_options.waitfor)
365 result.AppendErrorWithFormat ("Waiting for a process to launch named '%s': %s\n",
366 m_options.name.c_str(),
367 error.AsCString());
368 else
369 result.AppendErrorWithFormat ("Failed to a process named '%s': %s\n",
370 m_options.name.c_str(),
371 error.AsCString());
372 result.SetStatus (eReturnStatusFailed);
373 }
374 }
375 }
376 }
377 return result.Succeeded();
378 }
379
380 Options *
381 GetOptions ()
382 {
383 return &m_options;
384 }
385
386 class CommandOptions : public Options
387 {
388 public:
389
390 CommandOptions () :
391 Options()
392 {
393 // Keep default values of all options in one place: ResetOptionValues ()
394 ResetOptionValues ();
395 }
396
397 ~CommandOptions ()
398 {
399 }
400
401 Error
402 SetOptionValue (int option_idx, const char *option_arg)
403 {
404 Error error;
405 char short_option = (char) m_getopt_table[option_idx].val;
406 bool success = false;
407 switch (short_option)
408 {
409 case 'p':
410 pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success);
411 if (!success || pid == LLDB_INVALID_PROCESS_ID)
412 {
413 error.SetErrorStringWithFormat("Invalid process ID '%s'.\n", option_arg);
414 }
415 break;
416
417 case 'P':
418 plugin_name = option_arg;
419 break;
420
421 case 'n':
422 name.assign(option_arg);
423 break;
424
425 case 'w':
426 waitfor = true;
427 break;
428
429 default:
430 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
431 break;
432 }
433 return error;
434 }
435
436 void
437 ResetOptionValues ()
438 {
439 Options::ResetOptionValues();
440 pid = LLDB_INVALID_PROCESS_ID;
441 name.clear();
442 waitfor = false;
443 }
444
445 const lldb::OptionDefinition*
446 GetDefinitions ()
447 {
448 return g_option_table;
449 }
450
451 // Options table: Required for subclasses of Options.
452
453 static lldb::OptionDefinition g_option_table[];
454
455 // Instance variables to hold the values for command options.
456
457 lldb::pid_t pid;
458 std::string plugin_name;
459 std::string name;
460 bool waitfor;
461 };
462
463protected:
464
465 CommandOptions m_options;
466};
467
468
469lldb::OptionDefinition
470CommandObjectProcessAttach::CommandOptions::g_option_table[] =
471{
Jim Ingham34e9a982010-06-15 18:47:14 +0000472{ LLDB_OPT_SET_ALL, false, "plugin", 'P', required_argument, NULL, 0, "<plugin>", "Name of the process plugin you want to use."},
473{ LLDB_OPT_SET_1, false, "pid", 'p', required_argument, NULL, 0, "<pid>", "The process ID of an existing process to attach to."},
474{ LLDB_OPT_SET_2, true, "name", 'n', required_argument, NULL, 0, "<process-name>", "The name of the process to attach to."},
475{ 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 +0000476{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
477};
478
479//-------------------------------------------------------------------------
480// CommandObjectProcessContinue
481//-------------------------------------------------------------------------
482
483class CommandObjectProcessContinue : public CommandObject
484{
485public:
486
487 CommandObjectProcessContinue () :
488 CommandObject ("process continue",
489 "Continues execution all threads in the current process.",
490 "process continue",
491 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
492 {
493 }
494
495
496 ~CommandObjectProcessContinue ()
497 {
498 }
499
500 bool
Greg Clayton63094e02010-06-23 01:19:29 +0000501 Execute (CommandInterpreter &interpreter,
502 Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000503 CommandReturnObject &result)
504 {
Greg Clayton63094e02010-06-23 01:19:29 +0000505 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
506 bool synchronous_execution = interpreter.GetSynchronous ();
Chris Lattner24943d22010-06-08 16:52:24 +0000507
508 if (process == NULL)
509 {
510 result.AppendError ("no process to continue");
511 result.SetStatus (eReturnStatusFailed);
512 return false;
513 }
514
515 StateType state = process->GetState();
516 if (state == eStateStopped)
517 {
518 if (command.GetArgumentCount() != 0)
519 {
520 result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str());
521 result.SetStatus (eReturnStatusFailed);
522 return false;
523 }
524
525 const uint32_t num_threads = process->GetThreadList().GetSize();
526
527 // Set the actions that the threads should each take when resuming
528 for (uint32_t idx=0; idx<num_threads; ++idx)
529 {
530 process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning);
531 }
532
533 Error error(process->Resume());
534 if (error.Success())
535 {
536 result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID());
537 if (synchronous_execution)
538 {
Greg Claytonbef15832010-07-14 00:18:15 +0000539 state = process->WaitForProcessToStop (NULL);
Chris Lattner24943d22010-06-08 16:52:24 +0000540
541 result.SetDidChangeProcessState (true);
542 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
543 result.SetStatus (eReturnStatusSuccessFinishNoResult);
544 }
545 else
546 {
547 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
548 }
549 }
550 else
551 {
552 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
553 result.SetStatus (eReturnStatusFailed);
554 }
555 }
556 else
557 {
558 result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
559 StateAsCString(state));
560 result.SetStatus (eReturnStatusFailed);
561 }
562 return result.Succeeded();
563 }
564};
565
566//-------------------------------------------------------------------------
567// CommandObjectProcessDetach
568//-------------------------------------------------------------------------
569
570class CommandObjectProcessDetach : public CommandObject
571{
572public:
573
574 CommandObjectProcessDetach () :
575 CommandObject ("process detach",
576 "Detaches from the current process being debugged.",
577 "process detach",
578 eFlagProcessMustBeLaunched)
579 {
580 }
581
582 ~CommandObjectProcessDetach ()
583 {
584 }
585
586 bool
Greg Clayton63094e02010-06-23 01:19:29 +0000587 Execute (CommandInterpreter &interpreter,
588 Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000589 CommandReturnObject &result)
590 {
Greg Clayton63094e02010-06-23 01:19:29 +0000591 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000592 if (process == NULL)
593 {
594 result.AppendError ("must have a valid process in order to detach");
595 result.SetStatus (eReturnStatusFailed);
596 return false;
597 }
598
599 Error error (process->Detach());
600 if (error.Success())
601 {
602 result.SetStatus (eReturnStatusSuccessFinishResult);
603 }
604 else
605 {
606 result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString());
607 result.SetStatus (eReturnStatusFailed);
608 return false;
609 }
610 return result.Succeeded();
611 }
612};
613
614//-------------------------------------------------------------------------
615// CommandObjectProcessSignal
616//-------------------------------------------------------------------------
617
618class CommandObjectProcessSignal : public CommandObject
619{
620public:
621
622 CommandObjectProcessSignal () :
623 CommandObject ("process signal",
624 "Sends a UNIX signal to the current process being debugged.",
625 "process signal <unix-signal-number>")
626 {
627 }
628
629 ~CommandObjectProcessSignal ()
630 {
631 }
632
633 bool
Greg Clayton63094e02010-06-23 01:19:29 +0000634 Execute (CommandInterpreter &interpreter,
635 Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000636 CommandReturnObject &result)
637 {
Greg Clayton63094e02010-06-23 01:19:29 +0000638 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000639 if (process == NULL)
640 {
641 result.AppendError ("no process to signal");
642 result.SetStatus (eReturnStatusFailed);
643 return false;
644 }
645
646 if (command.GetArgumentCount() == 1)
647 {
648 int signo = Args::StringToSInt32(command.GetArgumentAtIndex(0), -1, 0);
649 if (signo == -1)
650 {
651 result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0));
652 result.SetStatus (eReturnStatusFailed);
653 }
654 else
655 {
656 Error error (process->Signal (signo));
657 if (error.Success())
658 {
659 result.SetStatus (eReturnStatusSuccessFinishResult);
660 }
661 else
662 {
663 result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString());
664 result.SetStatus (eReturnStatusFailed);
665 }
666 }
667 }
668 else
669 {
670 result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: \n", m_cmd_name.c_str(),
671 m_cmd_syntax.c_str());
672 result.SetStatus (eReturnStatusFailed);
673 }
674 return result.Succeeded();
675 }
676};
677
678
679//-------------------------------------------------------------------------
680// CommandObjectProcessInterrupt
681//-------------------------------------------------------------------------
682
683class CommandObjectProcessInterrupt : public CommandObject
684{
685public:
686
687
688 CommandObjectProcessInterrupt () :
689 CommandObject ("process interrupt",
690 "Interrupts the current process being debugged.",
691 "process interrupt",
692 eFlagProcessMustBeLaunched)
693 {
694 }
695
696 ~CommandObjectProcessInterrupt ()
697 {
698 }
699
700 bool
Greg Clayton63094e02010-06-23 01:19:29 +0000701 Execute (CommandInterpreter &interpreter,
702 Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000703 CommandReturnObject &result)
704 {
Greg Clayton63094e02010-06-23 01:19:29 +0000705 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000706 if (process == NULL)
707 {
708 result.AppendError ("no process to halt");
709 result.SetStatus (eReturnStatusFailed);
710 return false;
711 }
712
713 if (command.GetArgumentCount() == 0)
714 {
715 Error error(process->Halt ());
716 if (error.Success())
717 {
718 result.SetStatus (eReturnStatusSuccessFinishResult);
719
720 // Maybe we should add a "SuspendThreadPlans so we
721 // can halt, and keep in place all the current thread plans.
722 process->GetThreadList().DiscardThreadPlans();
723 }
724 else
725 {
726 result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString());
727 result.SetStatus (eReturnStatusFailed);
728 }
729 }
730 else
731 {
732 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
733 m_cmd_name.c_str(),
734 m_cmd_syntax.c_str());
735 result.SetStatus (eReturnStatusFailed);
736 }
737 return result.Succeeded();
738 }
739};
740
741//-------------------------------------------------------------------------
742// CommandObjectProcessKill
743//-------------------------------------------------------------------------
744
745class CommandObjectProcessKill : public CommandObject
746{
747public:
748
749 CommandObjectProcessKill () :
750 CommandObject ("process kill",
751 "Terminates the current process being debugged.",
752 "process kill",
753 eFlagProcessMustBeLaunched)
754 {
755 }
756
757 ~CommandObjectProcessKill ()
758 {
759 }
760
761 bool
Greg Clayton63094e02010-06-23 01:19:29 +0000762 Execute (CommandInterpreter &interpreter,
763 Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000764 CommandReturnObject &result)
765 {
Greg Clayton63094e02010-06-23 01:19:29 +0000766 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000767 if (process == NULL)
768 {
769 result.AppendError ("no process to kill");
770 result.SetStatus (eReturnStatusFailed);
771 return false;
772 }
773
774 if (command.GetArgumentCount() == 0)
775 {
776 Error error (process->Destroy());
777 if (error.Success())
778 {
779 result.SetStatus (eReturnStatusSuccessFinishResult);
780 }
781 else
782 {
783 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString());
784 result.SetStatus (eReturnStatusFailed);
785 }
786 }
787 else
788 {
789 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
790 m_cmd_name.c_str(),
791 m_cmd_syntax.c_str());
792 result.SetStatus (eReturnStatusFailed);
793 }
794 return result.Succeeded();
795 }
796};
797
798//-------------------------------------------------------------------------
Jim Ingham41313fc2010-06-18 01:23:09 +0000799// CommandObjectProcessStatus
800//-------------------------------------------------------------------------
801class CommandObjectProcessStatus : public CommandObject
802{
803public:
804 CommandObjectProcessStatus () :
805 CommandObject ("status",
806 "Shows the current status and location of executing process.",
807 "status",
808 0)
809 {
810 }
811
812 ~CommandObjectProcessStatus()
813 {
814 }
815
816
817 bool
818 Execute
819 (
Greg Clayton63094e02010-06-23 01:19:29 +0000820 CommandInterpreter &interpreter,
Jim Ingham41313fc2010-06-18 01:23:09 +0000821 Args& command,
Jim Ingham41313fc2010-06-18 01:23:09 +0000822 CommandReturnObject &result
823 )
824 {
825 StreamString &output_stream = result.GetOutputStream();
826 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Greg Clayton63094e02010-06-23 01:19:29 +0000827 ExecutionContext exe_ctx(interpreter.GetDebugger().GetExecutionContext());
Jim Ingham41313fc2010-06-18 01:23:09 +0000828 if (exe_ctx.process)
829 {
830 const StateType state = exe_ctx.process->GetState();
831 if (StateIsStoppedState(state))
832 {
833 if (state == eStateExited)
834 {
835 int exit_status = exe_ctx.process->GetExitStatus();
836 const char *exit_description = exe_ctx.process->GetExitDescription();
837 output_stream.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n",
838 exe_ctx.process->GetID(),
839 exit_status,
840 exit_status,
841 exit_description ? exit_description : "");
842 }
843 else
844 {
845 output_stream.Printf ("Process %d %s\n", exe_ctx.process->GetID(), StateAsCString (state));
846 if (exe_ctx.thread == NULL)
847 exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
848 if (exe_ctx.thread != NULL)
849 {
850 DisplayThreadsInfo (interpreter, &exe_ctx, result, true, true);
851 }
852 else
853 {
854 result.AppendError ("No valid thread found in current process.");
855 result.SetStatus (eReturnStatusFailed);
856 }
857 }
858 }
859 else
860 {
861 output_stream.Printf ("Process %d is running.\n",
862 exe_ctx.process->GetID());
863 }
864 }
865 else
866 {
867 result.AppendError ("No current location or status available.");
868 result.SetStatus (eReturnStatusFailed);
869 }
870 return result.Succeeded();
871 }
872};
873
874//-------------------------------------------------------------------------
Chris Lattner24943d22010-06-08 16:52:24 +0000875// CommandObjectMultiwordProcess
876//-------------------------------------------------------------------------
877
Greg Clayton63094e02010-06-23 01:19:29 +0000878CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter &interpreter) :
Chris Lattner24943d22010-06-08 16:52:24 +0000879 CommandObjectMultiword ("process",
880 "A set of commands for operating on a process.",
881 "process <subcommand> [<subcommand-options>]")
882{
Greg Clayton63094e02010-06-23 01:19:29 +0000883 LoadSubCommand (interpreter, "attach", CommandObjectSP (new CommandObjectProcessAttach ()));
884 LoadSubCommand (interpreter, "launch", CommandObjectSP (new CommandObjectProcessLaunch ()));
885 LoadSubCommand (interpreter, "continue", CommandObjectSP (new CommandObjectProcessContinue ()));
886 LoadSubCommand (interpreter, "detach", CommandObjectSP (new CommandObjectProcessDetach ()));
887 LoadSubCommand (interpreter, "signal", CommandObjectSP (new CommandObjectProcessSignal ()));
888 LoadSubCommand (interpreter, "status", CommandObjectSP (new CommandObjectProcessStatus ()));
889 LoadSubCommand (interpreter, "interrupt", CommandObjectSP (new CommandObjectProcessInterrupt ()));
890 LoadSubCommand (interpreter, "kill", CommandObjectSP (new CommandObjectProcessKill ()));
Chris Lattner24943d22010-06-08 16:52:24 +0000891}
892
893CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess ()
894{
895}
896