blob: 7dd42237ea71986e83369f261a3d80c35170c8a7 [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"
Greg Claytoncd548032011-02-01 01:31:41 +000022#include "lldb/Host/Host.h"
Chris Lattner24943d22010-06-08 16:52:24 +000023#include "lldb/Target/Process.h"
24#include "lldb/Target/Target.h"
25#include "lldb/Target/Thread.h"
26
27using namespace lldb;
28using namespace lldb_private;
29
30//-------------------------------------------------------------------------
31// CommandObjectProcessLaunch
32//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +000033#pragma mark CommandObjectProjectLaunch
Chris Lattner24943d22010-06-08 16:52:24 +000034class CommandObjectProcessLaunch : public CommandObject
35{
36public:
37
38 class CommandOptions : public Options
39 {
40 public:
41
42 CommandOptions () :
43 Options()
44 {
45 // Keep default values of all options in one place: ResetOptionValues ()
46 ResetOptionValues ();
47 }
48
49 ~CommandOptions ()
50 {
51 }
52
53 Error
54 SetOptionValue (int option_idx, const char *option_arg)
55 {
56 Error error;
57 char short_option = (char) m_getopt_table[option_idx].val;
58
59 switch (short_option)
60 {
Greg Claytonde915be2011-01-23 05:56:20 +000061 case 's': stop_at_entry = true; break;
62 case 'e': stderr_path.assign (option_arg); break;
63 case 'i': stdin_path.assign (option_arg); break;
64 case 'o': stdout_path.assign (option_arg); break;
65 case 'p': plugin_name.assign (option_arg); break;
66 case 'n': no_stdio = true; break;
67 case 'w': working_dir.assign (option_arg); break;
Greg Claytonbb0c91f2010-10-19 23:16:00 +000068 case 't':
69 if (option_arg && option_arg[0])
70 tty_name.assign (option_arg);
71 in_new_tty = true;
72 break;
Chris Lattner24943d22010-06-08 16:52:24 +000073 default:
74 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
75 break;
76
77 }
78 return error;
79 }
80
81 void
82 ResetOptionValues ()
83 {
84 Options::ResetOptionValues();
85 stop_at_entry = false;
Greg Claytonc1d37752010-10-18 01:45:30 +000086 in_new_tty = false;
Greg Claytonbb0c91f2010-10-19 23:16:00 +000087 tty_name.clear();
Chris Lattner24943d22010-06-08 16:52:24 +000088 stdin_path.clear();
89 stdout_path.clear();
90 stderr_path.clear();
91 plugin_name.clear();
Greg Claytonde915be2011-01-23 05:56:20 +000092 working_dir.clear();
Caroline Ticebd666012010-12-03 18:46:09 +000093 no_stdio = false;
Chris Lattner24943d22010-06-08 16:52:24 +000094 }
95
96 const lldb::OptionDefinition*
97 GetDefinitions ()
98 {
99 return g_option_table;
100 }
101
102 // Options table: Required for subclasses of Options.
103
104 static lldb::OptionDefinition g_option_table[];
105
106 // Instance variables to hold the values for command options.
107
108 bool stop_at_entry;
Greg Claytonc1d37752010-10-18 01:45:30 +0000109 bool in_new_tty;
Caroline Ticebd666012010-12-03 18:46:09 +0000110 bool no_stdio;
Greg Claytonbb0c91f2010-10-19 23:16:00 +0000111 std::string tty_name;
Chris Lattner24943d22010-06-08 16:52:24 +0000112 std::string stderr_path;
113 std::string stdin_path;
114 std::string stdout_path;
115 std::string plugin_name;
Greg Claytonde915be2011-01-23 05:56:20 +0000116 std::string working_dir;
Chris Lattner24943d22010-06-08 16:52:24 +0000117
118 };
119
Greg Clayton238c0a12010-09-18 01:14:36 +0000120 CommandObjectProcessLaunch (CommandInterpreter &interpreter) :
121 CommandObject (interpreter,
122 "process launch",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000123 "Launch the executable in the debugger.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000124 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000125 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000126 CommandArgumentEntry arg;
127 CommandArgumentData run_args_arg;
128
129 // Define the first (and only) variant of this arg.
130 run_args_arg.arg_type = eArgTypeRunArgs;
131 run_args_arg.arg_repetition = eArgRepeatOptional;
132
133 // There is only one variant this argument could be; put it into the argument entry.
134 arg.push_back (run_args_arg);
135
136 // Push the data for the first argument into the m_arguments vector.
137 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000138 }
139
140
141 ~CommandObjectProcessLaunch ()
142 {
143 }
144
145 Options *
146 GetOptions ()
147 {
148 return &m_options;
149 }
150
151 bool
Greg Claytond8c62532010-10-07 04:19:01 +0000152 Execute (Args& launch_args, CommandReturnObject &result)
Chris Lattner24943d22010-06-08 16:52:24 +0000153 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000154 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000155
156 if (target == NULL)
157 {
158 result.AppendError ("invalid target, set executable file using 'file' command");
159 result.SetStatus (eReturnStatusFailed);
160 return false;
161 }
162
163 // If our listener is NULL, users aren't allows to launch
Chris Lattner24943d22010-06-08 16:52:24 +0000164 char filename[PATH_MAX];
Greg Claytonc1d37752010-10-18 01:45:30 +0000165 const Module *exe_module = target->GetExecutableModule().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000166 exe_module->GetFileSpec().GetPath(filename, sizeof(filename));
167
Greg Clayton238c0a12010-09-18 01:14:36 +0000168 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
169 if (process && process->IsAlive())
Jim Ingham22dc9722010-12-09 18:58:16 +0000170 {
Greg Clayton7e2f91c2011-01-29 07:10:55 +0000171 char message[1024];
172 if (process->GetState() == eStateAttaching)
173 ::strncpy (message, "There is a pending attach, abort it and launch a new process?", sizeof(message));
174 else
175 ::strncpy (message, "There is a running process, kill it and restart?", sizeof(message));
176
177 if (!m_interpreter.Confirm (message, true))
Jim Ingham22dc9722010-12-09 18:58:16 +0000178 {
Jim Ingham22dc9722010-12-09 18:58:16 +0000179 result.SetStatus (eReturnStatusFailed);
180 return false;
181 }
182 else
183 {
184 Error error (process->Destroy());
185 if (error.Success())
186 {
187 result.SetStatus (eReturnStatusSuccessFinishResult);
188 }
189 else
190 {
191 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString());
192 result.SetStatus (eReturnStatusFailed);
193 }
194 }
Chris Lattner24943d22010-06-08 16:52:24 +0000195 }
Jim Ingham22dc9722010-12-09 18:58:16 +0000196
Chris Lattner24943d22010-06-08 16:52:24 +0000197 const char *plugin_name;
198 if (!m_options.plugin_name.empty())
199 plugin_name = m_options.plugin_name.c_str();
200 else
201 plugin_name = NULL;
202
Greg Clayton238c0a12010-09-18 01:14:36 +0000203 process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
Chris Lattner24943d22010-06-08 16:52:24 +0000204
Greg Clayton238c0a12010-09-18 01:14:36 +0000205 if (process == NULL)
Caroline Tice6e4c5ce2010-09-04 00:03:46 +0000206 {
Caroline Tice734b4832010-10-15 21:52:38 +0000207 result.AppendErrorWithFormat ("Failed to find a process plugin for executable.\n");
Chris Lattner24943d22010-06-08 16:52:24 +0000208 result.SetStatus (eReturnStatusFailed);
209 return false;
210 }
211
Greg Clayton238c0a12010-09-18 01:14:36 +0000212 // If no launch args were given on the command line, then use any that
213 // might have been set using the "run-args" set variable.
214 if (launch_args.GetArgumentCount() == 0)
215 {
216 if (process->GetRunArguments().GetArgumentCount() > 0)
217 launch_args = process->GetRunArguments();
218 }
219
Greg Claytonc1d37752010-10-18 01:45:30 +0000220 if (m_options.in_new_tty)
221 {
222 char exec_file_path[PATH_MAX];
223 if (exe_module->GetFileSpec().GetPath(exec_file_path, sizeof(exec_file_path)))
224 {
225 launch_args.InsertArgumentAtIndex(0, exec_file_path);
226 }
227 else
228 {
229 result.AppendError("invalid executable");
230 result.SetStatus (eReturnStatusFailed);
231 return false;
232 }
233 }
234
Greg Clayton238c0a12010-09-18 01:14:36 +0000235 Args environment;
236
237 process->GetEnvironmentAsArgs (environment);
238
239 uint32_t launch_flags = eLaunchFlagNone;
240
241 if (process->GetDisableASLR())
242 launch_flags |= eLaunchFlagDisableASLR;
Greg Claytonc1d37752010-10-18 01:45:30 +0000243
Caroline Ticebd666012010-12-03 18:46:09 +0000244 if (m_options.no_stdio)
245 launch_flags |= eLaunchFlagDisableSTDIO;
246 else if (!m_options.in_new_tty
247 && m_options.stdin_path.empty()
248 && m_options.stdout_path.empty()
249 && m_options.stderr_path.empty())
250 {
251 // Only use the settings value if the user hasn't specified any options that would override it.
252 if (process->GetDisableSTDIO())
253 launch_flags |= eLaunchFlagDisableSTDIO;
254 }
255
Greg Claytonc1d37752010-10-18 01:45:30 +0000256 const char **inferior_argv = launch_args.GetArgumentCount() ? launch_args.GetConstArgumentVector() : NULL;
257 const char **inferior_envp = environment.GetArgumentCount() ? environment.GetConstArgumentVector() : NULL;
Greg Clayton238c0a12010-09-18 01:14:36 +0000258
Greg Claytonc1d37752010-10-18 01:45:30 +0000259 Error error;
Greg Claytonde915be2011-01-23 05:56:20 +0000260 const char *working_dir = NULL;
261 if (!m_options.working_dir.empty())
262 working_dir = m_options.working_dir.c_str();
Greg Clayton238c0a12010-09-18 01:14:36 +0000263
Greg Claytonc1d37752010-10-18 01:45:30 +0000264 if (m_options.in_new_tty)
Greg Clayton238c0a12010-09-18 01:14:36 +0000265 {
Greg Claytonc1d37752010-10-18 01:45:30 +0000266
Greg Claytonbb0c91f2010-10-19 23:16:00 +0000267 lldb::pid_t pid = Host::LaunchInNewTerminal (m_options.tty_name.c_str(),
268 inferior_argv,
Greg Clayton36f63a92010-10-19 03:25:40 +0000269 inferior_envp,
Greg Claytonde915be2011-01-23 05:56:20 +0000270 working_dir,
Greg Clayton36f63a92010-10-19 03:25:40 +0000271 &exe_module->GetArchitecture(),
272 true,
273 process->GetDisableASLR());
Greg Claytonc1d37752010-10-18 01:45:30 +0000274
Greg Clayton36f63a92010-10-19 03:25:40 +0000275 if (pid != LLDB_INVALID_PROCESS_ID)
276 error = process->Attach (pid);
Greg Clayton238c0a12010-09-18 01:14:36 +0000277 }
278 else
279 {
Greg Claytonc1d37752010-10-18 01:45:30 +0000280 const char * stdin_path = NULL;
281 const char * stdout_path = NULL;
282 const char * stderr_path = NULL;
283
284 // Were any standard input/output/error paths given on the command line?
285 if (m_options.stdin_path.empty() &&
286 m_options.stdout_path.empty() &&
287 m_options.stderr_path.empty())
288 {
289 // No standard file handles were given on the command line, check
290 // with the process object in case they were give using "set settings"
291 stdin_path = process->GetStandardInputPath();
292 stdout_path = process->GetStandardOutputPath();
293 stderr_path = process->GetStandardErrorPath();
294 }
295 else
296 {
297 stdin_path = m_options.stdin_path.empty() ? NULL : m_options.stdin_path.c_str();
298 stdout_path = m_options.stdout_path.empty() ? NULL : m_options.stdout_path.c_str();
299 stderr_path = m_options.stderr_path.empty() ? NULL : m_options.stderr_path.c_str();
300 }
301
Greg Claytonc1d37752010-10-18 01:45:30 +0000302 error = process->Launch (inferior_argv,
303 inferior_envp,
304 launch_flags,
305 stdin_path,
306 stdout_path,
Greg Claytonde915be2011-01-23 05:56:20 +0000307 stderr_path,
308 working_dir);
Greg Clayton238c0a12010-09-18 01:14:36 +0000309 }
Greg Clayton238c0a12010-09-18 01:14:36 +0000310
311 if (error.Success())
312 {
Greg Claytonc1d37752010-10-18 01:45:30 +0000313 const char *archname = exe_module->GetArchitecture().AsCString();
314
315 result.AppendMessageWithFormat ("Process %i launched: '%s' (%s)\n", process->GetID(), filename, archname);
Greg Claytond8c62532010-10-07 04:19:01 +0000316 result.SetDidChangeProcessState (true);
Greg Clayton238c0a12010-09-18 01:14:36 +0000317 if (m_options.stop_at_entry == false)
318 {
Greg Claytond8c62532010-10-07 04:19:01 +0000319 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
Greg Clayton238c0a12010-09-18 01:14:36 +0000320 StateType state = process->WaitForProcessToStop (NULL);
321
322 if (state == eStateStopped)
323 {
Greg Claytond8c62532010-10-07 04:19:01 +0000324 error = process->Resume();
325 if (error.Success())
326 {
327 bool synchronous_execution = m_interpreter.GetSynchronous ();
328 if (synchronous_execution)
329 {
330 state = process->WaitForProcessToStop (NULL);
331 result.SetDidChangeProcessState (true);
332 result.SetStatus (eReturnStatusSuccessFinishResult);
333 }
334 else
335 {
336 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
337 }
338 }
Greg Clayton238c0a12010-09-18 01:14:36 +0000339 }
340 }
341 }
342
Chris Lattner24943d22010-06-08 16:52:24 +0000343 return result.Succeeded();
344 }
345
Jim Ingham767af882010-07-07 03:36:20 +0000346 virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
347 {
348 // No repeat for "process launch"...
349 return "";
350 }
351
Chris Lattner24943d22010-06-08 16:52:24 +0000352protected:
353
354 CommandOptions m_options;
355};
356
357
Greg Claytonc1d37752010-10-18 01:45:30 +0000358#define SET1 LLDB_OPT_SET_1
359#define SET2 LLDB_OPT_SET_2
Caroline Ticebd666012010-12-03 18:46:09 +0000360#define SET3 LLDB_OPT_SET_3
Greg Claytonc1d37752010-10-18 01:45:30 +0000361
Chris Lattner24943d22010-06-08 16:52:24 +0000362lldb::OptionDefinition
363CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
364{
Caroline Ticebd666012010-12-03 18:46:09 +0000365{ 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."},
366{ SET1 , false, "stdin", 'i', required_argument, NULL, 0, eArgTypePath, "Redirect stdin for the process to <path>."},
367{ SET1 , false, "stdout", 'o', required_argument, NULL, 0, eArgTypePath, "Redirect stdout for the process to <path>."},
368{ SET1 , false, "stderr", 'e', required_argument, NULL, 0, eArgTypePath, "Redirect stderr for the process to <path>."},
369{ SET1 | SET2 | SET3, false, "plugin", 'p', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
370{ 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."},
371{ 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 +0000372{ 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 +0000373{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +0000374};
375
Greg Claytonc1d37752010-10-18 01:45:30 +0000376#undef SET1
377#undef SET2
Caroline Ticebd666012010-12-03 18:46:09 +0000378#undef SET3
Chris Lattner24943d22010-06-08 16:52:24 +0000379
380//-------------------------------------------------------------------------
381// CommandObjectProcessAttach
382//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +0000383#pragma mark CommandObjectProcessAttach
Chris Lattner24943d22010-06-08 16:52:24 +0000384class CommandObjectProcessAttach : public CommandObject
385{
386public:
387
Chris Lattner24943d22010-06-08 16:52:24 +0000388 class CommandOptions : public Options
389 {
390 public:
391
392 CommandOptions () :
393 Options()
394 {
395 // Keep default values of all options in one place: ResetOptionValues ()
396 ResetOptionValues ();
397 }
398
399 ~CommandOptions ()
400 {
401 }
402
403 Error
404 SetOptionValue (int option_idx, const char *option_arg)
405 {
406 Error error;
407 char short_option = (char) m_getopt_table[option_idx].val;
408 bool success = false;
409 switch (short_option)
410 {
411 case 'p':
412 pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success);
413 if (!success || pid == LLDB_INVALID_PROCESS_ID)
414 {
415 error.SetErrorStringWithFormat("Invalid process ID '%s'.\n", option_arg);
416 }
417 break;
418
419 case 'P':
420 plugin_name = option_arg;
421 break;
422
423 case 'n':
424 name.assign(option_arg);
425 break;
426
427 case 'w':
428 waitfor = true;
429 break;
430
431 default:
432 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
433 break;
434 }
435 return error;
436 }
437
438 void
439 ResetOptionValues ()
440 {
441 Options::ResetOptionValues();
442 pid = LLDB_INVALID_PROCESS_ID;
443 name.clear();
444 waitfor = false;
445 }
446
447 const lldb::OptionDefinition*
448 GetDefinitions ()
449 {
450 return g_option_table;
451 }
452
Jim Ingham7508e732010-08-09 23:31:02 +0000453 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000454 HandleOptionArgumentCompletion (CommandInterpreter &interpeter,
Jim Ingham7508e732010-08-09 23:31:02 +0000455 Args &input,
456 int cursor_index,
457 int char_pos,
458 OptionElementVector &opt_element_vector,
459 int opt_element_index,
460 int match_start_point,
461 int max_return_elements,
462 bool &word_complete,
463 StringList &matches)
464 {
465 int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
466 int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
467
468 // We are only completing the name option for now...
469
470 const lldb::OptionDefinition *opt_defs = GetDefinitions();
471 if (opt_defs[opt_defs_index].short_option == 'n')
472 {
473 // Are we in the name?
474
475 // Look to see if there is a -P argument provided, and if so use that plugin, otherwise
476 // use the default plugin.
Greg Clayton238c0a12010-09-18 01:14:36 +0000477 Process *process = interpeter.GetDebugger().GetExecutionContext().process;
Jim Ingham7508e732010-08-09 23:31:02 +0000478 bool need_to_delete_process = false;
479
480 const char *partial_name = NULL;
481 partial_name = input.GetArgumentAtIndex(opt_arg_pos);
482
483 if (process && process->IsAlive())
484 return true;
485
Greg Clayton238c0a12010-09-18 01:14:36 +0000486 Target *target = interpeter.GetDebugger().GetSelectedTarget().get();
Jim Ingham7508e732010-08-09 23:31:02 +0000487 if (target == NULL)
488 {
489 // No target has been set yet, for now do host completion. Otherwise I don't know how we would
490 // figure out what the right target to use is...
491 std::vector<lldb::pid_t> pids;
492 Host::ListProcessesMatchingName (partial_name, matches, pids);
493 return true;
494 }
495 if (!process)
496 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000497 process = target->CreateProcess (interpeter.GetDebugger().GetListener(), partial_name).get();
Jim Ingham7508e732010-08-09 23:31:02 +0000498 need_to_delete_process = true;
499 }
500
501 if (process)
502 {
503 matches.Clear();
504 std::vector<lldb::pid_t> pids;
505 process->ListProcessesMatchingName (NULL, matches, pids);
506 if (need_to_delete_process)
507 target->DeleteCurrentProcess();
508 return true;
509 }
510 }
511
512 return false;
513 }
514
Chris Lattner24943d22010-06-08 16:52:24 +0000515 // Options table: Required for subclasses of Options.
516
517 static lldb::OptionDefinition g_option_table[];
518
519 // Instance variables to hold the values for command options.
520
521 lldb::pid_t pid;
522 std::string plugin_name;
523 std::string name;
524 bool waitfor;
525 };
526
Greg Clayton238c0a12010-09-18 01:14:36 +0000527 CommandObjectProcessAttach (CommandInterpreter &interpreter) :
528 CommandObject (interpreter,
529 "process attach",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000530 "Attach to a process.",
Jim Ingham7508e732010-08-09 23:31:02 +0000531 "process attach <cmd-options>")
532 {
Jim Ingham7508e732010-08-09 23:31:02 +0000533 }
534
535 ~CommandObjectProcessAttach ()
536 {
537 }
538
539 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000540 Execute (Args& command,
Jim Ingham7508e732010-08-09 23:31:02 +0000541 CommandReturnObject &result)
542 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000543 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Jim Inghamc2dc7c82011-01-29 01:49:25 +0000544 bool synchronous_execution = m_interpreter.GetSynchronous ();
545
Greg Clayton238c0a12010-09-18 01:14:36 +0000546 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Jim Ingham7508e732010-08-09 23:31:02 +0000547 if (process)
548 {
549 if (process->IsAlive())
550 {
551 result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before attaching.\n",
552 process->GetID());
553 result.SetStatus (eReturnStatusFailed);
554 return false;
555 }
556 }
557
558 if (target == NULL)
559 {
560 // If there isn't a current target create one.
561 TargetSP new_target_sp;
562 FileSpec emptyFileSpec;
563 ArchSpec emptyArchSpec;
564 Error error;
565
Greg Clayton238c0a12010-09-18 01:14:36 +0000566 error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(),
567 emptyFileSpec,
568 emptyArchSpec,
569 NULL,
570 false,
571 new_target_sp);
Jim Ingham7508e732010-08-09 23:31:02 +0000572 target = new_target_sp.get();
573 if (target == NULL || error.Fail())
574 {
575 result.AppendError(error.AsCString("Error creating empty target"));
576 return false;
577 }
Greg Clayton238c0a12010-09-18 01:14:36 +0000578 m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target);
Jim Ingham7508e732010-08-09 23:31:02 +0000579 }
580
581 // Record the old executable module, we want to issue a warning if the process of attaching changed the
582 // current executable (like somebody said "file foo" then attached to a PID whose executable was bar.)
583
584 ModuleSP old_exec_module_sp = target->GetExecutableModule();
585 ArchSpec old_arch_spec = target->GetArchitecture();
586
587 if (command.GetArgumentCount())
588 {
589 result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
590 result.SetStatus (eReturnStatusFailed);
591 }
592 else
593 {
594 const char *plugin_name = NULL;
595
596 if (!m_options.plugin_name.empty())
597 plugin_name = m_options.plugin_name.c_str();
598
Greg Clayton238c0a12010-09-18 01:14:36 +0000599 process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
Jim Ingham7508e732010-08-09 23:31:02 +0000600
601 if (process)
602 {
603 Error error;
604 int attach_pid = m_options.pid;
605
Jim Ingham4805a1c2010-09-15 01:34:14 +0000606 const char *wait_name = NULL;
607
608 if (m_options.name.empty())
609 {
610 if (old_exec_module_sp)
611 {
612 wait_name = old_exec_module_sp->GetFileSpec().GetFilename().AsCString();
613 }
614 }
615 else
616 {
617 wait_name = m_options.name.c_str();
618 }
619
Jim Ingham7508e732010-08-09 23:31:02 +0000620 // If we are waiting for a process with this name to show up, do that first.
621 if (m_options.waitfor)
622 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000623
624 if (wait_name == NULL)
Jim Ingham7508e732010-08-09 23:31:02 +0000625 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000626 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 +0000627 result.SetStatus (eReturnStatusFailed);
628 return false;
629 }
Jim Ingham4805a1c2010-09-15 01:34:14 +0000630
Greg Clayton7e2f91c2011-01-29 07:10:55 +0000631 result.AppendMessageWithFormat("Waiting to attach to a process named \"%s\".\n", wait_name);
Jim Ingham4805a1c2010-09-15 01:34:14 +0000632 error = process->Attach (wait_name, m_options.waitfor);
633 if (error.Success())
634 {
635 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
636 }
Jim Ingham7508e732010-08-09 23:31:02 +0000637 else
638 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000639 result.AppendErrorWithFormat ("Waiting for a process to launch named '%s': %s\n",
640 wait_name,
641 error.AsCString());
642 result.SetStatus (eReturnStatusFailed);
643 return false;
Jim Ingham7508e732010-08-09 23:31:02 +0000644 }
Jim Inghamc2dc7c82011-01-29 01:49:25 +0000645 // If we're synchronous, wait for the stopped event and report that.
646 // Otherwise just return.
647 // FIXME: in the async case it will now be possible to get to the command
648 // interpreter with a state eStateAttaching. Make sure we handle that correctly.
649 if (synchronous_execution)
650 {
651 StateType state = process->WaitForProcessToStop (NULL);
652
653 result.SetDidChangeProcessState (true);
654 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
655 result.SetStatus (eReturnStatusSuccessFinishNoResult);
656 }
657 else
658 {
659 result.SetDidChangeProcessState (true);
Jim Inghamc2dc7c82011-01-29 01:49:25 +0000660 result.SetStatus (eReturnStatusSuccessFinishNoResult);
661 }
Jim Ingham7508e732010-08-09 23:31:02 +0000662 }
663 else
664 {
665 // If the process was specified by name look it up, so we can warn if there are multiple
666 // processes with this pid.
667
Jim Ingham4805a1c2010-09-15 01:34:14 +0000668 if (attach_pid == LLDB_INVALID_PROCESS_ID && wait_name != NULL)
Jim Ingham7508e732010-08-09 23:31:02 +0000669 {
670 std::vector<lldb::pid_t> pids;
671 StringList matches;
672
Jim Ingham4805a1c2010-09-15 01:34:14 +0000673 process->ListProcessesMatchingName(wait_name, matches, pids);
Jim Ingham7508e732010-08-09 23:31:02 +0000674 if (matches.GetSize() > 1)
675 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000676 result.AppendErrorWithFormat("More than one process named %s\n", wait_name);
Jim Ingham7508e732010-08-09 23:31:02 +0000677 result.SetStatus (eReturnStatusFailed);
678 return false;
679 }
680 else if (matches.GetSize() == 0)
681 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000682 result.AppendErrorWithFormat("Could not find a process named %s\n", wait_name);
Jim Ingham7508e732010-08-09 23:31:02 +0000683 result.SetStatus (eReturnStatusFailed);
684 return false;
685 }
686 else
687 {
688 attach_pid = pids[0];
689 }
690
691 }
692
693 if (attach_pid != LLDB_INVALID_PROCESS_ID)
694 {
695 error = process->Attach (attach_pid);
696 if (error.Success())
697 {
698 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
699 }
700 else
701 {
702 result.AppendErrorWithFormat ("Attaching to process %i failed: %s.\n",
703 attach_pid,
704 error.AsCString());
705 result.SetStatus (eReturnStatusFailed);
706 }
Jim Inghamc2dc7c82011-01-29 01:49:25 +0000707 // See comment for synchronous_execution above.
708 if (synchronous_execution)
709 {
710 StateType state = process->WaitForProcessToStop (NULL);
711
712 result.SetDidChangeProcessState (true);
713 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
714 result.SetStatus (eReturnStatusSuccessFinishNoResult);
715 }
716 else
717 {
718 result.SetDidChangeProcessState (true);
Jim Inghamc2dc7c82011-01-29 01:49:25 +0000719 result.SetStatus (eReturnStatusSuccessFinishNoResult);
720 }
Jim Ingham7508e732010-08-09 23:31:02 +0000721 }
722 else
723 {
724 result.AppendErrorWithFormat ("No PID specified for attach\n",
725 attach_pid,
726 error.AsCString());
727 result.SetStatus (eReturnStatusFailed);
728
729 }
730 }
731 }
732 }
733
734 if (result.Succeeded())
735 {
736 // Okay, we're done. Last step is to warn if the executable module has changed:
Greg Clayton7e2f91c2011-01-29 07:10:55 +0000737 char new_path[PATH_MAX];
Jim Ingham7508e732010-08-09 23:31:02 +0000738 if (!old_exec_module_sp)
739 {
Greg Clayton7e2f91c2011-01-29 07:10:55 +0000740 // We might not have a module if we attached to a raw pid...
741 ModuleSP new_module_sp (target->GetExecutableModule());
742 if (new_module_sp)
743 {
744 new_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX);
745 result.AppendMessageWithFormat("Executable module set to \"%s\".\n", new_path);
746 }
Jim Ingham7508e732010-08-09 23:31:02 +0000747 }
748 else if (old_exec_module_sp->GetFileSpec() != target->GetExecutableModule()->GetFileSpec())
749 {
Greg Clayton7e2f91c2011-01-29 07:10:55 +0000750 char old_path[PATH_MAX];
Jim Ingham7508e732010-08-09 23:31:02 +0000751
752 old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX);
753 target->GetExecutableModule()->GetFileSpec().GetPath (new_path, PATH_MAX);
754
755 result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n",
756 old_path, new_path);
757 }
758
759 if (!old_arch_spec.IsValid())
760 {
761 result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().AsCString());
762 }
763 else if (old_arch_spec != target->GetArchitecture())
764 {
765 result.AppendWarningWithFormat("Architecture changed from %s to %s.\n",
766 old_arch_spec.AsCString(), target->GetArchitecture().AsCString());
767 }
768 }
769 return result.Succeeded();
770 }
771
772 Options *
773 GetOptions ()
774 {
775 return &m_options;
776 }
777
Chris Lattner24943d22010-06-08 16:52:24 +0000778protected:
779
780 CommandOptions m_options;
781};
782
783
784lldb::OptionDefinition
785CommandObjectProcessAttach::CommandOptions::g_option_table[] =
786{
Caroline Tice4d6675c2010-10-01 19:59:14 +0000787{ LLDB_OPT_SET_ALL, false, "plugin", 'P', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
788{ LLDB_OPT_SET_1, false, "pid", 'p', required_argument, NULL, 0, eArgTypePid, "The process ID of an existing process to attach to."},
789{ LLDB_OPT_SET_2, false, "name", 'n', required_argument, NULL, 0, eArgTypeProcessName, "The name of the process to attach to."},
790{ LLDB_OPT_SET_2, false, "waitfor",'w', no_argument, NULL, 0, eArgTypeNone, "Wait for the the process with <process-name> to launch."},
791{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +0000792};
793
794//-------------------------------------------------------------------------
795// CommandObjectProcessContinue
796//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +0000797#pragma mark CommandObjectProcessContinue
Chris Lattner24943d22010-06-08 16:52:24 +0000798
799class CommandObjectProcessContinue : public CommandObject
800{
801public:
802
Greg Clayton238c0a12010-09-18 01:14:36 +0000803 CommandObjectProcessContinue (CommandInterpreter &interpreter) :
804 CommandObject (interpreter,
805 "process continue",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000806 "Continue execution of all threads in the current process.",
Chris Lattner24943d22010-06-08 16:52:24 +0000807 "process continue",
808 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
809 {
810 }
811
812
813 ~CommandObjectProcessContinue ()
814 {
815 }
816
817 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000818 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000819 CommandReturnObject &result)
820 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000821 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
822 bool synchronous_execution = m_interpreter.GetSynchronous ();
Chris Lattner24943d22010-06-08 16:52:24 +0000823
824 if (process == NULL)
825 {
826 result.AppendError ("no process to continue");
827 result.SetStatus (eReturnStatusFailed);
828 return false;
829 }
830
831 StateType state = process->GetState();
832 if (state == eStateStopped)
833 {
834 if (command.GetArgumentCount() != 0)
835 {
836 result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str());
837 result.SetStatus (eReturnStatusFailed);
838 return false;
839 }
840
841 const uint32_t num_threads = process->GetThreadList().GetSize();
842
843 // Set the actions that the threads should each take when resuming
844 for (uint32_t idx=0; idx<num_threads; ++idx)
845 {
846 process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning);
847 }
848
849 Error error(process->Resume());
850 if (error.Success())
851 {
Greg Claytonc1d37752010-10-18 01:45:30 +0000852 result.AppendMessageWithFormat ("Process %i resuming\n", process->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000853 if (synchronous_execution)
854 {
Greg Claytonbef15832010-07-14 00:18:15 +0000855 state = process->WaitForProcessToStop (NULL);
Chris Lattner24943d22010-06-08 16:52:24 +0000856
857 result.SetDidChangeProcessState (true);
858 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
859 result.SetStatus (eReturnStatusSuccessFinishNoResult);
860 }
861 else
862 {
863 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
864 }
865 }
866 else
867 {
868 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
869 result.SetStatus (eReturnStatusFailed);
870 }
871 }
872 else
873 {
874 result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
875 StateAsCString(state));
876 result.SetStatus (eReturnStatusFailed);
877 }
878 return result.Succeeded();
879 }
880};
881
882//-------------------------------------------------------------------------
883// CommandObjectProcessDetach
884//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +0000885#pragma mark CommandObjectProcessDetach
Chris Lattner24943d22010-06-08 16:52:24 +0000886
887class CommandObjectProcessDetach : public CommandObject
888{
889public:
890
Greg Clayton238c0a12010-09-18 01:14:36 +0000891 CommandObjectProcessDetach (CommandInterpreter &interpreter) :
892 CommandObject (interpreter,
893 "process detach",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000894 "Detach from the current process being debugged.",
Chris Lattner24943d22010-06-08 16:52:24 +0000895 "process detach",
896 eFlagProcessMustBeLaunched)
897 {
898 }
899
900 ~CommandObjectProcessDetach ()
901 {
902 }
903
904 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000905 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000906 CommandReturnObject &result)
907 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000908 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000909 if (process == NULL)
910 {
911 result.AppendError ("must have a valid process in order to detach");
912 result.SetStatus (eReturnStatusFailed);
913 return false;
914 }
915
Caroline Tice90b42252010-11-02 16:16:53 +0000916 result.AppendMessageWithFormat ("Detaching from process %i\n", process->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000917 Error error (process->Detach());
918 if (error.Success())
919 {
920 result.SetStatus (eReturnStatusSuccessFinishResult);
921 }
922 else
923 {
924 result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString());
925 result.SetStatus (eReturnStatusFailed);
926 return false;
927 }
928 return result.Succeeded();
929 }
930};
931
932//-------------------------------------------------------------------------
Greg Clayton0baa3942010-11-04 01:54:29 +0000933// CommandObjectProcessLoad
934//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +0000935#pragma mark CommandObjectProcessLoad
Greg Clayton0baa3942010-11-04 01:54:29 +0000936
937class CommandObjectProcessLoad : public CommandObject
938{
939public:
940
941 CommandObjectProcessLoad (CommandInterpreter &interpreter) :
942 CommandObject (interpreter,
943 "process load",
944 "Load a shared library into the current process.",
945 "process load <filename> [<filename> ...]",
946 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
947 {
948 }
949
950 ~CommandObjectProcessLoad ()
951 {
952 }
953
954 bool
955 Execute (Args& command,
956 CommandReturnObject &result)
957 {
958 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
959 if (process == NULL)
960 {
961 result.AppendError ("must have a valid process in order to load a shared library");
962 result.SetStatus (eReturnStatusFailed);
963 return false;
964 }
965
966 const uint32_t argc = command.GetArgumentCount();
967
968 for (uint32_t i=0; i<argc; ++i)
969 {
970 Error error;
971 const char *image_path = command.GetArgumentAtIndex(i);
972 FileSpec image_spec (image_path, false);
973 uint32_t image_token = process->LoadImage(image_spec, error);
974 if (image_token != LLDB_INVALID_IMAGE_TOKEN)
975 {
976 result.AppendMessageWithFormat ("Loading \"%s\"...ok\nImage %u loaded.\n", image_path, image_token);
977 result.SetStatus (eReturnStatusSuccessFinishResult);
978 }
979 else
980 {
981 result.AppendErrorWithFormat ("failed to load '%s': %s", image_path, error.AsCString());
982 result.SetStatus (eReturnStatusFailed);
983 }
984 }
985 return result.Succeeded();
986 }
987};
988
989
990//-------------------------------------------------------------------------
991// CommandObjectProcessUnload
992//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +0000993#pragma mark CommandObjectProcessUnload
Greg Clayton0baa3942010-11-04 01:54:29 +0000994
995class CommandObjectProcessUnload : public CommandObject
996{
997public:
998
999 CommandObjectProcessUnload (CommandInterpreter &interpreter) :
1000 CommandObject (interpreter,
1001 "process unload",
1002 "Unload a shared library from the current process using the index returned by a previous call to \"process load\".",
1003 "process unload <index>",
1004 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
1005 {
1006 }
1007
1008 ~CommandObjectProcessUnload ()
1009 {
1010 }
1011
1012 bool
1013 Execute (Args& command,
1014 CommandReturnObject &result)
1015 {
1016 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
1017 if (process == NULL)
1018 {
1019 result.AppendError ("must have a valid process in order to load a shared library");
1020 result.SetStatus (eReturnStatusFailed);
1021 return false;
1022 }
1023
1024 const uint32_t argc = command.GetArgumentCount();
1025
1026 for (uint32_t i=0; i<argc; ++i)
1027 {
1028 const char *image_token_cstr = command.GetArgumentAtIndex(i);
1029 uint32_t image_token = Args::StringToUInt32(image_token_cstr, LLDB_INVALID_IMAGE_TOKEN, 0);
1030 if (image_token == LLDB_INVALID_IMAGE_TOKEN)
1031 {
1032 result.AppendErrorWithFormat ("invalid image index argument '%s'", image_token_cstr);
1033 result.SetStatus (eReturnStatusFailed);
1034 break;
1035 }
1036 else
1037 {
1038 Error error (process->UnloadImage(image_token));
1039 if (error.Success())
1040 {
1041 result.AppendMessageWithFormat ("Unloading shared library with index %u...ok\n", image_token);
1042 result.SetStatus (eReturnStatusSuccessFinishResult);
1043 }
1044 else
1045 {
1046 result.AppendErrorWithFormat ("failed to unload image: %s", error.AsCString());
1047 result.SetStatus (eReturnStatusFailed);
1048 break;
1049 }
1050 }
1051 }
1052 return result.Succeeded();
1053 }
1054};
1055
1056//-------------------------------------------------------------------------
Chris Lattner24943d22010-06-08 16:52:24 +00001057// CommandObjectProcessSignal
1058//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +00001059#pragma mark CommandObjectProcessSignal
Chris Lattner24943d22010-06-08 16:52:24 +00001060
1061class CommandObjectProcessSignal : public CommandObject
1062{
1063public:
1064
Greg Clayton238c0a12010-09-18 01:14:36 +00001065 CommandObjectProcessSignal (CommandInterpreter &interpreter) :
1066 CommandObject (interpreter,
1067 "process signal",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001068 "Send a UNIX signal to the current process being debugged.",
Caroline Tice43b014a2010-10-04 22:28:36 +00001069 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +00001070 {
Caroline Tice43b014a2010-10-04 22:28:36 +00001071 CommandArgumentEntry arg;
1072 CommandArgumentData signal_arg;
1073
1074 // Define the first (and only) variant of this arg.
Caroline Tice3a62e6d2010-10-18 22:56:57 +00001075 signal_arg.arg_type = eArgTypeUnixSignal;
Caroline Tice43b014a2010-10-04 22:28:36 +00001076 signal_arg.arg_repetition = eArgRepeatPlain;
1077
1078 // There is only one variant this argument could be; put it into the argument entry.
1079 arg.push_back (signal_arg);
1080
1081 // Push the data for the first argument into the m_arguments vector.
1082 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +00001083 }
1084
1085 ~CommandObjectProcessSignal ()
1086 {
1087 }
1088
1089 bool
Greg Clayton238c0a12010-09-18 01:14:36 +00001090 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +00001091 CommandReturnObject &result)
1092 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001093 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +00001094 if (process == NULL)
1095 {
1096 result.AppendError ("no process to signal");
1097 result.SetStatus (eReturnStatusFailed);
1098 return false;
1099 }
1100
1101 if (command.GetArgumentCount() == 1)
1102 {
Greg Clayton8f6be2a2010-10-09 01:40:57 +00001103 int signo = LLDB_INVALID_SIGNAL_NUMBER;
1104
1105 const char *signal_name = command.GetArgumentAtIndex(0);
1106 if (::isxdigit (signal_name[0]))
1107 signo = Args::StringToSInt32(signal_name, LLDB_INVALID_SIGNAL_NUMBER, 0);
1108 else
1109 signo = process->GetUnixSignals().GetSignalNumberFromName (signal_name);
1110
1111 if (signo == LLDB_INVALID_SIGNAL_NUMBER)
Chris Lattner24943d22010-06-08 16:52:24 +00001112 {
1113 result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0));
1114 result.SetStatus (eReturnStatusFailed);
1115 }
1116 else
1117 {
1118 Error error (process->Signal (signo));
1119 if (error.Success())
1120 {
1121 result.SetStatus (eReturnStatusSuccessFinishResult);
1122 }
1123 else
1124 {
1125 result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString());
1126 result.SetStatus (eReturnStatusFailed);
1127 }
1128 }
1129 }
1130 else
1131 {
1132 result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: \n", m_cmd_name.c_str(),
1133 m_cmd_syntax.c_str());
1134 result.SetStatus (eReturnStatusFailed);
1135 }
1136 return result.Succeeded();
1137 }
1138};
1139
1140
1141//-------------------------------------------------------------------------
1142// CommandObjectProcessInterrupt
1143//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +00001144#pragma mark CommandObjectProcessInterrupt
Chris Lattner24943d22010-06-08 16:52:24 +00001145
1146class CommandObjectProcessInterrupt : public CommandObject
1147{
1148public:
1149
1150
Greg Clayton238c0a12010-09-18 01:14:36 +00001151 CommandObjectProcessInterrupt (CommandInterpreter &interpreter) :
1152 CommandObject (interpreter,
1153 "process interrupt",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001154 "Interrupt the current process being debugged.",
Chris Lattner24943d22010-06-08 16:52:24 +00001155 "process interrupt",
1156 eFlagProcessMustBeLaunched)
1157 {
1158 }
1159
1160 ~CommandObjectProcessInterrupt ()
1161 {
1162 }
1163
1164 bool
Greg Clayton238c0a12010-09-18 01:14:36 +00001165 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +00001166 CommandReturnObject &result)
1167 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001168 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +00001169 if (process == NULL)
1170 {
1171 result.AppendError ("no process to halt");
1172 result.SetStatus (eReturnStatusFailed);
1173 return false;
1174 }
1175
1176 if (command.GetArgumentCount() == 0)
1177 {
1178 Error error(process->Halt ());
1179 if (error.Success())
1180 {
1181 result.SetStatus (eReturnStatusSuccessFinishResult);
1182
1183 // Maybe we should add a "SuspendThreadPlans so we
1184 // can halt, and keep in place all the current thread plans.
1185 process->GetThreadList().DiscardThreadPlans();
1186 }
1187 else
1188 {
1189 result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString());
1190 result.SetStatus (eReturnStatusFailed);
1191 }
1192 }
1193 else
1194 {
1195 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
1196 m_cmd_name.c_str(),
1197 m_cmd_syntax.c_str());
1198 result.SetStatus (eReturnStatusFailed);
1199 }
1200 return result.Succeeded();
1201 }
1202};
1203
1204//-------------------------------------------------------------------------
1205// CommandObjectProcessKill
1206//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +00001207#pragma mark CommandObjectProcessKill
Chris Lattner24943d22010-06-08 16:52:24 +00001208
1209class CommandObjectProcessKill : public CommandObject
1210{
1211public:
1212
Greg Clayton238c0a12010-09-18 01:14:36 +00001213 CommandObjectProcessKill (CommandInterpreter &interpreter) :
1214 CommandObject (interpreter,
1215 "process kill",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001216 "Terminate the current process being debugged.",
Chris Lattner24943d22010-06-08 16:52:24 +00001217 "process kill",
1218 eFlagProcessMustBeLaunched)
1219 {
1220 }
1221
1222 ~CommandObjectProcessKill ()
1223 {
1224 }
1225
1226 bool
Greg Clayton238c0a12010-09-18 01:14:36 +00001227 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +00001228 CommandReturnObject &result)
1229 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001230 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +00001231 if (process == NULL)
1232 {
1233 result.AppendError ("no process to kill");
1234 result.SetStatus (eReturnStatusFailed);
1235 return false;
1236 }
1237
1238 if (command.GetArgumentCount() == 0)
1239 {
1240 Error error (process->Destroy());
1241 if (error.Success())
1242 {
1243 result.SetStatus (eReturnStatusSuccessFinishResult);
1244 }
1245 else
1246 {
1247 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString());
1248 result.SetStatus (eReturnStatusFailed);
1249 }
1250 }
1251 else
1252 {
1253 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
1254 m_cmd_name.c_str(),
1255 m_cmd_syntax.c_str());
1256 result.SetStatus (eReturnStatusFailed);
1257 }
1258 return result.Succeeded();
1259 }
1260};
1261
1262//-------------------------------------------------------------------------
Jim Ingham41313fc2010-06-18 01:23:09 +00001263// CommandObjectProcessStatus
1264//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +00001265#pragma mark CommandObjectProcessStatus
1266
Jim Ingham41313fc2010-06-18 01:23:09 +00001267class CommandObjectProcessStatus : public CommandObject
1268{
1269public:
Greg Clayton238c0a12010-09-18 01:14:36 +00001270 CommandObjectProcessStatus (CommandInterpreter &interpreter) :
1271 CommandObject (interpreter,
1272 "process status",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001273 "Show the current status and location of executing process.",
1274 "process status",
Jim Ingham41313fc2010-06-18 01:23:09 +00001275 0)
1276 {
1277 }
1278
1279 ~CommandObjectProcessStatus()
1280 {
1281 }
1282
1283
1284 bool
1285 Execute
1286 (
1287 Args& command,
Jim Ingham41313fc2010-06-18 01:23:09 +00001288 CommandReturnObject &result
1289 )
1290 {
1291 StreamString &output_stream = result.GetOutputStream();
1292 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Greg Clayton238c0a12010-09-18 01:14:36 +00001293 ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
Jim Ingham41313fc2010-06-18 01:23:09 +00001294 if (exe_ctx.process)
1295 {
1296 const StateType state = exe_ctx.process->GetState();
1297 if (StateIsStoppedState(state))
1298 {
1299 if (state == eStateExited)
1300 {
1301 int exit_status = exe_ctx.process->GetExitStatus();
1302 const char *exit_description = exe_ctx.process->GetExitDescription();
1303 output_stream.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n",
1304 exe_ctx.process->GetID(),
1305 exit_status,
1306 exit_status,
1307 exit_description ? exit_description : "");
1308 }
1309 else
1310 {
1311 output_stream.Printf ("Process %d %s\n", exe_ctx.process->GetID(), StateAsCString (state));
1312 if (exe_ctx.thread == NULL)
1313 exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
1314 if (exe_ctx.thread != NULL)
1315 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001316 DisplayThreadsInfo (m_interpreter, &exe_ctx, result, true, true);
Jim Ingham41313fc2010-06-18 01:23:09 +00001317 }
1318 else
1319 {
1320 result.AppendError ("No valid thread found in current process.");
1321 result.SetStatus (eReturnStatusFailed);
1322 }
1323 }
1324 }
1325 else
1326 {
1327 output_stream.Printf ("Process %d is running.\n",
1328 exe_ctx.process->GetID());
1329 }
1330 }
1331 else
1332 {
1333 result.AppendError ("No current location or status available.");
1334 result.SetStatus (eReturnStatusFailed);
1335 }
1336 return result.Succeeded();
1337 }
1338};
1339
1340//-------------------------------------------------------------------------
Caroline Tice23d6f272010-10-13 20:44:39 +00001341// CommandObjectProcessHandle
1342//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +00001343#pragma mark CommandObjectProcessHandle
Caroline Tice23d6f272010-10-13 20:44:39 +00001344
1345class CommandObjectProcessHandle : public CommandObject
1346{
1347public:
1348
1349 class CommandOptions : public Options
1350 {
1351 public:
1352
1353 CommandOptions () :
1354 Options ()
1355 {
1356 ResetOptionValues ();
1357 }
1358
1359 ~CommandOptions ()
1360 {
1361 }
1362
1363 Error
1364 SetOptionValue (int option_idx, const char *option_arg)
1365 {
1366 Error error;
1367 char short_option = (char) m_getopt_table[option_idx].val;
1368
1369 switch (short_option)
1370 {
1371 case 's':
1372 stop = option_arg;
1373 break;
1374 case 'n':
1375 notify = option_arg;
1376 break;
1377 case 'p':
1378 pass = option_arg;
1379 break;
1380 default:
1381 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
1382 break;
1383 }
1384 return error;
1385 }
1386
1387 void
1388 ResetOptionValues ()
1389 {
1390 Options::ResetOptionValues();
1391 stop.clear();
1392 notify.clear();
1393 pass.clear();
1394 }
1395
1396 const lldb::OptionDefinition*
1397 GetDefinitions ()
1398 {
1399 return g_option_table;
1400 }
1401
1402 // Options table: Required for subclasses of Options.
1403
1404 static lldb::OptionDefinition g_option_table[];
1405
1406 // Instance variables to hold the values for command options.
1407
1408 std::string stop;
1409 std::string notify;
1410 std::string pass;
1411 };
1412
1413
1414 CommandObjectProcessHandle (CommandInterpreter &interpreter) :
1415 CommandObject (interpreter,
1416 "process handle",
Caroline Ticee7471982010-10-14 21:31:13 +00001417 "Show or update what the process and debugger should do with various signals received from the OS.",
Caroline Tice23d6f272010-10-13 20:44:39 +00001418 NULL)
1419 {
Caroline Ticee7471982010-10-14 21:31:13 +00001420 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 +00001421 CommandArgumentEntry arg;
Caroline Tice3a62e6d2010-10-18 22:56:57 +00001422 CommandArgumentData signal_arg;
Caroline Tice23d6f272010-10-13 20:44:39 +00001423
Caroline Tice3a62e6d2010-10-18 22:56:57 +00001424 signal_arg.arg_type = eArgTypeUnixSignal;
1425 signal_arg.arg_repetition = eArgRepeatStar;
Caroline Tice23d6f272010-10-13 20:44:39 +00001426
Caroline Tice3a62e6d2010-10-18 22:56:57 +00001427 arg.push_back (signal_arg);
Caroline Tice23d6f272010-10-13 20:44:39 +00001428
1429 m_arguments.push_back (arg);
1430 }
1431
1432 ~CommandObjectProcessHandle ()
1433 {
1434 }
1435
1436 Options *
1437 GetOptions ()
1438 {
1439 return &m_options;
1440 }
1441
1442 bool
Caroline Ticee7471982010-10-14 21:31:13 +00001443 VerifyCommandOptionValue (const std::string &option, int &real_value)
Caroline Tice23d6f272010-10-13 20:44:39 +00001444 {
1445 bool okay = true;
1446
Caroline Ticee7471982010-10-14 21:31:13 +00001447 bool success = false;
1448 bool tmp_value = Args::StringToBoolean (option.c_str(), false, &success);
1449
1450 if (success && tmp_value)
1451 real_value = 1;
1452 else if (success && !tmp_value)
1453 real_value = 0;
Caroline Tice23d6f272010-10-13 20:44:39 +00001454 else
1455 {
1456 // If the value isn't 'true' or 'false', it had better be 0 or 1.
Caroline Ticee7471982010-10-14 21:31:13 +00001457 real_value = Args::StringToUInt32 (option.c_str(), 3);
1458 if (real_value != 0 && real_value != 1)
Caroline Tice23d6f272010-10-13 20:44:39 +00001459 okay = false;
1460 }
1461
1462 return okay;
1463 }
1464
Caroline Ticee7471982010-10-14 21:31:13 +00001465 void
1466 PrintSignalHeader (Stream &str)
1467 {
1468 str.Printf ("NAME PASS STOP NOTIFY\n");
1469 str.Printf ("========== ===== ===== ======\n");
1470 }
1471
1472 void
1473 PrintSignal (Stream &str, int32_t signo, const char *sig_name, UnixSignals &signals)
1474 {
1475 bool stop;
1476 bool suppress;
1477 bool notify;
1478
1479 str.Printf ("%-10s ", sig_name);
1480 if (signals.GetSignalInfo (signo, suppress, stop, notify))
1481 {
1482 bool pass = !suppress;
1483 str.Printf ("%s %s %s",
1484 (pass ? "true " : "false"),
1485 (stop ? "true " : "false"),
1486 (notify ? "true " : "false"));
1487 }
1488 str.Printf ("\n");
1489 }
1490
1491 void
1492 PrintSignalInformation (Stream &str, Args &signal_args, int num_valid_signals, UnixSignals &signals)
1493 {
1494 PrintSignalHeader (str);
1495
1496 if (num_valid_signals > 0)
1497 {
1498 size_t num_args = signal_args.GetArgumentCount();
1499 for (size_t i = 0; i < num_args; ++i)
1500 {
1501 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
1502 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
1503 PrintSignal (str, signo, signal_args.GetArgumentAtIndex (i), signals);
1504 }
1505 }
1506 else // Print info for ALL signals
1507 {
1508 int32_t signo = signals.GetFirstSignalNumber();
1509 while (signo != LLDB_INVALID_SIGNAL_NUMBER)
1510 {
1511 PrintSignal (str, signo, signals.GetSignalAsCString (signo), signals);
1512 signo = signals.GetNextSignalNumber (signo);
1513 }
1514 }
1515 }
1516
Caroline Tice23d6f272010-10-13 20:44:39 +00001517 bool
1518 Execute (Args &signal_args, CommandReturnObject &result)
1519 {
1520 TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
1521
1522 if (!target_sp)
1523 {
1524 result.AppendError ("No current target;"
1525 " cannot handle signals until you have a valid target and process.\n");
1526 result.SetStatus (eReturnStatusFailed);
1527 return false;
1528 }
1529
1530 ProcessSP process_sp = target_sp->GetProcessSP();
1531
1532 if (!process_sp)
1533 {
1534 result.AppendError ("No current process; cannot handle signals until you have a valid process.\n");
1535 result.SetStatus (eReturnStatusFailed);
1536 return false;
1537 }
1538
Caroline Tice23d6f272010-10-13 20:44:39 +00001539 int stop_action = -1; // -1 means leave the current setting alone
Caroline Ticee7471982010-10-14 21:31:13 +00001540 int pass_action = -1; // -1 means leave the current setting alone
Caroline Tice23d6f272010-10-13 20:44:39 +00001541 int notify_action = -1; // -1 means leave the current setting alone
1542
1543 if (! m_options.stop.empty()
Caroline Ticee7471982010-10-14 21:31:13 +00001544 && ! VerifyCommandOptionValue (m_options.stop, stop_action))
Caroline Tice23d6f272010-10-13 20:44:39 +00001545 {
1546 result.AppendError ("Invalid argument for command option --stop; must be true or false.\n");
1547 result.SetStatus (eReturnStatusFailed);
1548 return false;
1549 }
1550
1551 if (! m_options.notify.empty()
Caroline Ticee7471982010-10-14 21:31:13 +00001552 && ! VerifyCommandOptionValue (m_options.notify, notify_action))
Caroline Tice23d6f272010-10-13 20:44:39 +00001553 {
1554 result.AppendError ("Invalid argument for command option --notify; must be true or false.\n");
1555 result.SetStatus (eReturnStatusFailed);
1556 return false;
1557 }
1558
1559 if (! m_options.pass.empty()
Caroline Ticee7471982010-10-14 21:31:13 +00001560 && ! VerifyCommandOptionValue (m_options.pass, pass_action))
Caroline Tice23d6f272010-10-13 20:44:39 +00001561 {
1562 result.AppendError ("Invalid argument for command option --pass; must be true or false.\n");
1563 result.SetStatus (eReturnStatusFailed);
1564 return false;
1565 }
1566
1567 size_t num_args = signal_args.GetArgumentCount();
1568 UnixSignals &signals = process_sp->GetUnixSignals();
1569 int num_signals_set = 0;
1570
Caroline Ticee7471982010-10-14 21:31:13 +00001571 if (num_args > 0)
Caroline Tice23d6f272010-10-13 20:44:39 +00001572 {
Caroline Ticee7471982010-10-14 21:31:13 +00001573 for (size_t i = 0; i < num_args; ++i)
Caroline Tice23d6f272010-10-13 20:44:39 +00001574 {
Caroline Ticee7471982010-10-14 21:31:13 +00001575 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
1576 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
Caroline Tice23d6f272010-10-13 20:44:39 +00001577 {
Caroline Ticee7471982010-10-14 21:31:13 +00001578 // Casting the actions as bools here should be okay, because VerifyCommandOptionValue guarantees
1579 // the value is either 0 or 1.
1580 if (stop_action != -1)
1581 signals.SetShouldStop (signo, (bool) stop_action);
1582 if (pass_action != -1)
1583 {
1584 bool suppress = ! ((bool) pass_action);
1585 signals.SetShouldSuppress (signo, suppress);
1586 }
1587 if (notify_action != -1)
1588 signals.SetShouldNotify (signo, (bool) notify_action);
1589 ++num_signals_set;
Caroline Tice23d6f272010-10-13 20:44:39 +00001590 }
Caroline Ticee7471982010-10-14 21:31:13 +00001591 else
1592 {
1593 result.AppendErrorWithFormat ("Invalid signal name '%s'\n", signal_args.GetArgumentAtIndex (i));
1594 }
Caroline Tice23d6f272010-10-13 20:44:39 +00001595 }
1596 }
Caroline Ticee7471982010-10-14 21:31:13 +00001597 else
1598 {
1599 // No signal specified, if any command options were specified, update ALL signals.
1600 if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1))
1601 {
1602 if (m_interpreter.Confirm ("Do you really want to update all the signals?", false))
1603 {
1604 int32_t signo = signals.GetFirstSignalNumber();
1605 while (signo != LLDB_INVALID_SIGNAL_NUMBER)
1606 {
1607 if (notify_action != -1)
1608 signals.SetShouldNotify (signo, (bool) notify_action);
1609 if (stop_action != -1)
1610 signals.SetShouldStop (signo, (bool) stop_action);
1611 if (pass_action != -1)
1612 {
1613 bool suppress = ! ((bool) pass_action);
1614 signals.SetShouldSuppress (signo, suppress);
1615 }
1616 signo = signals.GetNextSignalNumber (signo);
1617 }
1618 }
1619 }
1620 }
1621
1622 PrintSignalInformation (result.GetOutputStream(), signal_args, num_signals_set, signals);
Caroline Tice23d6f272010-10-13 20:44:39 +00001623
1624 if (num_signals_set > 0)
1625 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1626 else
1627 result.SetStatus (eReturnStatusFailed);
1628
1629 return result.Succeeded();
1630 }
1631
1632protected:
1633
1634 CommandOptions m_options;
1635};
1636
1637lldb::OptionDefinition
1638CommandObjectProcessHandle::CommandOptions::g_option_table[] =
1639{
1640{ 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." },
1641{ 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." },
1642{ LLDB_OPT_SET_1, false, "pass", 'p', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." },
1643{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1644};
1645
1646//-------------------------------------------------------------------------
Chris Lattner24943d22010-06-08 16:52:24 +00001647// CommandObjectMultiwordProcess
1648//-------------------------------------------------------------------------
1649
Greg Clayton63094e02010-06-23 01:19:29 +00001650CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001651 CommandObjectMultiword (interpreter,
1652 "process",
1653 "A set of commands for operating on a process.",
1654 "process <subcommand> [<subcommand-options>]")
Chris Lattner24943d22010-06-08 16:52:24 +00001655{
Greg Clayton238c0a12010-09-18 01:14:36 +00001656 LoadSubCommand ("attach", CommandObjectSP (new CommandObjectProcessAttach (interpreter)));
1657 LoadSubCommand ("launch", CommandObjectSP (new CommandObjectProcessLaunch (interpreter)));
1658 LoadSubCommand ("continue", CommandObjectSP (new CommandObjectProcessContinue (interpreter)));
1659 LoadSubCommand ("detach", CommandObjectSP (new CommandObjectProcessDetach (interpreter)));
Greg Clayton0baa3942010-11-04 01:54:29 +00001660 LoadSubCommand ("load", CommandObjectSP (new CommandObjectProcessLoad (interpreter)));
1661 LoadSubCommand ("unload", CommandObjectSP (new CommandObjectProcessUnload (interpreter)));
Greg Clayton238c0a12010-09-18 01:14:36 +00001662 LoadSubCommand ("signal", CommandObjectSP (new CommandObjectProcessSignal (interpreter)));
Caroline Tice23d6f272010-10-13 20:44:39 +00001663 LoadSubCommand ("handle", CommandObjectSP (new CommandObjectProcessHandle (interpreter)));
Greg Clayton238c0a12010-09-18 01:14:36 +00001664 LoadSubCommand ("status", CommandObjectSP (new CommandObjectProcessStatus (interpreter)));
1665 LoadSubCommand ("interrupt", CommandObjectSP (new CommandObjectProcessInterrupt (interpreter)));
1666 LoadSubCommand ("kill", CommandObjectSP (new CommandObjectProcessKill (interpreter)));
Chris Lattner24943d22010-06-08 16:52:24 +00001667}
1668
1669CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess ()
1670{
1671}
1672