blob: 42bc4af3bb2022ab4c88dde760cf5ac8ac117751 [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//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +000032#pragma mark CommandObjectProjectLaunch
Chris Lattner24943d22010-06-08 16:52:24 +000033class 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 {
Greg Claytonde915be2011-01-23 05:56:20 +000060 case 's': stop_at_entry = true; break;
61 case 'e': stderr_path.assign (option_arg); break;
62 case 'i': stdin_path.assign (option_arg); break;
63 case 'o': stdout_path.assign (option_arg); break;
64 case 'p': plugin_name.assign (option_arg); break;
65 case 'n': no_stdio = true; break;
66 case 'w': working_dir.assign (option_arg); break;
Greg Claytonbb0c91f2010-10-19 23:16:00 +000067 case 't':
68 if (option_arg && option_arg[0])
69 tty_name.assign (option_arg);
70 in_new_tty = true;
71 break;
Chris Lattner24943d22010-06-08 16:52:24 +000072 default:
73 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
74 break;
75
76 }
77 return error;
78 }
79
80 void
81 ResetOptionValues ()
82 {
83 Options::ResetOptionValues();
84 stop_at_entry = false;
Greg Claytonc1d37752010-10-18 01:45:30 +000085 in_new_tty = false;
Greg Claytonbb0c91f2010-10-19 23:16:00 +000086 tty_name.clear();
Chris Lattner24943d22010-06-08 16:52:24 +000087 stdin_path.clear();
88 stdout_path.clear();
89 stderr_path.clear();
90 plugin_name.clear();
Greg Claytonde915be2011-01-23 05:56:20 +000091 working_dir.clear();
Caroline Ticebd666012010-12-03 18:46:09 +000092 no_stdio = false;
Chris Lattner24943d22010-06-08 16:52:24 +000093 }
94
95 const lldb::OptionDefinition*
96 GetDefinitions ()
97 {
98 return g_option_table;
99 }
100
101 // Options table: Required for subclasses of Options.
102
103 static lldb::OptionDefinition g_option_table[];
104
105 // Instance variables to hold the values for command options.
106
107 bool stop_at_entry;
Greg Claytonc1d37752010-10-18 01:45:30 +0000108 bool in_new_tty;
Caroline Ticebd666012010-12-03 18:46:09 +0000109 bool no_stdio;
Greg Claytonbb0c91f2010-10-19 23:16:00 +0000110 std::string tty_name;
Chris Lattner24943d22010-06-08 16:52:24 +0000111 std::string stderr_path;
112 std::string stdin_path;
113 std::string stdout_path;
114 std::string plugin_name;
Greg Claytonde915be2011-01-23 05:56:20 +0000115 std::string working_dir;
Chris Lattner24943d22010-06-08 16:52:24 +0000116
117 };
118
Greg Clayton238c0a12010-09-18 01:14:36 +0000119 CommandObjectProcessLaunch (CommandInterpreter &interpreter) :
120 CommandObject (interpreter,
121 "process launch",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000122 "Launch the executable in the debugger.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000123 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000124 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000125 CommandArgumentEntry arg;
126 CommandArgumentData run_args_arg;
127
128 // Define the first (and only) variant of this arg.
129 run_args_arg.arg_type = eArgTypeRunArgs;
130 run_args_arg.arg_repetition = eArgRepeatOptional;
131
132 // There is only one variant this argument could be; put it into the argument entry.
133 arg.push_back (run_args_arg);
134
135 // Push the data for the first argument into the m_arguments vector.
136 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000137 }
138
139
140 ~CommandObjectProcessLaunch ()
141 {
142 }
143
144 Options *
145 GetOptions ()
146 {
147 return &m_options;
148 }
149
150 bool
Greg Claytond8c62532010-10-07 04:19:01 +0000151 Execute (Args& launch_args, CommandReturnObject &result)
Chris Lattner24943d22010-06-08 16:52:24 +0000152 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000153 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000154
155 if (target == NULL)
156 {
157 result.AppendError ("invalid target, set executable file using 'file' command");
158 result.SetStatus (eReturnStatusFailed);
159 return false;
160 }
161
162 // If our listener is NULL, users aren't allows to launch
Chris Lattner24943d22010-06-08 16:52:24 +0000163 char filename[PATH_MAX];
Greg Claytonc1d37752010-10-18 01:45:30 +0000164 const Module *exe_module = target->GetExecutableModule().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000165 exe_module->GetFileSpec().GetPath(filename, sizeof(filename));
166
Greg Clayton238c0a12010-09-18 01:14:36 +0000167 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
168 if (process && process->IsAlive())
Jim Ingham22dc9722010-12-09 18:58:16 +0000169 {
170 if (!m_interpreter.Confirm ("There is a running process, kill it and restart?", true))
171 {
172 result.AppendErrorWithFormat ("Process %u is currently being debugged, restart cancelled.\n",
173 process->GetID());
174 result.SetStatus (eReturnStatusFailed);
175 return false;
176 }
177 else
178 {
179 Error error (process->Destroy());
180 if (error.Success())
181 {
182 result.SetStatus (eReturnStatusSuccessFinishResult);
183 }
184 else
185 {
186 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString());
187 result.SetStatus (eReturnStatusFailed);
188 }
189 }
Chris Lattner24943d22010-06-08 16:52:24 +0000190 }
Jim Ingham22dc9722010-12-09 18:58:16 +0000191
Chris Lattner24943d22010-06-08 16:52:24 +0000192 const char *plugin_name;
193 if (!m_options.plugin_name.empty())
194 plugin_name = m_options.plugin_name.c_str();
195 else
196 plugin_name = NULL;
197
Greg Clayton238c0a12010-09-18 01:14:36 +0000198 process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
Chris Lattner24943d22010-06-08 16:52:24 +0000199
Greg Clayton238c0a12010-09-18 01:14:36 +0000200 if (process == NULL)
Caroline Tice6e4c5ce2010-09-04 00:03:46 +0000201 {
Caroline Tice734b4832010-10-15 21:52:38 +0000202 result.AppendErrorWithFormat ("Failed to find a process plugin for executable.\n");
Chris Lattner24943d22010-06-08 16:52:24 +0000203 result.SetStatus (eReturnStatusFailed);
204 return false;
205 }
206
Greg Clayton238c0a12010-09-18 01:14:36 +0000207 // If no launch args were given on the command line, then use any that
208 // might have been set using the "run-args" set variable.
209 if (launch_args.GetArgumentCount() == 0)
210 {
211 if (process->GetRunArguments().GetArgumentCount() > 0)
212 launch_args = process->GetRunArguments();
213 }
214
Greg Claytonc1d37752010-10-18 01:45:30 +0000215 if (m_options.in_new_tty)
216 {
217 char exec_file_path[PATH_MAX];
218 if (exe_module->GetFileSpec().GetPath(exec_file_path, sizeof(exec_file_path)))
219 {
220 launch_args.InsertArgumentAtIndex(0, exec_file_path);
221 }
222 else
223 {
224 result.AppendError("invalid executable");
225 result.SetStatus (eReturnStatusFailed);
226 return false;
227 }
228 }
229
Greg Clayton238c0a12010-09-18 01:14:36 +0000230 Args environment;
231
232 process->GetEnvironmentAsArgs (environment);
233
234 uint32_t launch_flags = eLaunchFlagNone;
235
236 if (process->GetDisableASLR())
237 launch_flags |= eLaunchFlagDisableASLR;
Greg Claytonc1d37752010-10-18 01:45:30 +0000238
Caroline Ticebd666012010-12-03 18:46:09 +0000239 if (m_options.no_stdio)
240 launch_flags |= eLaunchFlagDisableSTDIO;
241 else if (!m_options.in_new_tty
242 && m_options.stdin_path.empty()
243 && m_options.stdout_path.empty()
244 && m_options.stderr_path.empty())
245 {
246 // Only use the settings value if the user hasn't specified any options that would override it.
247 if (process->GetDisableSTDIO())
248 launch_flags |= eLaunchFlagDisableSTDIO;
249 }
250
Greg Claytonc1d37752010-10-18 01:45:30 +0000251 const char **inferior_argv = launch_args.GetArgumentCount() ? launch_args.GetConstArgumentVector() : NULL;
252 const char **inferior_envp = environment.GetArgumentCount() ? environment.GetConstArgumentVector() : NULL;
Greg Clayton238c0a12010-09-18 01:14:36 +0000253
Greg Claytonc1d37752010-10-18 01:45:30 +0000254 Error error;
Greg Claytonde915be2011-01-23 05:56:20 +0000255 const char *working_dir = NULL;
256 if (!m_options.working_dir.empty())
257 working_dir = m_options.working_dir.c_str();
Greg Clayton238c0a12010-09-18 01:14:36 +0000258
Greg Claytonc1d37752010-10-18 01:45:30 +0000259 if (m_options.in_new_tty)
Greg Clayton238c0a12010-09-18 01:14:36 +0000260 {
Greg Claytonc1d37752010-10-18 01:45:30 +0000261
Greg Claytonbb0c91f2010-10-19 23:16:00 +0000262 lldb::pid_t pid = Host::LaunchInNewTerminal (m_options.tty_name.c_str(),
263 inferior_argv,
Greg Clayton36f63a92010-10-19 03:25:40 +0000264 inferior_envp,
Greg Claytonde915be2011-01-23 05:56:20 +0000265 working_dir,
Greg Clayton36f63a92010-10-19 03:25:40 +0000266 &exe_module->GetArchitecture(),
267 true,
268 process->GetDisableASLR());
Greg Claytonc1d37752010-10-18 01:45:30 +0000269
Greg Clayton36f63a92010-10-19 03:25:40 +0000270 if (pid != LLDB_INVALID_PROCESS_ID)
271 error = process->Attach (pid);
Greg Clayton238c0a12010-09-18 01:14:36 +0000272 }
273 else
274 {
Greg Claytonc1d37752010-10-18 01:45:30 +0000275 const char * stdin_path = NULL;
276 const char * stdout_path = NULL;
277 const char * stderr_path = NULL;
278
279 // Were any standard input/output/error paths given on the command line?
280 if (m_options.stdin_path.empty() &&
281 m_options.stdout_path.empty() &&
282 m_options.stderr_path.empty())
283 {
284 // No standard file handles were given on the command line, check
285 // with the process object in case they were give using "set settings"
286 stdin_path = process->GetStandardInputPath();
287 stdout_path = process->GetStandardOutputPath();
288 stderr_path = process->GetStandardErrorPath();
289 }
290 else
291 {
292 stdin_path = m_options.stdin_path.empty() ? NULL : m_options.stdin_path.c_str();
293 stdout_path = m_options.stdout_path.empty() ? NULL : m_options.stdout_path.c_str();
294 stderr_path = m_options.stderr_path.empty() ? NULL : m_options.stderr_path.c_str();
295 }
296
Greg Claytonc1d37752010-10-18 01:45:30 +0000297 error = process->Launch (inferior_argv,
298 inferior_envp,
299 launch_flags,
300 stdin_path,
301 stdout_path,
Greg Claytonde915be2011-01-23 05:56:20 +0000302 stderr_path,
303 working_dir);
Greg Clayton238c0a12010-09-18 01:14:36 +0000304 }
Greg Clayton238c0a12010-09-18 01:14:36 +0000305
306 if (error.Success())
307 {
Greg Claytonc1d37752010-10-18 01:45:30 +0000308 const char *archname = exe_module->GetArchitecture().AsCString();
309
310 result.AppendMessageWithFormat ("Process %i launched: '%s' (%s)\n", process->GetID(), filename, archname);
Greg Claytond8c62532010-10-07 04:19:01 +0000311 result.SetDidChangeProcessState (true);
Greg Clayton238c0a12010-09-18 01:14:36 +0000312 if (m_options.stop_at_entry == false)
313 {
Greg Claytond8c62532010-10-07 04:19:01 +0000314 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
Greg Clayton238c0a12010-09-18 01:14:36 +0000315 StateType state = process->WaitForProcessToStop (NULL);
316
317 if (state == eStateStopped)
318 {
Greg Claytond8c62532010-10-07 04:19:01 +0000319 error = process->Resume();
320 if (error.Success())
321 {
322 bool synchronous_execution = m_interpreter.GetSynchronous ();
323 if (synchronous_execution)
324 {
325 state = process->WaitForProcessToStop (NULL);
326 result.SetDidChangeProcessState (true);
327 result.SetStatus (eReturnStatusSuccessFinishResult);
328 }
329 else
330 {
331 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
332 }
333 }
Greg Clayton238c0a12010-09-18 01:14:36 +0000334 }
335 }
336 }
337
Chris Lattner24943d22010-06-08 16:52:24 +0000338 return result.Succeeded();
339 }
340
Jim Ingham767af882010-07-07 03:36:20 +0000341 virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
342 {
343 // No repeat for "process launch"...
344 return "";
345 }
346
Chris Lattner24943d22010-06-08 16:52:24 +0000347protected:
348
349 CommandOptions m_options;
350};
351
352
Greg Claytonc1d37752010-10-18 01:45:30 +0000353#define SET1 LLDB_OPT_SET_1
354#define SET2 LLDB_OPT_SET_2
Caroline Ticebd666012010-12-03 18:46:09 +0000355#define SET3 LLDB_OPT_SET_3
Greg Claytonc1d37752010-10-18 01:45:30 +0000356
Chris Lattner24943d22010-06-08 16:52:24 +0000357lldb::OptionDefinition
358CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
359{
Caroline Ticebd666012010-12-03 18:46:09 +0000360{ 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."},
361{ SET1 , false, "stdin", 'i', required_argument, NULL, 0, eArgTypePath, "Redirect stdin for the process to <path>."},
362{ SET1 , false, "stdout", 'o', required_argument, NULL, 0, eArgTypePath, "Redirect stdout for the process to <path>."},
363{ SET1 , false, "stderr", 'e', required_argument, NULL, 0, eArgTypePath, "Redirect stderr for the process to <path>."},
364{ SET1 | SET2 | SET3, false, "plugin", 'p', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
365{ 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."},
366{ SET3, false, "no-stdio", 'n', no_argument, NULL, 0, eArgTypeNone, "Do not set up for terminal I/O to go to running process."},
Greg Claytonde915be2011-01-23 05:56:20 +0000367{ SET1 | SET2 | SET3, false, "working-dir", 'w', required_argument, NULL, 0, eArgTypePath, "Set the current working directory to <path> when running the inferior."},
Caroline Ticebd666012010-12-03 18:46:09 +0000368{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +0000369};
370
Greg Claytonc1d37752010-10-18 01:45:30 +0000371#undef SET1
372#undef SET2
Caroline Ticebd666012010-12-03 18:46:09 +0000373#undef SET3
Chris Lattner24943d22010-06-08 16:52:24 +0000374
375//-------------------------------------------------------------------------
376// CommandObjectProcessAttach
377//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +0000378#pragma mark CommandObjectProcessAttach
Chris Lattner24943d22010-06-08 16:52:24 +0000379class CommandObjectProcessAttach : public CommandObject
380{
381public:
382
Chris Lattner24943d22010-06-08 16:52:24 +0000383 class CommandOptions : public Options
384 {
385 public:
386
387 CommandOptions () :
388 Options()
389 {
390 // Keep default values of all options in one place: ResetOptionValues ()
391 ResetOptionValues ();
392 }
393
394 ~CommandOptions ()
395 {
396 }
397
398 Error
399 SetOptionValue (int option_idx, const char *option_arg)
400 {
401 Error error;
402 char short_option = (char) m_getopt_table[option_idx].val;
403 bool success = false;
404 switch (short_option)
405 {
406 case 'p':
407 pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success);
408 if (!success || pid == LLDB_INVALID_PROCESS_ID)
409 {
410 error.SetErrorStringWithFormat("Invalid process ID '%s'.\n", option_arg);
411 }
412 break;
413
414 case 'P':
415 plugin_name = option_arg;
416 break;
417
418 case 'n':
419 name.assign(option_arg);
420 break;
421
422 case 'w':
423 waitfor = true;
424 break;
425
426 default:
427 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
428 break;
429 }
430 return error;
431 }
432
433 void
434 ResetOptionValues ()
435 {
436 Options::ResetOptionValues();
437 pid = LLDB_INVALID_PROCESS_ID;
438 name.clear();
439 waitfor = false;
440 }
441
442 const lldb::OptionDefinition*
443 GetDefinitions ()
444 {
445 return g_option_table;
446 }
447
Jim Ingham7508e732010-08-09 23:31:02 +0000448 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000449 HandleOptionArgumentCompletion (CommandInterpreter &interpeter,
Jim Ingham7508e732010-08-09 23:31:02 +0000450 Args &input,
451 int cursor_index,
452 int char_pos,
453 OptionElementVector &opt_element_vector,
454 int opt_element_index,
455 int match_start_point,
456 int max_return_elements,
457 bool &word_complete,
458 StringList &matches)
459 {
460 int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
461 int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
462
463 // We are only completing the name option for now...
464
465 const lldb::OptionDefinition *opt_defs = GetDefinitions();
466 if (opt_defs[opt_defs_index].short_option == 'n')
467 {
468 // Are we in the name?
469
470 // Look to see if there is a -P argument provided, and if so use that plugin, otherwise
471 // use the default plugin.
Greg Clayton238c0a12010-09-18 01:14:36 +0000472 Process *process = interpeter.GetDebugger().GetExecutionContext().process;
Jim Ingham7508e732010-08-09 23:31:02 +0000473 bool need_to_delete_process = false;
474
475 const char *partial_name = NULL;
476 partial_name = input.GetArgumentAtIndex(opt_arg_pos);
477
478 if (process && process->IsAlive())
479 return true;
480
Greg Clayton238c0a12010-09-18 01:14:36 +0000481 Target *target = interpeter.GetDebugger().GetSelectedTarget().get();
Jim Ingham7508e732010-08-09 23:31:02 +0000482 if (target == NULL)
483 {
484 // No target has been set yet, for now do host completion. Otherwise I don't know how we would
485 // figure out what the right target to use is...
486 std::vector<lldb::pid_t> pids;
487 Host::ListProcessesMatchingName (partial_name, matches, pids);
488 return true;
489 }
490 if (!process)
491 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000492 process = target->CreateProcess (interpeter.GetDebugger().GetListener(), partial_name).get();
Jim Ingham7508e732010-08-09 23:31:02 +0000493 need_to_delete_process = true;
494 }
495
496 if (process)
497 {
498 matches.Clear();
499 std::vector<lldb::pid_t> pids;
500 process->ListProcessesMatchingName (NULL, matches, pids);
501 if (need_to_delete_process)
502 target->DeleteCurrentProcess();
503 return true;
504 }
505 }
506
507 return false;
508 }
509
Chris Lattner24943d22010-06-08 16:52:24 +0000510 // Options table: Required for subclasses of Options.
511
512 static lldb::OptionDefinition g_option_table[];
513
514 // Instance variables to hold the values for command options.
515
516 lldb::pid_t pid;
517 std::string plugin_name;
518 std::string name;
519 bool waitfor;
520 };
521
Greg Clayton238c0a12010-09-18 01:14:36 +0000522 CommandObjectProcessAttach (CommandInterpreter &interpreter) :
523 CommandObject (interpreter,
524 "process attach",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000525 "Attach to a process.",
Jim Ingham7508e732010-08-09 23:31:02 +0000526 "process attach <cmd-options>")
527 {
Jim Ingham7508e732010-08-09 23:31:02 +0000528 }
529
530 ~CommandObjectProcessAttach ()
531 {
532 }
533
534 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000535 Execute (Args& command,
Jim Ingham7508e732010-08-09 23:31:02 +0000536 CommandReturnObject &result)
537 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000538 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Jim Inghamc2dc7c82011-01-29 01:49:25 +0000539 bool synchronous_execution = m_interpreter.GetSynchronous ();
540
Greg Clayton238c0a12010-09-18 01:14:36 +0000541 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Jim Ingham7508e732010-08-09 23:31:02 +0000542 if (process)
543 {
544 if (process->IsAlive())
545 {
546 result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before attaching.\n",
547 process->GetID());
548 result.SetStatus (eReturnStatusFailed);
549 return false;
550 }
551 }
552
553 if (target == NULL)
554 {
555 // If there isn't a current target create one.
556 TargetSP new_target_sp;
557 FileSpec emptyFileSpec;
558 ArchSpec emptyArchSpec;
559 Error error;
560
Greg Clayton238c0a12010-09-18 01:14:36 +0000561 error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(),
562 emptyFileSpec,
563 emptyArchSpec,
564 NULL,
565 false,
566 new_target_sp);
Jim Ingham7508e732010-08-09 23:31:02 +0000567 target = new_target_sp.get();
568 if (target == NULL || error.Fail())
569 {
570 result.AppendError(error.AsCString("Error creating empty target"));
571 return false;
572 }
Greg Clayton238c0a12010-09-18 01:14:36 +0000573 m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target);
Jim Ingham7508e732010-08-09 23:31:02 +0000574 }
575
576 // Record the old executable module, we want to issue a warning if the process of attaching changed the
577 // current executable (like somebody said "file foo" then attached to a PID whose executable was bar.)
578
579 ModuleSP old_exec_module_sp = target->GetExecutableModule();
580 ArchSpec old_arch_spec = target->GetArchitecture();
581
582 if (command.GetArgumentCount())
583 {
584 result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
585 result.SetStatus (eReturnStatusFailed);
586 }
587 else
588 {
589 const char *plugin_name = NULL;
590
591 if (!m_options.plugin_name.empty())
592 plugin_name = m_options.plugin_name.c_str();
593
Greg Clayton238c0a12010-09-18 01:14:36 +0000594 process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
Jim Ingham7508e732010-08-09 23:31:02 +0000595
596 if (process)
597 {
598 Error error;
599 int attach_pid = m_options.pid;
600
Jim Ingham4805a1c2010-09-15 01:34:14 +0000601 const char *wait_name = NULL;
602
603 if (m_options.name.empty())
604 {
605 if (old_exec_module_sp)
606 {
607 wait_name = old_exec_module_sp->GetFileSpec().GetFilename().AsCString();
608 }
609 }
610 else
611 {
612 wait_name = m_options.name.c_str();
613 }
614
Jim Ingham7508e732010-08-09 23:31:02 +0000615 // If we are waiting for a process with this name to show up, do that first.
616 if (m_options.waitfor)
617 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000618
619 if (wait_name == NULL)
Jim Ingham7508e732010-08-09 23:31:02 +0000620 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000621 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 +0000622 result.SetStatus (eReturnStatusFailed);
623 return false;
624 }
Jim Ingham4805a1c2010-09-15 01:34:14 +0000625
Greg Clayton238c0a12010-09-18 01:14:36 +0000626 m_interpreter.GetDebugger().GetOutputStream().Printf("Waiting to attach to a process named \"%s\".\n", wait_name);
Jim Ingham4805a1c2010-09-15 01:34:14 +0000627 error = process->Attach (wait_name, m_options.waitfor);
628 if (error.Success())
629 {
630 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
631 }
Jim Ingham7508e732010-08-09 23:31:02 +0000632 else
633 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000634 result.AppendErrorWithFormat ("Waiting for a process to launch named '%s': %s\n",
635 wait_name,
636 error.AsCString());
637 result.SetStatus (eReturnStatusFailed);
638 return false;
Jim Ingham7508e732010-08-09 23:31:02 +0000639 }
Jim Inghamc2dc7c82011-01-29 01:49:25 +0000640 // If we're synchronous, wait for the stopped event and report that.
641 // Otherwise just return.
642 // FIXME: in the async case it will now be possible to get to the command
643 // interpreter with a state eStateAttaching. Make sure we handle that correctly.
644 if (synchronous_execution)
645 {
646 StateType state = process->WaitForProcessToStop (NULL);
647
648 result.SetDidChangeProcessState (true);
649 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
650 result.SetStatus (eReturnStatusSuccessFinishNoResult);
651 }
652 else
653 {
654 result.SetDidChangeProcessState (true);
655 result.AppendMessageWithFormat ("Starting to attach to process.");
656 result.SetStatus (eReturnStatusSuccessFinishNoResult);
657 }
Jim Ingham7508e732010-08-09 23:31:02 +0000658 }
659 else
660 {
661 // If the process was specified by name look it up, so we can warn if there are multiple
662 // processes with this pid.
663
Jim Ingham4805a1c2010-09-15 01:34:14 +0000664 if (attach_pid == LLDB_INVALID_PROCESS_ID && wait_name != NULL)
Jim Ingham7508e732010-08-09 23:31:02 +0000665 {
666 std::vector<lldb::pid_t> pids;
667 StringList matches;
668
Jim Ingham4805a1c2010-09-15 01:34:14 +0000669 process->ListProcessesMatchingName(wait_name, matches, pids);
Jim Ingham7508e732010-08-09 23:31:02 +0000670 if (matches.GetSize() > 1)
671 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000672 result.AppendErrorWithFormat("More than one process named %s\n", wait_name);
Jim Ingham7508e732010-08-09 23:31:02 +0000673 result.SetStatus (eReturnStatusFailed);
674 return false;
675 }
676 else if (matches.GetSize() == 0)
677 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000678 result.AppendErrorWithFormat("Could not find a process named %s\n", wait_name);
Jim Ingham7508e732010-08-09 23:31:02 +0000679 result.SetStatus (eReturnStatusFailed);
680 return false;
681 }
682 else
683 {
684 attach_pid = pids[0];
685 }
686
687 }
688
689 if (attach_pid != LLDB_INVALID_PROCESS_ID)
690 {
691 error = process->Attach (attach_pid);
692 if (error.Success())
693 {
694 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
695 }
696 else
697 {
698 result.AppendErrorWithFormat ("Attaching to process %i failed: %s.\n",
699 attach_pid,
700 error.AsCString());
701 result.SetStatus (eReturnStatusFailed);
702 }
Jim Inghamc2dc7c82011-01-29 01:49:25 +0000703 // See comment for synchronous_execution above.
704 if (synchronous_execution)
705 {
706 StateType state = process->WaitForProcessToStop (NULL);
707
708 result.SetDidChangeProcessState (true);
709 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
710 result.SetStatus (eReturnStatusSuccessFinishNoResult);
711 }
712 else
713 {
714 result.SetDidChangeProcessState (true);
715 result.AppendMessageWithFormat ("Starting to attach to process.");
716 result.SetStatus (eReturnStatusSuccessFinishNoResult);
717 }
Jim Ingham7508e732010-08-09 23:31:02 +0000718 }
719 else
720 {
721 result.AppendErrorWithFormat ("No PID specified for attach\n",
722 attach_pid,
723 error.AsCString());
724 result.SetStatus (eReturnStatusFailed);
725
726 }
727 }
728 }
729 }
730
731 if (result.Succeeded())
732 {
733 // Okay, we're done. Last step is to warn if the executable module has changed:
734 if (!old_exec_module_sp)
735 {
736 char new_path[PATH_MAX + 1];
737 target->GetExecutableModule()->GetFileSpec().GetPath(new_path, PATH_MAX);
738
739 result.AppendMessageWithFormat("Executable module set to \"%s\".\n",
740 new_path);
741 }
742 else if (old_exec_module_sp->GetFileSpec() != target->GetExecutableModule()->GetFileSpec())
743 {
744 char old_path[PATH_MAX + 1];
745 char new_path[PATH_MAX + 1];
746
747 old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX);
748 target->GetExecutableModule()->GetFileSpec().GetPath (new_path, PATH_MAX);
749
750 result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n",
751 old_path, new_path);
752 }
753
754 if (!old_arch_spec.IsValid())
755 {
756 result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().AsCString());
757 }
758 else if (old_arch_spec != target->GetArchitecture())
759 {
760 result.AppendWarningWithFormat("Architecture changed from %s to %s.\n",
761 old_arch_spec.AsCString(), target->GetArchitecture().AsCString());
762 }
763 }
764 return result.Succeeded();
765 }
766
767 Options *
768 GetOptions ()
769 {
770 return &m_options;
771 }
772
Chris Lattner24943d22010-06-08 16:52:24 +0000773protected:
774
775 CommandOptions m_options;
776};
777
778
779lldb::OptionDefinition
780CommandObjectProcessAttach::CommandOptions::g_option_table[] =
781{
Caroline Tice4d6675c2010-10-01 19:59:14 +0000782{ LLDB_OPT_SET_ALL, false, "plugin", 'P', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
783{ LLDB_OPT_SET_1, false, "pid", 'p', required_argument, NULL, 0, eArgTypePid, "The process ID of an existing process to attach to."},
784{ LLDB_OPT_SET_2, false, "name", 'n', required_argument, NULL, 0, eArgTypeProcessName, "The name of the process to attach to."},
785{ LLDB_OPT_SET_2, false, "waitfor",'w', no_argument, NULL, 0, eArgTypeNone, "Wait for the the process with <process-name> to launch."},
786{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +0000787};
788
789//-------------------------------------------------------------------------
790// CommandObjectProcessContinue
791//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +0000792#pragma mark CommandObjectProcessContinue
Chris Lattner24943d22010-06-08 16:52:24 +0000793
794class CommandObjectProcessContinue : public CommandObject
795{
796public:
797
Greg Clayton238c0a12010-09-18 01:14:36 +0000798 CommandObjectProcessContinue (CommandInterpreter &interpreter) :
799 CommandObject (interpreter,
800 "process continue",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000801 "Continue execution of all threads in the current process.",
Chris Lattner24943d22010-06-08 16:52:24 +0000802 "process continue",
803 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
804 {
805 }
806
807
808 ~CommandObjectProcessContinue ()
809 {
810 }
811
812 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000813 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000814 CommandReturnObject &result)
815 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000816 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
817 bool synchronous_execution = m_interpreter.GetSynchronous ();
Chris Lattner24943d22010-06-08 16:52:24 +0000818
819 if (process == NULL)
820 {
821 result.AppendError ("no process to continue");
822 result.SetStatus (eReturnStatusFailed);
823 return false;
824 }
825
826 StateType state = process->GetState();
827 if (state == eStateStopped)
828 {
829 if (command.GetArgumentCount() != 0)
830 {
831 result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str());
832 result.SetStatus (eReturnStatusFailed);
833 return false;
834 }
835
836 const uint32_t num_threads = process->GetThreadList().GetSize();
837
838 // Set the actions that the threads should each take when resuming
839 for (uint32_t idx=0; idx<num_threads; ++idx)
840 {
841 process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning);
842 }
843
844 Error error(process->Resume());
845 if (error.Success())
846 {
Greg Claytonc1d37752010-10-18 01:45:30 +0000847 result.AppendMessageWithFormat ("Process %i resuming\n", process->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000848 if (synchronous_execution)
849 {
Greg Claytonbef15832010-07-14 00:18:15 +0000850 state = process->WaitForProcessToStop (NULL);
Chris Lattner24943d22010-06-08 16:52:24 +0000851
852 result.SetDidChangeProcessState (true);
853 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
854 result.SetStatus (eReturnStatusSuccessFinishNoResult);
855 }
856 else
857 {
858 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
859 }
860 }
861 else
862 {
863 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
864 result.SetStatus (eReturnStatusFailed);
865 }
866 }
867 else
868 {
869 result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
870 StateAsCString(state));
871 result.SetStatus (eReturnStatusFailed);
872 }
873 return result.Succeeded();
874 }
875};
876
877//-------------------------------------------------------------------------
878// CommandObjectProcessDetach
879//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +0000880#pragma mark CommandObjectProcessDetach
Chris Lattner24943d22010-06-08 16:52:24 +0000881
882class CommandObjectProcessDetach : public CommandObject
883{
884public:
885
Greg Clayton238c0a12010-09-18 01:14:36 +0000886 CommandObjectProcessDetach (CommandInterpreter &interpreter) :
887 CommandObject (interpreter,
888 "process detach",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000889 "Detach from the current process being debugged.",
Chris Lattner24943d22010-06-08 16:52:24 +0000890 "process detach",
891 eFlagProcessMustBeLaunched)
892 {
893 }
894
895 ~CommandObjectProcessDetach ()
896 {
897 }
898
899 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000900 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000901 CommandReturnObject &result)
902 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000903 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000904 if (process == NULL)
905 {
906 result.AppendError ("must have a valid process in order to detach");
907 result.SetStatus (eReturnStatusFailed);
908 return false;
909 }
910
Caroline Tice90b42252010-11-02 16:16:53 +0000911 result.AppendMessageWithFormat ("Detaching from process %i\n", process->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000912 Error error (process->Detach());
913 if (error.Success())
914 {
915 result.SetStatus (eReturnStatusSuccessFinishResult);
916 }
917 else
918 {
919 result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString());
920 result.SetStatus (eReturnStatusFailed);
921 return false;
922 }
923 return result.Succeeded();
924 }
925};
926
927//-------------------------------------------------------------------------
Greg Clayton0baa3942010-11-04 01:54:29 +0000928// CommandObjectProcessLoad
929//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +0000930#pragma mark CommandObjectProcessLoad
Greg Clayton0baa3942010-11-04 01:54:29 +0000931
932class CommandObjectProcessLoad : public CommandObject
933{
934public:
935
936 CommandObjectProcessLoad (CommandInterpreter &interpreter) :
937 CommandObject (interpreter,
938 "process load",
939 "Load a shared library into the current process.",
940 "process load <filename> [<filename> ...]",
941 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
942 {
943 }
944
945 ~CommandObjectProcessLoad ()
946 {
947 }
948
949 bool
950 Execute (Args& command,
951 CommandReturnObject &result)
952 {
953 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
954 if (process == NULL)
955 {
956 result.AppendError ("must have a valid process in order to load a shared library");
957 result.SetStatus (eReturnStatusFailed);
958 return false;
959 }
960
961 const uint32_t argc = command.GetArgumentCount();
962
963 for (uint32_t i=0; i<argc; ++i)
964 {
965 Error error;
966 const char *image_path = command.GetArgumentAtIndex(i);
967 FileSpec image_spec (image_path, false);
968 uint32_t image_token = process->LoadImage(image_spec, error);
969 if (image_token != LLDB_INVALID_IMAGE_TOKEN)
970 {
971 result.AppendMessageWithFormat ("Loading \"%s\"...ok\nImage %u loaded.\n", image_path, image_token);
972 result.SetStatus (eReturnStatusSuccessFinishResult);
973 }
974 else
975 {
976 result.AppendErrorWithFormat ("failed to load '%s': %s", image_path, error.AsCString());
977 result.SetStatus (eReturnStatusFailed);
978 }
979 }
980 return result.Succeeded();
981 }
982};
983
984
985//-------------------------------------------------------------------------
986// CommandObjectProcessUnload
987//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +0000988#pragma mark CommandObjectProcessUnload
Greg Clayton0baa3942010-11-04 01:54:29 +0000989
990class CommandObjectProcessUnload : public CommandObject
991{
992public:
993
994 CommandObjectProcessUnload (CommandInterpreter &interpreter) :
995 CommandObject (interpreter,
996 "process unload",
997 "Unload a shared library from the current process using the index returned by a previous call to \"process load\".",
998 "process unload <index>",
999 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
1000 {
1001 }
1002
1003 ~CommandObjectProcessUnload ()
1004 {
1005 }
1006
1007 bool
1008 Execute (Args& command,
1009 CommandReturnObject &result)
1010 {
1011 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
1012 if (process == NULL)
1013 {
1014 result.AppendError ("must have a valid process in order to load a shared library");
1015 result.SetStatus (eReturnStatusFailed);
1016 return false;
1017 }
1018
1019 const uint32_t argc = command.GetArgumentCount();
1020
1021 for (uint32_t i=0; i<argc; ++i)
1022 {
1023 const char *image_token_cstr = command.GetArgumentAtIndex(i);
1024 uint32_t image_token = Args::StringToUInt32(image_token_cstr, LLDB_INVALID_IMAGE_TOKEN, 0);
1025 if (image_token == LLDB_INVALID_IMAGE_TOKEN)
1026 {
1027 result.AppendErrorWithFormat ("invalid image index argument '%s'", image_token_cstr);
1028 result.SetStatus (eReturnStatusFailed);
1029 break;
1030 }
1031 else
1032 {
1033 Error error (process->UnloadImage(image_token));
1034 if (error.Success())
1035 {
1036 result.AppendMessageWithFormat ("Unloading shared library with index %u...ok\n", image_token);
1037 result.SetStatus (eReturnStatusSuccessFinishResult);
1038 }
1039 else
1040 {
1041 result.AppendErrorWithFormat ("failed to unload image: %s", error.AsCString());
1042 result.SetStatus (eReturnStatusFailed);
1043 break;
1044 }
1045 }
1046 }
1047 return result.Succeeded();
1048 }
1049};
1050
1051//-------------------------------------------------------------------------
Chris Lattner24943d22010-06-08 16:52:24 +00001052// CommandObjectProcessSignal
1053//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +00001054#pragma mark CommandObjectProcessSignal
Chris Lattner24943d22010-06-08 16:52:24 +00001055
1056class CommandObjectProcessSignal : public CommandObject
1057{
1058public:
1059
Greg Clayton238c0a12010-09-18 01:14:36 +00001060 CommandObjectProcessSignal (CommandInterpreter &interpreter) :
1061 CommandObject (interpreter,
1062 "process signal",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001063 "Send a UNIX signal to the current process being debugged.",
Caroline Tice43b014a2010-10-04 22:28:36 +00001064 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +00001065 {
Caroline Tice43b014a2010-10-04 22:28:36 +00001066 CommandArgumentEntry arg;
1067 CommandArgumentData signal_arg;
1068
1069 // Define the first (and only) variant of this arg.
Caroline Tice3a62e6d2010-10-18 22:56:57 +00001070 signal_arg.arg_type = eArgTypeUnixSignal;
Caroline Tice43b014a2010-10-04 22:28:36 +00001071 signal_arg.arg_repetition = eArgRepeatPlain;
1072
1073 // There is only one variant this argument could be; put it into the argument entry.
1074 arg.push_back (signal_arg);
1075
1076 // Push the data for the first argument into the m_arguments vector.
1077 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +00001078 }
1079
1080 ~CommandObjectProcessSignal ()
1081 {
1082 }
1083
1084 bool
Greg Clayton238c0a12010-09-18 01:14:36 +00001085 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +00001086 CommandReturnObject &result)
1087 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001088 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +00001089 if (process == NULL)
1090 {
1091 result.AppendError ("no process to signal");
1092 result.SetStatus (eReturnStatusFailed);
1093 return false;
1094 }
1095
1096 if (command.GetArgumentCount() == 1)
1097 {
Greg Clayton8f6be2a2010-10-09 01:40:57 +00001098 int signo = LLDB_INVALID_SIGNAL_NUMBER;
1099
1100 const char *signal_name = command.GetArgumentAtIndex(0);
1101 if (::isxdigit (signal_name[0]))
1102 signo = Args::StringToSInt32(signal_name, LLDB_INVALID_SIGNAL_NUMBER, 0);
1103 else
1104 signo = process->GetUnixSignals().GetSignalNumberFromName (signal_name);
1105
1106 if (signo == LLDB_INVALID_SIGNAL_NUMBER)
Chris Lattner24943d22010-06-08 16:52:24 +00001107 {
1108 result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0));
1109 result.SetStatus (eReturnStatusFailed);
1110 }
1111 else
1112 {
1113 Error error (process->Signal (signo));
1114 if (error.Success())
1115 {
1116 result.SetStatus (eReturnStatusSuccessFinishResult);
1117 }
1118 else
1119 {
1120 result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString());
1121 result.SetStatus (eReturnStatusFailed);
1122 }
1123 }
1124 }
1125 else
1126 {
1127 result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: \n", m_cmd_name.c_str(),
1128 m_cmd_syntax.c_str());
1129 result.SetStatus (eReturnStatusFailed);
1130 }
1131 return result.Succeeded();
1132 }
1133};
1134
1135
1136//-------------------------------------------------------------------------
1137// CommandObjectProcessInterrupt
1138//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +00001139#pragma mark CommandObjectProcessInterrupt
Chris Lattner24943d22010-06-08 16:52:24 +00001140
1141class CommandObjectProcessInterrupt : public CommandObject
1142{
1143public:
1144
1145
Greg Clayton238c0a12010-09-18 01:14:36 +00001146 CommandObjectProcessInterrupt (CommandInterpreter &interpreter) :
1147 CommandObject (interpreter,
1148 "process interrupt",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001149 "Interrupt the current process being debugged.",
Chris Lattner24943d22010-06-08 16:52:24 +00001150 "process interrupt",
1151 eFlagProcessMustBeLaunched)
1152 {
1153 }
1154
1155 ~CommandObjectProcessInterrupt ()
1156 {
1157 }
1158
1159 bool
Greg Clayton238c0a12010-09-18 01:14:36 +00001160 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +00001161 CommandReturnObject &result)
1162 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001163 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +00001164 if (process == NULL)
1165 {
1166 result.AppendError ("no process to halt");
1167 result.SetStatus (eReturnStatusFailed);
1168 return false;
1169 }
1170
1171 if (command.GetArgumentCount() == 0)
1172 {
1173 Error error(process->Halt ());
1174 if (error.Success())
1175 {
1176 result.SetStatus (eReturnStatusSuccessFinishResult);
1177
1178 // Maybe we should add a "SuspendThreadPlans so we
1179 // can halt, and keep in place all the current thread plans.
1180 process->GetThreadList().DiscardThreadPlans();
1181 }
1182 else
1183 {
1184 result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString());
1185 result.SetStatus (eReturnStatusFailed);
1186 }
1187 }
1188 else
1189 {
1190 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
1191 m_cmd_name.c_str(),
1192 m_cmd_syntax.c_str());
1193 result.SetStatus (eReturnStatusFailed);
1194 }
1195 return result.Succeeded();
1196 }
1197};
1198
1199//-------------------------------------------------------------------------
1200// CommandObjectProcessKill
1201//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +00001202#pragma mark CommandObjectProcessKill
Chris Lattner24943d22010-06-08 16:52:24 +00001203
1204class CommandObjectProcessKill : public CommandObject
1205{
1206public:
1207
Greg Clayton238c0a12010-09-18 01:14:36 +00001208 CommandObjectProcessKill (CommandInterpreter &interpreter) :
1209 CommandObject (interpreter,
1210 "process kill",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001211 "Terminate the current process being debugged.",
Chris Lattner24943d22010-06-08 16:52:24 +00001212 "process kill",
1213 eFlagProcessMustBeLaunched)
1214 {
1215 }
1216
1217 ~CommandObjectProcessKill ()
1218 {
1219 }
1220
1221 bool
Greg Clayton238c0a12010-09-18 01:14:36 +00001222 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +00001223 CommandReturnObject &result)
1224 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001225 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +00001226 if (process == NULL)
1227 {
1228 result.AppendError ("no process to kill");
1229 result.SetStatus (eReturnStatusFailed);
1230 return false;
1231 }
1232
1233 if (command.GetArgumentCount() == 0)
1234 {
1235 Error error (process->Destroy());
1236 if (error.Success())
1237 {
1238 result.SetStatus (eReturnStatusSuccessFinishResult);
1239 }
1240 else
1241 {
1242 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString());
1243 result.SetStatus (eReturnStatusFailed);
1244 }
1245 }
1246 else
1247 {
1248 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
1249 m_cmd_name.c_str(),
1250 m_cmd_syntax.c_str());
1251 result.SetStatus (eReturnStatusFailed);
1252 }
1253 return result.Succeeded();
1254 }
1255};
1256
1257//-------------------------------------------------------------------------
Jim Ingham41313fc2010-06-18 01:23:09 +00001258// CommandObjectProcessStatus
1259//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +00001260#pragma mark CommandObjectProcessStatus
1261
Jim Ingham41313fc2010-06-18 01:23:09 +00001262class CommandObjectProcessStatus : public CommandObject
1263{
1264public:
Greg Clayton238c0a12010-09-18 01:14:36 +00001265 CommandObjectProcessStatus (CommandInterpreter &interpreter) :
1266 CommandObject (interpreter,
1267 "process status",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001268 "Show the current status and location of executing process.",
1269 "process status",
Jim Ingham41313fc2010-06-18 01:23:09 +00001270 0)
1271 {
1272 }
1273
1274 ~CommandObjectProcessStatus()
1275 {
1276 }
1277
1278
1279 bool
1280 Execute
1281 (
1282 Args& command,
Jim Ingham41313fc2010-06-18 01:23:09 +00001283 CommandReturnObject &result
1284 )
1285 {
1286 StreamString &output_stream = result.GetOutputStream();
1287 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Greg Clayton238c0a12010-09-18 01:14:36 +00001288 ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
Jim Ingham41313fc2010-06-18 01:23:09 +00001289 if (exe_ctx.process)
1290 {
1291 const StateType state = exe_ctx.process->GetState();
1292 if (StateIsStoppedState(state))
1293 {
1294 if (state == eStateExited)
1295 {
1296 int exit_status = exe_ctx.process->GetExitStatus();
1297 const char *exit_description = exe_ctx.process->GetExitDescription();
1298 output_stream.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n",
1299 exe_ctx.process->GetID(),
1300 exit_status,
1301 exit_status,
1302 exit_description ? exit_description : "");
1303 }
1304 else
1305 {
1306 output_stream.Printf ("Process %d %s\n", exe_ctx.process->GetID(), StateAsCString (state));
1307 if (exe_ctx.thread == NULL)
1308 exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
1309 if (exe_ctx.thread != NULL)
1310 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001311 DisplayThreadsInfo (m_interpreter, &exe_ctx, result, true, true);
Jim Ingham41313fc2010-06-18 01:23:09 +00001312 }
1313 else
1314 {
1315 result.AppendError ("No valid thread found in current process.");
1316 result.SetStatus (eReturnStatusFailed);
1317 }
1318 }
1319 }
1320 else
1321 {
1322 output_stream.Printf ("Process %d is running.\n",
1323 exe_ctx.process->GetID());
1324 }
1325 }
1326 else
1327 {
1328 result.AppendError ("No current location or status available.");
1329 result.SetStatus (eReturnStatusFailed);
1330 }
1331 return result.Succeeded();
1332 }
1333};
1334
1335//-------------------------------------------------------------------------
Caroline Tice23d6f272010-10-13 20:44:39 +00001336// CommandObjectProcessHandle
1337//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +00001338#pragma mark CommandObjectProcessHandle
Caroline Tice23d6f272010-10-13 20:44:39 +00001339
1340class CommandObjectProcessHandle : public CommandObject
1341{
1342public:
1343
1344 class CommandOptions : public Options
1345 {
1346 public:
1347
1348 CommandOptions () :
1349 Options ()
1350 {
1351 ResetOptionValues ();
1352 }
1353
1354 ~CommandOptions ()
1355 {
1356 }
1357
1358 Error
1359 SetOptionValue (int option_idx, const char *option_arg)
1360 {
1361 Error error;
1362 char short_option = (char) m_getopt_table[option_idx].val;
1363
1364 switch (short_option)
1365 {
1366 case 's':
1367 stop = option_arg;
1368 break;
1369 case 'n':
1370 notify = option_arg;
1371 break;
1372 case 'p':
1373 pass = option_arg;
1374 break;
1375 default:
1376 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
1377 break;
1378 }
1379 return error;
1380 }
1381
1382 void
1383 ResetOptionValues ()
1384 {
1385 Options::ResetOptionValues();
1386 stop.clear();
1387 notify.clear();
1388 pass.clear();
1389 }
1390
1391 const lldb::OptionDefinition*
1392 GetDefinitions ()
1393 {
1394 return g_option_table;
1395 }
1396
1397 // Options table: Required for subclasses of Options.
1398
1399 static lldb::OptionDefinition g_option_table[];
1400
1401 // Instance variables to hold the values for command options.
1402
1403 std::string stop;
1404 std::string notify;
1405 std::string pass;
1406 };
1407
1408
1409 CommandObjectProcessHandle (CommandInterpreter &interpreter) :
1410 CommandObject (interpreter,
1411 "process handle",
Caroline Ticee7471982010-10-14 21:31:13 +00001412 "Show or update what the process and debugger should do with various signals received from the OS.",
Caroline Tice23d6f272010-10-13 20:44:39 +00001413 NULL)
1414 {
Caroline Ticee7471982010-10-14 21:31:13 +00001415 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 +00001416 CommandArgumentEntry arg;
Caroline Tice3a62e6d2010-10-18 22:56:57 +00001417 CommandArgumentData signal_arg;
Caroline Tice23d6f272010-10-13 20:44:39 +00001418
Caroline Tice3a62e6d2010-10-18 22:56:57 +00001419 signal_arg.arg_type = eArgTypeUnixSignal;
1420 signal_arg.arg_repetition = eArgRepeatStar;
Caroline Tice23d6f272010-10-13 20:44:39 +00001421
Caroline Tice3a62e6d2010-10-18 22:56:57 +00001422 arg.push_back (signal_arg);
Caroline Tice23d6f272010-10-13 20:44:39 +00001423
1424 m_arguments.push_back (arg);
1425 }
1426
1427 ~CommandObjectProcessHandle ()
1428 {
1429 }
1430
1431 Options *
1432 GetOptions ()
1433 {
1434 return &m_options;
1435 }
1436
1437 bool
Caroline Ticee7471982010-10-14 21:31:13 +00001438 VerifyCommandOptionValue (const std::string &option, int &real_value)
Caroline Tice23d6f272010-10-13 20:44:39 +00001439 {
1440 bool okay = true;
1441
Caroline Ticee7471982010-10-14 21:31:13 +00001442 bool success = false;
1443 bool tmp_value = Args::StringToBoolean (option.c_str(), false, &success);
1444
1445 if (success && tmp_value)
1446 real_value = 1;
1447 else if (success && !tmp_value)
1448 real_value = 0;
Caroline Tice23d6f272010-10-13 20:44:39 +00001449 else
1450 {
1451 // If the value isn't 'true' or 'false', it had better be 0 or 1.
Caroline Ticee7471982010-10-14 21:31:13 +00001452 real_value = Args::StringToUInt32 (option.c_str(), 3);
1453 if (real_value != 0 && real_value != 1)
Caroline Tice23d6f272010-10-13 20:44:39 +00001454 okay = false;
1455 }
1456
1457 return okay;
1458 }
1459
Caroline Ticee7471982010-10-14 21:31:13 +00001460 void
1461 PrintSignalHeader (Stream &str)
1462 {
1463 str.Printf ("NAME PASS STOP NOTIFY\n");
1464 str.Printf ("========== ===== ===== ======\n");
1465 }
1466
1467 void
1468 PrintSignal (Stream &str, int32_t signo, const char *sig_name, UnixSignals &signals)
1469 {
1470 bool stop;
1471 bool suppress;
1472 bool notify;
1473
1474 str.Printf ("%-10s ", sig_name);
1475 if (signals.GetSignalInfo (signo, suppress, stop, notify))
1476 {
1477 bool pass = !suppress;
1478 str.Printf ("%s %s %s",
1479 (pass ? "true " : "false"),
1480 (stop ? "true " : "false"),
1481 (notify ? "true " : "false"));
1482 }
1483 str.Printf ("\n");
1484 }
1485
1486 void
1487 PrintSignalInformation (Stream &str, Args &signal_args, int num_valid_signals, UnixSignals &signals)
1488 {
1489 PrintSignalHeader (str);
1490
1491 if (num_valid_signals > 0)
1492 {
1493 size_t num_args = signal_args.GetArgumentCount();
1494 for (size_t i = 0; i < num_args; ++i)
1495 {
1496 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
1497 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
1498 PrintSignal (str, signo, signal_args.GetArgumentAtIndex (i), signals);
1499 }
1500 }
1501 else // Print info for ALL signals
1502 {
1503 int32_t signo = signals.GetFirstSignalNumber();
1504 while (signo != LLDB_INVALID_SIGNAL_NUMBER)
1505 {
1506 PrintSignal (str, signo, signals.GetSignalAsCString (signo), signals);
1507 signo = signals.GetNextSignalNumber (signo);
1508 }
1509 }
1510 }
1511
Caroline Tice23d6f272010-10-13 20:44:39 +00001512 bool
1513 Execute (Args &signal_args, CommandReturnObject &result)
1514 {
1515 TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
1516
1517 if (!target_sp)
1518 {
1519 result.AppendError ("No current target;"
1520 " cannot handle signals until you have a valid target and process.\n");
1521 result.SetStatus (eReturnStatusFailed);
1522 return false;
1523 }
1524
1525 ProcessSP process_sp = target_sp->GetProcessSP();
1526
1527 if (!process_sp)
1528 {
1529 result.AppendError ("No current process; cannot handle signals until you have a valid process.\n");
1530 result.SetStatus (eReturnStatusFailed);
1531 return false;
1532 }
1533
Caroline Tice23d6f272010-10-13 20:44:39 +00001534 int stop_action = -1; // -1 means leave the current setting alone
Caroline Ticee7471982010-10-14 21:31:13 +00001535 int pass_action = -1; // -1 means leave the current setting alone
Caroline Tice23d6f272010-10-13 20:44:39 +00001536 int notify_action = -1; // -1 means leave the current setting alone
1537
1538 if (! m_options.stop.empty()
Caroline Ticee7471982010-10-14 21:31:13 +00001539 && ! VerifyCommandOptionValue (m_options.stop, stop_action))
Caroline Tice23d6f272010-10-13 20:44:39 +00001540 {
1541 result.AppendError ("Invalid argument for command option --stop; must be true or false.\n");
1542 result.SetStatus (eReturnStatusFailed);
1543 return false;
1544 }
1545
1546 if (! m_options.notify.empty()
Caroline Ticee7471982010-10-14 21:31:13 +00001547 && ! VerifyCommandOptionValue (m_options.notify, notify_action))
Caroline Tice23d6f272010-10-13 20:44:39 +00001548 {
1549 result.AppendError ("Invalid argument for command option --notify; must be true or false.\n");
1550 result.SetStatus (eReturnStatusFailed);
1551 return false;
1552 }
1553
1554 if (! m_options.pass.empty()
Caroline Ticee7471982010-10-14 21:31:13 +00001555 && ! VerifyCommandOptionValue (m_options.pass, pass_action))
Caroline Tice23d6f272010-10-13 20:44:39 +00001556 {
1557 result.AppendError ("Invalid argument for command option --pass; must be true or false.\n");
1558 result.SetStatus (eReturnStatusFailed);
1559 return false;
1560 }
1561
1562 size_t num_args = signal_args.GetArgumentCount();
1563 UnixSignals &signals = process_sp->GetUnixSignals();
1564 int num_signals_set = 0;
1565
Caroline Ticee7471982010-10-14 21:31:13 +00001566 if (num_args > 0)
Caroline Tice23d6f272010-10-13 20:44:39 +00001567 {
Caroline Ticee7471982010-10-14 21:31:13 +00001568 for (size_t i = 0; i < num_args; ++i)
Caroline Tice23d6f272010-10-13 20:44:39 +00001569 {
Caroline Ticee7471982010-10-14 21:31:13 +00001570 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
1571 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
Caroline Tice23d6f272010-10-13 20:44:39 +00001572 {
Caroline Ticee7471982010-10-14 21:31:13 +00001573 // Casting the actions as bools here should be okay, because VerifyCommandOptionValue guarantees
1574 // the value is either 0 or 1.
1575 if (stop_action != -1)
1576 signals.SetShouldStop (signo, (bool) stop_action);
1577 if (pass_action != -1)
1578 {
1579 bool suppress = ! ((bool) pass_action);
1580 signals.SetShouldSuppress (signo, suppress);
1581 }
1582 if (notify_action != -1)
1583 signals.SetShouldNotify (signo, (bool) notify_action);
1584 ++num_signals_set;
Caroline Tice23d6f272010-10-13 20:44:39 +00001585 }
Caroline Ticee7471982010-10-14 21:31:13 +00001586 else
1587 {
1588 result.AppendErrorWithFormat ("Invalid signal name '%s'\n", signal_args.GetArgumentAtIndex (i));
1589 }
Caroline Tice23d6f272010-10-13 20:44:39 +00001590 }
1591 }
Caroline Ticee7471982010-10-14 21:31:13 +00001592 else
1593 {
1594 // No signal specified, if any command options were specified, update ALL signals.
1595 if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1))
1596 {
1597 if (m_interpreter.Confirm ("Do you really want to update all the signals?", false))
1598 {
1599 int32_t signo = signals.GetFirstSignalNumber();
1600 while (signo != LLDB_INVALID_SIGNAL_NUMBER)
1601 {
1602 if (notify_action != -1)
1603 signals.SetShouldNotify (signo, (bool) notify_action);
1604 if (stop_action != -1)
1605 signals.SetShouldStop (signo, (bool) stop_action);
1606 if (pass_action != -1)
1607 {
1608 bool suppress = ! ((bool) pass_action);
1609 signals.SetShouldSuppress (signo, suppress);
1610 }
1611 signo = signals.GetNextSignalNumber (signo);
1612 }
1613 }
1614 }
1615 }
1616
1617 PrintSignalInformation (result.GetOutputStream(), signal_args, num_signals_set, signals);
Caroline Tice23d6f272010-10-13 20:44:39 +00001618
1619 if (num_signals_set > 0)
1620 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1621 else
1622 result.SetStatus (eReturnStatusFailed);
1623
1624 return result.Succeeded();
1625 }
1626
1627protected:
1628
1629 CommandOptions m_options;
1630};
1631
1632lldb::OptionDefinition
1633CommandObjectProcessHandle::CommandOptions::g_option_table[] =
1634{
1635{ 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." },
1636{ 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." },
1637{ LLDB_OPT_SET_1, false, "pass", 'p', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." },
1638{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1639};
1640
1641//-------------------------------------------------------------------------
Chris Lattner24943d22010-06-08 16:52:24 +00001642// CommandObjectMultiwordProcess
1643//-------------------------------------------------------------------------
1644
Greg Clayton63094e02010-06-23 01:19:29 +00001645CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001646 CommandObjectMultiword (interpreter,
1647 "process",
1648 "A set of commands for operating on a process.",
1649 "process <subcommand> [<subcommand-options>]")
Chris Lattner24943d22010-06-08 16:52:24 +00001650{
Greg Clayton238c0a12010-09-18 01:14:36 +00001651 LoadSubCommand ("attach", CommandObjectSP (new CommandObjectProcessAttach (interpreter)));
1652 LoadSubCommand ("launch", CommandObjectSP (new CommandObjectProcessLaunch (interpreter)));
1653 LoadSubCommand ("continue", CommandObjectSP (new CommandObjectProcessContinue (interpreter)));
1654 LoadSubCommand ("detach", CommandObjectSP (new CommandObjectProcessDetach (interpreter)));
Greg Clayton0baa3942010-11-04 01:54:29 +00001655 LoadSubCommand ("load", CommandObjectSP (new CommandObjectProcessLoad (interpreter)));
1656 LoadSubCommand ("unload", CommandObjectSP (new CommandObjectProcessUnload (interpreter)));
Greg Clayton238c0a12010-09-18 01:14:36 +00001657 LoadSubCommand ("signal", CommandObjectSP (new CommandObjectProcessSignal (interpreter)));
Caroline Tice23d6f272010-10-13 20:44:39 +00001658 LoadSubCommand ("handle", CommandObjectSP (new CommandObjectProcessHandle (interpreter)));
Greg Clayton238c0a12010-09-18 01:14:36 +00001659 LoadSubCommand ("status", CommandObjectSP (new CommandObjectProcessStatus (interpreter)));
1660 LoadSubCommand ("interrupt", CommandObjectSP (new CommandObjectProcessInterrupt (interpreter)));
1661 LoadSubCommand ("kill", CommandObjectSP (new CommandObjectProcessKill (interpreter)));
Chris Lattner24943d22010-06-08 16:52:24 +00001662}
1663
1664CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess ()
1665{
1666}
1667