blob: 3a3e7dc56245de815464a18207a0bb9cb72e620c [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;
Caroline Ticebd666012010-12-03 18:46:09 +000065 case 'n': no_stdio = true; break;
Greg Claytonbb0c91f2010-10-19 23:16:00 +000066 case 't':
67 if (option_arg && option_arg[0])
68 tty_name.assign (option_arg);
69 in_new_tty = true;
70 break;
Chris Lattner24943d22010-06-08 16:52:24 +000071 default:
72 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
73 break;
74
75 }
76 return error;
77 }
78
79 void
80 ResetOptionValues ()
81 {
82 Options::ResetOptionValues();
83 stop_at_entry = false;
Greg Claytonc1d37752010-10-18 01:45:30 +000084 in_new_tty = false;
Greg Claytonbb0c91f2010-10-19 23:16:00 +000085 tty_name.clear();
Chris Lattner24943d22010-06-08 16:52:24 +000086 stdin_path.clear();
87 stdout_path.clear();
88 stderr_path.clear();
89 plugin_name.clear();
Caroline Ticebd666012010-12-03 18:46:09 +000090 no_stdio = false;
Chris Lattner24943d22010-06-08 16:52:24 +000091 }
92
93 const lldb::OptionDefinition*
94 GetDefinitions ()
95 {
96 return g_option_table;
97 }
98
99 // Options table: Required for subclasses of Options.
100
101 static lldb::OptionDefinition g_option_table[];
102
103 // Instance variables to hold the values for command options.
104
105 bool stop_at_entry;
Greg Claytonc1d37752010-10-18 01:45:30 +0000106 bool in_new_tty;
Caroline Ticebd666012010-12-03 18:46:09 +0000107 bool no_stdio;
Greg Claytonbb0c91f2010-10-19 23:16:00 +0000108 std::string tty_name;
Chris Lattner24943d22010-06-08 16:52:24 +0000109 std::string stderr_path;
110 std::string stdin_path;
111 std::string stdout_path;
112 std::string plugin_name;
113
114 };
115
Greg Clayton238c0a12010-09-18 01:14:36 +0000116 CommandObjectProcessLaunch (CommandInterpreter &interpreter) :
117 CommandObject (interpreter,
118 "process launch",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000119 "Launch the executable in the debugger.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000120 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000121 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000122 CommandArgumentEntry arg;
123 CommandArgumentData run_args_arg;
124
125 // Define the first (and only) variant of this arg.
126 run_args_arg.arg_type = eArgTypeRunArgs;
127 run_args_arg.arg_repetition = eArgRepeatOptional;
128
129 // There is only one variant this argument could be; put it into the argument entry.
130 arg.push_back (run_args_arg);
131
132 // Push the data for the first argument into the m_arguments vector.
133 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000134 }
135
136
137 ~CommandObjectProcessLaunch ()
138 {
139 }
140
141 Options *
142 GetOptions ()
143 {
144 return &m_options;
145 }
146
147 bool
Greg Claytond8c62532010-10-07 04:19:01 +0000148 Execute (Args& launch_args, CommandReturnObject &result)
Chris Lattner24943d22010-06-08 16:52:24 +0000149 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000150 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000151
152 if (target == NULL)
153 {
154 result.AppendError ("invalid target, set executable file using 'file' command");
155 result.SetStatus (eReturnStatusFailed);
156 return false;
157 }
158
159 // If our listener is NULL, users aren't allows to launch
Chris Lattner24943d22010-06-08 16:52:24 +0000160 char filename[PATH_MAX];
Greg Claytonc1d37752010-10-18 01:45:30 +0000161 const Module *exe_module = target->GetExecutableModule().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000162 exe_module->GetFileSpec().GetPath(filename, sizeof(filename));
163
Greg Clayton238c0a12010-09-18 01:14:36 +0000164 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
165 if (process && process->IsAlive())
Chris Lattner24943d22010-06-08 16:52:24 +0000166 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000167 result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before running again.\n",
168 process->GetID());
169 result.SetStatus (eReturnStatusFailed);
170 return false;
Chris Lattner24943d22010-06-08 16:52:24 +0000171 }
172
173 const char *plugin_name;
174 if (!m_options.plugin_name.empty())
175 plugin_name = m_options.plugin_name.c_str();
176 else
177 plugin_name = NULL;
178
Greg Clayton238c0a12010-09-18 01:14:36 +0000179 process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
Chris Lattner24943d22010-06-08 16:52:24 +0000180
Greg Clayton238c0a12010-09-18 01:14:36 +0000181 if (process == NULL)
Caroline Tice6e4c5ce2010-09-04 00:03:46 +0000182 {
Caroline Tice734b4832010-10-15 21:52:38 +0000183 result.AppendErrorWithFormat ("Failed to find a process plugin for executable.\n");
Chris Lattner24943d22010-06-08 16:52:24 +0000184 result.SetStatus (eReturnStatusFailed);
185 return false;
186 }
187
Greg Clayton238c0a12010-09-18 01:14:36 +0000188 // If no launch args were given on the command line, then use any that
189 // might have been set using the "run-args" set variable.
190 if (launch_args.GetArgumentCount() == 0)
191 {
192 if (process->GetRunArguments().GetArgumentCount() > 0)
193 launch_args = process->GetRunArguments();
194 }
195
Greg Claytonc1d37752010-10-18 01:45:30 +0000196 if (m_options.in_new_tty)
197 {
198 char exec_file_path[PATH_MAX];
199 if (exe_module->GetFileSpec().GetPath(exec_file_path, sizeof(exec_file_path)))
200 {
201 launch_args.InsertArgumentAtIndex(0, exec_file_path);
202 }
203 else
204 {
205 result.AppendError("invalid executable");
206 result.SetStatus (eReturnStatusFailed);
207 return false;
208 }
209 }
210
Greg Clayton238c0a12010-09-18 01:14:36 +0000211 Args environment;
212
213 process->GetEnvironmentAsArgs (environment);
214
215 uint32_t launch_flags = eLaunchFlagNone;
216
217 if (process->GetDisableASLR())
218 launch_flags |= eLaunchFlagDisableASLR;
Greg Claytonc1d37752010-10-18 01:45:30 +0000219
Caroline Ticebd666012010-12-03 18:46:09 +0000220 if (m_options.no_stdio)
221 launch_flags |= eLaunchFlagDisableSTDIO;
222 else if (!m_options.in_new_tty
223 && m_options.stdin_path.empty()
224 && m_options.stdout_path.empty()
225 && m_options.stderr_path.empty())
226 {
227 // Only use the settings value if the user hasn't specified any options that would override it.
228 if (process->GetDisableSTDIO())
229 launch_flags |= eLaunchFlagDisableSTDIO;
230 }
231
Greg Claytonc1d37752010-10-18 01:45:30 +0000232 const char **inferior_argv = launch_args.GetArgumentCount() ? launch_args.GetConstArgumentVector() : NULL;
233 const char **inferior_envp = environment.GetArgumentCount() ? environment.GetConstArgumentVector() : NULL;
Greg Clayton238c0a12010-09-18 01:14:36 +0000234
Greg Claytonc1d37752010-10-18 01:45:30 +0000235 Error error;
Greg Clayton238c0a12010-09-18 01:14:36 +0000236
Greg Claytonc1d37752010-10-18 01:45:30 +0000237 if (m_options.in_new_tty)
Greg Clayton238c0a12010-09-18 01:14:36 +0000238 {
Greg Claytonc1d37752010-10-18 01:45:30 +0000239
Greg Claytonbb0c91f2010-10-19 23:16:00 +0000240 lldb::pid_t pid = Host::LaunchInNewTerminal (m_options.tty_name.c_str(),
241 inferior_argv,
Greg Clayton36f63a92010-10-19 03:25:40 +0000242 inferior_envp,
243 &exe_module->GetArchitecture(),
244 true,
245 process->GetDisableASLR());
Greg Claytonc1d37752010-10-18 01:45:30 +0000246
Greg Clayton36f63a92010-10-19 03:25:40 +0000247 if (pid != LLDB_INVALID_PROCESS_ID)
248 error = process->Attach (pid);
Greg Clayton238c0a12010-09-18 01:14:36 +0000249 }
250 else
251 {
Greg Claytonc1d37752010-10-18 01:45:30 +0000252 const char * stdin_path = NULL;
253 const char * stdout_path = NULL;
254 const char * stderr_path = NULL;
255
256 // Were any standard input/output/error paths given on the command line?
257 if (m_options.stdin_path.empty() &&
258 m_options.stdout_path.empty() &&
259 m_options.stderr_path.empty())
260 {
261 // No standard file handles were given on the command line, check
262 // with the process object in case they were give using "set settings"
263 stdin_path = process->GetStandardInputPath();
264 stdout_path = process->GetStandardOutputPath();
265 stderr_path = process->GetStandardErrorPath();
266 }
267 else
268 {
269 stdin_path = m_options.stdin_path.empty() ? NULL : m_options.stdin_path.c_str();
270 stdout_path = m_options.stdout_path.empty() ? NULL : m_options.stdout_path.c_str();
271 stderr_path = m_options.stderr_path.empty() ? NULL : m_options.stderr_path.c_str();
272 }
273
274 if (stdin_path == NULL)
275 stdin_path = "/dev/null";
276 if (stdout_path == NULL)
277 stdout_path = "/dev/null";
278 if (stderr_path == NULL)
279 stderr_path = "/dev/null";
280
281 error = process->Launch (inferior_argv,
282 inferior_envp,
283 launch_flags,
284 stdin_path,
285 stdout_path,
286 stderr_path);
Greg Clayton238c0a12010-09-18 01:14:36 +0000287 }
Greg Clayton238c0a12010-09-18 01:14:36 +0000288
289 if (error.Success())
290 {
Greg Claytonc1d37752010-10-18 01:45:30 +0000291 const char *archname = exe_module->GetArchitecture().AsCString();
292
293 result.AppendMessageWithFormat ("Process %i launched: '%s' (%s)\n", process->GetID(), filename, archname);
Greg Claytond8c62532010-10-07 04:19:01 +0000294 result.SetDidChangeProcessState (true);
Greg Clayton238c0a12010-09-18 01:14:36 +0000295 if (m_options.stop_at_entry == false)
296 {
Greg Claytond8c62532010-10-07 04:19:01 +0000297 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
Greg Clayton238c0a12010-09-18 01:14:36 +0000298 StateType state = process->WaitForProcessToStop (NULL);
299
300 if (state == eStateStopped)
301 {
Greg Claytond8c62532010-10-07 04:19:01 +0000302 error = process->Resume();
303 if (error.Success())
304 {
305 bool synchronous_execution = m_interpreter.GetSynchronous ();
306 if (synchronous_execution)
307 {
308 state = process->WaitForProcessToStop (NULL);
309 result.SetDidChangeProcessState (true);
310 result.SetStatus (eReturnStatusSuccessFinishResult);
311 }
312 else
313 {
314 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
315 }
316 }
Greg Clayton238c0a12010-09-18 01:14:36 +0000317 }
318 }
319 }
320
Chris Lattner24943d22010-06-08 16:52:24 +0000321 return result.Succeeded();
322 }
323
Jim Ingham767af882010-07-07 03:36:20 +0000324 virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
325 {
326 // No repeat for "process launch"...
327 return "";
328 }
329
Chris Lattner24943d22010-06-08 16:52:24 +0000330protected:
331
332 CommandOptions m_options;
333};
334
335
Greg Claytonc1d37752010-10-18 01:45:30 +0000336#define SET1 LLDB_OPT_SET_1
337#define SET2 LLDB_OPT_SET_2
Caroline Ticebd666012010-12-03 18:46:09 +0000338#define SET3 LLDB_OPT_SET_3
Greg Claytonc1d37752010-10-18 01:45:30 +0000339
Chris Lattner24943d22010-06-08 16:52:24 +0000340lldb::OptionDefinition
341CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
342{
Caroline Ticebd666012010-12-03 18:46:09 +0000343{ SET1 | SET2 | SET3, false, "stop-at-entry", 's', no_argument, NULL, 0, eArgTypeNone, "Stop at the entry point of the program when launching a process."},
344{ SET1 , false, "stdin", 'i', required_argument, NULL, 0, eArgTypePath, "Redirect stdin for the process to <path>."},
345{ SET1 , false, "stdout", 'o', required_argument, NULL, 0, eArgTypePath, "Redirect stdout for the process to <path>."},
346{ SET1 , false, "stderr", 'e', required_argument, NULL, 0, eArgTypePath, "Redirect stderr for the process to <path>."},
347{ SET1 | SET2 | SET3, false, "plugin", 'p', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
348{ SET2 , false, "tty", 't', optional_argument, NULL, 0, eArgTypePath, "Start the process in a terminal. If <path> is specified, look for a terminal whose name contains <path>, else start the process in a new terminal."},
349{ SET3, false, "no-stdio", 'n', no_argument, NULL, 0, eArgTypeNone, "Do not set up for terminal I/O to go to running process."},
350{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +0000351};
352
Greg Claytonc1d37752010-10-18 01:45:30 +0000353#undef SET1
354#undef SET2
Caroline Ticebd666012010-12-03 18:46:09 +0000355#undef SET3
Chris Lattner24943d22010-06-08 16:52:24 +0000356
357//-------------------------------------------------------------------------
358// CommandObjectProcessAttach
359//-------------------------------------------------------------------------
360
361class CommandObjectProcessAttach : public CommandObject
362{
363public:
364
Chris Lattner24943d22010-06-08 16:52:24 +0000365 class CommandOptions : public Options
366 {
367 public:
368
369 CommandOptions () :
370 Options()
371 {
372 // Keep default values of all options in one place: ResetOptionValues ()
373 ResetOptionValues ();
374 }
375
376 ~CommandOptions ()
377 {
378 }
379
380 Error
381 SetOptionValue (int option_idx, const char *option_arg)
382 {
383 Error error;
384 char short_option = (char) m_getopt_table[option_idx].val;
385 bool success = false;
386 switch (short_option)
387 {
388 case 'p':
389 pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success);
390 if (!success || pid == LLDB_INVALID_PROCESS_ID)
391 {
392 error.SetErrorStringWithFormat("Invalid process ID '%s'.\n", option_arg);
393 }
394 break;
395
396 case 'P':
397 plugin_name = option_arg;
398 break;
399
400 case 'n':
401 name.assign(option_arg);
402 break;
403
404 case 'w':
405 waitfor = true;
406 break;
407
408 default:
409 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
410 break;
411 }
412 return error;
413 }
414
415 void
416 ResetOptionValues ()
417 {
418 Options::ResetOptionValues();
419 pid = LLDB_INVALID_PROCESS_ID;
420 name.clear();
421 waitfor = false;
422 }
423
424 const lldb::OptionDefinition*
425 GetDefinitions ()
426 {
427 return g_option_table;
428 }
429
Jim Ingham7508e732010-08-09 23:31:02 +0000430 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000431 HandleOptionArgumentCompletion (CommandInterpreter &interpeter,
Jim Ingham7508e732010-08-09 23:31:02 +0000432 Args &input,
433 int cursor_index,
434 int char_pos,
435 OptionElementVector &opt_element_vector,
436 int opt_element_index,
437 int match_start_point,
438 int max_return_elements,
439 bool &word_complete,
440 StringList &matches)
441 {
442 int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
443 int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
444
445 // We are only completing the name option for now...
446
447 const lldb::OptionDefinition *opt_defs = GetDefinitions();
448 if (opt_defs[opt_defs_index].short_option == 'n')
449 {
450 // Are we in the name?
451
452 // Look to see if there is a -P argument provided, and if so use that plugin, otherwise
453 // use the default plugin.
Greg Clayton238c0a12010-09-18 01:14:36 +0000454 Process *process = interpeter.GetDebugger().GetExecutionContext().process;
Jim Ingham7508e732010-08-09 23:31:02 +0000455 bool need_to_delete_process = false;
456
457 const char *partial_name = NULL;
458 partial_name = input.GetArgumentAtIndex(opt_arg_pos);
459
460 if (process && process->IsAlive())
461 return true;
462
Greg Clayton238c0a12010-09-18 01:14:36 +0000463 Target *target = interpeter.GetDebugger().GetSelectedTarget().get();
Jim Ingham7508e732010-08-09 23:31:02 +0000464 if (target == NULL)
465 {
466 // No target has been set yet, for now do host completion. Otherwise I don't know how we would
467 // figure out what the right target to use is...
468 std::vector<lldb::pid_t> pids;
469 Host::ListProcessesMatchingName (partial_name, matches, pids);
470 return true;
471 }
472 if (!process)
473 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000474 process = target->CreateProcess (interpeter.GetDebugger().GetListener(), partial_name).get();
Jim Ingham7508e732010-08-09 23:31:02 +0000475 need_to_delete_process = true;
476 }
477
478 if (process)
479 {
480 matches.Clear();
481 std::vector<lldb::pid_t> pids;
482 process->ListProcessesMatchingName (NULL, matches, pids);
483 if (need_to_delete_process)
484 target->DeleteCurrentProcess();
485 return true;
486 }
487 }
488
489 return false;
490 }
491
Chris Lattner24943d22010-06-08 16:52:24 +0000492 // Options table: Required for subclasses of Options.
493
494 static lldb::OptionDefinition g_option_table[];
495
496 // Instance variables to hold the values for command options.
497
498 lldb::pid_t pid;
499 std::string plugin_name;
500 std::string name;
501 bool waitfor;
502 };
503
Greg Clayton238c0a12010-09-18 01:14:36 +0000504 CommandObjectProcessAttach (CommandInterpreter &interpreter) :
505 CommandObject (interpreter,
506 "process attach",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000507 "Attach to a process.",
Jim Ingham7508e732010-08-09 23:31:02 +0000508 "process attach <cmd-options>")
509 {
Jim Ingham7508e732010-08-09 23:31:02 +0000510 }
511
512 ~CommandObjectProcessAttach ()
513 {
514 }
515
516 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000517 Execute (Args& command,
Jim Ingham7508e732010-08-09 23:31:02 +0000518 CommandReturnObject &result)
519 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000520 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Jim Ingham7508e732010-08-09 23:31:02 +0000521
Greg Clayton238c0a12010-09-18 01:14:36 +0000522 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Jim Ingham7508e732010-08-09 23:31:02 +0000523 if (process)
524 {
525 if (process->IsAlive())
526 {
527 result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before attaching.\n",
528 process->GetID());
529 result.SetStatus (eReturnStatusFailed);
530 return false;
531 }
532 }
533
534 if (target == NULL)
535 {
536 // If there isn't a current target create one.
537 TargetSP new_target_sp;
538 FileSpec emptyFileSpec;
539 ArchSpec emptyArchSpec;
540 Error error;
541
Greg Clayton238c0a12010-09-18 01:14:36 +0000542 error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(),
543 emptyFileSpec,
544 emptyArchSpec,
545 NULL,
546 false,
547 new_target_sp);
Jim Ingham7508e732010-08-09 23:31:02 +0000548 target = new_target_sp.get();
549 if (target == NULL || error.Fail())
550 {
551 result.AppendError(error.AsCString("Error creating empty target"));
552 return false;
553 }
Greg Clayton238c0a12010-09-18 01:14:36 +0000554 m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target);
Jim Ingham7508e732010-08-09 23:31:02 +0000555 }
556
557 // Record the old executable module, we want to issue a warning if the process of attaching changed the
558 // current executable (like somebody said "file foo" then attached to a PID whose executable was bar.)
559
560 ModuleSP old_exec_module_sp = target->GetExecutableModule();
561 ArchSpec old_arch_spec = target->GetArchitecture();
562
563 if (command.GetArgumentCount())
564 {
565 result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
566 result.SetStatus (eReturnStatusFailed);
567 }
568 else
569 {
570 const char *plugin_name = NULL;
571
572 if (!m_options.plugin_name.empty())
573 plugin_name = m_options.plugin_name.c_str();
574
Greg Clayton238c0a12010-09-18 01:14:36 +0000575 process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
Jim Ingham7508e732010-08-09 23:31:02 +0000576
577 if (process)
578 {
579 Error error;
580 int attach_pid = m_options.pid;
581
Jim Ingham4805a1c2010-09-15 01:34:14 +0000582 const char *wait_name = NULL;
583
584 if (m_options.name.empty())
585 {
586 if (old_exec_module_sp)
587 {
588 wait_name = old_exec_module_sp->GetFileSpec().GetFilename().AsCString();
589 }
590 }
591 else
592 {
593 wait_name = m_options.name.c_str();
594 }
595
Jim Ingham7508e732010-08-09 23:31:02 +0000596 // If we are waiting for a process with this name to show up, do that first.
597 if (m_options.waitfor)
598 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000599
600 if (wait_name == NULL)
Jim Ingham7508e732010-08-09 23:31:02 +0000601 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000602 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 +0000603 result.SetStatus (eReturnStatusFailed);
604 return false;
605 }
Jim Ingham4805a1c2010-09-15 01:34:14 +0000606
Greg Clayton238c0a12010-09-18 01:14:36 +0000607 m_interpreter.GetDebugger().GetOutputStream().Printf("Waiting to attach to a process named \"%s\".\n", wait_name);
Jim Ingham4805a1c2010-09-15 01:34:14 +0000608 error = process->Attach (wait_name, m_options.waitfor);
609 if (error.Success())
610 {
611 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
612 }
Jim Ingham7508e732010-08-09 23:31:02 +0000613 else
614 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000615 result.AppendErrorWithFormat ("Waiting for a process to launch named '%s': %s\n",
616 wait_name,
617 error.AsCString());
618 result.SetStatus (eReturnStatusFailed);
619 return false;
Jim Ingham7508e732010-08-09 23:31:02 +0000620 }
621 }
622 else
623 {
624 // If the process was specified by name look it up, so we can warn if there are multiple
625 // processes with this pid.
626
Jim Ingham4805a1c2010-09-15 01:34:14 +0000627 if (attach_pid == LLDB_INVALID_PROCESS_ID && wait_name != NULL)
Jim Ingham7508e732010-08-09 23:31:02 +0000628 {
629 std::vector<lldb::pid_t> pids;
630 StringList matches;
631
Jim Ingham4805a1c2010-09-15 01:34:14 +0000632 process->ListProcessesMatchingName(wait_name, matches, pids);
Jim Ingham7508e732010-08-09 23:31:02 +0000633 if (matches.GetSize() > 1)
634 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000635 result.AppendErrorWithFormat("More than one process named %s\n", wait_name);
Jim Ingham7508e732010-08-09 23:31:02 +0000636 result.SetStatus (eReturnStatusFailed);
637 return false;
638 }
639 else if (matches.GetSize() == 0)
640 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000641 result.AppendErrorWithFormat("Could not find a process named %s\n", wait_name);
Jim Ingham7508e732010-08-09 23:31:02 +0000642 result.SetStatus (eReturnStatusFailed);
643 return false;
644 }
645 else
646 {
647 attach_pid = pids[0];
648 }
649
650 }
651
652 if (attach_pid != LLDB_INVALID_PROCESS_ID)
653 {
654 error = process->Attach (attach_pid);
655 if (error.Success())
656 {
657 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
658 }
659 else
660 {
661 result.AppendErrorWithFormat ("Attaching to process %i failed: %s.\n",
662 attach_pid,
663 error.AsCString());
664 result.SetStatus (eReturnStatusFailed);
665 }
666 }
667 else
668 {
669 result.AppendErrorWithFormat ("No PID specified for attach\n",
670 attach_pid,
671 error.AsCString());
672 result.SetStatus (eReturnStatusFailed);
673
674 }
675 }
676 }
677 }
678
679 if (result.Succeeded())
680 {
681 // Okay, we're done. Last step is to warn if the executable module has changed:
682 if (!old_exec_module_sp)
683 {
684 char new_path[PATH_MAX + 1];
685 target->GetExecutableModule()->GetFileSpec().GetPath(new_path, PATH_MAX);
686
687 result.AppendMessageWithFormat("Executable module set to \"%s\".\n",
688 new_path);
689 }
690 else if (old_exec_module_sp->GetFileSpec() != target->GetExecutableModule()->GetFileSpec())
691 {
692 char old_path[PATH_MAX + 1];
693 char new_path[PATH_MAX + 1];
694
695 old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX);
696 target->GetExecutableModule()->GetFileSpec().GetPath (new_path, PATH_MAX);
697
698 result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n",
699 old_path, new_path);
700 }
701
702 if (!old_arch_spec.IsValid())
703 {
704 result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().AsCString());
705 }
706 else if (old_arch_spec != target->GetArchitecture())
707 {
708 result.AppendWarningWithFormat("Architecture changed from %s to %s.\n",
709 old_arch_spec.AsCString(), target->GetArchitecture().AsCString());
710 }
711 }
712 return result.Succeeded();
713 }
714
715 Options *
716 GetOptions ()
717 {
718 return &m_options;
719 }
720
Chris Lattner24943d22010-06-08 16:52:24 +0000721protected:
722
723 CommandOptions m_options;
724};
725
726
727lldb::OptionDefinition
728CommandObjectProcessAttach::CommandOptions::g_option_table[] =
729{
Caroline Tice4d6675c2010-10-01 19:59:14 +0000730{ LLDB_OPT_SET_ALL, false, "plugin", 'P', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
731{ LLDB_OPT_SET_1, false, "pid", 'p', required_argument, NULL, 0, eArgTypePid, "The process ID of an existing process to attach to."},
732{ LLDB_OPT_SET_2, false, "name", 'n', required_argument, NULL, 0, eArgTypeProcessName, "The name of the process to attach to."},
733{ LLDB_OPT_SET_2, false, "waitfor",'w', no_argument, NULL, 0, eArgTypeNone, "Wait for the the process with <process-name> to launch."},
734{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +0000735};
736
737//-------------------------------------------------------------------------
738// CommandObjectProcessContinue
739//-------------------------------------------------------------------------
740
741class CommandObjectProcessContinue : public CommandObject
742{
743public:
744
Greg Clayton238c0a12010-09-18 01:14:36 +0000745 CommandObjectProcessContinue (CommandInterpreter &interpreter) :
746 CommandObject (interpreter,
747 "process continue",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000748 "Continue execution of all threads in the current process.",
Chris Lattner24943d22010-06-08 16:52:24 +0000749 "process continue",
750 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
751 {
752 }
753
754
755 ~CommandObjectProcessContinue ()
756 {
757 }
758
759 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000760 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000761 CommandReturnObject &result)
762 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000763 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
764 bool synchronous_execution = m_interpreter.GetSynchronous ();
Chris Lattner24943d22010-06-08 16:52:24 +0000765
766 if (process == NULL)
767 {
768 result.AppendError ("no process to continue");
769 result.SetStatus (eReturnStatusFailed);
770 return false;
771 }
772
773 StateType state = process->GetState();
774 if (state == eStateStopped)
775 {
776 if (command.GetArgumentCount() != 0)
777 {
778 result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str());
779 result.SetStatus (eReturnStatusFailed);
780 return false;
781 }
782
783 const uint32_t num_threads = process->GetThreadList().GetSize();
784
785 // Set the actions that the threads should each take when resuming
786 for (uint32_t idx=0; idx<num_threads; ++idx)
787 {
788 process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning);
789 }
790
791 Error error(process->Resume());
792 if (error.Success())
793 {
Greg Claytonc1d37752010-10-18 01:45:30 +0000794 result.AppendMessageWithFormat ("Process %i resuming\n", process->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000795 if (synchronous_execution)
796 {
Greg Claytonbef15832010-07-14 00:18:15 +0000797 state = process->WaitForProcessToStop (NULL);
Chris Lattner24943d22010-06-08 16:52:24 +0000798
799 result.SetDidChangeProcessState (true);
800 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
801 result.SetStatus (eReturnStatusSuccessFinishNoResult);
802 }
803 else
804 {
805 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
806 }
807 }
808 else
809 {
810 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
811 result.SetStatus (eReturnStatusFailed);
812 }
813 }
814 else
815 {
816 result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
817 StateAsCString(state));
818 result.SetStatus (eReturnStatusFailed);
819 }
820 return result.Succeeded();
821 }
822};
823
824//-------------------------------------------------------------------------
825// CommandObjectProcessDetach
826//-------------------------------------------------------------------------
827
828class CommandObjectProcessDetach : public CommandObject
829{
830public:
831
Greg Clayton238c0a12010-09-18 01:14:36 +0000832 CommandObjectProcessDetach (CommandInterpreter &interpreter) :
833 CommandObject (interpreter,
834 "process detach",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000835 "Detach from the current process being debugged.",
Chris Lattner24943d22010-06-08 16:52:24 +0000836 "process detach",
837 eFlagProcessMustBeLaunched)
838 {
839 }
840
841 ~CommandObjectProcessDetach ()
842 {
843 }
844
845 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000846 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000847 CommandReturnObject &result)
848 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000849 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000850 if (process == NULL)
851 {
852 result.AppendError ("must have a valid process in order to detach");
853 result.SetStatus (eReturnStatusFailed);
854 return false;
855 }
856
Caroline Tice90b42252010-11-02 16:16:53 +0000857 result.AppendMessageWithFormat ("Detaching from process %i\n", process->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000858 Error error (process->Detach());
859 if (error.Success())
860 {
861 result.SetStatus (eReturnStatusSuccessFinishResult);
862 }
863 else
864 {
865 result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString());
866 result.SetStatus (eReturnStatusFailed);
867 return false;
868 }
869 return result.Succeeded();
870 }
871};
872
873//-------------------------------------------------------------------------
Greg Clayton0baa3942010-11-04 01:54:29 +0000874// CommandObjectProcessLoad
875//-------------------------------------------------------------------------
876
877class CommandObjectProcessLoad : public CommandObject
878{
879public:
880
881 CommandObjectProcessLoad (CommandInterpreter &interpreter) :
882 CommandObject (interpreter,
883 "process load",
884 "Load a shared library into the current process.",
885 "process load <filename> [<filename> ...]",
886 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
887 {
888 }
889
890 ~CommandObjectProcessLoad ()
891 {
892 }
893
894 bool
895 Execute (Args& command,
896 CommandReturnObject &result)
897 {
898 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
899 if (process == NULL)
900 {
901 result.AppendError ("must have a valid process in order to load a shared library");
902 result.SetStatus (eReturnStatusFailed);
903 return false;
904 }
905
906 const uint32_t argc = command.GetArgumentCount();
907
908 for (uint32_t i=0; i<argc; ++i)
909 {
910 Error error;
911 const char *image_path = command.GetArgumentAtIndex(i);
912 FileSpec image_spec (image_path, false);
913 uint32_t image_token = process->LoadImage(image_spec, error);
914 if (image_token != LLDB_INVALID_IMAGE_TOKEN)
915 {
916 result.AppendMessageWithFormat ("Loading \"%s\"...ok\nImage %u loaded.\n", image_path, image_token);
917 result.SetStatus (eReturnStatusSuccessFinishResult);
918 }
919 else
920 {
921 result.AppendErrorWithFormat ("failed to load '%s': %s", image_path, error.AsCString());
922 result.SetStatus (eReturnStatusFailed);
923 }
924 }
925 return result.Succeeded();
926 }
927};
928
929
930//-------------------------------------------------------------------------
931// CommandObjectProcessUnload
932//-------------------------------------------------------------------------
933
934class CommandObjectProcessUnload : public CommandObject
935{
936public:
937
938 CommandObjectProcessUnload (CommandInterpreter &interpreter) :
939 CommandObject (interpreter,
940 "process unload",
941 "Unload a shared library from the current process using the index returned by a previous call to \"process load\".",
942 "process unload <index>",
943 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
944 {
945 }
946
947 ~CommandObjectProcessUnload ()
948 {
949 }
950
951 bool
952 Execute (Args& command,
953 CommandReturnObject &result)
954 {
955 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
956 if (process == NULL)
957 {
958 result.AppendError ("must have a valid process in order to load a shared library");
959 result.SetStatus (eReturnStatusFailed);
960 return false;
961 }
962
963 const uint32_t argc = command.GetArgumentCount();
964
965 for (uint32_t i=0; i<argc; ++i)
966 {
967 const char *image_token_cstr = command.GetArgumentAtIndex(i);
968 uint32_t image_token = Args::StringToUInt32(image_token_cstr, LLDB_INVALID_IMAGE_TOKEN, 0);
969 if (image_token == LLDB_INVALID_IMAGE_TOKEN)
970 {
971 result.AppendErrorWithFormat ("invalid image index argument '%s'", image_token_cstr);
972 result.SetStatus (eReturnStatusFailed);
973 break;
974 }
975 else
976 {
977 Error error (process->UnloadImage(image_token));
978 if (error.Success())
979 {
980 result.AppendMessageWithFormat ("Unloading shared library with index %u...ok\n", image_token);
981 result.SetStatus (eReturnStatusSuccessFinishResult);
982 }
983 else
984 {
985 result.AppendErrorWithFormat ("failed to unload image: %s", error.AsCString());
986 result.SetStatus (eReturnStatusFailed);
987 break;
988 }
989 }
990 }
991 return result.Succeeded();
992 }
993};
994
995//-------------------------------------------------------------------------
Chris Lattner24943d22010-06-08 16:52:24 +0000996// CommandObjectProcessSignal
997//-------------------------------------------------------------------------
998
999class CommandObjectProcessSignal : public CommandObject
1000{
1001public:
1002
Greg Clayton238c0a12010-09-18 01:14:36 +00001003 CommandObjectProcessSignal (CommandInterpreter &interpreter) :
1004 CommandObject (interpreter,
1005 "process signal",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001006 "Send a UNIX signal to the current process being debugged.",
Caroline Tice43b014a2010-10-04 22:28:36 +00001007 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +00001008 {
Caroline Tice43b014a2010-10-04 22:28:36 +00001009 CommandArgumentEntry arg;
1010 CommandArgumentData signal_arg;
1011
1012 // Define the first (and only) variant of this arg.
Caroline Tice3a62e6d2010-10-18 22:56:57 +00001013 signal_arg.arg_type = eArgTypeUnixSignal;
Caroline Tice43b014a2010-10-04 22:28:36 +00001014 signal_arg.arg_repetition = eArgRepeatPlain;
1015
1016 // There is only one variant this argument could be; put it into the argument entry.
1017 arg.push_back (signal_arg);
1018
1019 // Push the data for the first argument into the m_arguments vector.
1020 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +00001021 }
1022
1023 ~CommandObjectProcessSignal ()
1024 {
1025 }
1026
1027 bool
Greg Clayton238c0a12010-09-18 01:14:36 +00001028 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +00001029 CommandReturnObject &result)
1030 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001031 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +00001032 if (process == NULL)
1033 {
1034 result.AppendError ("no process to signal");
1035 result.SetStatus (eReturnStatusFailed);
1036 return false;
1037 }
1038
1039 if (command.GetArgumentCount() == 1)
1040 {
Greg Clayton8f6be2a2010-10-09 01:40:57 +00001041 int signo = LLDB_INVALID_SIGNAL_NUMBER;
1042
1043 const char *signal_name = command.GetArgumentAtIndex(0);
1044 if (::isxdigit (signal_name[0]))
1045 signo = Args::StringToSInt32(signal_name, LLDB_INVALID_SIGNAL_NUMBER, 0);
1046 else
1047 signo = process->GetUnixSignals().GetSignalNumberFromName (signal_name);
1048
1049 if (signo == LLDB_INVALID_SIGNAL_NUMBER)
Chris Lattner24943d22010-06-08 16:52:24 +00001050 {
1051 result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0));
1052 result.SetStatus (eReturnStatusFailed);
1053 }
1054 else
1055 {
1056 Error error (process->Signal (signo));
1057 if (error.Success())
1058 {
1059 result.SetStatus (eReturnStatusSuccessFinishResult);
1060 }
1061 else
1062 {
1063 result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString());
1064 result.SetStatus (eReturnStatusFailed);
1065 }
1066 }
1067 }
1068 else
1069 {
1070 result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: \n", m_cmd_name.c_str(),
1071 m_cmd_syntax.c_str());
1072 result.SetStatus (eReturnStatusFailed);
1073 }
1074 return result.Succeeded();
1075 }
1076};
1077
1078
1079//-------------------------------------------------------------------------
1080// CommandObjectProcessInterrupt
1081//-------------------------------------------------------------------------
1082
1083class CommandObjectProcessInterrupt : public CommandObject
1084{
1085public:
1086
1087
Greg Clayton238c0a12010-09-18 01:14:36 +00001088 CommandObjectProcessInterrupt (CommandInterpreter &interpreter) :
1089 CommandObject (interpreter,
1090 "process interrupt",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001091 "Interrupt the current process being debugged.",
Chris Lattner24943d22010-06-08 16:52:24 +00001092 "process interrupt",
1093 eFlagProcessMustBeLaunched)
1094 {
1095 }
1096
1097 ~CommandObjectProcessInterrupt ()
1098 {
1099 }
1100
1101 bool
Greg Clayton238c0a12010-09-18 01:14:36 +00001102 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +00001103 CommandReturnObject &result)
1104 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001105 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +00001106 if (process == NULL)
1107 {
1108 result.AppendError ("no process to halt");
1109 result.SetStatus (eReturnStatusFailed);
1110 return false;
1111 }
1112
1113 if (command.GetArgumentCount() == 0)
1114 {
1115 Error error(process->Halt ());
1116 if (error.Success())
1117 {
1118 result.SetStatus (eReturnStatusSuccessFinishResult);
1119
1120 // Maybe we should add a "SuspendThreadPlans so we
1121 // can halt, and keep in place all the current thread plans.
1122 process->GetThreadList().DiscardThreadPlans();
1123 }
1124 else
1125 {
1126 result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString());
1127 result.SetStatus (eReturnStatusFailed);
1128 }
1129 }
1130 else
1131 {
1132 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
1133 m_cmd_name.c_str(),
1134 m_cmd_syntax.c_str());
1135 result.SetStatus (eReturnStatusFailed);
1136 }
1137 return result.Succeeded();
1138 }
1139};
1140
1141//-------------------------------------------------------------------------
1142// CommandObjectProcessKill
1143//-------------------------------------------------------------------------
1144
1145class CommandObjectProcessKill : public CommandObject
1146{
1147public:
1148
Greg Clayton238c0a12010-09-18 01:14:36 +00001149 CommandObjectProcessKill (CommandInterpreter &interpreter) :
1150 CommandObject (interpreter,
1151 "process kill",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001152 "Terminate the current process being debugged.",
Chris Lattner24943d22010-06-08 16:52:24 +00001153 "process kill",
1154 eFlagProcessMustBeLaunched)
1155 {
1156 }
1157
1158 ~CommandObjectProcessKill ()
1159 {
1160 }
1161
1162 bool
Greg Clayton238c0a12010-09-18 01:14:36 +00001163 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +00001164 CommandReturnObject &result)
1165 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001166 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +00001167 if (process == NULL)
1168 {
1169 result.AppendError ("no process to kill");
1170 result.SetStatus (eReturnStatusFailed);
1171 return false;
1172 }
1173
1174 if (command.GetArgumentCount() == 0)
1175 {
1176 Error error (process->Destroy());
1177 if (error.Success())
1178 {
1179 result.SetStatus (eReturnStatusSuccessFinishResult);
1180 }
1181 else
1182 {
1183 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString());
1184 result.SetStatus (eReturnStatusFailed);
1185 }
1186 }
1187 else
1188 {
1189 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
1190 m_cmd_name.c_str(),
1191 m_cmd_syntax.c_str());
1192 result.SetStatus (eReturnStatusFailed);
1193 }
1194 return result.Succeeded();
1195 }
1196};
1197
1198//-------------------------------------------------------------------------
Jim Ingham41313fc2010-06-18 01:23:09 +00001199// CommandObjectProcessStatus
1200//-------------------------------------------------------------------------
1201class CommandObjectProcessStatus : public CommandObject
1202{
1203public:
Greg Clayton238c0a12010-09-18 01:14:36 +00001204 CommandObjectProcessStatus (CommandInterpreter &interpreter) :
1205 CommandObject (interpreter,
1206 "process status",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001207 "Show the current status and location of executing process.",
1208 "process status",
Jim Ingham41313fc2010-06-18 01:23:09 +00001209 0)
1210 {
1211 }
1212
1213 ~CommandObjectProcessStatus()
1214 {
1215 }
1216
1217
1218 bool
1219 Execute
1220 (
1221 Args& command,
Jim Ingham41313fc2010-06-18 01:23:09 +00001222 CommandReturnObject &result
1223 )
1224 {
1225 StreamString &output_stream = result.GetOutputStream();
1226 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Greg Clayton238c0a12010-09-18 01:14:36 +00001227 ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
Jim Ingham41313fc2010-06-18 01:23:09 +00001228 if (exe_ctx.process)
1229 {
1230 const StateType state = exe_ctx.process->GetState();
1231 if (StateIsStoppedState(state))
1232 {
1233 if (state == eStateExited)
1234 {
1235 int exit_status = exe_ctx.process->GetExitStatus();
1236 const char *exit_description = exe_ctx.process->GetExitDescription();
1237 output_stream.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n",
1238 exe_ctx.process->GetID(),
1239 exit_status,
1240 exit_status,
1241 exit_description ? exit_description : "");
1242 }
1243 else
1244 {
1245 output_stream.Printf ("Process %d %s\n", exe_ctx.process->GetID(), StateAsCString (state));
1246 if (exe_ctx.thread == NULL)
1247 exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
1248 if (exe_ctx.thread != NULL)
1249 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001250 DisplayThreadsInfo (m_interpreter, &exe_ctx, result, true, true);
Jim Ingham41313fc2010-06-18 01:23:09 +00001251 }
1252 else
1253 {
1254 result.AppendError ("No valid thread found in current process.");
1255 result.SetStatus (eReturnStatusFailed);
1256 }
1257 }
1258 }
1259 else
1260 {
1261 output_stream.Printf ("Process %d is running.\n",
1262 exe_ctx.process->GetID());
1263 }
1264 }
1265 else
1266 {
1267 result.AppendError ("No current location or status available.");
1268 result.SetStatus (eReturnStatusFailed);
1269 }
1270 return result.Succeeded();
1271 }
1272};
1273
1274//-------------------------------------------------------------------------
Caroline Tice23d6f272010-10-13 20:44:39 +00001275// CommandObjectProcessHandle
1276//-------------------------------------------------------------------------
1277
1278class CommandObjectProcessHandle : public CommandObject
1279{
1280public:
1281
1282 class CommandOptions : public Options
1283 {
1284 public:
1285
1286 CommandOptions () :
1287 Options ()
1288 {
1289 ResetOptionValues ();
1290 }
1291
1292 ~CommandOptions ()
1293 {
1294 }
1295
1296 Error
1297 SetOptionValue (int option_idx, const char *option_arg)
1298 {
1299 Error error;
1300 char short_option = (char) m_getopt_table[option_idx].val;
1301
1302 switch (short_option)
1303 {
1304 case 's':
1305 stop = option_arg;
1306 break;
1307 case 'n':
1308 notify = option_arg;
1309 break;
1310 case 'p':
1311 pass = option_arg;
1312 break;
1313 default:
1314 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
1315 break;
1316 }
1317 return error;
1318 }
1319
1320 void
1321 ResetOptionValues ()
1322 {
1323 Options::ResetOptionValues();
1324 stop.clear();
1325 notify.clear();
1326 pass.clear();
1327 }
1328
1329 const lldb::OptionDefinition*
1330 GetDefinitions ()
1331 {
1332 return g_option_table;
1333 }
1334
1335 // Options table: Required for subclasses of Options.
1336
1337 static lldb::OptionDefinition g_option_table[];
1338
1339 // Instance variables to hold the values for command options.
1340
1341 std::string stop;
1342 std::string notify;
1343 std::string pass;
1344 };
1345
1346
1347 CommandObjectProcessHandle (CommandInterpreter &interpreter) :
1348 CommandObject (interpreter,
1349 "process handle",
Caroline Ticee7471982010-10-14 21:31:13 +00001350 "Show or update what the process and debugger should do with various signals received from the OS.",
Caroline Tice23d6f272010-10-13 20:44:39 +00001351 NULL)
1352 {
Caroline Ticee7471982010-10-14 21:31:13 +00001353 SetHelpLong ("If no signals are specified, update them all. If no update option is specified, list the current values.\n");
Caroline Tice23d6f272010-10-13 20:44:39 +00001354 CommandArgumentEntry arg;
Caroline Tice3a62e6d2010-10-18 22:56:57 +00001355 CommandArgumentData signal_arg;
Caroline Tice23d6f272010-10-13 20:44:39 +00001356
Caroline Tice3a62e6d2010-10-18 22:56:57 +00001357 signal_arg.arg_type = eArgTypeUnixSignal;
1358 signal_arg.arg_repetition = eArgRepeatStar;
Caroline Tice23d6f272010-10-13 20:44:39 +00001359
Caroline Tice3a62e6d2010-10-18 22:56:57 +00001360 arg.push_back (signal_arg);
Caroline Tice23d6f272010-10-13 20:44:39 +00001361
1362 m_arguments.push_back (arg);
1363 }
1364
1365 ~CommandObjectProcessHandle ()
1366 {
1367 }
1368
1369 Options *
1370 GetOptions ()
1371 {
1372 return &m_options;
1373 }
1374
1375 bool
Caroline Ticee7471982010-10-14 21:31:13 +00001376 VerifyCommandOptionValue (const std::string &option, int &real_value)
Caroline Tice23d6f272010-10-13 20:44:39 +00001377 {
1378 bool okay = true;
1379
Caroline Ticee7471982010-10-14 21:31:13 +00001380 bool success = false;
1381 bool tmp_value = Args::StringToBoolean (option.c_str(), false, &success);
1382
1383 if (success && tmp_value)
1384 real_value = 1;
1385 else if (success && !tmp_value)
1386 real_value = 0;
Caroline Tice23d6f272010-10-13 20:44:39 +00001387 else
1388 {
1389 // If the value isn't 'true' or 'false', it had better be 0 or 1.
Caroline Ticee7471982010-10-14 21:31:13 +00001390 real_value = Args::StringToUInt32 (option.c_str(), 3);
1391 if (real_value != 0 && real_value != 1)
Caroline Tice23d6f272010-10-13 20:44:39 +00001392 okay = false;
1393 }
1394
1395 return okay;
1396 }
1397
Caroline Ticee7471982010-10-14 21:31:13 +00001398 void
1399 PrintSignalHeader (Stream &str)
1400 {
1401 str.Printf ("NAME PASS STOP NOTIFY\n");
1402 str.Printf ("========== ===== ===== ======\n");
1403 }
1404
1405 void
1406 PrintSignal (Stream &str, int32_t signo, const char *sig_name, UnixSignals &signals)
1407 {
1408 bool stop;
1409 bool suppress;
1410 bool notify;
1411
1412 str.Printf ("%-10s ", sig_name);
1413 if (signals.GetSignalInfo (signo, suppress, stop, notify))
1414 {
1415 bool pass = !suppress;
1416 str.Printf ("%s %s %s",
1417 (pass ? "true " : "false"),
1418 (stop ? "true " : "false"),
1419 (notify ? "true " : "false"));
1420 }
1421 str.Printf ("\n");
1422 }
1423
1424 void
1425 PrintSignalInformation (Stream &str, Args &signal_args, int num_valid_signals, UnixSignals &signals)
1426 {
1427 PrintSignalHeader (str);
1428
1429 if (num_valid_signals > 0)
1430 {
1431 size_t num_args = signal_args.GetArgumentCount();
1432 for (size_t i = 0; i < num_args; ++i)
1433 {
1434 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
1435 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
1436 PrintSignal (str, signo, signal_args.GetArgumentAtIndex (i), signals);
1437 }
1438 }
1439 else // Print info for ALL signals
1440 {
1441 int32_t signo = signals.GetFirstSignalNumber();
1442 while (signo != LLDB_INVALID_SIGNAL_NUMBER)
1443 {
1444 PrintSignal (str, signo, signals.GetSignalAsCString (signo), signals);
1445 signo = signals.GetNextSignalNumber (signo);
1446 }
1447 }
1448 }
1449
Caroline Tice23d6f272010-10-13 20:44:39 +00001450 bool
1451 Execute (Args &signal_args, CommandReturnObject &result)
1452 {
1453 TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
1454
1455 if (!target_sp)
1456 {
1457 result.AppendError ("No current target;"
1458 " cannot handle signals until you have a valid target and process.\n");
1459 result.SetStatus (eReturnStatusFailed);
1460 return false;
1461 }
1462
1463 ProcessSP process_sp = target_sp->GetProcessSP();
1464
1465 if (!process_sp)
1466 {
1467 result.AppendError ("No current process; cannot handle signals until you have a valid process.\n");
1468 result.SetStatus (eReturnStatusFailed);
1469 return false;
1470 }
1471
Caroline Tice23d6f272010-10-13 20:44:39 +00001472 int stop_action = -1; // -1 means leave the current setting alone
Caroline Ticee7471982010-10-14 21:31:13 +00001473 int pass_action = -1; // -1 means leave the current setting alone
Caroline Tice23d6f272010-10-13 20:44:39 +00001474 int notify_action = -1; // -1 means leave the current setting alone
1475
1476 if (! m_options.stop.empty()
Caroline Ticee7471982010-10-14 21:31:13 +00001477 && ! VerifyCommandOptionValue (m_options.stop, stop_action))
Caroline Tice23d6f272010-10-13 20:44:39 +00001478 {
1479 result.AppendError ("Invalid argument for command option --stop; must be true or false.\n");
1480 result.SetStatus (eReturnStatusFailed);
1481 return false;
1482 }
1483
1484 if (! m_options.notify.empty()
Caroline Ticee7471982010-10-14 21:31:13 +00001485 && ! VerifyCommandOptionValue (m_options.notify, notify_action))
Caroline Tice23d6f272010-10-13 20:44:39 +00001486 {
1487 result.AppendError ("Invalid argument for command option --notify; must be true or false.\n");
1488 result.SetStatus (eReturnStatusFailed);
1489 return false;
1490 }
1491
1492 if (! m_options.pass.empty()
Caroline Ticee7471982010-10-14 21:31:13 +00001493 && ! VerifyCommandOptionValue (m_options.pass, pass_action))
Caroline Tice23d6f272010-10-13 20:44:39 +00001494 {
1495 result.AppendError ("Invalid argument for command option --pass; must be true or false.\n");
1496 result.SetStatus (eReturnStatusFailed);
1497 return false;
1498 }
1499
1500 size_t num_args = signal_args.GetArgumentCount();
1501 UnixSignals &signals = process_sp->GetUnixSignals();
1502 int num_signals_set = 0;
1503
Caroline Ticee7471982010-10-14 21:31:13 +00001504 if (num_args > 0)
Caroline Tice23d6f272010-10-13 20:44:39 +00001505 {
Caroline Ticee7471982010-10-14 21:31:13 +00001506 for (size_t i = 0; i < num_args; ++i)
Caroline Tice23d6f272010-10-13 20:44:39 +00001507 {
Caroline Ticee7471982010-10-14 21:31:13 +00001508 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
1509 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
Caroline Tice23d6f272010-10-13 20:44:39 +00001510 {
Caroline Ticee7471982010-10-14 21:31:13 +00001511 // Casting the actions as bools here should be okay, because VerifyCommandOptionValue guarantees
1512 // the value is either 0 or 1.
1513 if (stop_action != -1)
1514 signals.SetShouldStop (signo, (bool) stop_action);
1515 if (pass_action != -1)
1516 {
1517 bool suppress = ! ((bool) pass_action);
1518 signals.SetShouldSuppress (signo, suppress);
1519 }
1520 if (notify_action != -1)
1521 signals.SetShouldNotify (signo, (bool) notify_action);
1522 ++num_signals_set;
Caroline Tice23d6f272010-10-13 20:44:39 +00001523 }
Caroline Ticee7471982010-10-14 21:31:13 +00001524 else
1525 {
1526 result.AppendErrorWithFormat ("Invalid signal name '%s'\n", signal_args.GetArgumentAtIndex (i));
1527 }
Caroline Tice23d6f272010-10-13 20:44:39 +00001528 }
1529 }
Caroline Ticee7471982010-10-14 21:31:13 +00001530 else
1531 {
1532 // No signal specified, if any command options were specified, update ALL signals.
1533 if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1))
1534 {
1535 if (m_interpreter.Confirm ("Do you really want to update all the signals?", false))
1536 {
1537 int32_t signo = signals.GetFirstSignalNumber();
1538 while (signo != LLDB_INVALID_SIGNAL_NUMBER)
1539 {
1540 if (notify_action != -1)
1541 signals.SetShouldNotify (signo, (bool) notify_action);
1542 if (stop_action != -1)
1543 signals.SetShouldStop (signo, (bool) stop_action);
1544 if (pass_action != -1)
1545 {
1546 bool suppress = ! ((bool) pass_action);
1547 signals.SetShouldSuppress (signo, suppress);
1548 }
1549 signo = signals.GetNextSignalNumber (signo);
1550 }
1551 }
1552 }
1553 }
1554
1555 PrintSignalInformation (result.GetOutputStream(), signal_args, num_signals_set, signals);
Caroline Tice23d6f272010-10-13 20:44:39 +00001556
1557 if (num_signals_set > 0)
1558 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1559 else
1560 result.SetStatus (eReturnStatusFailed);
1561
1562 return result.Succeeded();
1563 }
1564
1565protected:
1566
1567 CommandOptions m_options;
1568};
1569
1570lldb::OptionDefinition
1571CommandObjectProcessHandle::CommandOptions::g_option_table[] =
1572{
1573{ LLDB_OPT_SET_1, false, "stop", 's', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the process should be stopped if the signal is received." },
1574{ LLDB_OPT_SET_1, false, "notify", 'n', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the debugger should notify the user if the signal is received." },
1575{ LLDB_OPT_SET_1, false, "pass", 'p', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." },
1576{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1577};
1578
1579//-------------------------------------------------------------------------
Chris Lattner24943d22010-06-08 16:52:24 +00001580// CommandObjectMultiwordProcess
1581//-------------------------------------------------------------------------
1582
Greg Clayton63094e02010-06-23 01:19:29 +00001583CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001584 CommandObjectMultiword (interpreter,
1585 "process",
1586 "A set of commands for operating on a process.",
1587 "process <subcommand> [<subcommand-options>]")
Chris Lattner24943d22010-06-08 16:52:24 +00001588{
Greg Clayton238c0a12010-09-18 01:14:36 +00001589 LoadSubCommand ("attach", CommandObjectSP (new CommandObjectProcessAttach (interpreter)));
1590 LoadSubCommand ("launch", CommandObjectSP (new CommandObjectProcessLaunch (interpreter)));
1591 LoadSubCommand ("continue", CommandObjectSP (new CommandObjectProcessContinue (interpreter)));
1592 LoadSubCommand ("detach", CommandObjectSP (new CommandObjectProcessDetach (interpreter)));
Greg Clayton0baa3942010-11-04 01:54:29 +00001593 LoadSubCommand ("load", CommandObjectSP (new CommandObjectProcessLoad (interpreter)));
1594 LoadSubCommand ("unload", CommandObjectSP (new CommandObjectProcessUnload (interpreter)));
Greg Clayton238c0a12010-09-18 01:14:36 +00001595 LoadSubCommand ("signal", CommandObjectSP (new CommandObjectProcessSignal (interpreter)));
Caroline Tice23d6f272010-10-13 20:44:39 +00001596 LoadSubCommand ("handle", CommandObjectSP (new CommandObjectProcessHandle (interpreter)));
Greg Clayton238c0a12010-09-18 01:14:36 +00001597 LoadSubCommand ("status", CommandObjectSP (new CommandObjectProcessStatus (interpreter)));
1598 LoadSubCommand ("interrupt", CommandObjectSP (new CommandObjectProcessInterrupt (interpreter)));
1599 LoadSubCommand ("kill", CommandObjectSP (new CommandObjectProcessKill (interpreter)));
Chris Lattner24943d22010-06-08 16:52:24 +00001600}
1601
1602CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess ()
1603{
1604}
1605