blob: 09459d856b3e64ff578acf4bde4c3febc4428c66 [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.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000108 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000109 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000110 CommandArgumentEntry arg;
111 CommandArgumentData run_args_arg;
112
113 // Define the first (and only) variant of this arg.
114 run_args_arg.arg_type = eArgTypeRunArgs;
115 run_args_arg.arg_repetition = eArgRepeatOptional;
116
117 // There is only one variant this argument could be; put it into the argument entry.
118 arg.push_back (run_args_arg);
119
120 // Push the data for the first argument into the m_arguments vector.
121 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000122 }
123
124
125 ~CommandObjectProcessLaunch ()
126 {
127 }
128
129 Options *
130 GetOptions ()
131 {
132 return &m_options;
133 }
134
135 bool
Greg Claytond8c62532010-10-07 04:19:01 +0000136 Execute (Args& launch_args, CommandReturnObject &result)
Chris Lattner24943d22010-06-08 16:52:24 +0000137 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000138 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000139
140 if (target == NULL)
141 {
142 result.AppendError ("invalid target, set executable file using 'file' command");
143 result.SetStatus (eReturnStatusFailed);
144 return false;
145 }
146
147 // If our listener is NULL, users aren't allows to launch
Chris Lattner24943d22010-06-08 16:52:24 +0000148 char filename[PATH_MAX];
149 Module *exe_module = target->GetExecutableModule().get();
150 exe_module->GetFileSpec().GetPath(filename, sizeof(filename));
151
Greg Clayton238c0a12010-09-18 01:14:36 +0000152 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
153 if (process && process->IsAlive())
Chris Lattner24943d22010-06-08 16:52:24 +0000154 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000155 result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before running again.\n",
156 process->GetID());
157 result.SetStatus (eReturnStatusFailed);
158 return false;
Chris Lattner24943d22010-06-08 16:52:24 +0000159 }
160
161 const char *plugin_name;
162 if (!m_options.plugin_name.empty())
163 plugin_name = m_options.plugin_name.c_str();
164 else
165 plugin_name = NULL;
166
Greg Clayton238c0a12010-09-18 01:14:36 +0000167 process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
Chris Lattner24943d22010-06-08 16:52:24 +0000168
Greg Clayton238c0a12010-09-18 01:14:36 +0000169 if (process == NULL)
Caroline Tice6e4c5ce2010-09-04 00:03:46 +0000170 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000171 result.AppendErrorWithFormat ("Failed to find a process plugin for executable");
Chris Lattner24943d22010-06-08 16:52:24 +0000172 result.SetStatus (eReturnStatusFailed);
173 return false;
174 }
175
Greg Clayton238c0a12010-09-18 01:14:36 +0000176 // If no launch args were given on the command line, then use any that
177 // might have been set using the "run-args" set variable.
178 if (launch_args.GetArgumentCount() == 0)
179 {
180 if (process->GetRunArguments().GetArgumentCount() > 0)
181 launch_args = process->GetRunArguments();
182 }
183
184 Args environment;
185
186 process->GetEnvironmentAsArgs (environment);
187
188 uint32_t launch_flags = eLaunchFlagNone;
189
190 if (process->GetDisableASLR())
191 launch_flags |= eLaunchFlagDisableASLR;
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 // Were any standard input/output/error paths given on the command line?
200 if (m_options.stdin_path.empty() &&
201 m_options.stdout_path.empty() &&
202 m_options.stderr_path.empty())
203 {
204 // No standard file handles were given on the command line, check
205 // with the process object in case they were give using "set settings"
206 stdin_path = process->GetStandardInputPath();
207 stdout_path = process->GetStandardOutputPath();
208 stderr_path = process->GetStandardErrorPath();
209 }
210 else
211 {
212 stdin_path = m_options.stdin_path.empty() ? NULL : m_options.stdin_path.c_str();
213 stdout_path = m_options.stdout_path.empty() ? NULL : m_options.stdout_path.c_str();
214 stderr_path = m_options.stderr_path.empty() ? NULL : m_options.stderr_path.c_str();
215 }
216
217 if (stdin_path == NULL)
218 stdin_path = "/dev/null";
219 if (stdout_path == NULL)
220 stdout_path = "/dev/null";
221 if (stderr_path == NULL)
222 stderr_path = "/dev/null";
223
224 Error error (process->Launch (launch_args.GetArgumentCount() ? launch_args.GetConstArgumentVector() : NULL,
225 environment.GetArgumentCount() ? environment.GetConstArgumentVector() : NULL,
226 launch_flags,
227 stdin_path,
228 stdout_path,
229 stderr_path));
230
231 if (error.Success())
232 {
233 result.AppendMessageWithFormat ("Launching '%s' (%s)\n", filename, archname);
Greg Claytond8c62532010-10-07 04:19:01 +0000234 result.SetDidChangeProcessState (true);
Greg Clayton238c0a12010-09-18 01:14:36 +0000235 if (m_options.stop_at_entry == false)
236 {
Greg Claytond8c62532010-10-07 04:19:01 +0000237 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
Greg Clayton238c0a12010-09-18 01:14:36 +0000238 StateType state = process->WaitForProcessToStop (NULL);
239
240 if (state == eStateStopped)
241 {
Greg Claytond8c62532010-10-07 04:19:01 +0000242 error = process->Resume();
243 if (error.Success())
244 {
245 bool synchronous_execution = m_interpreter.GetSynchronous ();
246 if (synchronous_execution)
247 {
248 state = process->WaitForProcessToStop (NULL);
249 result.SetDidChangeProcessState (true);
250 result.SetStatus (eReturnStatusSuccessFinishResult);
251 }
252 else
253 {
254 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
255 }
256 }
Greg Clayton238c0a12010-09-18 01:14:36 +0000257 }
258 }
259 }
260
Chris Lattner24943d22010-06-08 16:52:24 +0000261 return result.Succeeded();
262 }
263
Jim Ingham767af882010-07-07 03:36:20 +0000264 virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
265 {
266 // No repeat for "process launch"...
267 return "";
268 }
269
Chris Lattner24943d22010-06-08 16:52:24 +0000270protected:
271
272 CommandOptions m_options;
273};
274
275
276lldb::OptionDefinition
277CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
278{
Caroline Tice4d6675c2010-10-01 19:59:14 +0000279{ LLDB_OPT_SET_1, false, "stop-at-entry", 's', no_argument, NULL, 0, eArgTypeNone, "Stop at the entry point of the program when launching a process."},
280{ LLDB_OPT_SET_1, false, "stdin", 'i', required_argument, NULL, 0, eArgTypePath, "Redirect stdin for the process to <path>."},
281{ LLDB_OPT_SET_1, false, "stdout", 'o', required_argument, NULL, 0, eArgTypePath, "Redirect stdout for the process to <path>."},
282{ LLDB_OPT_SET_1, false, "stderr", 'e', required_argument, NULL, 0, eArgTypePath, "Redirect stderr for the process to <path>."},
283{ LLDB_OPT_SET_1, false, "plugin", 'p', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
284{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +0000285};
286
287
288//-------------------------------------------------------------------------
289// CommandObjectProcessAttach
290//-------------------------------------------------------------------------
291
292class CommandObjectProcessAttach : public CommandObject
293{
294public:
295
Chris Lattner24943d22010-06-08 16:52:24 +0000296 class CommandOptions : public Options
297 {
298 public:
299
300 CommandOptions () :
301 Options()
302 {
303 // Keep default values of all options in one place: ResetOptionValues ()
304 ResetOptionValues ();
305 }
306
307 ~CommandOptions ()
308 {
309 }
310
311 Error
312 SetOptionValue (int option_idx, const char *option_arg)
313 {
314 Error error;
315 char short_option = (char) m_getopt_table[option_idx].val;
316 bool success = false;
317 switch (short_option)
318 {
319 case 'p':
320 pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success);
321 if (!success || pid == LLDB_INVALID_PROCESS_ID)
322 {
323 error.SetErrorStringWithFormat("Invalid process ID '%s'.\n", option_arg);
324 }
325 break;
326
327 case 'P':
328 plugin_name = option_arg;
329 break;
330
331 case 'n':
332 name.assign(option_arg);
333 break;
334
335 case 'w':
336 waitfor = true;
337 break;
338
339 default:
340 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
341 break;
342 }
343 return error;
344 }
345
346 void
347 ResetOptionValues ()
348 {
349 Options::ResetOptionValues();
350 pid = LLDB_INVALID_PROCESS_ID;
351 name.clear();
352 waitfor = false;
353 }
354
355 const lldb::OptionDefinition*
356 GetDefinitions ()
357 {
358 return g_option_table;
359 }
360
Jim Ingham7508e732010-08-09 23:31:02 +0000361 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000362 HandleOptionArgumentCompletion (CommandInterpreter &interpeter,
Jim Ingham7508e732010-08-09 23:31:02 +0000363 Args &input,
364 int cursor_index,
365 int char_pos,
366 OptionElementVector &opt_element_vector,
367 int opt_element_index,
368 int match_start_point,
369 int max_return_elements,
370 bool &word_complete,
371 StringList &matches)
372 {
373 int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
374 int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
375
376 // We are only completing the name option for now...
377
378 const lldb::OptionDefinition *opt_defs = GetDefinitions();
379 if (opt_defs[opt_defs_index].short_option == 'n')
380 {
381 // Are we in the name?
382
383 // Look to see if there is a -P argument provided, and if so use that plugin, otherwise
384 // use the default plugin.
Greg Clayton238c0a12010-09-18 01:14:36 +0000385 Process *process = interpeter.GetDebugger().GetExecutionContext().process;
Jim Ingham7508e732010-08-09 23:31:02 +0000386 bool need_to_delete_process = false;
387
388 const char *partial_name = NULL;
389 partial_name = input.GetArgumentAtIndex(opt_arg_pos);
390
391 if (process && process->IsAlive())
392 return true;
393
Greg Clayton238c0a12010-09-18 01:14:36 +0000394 Target *target = interpeter.GetDebugger().GetSelectedTarget().get();
Jim Ingham7508e732010-08-09 23:31:02 +0000395 if (target == NULL)
396 {
397 // No target has been set yet, for now do host completion. Otherwise I don't know how we would
398 // figure out what the right target to use is...
399 std::vector<lldb::pid_t> pids;
400 Host::ListProcessesMatchingName (partial_name, matches, pids);
401 return true;
402 }
403 if (!process)
404 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000405 process = target->CreateProcess (interpeter.GetDebugger().GetListener(), partial_name).get();
Jim Ingham7508e732010-08-09 23:31:02 +0000406 need_to_delete_process = true;
407 }
408
409 if (process)
410 {
411 matches.Clear();
412 std::vector<lldb::pid_t> pids;
413 process->ListProcessesMatchingName (NULL, matches, pids);
414 if (need_to_delete_process)
415 target->DeleteCurrentProcess();
416 return true;
417 }
418 }
419
420 return false;
421 }
422
Chris Lattner24943d22010-06-08 16:52:24 +0000423 // Options table: Required for subclasses of Options.
424
425 static lldb::OptionDefinition g_option_table[];
426
427 // Instance variables to hold the values for command options.
428
429 lldb::pid_t pid;
430 std::string plugin_name;
431 std::string name;
432 bool waitfor;
433 };
434
Greg Clayton238c0a12010-09-18 01:14:36 +0000435 CommandObjectProcessAttach (CommandInterpreter &interpreter) :
436 CommandObject (interpreter,
437 "process attach",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000438 "Attach to a process.",
Jim Ingham7508e732010-08-09 23:31:02 +0000439 "process attach <cmd-options>")
440 {
Jim Ingham7508e732010-08-09 23:31:02 +0000441 }
442
443 ~CommandObjectProcessAttach ()
444 {
445 }
446
447 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000448 Execute (Args& command,
Jim Ingham7508e732010-08-09 23:31:02 +0000449 CommandReturnObject &result)
450 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000451 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Jim Ingham7508e732010-08-09 23:31:02 +0000452
Greg Clayton238c0a12010-09-18 01:14:36 +0000453 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Jim Ingham7508e732010-08-09 23:31:02 +0000454 if (process)
455 {
456 if (process->IsAlive())
457 {
458 result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before attaching.\n",
459 process->GetID());
460 result.SetStatus (eReturnStatusFailed);
461 return false;
462 }
463 }
464
465 if (target == NULL)
466 {
467 // If there isn't a current target create one.
468 TargetSP new_target_sp;
469 FileSpec emptyFileSpec;
470 ArchSpec emptyArchSpec;
471 Error error;
472
Greg Clayton238c0a12010-09-18 01:14:36 +0000473 error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(),
474 emptyFileSpec,
475 emptyArchSpec,
476 NULL,
477 false,
478 new_target_sp);
Jim Ingham7508e732010-08-09 23:31:02 +0000479 target = new_target_sp.get();
480 if (target == NULL || error.Fail())
481 {
482 result.AppendError(error.AsCString("Error creating empty target"));
483 return false;
484 }
Greg Clayton238c0a12010-09-18 01:14:36 +0000485 m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target);
Jim Ingham7508e732010-08-09 23:31:02 +0000486 }
487
488 // Record the old executable module, we want to issue a warning if the process of attaching changed the
489 // current executable (like somebody said "file foo" then attached to a PID whose executable was bar.)
490
491 ModuleSP old_exec_module_sp = target->GetExecutableModule();
492 ArchSpec old_arch_spec = target->GetArchitecture();
493
494 if (command.GetArgumentCount())
495 {
496 result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
497 result.SetStatus (eReturnStatusFailed);
498 }
499 else
500 {
501 const char *plugin_name = NULL;
502
503 if (!m_options.plugin_name.empty())
504 plugin_name = m_options.plugin_name.c_str();
505
Greg Clayton238c0a12010-09-18 01:14:36 +0000506 process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
Jim Ingham7508e732010-08-09 23:31:02 +0000507
508 if (process)
509 {
510 Error error;
511 int attach_pid = m_options.pid;
512
Jim Ingham4805a1c2010-09-15 01:34:14 +0000513 const char *wait_name = NULL;
514
515 if (m_options.name.empty())
516 {
517 if (old_exec_module_sp)
518 {
519 wait_name = old_exec_module_sp->GetFileSpec().GetFilename().AsCString();
520 }
521 }
522 else
523 {
524 wait_name = m_options.name.c_str();
525 }
526
Jim Ingham7508e732010-08-09 23:31:02 +0000527 // If we are waiting for a process with this name to show up, do that first.
528 if (m_options.waitfor)
529 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000530
531 if (wait_name == NULL)
Jim Ingham7508e732010-08-09 23:31:02 +0000532 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000533 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 +0000534 result.SetStatus (eReturnStatusFailed);
535 return false;
536 }
Jim Ingham4805a1c2010-09-15 01:34:14 +0000537
Greg Clayton238c0a12010-09-18 01:14:36 +0000538 m_interpreter.GetDebugger().GetOutputStream().Printf("Waiting to attach to a process named \"%s\".\n", wait_name);
Jim Ingham4805a1c2010-09-15 01:34:14 +0000539 error = process->Attach (wait_name, m_options.waitfor);
540 if (error.Success())
541 {
542 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
543 }
Jim Ingham7508e732010-08-09 23:31:02 +0000544 else
545 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000546 result.AppendErrorWithFormat ("Waiting for a process to launch named '%s': %s\n",
547 wait_name,
548 error.AsCString());
549 result.SetStatus (eReturnStatusFailed);
550 return false;
Jim Ingham7508e732010-08-09 23:31:02 +0000551 }
552 }
553 else
554 {
555 // If the process was specified by name look it up, so we can warn if there are multiple
556 // processes with this pid.
557
Jim Ingham4805a1c2010-09-15 01:34:14 +0000558 if (attach_pid == LLDB_INVALID_PROCESS_ID && wait_name != NULL)
Jim Ingham7508e732010-08-09 23:31:02 +0000559 {
560 std::vector<lldb::pid_t> pids;
561 StringList matches;
562
Jim Ingham4805a1c2010-09-15 01:34:14 +0000563 process->ListProcessesMatchingName(wait_name, matches, pids);
Jim Ingham7508e732010-08-09 23:31:02 +0000564 if (matches.GetSize() > 1)
565 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000566 result.AppendErrorWithFormat("More than one process named %s\n", wait_name);
Jim Ingham7508e732010-08-09 23:31:02 +0000567 result.SetStatus (eReturnStatusFailed);
568 return false;
569 }
570 else if (matches.GetSize() == 0)
571 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000572 result.AppendErrorWithFormat("Could not find a process named %s\n", wait_name);
Jim Ingham7508e732010-08-09 23:31:02 +0000573 result.SetStatus (eReturnStatusFailed);
574 return false;
575 }
576 else
577 {
578 attach_pid = pids[0];
579 }
580
581 }
582
583 if (attach_pid != LLDB_INVALID_PROCESS_ID)
584 {
585 error = process->Attach (attach_pid);
586 if (error.Success())
587 {
588 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
589 }
590 else
591 {
592 result.AppendErrorWithFormat ("Attaching to process %i failed: %s.\n",
593 attach_pid,
594 error.AsCString());
595 result.SetStatus (eReturnStatusFailed);
596 }
597 }
598 else
599 {
600 result.AppendErrorWithFormat ("No PID specified for attach\n",
601 attach_pid,
602 error.AsCString());
603 result.SetStatus (eReturnStatusFailed);
604
605 }
606 }
607 }
608 }
609
610 if (result.Succeeded())
611 {
612 // Okay, we're done. Last step is to warn if the executable module has changed:
613 if (!old_exec_module_sp)
614 {
615 char new_path[PATH_MAX + 1];
616 target->GetExecutableModule()->GetFileSpec().GetPath(new_path, PATH_MAX);
617
618 result.AppendMessageWithFormat("Executable module set to \"%s\".\n",
619 new_path);
620 }
621 else if (old_exec_module_sp->GetFileSpec() != target->GetExecutableModule()->GetFileSpec())
622 {
623 char old_path[PATH_MAX + 1];
624 char new_path[PATH_MAX + 1];
625
626 old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX);
627 target->GetExecutableModule()->GetFileSpec().GetPath (new_path, PATH_MAX);
628
629 result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n",
630 old_path, new_path);
631 }
632
633 if (!old_arch_spec.IsValid())
634 {
635 result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().AsCString());
636 }
637 else if (old_arch_spec != target->GetArchitecture())
638 {
639 result.AppendWarningWithFormat("Architecture changed from %s to %s.\n",
640 old_arch_spec.AsCString(), target->GetArchitecture().AsCString());
641 }
642 }
643 return result.Succeeded();
644 }
645
646 Options *
647 GetOptions ()
648 {
649 return &m_options;
650 }
651
Chris Lattner24943d22010-06-08 16:52:24 +0000652protected:
653
654 CommandOptions m_options;
655};
656
657
658lldb::OptionDefinition
659CommandObjectProcessAttach::CommandOptions::g_option_table[] =
660{
Caroline Tice4d6675c2010-10-01 19:59:14 +0000661{ LLDB_OPT_SET_ALL, false, "plugin", 'P', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
662{ LLDB_OPT_SET_1, false, "pid", 'p', required_argument, NULL, 0, eArgTypePid, "The process ID of an existing process to attach to."},
663{ LLDB_OPT_SET_2, false, "name", 'n', required_argument, NULL, 0, eArgTypeProcessName, "The name of the process to attach to."},
664{ LLDB_OPT_SET_2, false, "waitfor",'w', no_argument, NULL, 0, eArgTypeNone, "Wait for the the process with <process-name> to launch."},
665{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +0000666};
667
668//-------------------------------------------------------------------------
669// CommandObjectProcessContinue
670//-------------------------------------------------------------------------
671
672class CommandObjectProcessContinue : public CommandObject
673{
674public:
675
Greg Clayton238c0a12010-09-18 01:14:36 +0000676 CommandObjectProcessContinue (CommandInterpreter &interpreter) :
677 CommandObject (interpreter,
678 "process continue",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000679 "Continue execution of all threads in the current process.",
Chris Lattner24943d22010-06-08 16:52:24 +0000680 "process continue",
681 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
682 {
683 }
684
685
686 ~CommandObjectProcessContinue ()
687 {
688 }
689
690 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000691 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000692 CommandReturnObject &result)
693 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000694 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
695 bool synchronous_execution = m_interpreter.GetSynchronous ();
Chris Lattner24943d22010-06-08 16:52:24 +0000696
697 if (process == NULL)
698 {
699 result.AppendError ("no process to continue");
700 result.SetStatus (eReturnStatusFailed);
701 return false;
702 }
703
704 StateType state = process->GetState();
705 if (state == eStateStopped)
706 {
707 if (command.GetArgumentCount() != 0)
708 {
709 result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str());
710 result.SetStatus (eReturnStatusFailed);
711 return false;
712 }
713
714 const uint32_t num_threads = process->GetThreadList().GetSize();
715
716 // Set the actions that the threads should each take when resuming
717 for (uint32_t idx=0; idx<num_threads; ++idx)
718 {
719 process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning);
720 }
721
722 Error error(process->Resume());
723 if (error.Success())
724 {
725 result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID());
726 if (synchronous_execution)
727 {
Greg Claytonbef15832010-07-14 00:18:15 +0000728 state = process->WaitForProcessToStop (NULL);
Chris Lattner24943d22010-06-08 16:52:24 +0000729
730 result.SetDidChangeProcessState (true);
731 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
732 result.SetStatus (eReturnStatusSuccessFinishNoResult);
733 }
734 else
735 {
736 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
737 }
738 }
739 else
740 {
741 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
742 result.SetStatus (eReturnStatusFailed);
743 }
744 }
745 else
746 {
747 result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
748 StateAsCString(state));
749 result.SetStatus (eReturnStatusFailed);
750 }
751 return result.Succeeded();
752 }
753};
754
755//-------------------------------------------------------------------------
756// CommandObjectProcessDetach
757//-------------------------------------------------------------------------
758
759class CommandObjectProcessDetach : public CommandObject
760{
761public:
762
Greg Clayton238c0a12010-09-18 01:14:36 +0000763 CommandObjectProcessDetach (CommandInterpreter &interpreter) :
764 CommandObject (interpreter,
765 "process detach",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000766 "Detach from the current process being debugged.",
Chris Lattner24943d22010-06-08 16:52:24 +0000767 "process detach",
768 eFlagProcessMustBeLaunched)
769 {
770 }
771
772 ~CommandObjectProcessDetach ()
773 {
774 }
775
776 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000777 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000778 CommandReturnObject &result)
779 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000780 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000781 if (process == NULL)
782 {
783 result.AppendError ("must have a valid process in order to detach");
784 result.SetStatus (eReturnStatusFailed);
785 return false;
786 }
787
788 Error error (process->Detach());
789 if (error.Success())
790 {
791 result.SetStatus (eReturnStatusSuccessFinishResult);
792 }
793 else
794 {
795 result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString());
796 result.SetStatus (eReturnStatusFailed);
797 return false;
798 }
799 return result.Succeeded();
800 }
801};
802
803//-------------------------------------------------------------------------
804// CommandObjectProcessSignal
805//-------------------------------------------------------------------------
806
807class CommandObjectProcessSignal : public CommandObject
808{
809public:
810
Greg Clayton238c0a12010-09-18 01:14:36 +0000811 CommandObjectProcessSignal (CommandInterpreter &interpreter) :
812 CommandObject (interpreter,
813 "process signal",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000814 "Send a UNIX signal to the current process being debugged.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000815 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000816 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000817 CommandArgumentEntry arg;
818 CommandArgumentData signal_arg;
819
820 // Define the first (and only) variant of this arg.
821 signal_arg.arg_type = eArgTypeUnixSignalNumber;
822 signal_arg.arg_repetition = eArgRepeatPlain;
823
824 // There is only one variant this argument could be; put it into the argument entry.
825 arg.push_back (signal_arg);
826
827 // Push the data for the first argument into the m_arguments vector.
828 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000829 }
830
831 ~CommandObjectProcessSignal ()
832 {
833 }
834
835 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000836 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000837 CommandReturnObject &result)
838 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000839 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000840 if (process == NULL)
841 {
842 result.AppendError ("no process to signal");
843 result.SetStatus (eReturnStatusFailed);
844 return false;
845 }
846
847 if (command.GetArgumentCount() == 1)
848 {
Greg Clayton8f6be2a2010-10-09 01:40:57 +0000849 int signo = LLDB_INVALID_SIGNAL_NUMBER;
850
851 const char *signal_name = command.GetArgumentAtIndex(0);
852 if (::isxdigit (signal_name[0]))
853 signo = Args::StringToSInt32(signal_name, LLDB_INVALID_SIGNAL_NUMBER, 0);
854 else
855 signo = process->GetUnixSignals().GetSignalNumberFromName (signal_name);
856
857 if (signo == LLDB_INVALID_SIGNAL_NUMBER)
Chris Lattner24943d22010-06-08 16:52:24 +0000858 {
859 result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0));
860 result.SetStatus (eReturnStatusFailed);
861 }
862 else
863 {
864 Error error (process->Signal (signo));
865 if (error.Success())
866 {
867 result.SetStatus (eReturnStatusSuccessFinishResult);
868 }
869 else
870 {
871 result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString());
872 result.SetStatus (eReturnStatusFailed);
873 }
874 }
875 }
876 else
877 {
878 result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: \n", m_cmd_name.c_str(),
879 m_cmd_syntax.c_str());
880 result.SetStatus (eReturnStatusFailed);
881 }
882 return result.Succeeded();
883 }
884};
885
886
887//-------------------------------------------------------------------------
888// CommandObjectProcessInterrupt
889//-------------------------------------------------------------------------
890
891class CommandObjectProcessInterrupt : public CommandObject
892{
893public:
894
895
Greg Clayton238c0a12010-09-18 01:14:36 +0000896 CommandObjectProcessInterrupt (CommandInterpreter &interpreter) :
897 CommandObject (interpreter,
898 "process interrupt",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000899 "Interrupt the current process being debugged.",
Chris Lattner24943d22010-06-08 16:52:24 +0000900 "process interrupt",
901 eFlagProcessMustBeLaunched)
902 {
903 }
904
905 ~CommandObjectProcessInterrupt ()
906 {
907 }
908
909 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000910 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000911 CommandReturnObject &result)
912 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000913 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000914 if (process == NULL)
915 {
916 result.AppendError ("no process to halt");
917 result.SetStatus (eReturnStatusFailed);
918 return false;
919 }
920
921 if (command.GetArgumentCount() == 0)
922 {
923 Error error(process->Halt ());
924 if (error.Success())
925 {
926 result.SetStatus (eReturnStatusSuccessFinishResult);
927
928 // Maybe we should add a "SuspendThreadPlans so we
929 // can halt, and keep in place all the current thread plans.
930 process->GetThreadList().DiscardThreadPlans();
931 }
932 else
933 {
934 result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString());
935 result.SetStatus (eReturnStatusFailed);
936 }
937 }
938 else
939 {
940 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
941 m_cmd_name.c_str(),
942 m_cmd_syntax.c_str());
943 result.SetStatus (eReturnStatusFailed);
944 }
945 return result.Succeeded();
946 }
947};
948
949//-------------------------------------------------------------------------
950// CommandObjectProcessKill
951//-------------------------------------------------------------------------
952
953class CommandObjectProcessKill : public CommandObject
954{
955public:
956
Greg Clayton238c0a12010-09-18 01:14:36 +0000957 CommandObjectProcessKill (CommandInterpreter &interpreter) :
958 CommandObject (interpreter,
959 "process kill",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000960 "Terminate the current process being debugged.",
Chris Lattner24943d22010-06-08 16:52:24 +0000961 "process kill",
962 eFlagProcessMustBeLaunched)
963 {
964 }
965
966 ~CommandObjectProcessKill ()
967 {
968 }
969
970 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000971 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000972 CommandReturnObject &result)
973 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000974 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000975 if (process == NULL)
976 {
977 result.AppendError ("no process to kill");
978 result.SetStatus (eReturnStatusFailed);
979 return false;
980 }
981
982 if (command.GetArgumentCount() == 0)
983 {
984 Error error (process->Destroy());
985 if (error.Success())
986 {
987 result.SetStatus (eReturnStatusSuccessFinishResult);
988 }
989 else
990 {
991 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString());
992 result.SetStatus (eReturnStatusFailed);
993 }
994 }
995 else
996 {
997 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
998 m_cmd_name.c_str(),
999 m_cmd_syntax.c_str());
1000 result.SetStatus (eReturnStatusFailed);
1001 }
1002 return result.Succeeded();
1003 }
1004};
1005
1006//-------------------------------------------------------------------------
Jim Ingham41313fc2010-06-18 01:23:09 +00001007// CommandObjectProcessStatus
1008//-------------------------------------------------------------------------
1009class CommandObjectProcessStatus : public CommandObject
1010{
1011public:
Greg Clayton238c0a12010-09-18 01:14:36 +00001012 CommandObjectProcessStatus (CommandInterpreter &interpreter) :
1013 CommandObject (interpreter,
1014 "process status",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001015 "Show the current status and location of executing process.",
1016 "process status",
Jim Ingham41313fc2010-06-18 01:23:09 +00001017 0)
1018 {
1019 }
1020
1021 ~CommandObjectProcessStatus()
1022 {
1023 }
1024
1025
1026 bool
1027 Execute
1028 (
1029 Args& command,
Jim Ingham41313fc2010-06-18 01:23:09 +00001030 CommandReturnObject &result
1031 )
1032 {
1033 StreamString &output_stream = result.GetOutputStream();
1034 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Greg Clayton238c0a12010-09-18 01:14:36 +00001035 ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
Jim Ingham41313fc2010-06-18 01:23:09 +00001036 if (exe_ctx.process)
1037 {
1038 const StateType state = exe_ctx.process->GetState();
1039 if (StateIsStoppedState(state))
1040 {
1041 if (state == eStateExited)
1042 {
1043 int exit_status = exe_ctx.process->GetExitStatus();
1044 const char *exit_description = exe_ctx.process->GetExitDescription();
1045 output_stream.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n",
1046 exe_ctx.process->GetID(),
1047 exit_status,
1048 exit_status,
1049 exit_description ? exit_description : "");
1050 }
1051 else
1052 {
1053 output_stream.Printf ("Process %d %s\n", exe_ctx.process->GetID(), StateAsCString (state));
1054 if (exe_ctx.thread == NULL)
1055 exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
1056 if (exe_ctx.thread != NULL)
1057 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001058 DisplayThreadsInfo (m_interpreter, &exe_ctx, result, true, true);
Jim Ingham41313fc2010-06-18 01:23:09 +00001059 }
1060 else
1061 {
1062 result.AppendError ("No valid thread found in current process.");
1063 result.SetStatus (eReturnStatusFailed);
1064 }
1065 }
1066 }
1067 else
1068 {
1069 output_stream.Printf ("Process %d is running.\n",
1070 exe_ctx.process->GetID());
1071 }
1072 }
1073 else
1074 {
1075 result.AppendError ("No current location or status available.");
1076 result.SetStatus (eReturnStatusFailed);
1077 }
1078 return result.Succeeded();
1079 }
1080};
1081
1082//-------------------------------------------------------------------------
Chris Lattner24943d22010-06-08 16:52:24 +00001083// CommandObjectMultiwordProcess
1084//-------------------------------------------------------------------------
1085
Greg Clayton63094e02010-06-23 01:19:29 +00001086CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001087 CommandObjectMultiword (interpreter,
1088 "process",
1089 "A set of commands for operating on a process.",
1090 "process <subcommand> [<subcommand-options>]")
Chris Lattner24943d22010-06-08 16:52:24 +00001091{
Greg Clayton238c0a12010-09-18 01:14:36 +00001092 LoadSubCommand ("attach", CommandObjectSP (new CommandObjectProcessAttach (interpreter)));
1093 LoadSubCommand ("launch", CommandObjectSP (new CommandObjectProcessLaunch (interpreter)));
1094 LoadSubCommand ("continue", CommandObjectSP (new CommandObjectProcessContinue (interpreter)));
1095 LoadSubCommand ("detach", CommandObjectSP (new CommandObjectProcessDetach (interpreter)));
1096 LoadSubCommand ("signal", CommandObjectSP (new CommandObjectProcessSignal (interpreter)));
1097 LoadSubCommand ("status", CommandObjectSP (new CommandObjectProcessStatus (interpreter)));
1098 LoadSubCommand ("interrupt", CommandObjectSP (new CommandObjectProcessInterrupt (interpreter)));
1099 LoadSubCommand ("kill", CommandObjectSP (new CommandObjectProcessKill (interpreter)));
Chris Lattner24943d22010-06-08 16:52:24 +00001100}
1101
1102CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess ()
1103{
1104}
1105