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