blob: cae26a81973b7dc462bafc6f3c888b9be86d212a [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
Greg Clayton238c0a12010-09-18 01:14:36 +0000104 CommandObjectProcessLaunch (CommandInterpreter &interpreter) :
105 CommandObject (interpreter,
106 "process launch",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000107 "Launch the executable in the debugger.",
Chris Lattner24943d22010-06-08 16:52:24 +0000108 "process launch [<cmd-options>] [<arguments-for-running-the-program>]")
109 {
110 }
111
112
113 ~CommandObjectProcessLaunch ()
114 {
115 }
116
117 Options *
118 GetOptions ()
119 {
120 return &m_options;
121 }
122
123 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000124 Execute (Args& launch_args,
Chris Lattner24943d22010-06-08 16:52:24 +0000125 CommandReturnObject &result)
126 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000127 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
128 bool synchronous_execution = m_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 Clayton238c0a12010-09-18 01:14:36 +0000144 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
145 if (process && process->IsAlive())
Chris Lattner24943d22010-06-08 16:52:24 +0000146 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000147 result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before running again.\n",
148 process->GetID());
149 result.SetStatus (eReturnStatusFailed);
150 return false;
Chris Lattner24943d22010-06-08 16:52:24 +0000151 }
152
153 const char *plugin_name;
154 if (!m_options.plugin_name.empty())
155 plugin_name = m_options.plugin_name.c_str();
156 else
157 plugin_name = NULL;
158
Greg Clayton238c0a12010-09-18 01:14:36 +0000159 process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
Chris Lattner24943d22010-06-08 16:52:24 +0000160
Greg Clayton238c0a12010-09-18 01:14:36 +0000161 if (process == NULL)
Caroline Tice6e4c5ce2010-09-04 00:03:46 +0000162 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000163 result.AppendErrorWithFormat ("Failed to find a process plugin for executable");
Chris Lattner24943d22010-06-08 16:52:24 +0000164 result.SetStatus (eReturnStatusFailed);
165 return false;
166 }
167
Greg Clayton238c0a12010-09-18 01:14:36 +0000168 // If no launch args were given on the command line, then use any that
169 // might have been set using the "run-args" set variable.
170 if (launch_args.GetArgumentCount() == 0)
171 {
172 if (process->GetRunArguments().GetArgumentCount() > 0)
173 launch_args = process->GetRunArguments();
174 }
175
176 Args environment;
177
178 process->GetEnvironmentAsArgs (environment);
179
180 uint32_t launch_flags = eLaunchFlagNone;
181
182 if (process->GetDisableASLR())
183 launch_flags |= eLaunchFlagDisableASLR;
184
185 const char *archname = exe_module->GetArchitecture().AsCString();
186
187 const char * stdin_path = NULL;
188 const char * stdout_path = NULL;
189 const char * stderr_path = NULL;
190
191 // Were any standard input/output/error paths given on the command line?
192 if (m_options.stdin_path.empty() &&
193 m_options.stdout_path.empty() &&
194 m_options.stderr_path.empty())
195 {
196 // No standard file handles were given on the command line, check
197 // with the process object in case they were give using "set settings"
198 stdin_path = process->GetStandardInputPath();
199 stdout_path = process->GetStandardOutputPath();
200 stderr_path = process->GetStandardErrorPath();
201 }
202 else
203 {
204 stdin_path = m_options.stdin_path.empty() ? NULL : m_options.stdin_path.c_str();
205 stdout_path = m_options.stdout_path.empty() ? NULL : m_options.stdout_path.c_str();
206 stderr_path = m_options.stderr_path.empty() ? NULL : m_options.stderr_path.c_str();
207 }
208
209 if (stdin_path == NULL)
210 stdin_path = "/dev/null";
211 if (stdout_path == NULL)
212 stdout_path = "/dev/null";
213 if (stderr_path == NULL)
214 stderr_path = "/dev/null";
215
216 Error error (process->Launch (launch_args.GetArgumentCount() ? launch_args.GetConstArgumentVector() : NULL,
217 environment.GetArgumentCount() ? environment.GetConstArgumentVector() : NULL,
218 launch_flags,
219 stdin_path,
220 stdout_path,
221 stderr_path));
222
223 if (error.Success())
224 {
225 result.AppendMessageWithFormat ("Launching '%s' (%s)\n", filename, archname);
226 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
227 if (m_options.stop_at_entry == false)
228 {
229 StateType state = process->WaitForProcessToStop (NULL);
230
231 if (state == eStateStopped)
232 {
233 // Call continue_command.
234 CommandReturnObject continue_result;
235 m_interpreter.HandleCommand("process continue", false, continue_result);
236 }
237
238 if (synchronous_execution)
239 {
240 result.SetDidChangeProcessState (true);
241 result.SetStatus (eReturnStatusSuccessFinishNoResult);
242 }
243 }
244 }
245
Chris Lattner24943d22010-06-08 16:52:24 +0000246 return result.Succeeded();
247 }
248
Jim Ingham767af882010-07-07 03:36:20 +0000249 virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
250 {
251 // No repeat for "process launch"...
252 return "";
253 }
254
Chris Lattner24943d22010-06-08 16:52:24 +0000255protected:
256
257 CommandOptions m_options;
258};
259
260
261lldb::OptionDefinition
262CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
263{
Jim Ingham34e9a982010-06-15 18:47:14 +0000264{ 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."},
265{ LLDB_OPT_SET_1, false, "stdin", 'i', required_argument, NULL, 0, "<path>", "Redirect stdin for the process to <path>."},
266{ LLDB_OPT_SET_1, false, "stdout", 'o', required_argument, NULL, 0, "<path>", "Redirect stdout for the process to <path>."},
267{ LLDB_OPT_SET_1, false, "stderr", 'e', required_argument, NULL, 0, "<path>", "Redirect stderr for the process to <path>."},
268{ 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 +0000269{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
270};
271
272
273//-------------------------------------------------------------------------
274// CommandObjectProcessAttach
275//-------------------------------------------------------------------------
276
277class CommandObjectProcessAttach : public CommandObject
278{
279public:
280
Chris Lattner24943d22010-06-08 16:52:24 +0000281 class CommandOptions : public Options
282 {
283 public:
284
285 CommandOptions () :
286 Options()
287 {
288 // Keep default values of all options in one place: ResetOptionValues ()
289 ResetOptionValues ();
290 }
291
292 ~CommandOptions ()
293 {
294 }
295
296 Error
297 SetOptionValue (int option_idx, const char *option_arg)
298 {
299 Error error;
300 char short_option = (char) m_getopt_table[option_idx].val;
301 bool success = false;
302 switch (short_option)
303 {
304 case 'p':
305 pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success);
306 if (!success || pid == LLDB_INVALID_PROCESS_ID)
307 {
308 error.SetErrorStringWithFormat("Invalid process ID '%s'.\n", option_arg);
309 }
310 break;
311
312 case 'P':
313 plugin_name = option_arg;
314 break;
315
316 case 'n':
317 name.assign(option_arg);
318 break;
319
320 case 'w':
321 waitfor = true;
322 break;
323
324 default:
325 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
326 break;
327 }
328 return error;
329 }
330
331 void
332 ResetOptionValues ()
333 {
334 Options::ResetOptionValues();
335 pid = LLDB_INVALID_PROCESS_ID;
336 name.clear();
337 waitfor = false;
338 }
339
340 const lldb::OptionDefinition*
341 GetDefinitions ()
342 {
343 return g_option_table;
344 }
345
Jim Ingham7508e732010-08-09 23:31:02 +0000346 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000347 HandleOptionArgumentCompletion (CommandInterpreter &interpeter,
Jim Ingham7508e732010-08-09 23:31:02 +0000348 Args &input,
349 int cursor_index,
350 int char_pos,
351 OptionElementVector &opt_element_vector,
352 int opt_element_index,
353 int match_start_point,
354 int max_return_elements,
355 bool &word_complete,
356 StringList &matches)
357 {
358 int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
359 int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
360
361 // We are only completing the name option for now...
362
363 const lldb::OptionDefinition *opt_defs = GetDefinitions();
364 if (opt_defs[opt_defs_index].short_option == 'n')
365 {
366 // Are we in the name?
367
368 // Look to see if there is a -P argument provided, and if so use that plugin, otherwise
369 // use the default plugin.
Greg Clayton238c0a12010-09-18 01:14:36 +0000370 Process *process = interpeter.GetDebugger().GetExecutionContext().process;
Jim Ingham7508e732010-08-09 23:31:02 +0000371 bool need_to_delete_process = false;
372
373 const char *partial_name = NULL;
374 partial_name = input.GetArgumentAtIndex(opt_arg_pos);
375
376 if (process && process->IsAlive())
377 return true;
378
Greg Clayton238c0a12010-09-18 01:14:36 +0000379 Target *target = interpeter.GetDebugger().GetSelectedTarget().get();
Jim Ingham7508e732010-08-09 23:31:02 +0000380 if (target == NULL)
381 {
382 // No target has been set yet, for now do host completion. Otherwise I don't know how we would
383 // figure out what the right target to use is...
384 std::vector<lldb::pid_t> pids;
385 Host::ListProcessesMatchingName (partial_name, matches, pids);
386 return true;
387 }
388 if (!process)
389 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000390 process = target->CreateProcess (interpeter.GetDebugger().GetListener(), partial_name).get();
Jim Ingham7508e732010-08-09 23:31:02 +0000391 need_to_delete_process = true;
392 }
393
394 if (process)
395 {
396 matches.Clear();
397 std::vector<lldb::pid_t> pids;
398 process->ListProcessesMatchingName (NULL, matches, pids);
399 if (need_to_delete_process)
400 target->DeleteCurrentProcess();
401 return true;
402 }
403 }
404
405 return false;
406 }
407
Chris Lattner24943d22010-06-08 16:52:24 +0000408 // Options table: Required for subclasses of Options.
409
410 static lldb::OptionDefinition g_option_table[];
411
412 // Instance variables to hold the values for command options.
413
414 lldb::pid_t pid;
415 std::string plugin_name;
416 std::string name;
417 bool waitfor;
418 };
419
Greg Clayton238c0a12010-09-18 01:14:36 +0000420 CommandObjectProcessAttach (CommandInterpreter &interpreter) :
421 CommandObject (interpreter,
422 "process attach",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000423 "Attach to a process.",
Jim Ingham7508e732010-08-09 23:31:02 +0000424 "process attach <cmd-options>")
425 {
Jim Ingham7508e732010-08-09 23:31:02 +0000426 }
427
428 ~CommandObjectProcessAttach ()
429 {
430 }
431
432 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000433 Execute (Args& command,
Jim Ingham7508e732010-08-09 23:31:02 +0000434 CommandReturnObject &result)
435 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000436 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Jim Ingham7508e732010-08-09 23:31:02 +0000437
Greg Clayton238c0a12010-09-18 01:14:36 +0000438 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Jim Ingham7508e732010-08-09 23:31:02 +0000439 if (process)
440 {
441 if (process->IsAlive())
442 {
443 result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before attaching.\n",
444 process->GetID());
445 result.SetStatus (eReturnStatusFailed);
446 return false;
447 }
448 }
449
450 if (target == NULL)
451 {
452 // If there isn't a current target create one.
453 TargetSP new_target_sp;
454 FileSpec emptyFileSpec;
455 ArchSpec emptyArchSpec;
456 Error error;
457
Greg Clayton238c0a12010-09-18 01:14:36 +0000458 error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(),
459 emptyFileSpec,
460 emptyArchSpec,
461 NULL,
462 false,
463 new_target_sp);
Jim Ingham7508e732010-08-09 23:31:02 +0000464 target = new_target_sp.get();
465 if (target == NULL || error.Fail())
466 {
467 result.AppendError(error.AsCString("Error creating empty target"));
468 return false;
469 }
Greg Clayton238c0a12010-09-18 01:14:36 +0000470 m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target);
Jim Ingham7508e732010-08-09 23:31:02 +0000471 }
472
473 // Record the old executable module, we want to issue a warning if the process of attaching changed the
474 // current executable (like somebody said "file foo" then attached to a PID whose executable was bar.)
475
476 ModuleSP old_exec_module_sp = target->GetExecutableModule();
477 ArchSpec old_arch_spec = target->GetArchitecture();
478
479 if (command.GetArgumentCount())
480 {
481 result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
482 result.SetStatus (eReturnStatusFailed);
483 }
484 else
485 {
486 const char *plugin_name = NULL;
487
488 if (!m_options.plugin_name.empty())
489 plugin_name = m_options.plugin_name.c_str();
490
Greg Clayton238c0a12010-09-18 01:14:36 +0000491 process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
Jim Ingham7508e732010-08-09 23:31:02 +0000492
493 if (process)
494 {
495 Error error;
496 int attach_pid = m_options.pid;
497
Jim Ingham4805a1c2010-09-15 01:34:14 +0000498 const char *wait_name = NULL;
499
500 if (m_options.name.empty())
501 {
502 if (old_exec_module_sp)
503 {
504 wait_name = old_exec_module_sp->GetFileSpec().GetFilename().AsCString();
505 }
506 }
507 else
508 {
509 wait_name = m_options.name.c_str();
510 }
511
Jim Ingham7508e732010-08-09 23:31:02 +0000512 // If we are waiting for a process with this name to show up, do that first.
513 if (m_options.waitfor)
514 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000515
516 if (wait_name == NULL)
Jim Ingham7508e732010-08-09 23:31:02 +0000517 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000518 result.AppendError("Invalid arguments: must have a file loaded or supply a process name with the waitfor option.\n");
Jim Ingham7508e732010-08-09 23:31:02 +0000519 result.SetStatus (eReturnStatusFailed);
520 return false;
521 }
Jim Ingham4805a1c2010-09-15 01:34:14 +0000522
Greg Clayton238c0a12010-09-18 01:14:36 +0000523 m_interpreter.GetDebugger().GetOutputStream().Printf("Waiting to attach to a process named \"%s\".\n", wait_name);
Jim Ingham4805a1c2010-09-15 01:34:14 +0000524 error = process->Attach (wait_name, m_options.waitfor);
525 if (error.Success())
526 {
527 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
528 }
Jim Ingham7508e732010-08-09 23:31:02 +0000529 else
530 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000531 result.AppendErrorWithFormat ("Waiting for a process to launch named '%s': %s\n",
532 wait_name,
533 error.AsCString());
534 result.SetStatus (eReturnStatusFailed);
535 return false;
Jim Ingham7508e732010-08-09 23:31:02 +0000536 }
537 }
538 else
539 {
540 // If the process was specified by name look it up, so we can warn if there are multiple
541 // processes with this pid.
542
Jim Ingham4805a1c2010-09-15 01:34:14 +0000543 if (attach_pid == LLDB_INVALID_PROCESS_ID && wait_name != NULL)
Jim Ingham7508e732010-08-09 23:31:02 +0000544 {
545 std::vector<lldb::pid_t> pids;
546 StringList matches;
547
Jim Ingham4805a1c2010-09-15 01:34:14 +0000548 process->ListProcessesMatchingName(wait_name, matches, pids);
Jim Ingham7508e732010-08-09 23:31:02 +0000549 if (matches.GetSize() > 1)
550 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000551 result.AppendErrorWithFormat("More than one process named %s\n", wait_name);
Jim Ingham7508e732010-08-09 23:31:02 +0000552 result.SetStatus (eReturnStatusFailed);
553 return false;
554 }
555 else if (matches.GetSize() == 0)
556 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000557 result.AppendErrorWithFormat("Could not find a process named %s\n", wait_name);
Jim Ingham7508e732010-08-09 23:31:02 +0000558 result.SetStatus (eReturnStatusFailed);
559 return false;
560 }
561 else
562 {
563 attach_pid = pids[0];
564 }
565
566 }
567
568 if (attach_pid != LLDB_INVALID_PROCESS_ID)
569 {
570 error = process->Attach (attach_pid);
571 if (error.Success())
572 {
573 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
574 }
575 else
576 {
577 result.AppendErrorWithFormat ("Attaching to process %i failed: %s.\n",
578 attach_pid,
579 error.AsCString());
580 result.SetStatus (eReturnStatusFailed);
581 }
582 }
583 else
584 {
585 result.AppendErrorWithFormat ("No PID specified for attach\n",
586 attach_pid,
587 error.AsCString());
588 result.SetStatus (eReturnStatusFailed);
589
590 }
591 }
592 }
593 }
594
595 if (result.Succeeded())
596 {
597 // Okay, we're done. Last step is to warn if the executable module has changed:
598 if (!old_exec_module_sp)
599 {
600 char new_path[PATH_MAX + 1];
601 target->GetExecutableModule()->GetFileSpec().GetPath(new_path, PATH_MAX);
602
603 result.AppendMessageWithFormat("Executable module set to \"%s\".\n",
604 new_path);
605 }
606 else if (old_exec_module_sp->GetFileSpec() != target->GetExecutableModule()->GetFileSpec())
607 {
608 char old_path[PATH_MAX + 1];
609 char new_path[PATH_MAX + 1];
610
611 old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX);
612 target->GetExecutableModule()->GetFileSpec().GetPath (new_path, PATH_MAX);
613
614 result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n",
615 old_path, new_path);
616 }
617
618 if (!old_arch_spec.IsValid())
619 {
620 result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().AsCString());
621 }
622 else if (old_arch_spec != target->GetArchitecture())
623 {
624 result.AppendWarningWithFormat("Architecture changed from %s to %s.\n",
625 old_arch_spec.AsCString(), target->GetArchitecture().AsCString());
626 }
627 }
628 return result.Succeeded();
629 }
630
631 Options *
632 GetOptions ()
633 {
634 return &m_options;
635 }
636
Chris Lattner24943d22010-06-08 16:52:24 +0000637protected:
638
639 CommandOptions m_options;
640};
641
642
643lldb::OptionDefinition
644CommandObjectProcessAttach::CommandOptions::g_option_table[] =
645{
Greg Claytonfe424a92010-09-18 03:37:20 +0000646{ LLDB_OPT_SET_ALL, false, "plugin", 'P', required_argument, NULL, 0, "<plugin>", "Name of the process plugin you want to use."},
647{ LLDB_OPT_SET_1, false, "pid", 'p', required_argument, NULL, 0, "<pid>", "The process ID of an existing process to attach to."},
648{ LLDB_OPT_SET_2, false, "name", 'n', required_argument, NULL, 0, "<process-name>", "The name of the process to attach to."},
649{ 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 +0000650{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
651};
652
653//-------------------------------------------------------------------------
654// CommandObjectProcessContinue
655//-------------------------------------------------------------------------
656
657class CommandObjectProcessContinue : public CommandObject
658{
659public:
660
Greg Clayton238c0a12010-09-18 01:14:36 +0000661 CommandObjectProcessContinue (CommandInterpreter &interpreter) :
662 CommandObject (interpreter,
663 "process continue",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000664 "Continue execution of all threads in the current process.",
Chris Lattner24943d22010-06-08 16:52:24 +0000665 "process continue",
666 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
667 {
668 }
669
670
671 ~CommandObjectProcessContinue ()
672 {
673 }
674
675 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000676 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000677 CommandReturnObject &result)
678 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000679 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
680 bool synchronous_execution = m_interpreter.GetSynchronous ();
Chris Lattner24943d22010-06-08 16:52:24 +0000681
682 if (process == NULL)
683 {
684 result.AppendError ("no process to continue");
685 result.SetStatus (eReturnStatusFailed);
686 return false;
687 }
688
689 StateType state = process->GetState();
690 if (state == eStateStopped)
691 {
692 if (command.GetArgumentCount() != 0)
693 {
694 result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str());
695 result.SetStatus (eReturnStatusFailed);
696 return false;
697 }
698
699 const uint32_t num_threads = process->GetThreadList().GetSize();
700
701 // Set the actions that the threads should each take when resuming
702 for (uint32_t idx=0; idx<num_threads; ++idx)
703 {
704 process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning);
705 }
706
707 Error error(process->Resume());
708 if (error.Success())
709 {
710 result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID());
711 if (synchronous_execution)
712 {
Greg Claytonbef15832010-07-14 00:18:15 +0000713 state = process->WaitForProcessToStop (NULL);
Chris Lattner24943d22010-06-08 16:52:24 +0000714
715 result.SetDidChangeProcessState (true);
716 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
717 result.SetStatus (eReturnStatusSuccessFinishNoResult);
718 }
719 else
720 {
721 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
722 }
723 }
724 else
725 {
726 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
727 result.SetStatus (eReturnStatusFailed);
728 }
729 }
730 else
731 {
732 result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
733 StateAsCString(state));
734 result.SetStatus (eReturnStatusFailed);
735 }
736 return result.Succeeded();
737 }
738};
739
740//-------------------------------------------------------------------------
741// CommandObjectProcessDetach
742//-------------------------------------------------------------------------
743
744class CommandObjectProcessDetach : public CommandObject
745{
746public:
747
Greg Clayton238c0a12010-09-18 01:14:36 +0000748 CommandObjectProcessDetach (CommandInterpreter &interpreter) :
749 CommandObject (interpreter,
750 "process detach",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000751 "Detach from the current process being debugged.",
Chris Lattner24943d22010-06-08 16:52:24 +0000752 "process detach",
753 eFlagProcessMustBeLaunched)
754 {
755 }
756
757 ~CommandObjectProcessDetach ()
758 {
759 }
760
761 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000762 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000763 CommandReturnObject &result)
764 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000765 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000766 if (process == NULL)
767 {
768 result.AppendError ("must have a valid process in order to detach");
769 result.SetStatus (eReturnStatusFailed);
770 return false;
771 }
772
773 Error error (process->Detach());
774 if (error.Success())
775 {
776 result.SetStatus (eReturnStatusSuccessFinishResult);
777 }
778 else
779 {
780 result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString());
781 result.SetStatus (eReturnStatusFailed);
782 return false;
783 }
784 return result.Succeeded();
785 }
786};
787
788//-------------------------------------------------------------------------
789// CommandObjectProcessSignal
790//-------------------------------------------------------------------------
791
792class CommandObjectProcessSignal : public CommandObject
793{
794public:
795
Greg Clayton238c0a12010-09-18 01:14:36 +0000796 CommandObjectProcessSignal (CommandInterpreter &interpreter) :
797 CommandObject (interpreter,
798 "process signal",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000799 "Send a UNIX signal to the current process being debugged.",
Chris Lattner24943d22010-06-08 16:52:24 +0000800 "process signal <unix-signal-number>")
801 {
802 }
803
804 ~CommandObjectProcessSignal ()
805 {
806 }
807
808 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000809 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000810 CommandReturnObject &result)
811 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000812 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000813 if (process == NULL)
814 {
815 result.AppendError ("no process to signal");
816 result.SetStatus (eReturnStatusFailed);
817 return false;
818 }
819
820 if (command.GetArgumentCount() == 1)
821 {
822 int signo = Args::StringToSInt32(command.GetArgumentAtIndex(0), -1, 0);
823 if (signo == -1)
824 {
825 result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0));
826 result.SetStatus (eReturnStatusFailed);
827 }
828 else
829 {
830 Error error (process->Signal (signo));
831 if (error.Success())
832 {
833 result.SetStatus (eReturnStatusSuccessFinishResult);
834 }
835 else
836 {
837 result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString());
838 result.SetStatus (eReturnStatusFailed);
839 }
840 }
841 }
842 else
843 {
844 result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: \n", m_cmd_name.c_str(),
845 m_cmd_syntax.c_str());
846 result.SetStatus (eReturnStatusFailed);
847 }
848 return result.Succeeded();
849 }
850};
851
852
853//-------------------------------------------------------------------------
854// CommandObjectProcessInterrupt
855//-------------------------------------------------------------------------
856
857class CommandObjectProcessInterrupt : public CommandObject
858{
859public:
860
861
Greg Clayton238c0a12010-09-18 01:14:36 +0000862 CommandObjectProcessInterrupt (CommandInterpreter &interpreter) :
863 CommandObject (interpreter,
864 "process interrupt",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000865 "Interrupt the current process being debugged.",
Chris Lattner24943d22010-06-08 16:52:24 +0000866 "process interrupt",
867 eFlagProcessMustBeLaunched)
868 {
869 }
870
871 ~CommandObjectProcessInterrupt ()
872 {
873 }
874
875 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000876 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000877 CommandReturnObject &result)
878 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000879 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000880 if (process == NULL)
881 {
882 result.AppendError ("no process to halt");
883 result.SetStatus (eReturnStatusFailed);
884 return false;
885 }
886
887 if (command.GetArgumentCount() == 0)
888 {
889 Error error(process->Halt ());
890 if (error.Success())
891 {
892 result.SetStatus (eReturnStatusSuccessFinishResult);
893
894 // Maybe we should add a "SuspendThreadPlans so we
895 // can halt, and keep in place all the current thread plans.
896 process->GetThreadList().DiscardThreadPlans();
897 }
898 else
899 {
900 result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString());
901 result.SetStatus (eReturnStatusFailed);
902 }
903 }
904 else
905 {
906 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
907 m_cmd_name.c_str(),
908 m_cmd_syntax.c_str());
909 result.SetStatus (eReturnStatusFailed);
910 }
911 return result.Succeeded();
912 }
913};
914
915//-------------------------------------------------------------------------
916// CommandObjectProcessKill
917//-------------------------------------------------------------------------
918
919class CommandObjectProcessKill : public CommandObject
920{
921public:
922
Greg Clayton238c0a12010-09-18 01:14:36 +0000923 CommandObjectProcessKill (CommandInterpreter &interpreter) :
924 CommandObject (interpreter,
925 "process kill",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000926 "Terminate the current process being debugged.",
Chris Lattner24943d22010-06-08 16:52:24 +0000927 "process kill",
928 eFlagProcessMustBeLaunched)
929 {
930 }
931
932 ~CommandObjectProcessKill ()
933 {
934 }
935
936 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000937 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000938 CommandReturnObject &result)
939 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000940 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000941 if (process == NULL)
942 {
943 result.AppendError ("no process to kill");
944 result.SetStatus (eReturnStatusFailed);
945 return false;
946 }
947
948 if (command.GetArgumentCount() == 0)
949 {
950 Error error (process->Destroy());
951 if (error.Success())
952 {
953 result.SetStatus (eReturnStatusSuccessFinishResult);
954 }
955 else
956 {
957 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString());
958 result.SetStatus (eReturnStatusFailed);
959 }
960 }
961 else
962 {
963 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
964 m_cmd_name.c_str(),
965 m_cmd_syntax.c_str());
966 result.SetStatus (eReturnStatusFailed);
967 }
968 return result.Succeeded();
969 }
970};
971
972//-------------------------------------------------------------------------
Jim Ingham41313fc2010-06-18 01:23:09 +0000973// CommandObjectProcessStatus
974//-------------------------------------------------------------------------
975class CommandObjectProcessStatus : public CommandObject
976{
977public:
Greg Clayton238c0a12010-09-18 01:14:36 +0000978 CommandObjectProcessStatus (CommandInterpreter &interpreter) :
979 CommandObject (interpreter,
980 "process status",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000981 "Show the current status and location of executing process.",
982 "process status",
Jim Ingham41313fc2010-06-18 01:23:09 +0000983 0)
984 {
985 }
986
987 ~CommandObjectProcessStatus()
988 {
989 }
990
991
992 bool
993 Execute
994 (
995 Args& command,
Jim Ingham41313fc2010-06-18 01:23:09 +0000996 CommandReturnObject &result
997 )
998 {
999 StreamString &output_stream = result.GetOutputStream();
1000 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Greg Clayton238c0a12010-09-18 01:14:36 +00001001 ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
Jim Ingham41313fc2010-06-18 01:23:09 +00001002 if (exe_ctx.process)
1003 {
1004 const StateType state = exe_ctx.process->GetState();
1005 if (StateIsStoppedState(state))
1006 {
1007 if (state == eStateExited)
1008 {
1009 int exit_status = exe_ctx.process->GetExitStatus();
1010 const char *exit_description = exe_ctx.process->GetExitDescription();
1011 output_stream.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n",
1012 exe_ctx.process->GetID(),
1013 exit_status,
1014 exit_status,
1015 exit_description ? exit_description : "");
1016 }
1017 else
1018 {
1019 output_stream.Printf ("Process %d %s\n", exe_ctx.process->GetID(), StateAsCString (state));
1020 if (exe_ctx.thread == NULL)
1021 exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
1022 if (exe_ctx.thread != NULL)
1023 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001024 DisplayThreadsInfo (m_interpreter, &exe_ctx, result, true, true);
Jim Ingham41313fc2010-06-18 01:23:09 +00001025 }
1026 else
1027 {
1028 result.AppendError ("No valid thread found in current process.");
1029 result.SetStatus (eReturnStatusFailed);
1030 }
1031 }
1032 }
1033 else
1034 {
1035 output_stream.Printf ("Process %d is running.\n",
1036 exe_ctx.process->GetID());
1037 }
1038 }
1039 else
1040 {
1041 result.AppendError ("No current location or status available.");
1042 result.SetStatus (eReturnStatusFailed);
1043 }
1044 return result.Succeeded();
1045 }
1046};
1047
1048//-------------------------------------------------------------------------
Chris Lattner24943d22010-06-08 16:52:24 +00001049// CommandObjectMultiwordProcess
1050//-------------------------------------------------------------------------
1051
Greg Clayton63094e02010-06-23 01:19:29 +00001052CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001053 CommandObjectMultiword (interpreter,
1054 "process",
1055 "A set of commands for operating on a process.",
1056 "process <subcommand> [<subcommand-options>]")
Chris Lattner24943d22010-06-08 16:52:24 +00001057{
Greg Clayton238c0a12010-09-18 01:14:36 +00001058 LoadSubCommand ("attach", CommandObjectSP (new CommandObjectProcessAttach (interpreter)));
1059 LoadSubCommand ("launch", CommandObjectSP (new CommandObjectProcessLaunch (interpreter)));
1060 LoadSubCommand ("continue", CommandObjectSP (new CommandObjectProcessContinue (interpreter)));
1061 LoadSubCommand ("detach", CommandObjectSP (new CommandObjectProcessDetach (interpreter)));
1062 LoadSubCommand ("signal", CommandObjectSP (new CommandObjectProcessSignal (interpreter)));
1063 LoadSubCommand ("status", CommandObjectSP (new CommandObjectProcessStatus (interpreter)));
1064 LoadSubCommand ("interrupt", CommandObjectSP (new CommandObjectProcessInterrupt (interpreter)));
1065 LoadSubCommand ("kill", CommandObjectSP (new CommandObjectProcessKill (interpreter)));
Chris Lattner24943d22010-06-08 16:52:24 +00001066}
1067
1068CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess ()
1069{
1070}
1071