blob: 73386b4fe170ef14d57c9563c154e7f858a804fd [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 {
Jim Inghamc8332952010-08-26 21:32:51 +0000127 Target *target = interpreter.GetDebugger().GetSelectedTarget().get();
Greg Clayton63094e02010-06-23 01:19:29 +0000128 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();
Greg Clayton452bf612010-08-31 18:35:14 +0000166 uint32_t launch_flags = eLaunchFlagNone;
167 if (interpreter.GetDisableASLR())
168 launch_flags |= eLaunchFlagDisableASLR;
Chris Lattner24943d22010-06-08 16:52:24 +0000169
170 // There are two possible sources of args to be passed to the process upon launching: Those the user
171 // typed at the run command (launch_args); or those the user pre-set in the run-args variable (run_args).
172
173 // If launch_args is empty, use run_args.
174 if (launch_args.GetArgumentCount() == 0)
175 {
176 if (run_args != NULL)
177 launch_args.AppendArguments (*run_args);
178 }
179 else
180 {
181 // launch-args was not empty; use that, AND re-set run-args to contains launch-args values.
Greg Clayton63094e02010-06-23 01:19:29 +0000182 StateVariable *run_args_var = interpreter.GetStateVariable ("run-args");
Chris Lattner24943d22010-06-08 16:52:24 +0000183 if (run_args_var != NULL)
184 {
185 run_args_var->ArrayClearValues();
186 run_args_var->GetArgs().AppendArguments (launch_args);
187 }
188 }
189
190
191 if (process)
192 {
193 const char *archname = exe_module->GetArchitecture().AsCString();
194
195 const char * stdin_path = NULL;
196 const char * stdout_path = NULL;
197 const char * stderr_path = NULL;
198
199 if (!(m_options.stdin_path.empty() &&
200 m_options.stdout_path.empty() &&
201 m_options.stderr_path.empty()))
202 {
203 stdin_path = m_options.stdin_path.empty() ? "/dev/null" : m_options.stdin_path.c_str();
204 stdout_path = m_options.stdout_path.empty() ? "/dev/null" : m_options.stdout_path.c_str();
205 stderr_path = m_options.stderr_path.empty() ? "/dev/null" : m_options.stderr_path.c_str();
206 }
207
208 Error error (process->Launch (launch_args.GetConstArgumentVector(),
209 environment ? environment->GetConstArgumentVector() : NULL,
Greg Clayton452bf612010-08-31 18:35:14 +0000210 launch_flags,
Chris Lattner24943d22010-06-08 16:52:24 +0000211 stdin_path,
212 stdout_path,
213 stderr_path));
214
215 if (error.Success())
216 {
217 result.AppendMessageWithFormat ("Launching '%s' (%s)\n", filename, archname);
218 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
219 if (m_options.stop_at_entry == false)
220 {
221 StateType state = process->WaitForProcessToStop (NULL);
222
223 if (state == eStateStopped)
224 {
225 // Call continue_command.
226 CommandReturnObject continue_result;
Greg Clayton63094e02010-06-23 01:19:29 +0000227 interpreter.HandleCommand("process continue", false, continue_result);
Chris Lattner24943d22010-06-08 16:52:24 +0000228 }
229
230 if (synchronous_execution)
231 {
232 result.SetDidChangeProcessState (true);
233 result.SetStatus (eReturnStatusSuccessFinishNoResult);
234 }
235 }
236 }
237 else
238 {
239 result.AppendErrorWithFormat ("Process launch failed: %s",
240 error.AsCString());
241 result.SetStatus (eReturnStatusFailed);
242 }
243 }
244 else
245 {
246 result.AppendErrorWithFormat ("Process launch failed: unable to create a process object.\n");
247 result.SetStatus (eReturnStatusFailed);
248 return false;
249 }
250
251 return result.Succeeded();
252 }
253
Jim Ingham767af882010-07-07 03:36:20 +0000254 virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
255 {
256 // No repeat for "process launch"...
257 return "";
258 }
259
Chris Lattner24943d22010-06-08 16:52:24 +0000260protected:
261
262 CommandOptions m_options;
263};
264
265
266lldb::OptionDefinition
267CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
268{
Jim Ingham34e9a982010-06-15 18:47:14 +0000269{ 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."},
270{ LLDB_OPT_SET_1, false, "stdin", 'i', required_argument, NULL, 0, "<path>", "Redirect stdin for the process to <path>."},
271{ LLDB_OPT_SET_1, false, "stdout", 'o', required_argument, NULL, 0, "<path>", "Redirect stdout for the process to <path>."},
272{ LLDB_OPT_SET_1, false, "stderr", 'e', required_argument, NULL, 0, "<path>", "Redirect stderr for the process to <path>."},
273{ 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 +0000274{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
275};
276
277
278//-------------------------------------------------------------------------
279// CommandObjectProcessAttach
280//-------------------------------------------------------------------------
281
282class CommandObjectProcessAttach : public CommandObject
283{
284public:
285
Chris Lattner24943d22010-06-08 16:52:24 +0000286 class CommandOptions : public Options
287 {
288 public:
289
290 CommandOptions () :
291 Options()
292 {
293 // Keep default values of all options in one place: ResetOptionValues ()
294 ResetOptionValues ();
295 }
296
297 ~CommandOptions ()
298 {
299 }
300
301 Error
302 SetOptionValue (int option_idx, const char *option_arg)
303 {
304 Error error;
305 char short_option = (char) m_getopt_table[option_idx].val;
306 bool success = false;
307 switch (short_option)
308 {
309 case 'p':
310 pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success);
311 if (!success || pid == LLDB_INVALID_PROCESS_ID)
312 {
313 error.SetErrorStringWithFormat("Invalid process ID '%s'.\n", option_arg);
314 }
315 break;
316
317 case 'P':
318 plugin_name = option_arg;
319 break;
320
321 case 'n':
322 name.assign(option_arg);
323 break;
324
325 case 'w':
326 waitfor = true;
327 break;
328
329 default:
330 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
331 break;
332 }
333 return error;
334 }
335
336 void
337 ResetOptionValues ()
338 {
339 Options::ResetOptionValues();
340 pid = LLDB_INVALID_PROCESS_ID;
341 name.clear();
342 waitfor = false;
343 }
344
345 const lldb::OptionDefinition*
346 GetDefinitions ()
347 {
348 return g_option_table;
349 }
350
Jim Ingham7508e732010-08-09 23:31:02 +0000351 virtual bool
352 HandleOptionArgumentCompletion (CommandInterpreter &interpreter,
353 Args &input,
354 int cursor_index,
355 int char_pos,
356 OptionElementVector &opt_element_vector,
357 int opt_element_index,
358 int match_start_point,
359 int max_return_elements,
360 bool &word_complete,
361 StringList &matches)
362 {
363 int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
364 int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
365
366 // We are only completing the name option for now...
367
368 const lldb::OptionDefinition *opt_defs = GetDefinitions();
369 if (opt_defs[opt_defs_index].short_option == 'n')
370 {
371 // Are we in the name?
372
373 // Look to see if there is a -P argument provided, and if so use that plugin, otherwise
374 // use the default plugin.
375 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
376 bool need_to_delete_process = false;
377
378 const char *partial_name = NULL;
379 partial_name = input.GetArgumentAtIndex(opt_arg_pos);
380
381 if (process && process->IsAlive())
382 return true;
383
Jim Inghamc8332952010-08-26 21:32:51 +0000384 Target *target = interpreter.GetDebugger().GetSelectedTarget().get();
Jim Ingham7508e732010-08-09 23:31:02 +0000385 if (target == NULL)
386 {
387 // No target has been set yet, for now do host completion. Otherwise I don't know how we would
388 // figure out what the right target to use is...
389 std::vector<lldb::pid_t> pids;
390 Host::ListProcessesMatchingName (partial_name, matches, pids);
391 return true;
392 }
393 if (!process)
394 {
395 process = target->CreateProcess (interpreter.GetDebugger().GetListener(), partial_name).get();
396 need_to_delete_process = true;
397 }
398
399 if (process)
400 {
401 matches.Clear();
402 std::vector<lldb::pid_t> pids;
403 process->ListProcessesMatchingName (NULL, matches, pids);
404 if (need_to_delete_process)
405 target->DeleteCurrentProcess();
406 return true;
407 }
408 }
409
410 return false;
411 }
412
Chris Lattner24943d22010-06-08 16:52:24 +0000413 // Options table: Required for subclasses of Options.
414
415 static lldb::OptionDefinition g_option_table[];
416
417 // Instance variables to hold the values for command options.
418
419 lldb::pid_t pid;
420 std::string plugin_name;
421 std::string name;
422 bool waitfor;
423 };
424
Jim Ingham7508e732010-08-09 23:31:02 +0000425 CommandObjectProcessAttach () :
426 CommandObject ("process attach",
427 "Attaches to a process.",
428 "process attach <cmd-options>")
429 {
430 SetHelpLong("Currently, you must set the executable file before you can attach "
431 "to a process.\n");
432 }
433
434 ~CommandObjectProcessAttach ()
435 {
436 }
437
438 bool
439 Execute (CommandInterpreter &interpreter,
440 Args& command,
441 CommandReturnObject &result)
442 {
Jim Inghamc8332952010-08-26 21:32:51 +0000443 Target *target = interpreter.GetDebugger().GetSelectedTarget().get();
Jim Ingham7508e732010-08-09 23:31:02 +0000444
445 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
446 if (process)
447 {
448 if (process->IsAlive())
449 {
450 result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before attaching.\n",
451 process->GetID());
452 result.SetStatus (eReturnStatusFailed);
453 return false;
454 }
455 }
456
457 if (target == NULL)
458 {
459 // If there isn't a current target create one.
460 TargetSP new_target_sp;
461 FileSpec emptyFileSpec;
462 ArchSpec emptyArchSpec;
463 Error error;
464
465 error = interpreter.GetDebugger().GetTargetList().CreateTarget(interpreter.GetDebugger(),
466 emptyFileSpec,
467 emptyArchSpec,
468 NULL,
469 false,
470 new_target_sp);
471 target = new_target_sp.get();
472 if (target == NULL || error.Fail())
473 {
474 result.AppendError(error.AsCString("Error creating empty target"));
475 return false;
476 }
Jim Inghamc8332952010-08-26 21:32:51 +0000477 interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target);
Jim Ingham7508e732010-08-09 23:31:02 +0000478 }
479
480 // Record the old executable module, we want to issue a warning if the process of attaching changed the
481 // current executable (like somebody said "file foo" then attached to a PID whose executable was bar.)
482
483 ModuleSP old_exec_module_sp = target->GetExecutableModule();
484 ArchSpec old_arch_spec = target->GetArchitecture();
485
486 if (command.GetArgumentCount())
487 {
488 result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
489 result.SetStatus (eReturnStatusFailed);
490 }
491 else
492 {
493 const char *plugin_name = NULL;
494
495 if (!m_options.plugin_name.empty())
496 plugin_name = m_options.plugin_name.c_str();
497
498 process = target->CreateProcess (interpreter.GetDebugger().GetListener(), plugin_name).get();
499
500 if (process)
501 {
502 Error error;
503 int attach_pid = m_options.pid;
504
505 // If we are waiting for a process with this name to show up, do that first.
506 if (m_options.waitfor)
507 {
508 if (m_options.name.empty())
509 {
510 result.AppendError("Invalid arguments: must supply a process name with the waitfor option.\n");
511 result.SetStatus (eReturnStatusFailed);
512 return false;
513 }
514 else
515 {
516 error = process->Attach (m_options.name.c_str(), m_options.waitfor);
517 if (error.Success())
518 {
519 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
520 }
521 else
522 {
523 result.AppendErrorWithFormat ("Waiting for a process to launch named '%s': %s\n",
524 m_options.name.c_str(),
525 error.AsCString());
526 result.SetStatus (eReturnStatusFailed);
527 return false;
528 }
529 }
530 }
531 else
532 {
533 // If the process was specified by name look it up, so we can warn if there are multiple
534 // processes with this pid.
535
536 if (attach_pid == LLDB_INVALID_PROCESS_ID && !m_options.name.empty())
537 {
538 std::vector<lldb::pid_t> pids;
539 StringList matches;
540
541 process->ListProcessesMatchingName(m_options.name.c_str(), matches, pids);
542 if (matches.GetSize() > 1)
543 {
544 result.AppendErrorWithFormat("More than one process named %s\n", m_options.name.c_str());
545 result.SetStatus (eReturnStatusFailed);
546 return false;
547 }
548 else if (matches.GetSize() == 0)
549 {
550 result.AppendErrorWithFormat("Could not find a process named %s\n", m_options.name.c_str());
551 result.SetStatus (eReturnStatusFailed);
552 return false;
553 }
554 else
555 {
556 attach_pid = pids[0];
557 }
558
559 }
560
561 if (attach_pid != LLDB_INVALID_PROCESS_ID)
562 {
563 error = process->Attach (attach_pid);
564 if (error.Success())
565 {
566 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
567 }
568 else
569 {
570 result.AppendErrorWithFormat ("Attaching to process %i failed: %s.\n",
571 attach_pid,
572 error.AsCString());
573 result.SetStatus (eReturnStatusFailed);
574 }
575 }
576 else
577 {
578 result.AppendErrorWithFormat ("No PID specified for attach\n",
579 attach_pid,
580 error.AsCString());
581 result.SetStatus (eReturnStatusFailed);
582
583 }
584 }
585 }
586 }
587
588 if (result.Succeeded())
589 {
590 // Okay, we're done. Last step is to warn if the executable module has changed:
591 if (!old_exec_module_sp)
592 {
593 char new_path[PATH_MAX + 1];
594 target->GetExecutableModule()->GetFileSpec().GetPath(new_path, PATH_MAX);
595
596 result.AppendMessageWithFormat("Executable module set to \"%s\".\n",
597 new_path);
598 }
599 else if (old_exec_module_sp->GetFileSpec() != target->GetExecutableModule()->GetFileSpec())
600 {
601 char old_path[PATH_MAX + 1];
602 char new_path[PATH_MAX + 1];
603
604 old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX);
605 target->GetExecutableModule()->GetFileSpec().GetPath (new_path, PATH_MAX);
606
607 result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n",
608 old_path, new_path);
609 }
610
611 if (!old_arch_spec.IsValid())
612 {
613 result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().AsCString());
614 }
615 else if (old_arch_spec != target->GetArchitecture())
616 {
617 result.AppendWarningWithFormat("Architecture changed from %s to %s.\n",
618 old_arch_spec.AsCString(), target->GetArchitecture().AsCString());
619 }
620 }
621 return result.Succeeded();
622 }
623
624 Options *
625 GetOptions ()
626 {
627 return &m_options;
628 }
629
Chris Lattner24943d22010-06-08 16:52:24 +0000630protected:
631
632 CommandOptions m_options;
633};
634
635
636lldb::OptionDefinition
637CommandObjectProcessAttach::CommandOptions::g_option_table[] =
638{
Jim Ingham34e9a982010-06-15 18:47:14 +0000639{ LLDB_OPT_SET_ALL, false, "plugin", 'P', required_argument, NULL, 0, "<plugin>", "Name of the process plugin you want to use."},
640{ LLDB_OPT_SET_1, false, "pid", 'p', required_argument, NULL, 0, "<pid>", "The process ID of an existing process to attach to."},
641{ LLDB_OPT_SET_2, true, "name", 'n', required_argument, NULL, 0, "<process-name>", "The name of the process to attach to."},
642{ 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 +0000643{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
644};
645
646//-------------------------------------------------------------------------
647// CommandObjectProcessContinue
648//-------------------------------------------------------------------------
649
650class CommandObjectProcessContinue : public CommandObject
651{
652public:
653
654 CommandObjectProcessContinue () :
655 CommandObject ("process continue",
656 "Continues execution all threads in the current process.",
657 "process continue",
658 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
659 {
660 }
661
662
663 ~CommandObjectProcessContinue ()
664 {
665 }
666
667 bool
Greg Clayton63094e02010-06-23 01:19:29 +0000668 Execute (CommandInterpreter &interpreter,
669 Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000670 CommandReturnObject &result)
671 {
Greg Clayton63094e02010-06-23 01:19:29 +0000672 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
673 bool synchronous_execution = interpreter.GetSynchronous ();
Chris Lattner24943d22010-06-08 16:52:24 +0000674
675 if (process == NULL)
676 {
677 result.AppendError ("no process to continue");
678 result.SetStatus (eReturnStatusFailed);
679 return false;
680 }
681
682 StateType state = process->GetState();
683 if (state == eStateStopped)
684 {
685 if (command.GetArgumentCount() != 0)
686 {
687 result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str());
688 result.SetStatus (eReturnStatusFailed);
689 return false;
690 }
691
692 const uint32_t num_threads = process->GetThreadList().GetSize();
693
694 // Set the actions that the threads should each take when resuming
695 for (uint32_t idx=0; idx<num_threads; ++idx)
696 {
697 process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning);
698 }
699
700 Error error(process->Resume());
701 if (error.Success())
702 {
703 result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID());
704 if (synchronous_execution)
705 {
Greg Claytonbef15832010-07-14 00:18:15 +0000706 state = process->WaitForProcessToStop (NULL);
Chris Lattner24943d22010-06-08 16:52:24 +0000707
708 result.SetDidChangeProcessState (true);
709 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
710 result.SetStatus (eReturnStatusSuccessFinishNoResult);
711 }
712 else
713 {
714 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
715 }
716 }
717 else
718 {
719 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
720 result.SetStatus (eReturnStatusFailed);
721 }
722 }
723 else
724 {
725 result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
726 StateAsCString(state));
727 result.SetStatus (eReturnStatusFailed);
728 }
729 return result.Succeeded();
730 }
731};
732
733//-------------------------------------------------------------------------
734// CommandObjectProcessDetach
735//-------------------------------------------------------------------------
736
737class CommandObjectProcessDetach : public CommandObject
738{
739public:
740
741 CommandObjectProcessDetach () :
742 CommandObject ("process detach",
743 "Detaches from the current process being debugged.",
744 "process detach",
745 eFlagProcessMustBeLaunched)
746 {
747 }
748
749 ~CommandObjectProcessDetach ()
750 {
751 }
752
753 bool
Greg Clayton63094e02010-06-23 01:19:29 +0000754 Execute (CommandInterpreter &interpreter,
755 Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000756 CommandReturnObject &result)
757 {
Greg Clayton63094e02010-06-23 01:19:29 +0000758 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000759 if (process == NULL)
760 {
761 result.AppendError ("must have a valid process in order to detach");
762 result.SetStatus (eReturnStatusFailed);
763 return false;
764 }
765
766 Error error (process->Detach());
767 if (error.Success())
768 {
769 result.SetStatus (eReturnStatusSuccessFinishResult);
770 }
771 else
772 {
773 result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString());
774 result.SetStatus (eReturnStatusFailed);
775 return false;
776 }
777 return result.Succeeded();
778 }
779};
780
781//-------------------------------------------------------------------------
782// CommandObjectProcessSignal
783//-------------------------------------------------------------------------
784
785class CommandObjectProcessSignal : public CommandObject
786{
787public:
788
789 CommandObjectProcessSignal () :
790 CommandObject ("process signal",
791 "Sends a UNIX signal to the current process being debugged.",
792 "process signal <unix-signal-number>")
793 {
794 }
795
796 ~CommandObjectProcessSignal ()
797 {
798 }
799
800 bool
Greg Clayton63094e02010-06-23 01:19:29 +0000801 Execute (CommandInterpreter &interpreter,
802 Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000803 CommandReturnObject &result)
804 {
Greg Clayton63094e02010-06-23 01:19:29 +0000805 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000806 if (process == NULL)
807 {
808 result.AppendError ("no process to signal");
809 result.SetStatus (eReturnStatusFailed);
810 return false;
811 }
812
813 if (command.GetArgumentCount() == 1)
814 {
815 int signo = Args::StringToSInt32(command.GetArgumentAtIndex(0), -1, 0);
816 if (signo == -1)
817 {
818 result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0));
819 result.SetStatus (eReturnStatusFailed);
820 }
821 else
822 {
823 Error error (process->Signal (signo));
824 if (error.Success())
825 {
826 result.SetStatus (eReturnStatusSuccessFinishResult);
827 }
828 else
829 {
830 result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString());
831 result.SetStatus (eReturnStatusFailed);
832 }
833 }
834 }
835 else
836 {
837 result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: \n", m_cmd_name.c_str(),
838 m_cmd_syntax.c_str());
839 result.SetStatus (eReturnStatusFailed);
840 }
841 return result.Succeeded();
842 }
843};
844
845
846//-------------------------------------------------------------------------
847// CommandObjectProcessInterrupt
848//-------------------------------------------------------------------------
849
850class CommandObjectProcessInterrupt : public CommandObject
851{
852public:
853
854
855 CommandObjectProcessInterrupt () :
856 CommandObject ("process interrupt",
857 "Interrupts the current process being debugged.",
858 "process interrupt",
859 eFlagProcessMustBeLaunched)
860 {
861 }
862
863 ~CommandObjectProcessInterrupt ()
864 {
865 }
866
867 bool
Greg Clayton63094e02010-06-23 01:19:29 +0000868 Execute (CommandInterpreter &interpreter,
869 Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000870 CommandReturnObject &result)
871 {
Greg Clayton63094e02010-06-23 01:19:29 +0000872 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000873 if (process == NULL)
874 {
875 result.AppendError ("no process to halt");
876 result.SetStatus (eReturnStatusFailed);
877 return false;
878 }
879
880 if (command.GetArgumentCount() == 0)
881 {
882 Error error(process->Halt ());
883 if (error.Success())
884 {
885 result.SetStatus (eReturnStatusSuccessFinishResult);
886
887 // Maybe we should add a "SuspendThreadPlans so we
888 // can halt, and keep in place all the current thread plans.
889 process->GetThreadList().DiscardThreadPlans();
890 }
891 else
892 {
893 result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString());
894 result.SetStatus (eReturnStatusFailed);
895 }
896 }
897 else
898 {
899 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
900 m_cmd_name.c_str(),
901 m_cmd_syntax.c_str());
902 result.SetStatus (eReturnStatusFailed);
903 }
904 return result.Succeeded();
905 }
906};
907
908//-------------------------------------------------------------------------
909// CommandObjectProcessKill
910//-------------------------------------------------------------------------
911
912class CommandObjectProcessKill : public CommandObject
913{
914public:
915
916 CommandObjectProcessKill () :
917 CommandObject ("process kill",
918 "Terminates the current process being debugged.",
919 "process kill",
920 eFlagProcessMustBeLaunched)
921 {
922 }
923
924 ~CommandObjectProcessKill ()
925 {
926 }
927
928 bool
Greg Clayton63094e02010-06-23 01:19:29 +0000929 Execute (CommandInterpreter &interpreter,
930 Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000931 CommandReturnObject &result)
932 {
Greg Clayton63094e02010-06-23 01:19:29 +0000933 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000934 if (process == NULL)
935 {
936 result.AppendError ("no process to kill");
937 result.SetStatus (eReturnStatusFailed);
938 return false;
939 }
940
941 if (command.GetArgumentCount() == 0)
942 {
943 Error error (process->Destroy());
944 if (error.Success())
945 {
946 result.SetStatus (eReturnStatusSuccessFinishResult);
947 }
948 else
949 {
950 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString());
951 result.SetStatus (eReturnStatusFailed);
952 }
953 }
954 else
955 {
956 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
957 m_cmd_name.c_str(),
958 m_cmd_syntax.c_str());
959 result.SetStatus (eReturnStatusFailed);
960 }
961 return result.Succeeded();
962 }
963};
964
965//-------------------------------------------------------------------------
Jim Ingham41313fc2010-06-18 01:23:09 +0000966// CommandObjectProcessStatus
967//-------------------------------------------------------------------------
968class CommandObjectProcessStatus : public CommandObject
969{
970public:
971 CommandObjectProcessStatus () :
972 CommandObject ("status",
973 "Shows the current status and location of executing process.",
974 "status",
975 0)
976 {
977 }
978
979 ~CommandObjectProcessStatus()
980 {
981 }
982
983
984 bool
985 Execute
986 (
Greg Clayton63094e02010-06-23 01:19:29 +0000987 CommandInterpreter &interpreter,
Jim Ingham41313fc2010-06-18 01:23:09 +0000988 Args& command,
Jim Ingham41313fc2010-06-18 01:23:09 +0000989 CommandReturnObject &result
990 )
991 {
992 StreamString &output_stream = result.GetOutputStream();
993 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Greg Clayton63094e02010-06-23 01:19:29 +0000994 ExecutionContext exe_ctx(interpreter.GetDebugger().GetExecutionContext());
Jim Ingham41313fc2010-06-18 01:23:09 +0000995 if (exe_ctx.process)
996 {
997 const StateType state = exe_ctx.process->GetState();
998 if (StateIsStoppedState(state))
999 {
1000 if (state == eStateExited)
1001 {
1002 int exit_status = exe_ctx.process->GetExitStatus();
1003 const char *exit_description = exe_ctx.process->GetExitDescription();
1004 output_stream.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n",
1005 exe_ctx.process->GetID(),
1006 exit_status,
1007 exit_status,
1008 exit_description ? exit_description : "");
1009 }
1010 else
1011 {
1012 output_stream.Printf ("Process %d %s\n", exe_ctx.process->GetID(), StateAsCString (state));
1013 if (exe_ctx.thread == NULL)
1014 exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
1015 if (exe_ctx.thread != NULL)
1016 {
1017 DisplayThreadsInfo (interpreter, &exe_ctx, result, true, true);
1018 }
1019 else
1020 {
1021 result.AppendError ("No valid thread found in current process.");
1022 result.SetStatus (eReturnStatusFailed);
1023 }
1024 }
1025 }
1026 else
1027 {
1028 output_stream.Printf ("Process %d is running.\n",
1029 exe_ctx.process->GetID());
1030 }
1031 }
1032 else
1033 {
1034 result.AppendError ("No current location or status available.");
1035 result.SetStatus (eReturnStatusFailed);
1036 }
1037 return result.Succeeded();
1038 }
1039};
1040
1041//-------------------------------------------------------------------------
Chris Lattner24943d22010-06-08 16:52:24 +00001042// CommandObjectMultiwordProcess
1043//-------------------------------------------------------------------------
1044
Greg Clayton63094e02010-06-23 01:19:29 +00001045CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter &interpreter) :
Chris Lattner24943d22010-06-08 16:52:24 +00001046 CommandObjectMultiword ("process",
1047 "A set of commands for operating on a process.",
1048 "process <subcommand> [<subcommand-options>]")
1049{
Greg Clayton63094e02010-06-23 01:19:29 +00001050 LoadSubCommand (interpreter, "attach", CommandObjectSP (new CommandObjectProcessAttach ()));
1051 LoadSubCommand (interpreter, "launch", CommandObjectSP (new CommandObjectProcessLaunch ()));
1052 LoadSubCommand (interpreter, "continue", CommandObjectSP (new CommandObjectProcessContinue ()));
1053 LoadSubCommand (interpreter, "detach", CommandObjectSP (new CommandObjectProcessDetach ()));
1054 LoadSubCommand (interpreter, "signal", CommandObjectSP (new CommandObjectProcessSignal ()));
1055 LoadSubCommand (interpreter, "status", CommandObjectSP (new CommandObjectProcessStatus ()));
1056 LoadSubCommand (interpreter, "interrupt", CommandObjectSP (new CommandObjectProcessInterrupt ()));
1057 LoadSubCommand (interpreter, "kill", CommandObjectSP (new CommandObjectProcessKill ()));
Chris Lattner24943d22010-06-08 16:52:24 +00001058}
1059
1060CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess ()
1061{
1062}
1063