blob: ae6984e0f0a713bf13e3e9127451dff5169382b3 [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"
Greg Claytonabe0fed2011-04-18 08:33:37 +000019#include "lldb/Host/Host.h"
Chris Lattner24943d22010-06-08 16:52:24 +000020#include "lldb/Interpreter/CommandInterpreter.h"
21#include "lldb/Interpreter/CommandReturnObject.h"
Greg Claytone4b9c1f2011-03-08 22:40:15 +000022#include "lldb/Target/Platform.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
Greg Clayton36bc5ea2011-11-03 21:22:33 +000038// class CommandOptions : public Options
39// {
40// public:
41//
42// CommandOptions (CommandInterpreter &interpreter) :
43// Options(interpreter)
44// {
45// // Keep default values of all options in one place: OptionParsingStarting ()
46// OptionParsingStarting ();
47// }
48//
49// ~CommandOptions ()
50// {
51// }
52//
53// Error
54// SetOptionValue (uint32_t 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// {
61// 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;
68// case 't':
69// if (option_arg && option_arg[0])
70// tty_name.assign (option_arg);
71// in_new_tty = true;
72// break;
73// default:
74// error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
75// break;
76//
77// }
78// return error;
79// }
80//
81// void
82// OptionParsingStarting ()
83// {
84// stop_at_entry = false;
85// in_new_tty = false;
86// tty_name.clear();
87// stdin_path.clear();
88// stdout_path.clear();
89// stderr_path.clear();
90// plugin_name.clear();
91// working_dir.clear();
92// no_stdio = false;
93// }
94//
95// const OptionDefinition*
96// GetDefinitions ()
97// {
98// return g_option_table;
99// }
100//
101// // Options table: Required for subclasses of Options.
102//
103// static OptionDefinition g_option_table[];
104//
105// // Instance variables to hold the values for command options.
106//
107// bool stop_at_entry;
108// bool in_new_tty;
109// bool no_stdio;
110// std::string tty_name;
111// std::string stderr_path;
112// std::string stdin_path;
113// std::string stdout_path;
114// std::string plugin_name;
115// std::string working_dir;
116//
117// };
Chris Lattner24943d22010-06-08 16:52:24 +0000118
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.",
Greg Claytonf15996e2011-04-07 22:46:35 +0000123 NULL),
124 m_options (interpreter)
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 Claytonabb33022011-11-08 02:43:13 +0000154 Debugger &debugger = m_interpreter.GetDebugger();
155 Target *target = debugger.GetSelectedTarget().get();
156 Error error;
Chris Lattner24943d22010-06-08 16:52:24 +0000157
158 if (target == NULL)
159 {
Greg Claytone1f50b92011-05-03 22:09:39 +0000160 result.AppendError ("invalid target, create a debug target using the 'target create' command");
Chris Lattner24943d22010-06-08 16:52:24 +0000161 result.SetStatus (eReturnStatusFailed);
162 return false;
163 }
Chris Lattner24943d22010-06-08 16:52:24 +0000164 // If our listener is NULL, users aren't allows to launch
Chris Lattner24943d22010-06-08 16:52:24 +0000165 char filename[PATH_MAX];
Greg Clayton5beb99d2011-08-11 02:48:45 +0000166 const Module *exe_module = target->GetExecutableModulePointer();
Greg Claytona2f74232011-02-24 22:24:29 +0000167
168 if (exe_module == NULL)
169 {
Greg Claytone1f50b92011-05-03 22:09:39 +0000170 result.AppendError ("no file in target, create a debug target using the 'target create' command");
Greg Claytona2f74232011-02-24 22:24:29 +0000171 result.SetStatus (eReturnStatusFailed);
172 return false;
173 }
174
Greg Clayton36bc5ea2011-11-03 21:22:33 +0000175 exe_module->GetFileSpec().GetPath (filename, sizeof(filename));
Chris Lattner24943d22010-06-08 16:52:24 +0000176
Greg Clayton36bc5ea2011-11-03 21:22:33 +0000177 const bool add_exe_file_as_first_arg = true;
178 m_options.launch_info.SetExecutableFile(exe_module->GetFileSpec(), add_exe_file_as_first_arg);
179
Greg Claytona2f74232011-02-24 22:24:29 +0000180 StateType state = eStateInvalid;
Greg Clayton567e7f32011-09-22 04:58:26 +0000181 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Greg Claytona2f74232011-02-24 22:24:29 +0000182 if (process)
183 {
184 state = process->GetState();
185
186 if (process->IsAlive() && state != eStateConnected)
187 {
188 char message[1024];
189 if (process->GetState() == eStateAttaching)
190 ::strncpy (message, "There is a pending attach, abort it and launch a new process?", sizeof(message));
191 else
192 ::strncpy (message, "There is a running process, kill it and restart?", sizeof(message));
193
194 if (!m_interpreter.Confirm (message, true))
Jim Ingham22dc9722010-12-09 18:58:16 +0000195 {
Greg Claytona2f74232011-02-24 22:24:29 +0000196 result.SetStatus (eReturnStatusFailed);
197 return false;
Jim Ingham22dc9722010-12-09 18:58:16 +0000198 }
199 else
200 {
Greg Claytonabb33022011-11-08 02:43:13 +0000201 Error destroy_error (process->Destroy());
202 if (destroy_error.Success())
Greg Claytona2f74232011-02-24 22:24:29 +0000203 {
204 result.SetStatus (eReturnStatusSuccessFinishResult);
205 }
206 else
207 {
Greg Claytonabb33022011-11-08 02:43:13 +0000208 result.AppendErrorWithFormat ("Failed to kill process: %s\n", destroy_error.AsCString());
Greg Claytona2f74232011-02-24 22:24:29 +0000209 result.SetStatus (eReturnStatusFailed);
210 }
Jim Ingham22dc9722010-12-09 18:58:16 +0000211 }
212 }
Chris Lattner24943d22010-06-08 16:52:24 +0000213 }
Jim Ingham22dc9722010-12-09 18:58:16 +0000214
Greg Claytonabb33022011-11-08 02:43:13 +0000215 if (launch_args.GetArgumentCount() > 0)
216 {
217 m_options.launch_info.GetArguments().AppendArguments (launch_args);
218 }
219
220
221 if (state == eStateConnected)
222 {
223 if (m_options.launch_info.GetFlags().Test (eLaunchFlagLaunchInTTY))
224 {
225 result.AppendWarning("can't launch in tty when launching through a remote connection");
226 m_options.launch_info.GetFlags().Clear (eLaunchFlagLaunchInTTY);
227 }
228 }
229 else
Caroline Tice6e4c5ce2010-09-04 00:03:46 +0000230 {
Greg Clayton36bc5ea2011-11-03 21:22:33 +0000231 const char *plugin_name = m_options.launch_info.GetProcessPluginName();
Greg Claytona2f74232011-02-24 22:24:29 +0000232
Greg Claytonabb33022011-11-08 02:43:13 +0000233 if (m_options.launch_info.GetFlags().Test (eLaunchFlagLaunchInTTY))
234 {
235 process = target->GetPlatform()->DebugProcess (m_options.launch_info,
236 debugger,
237 target,
238 debugger.GetListener(),
239 error).get();
240 }
241 else
242 {
243 process = target->CreateProcess (debugger.GetListener(), plugin_name).get();
244
245 if (launch_args.GetArgumentCount() == 0)
246 {
247 const Args &process_args = target->GetRunArguments();
248 if (process_args.GetArgumentCount() > 0)
249 m_options.launch_info.GetArguments().AppendArguments (process_args);
250 }
251
252 Args environment;
253 target->GetEnvironmentAsArgs (environment);
254 m_options.launch_info.GetEnvironmentEntries ().AppendArguments (environment);
255
256 if (target->GetDisableASLR())
257 m_options.launch_info.GetFlags().Set (eLaunchFlagDisableASLR);
258
259 if (m_options.launch_info.GetNumFileActions() == 0)
260 {
261 // Only use the settings value if the user hasn't specified any options that would override it.
262 if (target->GetDisableSTDIO())
263 m_options.launch_info.GetFlags().Set (eLaunchFlagDisableSTDIO);
264
265 const char *path;
266 path = target->GetStandardErrorPath();
267 if (path)
268 {
269 ProcessLaunchInfo::FileAction file_action;
270 const bool read = true;
271 const bool write = true;
272 if (file_action.Open(STDERR_FILENO, path, read, write))
273 m_options.launch_info.AppendFileAction (file_action);
274 }
275 path = target->GetStandardInputPath();
276 if (path)
277 {
278 ProcessLaunchInfo::FileAction file_action;
279 const bool read = true;
280 const bool write = false;
281 if (file_action.Open(STDIN_FILENO, path, read, write))
282 m_options.launch_info.AppendFileAction (file_action);
283 }
284
285 path = target->GetStandardOutputPath();
286 if (path)
287 {
288 ProcessLaunchInfo::FileAction file_action;
289 const bool read = false;
290 const bool write = true;
291 if (file_action.Open(STDOUT_FILENO, path, read, write))
292 m_options.launch_info.AppendFileAction (file_action);
293 }
294 }
295 error = process->Launch (m_options.launch_info);
296 }
Greg Claytona2f74232011-02-24 22:24:29 +0000297 if (process == NULL)
298 {
299 result.AppendErrorWithFormat ("Failed to find a process plugin for executable.\n");
300 result.SetStatus (eReturnStatusFailed);
301 return false;
302 }
Chris Lattner24943d22010-06-08 16:52:24 +0000303 }
Greg Claytonabb33022011-11-08 02:43:13 +0000304
Greg Clayton238c0a12010-09-18 01:14:36 +0000305 if (error.Success())
306 {
Greg Clayton940b1032011-02-23 00:35:02 +0000307 const char *archname = exe_module->GetArchitecture().GetArchitectureName();
Greg Claytonc1d37752010-10-18 01:45:30 +0000308
Greg Clayton444e35b2011-10-19 18:09:39 +0000309 result.AppendMessageWithFormat ("Process %llu launched: '%s' (%s)\n", process->GetID(), filename, archname);
Greg Claytond8c62532010-10-07 04:19:01 +0000310 result.SetDidChangeProcessState (true);
Greg Clayton36bc5ea2011-11-03 21:22:33 +0000311 if (m_options.launch_info.GetFlags().Test(eLaunchFlagStopAtEntry) == false)
Greg Clayton238c0a12010-09-18 01:14:36 +0000312 {
Greg Claytond8c62532010-10-07 04:19:01 +0000313 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
Greg Clayton238c0a12010-09-18 01:14:36 +0000314 StateType state = process->WaitForProcessToStop (NULL);
315
316 if (state == eStateStopped)
317 {
Greg Claytond8c62532010-10-07 04:19:01 +0000318 error = process->Resume();
319 if (error.Success())
320 {
321 bool synchronous_execution = m_interpreter.GetSynchronous ();
322 if (synchronous_execution)
323 {
324 state = process->WaitForProcessToStop (NULL);
Greg Clayton940b1032011-02-23 00:35:02 +0000325 if (!StateIsStoppedState(state))
Greg Clayton395fc332011-02-15 21:59:32 +0000326 {
327 result.AppendErrorWithFormat ("Process isn't stopped: %s", StateAsCString(state));
328 }
Greg Claytond8c62532010-10-07 04:19:01 +0000329 result.SetDidChangeProcessState (true);
330 result.SetStatus (eReturnStatusSuccessFinishResult);
331 }
332 else
333 {
334 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
335 }
336 }
Greg Clayton395fc332011-02-15 21:59:32 +0000337 else
338 {
339 result.AppendErrorWithFormat ("Process resume at entry point failed: %s", error.AsCString());
340 result.SetStatus (eReturnStatusFailed);
341 }
Greg Clayton238c0a12010-09-18 01:14:36 +0000342 }
Greg Clayton395fc332011-02-15 21:59:32 +0000343 else
344 {
345 result.AppendErrorWithFormat ("Initial process state wasn't stopped: %s", StateAsCString(state));
346 result.SetStatus (eReturnStatusFailed);
347 }
Greg Clayton238c0a12010-09-18 01:14:36 +0000348 }
349 }
Greg Clayton395fc332011-02-15 21:59:32 +0000350 else
351 {
Greg Claytona9eb8272011-07-02 21:07:54 +0000352 result.AppendErrorWithFormat ("process launch failed: %s", error.AsCString());
Greg Clayton395fc332011-02-15 21:59:32 +0000353 result.SetStatus (eReturnStatusFailed);
354 }
Greg Clayton238c0a12010-09-18 01:14:36 +0000355
Chris Lattner24943d22010-06-08 16:52:24 +0000356 return result.Succeeded();
357 }
358
Jim Ingham767af882010-07-07 03:36:20 +0000359 virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
360 {
361 // No repeat for "process launch"...
362 return "";
363 }
364
Chris Lattner24943d22010-06-08 16:52:24 +0000365protected:
Greg Clayton36bc5ea2011-11-03 21:22:33 +0000366 ProcessLaunchCommandOptions m_options;
Chris Lattner24943d22010-06-08 16:52:24 +0000367};
368
369
Greg Clayton36bc5ea2011-11-03 21:22:33 +0000370//#define SET1 LLDB_OPT_SET_1
371//#define SET2 LLDB_OPT_SET_2
372//#define SET3 LLDB_OPT_SET_3
373//
374//OptionDefinition
375//CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
376//{
377//{ 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."},
378//{ SET1 , false, "stdin", 'i', required_argument, NULL, 0, eArgTypePath, "Redirect stdin for the process to <path>."},
379//{ SET1 , false, "stdout", 'o', required_argument, NULL, 0, eArgTypePath, "Redirect stdout for the process to <path>."},
380//{ SET1 , false, "stderr", 'e', required_argument, NULL, 0, eArgTypePath, "Redirect stderr for the process to <path>."},
381//{ SET1 | SET2 | SET3, false, "plugin", 'p', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
382//{ 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."},
383//{ SET3, false, "no-stdio", 'n', no_argument, NULL, 0, eArgTypeNone, "Do not set up for terminal I/O to go to running process."},
384//{ SET1 | SET2 | SET3, false, "working-dir", 'w', required_argument, NULL, 0, eArgTypePath, "Set the current working directory to <path> when running the inferior."},
385//{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
386//};
387//
388//#undef SET1
389//#undef SET2
390//#undef SET3
Chris Lattner24943d22010-06-08 16:52:24 +0000391
392//-------------------------------------------------------------------------
393// CommandObjectProcessAttach
394//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +0000395#pragma mark CommandObjectProcessAttach
Chris Lattner24943d22010-06-08 16:52:24 +0000396class CommandObjectProcessAttach : public CommandObject
397{
398public:
399
Chris Lattner24943d22010-06-08 16:52:24 +0000400 class CommandOptions : public Options
401 {
402 public:
403
Greg Claytonf15996e2011-04-07 22:46:35 +0000404 CommandOptions (CommandInterpreter &interpreter) :
405 Options(interpreter)
Chris Lattner24943d22010-06-08 16:52:24 +0000406 {
Greg Clayton143fcc32011-04-13 00:18:08 +0000407 // Keep default values of all options in one place: OptionParsingStarting ()
408 OptionParsingStarting ();
Chris Lattner24943d22010-06-08 16:52:24 +0000409 }
410
411 ~CommandOptions ()
412 {
413 }
414
415 Error
Greg Clayton143fcc32011-04-13 00:18:08 +0000416 SetOptionValue (uint32_t option_idx, const char *option_arg)
Chris Lattner24943d22010-06-08 16:52:24 +0000417 {
418 Error error;
419 char short_option = (char) m_getopt_table[option_idx].val;
420 bool success = false;
421 switch (short_option)
422 {
423 case 'p':
424 pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success);
425 if (!success || pid == LLDB_INVALID_PROCESS_ID)
426 {
Greg Clayton9c236732011-10-26 00:56:27 +0000427 error.SetErrorStringWithFormat("invalid process ID '%s'", option_arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000428 }
429 break;
430
431 case 'P':
432 plugin_name = option_arg;
433 break;
434
435 case 'n':
436 name.assign(option_arg);
437 break;
438
439 case 'w':
440 waitfor = true;
441 break;
442
443 default:
Greg Clayton9c236732011-10-26 00:56:27 +0000444 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
Chris Lattner24943d22010-06-08 16:52:24 +0000445 break;
446 }
447 return error;
448 }
449
450 void
Greg Clayton143fcc32011-04-13 00:18:08 +0000451 OptionParsingStarting ()
Chris Lattner24943d22010-06-08 16:52:24 +0000452 {
Chris Lattner24943d22010-06-08 16:52:24 +0000453 pid = LLDB_INVALID_PROCESS_ID;
454 name.clear();
455 waitfor = false;
456 }
457
Greg Claytonb3448432011-03-24 21:19:54 +0000458 const OptionDefinition*
Chris Lattner24943d22010-06-08 16:52:24 +0000459 GetDefinitions ()
460 {
461 return g_option_table;
462 }
463
Jim Ingham7508e732010-08-09 23:31:02 +0000464 virtual bool
Greg Claytonf15996e2011-04-07 22:46:35 +0000465 HandleOptionArgumentCompletion (Args &input,
Jim Ingham7508e732010-08-09 23:31:02 +0000466 int cursor_index,
467 int char_pos,
468 OptionElementVector &opt_element_vector,
469 int opt_element_index,
470 int match_start_point,
471 int max_return_elements,
472 bool &word_complete,
473 StringList &matches)
474 {
475 int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
476 int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
477
478 // We are only completing the name option for now...
479
Greg Claytonb3448432011-03-24 21:19:54 +0000480 const OptionDefinition *opt_defs = GetDefinitions();
Jim Ingham7508e732010-08-09 23:31:02 +0000481 if (opt_defs[opt_defs_index].short_option == 'n')
482 {
483 // Are we in the name?
484
485 // Look to see if there is a -P argument provided, and if so use that plugin, otherwise
486 // use the default plugin.
Jim Ingham7508e732010-08-09 23:31:02 +0000487
488 const char *partial_name = NULL;
489 partial_name = input.GetArgumentAtIndex(opt_arg_pos);
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000490
Greg Claytonb72d0f02011-04-12 05:54:46 +0000491 PlatformSP platform_sp (m_interpreter.GetPlatform (true));
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000492 if (platform_sp)
Jim Ingham7508e732010-08-09 23:31:02 +0000493 {
Greg Claytonb72d0f02011-04-12 05:54:46 +0000494 ProcessInstanceInfoList process_infos;
495 ProcessInstanceInfoMatch match_info;
Greg Clayton24bc5d92011-03-30 18:16:51 +0000496 if (partial_name)
497 {
498 match_info.GetProcessInfo().SetName(partial_name);
499 match_info.SetNameMatchType(eNameMatchStartsWith);
500 }
501 platform_sp->FindProcesses (match_info, process_infos);
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000502 const uint32_t num_matches = process_infos.GetSize();
503 if (num_matches > 0)
504 {
505 for (uint32_t i=0; i<num_matches; ++i)
506 {
507 matches.AppendString (process_infos.GetProcessNameAtIndex(i),
508 process_infos.GetProcessNameLengthAtIndex(i));
509 }
510 }
Jim Ingham7508e732010-08-09 23:31:02 +0000511 }
512 }
513
514 return false;
515 }
516
Chris Lattner24943d22010-06-08 16:52:24 +0000517 // Options table: Required for subclasses of Options.
518
Greg Claytonb3448432011-03-24 21:19:54 +0000519 static OptionDefinition g_option_table[];
Chris Lattner24943d22010-06-08 16:52:24 +0000520
521 // Instance variables to hold the values for command options.
522
523 lldb::pid_t pid;
524 std::string plugin_name;
525 std::string name;
526 bool waitfor;
527 };
528
Greg Clayton238c0a12010-09-18 01:14:36 +0000529 CommandObjectProcessAttach (CommandInterpreter &interpreter) :
530 CommandObject (interpreter,
531 "process attach",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000532 "Attach to a process.",
Greg Claytonf15996e2011-04-07 22:46:35 +0000533 "process attach <cmd-options>"),
534 m_options (interpreter)
Jim Ingham7508e732010-08-09 23:31:02 +0000535 {
Jim Ingham7508e732010-08-09 23:31:02 +0000536 }
537
538 ~CommandObjectProcessAttach ()
539 {
540 }
541
542 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000543 Execute (Args& command,
Jim Ingham7508e732010-08-09 23:31:02 +0000544 CommandReturnObject &result)
545 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000546 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Jim Inghamee940e22011-09-15 01:08:57 +0000547 // N.B. The attach should be synchronous. It doesn't help much to get the prompt back between initiating the attach
548 // and the target actually stopping. So even if the interpreter is set to be asynchronous, we wait for the stop
549 // ourselves here.
Jim Inghamc2dc7c82011-01-29 01:49:25 +0000550
Greg Clayton567e7f32011-09-22 04:58:26 +0000551 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Greg Claytona2f74232011-02-24 22:24:29 +0000552 StateType state = eStateInvalid;
Jim Ingham7508e732010-08-09 23:31:02 +0000553 if (process)
554 {
Greg Claytona2f74232011-02-24 22:24:29 +0000555 state = process->GetState();
556 if (process->IsAlive() && state != eStateConnected)
Jim Ingham7508e732010-08-09 23:31:02 +0000557 {
Greg Clayton444e35b2011-10-19 18:09:39 +0000558 result.AppendErrorWithFormat ("Process %llu is currently being debugged, kill the process before attaching.\n",
Jim Ingham7508e732010-08-09 23:31:02 +0000559 process->GetID());
560 result.SetStatus (eReturnStatusFailed);
561 return false;
562 }
563 }
564
565 if (target == NULL)
566 {
567 // If there isn't a current target create one.
568 TargetSP new_target_sp;
569 FileSpec emptyFileSpec;
Jim Ingham7508e732010-08-09 23:31:02 +0000570 Error error;
571
Greg Clayton238c0a12010-09-18 01:14:36 +0000572 error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(),
573 emptyFileSpec,
Greg Clayton3e8c25f2011-09-24 00:52:29 +0000574 NULL,
Greg Clayton238c0a12010-09-18 01:14:36 +0000575 false,
Greg Clayton3e8c25f2011-09-24 00:52:29 +0000576 NULL, // No platform options
Greg Clayton238c0a12010-09-18 01:14:36 +0000577 new_target_sp);
Jim Ingham7508e732010-08-09 23:31:02 +0000578 target = new_target_sp.get();
579 if (target == NULL || error.Fail())
580 {
Greg Claytone71e2582011-02-04 01:58:07 +0000581 result.AppendError(error.AsCString("Error creating target"));
Jim Ingham7508e732010-08-09 23:31:02 +0000582 return false;
583 }
Greg Clayton238c0a12010-09-18 01:14:36 +0000584 m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target);
Jim Ingham7508e732010-08-09 23:31:02 +0000585 }
586
587 // Record the old executable module, we want to issue a warning if the process of attaching changed the
588 // current executable (like somebody said "file foo" then attached to a PID whose executable was bar.)
589
590 ModuleSP old_exec_module_sp = target->GetExecutableModule();
591 ArchSpec old_arch_spec = target->GetArchitecture();
592
593 if (command.GetArgumentCount())
594 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +0000595 result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: %s\n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
Jim Ingham7508e732010-08-09 23:31:02 +0000596 result.SetStatus (eReturnStatusFailed);
597 }
598 else
599 {
Greg Claytona2f74232011-02-24 22:24:29 +0000600 if (state != eStateConnected)
601 {
602 const char *plugin_name = NULL;
603
604 if (!m_options.plugin_name.empty())
605 plugin_name = m_options.plugin_name.c_str();
Jim Ingham7508e732010-08-09 23:31:02 +0000606
Greg Claytona2f74232011-02-24 22:24:29 +0000607 process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
608 }
Jim Ingham7508e732010-08-09 23:31:02 +0000609
610 if (process)
611 {
612 Error error;
613 int attach_pid = m_options.pid;
614
Jim Ingham4805a1c2010-09-15 01:34:14 +0000615 const char *wait_name = NULL;
616
617 if (m_options.name.empty())
618 {
619 if (old_exec_module_sp)
620 {
621 wait_name = old_exec_module_sp->GetFileSpec().GetFilename().AsCString();
622 }
623 }
624 else
625 {
626 wait_name = m_options.name.c_str();
627 }
628
Jim Ingham7508e732010-08-09 23:31:02 +0000629 // If we are waiting for a process with this name to show up, do that first.
630 if (m_options.waitfor)
631 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000632
633 if (wait_name == NULL)
Jim Ingham7508e732010-08-09 23:31:02 +0000634 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000635 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 +0000636 result.SetStatus (eReturnStatusFailed);
637 return false;
638 }
Jim Ingham4805a1c2010-09-15 01:34:14 +0000639
Greg Clayton7e2f91c2011-01-29 07:10:55 +0000640 result.AppendMessageWithFormat("Waiting to attach to a process named \"%s\".\n", wait_name);
Jim Ingham4805a1c2010-09-15 01:34:14 +0000641 error = process->Attach (wait_name, m_options.waitfor);
642 if (error.Success())
643 {
644 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
645 }
Jim Ingham7508e732010-08-09 23:31:02 +0000646 else
647 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000648 result.AppendErrorWithFormat ("Waiting for a process to launch named '%s': %s\n",
649 wait_name,
650 error.AsCString());
651 result.SetStatus (eReturnStatusFailed);
652 return false;
Jim Ingham7508e732010-08-09 23:31:02 +0000653 }
Jim Inghamc2dc7c82011-01-29 01:49:25 +0000654 // If we're synchronous, wait for the stopped event and report that.
655 // Otherwise just return.
656 // FIXME: in the async case it will now be possible to get to the command
657 // interpreter with a state eStateAttaching. Make sure we handle that correctly.
Jim Inghamee940e22011-09-15 01:08:57 +0000658 StateType state = process->WaitForProcessToStop (NULL);
Jim Inghamc2dc7c82011-01-29 01:49:25 +0000659
Jim Inghamee940e22011-09-15 01:08:57 +0000660 result.SetDidChangeProcessState (true);
Greg Clayton444e35b2011-10-19 18:09:39 +0000661 result.AppendMessageWithFormat ("Process %llu %s\n", process->GetID(), StateAsCString (state));
Jim Inghamee940e22011-09-15 01:08:57 +0000662 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Jim Ingham7508e732010-08-09 23:31:02 +0000663 }
664 else
665 {
666 // If the process was specified by name look it up, so we can warn if there are multiple
667 // processes with this pid.
668
Jim Ingham4805a1c2010-09-15 01:34:14 +0000669 if (attach_pid == LLDB_INVALID_PROCESS_ID && wait_name != NULL)
Jim Ingham7508e732010-08-09 23:31:02 +0000670 {
Greg Claytonb72d0f02011-04-12 05:54:46 +0000671 ProcessInstanceInfoList process_infos;
672 PlatformSP platform_sp (m_interpreter.GetPlatform (true));
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000673 if (platform_sp)
674 {
Greg Claytonb72d0f02011-04-12 05:54:46 +0000675 ProcessInstanceInfoMatch match_info (wait_name, eNameMatchEquals);
Greg Clayton24bc5d92011-03-30 18:16:51 +0000676 platform_sp->FindProcesses (match_info, process_infos);
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000677 }
678 if (process_infos.GetSize() > 1)
Jim Ingham7508e732010-08-09 23:31:02 +0000679 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000680 result.AppendErrorWithFormat("More than one process named %s\n", wait_name);
Jim Ingham7508e732010-08-09 23:31:02 +0000681 result.SetStatus (eReturnStatusFailed);
682 return false;
683 }
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000684 else if (process_infos.GetSize() == 0)
Jim Ingham7508e732010-08-09 23:31:02 +0000685 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000686 result.AppendErrorWithFormat("Could not find a process named %s\n", wait_name);
Jim Ingham7508e732010-08-09 23:31:02 +0000687 result.SetStatus (eReturnStatusFailed);
688 return false;
689 }
690 else
691 {
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000692 attach_pid = process_infos.GetProcessIDAtIndex (0);
Jim Ingham7508e732010-08-09 23:31:02 +0000693 }
Jim Ingham7508e732010-08-09 23:31:02 +0000694 }
695
696 if (attach_pid != LLDB_INVALID_PROCESS_ID)
697 {
698 error = process->Attach (attach_pid);
699 if (error.Success())
700 {
701 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
702 }
703 else
704 {
705 result.AppendErrorWithFormat ("Attaching to process %i failed: %s.\n",
706 attach_pid,
707 error.AsCString());
708 result.SetStatus (eReturnStatusFailed);
709 }
Jim Inghamee940e22011-09-15 01:08:57 +0000710 StateType state = process->WaitForProcessToStop (NULL);
Jim Inghamc2dc7c82011-01-29 01:49:25 +0000711
Jim Inghamee940e22011-09-15 01:08:57 +0000712 result.SetDidChangeProcessState (true);
Greg Clayton444e35b2011-10-19 18:09:39 +0000713 result.AppendMessageWithFormat ("Process %llu %s\n", process->GetID(), StateAsCString (state));
Jim Inghamee940e22011-09-15 01:08:57 +0000714 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Jim Ingham7508e732010-08-09 23:31:02 +0000715 }
716 else
717 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +0000718 result.AppendErrorWithFormat ("No PID specified for attach\n");
Jim Ingham7508e732010-08-09 23:31:02 +0000719 result.SetStatus (eReturnStatusFailed);
720
721 }
722 }
723 }
724 }
725
726 if (result.Succeeded())
727 {
728 // Okay, we're done. Last step is to warn if the executable module has changed:
Greg Clayton7e2f91c2011-01-29 07:10:55 +0000729 char new_path[PATH_MAX];
Greg Clayton5beb99d2011-08-11 02:48:45 +0000730 ModuleSP new_exec_module_sp (target->GetExecutableModule());
Jim Ingham7508e732010-08-09 23:31:02 +0000731 if (!old_exec_module_sp)
732 {
Greg Clayton7e2f91c2011-01-29 07:10:55 +0000733 // We might not have a module if we attached to a raw pid...
Greg Clayton5beb99d2011-08-11 02:48:45 +0000734 if (new_exec_module_sp)
Greg Clayton7e2f91c2011-01-29 07:10:55 +0000735 {
Greg Clayton5beb99d2011-08-11 02:48:45 +0000736 new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX);
Greg Clayton7e2f91c2011-01-29 07:10:55 +0000737 result.AppendMessageWithFormat("Executable module set to \"%s\".\n", new_path);
738 }
Jim Ingham7508e732010-08-09 23:31:02 +0000739 }
Greg Clayton5beb99d2011-08-11 02:48:45 +0000740 else if (old_exec_module_sp->GetFileSpec() != new_exec_module_sp->GetFileSpec())
Jim Ingham7508e732010-08-09 23:31:02 +0000741 {
Greg Clayton7e2f91c2011-01-29 07:10:55 +0000742 char old_path[PATH_MAX];
Jim Ingham7508e732010-08-09 23:31:02 +0000743
Greg Clayton5beb99d2011-08-11 02:48:45 +0000744 old_exec_module_sp->GetFileSpec().GetPath (old_path, PATH_MAX);
745 new_exec_module_sp->GetFileSpec().GetPath (new_path, PATH_MAX);
Jim Ingham7508e732010-08-09 23:31:02 +0000746
747 result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n",
748 old_path, new_path);
749 }
750
751 if (!old_arch_spec.IsValid())
752 {
Greg Clayton940b1032011-02-23 00:35:02 +0000753 result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().GetArchitectureName());
Jim Ingham7508e732010-08-09 23:31:02 +0000754 }
755 else if (old_arch_spec != target->GetArchitecture())
756 {
757 result.AppendWarningWithFormat("Architecture changed from %s to %s.\n",
Greg Clayton940b1032011-02-23 00:35:02 +0000758 old_arch_spec.GetArchitectureName(), target->GetArchitecture().GetArchitectureName());
Jim Ingham7508e732010-08-09 23:31:02 +0000759 }
760 }
761 return result.Succeeded();
762 }
763
764 Options *
765 GetOptions ()
766 {
767 return &m_options;
768 }
769
Chris Lattner24943d22010-06-08 16:52:24 +0000770protected:
771
772 CommandOptions m_options;
773};
774
775
Greg Claytonb3448432011-03-24 21:19:54 +0000776OptionDefinition
Chris Lattner24943d22010-06-08 16:52:24 +0000777CommandObjectProcessAttach::CommandOptions::g_option_table[] =
778{
Caroline Tice4d6675c2010-10-01 19:59:14 +0000779{ LLDB_OPT_SET_ALL, false, "plugin", 'P', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
780{ LLDB_OPT_SET_1, false, "pid", 'p', required_argument, NULL, 0, eArgTypePid, "The process ID of an existing process to attach to."},
781{ LLDB_OPT_SET_2, false, "name", 'n', required_argument, NULL, 0, eArgTypeProcessName, "The name of the process to attach to."},
782{ LLDB_OPT_SET_2, false, "waitfor",'w', no_argument, NULL, 0, eArgTypeNone, "Wait for the the process with <process-name> to launch."},
783{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +0000784};
785
786//-------------------------------------------------------------------------
787// CommandObjectProcessContinue
788//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +0000789#pragma mark CommandObjectProcessContinue
Chris Lattner24943d22010-06-08 16:52:24 +0000790
791class CommandObjectProcessContinue : public CommandObject
792{
793public:
794
Greg Clayton238c0a12010-09-18 01:14:36 +0000795 CommandObjectProcessContinue (CommandInterpreter &interpreter) :
796 CommandObject (interpreter,
797 "process continue",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000798 "Continue execution of all threads in the current process.",
Chris Lattner24943d22010-06-08 16:52:24 +0000799 "process continue",
800 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
801 {
802 }
803
804
805 ~CommandObjectProcessContinue ()
806 {
807 }
808
809 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000810 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000811 CommandReturnObject &result)
812 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000813 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Greg Clayton238c0a12010-09-18 01:14:36 +0000814 bool synchronous_execution = m_interpreter.GetSynchronous ();
Chris Lattner24943d22010-06-08 16:52:24 +0000815
816 if (process == NULL)
817 {
818 result.AppendError ("no process to continue");
819 result.SetStatus (eReturnStatusFailed);
820 return false;
821 }
822
823 StateType state = process->GetState();
824 if (state == eStateStopped)
825 {
826 if (command.GetArgumentCount() != 0)
827 {
828 result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str());
829 result.SetStatus (eReturnStatusFailed);
830 return false;
831 }
832
833 const uint32_t num_threads = process->GetThreadList().GetSize();
834
835 // Set the actions that the threads should each take when resuming
836 for (uint32_t idx=0; idx<num_threads; ++idx)
837 {
838 process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning);
839 }
840
841 Error error(process->Resume());
842 if (error.Success())
843 {
Greg Clayton444e35b2011-10-19 18:09:39 +0000844 result.AppendMessageWithFormat ("Process %llu resuming\n", process->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000845 if (synchronous_execution)
846 {
Greg Claytonbef15832010-07-14 00:18:15 +0000847 state = process->WaitForProcessToStop (NULL);
Chris Lattner24943d22010-06-08 16:52:24 +0000848
849 result.SetDidChangeProcessState (true);
Greg Clayton444e35b2011-10-19 18:09:39 +0000850 result.AppendMessageWithFormat ("Process %llu %s\n", process->GetID(), StateAsCString (state));
Chris Lattner24943d22010-06-08 16:52:24 +0000851 result.SetStatus (eReturnStatusSuccessFinishNoResult);
852 }
853 else
854 {
855 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
856 }
857 }
858 else
859 {
860 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
861 result.SetStatus (eReturnStatusFailed);
862 }
863 }
864 else
865 {
866 result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
867 StateAsCString(state));
868 result.SetStatus (eReturnStatusFailed);
869 }
870 return result.Succeeded();
871 }
872};
873
874//-------------------------------------------------------------------------
875// CommandObjectProcessDetach
876//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +0000877#pragma mark CommandObjectProcessDetach
Chris Lattner24943d22010-06-08 16:52:24 +0000878
879class CommandObjectProcessDetach : public CommandObject
880{
881public:
882
Greg Clayton238c0a12010-09-18 01:14:36 +0000883 CommandObjectProcessDetach (CommandInterpreter &interpreter) :
884 CommandObject (interpreter,
885 "process detach",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000886 "Detach from the current process being debugged.",
Chris Lattner24943d22010-06-08 16:52:24 +0000887 "process detach",
888 eFlagProcessMustBeLaunched)
889 {
890 }
891
892 ~CommandObjectProcessDetach ()
893 {
894 }
895
896 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000897 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000898 CommandReturnObject &result)
899 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000900 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Chris Lattner24943d22010-06-08 16:52:24 +0000901 if (process == NULL)
902 {
903 result.AppendError ("must have a valid process in order to detach");
904 result.SetStatus (eReturnStatusFailed);
905 return false;
906 }
907
Greg Clayton444e35b2011-10-19 18:09:39 +0000908 result.AppendMessageWithFormat ("Detaching from process %llu\n", process->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000909 Error error (process->Detach());
910 if (error.Success())
911 {
912 result.SetStatus (eReturnStatusSuccessFinishResult);
913 }
914 else
915 {
916 result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString());
917 result.SetStatus (eReturnStatusFailed);
918 return false;
919 }
920 return result.Succeeded();
921 }
922};
923
924//-------------------------------------------------------------------------
Greg Claytone71e2582011-02-04 01:58:07 +0000925// CommandObjectProcessConnect
926//-------------------------------------------------------------------------
927#pragma mark CommandObjectProcessConnect
928
929class CommandObjectProcessConnect : public CommandObject
930{
931public:
932
933 class CommandOptions : public Options
934 {
935 public:
936
Greg Claytonf15996e2011-04-07 22:46:35 +0000937 CommandOptions (CommandInterpreter &interpreter) :
938 Options(interpreter)
Greg Claytone71e2582011-02-04 01:58:07 +0000939 {
Greg Clayton143fcc32011-04-13 00:18:08 +0000940 // Keep default values of all options in one place: OptionParsingStarting ()
941 OptionParsingStarting ();
Greg Claytone71e2582011-02-04 01:58:07 +0000942 }
943
944 ~CommandOptions ()
945 {
946 }
947
948 Error
Greg Clayton143fcc32011-04-13 00:18:08 +0000949 SetOptionValue (uint32_t option_idx, const char *option_arg)
Greg Claytone71e2582011-02-04 01:58:07 +0000950 {
951 Error error;
952 char short_option = (char) m_getopt_table[option_idx].val;
953
954 switch (short_option)
955 {
956 case 'p':
957 plugin_name.assign (option_arg);
958 break;
959
960 default:
Greg Clayton9c236732011-10-26 00:56:27 +0000961 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
Greg Claytone71e2582011-02-04 01:58:07 +0000962 break;
963 }
964 return error;
965 }
966
967 void
Greg Clayton143fcc32011-04-13 00:18:08 +0000968 OptionParsingStarting ()
Greg Claytone71e2582011-02-04 01:58:07 +0000969 {
Greg Claytone71e2582011-02-04 01:58:07 +0000970 plugin_name.clear();
971 }
972
Greg Claytonb3448432011-03-24 21:19:54 +0000973 const OptionDefinition*
Greg Claytone71e2582011-02-04 01:58:07 +0000974 GetDefinitions ()
975 {
976 return g_option_table;
977 }
978
979 // Options table: Required for subclasses of Options.
980
Greg Claytonb3448432011-03-24 21:19:54 +0000981 static OptionDefinition g_option_table[];
Greg Claytone71e2582011-02-04 01:58:07 +0000982
983 // Instance variables to hold the values for command options.
984
985 std::string plugin_name;
986 };
987
988 CommandObjectProcessConnect (CommandInterpreter &interpreter) :
Greg Claytonf15996e2011-04-07 22:46:35 +0000989 CommandObject (interpreter,
990 "process connect",
991 "Connect to a remote debug service.",
992 "process connect <remote-url>",
993 0),
994 m_options (interpreter)
Greg Claytone71e2582011-02-04 01:58:07 +0000995 {
996 }
997
998 ~CommandObjectProcessConnect ()
999 {
1000 }
1001
1002
1003 bool
1004 Execute (Args& command,
1005 CommandReturnObject &result)
1006 {
1007
1008 TargetSP target_sp (m_interpreter.GetDebugger().GetSelectedTarget());
1009 Error error;
Greg Clayton567e7f32011-09-22 04:58:26 +00001010 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Greg Claytone71e2582011-02-04 01:58:07 +00001011 if (process)
1012 {
1013 if (process->IsAlive())
1014 {
Greg Clayton444e35b2011-10-19 18:09:39 +00001015 result.AppendErrorWithFormat ("Process %llu is currently being debugged, kill the process before connecting.\n",
Greg Claytone71e2582011-02-04 01:58:07 +00001016 process->GetID());
1017 result.SetStatus (eReturnStatusFailed);
1018 return false;
1019 }
1020 }
1021
1022 if (!target_sp)
1023 {
1024 // If there isn't a current target create one.
1025 FileSpec emptyFileSpec;
Greg Claytone71e2582011-02-04 01:58:07 +00001026
1027 error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(),
1028 emptyFileSpec,
Greg Clayton3e8c25f2011-09-24 00:52:29 +00001029 NULL,
Greg Claytone71e2582011-02-04 01:58:07 +00001030 false,
Greg Clayton3e8c25f2011-09-24 00:52:29 +00001031 NULL, // No platform options
Greg Claytone71e2582011-02-04 01:58:07 +00001032 target_sp);
1033 if (!target_sp || error.Fail())
1034 {
1035 result.AppendError(error.AsCString("Error creating target"));
1036 result.SetStatus (eReturnStatusFailed);
1037 return false;
1038 }
1039 m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target_sp.get());
1040 }
1041
1042 if (command.GetArgumentCount() == 1)
1043 {
1044 const char *plugin_name = NULL;
1045 if (!m_options.plugin_name.empty())
1046 plugin_name = m_options.plugin_name.c_str();
1047
1048 const char *remote_url = command.GetArgumentAtIndex(0);
1049 process = target_sp->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
1050
1051 if (process)
1052 {
1053 error = process->ConnectRemote (remote_url);
1054
1055 if (error.Fail())
1056 {
1057 result.AppendError(error.AsCString("Remote connect failed"));
1058 result.SetStatus (eReturnStatusFailed);
1059 return false;
1060 }
1061 }
1062 else
1063 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001064 result.AppendErrorWithFormat ("Unable to find process plug-in for remote URL '%s'.\nPlease specify a process plug-in name with the --plugin option, or specify an object file using the \"file\" command.\n",
1065 m_cmd_name.c_str());
Greg Claytone71e2582011-02-04 01:58:07 +00001066 result.SetStatus (eReturnStatusFailed);
1067 }
1068 }
1069 else
1070 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001071 result.AppendErrorWithFormat ("'%s' takes exactly one argument:\nUsage: %s\n",
Greg Claytone71e2582011-02-04 01:58:07 +00001072 m_cmd_name.c_str(),
1073 m_cmd_syntax.c_str());
1074 result.SetStatus (eReturnStatusFailed);
1075 }
1076 return result.Succeeded();
1077 }
1078
1079 Options *
1080 GetOptions ()
1081 {
1082 return &m_options;
1083 }
1084
1085protected:
1086
1087 CommandOptions m_options;
1088};
1089
1090
Greg Claytonb3448432011-03-24 21:19:54 +00001091OptionDefinition
Greg Claytone71e2582011-02-04 01:58:07 +00001092CommandObjectProcessConnect::CommandOptions::g_option_table[] =
1093{
1094 { LLDB_OPT_SET_ALL, false, "plugin", 'p', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
1095 { 0, false, NULL, 0 , 0, NULL, 0, eArgTypeNone, NULL }
1096};
1097
1098//-------------------------------------------------------------------------
Greg Clayton0baa3942010-11-04 01:54:29 +00001099// CommandObjectProcessLoad
1100//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +00001101#pragma mark CommandObjectProcessLoad
Greg Clayton0baa3942010-11-04 01:54:29 +00001102
1103class CommandObjectProcessLoad : public CommandObject
1104{
1105public:
1106
1107 CommandObjectProcessLoad (CommandInterpreter &interpreter) :
1108 CommandObject (interpreter,
1109 "process load",
1110 "Load a shared library into the current process.",
1111 "process load <filename> [<filename> ...]",
1112 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
1113 {
1114 }
1115
1116 ~CommandObjectProcessLoad ()
1117 {
1118 }
1119
1120 bool
1121 Execute (Args& command,
1122 CommandReturnObject &result)
1123 {
Greg Clayton567e7f32011-09-22 04:58:26 +00001124 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Greg Clayton0baa3942010-11-04 01:54:29 +00001125 if (process == NULL)
1126 {
1127 result.AppendError ("must have a valid process in order to load a shared library");
1128 result.SetStatus (eReturnStatusFailed);
1129 return false;
1130 }
1131
1132 const uint32_t argc = command.GetArgumentCount();
1133
1134 for (uint32_t i=0; i<argc; ++i)
1135 {
1136 Error error;
1137 const char *image_path = command.GetArgumentAtIndex(i);
1138 FileSpec image_spec (image_path, false);
Greg Claytonf2bf8702011-08-11 16:25:18 +00001139 process->GetTarget().GetPlatform()->ResolveRemotePath(image_spec, image_spec);
Greg Clayton0baa3942010-11-04 01:54:29 +00001140 uint32_t image_token = process->LoadImage(image_spec, error);
1141 if (image_token != LLDB_INVALID_IMAGE_TOKEN)
1142 {
1143 result.AppendMessageWithFormat ("Loading \"%s\"...ok\nImage %u loaded.\n", image_path, image_token);
1144 result.SetStatus (eReturnStatusSuccessFinishResult);
1145 }
1146 else
1147 {
1148 result.AppendErrorWithFormat ("failed to load '%s': %s", image_path, error.AsCString());
1149 result.SetStatus (eReturnStatusFailed);
1150 }
1151 }
1152 return result.Succeeded();
1153 }
1154};
1155
1156
1157//-------------------------------------------------------------------------
1158// CommandObjectProcessUnload
1159//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +00001160#pragma mark CommandObjectProcessUnload
Greg Clayton0baa3942010-11-04 01:54:29 +00001161
1162class CommandObjectProcessUnload : public CommandObject
1163{
1164public:
1165
1166 CommandObjectProcessUnload (CommandInterpreter &interpreter) :
1167 CommandObject (interpreter,
1168 "process unload",
1169 "Unload a shared library from the current process using the index returned by a previous call to \"process load\".",
1170 "process unload <index>",
1171 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
1172 {
1173 }
1174
1175 ~CommandObjectProcessUnload ()
1176 {
1177 }
1178
1179 bool
1180 Execute (Args& command,
1181 CommandReturnObject &result)
1182 {
Greg Clayton567e7f32011-09-22 04:58:26 +00001183 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Greg Clayton0baa3942010-11-04 01:54:29 +00001184 if (process == NULL)
1185 {
1186 result.AppendError ("must have a valid process in order to load a shared library");
1187 result.SetStatus (eReturnStatusFailed);
1188 return false;
1189 }
1190
1191 const uint32_t argc = command.GetArgumentCount();
1192
1193 for (uint32_t i=0; i<argc; ++i)
1194 {
1195 const char *image_token_cstr = command.GetArgumentAtIndex(i);
1196 uint32_t image_token = Args::StringToUInt32(image_token_cstr, LLDB_INVALID_IMAGE_TOKEN, 0);
1197 if (image_token == LLDB_INVALID_IMAGE_TOKEN)
1198 {
1199 result.AppendErrorWithFormat ("invalid image index argument '%s'", image_token_cstr);
1200 result.SetStatus (eReturnStatusFailed);
1201 break;
1202 }
1203 else
1204 {
1205 Error error (process->UnloadImage(image_token));
1206 if (error.Success())
1207 {
1208 result.AppendMessageWithFormat ("Unloading shared library with index %u...ok\n", image_token);
1209 result.SetStatus (eReturnStatusSuccessFinishResult);
1210 }
1211 else
1212 {
1213 result.AppendErrorWithFormat ("failed to unload image: %s", error.AsCString());
1214 result.SetStatus (eReturnStatusFailed);
1215 break;
1216 }
1217 }
1218 }
1219 return result.Succeeded();
1220 }
1221};
1222
1223//-------------------------------------------------------------------------
Chris Lattner24943d22010-06-08 16:52:24 +00001224// CommandObjectProcessSignal
1225//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +00001226#pragma mark CommandObjectProcessSignal
Chris Lattner24943d22010-06-08 16:52:24 +00001227
1228class CommandObjectProcessSignal : public CommandObject
1229{
1230public:
1231
Greg Clayton238c0a12010-09-18 01:14:36 +00001232 CommandObjectProcessSignal (CommandInterpreter &interpreter) :
1233 CommandObject (interpreter,
1234 "process signal",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001235 "Send a UNIX signal to the current process being debugged.",
Caroline Tice43b014a2010-10-04 22:28:36 +00001236 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +00001237 {
Caroline Tice43b014a2010-10-04 22:28:36 +00001238 CommandArgumentEntry arg;
1239 CommandArgumentData signal_arg;
1240
1241 // Define the first (and only) variant of this arg.
Caroline Tice3a62e6d2010-10-18 22:56:57 +00001242 signal_arg.arg_type = eArgTypeUnixSignal;
Caroline Tice43b014a2010-10-04 22:28:36 +00001243 signal_arg.arg_repetition = eArgRepeatPlain;
1244
1245 // There is only one variant this argument could be; put it into the argument entry.
1246 arg.push_back (signal_arg);
1247
1248 // Push the data for the first argument into the m_arguments vector.
1249 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +00001250 }
1251
1252 ~CommandObjectProcessSignal ()
1253 {
1254 }
1255
1256 bool
Greg Clayton238c0a12010-09-18 01:14:36 +00001257 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +00001258 CommandReturnObject &result)
1259 {
Greg Clayton567e7f32011-09-22 04:58:26 +00001260 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Chris Lattner24943d22010-06-08 16:52:24 +00001261 if (process == NULL)
1262 {
1263 result.AppendError ("no process to signal");
1264 result.SetStatus (eReturnStatusFailed);
1265 return false;
1266 }
1267
1268 if (command.GetArgumentCount() == 1)
1269 {
Greg Clayton8f6be2a2010-10-09 01:40:57 +00001270 int signo = LLDB_INVALID_SIGNAL_NUMBER;
1271
1272 const char *signal_name = command.GetArgumentAtIndex(0);
1273 if (::isxdigit (signal_name[0]))
1274 signo = Args::StringToSInt32(signal_name, LLDB_INVALID_SIGNAL_NUMBER, 0);
1275 else
1276 signo = process->GetUnixSignals().GetSignalNumberFromName (signal_name);
1277
1278 if (signo == LLDB_INVALID_SIGNAL_NUMBER)
Chris Lattner24943d22010-06-08 16:52:24 +00001279 {
1280 result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0));
1281 result.SetStatus (eReturnStatusFailed);
1282 }
1283 else
1284 {
1285 Error error (process->Signal (signo));
1286 if (error.Success())
1287 {
1288 result.SetStatus (eReturnStatusSuccessFinishResult);
1289 }
1290 else
1291 {
1292 result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString());
1293 result.SetStatus (eReturnStatusFailed);
1294 }
1295 }
1296 }
1297 else
1298 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001299 result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: %s\n", m_cmd_name.c_str(),
Chris Lattner24943d22010-06-08 16:52:24 +00001300 m_cmd_syntax.c_str());
1301 result.SetStatus (eReturnStatusFailed);
1302 }
1303 return result.Succeeded();
1304 }
1305};
1306
1307
1308//-------------------------------------------------------------------------
1309// CommandObjectProcessInterrupt
1310//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +00001311#pragma mark CommandObjectProcessInterrupt
Chris Lattner24943d22010-06-08 16:52:24 +00001312
1313class CommandObjectProcessInterrupt : public CommandObject
1314{
1315public:
1316
1317
Greg Clayton238c0a12010-09-18 01:14:36 +00001318 CommandObjectProcessInterrupt (CommandInterpreter &interpreter) :
1319 CommandObject (interpreter,
1320 "process interrupt",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001321 "Interrupt the current process being debugged.",
Chris Lattner24943d22010-06-08 16:52:24 +00001322 "process interrupt",
1323 eFlagProcessMustBeLaunched)
1324 {
1325 }
1326
1327 ~CommandObjectProcessInterrupt ()
1328 {
1329 }
1330
1331 bool
Greg Clayton238c0a12010-09-18 01:14:36 +00001332 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +00001333 CommandReturnObject &result)
1334 {
Greg Clayton567e7f32011-09-22 04:58:26 +00001335 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Chris Lattner24943d22010-06-08 16:52:24 +00001336 if (process == NULL)
1337 {
1338 result.AppendError ("no process to halt");
1339 result.SetStatus (eReturnStatusFailed);
1340 return false;
1341 }
1342
1343 if (command.GetArgumentCount() == 0)
1344 {
1345 Error error(process->Halt ());
1346 if (error.Success())
1347 {
1348 result.SetStatus (eReturnStatusSuccessFinishResult);
1349
1350 // Maybe we should add a "SuspendThreadPlans so we
1351 // can halt, and keep in place all the current thread plans.
1352 process->GetThreadList().DiscardThreadPlans();
1353 }
1354 else
1355 {
1356 result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString());
1357 result.SetStatus (eReturnStatusFailed);
1358 }
1359 }
1360 else
1361 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001362 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n",
Chris Lattner24943d22010-06-08 16:52:24 +00001363 m_cmd_name.c_str(),
1364 m_cmd_syntax.c_str());
1365 result.SetStatus (eReturnStatusFailed);
1366 }
1367 return result.Succeeded();
1368 }
1369};
1370
1371//-------------------------------------------------------------------------
1372// CommandObjectProcessKill
1373//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +00001374#pragma mark CommandObjectProcessKill
Chris Lattner24943d22010-06-08 16:52:24 +00001375
1376class CommandObjectProcessKill : public CommandObject
1377{
1378public:
1379
Greg Clayton238c0a12010-09-18 01:14:36 +00001380 CommandObjectProcessKill (CommandInterpreter &interpreter) :
1381 CommandObject (interpreter,
1382 "process kill",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001383 "Terminate the current process being debugged.",
Chris Lattner24943d22010-06-08 16:52:24 +00001384 "process kill",
1385 eFlagProcessMustBeLaunched)
1386 {
1387 }
1388
1389 ~CommandObjectProcessKill ()
1390 {
1391 }
1392
1393 bool
Greg Clayton238c0a12010-09-18 01:14:36 +00001394 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +00001395 CommandReturnObject &result)
1396 {
Greg Clayton567e7f32011-09-22 04:58:26 +00001397 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Chris Lattner24943d22010-06-08 16:52:24 +00001398 if (process == NULL)
1399 {
1400 result.AppendError ("no process to kill");
1401 result.SetStatus (eReturnStatusFailed);
1402 return false;
1403 }
1404
1405 if (command.GetArgumentCount() == 0)
1406 {
1407 Error error (process->Destroy());
1408 if (error.Success())
1409 {
1410 result.SetStatus (eReturnStatusSuccessFinishResult);
1411 }
1412 else
1413 {
1414 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString());
1415 result.SetStatus (eReturnStatusFailed);
1416 }
1417 }
1418 else
1419 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001420 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n",
Chris Lattner24943d22010-06-08 16:52:24 +00001421 m_cmd_name.c_str(),
1422 m_cmd_syntax.c_str());
1423 result.SetStatus (eReturnStatusFailed);
1424 }
1425 return result.Succeeded();
1426 }
1427};
1428
1429//-------------------------------------------------------------------------
Jim Ingham41313fc2010-06-18 01:23:09 +00001430// CommandObjectProcessStatus
1431//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +00001432#pragma mark CommandObjectProcessStatus
1433
Jim Ingham41313fc2010-06-18 01:23:09 +00001434class CommandObjectProcessStatus : public CommandObject
1435{
1436public:
Greg Clayton238c0a12010-09-18 01:14:36 +00001437 CommandObjectProcessStatus (CommandInterpreter &interpreter) :
1438 CommandObject (interpreter,
1439 "process status",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001440 "Show the current status and location of executing process.",
1441 "process status",
Jim Ingham41313fc2010-06-18 01:23:09 +00001442 0)
1443 {
1444 }
1445
1446 ~CommandObjectProcessStatus()
1447 {
1448 }
1449
1450
1451 bool
1452 Execute
1453 (
1454 Args& command,
Jim Ingham41313fc2010-06-18 01:23:09 +00001455 CommandReturnObject &result
1456 )
1457 {
Greg Claytonabe0fed2011-04-18 08:33:37 +00001458 Stream &strm = result.GetOutputStream();
Jim Ingham41313fc2010-06-18 01:23:09 +00001459 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Greg Claytonb72d0f02011-04-12 05:54:46 +00001460 ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
Greg Clayton567e7f32011-09-22 04:58:26 +00001461 Process *process = exe_ctx.GetProcessPtr();
1462 if (process)
Jim Ingham41313fc2010-06-18 01:23:09 +00001463 {
Greg Claytonabe0fed2011-04-18 08:33:37 +00001464 const bool only_threads_with_stop_reason = true;
1465 const uint32_t start_frame = 0;
1466 const uint32_t num_frames = 1;
1467 const uint32_t num_frames_with_source = 1;
Greg Clayton567e7f32011-09-22 04:58:26 +00001468 process->GetStatus(strm);
1469 process->GetThreadStatus (strm,
1470 only_threads_with_stop_reason,
1471 start_frame,
1472 num_frames,
1473 num_frames_with_source);
Greg Claytonabe0fed2011-04-18 08:33:37 +00001474
Jim Ingham41313fc2010-06-18 01:23:09 +00001475 }
1476 else
1477 {
Greg Claytonabe0fed2011-04-18 08:33:37 +00001478 result.AppendError ("No process.");
Jim Ingham41313fc2010-06-18 01:23:09 +00001479 result.SetStatus (eReturnStatusFailed);
1480 }
1481 return result.Succeeded();
1482 }
1483};
1484
1485//-------------------------------------------------------------------------
Caroline Tice23d6f272010-10-13 20:44:39 +00001486// CommandObjectProcessHandle
1487//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +00001488#pragma mark CommandObjectProcessHandle
Caroline Tice23d6f272010-10-13 20:44:39 +00001489
1490class CommandObjectProcessHandle : public CommandObject
1491{
1492public:
1493
1494 class CommandOptions : public Options
1495 {
1496 public:
1497
Greg Claytonf15996e2011-04-07 22:46:35 +00001498 CommandOptions (CommandInterpreter &interpreter) :
1499 Options (interpreter)
Caroline Tice23d6f272010-10-13 20:44:39 +00001500 {
Greg Clayton143fcc32011-04-13 00:18:08 +00001501 OptionParsingStarting ();
Caroline Tice23d6f272010-10-13 20:44:39 +00001502 }
1503
1504 ~CommandOptions ()
1505 {
1506 }
1507
1508 Error
Greg Clayton143fcc32011-04-13 00:18:08 +00001509 SetOptionValue (uint32_t option_idx, const char *option_arg)
Caroline Tice23d6f272010-10-13 20:44:39 +00001510 {
1511 Error error;
1512 char short_option = (char) m_getopt_table[option_idx].val;
1513
1514 switch (short_option)
1515 {
1516 case 's':
1517 stop = option_arg;
1518 break;
1519 case 'n':
1520 notify = option_arg;
1521 break;
1522 case 'p':
1523 pass = option_arg;
1524 break;
1525 default:
Greg Clayton9c236732011-10-26 00:56:27 +00001526 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
Caroline Tice23d6f272010-10-13 20:44:39 +00001527 break;
1528 }
1529 return error;
1530 }
1531
1532 void
Greg Clayton143fcc32011-04-13 00:18:08 +00001533 OptionParsingStarting ()
Caroline Tice23d6f272010-10-13 20:44:39 +00001534 {
Caroline Tice23d6f272010-10-13 20:44:39 +00001535 stop.clear();
1536 notify.clear();
1537 pass.clear();
1538 }
1539
Greg Claytonb3448432011-03-24 21:19:54 +00001540 const OptionDefinition*
Caroline Tice23d6f272010-10-13 20:44:39 +00001541 GetDefinitions ()
1542 {
1543 return g_option_table;
1544 }
1545
1546 // Options table: Required for subclasses of Options.
1547
Greg Claytonb3448432011-03-24 21:19:54 +00001548 static OptionDefinition g_option_table[];
Caroline Tice23d6f272010-10-13 20:44:39 +00001549
1550 // Instance variables to hold the values for command options.
1551
1552 std::string stop;
1553 std::string notify;
1554 std::string pass;
1555 };
1556
1557
1558 CommandObjectProcessHandle (CommandInterpreter &interpreter) :
1559 CommandObject (interpreter,
1560 "process handle",
Caroline Ticee7471982010-10-14 21:31:13 +00001561 "Show or update what the process and debugger should do with various signals received from the OS.",
Greg Claytonf15996e2011-04-07 22:46:35 +00001562 NULL),
1563 m_options (interpreter)
Caroline Tice23d6f272010-10-13 20:44:39 +00001564 {
Caroline Ticee7471982010-10-14 21:31:13 +00001565 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 +00001566 CommandArgumentEntry arg;
Caroline Tice3a62e6d2010-10-18 22:56:57 +00001567 CommandArgumentData signal_arg;
Caroline Tice23d6f272010-10-13 20:44:39 +00001568
Caroline Tice3a62e6d2010-10-18 22:56:57 +00001569 signal_arg.arg_type = eArgTypeUnixSignal;
1570 signal_arg.arg_repetition = eArgRepeatStar;
Caroline Tice23d6f272010-10-13 20:44:39 +00001571
Caroline Tice3a62e6d2010-10-18 22:56:57 +00001572 arg.push_back (signal_arg);
Caroline Tice23d6f272010-10-13 20:44:39 +00001573
1574 m_arguments.push_back (arg);
1575 }
1576
1577 ~CommandObjectProcessHandle ()
1578 {
1579 }
1580
1581 Options *
1582 GetOptions ()
1583 {
1584 return &m_options;
1585 }
1586
1587 bool
Caroline Ticee7471982010-10-14 21:31:13 +00001588 VerifyCommandOptionValue (const std::string &option, int &real_value)
Caroline Tice23d6f272010-10-13 20:44:39 +00001589 {
1590 bool okay = true;
1591
Caroline Ticee7471982010-10-14 21:31:13 +00001592 bool success = false;
1593 bool tmp_value = Args::StringToBoolean (option.c_str(), false, &success);
1594
1595 if (success && tmp_value)
1596 real_value = 1;
1597 else if (success && !tmp_value)
1598 real_value = 0;
Caroline Tice23d6f272010-10-13 20:44:39 +00001599 else
1600 {
1601 // If the value isn't 'true' or 'false', it had better be 0 or 1.
Caroline Ticee7471982010-10-14 21:31:13 +00001602 real_value = Args::StringToUInt32 (option.c_str(), 3);
1603 if (real_value != 0 && real_value != 1)
Caroline Tice23d6f272010-10-13 20:44:39 +00001604 okay = false;
1605 }
1606
1607 return okay;
1608 }
1609
Caroline Ticee7471982010-10-14 21:31:13 +00001610 void
1611 PrintSignalHeader (Stream &str)
1612 {
1613 str.Printf ("NAME PASS STOP NOTIFY\n");
1614 str.Printf ("========== ===== ===== ======\n");
1615 }
1616
1617 void
1618 PrintSignal (Stream &str, int32_t signo, const char *sig_name, UnixSignals &signals)
1619 {
1620 bool stop;
1621 bool suppress;
1622 bool notify;
1623
1624 str.Printf ("%-10s ", sig_name);
1625 if (signals.GetSignalInfo (signo, suppress, stop, notify))
1626 {
1627 bool pass = !suppress;
1628 str.Printf ("%s %s %s",
1629 (pass ? "true " : "false"),
1630 (stop ? "true " : "false"),
1631 (notify ? "true " : "false"));
1632 }
1633 str.Printf ("\n");
1634 }
1635
1636 void
1637 PrintSignalInformation (Stream &str, Args &signal_args, int num_valid_signals, UnixSignals &signals)
1638 {
1639 PrintSignalHeader (str);
1640
1641 if (num_valid_signals > 0)
1642 {
1643 size_t num_args = signal_args.GetArgumentCount();
1644 for (size_t i = 0; i < num_args; ++i)
1645 {
1646 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
1647 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
1648 PrintSignal (str, signo, signal_args.GetArgumentAtIndex (i), signals);
1649 }
1650 }
1651 else // Print info for ALL signals
1652 {
1653 int32_t signo = signals.GetFirstSignalNumber();
1654 while (signo != LLDB_INVALID_SIGNAL_NUMBER)
1655 {
1656 PrintSignal (str, signo, signals.GetSignalAsCString (signo), signals);
1657 signo = signals.GetNextSignalNumber (signo);
1658 }
1659 }
1660 }
1661
Caroline Tice23d6f272010-10-13 20:44:39 +00001662 bool
1663 Execute (Args &signal_args, CommandReturnObject &result)
1664 {
1665 TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
1666
1667 if (!target_sp)
1668 {
1669 result.AppendError ("No current target;"
1670 " cannot handle signals until you have a valid target and process.\n");
1671 result.SetStatus (eReturnStatusFailed);
1672 return false;
1673 }
1674
1675 ProcessSP process_sp = target_sp->GetProcessSP();
1676
1677 if (!process_sp)
1678 {
1679 result.AppendError ("No current process; cannot handle signals until you have a valid process.\n");
1680 result.SetStatus (eReturnStatusFailed);
1681 return false;
1682 }
1683
Caroline Tice23d6f272010-10-13 20:44:39 +00001684 int stop_action = -1; // -1 means leave the current setting alone
Caroline Ticee7471982010-10-14 21:31:13 +00001685 int pass_action = -1; // -1 means leave the current setting alone
Caroline Tice23d6f272010-10-13 20:44:39 +00001686 int notify_action = -1; // -1 means leave the current setting alone
1687
1688 if (! m_options.stop.empty()
Caroline Ticee7471982010-10-14 21:31:13 +00001689 && ! VerifyCommandOptionValue (m_options.stop, stop_action))
Caroline Tice23d6f272010-10-13 20:44:39 +00001690 {
1691 result.AppendError ("Invalid argument for command option --stop; must be true or false.\n");
1692 result.SetStatus (eReturnStatusFailed);
1693 return false;
1694 }
1695
1696 if (! m_options.notify.empty()
Caroline Ticee7471982010-10-14 21:31:13 +00001697 && ! VerifyCommandOptionValue (m_options.notify, notify_action))
Caroline Tice23d6f272010-10-13 20:44:39 +00001698 {
1699 result.AppendError ("Invalid argument for command option --notify; must be true or false.\n");
1700 result.SetStatus (eReturnStatusFailed);
1701 return false;
1702 }
1703
1704 if (! m_options.pass.empty()
Caroline Ticee7471982010-10-14 21:31:13 +00001705 && ! VerifyCommandOptionValue (m_options.pass, pass_action))
Caroline Tice23d6f272010-10-13 20:44:39 +00001706 {
1707 result.AppendError ("Invalid argument for command option --pass; must be true or false.\n");
1708 result.SetStatus (eReturnStatusFailed);
1709 return false;
1710 }
1711
1712 size_t num_args = signal_args.GetArgumentCount();
1713 UnixSignals &signals = process_sp->GetUnixSignals();
1714 int num_signals_set = 0;
1715
Caroline Ticee7471982010-10-14 21:31:13 +00001716 if (num_args > 0)
Caroline Tice23d6f272010-10-13 20:44:39 +00001717 {
Caroline Ticee7471982010-10-14 21:31:13 +00001718 for (size_t i = 0; i < num_args; ++i)
Caroline Tice23d6f272010-10-13 20:44:39 +00001719 {
Caroline Ticee7471982010-10-14 21:31:13 +00001720 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
1721 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
Caroline Tice23d6f272010-10-13 20:44:39 +00001722 {
Caroline Ticee7471982010-10-14 21:31:13 +00001723 // Casting the actions as bools here should be okay, because VerifyCommandOptionValue guarantees
1724 // the value is either 0 or 1.
1725 if (stop_action != -1)
1726 signals.SetShouldStop (signo, (bool) stop_action);
1727 if (pass_action != -1)
1728 {
1729 bool suppress = ! ((bool) pass_action);
1730 signals.SetShouldSuppress (signo, suppress);
1731 }
1732 if (notify_action != -1)
1733 signals.SetShouldNotify (signo, (bool) notify_action);
1734 ++num_signals_set;
Caroline Tice23d6f272010-10-13 20:44:39 +00001735 }
Caroline Ticee7471982010-10-14 21:31:13 +00001736 else
1737 {
1738 result.AppendErrorWithFormat ("Invalid signal name '%s'\n", signal_args.GetArgumentAtIndex (i));
1739 }
Caroline Tice23d6f272010-10-13 20:44:39 +00001740 }
1741 }
Caroline Ticee7471982010-10-14 21:31:13 +00001742 else
1743 {
1744 // No signal specified, if any command options were specified, update ALL signals.
1745 if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1))
1746 {
1747 if (m_interpreter.Confirm ("Do you really want to update all the signals?", false))
1748 {
1749 int32_t signo = signals.GetFirstSignalNumber();
1750 while (signo != LLDB_INVALID_SIGNAL_NUMBER)
1751 {
1752 if (notify_action != -1)
1753 signals.SetShouldNotify (signo, (bool) notify_action);
1754 if (stop_action != -1)
1755 signals.SetShouldStop (signo, (bool) stop_action);
1756 if (pass_action != -1)
1757 {
1758 bool suppress = ! ((bool) pass_action);
1759 signals.SetShouldSuppress (signo, suppress);
1760 }
1761 signo = signals.GetNextSignalNumber (signo);
1762 }
1763 }
1764 }
1765 }
1766
1767 PrintSignalInformation (result.GetOutputStream(), signal_args, num_signals_set, signals);
Caroline Tice23d6f272010-10-13 20:44:39 +00001768
1769 if (num_signals_set > 0)
1770 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1771 else
1772 result.SetStatus (eReturnStatusFailed);
1773
1774 return result.Succeeded();
1775 }
1776
1777protected:
1778
1779 CommandOptions m_options;
1780};
1781
Greg Claytonb3448432011-03-24 21:19:54 +00001782OptionDefinition
Caroline Tice23d6f272010-10-13 20:44:39 +00001783CommandObjectProcessHandle::CommandOptions::g_option_table[] =
1784{
1785{ 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." },
1786{ 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." },
1787{ LLDB_OPT_SET_1, false, "pass", 'p', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." },
1788{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1789};
1790
1791//-------------------------------------------------------------------------
Chris Lattner24943d22010-06-08 16:52:24 +00001792// CommandObjectMultiwordProcess
1793//-------------------------------------------------------------------------
1794
Greg Clayton63094e02010-06-23 01:19:29 +00001795CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001796 CommandObjectMultiword (interpreter,
1797 "process",
1798 "A set of commands for operating on a process.",
1799 "process <subcommand> [<subcommand-options>]")
Chris Lattner24943d22010-06-08 16:52:24 +00001800{
Greg Claytona9eb8272011-07-02 21:07:54 +00001801 LoadSubCommand ("attach", CommandObjectSP (new CommandObjectProcessAttach (interpreter)));
1802 LoadSubCommand ("launch", CommandObjectSP (new CommandObjectProcessLaunch (interpreter)));
1803 LoadSubCommand ("continue", CommandObjectSP (new CommandObjectProcessContinue (interpreter)));
1804 LoadSubCommand ("connect", CommandObjectSP (new CommandObjectProcessConnect (interpreter)));
1805 LoadSubCommand ("detach", CommandObjectSP (new CommandObjectProcessDetach (interpreter)));
1806 LoadSubCommand ("load", CommandObjectSP (new CommandObjectProcessLoad (interpreter)));
1807 LoadSubCommand ("unload", CommandObjectSP (new CommandObjectProcessUnload (interpreter)));
1808 LoadSubCommand ("signal", CommandObjectSP (new CommandObjectProcessSignal (interpreter)));
1809 LoadSubCommand ("handle", CommandObjectSP (new CommandObjectProcessHandle (interpreter)));
1810 LoadSubCommand ("status", CommandObjectSP (new CommandObjectProcessStatus (interpreter)));
Greg Clayton238c0a12010-09-18 01:14:36 +00001811 LoadSubCommand ("interrupt", CommandObjectSP (new CommandObjectProcessInterrupt (interpreter)));
Greg Claytona9eb8272011-07-02 21:07:54 +00001812 LoadSubCommand ("kill", CommandObjectSP (new CommandObjectProcessKill (interpreter)));
Chris Lattner24943d22010-06-08 16:52:24 +00001813}
1814
1815CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess ()
1816{
1817}
1818