blob: e048182d04b2c4c84ada3f6a42f43edb6bcbb9e2 [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 Clayton527154d2011-11-15 03:53:30 +0000215 if (launch_args.GetArgumentCount() == 0)
216 {
217 const Args &process_args = target->GetRunArguments();
218 if (process_args.GetArgumentCount() > 0)
219 m_options.launch_info.GetArguments().AppendArguments (process_args);
220 }
221 else
Greg Claytonabb33022011-11-08 02:43:13 +0000222 {
223 m_options.launch_info.GetArguments().AppendArguments (launch_args);
224 }
Greg Claytonabb33022011-11-08 02:43:13 +0000225
Greg Clayton527154d2011-11-15 03:53:30 +0000226 if (target->GetDisableASLR())
227 m_options.launch_info.GetFlags().Set (eLaunchFlagDisableASLR);
228
229 if (target->GetDisableSTDIO())
230 m_options.launch_info.GetFlags().Set (eLaunchFlagDisableSTDIO);
231
232 m_options.launch_info.GetFlags().Set (eLaunchFlagDebug);
233
234 Args environment;
235 target->GetEnvironmentAsArgs (environment);
236 if (environment.GetArgumentCount() > 0)
237 m_options.launch_info.GetEnvironmentEntries ().AppendArguments (environment);
238
239 m_options.launch_info.FinalizeFileActions (target);
240
Greg Claytonabb33022011-11-08 02:43:13 +0000241 if (state == eStateConnected)
242 {
243 if (m_options.launch_info.GetFlags().Test (eLaunchFlagLaunchInTTY))
244 {
245 result.AppendWarning("can't launch in tty when launching through a remote connection");
246 m_options.launch_info.GetFlags().Clear (eLaunchFlagLaunchInTTY);
247 }
248 }
249 else
Caroline Tice6e4c5ce2010-09-04 00:03:46 +0000250 {
Greg Clayton527154d2011-11-15 03:53:30 +0000251 if (!m_options.launch_info.GetArchitecture().IsValid())
Greg Clayton2d9adb72011-11-12 02:10:56 +0000252 m_options.launch_info.GetArchitecture() = target->GetArchitecture();
253
Greg Clayton527154d2011-11-15 03:53:30 +0000254 process = target->GetPlatform()->DebugProcess (m_options.launch_info,
255 debugger,
256 target,
257 debugger.GetListener(),
258 error).get();
Greg Claytonabb33022011-11-08 02:43:13 +0000259
Greg Claytona2f74232011-02-24 22:24:29 +0000260 if (process == NULL)
261 {
Greg Clayton527154d2011-11-15 03:53:30 +0000262 result.SetError (error, "failed to launch or debug process");
Greg Claytona2f74232011-02-24 22:24:29 +0000263 return false;
264 }
Chris Lattner24943d22010-06-08 16:52:24 +0000265 }
Greg Claytonabb33022011-11-08 02:43:13 +0000266
Greg Clayton238c0a12010-09-18 01:14:36 +0000267 if (error.Success())
268 {
Greg Clayton940b1032011-02-23 00:35:02 +0000269 const char *archname = exe_module->GetArchitecture().GetArchitectureName();
Greg Claytonc1d37752010-10-18 01:45:30 +0000270
Greg Clayton444e35b2011-10-19 18:09:39 +0000271 result.AppendMessageWithFormat ("Process %llu launched: '%s' (%s)\n", process->GetID(), filename, archname);
Greg Claytond8c62532010-10-07 04:19:01 +0000272 result.SetDidChangeProcessState (true);
Greg Clayton36bc5ea2011-11-03 21:22:33 +0000273 if (m_options.launch_info.GetFlags().Test(eLaunchFlagStopAtEntry) == false)
Greg Clayton238c0a12010-09-18 01:14:36 +0000274 {
Greg Claytond8c62532010-10-07 04:19:01 +0000275 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
Greg Clayton238c0a12010-09-18 01:14:36 +0000276 StateType state = process->WaitForProcessToStop (NULL);
277
278 if (state == eStateStopped)
279 {
Greg Claytond8c62532010-10-07 04:19:01 +0000280 error = process->Resume();
281 if (error.Success())
282 {
283 bool synchronous_execution = m_interpreter.GetSynchronous ();
284 if (synchronous_execution)
285 {
286 state = process->WaitForProcessToStop (NULL);
Greg Clayton940b1032011-02-23 00:35:02 +0000287 if (!StateIsStoppedState(state))
Greg Clayton395fc332011-02-15 21:59:32 +0000288 {
Greg Clayton527154d2011-11-15 03:53:30 +0000289 result.AppendErrorWithFormat ("process isn't stopped: %s", StateAsCString(state));
Greg Clayton395fc332011-02-15 21:59:32 +0000290 }
Greg Claytond8c62532010-10-07 04:19:01 +0000291 result.SetDidChangeProcessState (true);
292 result.SetStatus (eReturnStatusSuccessFinishResult);
293 }
294 else
295 {
296 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
297 }
298 }
Greg Clayton395fc332011-02-15 21:59:32 +0000299 else
300 {
Greg Clayton527154d2011-11-15 03:53:30 +0000301 result.AppendErrorWithFormat ("process resume at entry point failed: %s", error.AsCString());
Greg Clayton395fc332011-02-15 21:59:32 +0000302 result.SetStatus (eReturnStatusFailed);
303 }
Greg Clayton238c0a12010-09-18 01:14:36 +0000304 }
Greg Clayton395fc332011-02-15 21:59:32 +0000305 else
306 {
Greg Clayton527154d2011-11-15 03:53:30 +0000307 result.AppendErrorWithFormat ("initial process state wasn't stopped: %s", StateAsCString(state));
Greg Clayton395fc332011-02-15 21:59:32 +0000308 result.SetStatus (eReturnStatusFailed);
309 }
Greg Clayton238c0a12010-09-18 01:14:36 +0000310 }
311 }
Greg Clayton395fc332011-02-15 21:59:32 +0000312 else
313 {
Greg Claytona9eb8272011-07-02 21:07:54 +0000314 result.AppendErrorWithFormat ("process launch failed: %s", error.AsCString());
Greg Clayton395fc332011-02-15 21:59:32 +0000315 result.SetStatus (eReturnStatusFailed);
316 }
Greg Clayton238c0a12010-09-18 01:14:36 +0000317
Chris Lattner24943d22010-06-08 16:52:24 +0000318 return result.Succeeded();
319 }
320
Jim Ingham767af882010-07-07 03:36:20 +0000321 virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
322 {
323 // No repeat for "process launch"...
324 return "";
325 }
326
Chris Lattner24943d22010-06-08 16:52:24 +0000327protected:
Greg Clayton36bc5ea2011-11-03 21:22:33 +0000328 ProcessLaunchCommandOptions m_options;
Chris Lattner24943d22010-06-08 16:52:24 +0000329};
330
331
Greg Clayton36bc5ea2011-11-03 21:22:33 +0000332//#define SET1 LLDB_OPT_SET_1
333//#define SET2 LLDB_OPT_SET_2
334//#define SET3 LLDB_OPT_SET_3
335//
336//OptionDefinition
337//CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
338//{
339//{ 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."},
340//{ SET1 , false, "stdin", 'i', required_argument, NULL, 0, eArgTypePath, "Redirect stdin for the process to <path>."},
341//{ SET1 , false, "stdout", 'o', required_argument, NULL, 0, eArgTypePath, "Redirect stdout for the process to <path>."},
342//{ SET1 , false, "stderr", 'e', required_argument, NULL, 0, eArgTypePath, "Redirect stderr for the process to <path>."},
343//{ SET1 | SET2 | SET3, false, "plugin", 'p', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
344//{ 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."},
345//{ SET3, false, "no-stdio", 'n', no_argument, NULL, 0, eArgTypeNone, "Do not set up for terminal I/O to go to running process."},
346//{ SET1 | SET2 | SET3, false, "working-dir", 'w', required_argument, NULL, 0, eArgTypePath, "Set the current working directory to <path> when running the inferior."},
347//{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
348//};
349//
350//#undef SET1
351//#undef SET2
352//#undef SET3
Chris Lattner24943d22010-06-08 16:52:24 +0000353
354//-------------------------------------------------------------------------
355// CommandObjectProcessAttach
356//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +0000357#pragma mark CommandObjectProcessAttach
Chris Lattner24943d22010-06-08 16:52:24 +0000358class CommandObjectProcessAttach : public CommandObject
359{
360public:
361
Chris Lattner24943d22010-06-08 16:52:24 +0000362 class CommandOptions : public Options
363 {
364 public:
365
Greg Claytonf15996e2011-04-07 22:46:35 +0000366 CommandOptions (CommandInterpreter &interpreter) :
367 Options(interpreter)
Chris Lattner24943d22010-06-08 16:52:24 +0000368 {
Greg Clayton143fcc32011-04-13 00:18:08 +0000369 // Keep default values of all options in one place: OptionParsingStarting ()
370 OptionParsingStarting ();
Chris Lattner24943d22010-06-08 16:52:24 +0000371 }
372
373 ~CommandOptions ()
374 {
375 }
376
377 Error
Greg Clayton143fcc32011-04-13 00:18:08 +0000378 SetOptionValue (uint32_t option_idx, const char *option_arg)
Chris Lattner24943d22010-06-08 16:52:24 +0000379 {
380 Error error;
381 char short_option = (char) m_getopt_table[option_idx].val;
382 bool success = false;
383 switch (short_option)
384 {
385 case 'p':
Chris Lattner24943d22010-06-08 16:52:24 +0000386 {
Greg Clayton527154d2011-11-15 03:53:30 +0000387 lldb::pid_t pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success);
388 if (!success || pid == LLDB_INVALID_PROCESS_ID)
389 {
390 error.SetErrorStringWithFormat("invalid process ID '%s'", option_arg);
391 }
392 else
393 {
394 attach_info.SetProcessID (pid);
395 }
Chris Lattner24943d22010-06-08 16:52:24 +0000396 }
397 break;
398
399 case 'P':
Greg Clayton527154d2011-11-15 03:53:30 +0000400 attach_info.SetProcessPluginName (option_arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000401 break;
402
403 case 'n':
Greg Clayton527154d2011-11-15 03:53:30 +0000404 attach_info.GetExecutableFile().SetFile(option_arg, false);
Chris Lattner24943d22010-06-08 16:52:24 +0000405 break;
406
407 case 'w':
Greg Clayton527154d2011-11-15 03:53:30 +0000408 attach_info.SetWaitForLaunch(true);
Chris Lattner24943d22010-06-08 16:52:24 +0000409 break;
410
411 default:
Greg Clayton9c236732011-10-26 00:56:27 +0000412 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
Chris Lattner24943d22010-06-08 16:52:24 +0000413 break;
414 }
415 return error;
416 }
417
418 void
Greg Clayton143fcc32011-04-13 00:18:08 +0000419 OptionParsingStarting ()
Chris Lattner24943d22010-06-08 16:52:24 +0000420 {
Greg Clayton527154d2011-11-15 03:53:30 +0000421 attach_info.Clear();
Chris Lattner24943d22010-06-08 16:52:24 +0000422 }
423
Greg Claytonb3448432011-03-24 21:19:54 +0000424 const OptionDefinition*
Chris Lattner24943d22010-06-08 16:52:24 +0000425 GetDefinitions ()
426 {
427 return g_option_table;
428 }
429
Jim Ingham7508e732010-08-09 23:31:02 +0000430 virtual bool
Greg Claytonf15996e2011-04-07 22:46:35 +0000431 HandleOptionArgumentCompletion (Args &input,
Jim Ingham7508e732010-08-09 23:31:02 +0000432 int cursor_index,
433 int char_pos,
434 OptionElementVector &opt_element_vector,
435 int opt_element_index,
436 int match_start_point,
437 int max_return_elements,
438 bool &word_complete,
439 StringList &matches)
440 {
441 int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
442 int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
443
444 // We are only completing the name option for now...
445
Greg Claytonb3448432011-03-24 21:19:54 +0000446 const OptionDefinition *opt_defs = GetDefinitions();
Jim Ingham7508e732010-08-09 23:31:02 +0000447 if (opt_defs[opt_defs_index].short_option == 'n')
448 {
449 // Are we in the name?
450
451 // Look to see if there is a -P argument provided, and if so use that plugin, otherwise
452 // use the default plugin.
Jim Ingham7508e732010-08-09 23:31:02 +0000453
454 const char *partial_name = NULL;
455 partial_name = input.GetArgumentAtIndex(opt_arg_pos);
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000456
Greg Claytonb72d0f02011-04-12 05:54:46 +0000457 PlatformSP platform_sp (m_interpreter.GetPlatform (true));
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000458 if (platform_sp)
Jim Ingham7508e732010-08-09 23:31:02 +0000459 {
Greg Claytonb72d0f02011-04-12 05:54:46 +0000460 ProcessInstanceInfoList process_infos;
461 ProcessInstanceInfoMatch match_info;
Greg Clayton24bc5d92011-03-30 18:16:51 +0000462 if (partial_name)
463 {
Greg Clayton527154d2011-11-15 03:53:30 +0000464 match_info.GetProcessInfo().GetExecutableFile().SetFile(partial_name, false);
Greg Clayton24bc5d92011-03-30 18:16:51 +0000465 match_info.SetNameMatchType(eNameMatchStartsWith);
466 }
467 platform_sp->FindProcesses (match_info, process_infos);
Greg Claytone4b9c1f2011-03-08 22:40:15 +0000468 const uint32_t num_matches = process_infos.GetSize();
469 if (num_matches > 0)
470 {
471 for (uint32_t i=0; i<num_matches; ++i)
472 {
473 matches.AppendString (process_infos.GetProcessNameAtIndex(i),
474 process_infos.GetProcessNameLengthAtIndex(i));
475 }
476 }
Jim Ingham7508e732010-08-09 23:31:02 +0000477 }
478 }
479
480 return false;
481 }
482
Chris Lattner24943d22010-06-08 16:52:24 +0000483 // Options table: Required for subclasses of Options.
484
Greg Claytonb3448432011-03-24 21:19:54 +0000485 static OptionDefinition g_option_table[];
Chris Lattner24943d22010-06-08 16:52:24 +0000486
487 // Instance variables to hold the values for command options.
488
Greg Clayton527154d2011-11-15 03:53:30 +0000489 ProcessAttachInfo attach_info;
Chris Lattner24943d22010-06-08 16:52:24 +0000490 };
491
Greg Clayton238c0a12010-09-18 01:14:36 +0000492 CommandObjectProcessAttach (CommandInterpreter &interpreter) :
493 CommandObject (interpreter,
494 "process attach",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000495 "Attach to a process.",
Greg Claytonf15996e2011-04-07 22:46:35 +0000496 "process attach <cmd-options>"),
497 m_options (interpreter)
Jim Ingham7508e732010-08-09 23:31:02 +0000498 {
Jim Ingham7508e732010-08-09 23:31:02 +0000499 }
500
501 ~CommandObjectProcessAttach ()
502 {
503 }
504
505 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000506 Execute (Args& command,
Jim Ingham7508e732010-08-09 23:31:02 +0000507 CommandReturnObject &result)
508 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000509 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Jim Inghamee940e22011-09-15 01:08:57 +0000510 // N.B. The attach should be synchronous. It doesn't help much to get the prompt back between initiating the attach
511 // and the target actually stopping. So even if the interpreter is set to be asynchronous, we wait for the stop
512 // ourselves here.
Jim Inghamc2dc7c82011-01-29 01:49:25 +0000513
Greg Clayton567e7f32011-09-22 04:58:26 +0000514 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Greg Claytona2f74232011-02-24 22:24:29 +0000515 StateType state = eStateInvalid;
Jim Ingham7508e732010-08-09 23:31:02 +0000516 if (process)
517 {
Greg Claytona2f74232011-02-24 22:24:29 +0000518 state = process->GetState();
519 if (process->IsAlive() && state != eStateConnected)
Jim Ingham7508e732010-08-09 23:31:02 +0000520 {
Greg Clayton444e35b2011-10-19 18:09:39 +0000521 result.AppendErrorWithFormat ("Process %llu is currently being debugged, kill the process before attaching.\n",
Jim Ingham7508e732010-08-09 23:31:02 +0000522 process->GetID());
523 result.SetStatus (eReturnStatusFailed);
524 return false;
525 }
526 }
527
528 if (target == NULL)
529 {
530 // If there isn't a current target create one.
531 TargetSP new_target_sp;
532 FileSpec emptyFileSpec;
Jim Ingham7508e732010-08-09 23:31:02 +0000533 Error error;
534
Greg Clayton238c0a12010-09-18 01:14:36 +0000535 error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(),
536 emptyFileSpec,
Greg Clayton3e8c25f2011-09-24 00:52:29 +0000537 NULL,
Greg Clayton238c0a12010-09-18 01:14:36 +0000538 false,
Greg Clayton3e8c25f2011-09-24 00:52:29 +0000539 NULL, // No platform options
Greg Clayton238c0a12010-09-18 01:14:36 +0000540 new_target_sp);
Jim Ingham7508e732010-08-09 23:31:02 +0000541 target = new_target_sp.get();
542 if (target == NULL || error.Fail())
543 {
Greg Claytone71e2582011-02-04 01:58:07 +0000544 result.AppendError(error.AsCString("Error creating target"));
Jim Ingham7508e732010-08-09 23:31:02 +0000545 return false;
546 }
Greg Clayton238c0a12010-09-18 01:14:36 +0000547 m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target);
Jim Ingham7508e732010-08-09 23:31:02 +0000548 }
549
550 // Record the old executable module, we want to issue a warning if the process of attaching changed the
551 // current executable (like somebody said "file foo" then attached to a PID whose executable was bar.)
552
553 ModuleSP old_exec_module_sp = target->GetExecutableModule();
554 ArchSpec old_arch_spec = target->GetArchitecture();
555
556 if (command.GetArgumentCount())
557 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +0000558 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 +0000559 result.SetStatus (eReturnStatusFailed);
560 }
561 else
562 {
Greg Claytona2f74232011-02-24 22:24:29 +0000563 if (state != eStateConnected)
564 {
Greg Clayton527154d2011-11-15 03:53:30 +0000565 const char *plugin_name = m_options.attach_info.GetProcessPluginName();
Greg Claytona2f74232011-02-24 22:24:29 +0000566 process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
567 }
Jim Ingham7508e732010-08-09 23:31:02 +0000568
569 if (process)
570 {
571 Error error;
Greg Clayton527154d2011-11-15 03:53:30 +0000572 // If no process info was specified, then use the target executable
573 // name as the process to attach to by default
574 if (!m_options.attach_info.ProcessInfoSpecified ())
Jim Ingham4805a1c2010-09-15 01:34:14 +0000575 {
576 if (old_exec_module_sp)
Greg Clayton527154d2011-11-15 03:53:30 +0000577 m_options.attach_info.GetExecutableFile().GetFilename() = old_exec_module_sp->GetFileSpec().GetFilename();
Jim Ingham4805a1c2010-09-15 01:34:14 +0000578
Greg Clayton527154d2011-11-15 03:53:30 +0000579 if (!m_options.attach_info.ProcessInfoSpecified ())
580 {
581 error.SetErrorString ("no process specified, create a target with a file, or specify the --pid or --name command option");
582 }
583 }
584
585 if (error.Success())
586 {
587 error = process->Attach (m_options.attach_info);
588
Jim Ingham4805a1c2010-09-15 01:34:14 +0000589 if (error.Success())
590 {
591 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
592 }
Jim Ingham7508e732010-08-09 23:31:02 +0000593 else
594 {
Greg Clayton527154d2011-11-15 03:53:30 +0000595 result.AppendErrorWithFormat ("attach failed: %s\n", error.AsCString());
Jim Ingham4805a1c2010-09-15 01:34:14 +0000596 result.SetStatus (eReturnStatusFailed);
597 return false;
Jim Ingham7508e732010-08-09 23:31:02 +0000598 }
Jim Inghamc2dc7c82011-01-29 01:49:25 +0000599 // If we're synchronous, wait for the stopped event and report that.
600 // Otherwise just return.
601 // FIXME: in the async case it will now be possible to get to the command
602 // interpreter with a state eStateAttaching. Make sure we handle that correctly.
Jim Inghamee940e22011-09-15 01:08:57 +0000603 StateType state = process->WaitForProcessToStop (NULL);
Greg Clayton527154d2011-11-15 03:53:30 +0000604
Jim Inghamee940e22011-09-15 01:08:57 +0000605 result.SetDidChangeProcessState (true);
Greg Clayton444e35b2011-10-19 18:09:39 +0000606 result.AppendMessageWithFormat ("Process %llu %s\n", process->GetID(), StateAsCString (state));
Jim Inghamee940e22011-09-15 01:08:57 +0000607 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Jim Ingham7508e732010-08-09 23:31:02 +0000608 }
Jim Ingham7508e732010-08-09 23:31:02 +0000609 }
610 }
611
612 if (result.Succeeded())
613 {
614 // Okay, we're done. Last step is to warn if the executable module has changed:
Greg Clayton7e2f91c2011-01-29 07:10:55 +0000615 char new_path[PATH_MAX];
Greg Clayton5beb99d2011-08-11 02:48:45 +0000616 ModuleSP new_exec_module_sp (target->GetExecutableModule());
Jim Ingham7508e732010-08-09 23:31:02 +0000617 if (!old_exec_module_sp)
618 {
Greg Clayton7e2f91c2011-01-29 07:10:55 +0000619 // We might not have a module if we attached to a raw pid...
Greg Clayton5beb99d2011-08-11 02:48:45 +0000620 if (new_exec_module_sp)
Greg Clayton7e2f91c2011-01-29 07:10:55 +0000621 {
Greg Clayton5beb99d2011-08-11 02:48:45 +0000622 new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX);
Greg Clayton7e2f91c2011-01-29 07:10:55 +0000623 result.AppendMessageWithFormat("Executable module set to \"%s\".\n", new_path);
624 }
Jim Ingham7508e732010-08-09 23:31:02 +0000625 }
Greg Clayton5beb99d2011-08-11 02:48:45 +0000626 else if (old_exec_module_sp->GetFileSpec() != new_exec_module_sp->GetFileSpec())
Jim Ingham7508e732010-08-09 23:31:02 +0000627 {
Greg Clayton7e2f91c2011-01-29 07:10:55 +0000628 char old_path[PATH_MAX];
Jim Ingham7508e732010-08-09 23:31:02 +0000629
Greg Clayton5beb99d2011-08-11 02:48:45 +0000630 old_exec_module_sp->GetFileSpec().GetPath (old_path, PATH_MAX);
631 new_exec_module_sp->GetFileSpec().GetPath (new_path, PATH_MAX);
Jim Ingham7508e732010-08-09 23:31:02 +0000632
633 result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n",
634 old_path, new_path);
635 }
636
637 if (!old_arch_spec.IsValid())
638 {
Greg Clayton940b1032011-02-23 00:35:02 +0000639 result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().GetArchitectureName());
Jim Ingham7508e732010-08-09 23:31:02 +0000640 }
641 else if (old_arch_spec != target->GetArchitecture())
642 {
643 result.AppendWarningWithFormat("Architecture changed from %s to %s.\n",
Greg Clayton940b1032011-02-23 00:35:02 +0000644 old_arch_spec.GetArchitectureName(), target->GetArchitecture().GetArchitectureName());
Jim Ingham7508e732010-08-09 23:31:02 +0000645 }
646 }
647 return result.Succeeded();
648 }
649
650 Options *
651 GetOptions ()
652 {
653 return &m_options;
654 }
655
Chris Lattner24943d22010-06-08 16:52:24 +0000656protected:
657
658 CommandOptions m_options;
659};
660
661
Greg Claytonb3448432011-03-24 21:19:54 +0000662OptionDefinition
Chris Lattner24943d22010-06-08 16:52:24 +0000663CommandObjectProcessAttach::CommandOptions::g_option_table[] =
664{
Caroline Tice4d6675c2010-10-01 19:59:14 +0000665{ LLDB_OPT_SET_ALL, false, "plugin", 'P', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
666{ LLDB_OPT_SET_1, false, "pid", 'p', required_argument, NULL, 0, eArgTypePid, "The process ID of an existing process to attach to."},
667{ LLDB_OPT_SET_2, false, "name", 'n', required_argument, NULL, 0, eArgTypeProcessName, "The name of the process to attach to."},
668{ LLDB_OPT_SET_2, false, "waitfor",'w', no_argument, NULL, 0, eArgTypeNone, "Wait for the the process with <process-name> to launch."},
669{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +0000670};
671
672//-------------------------------------------------------------------------
673// CommandObjectProcessContinue
674//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +0000675#pragma mark CommandObjectProcessContinue
Chris Lattner24943d22010-06-08 16:52:24 +0000676
677class CommandObjectProcessContinue : public CommandObject
678{
679public:
680
Greg Clayton238c0a12010-09-18 01:14:36 +0000681 CommandObjectProcessContinue (CommandInterpreter &interpreter) :
682 CommandObject (interpreter,
683 "process continue",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000684 "Continue execution of all threads in the current process.",
Chris Lattner24943d22010-06-08 16:52:24 +0000685 "process continue",
686 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
687 {
688 }
689
690
691 ~CommandObjectProcessContinue ()
692 {
693 }
694
695 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000696 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000697 CommandReturnObject &result)
698 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000699 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Greg Clayton238c0a12010-09-18 01:14:36 +0000700 bool synchronous_execution = m_interpreter.GetSynchronous ();
Chris Lattner24943d22010-06-08 16:52:24 +0000701
702 if (process == NULL)
703 {
704 result.AppendError ("no process to continue");
705 result.SetStatus (eReturnStatusFailed);
706 return false;
707 }
708
709 StateType state = process->GetState();
710 if (state == eStateStopped)
711 {
712 if (command.GetArgumentCount() != 0)
713 {
714 result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str());
715 result.SetStatus (eReturnStatusFailed);
716 return false;
717 }
718
719 const uint32_t num_threads = process->GetThreadList().GetSize();
720
721 // Set the actions that the threads should each take when resuming
722 for (uint32_t idx=0; idx<num_threads; ++idx)
723 {
724 process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning);
725 }
726
727 Error error(process->Resume());
728 if (error.Success())
729 {
Greg Clayton444e35b2011-10-19 18:09:39 +0000730 result.AppendMessageWithFormat ("Process %llu resuming\n", process->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000731 if (synchronous_execution)
732 {
Greg Claytonbef15832010-07-14 00:18:15 +0000733 state = process->WaitForProcessToStop (NULL);
Chris Lattner24943d22010-06-08 16:52:24 +0000734
735 result.SetDidChangeProcessState (true);
Greg Clayton444e35b2011-10-19 18:09:39 +0000736 result.AppendMessageWithFormat ("Process %llu %s\n", process->GetID(), StateAsCString (state));
Chris Lattner24943d22010-06-08 16:52:24 +0000737 result.SetStatus (eReturnStatusSuccessFinishNoResult);
738 }
739 else
740 {
741 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
742 }
743 }
744 else
745 {
746 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
747 result.SetStatus (eReturnStatusFailed);
748 }
749 }
750 else
751 {
752 result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
753 StateAsCString(state));
754 result.SetStatus (eReturnStatusFailed);
755 }
756 return result.Succeeded();
757 }
758};
759
760//-------------------------------------------------------------------------
761// CommandObjectProcessDetach
762//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +0000763#pragma mark CommandObjectProcessDetach
Chris Lattner24943d22010-06-08 16:52:24 +0000764
765class CommandObjectProcessDetach : public CommandObject
766{
767public:
768
Greg Clayton238c0a12010-09-18 01:14:36 +0000769 CommandObjectProcessDetach (CommandInterpreter &interpreter) :
770 CommandObject (interpreter,
771 "process detach",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000772 "Detach from the current process being debugged.",
Chris Lattner24943d22010-06-08 16:52:24 +0000773 "process detach",
774 eFlagProcessMustBeLaunched)
775 {
776 }
777
778 ~CommandObjectProcessDetach ()
779 {
780 }
781
782 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000783 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000784 CommandReturnObject &result)
785 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000786 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Chris Lattner24943d22010-06-08 16:52:24 +0000787 if (process == NULL)
788 {
789 result.AppendError ("must have a valid process in order to detach");
790 result.SetStatus (eReturnStatusFailed);
791 return false;
792 }
793
Greg Clayton444e35b2011-10-19 18:09:39 +0000794 result.AppendMessageWithFormat ("Detaching from process %llu\n", process->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000795 Error error (process->Detach());
796 if (error.Success())
797 {
798 result.SetStatus (eReturnStatusSuccessFinishResult);
799 }
800 else
801 {
802 result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString());
803 result.SetStatus (eReturnStatusFailed);
804 return false;
805 }
806 return result.Succeeded();
807 }
808};
809
810//-------------------------------------------------------------------------
Greg Claytone71e2582011-02-04 01:58:07 +0000811// CommandObjectProcessConnect
812//-------------------------------------------------------------------------
813#pragma mark CommandObjectProcessConnect
814
815class CommandObjectProcessConnect : public CommandObject
816{
817public:
818
819 class CommandOptions : public Options
820 {
821 public:
822
Greg Claytonf15996e2011-04-07 22:46:35 +0000823 CommandOptions (CommandInterpreter &interpreter) :
824 Options(interpreter)
Greg Claytone71e2582011-02-04 01:58:07 +0000825 {
Greg Clayton143fcc32011-04-13 00:18:08 +0000826 // Keep default values of all options in one place: OptionParsingStarting ()
827 OptionParsingStarting ();
Greg Claytone71e2582011-02-04 01:58:07 +0000828 }
829
830 ~CommandOptions ()
831 {
832 }
833
834 Error
Greg Clayton143fcc32011-04-13 00:18:08 +0000835 SetOptionValue (uint32_t option_idx, const char *option_arg)
Greg Claytone71e2582011-02-04 01:58:07 +0000836 {
837 Error error;
838 char short_option = (char) m_getopt_table[option_idx].val;
839
840 switch (short_option)
841 {
842 case 'p':
843 plugin_name.assign (option_arg);
844 break;
845
846 default:
Greg Clayton9c236732011-10-26 00:56:27 +0000847 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
Greg Claytone71e2582011-02-04 01:58:07 +0000848 break;
849 }
850 return error;
851 }
852
853 void
Greg Clayton143fcc32011-04-13 00:18:08 +0000854 OptionParsingStarting ()
Greg Claytone71e2582011-02-04 01:58:07 +0000855 {
Greg Claytone71e2582011-02-04 01:58:07 +0000856 plugin_name.clear();
857 }
858
Greg Claytonb3448432011-03-24 21:19:54 +0000859 const OptionDefinition*
Greg Claytone71e2582011-02-04 01:58:07 +0000860 GetDefinitions ()
861 {
862 return g_option_table;
863 }
864
865 // Options table: Required for subclasses of Options.
866
Greg Claytonb3448432011-03-24 21:19:54 +0000867 static OptionDefinition g_option_table[];
Greg Claytone71e2582011-02-04 01:58:07 +0000868
869 // Instance variables to hold the values for command options.
870
871 std::string plugin_name;
872 };
873
874 CommandObjectProcessConnect (CommandInterpreter &interpreter) :
Greg Claytonf15996e2011-04-07 22:46:35 +0000875 CommandObject (interpreter,
876 "process connect",
877 "Connect to a remote debug service.",
878 "process connect <remote-url>",
879 0),
880 m_options (interpreter)
Greg Claytone71e2582011-02-04 01:58:07 +0000881 {
882 }
883
884 ~CommandObjectProcessConnect ()
885 {
886 }
887
888
889 bool
890 Execute (Args& command,
891 CommandReturnObject &result)
892 {
893
894 TargetSP target_sp (m_interpreter.GetDebugger().GetSelectedTarget());
895 Error error;
Greg Clayton567e7f32011-09-22 04:58:26 +0000896 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Greg Claytone71e2582011-02-04 01:58:07 +0000897 if (process)
898 {
899 if (process->IsAlive())
900 {
Greg Clayton444e35b2011-10-19 18:09:39 +0000901 result.AppendErrorWithFormat ("Process %llu is currently being debugged, kill the process before connecting.\n",
Greg Claytone71e2582011-02-04 01:58:07 +0000902 process->GetID());
903 result.SetStatus (eReturnStatusFailed);
904 return false;
905 }
906 }
907
908 if (!target_sp)
909 {
910 // If there isn't a current target create one.
911 FileSpec emptyFileSpec;
Greg Claytone71e2582011-02-04 01:58:07 +0000912
913 error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(),
914 emptyFileSpec,
Greg Clayton3e8c25f2011-09-24 00:52:29 +0000915 NULL,
Greg Claytone71e2582011-02-04 01:58:07 +0000916 false,
Greg Clayton3e8c25f2011-09-24 00:52:29 +0000917 NULL, // No platform options
Greg Claytone71e2582011-02-04 01:58:07 +0000918 target_sp);
919 if (!target_sp || error.Fail())
920 {
921 result.AppendError(error.AsCString("Error creating target"));
922 result.SetStatus (eReturnStatusFailed);
923 return false;
924 }
925 m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target_sp.get());
926 }
927
928 if (command.GetArgumentCount() == 1)
929 {
930 const char *plugin_name = NULL;
931 if (!m_options.plugin_name.empty())
932 plugin_name = m_options.plugin_name.c_str();
933
934 const char *remote_url = command.GetArgumentAtIndex(0);
935 process = target_sp->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
936
937 if (process)
938 {
939 error = process->ConnectRemote (remote_url);
940
941 if (error.Fail())
942 {
943 result.AppendError(error.AsCString("Remote connect failed"));
944 result.SetStatus (eReturnStatusFailed);
945 return false;
946 }
947 }
948 else
949 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +0000950 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",
951 m_cmd_name.c_str());
Greg Claytone71e2582011-02-04 01:58:07 +0000952 result.SetStatus (eReturnStatusFailed);
953 }
954 }
955 else
956 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +0000957 result.AppendErrorWithFormat ("'%s' takes exactly one argument:\nUsage: %s\n",
Greg Claytone71e2582011-02-04 01:58:07 +0000958 m_cmd_name.c_str(),
959 m_cmd_syntax.c_str());
960 result.SetStatus (eReturnStatusFailed);
961 }
962 return result.Succeeded();
963 }
964
965 Options *
966 GetOptions ()
967 {
968 return &m_options;
969 }
970
971protected:
972
973 CommandOptions m_options;
974};
975
976
Greg Claytonb3448432011-03-24 21:19:54 +0000977OptionDefinition
Greg Claytone71e2582011-02-04 01:58:07 +0000978CommandObjectProcessConnect::CommandOptions::g_option_table[] =
979{
980 { LLDB_OPT_SET_ALL, false, "plugin", 'p', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
981 { 0, false, NULL, 0 , 0, NULL, 0, eArgTypeNone, NULL }
982};
983
984//-------------------------------------------------------------------------
Greg Clayton0baa3942010-11-04 01:54:29 +0000985// CommandObjectProcessLoad
986//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +0000987#pragma mark CommandObjectProcessLoad
Greg Clayton0baa3942010-11-04 01:54:29 +0000988
989class CommandObjectProcessLoad : public CommandObject
990{
991public:
992
993 CommandObjectProcessLoad (CommandInterpreter &interpreter) :
994 CommandObject (interpreter,
995 "process load",
996 "Load a shared library into the current process.",
997 "process load <filename> [<filename> ...]",
998 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
999 {
1000 }
1001
1002 ~CommandObjectProcessLoad ()
1003 {
1004 }
1005
1006 bool
1007 Execute (Args& command,
1008 CommandReturnObject &result)
1009 {
Greg Clayton567e7f32011-09-22 04:58:26 +00001010 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Greg Clayton0baa3942010-11-04 01:54:29 +00001011 if (process == NULL)
1012 {
1013 result.AppendError ("must have a valid process in order to load a shared library");
1014 result.SetStatus (eReturnStatusFailed);
1015 return false;
1016 }
1017
1018 const uint32_t argc = command.GetArgumentCount();
1019
1020 for (uint32_t i=0; i<argc; ++i)
1021 {
1022 Error error;
1023 const char *image_path = command.GetArgumentAtIndex(i);
1024 FileSpec image_spec (image_path, false);
Greg Claytonf2bf8702011-08-11 16:25:18 +00001025 process->GetTarget().GetPlatform()->ResolveRemotePath(image_spec, image_spec);
Greg Clayton0baa3942010-11-04 01:54:29 +00001026 uint32_t image_token = process->LoadImage(image_spec, error);
1027 if (image_token != LLDB_INVALID_IMAGE_TOKEN)
1028 {
1029 result.AppendMessageWithFormat ("Loading \"%s\"...ok\nImage %u loaded.\n", image_path, image_token);
1030 result.SetStatus (eReturnStatusSuccessFinishResult);
1031 }
1032 else
1033 {
1034 result.AppendErrorWithFormat ("failed to load '%s': %s", image_path, error.AsCString());
1035 result.SetStatus (eReturnStatusFailed);
1036 }
1037 }
1038 return result.Succeeded();
1039 }
1040};
1041
1042
1043//-------------------------------------------------------------------------
1044// CommandObjectProcessUnload
1045//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +00001046#pragma mark CommandObjectProcessUnload
Greg Clayton0baa3942010-11-04 01:54:29 +00001047
1048class CommandObjectProcessUnload : public CommandObject
1049{
1050public:
1051
1052 CommandObjectProcessUnload (CommandInterpreter &interpreter) :
1053 CommandObject (interpreter,
1054 "process unload",
1055 "Unload a shared library from the current process using the index returned by a previous call to \"process load\".",
1056 "process unload <index>",
1057 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
1058 {
1059 }
1060
1061 ~CommandObjectProcessUnload ()
1062 {
1063 }
1064
1065 bool
1066 Execute (Args& command,
1067 CommandReturnObject &result)
1068 {
Greg Clayton567e7f32011-09-22 04:58:26 +00001069 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Greg Clayton0baa3942010-11-04 01:54:29 +00001070 if (process == NULL)
1071 {
1072 result.AppendError ("must have a valid process in order to load a shared library");
1073 result.SetStatus (eReturnStatusFailed);
1074 return false;
1075 }
1076
1077 const uint32_t argc = command.GetArgumentCount();
1078
1079 for (uint32_t i=0; i<argc; ++i)
1080 {
1081 const char *image_token_cstr = command.GetArgumentAtIndex(i);
1082 uint32_t image_token = Args::StringToUInt32(image_token_cstr, LLDB_INVALID_IMAGE_TOKEN, 0);
1083 if (image_token == LLDB_INVALID_IMAGE_TOKEN)
1084 {
1085 result.AppendErrorWithFormat ("invalid image index argument '%s'", image_token_cstr);
1086 result.SetStatus (eReturnStatusFailed);
1087 break;
1088 }
1089 else
1090 {
1091 Error error (process->UnloadImage(image_token));
1092 if (error.Success())
1093 {
1094 result.AppendMessageWithFormat ("Unloading shared library with index %u...ok\n", image_token);
1095 result.SetStatus (eReturnStatusSuccessFinishResult);
1096 }
1097 else
1098 {
1099 result.AppendErrorWithFormat ("failed to unload image: %s", error.AsCString());
1100 result.SetStatus (eReturnStatusFailed);
1101 break;
1102 }
1103 }
1104 }
1105 return result.Succeeded();
1106 }
1107};
1108
1109//-------------------------------------------------------------------------
Chris Lattner24943d22010-06-08 16:52:24 +00001110// CommandObjectProcessSignal
1111//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +00001112#pragma mark CommandObjectProcessSignal
Chris Lattner24943d22010-06-08 16:52:24 +00001113
1114class CommandObjectProcessSignal : public CommandObject
1115{
1116public:
1117
Greg Clayton238c0a12010-09-18 01:14:36 +00001118 CommandObjectProcessSignal (CommandInterpreter &interpreter) :
1119 CommandObject (interpreter,
1120 "process signal",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001121 "Send a UNIX signal to the current process being debugged.",
Caroline Tice43b014a2010-10-04 22:28:36 +00001122 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +00001123 {
Caroline Tice43b014a2010-10-04 22:28:36 +00001124 CommandArgumentEntry arg;
1125 CommandArgumentData signal_arg;
1126
1127 // Define the first (and only) variant of this arg.
Caroline Tice3a62e6d2010-10-18 22:56:57 +00001128 signal_arg.arg_type = eArgTypeUnixSignal;
Caroline Tice43b014a2010-10-04 22:28:36 +00001129 signal_arg.arg_repetition = eArgRepeatPlain;
1130
1131 // There is only one variant this argument could be; put it into the argument entry.
1132 arg.push_back (signal_arg);
1133
1134 // Push the data for the first argument into the m_arguments vector.
1135 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +00001136 }
1137
1138 ~CommandObjectProcessSignal ()
1139 {
1140 }
1141
1142 bool
Greg Clayton238c0a12010-09-18 01:14:36 +00001143 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +00001144 CommandReturnObject &result)
1145 {
Greg Clayton567e7f32011-09-22 04:58:26 +00001146 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Chris Lattner24943d22010-06-08 16:52:24 +00001147 if (process == NULL)
1148 {
1149 result.AppendError ("no process to signal");
1150 result.SetStatus (eReturnStatusFailed);
1151 return false;
1152 }
1153
1154 if (command.GetArgumentCount() == 1)
1155 {
Greg Clayton8f6be2a2010-10-09 01:40:57 +00001156 int signo = LLDB_INVALID_SIGNAL_NUMBER;
1157
1158 const char *signal_name = command.GetArgumentAtIndex(0);
1159 if (::isxdigit (signal_name[0]))
1160 signo = Args::StringToSInt32(signal_name, LLDB_INVALID_SIGNAL_NUMBER, 0);
1161 else
1162 signo = process->GetUnixSignals().GetSignalNumberFromName (signal_name);
1163
1164 if (signo == LLDB_INVALID_SIGNAL_NUMBER)
Chris Lattner24943d22010-06-08 16:52:24 +00001165 {
1166 result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0));
1167 result.SetStatus (eReturnStatusFailed);
1168 }
1169 else
1170 {
1171 Error error (process->Signal (signo));
1172 if (error.Success())
1173 {
1174 result.SetStatus (eReturnStatusSuccessFinishResult);
1175 }
1176 else
1177 {
1178 result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString());
1179 result.SetStatus (eReturnStatusFailed);
1180 }
1181 }
1182 }
1183 else
1184 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001185 result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: %s\n", m_cmd_name.c_str(),
Chris Lattner24943d22010-06-08 16:52:24 +00001186 m_cmd_syntax.c_str());
1187 result.SetStatus (eReturnStatusFailed);
1188 }
1189 return result.Succeeded();
1190 }
1191};
1192
1193
1194//-------------------------------------------------------------------------
1195// CommandObjectProcessInterrupt
1196//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +00001197#pragma mark CommandObjectProcessInterrupt
Chris Lattner24943d22010-06-08 16:52:24 +00001198
1199class CommandObjectProcessInterrupt : public CommandObject
1200{
1201public:
1202
1203
Greg Clayton238c0a12010-09-18 01:14:36 +00001204 CommandObjectProcessInterrupt (CommandInterpreter &interpreter) :
1205 CommandObject (interpreter,
1206 "process interrupt",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001207 "Interrupt the current process being debugged.",
Chris Lattner24943d22010-06-08 16:52:24 +00001208 "process interrupt",
1209 eFlagProcessMustBeLaunched)
1210 {
1211 }
1212
1213 ~CommandObjectProcessInterrupt ()
1214 {
1215 }
1216
1217 bool
Greg Clayton238c0a12010-09-18 01:14:36 +00001218 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +00001219 CommandReturnObject &result)
1220 {
Greg Clayton567e7f32011-09-22 04:58:26 +00001221 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Chris Lattner24943d22010-06-08 16:52:24 +00001222 if (process == NULL)
1223 {
1224 result.AppendError ("no process to halt");
1225 result.SetStatus (eReturnStatusFailed);
1226 return false;
1227 }
1228
1229 if (command.GetArgumentCount() == 0)
1230 {
1231 Error error(process->Halt ());
1232 if (error.Success())
1233 {
1234 result.SetStatus (eReturnStatusSuccessFinishResult);
1235
1236 // Maybe we should add a "SuspendThreadPlans so we
1237 // can halt, and keep in place all the current thread plans.
1238 process->GetThreadList().DiscardThreadPlans();
1239 }
1240 else
1241 {
1242 result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString());
1243 result.SetStatus (eReturnStatusFailed);
1244 }
1245 }
1246 else
1247 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001248 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n",
Chris Lattner24943d22010-06-08 16:52:24 +00001249 m_cmd_name.c_str(),
1250 m_cmd_syntax.c_str());
1251 result.SetStatus (eReturnStatusFailed);
1252 }
1253 return result.Succeeded();
1254 }
1255};
1256
1257//-------------------------------------------------------------------------
1258// CommandObjectProcessKill
1259//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +00001260#pragma mark CommandObjectProcessKill
Chris Lattner24943d22010-06-08 16:52:24 +00001261
1262class CommandObjectProcessKill : public CommandObject
1263{
1264public:
1265
Greg Clayton238c0a12010-09-18 01:14:36 +00001266 CommandObjectProcessKill (CommandInterpreter &interpreter) :
1267 CommandObject (interpreter,
1268 "process kill",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001269 "Terminate the current process being debugged.",
Chris Lattner24943d22010-06-08 16:52:24 +00001270 "process kill",
1271 eFlagProcessMustBeLaunched)
1272 {
1273 }
1274
1275 ~CommandObjectProcessKill ()
1276 {
1277 }
1278
1279 bool
Greg Clayton238c0a12010-09-18 01:14:36 +00001280 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +00001281 CommandReturnObject &result)
1282 {
Greg Clayton567e7f32011-09-22 04:58:26 +00001283 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Chris Lattner24943d22010-06-08 16:52:24 +00001284 if (process == NULL)
1285 {
1286 result.AppendError ("no process to kill");
1287 result.SetStatus (eReturnStatusFailed);
1288 return false;
1289 }
1290
1291 if (command.GetArgumentCount() == 0)
1292 {
1293 Error error (process->Destroy());
1294 if (error.Success())
1295 {
1296 result.SetStatus (eReturnStatusSuccessFinishResult);
1297 }
1298 else
1299 {
1300 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString());
1301 result.SetStatus (eReturnStatusFailed);
1302 }
1303 }
1304 else
1305 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001306 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n",
Chris Lattner24943d22010-06-08 16:52:24 +00001307 m_cmd_name.c_str(),
1308 m_cmd_syntax.c_str());
1309 result.SetStatus (eReturnStatusFailed);
1310 }
1311 return result.Succeeded();
1312 }
1313};
1314
1315//-------------------------------------------------------------------------
Jim Ingham41313fc2010-06-18 01:23:09 +00001316// CommandObjectProcessStatus
1317//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +00001318#pragma mark CommandObjectProcessStatus
1319
Jim Ingham41313fc2010-06-18 01:23:09 +00001320class CommandObjectProcessStatus : public CommandObject
1321{
1322public:
Greg Clayton238c0a12010-09-18 01:14:36 +00001323 CommandObjectProcessStatus (CommandInterpreter &interpreter) :
1324 CommandObject (interpreter,
1325 "process status",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001326 "Show the current status and location of executing process.",
1327 "process status",
Jim Ingham41313fc2010-06-18 01:23:09 +00001328 0)
1329 {
1330 }
1331
1332 ~CommandObjectProcessStatus()
1333 {
1334 }
1335
1336
1337 bool
1338 Execute
1339 (
1340 Args& command,
Jim Ingham41313fc2010-06-18 01:23:09 +00001341 CommandReturnObject &result
1342 )
1343 {
Greg Claytonabe0fed2011-04-18 08:33:37 +00001344 Stream &strm = result.GetOutputStream();
Jim Ingham41313fc2010-06-18 01:23:09 +00001345 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Greg Claytonb72d0f02011-04-12 05:54:46 +00001346 ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
Greg Clayton567e7f32011-09-22 04:58:26 +00001347 Process *process = exe_ctx.GetProcessPtr();
1348 if (process)
Jim Ingham41313fc2010-06-18 01:23:09 +00001349 {
Greg Claytonabe0fed2011-04-18 08:33:37 +00001350 const bool only_threads_with_stop_reason = true;
1351 const uint32_t start_frame = 0;
1352 const uint32_t num_frames = 1;
1353 const uint32_t num_frames_with_source = 1;
Greg Clayton567e7f32011-09-22 04:58:26 +00001354 process->GetStatus(strm);
1355 process->GetThreadStatus (strm,
1356 only_threads_with_stop_reason,
1357 start_frame,
1358 num_frames,
1359 num_frames_with_source);
Greg Claytonabe0fed2011-04-18 08:33:37 +00001360
Jim Ingham41313fc2010-06-18 01:23:09 +00001361 }
1362 else
1363 {
Greg Claytonabe0fed2011-04-18 08:33:37 +00001364 result.AppendError ("No process.");
Jim Ingham41313fc2010-06-18 01:23:09 +00001365 result.SetStatus (eReturnStatusFailed);
1366 }
1367 return result.Succeeded();
1368 }
1369};
1370
1371//-------------------------------------------------------------------------
Caroline Tice23d6f272010-10-13 20:44:39 +00001372// CommandObjectProcessHandle
1373//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +00001374#pragma mark CommandObjectProcessHandle
Caroline Tice23d6f272010-10-13 20:44:39 +00001375
1376class CommandObjectProcessHandle : public CommandObject
1377{
1378public:
1379
1380 class CommandOptions : public Options
1381 {
1382 public:
1383
Greg Claytonf15996e2011-04-07 22:46:35 +00001384 CommandOptions (CommandInterpreter &interpreter) :
1385 Options (interpreter)
Caroline Tice23d6f272010-10-13 20:44:39 +00001386 {
Greg Clayton143fcc32011-04-13 00:18:08 +00001387 OptionParsingStarting ();
Caroline Tice23d6f272010-10-13 20:44:39 +00001388 }
1389
1390 ~CommandOptions ()
1391 {
1392 }
1393
1394 Error
Greg Clayton143fcc32011-04-13 00:18:08 +00001395 SetOptionValue (uint32_t option_idx, const char *option_arg)
Caroline Tice23d6f272010-10-13 20:44:39 +00001396 {
1397 Error error;
1398 char short_option = (char) m_getopt_table[option_idx].val;
1399
1400 switch (short_option)
1401 {
1402 case 's':
1403 stop = option_arg;
1404 break;
1405 case 'n':
1406 notify = option_arg;
1407 break;
1408 case 'p':
1409 pass = option_arg;
1410 break;
1411 default:
Greg Clayton9c236732011-10-26 00:56:27 +00001412 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
Caroline Tice23d6f272010-10-13 20:44:39 +00001413 break;
1414 }
1415 return error;
1416 }
1417
1418 void
Greg Clayton143fcc32011-04-13 00:18:08 +00001419 OptionParsingStarting ()
Caroline Tice23d6f272010-10-13 20:44:39 +00001420 {
Caroline Tice23d6f272010-10-13 20:44:39 +00001421 stop.clear();
1422 notify.clear();
1423 pass.clear();
1424 }
1425
Greg Claytonb3448432011-03-24 21:19:54 +00001426 const OptionDefinition*
Caroline Tice23d6f272010-10-13 20:44:39 +00001427 GetDefinitions ()
1428 {
1429 return g_option_table;
1430 }
1431
1432 // Options table: Required for subclasses of Options.
1433
Greg Claytonb3448432011-03-24 21:19:54 +00001434 static OptionDefinition g_option_table[];
Caroline Tice23d6f272010-10-13 20:44:39 +00001435
1436 // Instance variables to hold the values for command options.
1437
1438 std::string stop;
1439 std::string notify;
1440 std::string pass;
1441 };
1442
1443
1444 CommandObjectProcessHandle (CommandInterpreter &interpreter) :
1445 CommandObject (interpreter,
1446 "process handle",
Caroline Ticee7471982010-10-14 21:31:13 +00001447 "Show or update what the process and debugger should do with various signals received from the OS.",
Greg Claytonf15996e2011-04-07 22:46:35 +00001448 NULL),
1449 m_options (interpreter)
Caroline Tice23d6f272010-10-13 20:44:39 +00001450 {
Caroline Ticee7471982010-10-14 21:31:13 +00001451 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 +00001452 CommandArgumentEntry arg;
Caroline Tice3a62e6d2010-10-18 22:56:57 +00001453 CommandArgumentData signal_arg;
Caroline Tice23d6f272010-10-13 20:44:39 +00001454
Caroline Tice3a62e6d2010-10-18 22:56:57 +00001455 signal_arg.arg_type = eArgTypeUnixSignal;
1456 signal_arg.arg_repetition = eArgRepeatStar;
Caroline Tice23d6f272010-10-13 20:44:39 +00001457
Caroline Tice3a62e6d2010-10-18 22:56:57 +00001458 arg.push_back (signal_arg);
Caroline Tice23d6f272010-10-13 20:44:39 +00001459
1460 m_arguments.push_back (arg);
1461 }
1462
1463 ~CommandObjectProcessHandle ()
1464 {
1465 }
1466
1467 Options *
1468 GetOptions ()
1469 {
1470 return &m_options;
1471 }
1472
1473 bool
Caroline Ticee7471982010-10-14 21:31:13 +00001474 VerifyCommandOptionValue (const std::string &option, int &real_value)
Caroline Tice23d6f272010-10-13 20:44:39 +00001475 {
1476 bool okay = true;
1477
Caroline Ticee7471982010-10-14 21:31:13 +00001478 bool success = false;
1479 bool tmp_value = Args::StringToBoolean (option.c_str(), false, &success);
1480
1481 if (success && tmp_value)
1482 real_value = 1;
1483 else if (success && !tmp_value)
1484 real_value = 0;
Caroline Tice23d6f272010-10-13 20:44:39 +00001485 else
1486 {
1487 // If the value isn't 'true' or 'false', it had better be 0 or 1.
Caroline Ticee7471982010-10-14 21:31:13 +00001488 real_value = Args::StringToUInt32 (option.c_str(), 3);
1489 if (real_value != 0 && real_value != 1)
Caroline Tice23d6f272010-10-13 20:44:39 +00001490 okay = false;
1491 }
1492
1493 return okay;
1494 }
1495
Caroline Ticee7471982010-10-14 21:31:13 +00001496 void
1497 PrintSignalHeader (Stream &str)
1498 {
1499 str.Printf ("NAME PASS STOP NOTIFY\n");
1500 str.Printf ("========== ===== ===== ======\n");
1501 }
1502
1503 void
1504 PrintSignal (Stream &str, int32_t signo, const char *sig_name, UnixSignals &signals)
1505 {
1506 bool stop;
1507 bool suppress;
1508 bool notify;
1509
1510 str.Printf ("%-10s ", sig_name);
1511 if (signals.GetSignalInfo (signo, suppress, stop, notify))
1512 {
1513 bool pass = !suppress;
1514 str.Printf ("%s %s %s",
1515 (pass ? "true " : "false"),
1516 (stop ? "true " : "false"),
1517 (notify ? "true " : "false"));
1518 }
1519 str.Printf ("\n");
1520 }
1521
1522 void
1523 PrintSignalInformation (Stream &str, Args &signal_args, int num_valid_signals, UnixSignals &signals)
1524 {
1525 PrintSignalHeader (str);
1526
1527 if (num_valid_signals > 0)
1528 {
1529 size_t num_args = signal_args.GetArgumentCount();
1530 for (size_t i = 0; i < num_args; ++i)
1531 {
1532 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
1533 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
1534 PrintSignal (str, signo, signal_args.GetArgumentAtIndex (i), signals);
1535 }
1536 }
1537 else // Print info for ALL signals
1538 {
1539 int32_t signo = signals.GetFirstSignalNumber();
1540 while (signo != LLDB_INVALID_SIGNAL_NUMBER)
1541 {
1542 PrintSignal (str, signo, signals.GetSignalAsCString (signo), signals);
1543 signo = signals.GetNextSignalNumber (signo);
1544 }
1545 }
1546 }
1547
Caroline Tice23d6f272010-10-13 20:44:39 +00001548 bool
1549 Execute (Args &signal_args, CommandReturnObject &result)
1550 {
1551 TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
1552
1553 if (!target_sp)
1554 {
1555 result.AppendError ("No current target;"
1556 " cannot handle signals until you have a valid target and process.\n");
1557 result.SetStatus (eReturnStatusFailed);
1558 return false;
1559 }
1560
1561 ProcessSP process_sp = target_sp->GetProcessSP();
1562
1563 if (!process_sp)
1564 {
1565 result.AppendError ("No current process; cannot handle signals until you have a valid process.\n");
1566 result.SetStatus (eReturnStatusFailed);
1567 return false;
1568 }
1569
Caroline Tice23d6f272010-10-13 20:44:39 +00001570 int stop_action = -1; // -1 means leave the current setting alone
Caroline Ticee7471982010-10-14 21:31:13 +00001571 int pass_action = -1; // -1 means leave the current setting alone
Caroline Tice23d6f272010-10-13 20:44:39 +00001572 int notify_action = -1; // -1 means leave the current setting alone
1573
1574 if (! m_options.stop.empty()
Caroline Ticee7471982010-10-14 21:31:13 +00001575 && ! VerifyCommandOptionValue (m_options.stop, stop_action))
Caroline Tice23d6f272010-10-13 20:44:39 +00001576 {
1577 result.AppendError ("Invalid argument for command option --stop; must be true or false.\n");
1578 result.SetStatus (eReturnStatusFailed);
1579 return false;
1580 }
1581
1582 if (! m_options.notify.empty()
Caroline Ticee7471982010-10-14 21:31:13 +00001583 && ! VerifyCommandOptionValue (m_options.notify, notify_action))
Caroline Tice23d6f272010-10-13 20:44:39 +00001584 {
1585 result.AppendError ("Invalid argument for command option --notify; must be true or false.\n");
1586 result.SetStatus (eReturnStatusFailed);
1587 return false;
1588 }
1589
1590 if (! m_options.pass.empty()
Caroline Ticee7471982010-10-14 21:31:13 +00001591 && ! VerifyCommandOptionValue (m_options.pass, pass_action))
Caroline Tice23d6f272010-10-13 20:44:39 +00001592 {
1593 result.AppendError ("Invalid argument for command option --pass; must be true or false.\n");
1594 result.SetStatus (eReturnStatusFailed);
1595 return false;
1596 }
1597
1598 size_t num_args = signal_args.GetArgumentCount();
1599 UnixSignals &signals = process_sp->GetUnixSignals();
1600 int num_signals_set = 0;
1601
Caroline Ticee7471982010-10-14 21:31:13 +00001602 if (num_args > 0)
Caroline Tice23d6f272010-10-13 20:44:39 +00001603 {
Caroline Ticee7471982010-10-14 21:31:13 +00001604 for (size_t i = 0; i < num_args; ++i)
Caroline Tice23d6f272010-10-13 20:44:39 +00001605 {
Caroline Ticee7471982010-10-14 21:31:13 +00001606 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
1607 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
Caroline Tice23d6f272010-10-13 20:44:39 +00001608 {
Caroline Ticee7471982010-10-14 21:31:13 +00001609 // Casting the actions as bools here should be okay, because VerifyCommandOptionValue guarantees
1610 // the value is either 0 or 1.
1611 if (stop_action != -1)
1612 signals.SetShouldStop (signo, (bool) stop_action);
1613 if (pass_action != -1)
1614 {
1615 bool suppress = ! ((bool) pass_action);
1616 signals.SetShouldSuppress (signo, suppress);
1617 }
1618 if (notify_action != -1)
1619 signals.SetShouldNotify (signo, (bool) notify_action);
1620 ++num_signals_set;
Caroline Tice23d6f272010-10-13 20:44:39 +00001621 }
Caroline Ticee7471982010-10-14 21:31:13 +00001622 else
1623 {
1624 result.AppendErrorWithFormat ("Invalid signal name '%s'\n", signal_args.GetArgumentAtIndex (i));
1625 }
Caroline Tice23d6f272010-10-13 20:44:39 +00001626 }
1627 }
Caroline Ticee7471982010-10-14 21:31:13 +00001628 else
1629 {
1630 // No signal specified, if any command options were specified, update ALL signals.
1631 if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1))
1632 {
1633 if (m_interpreter.Confirm ("Do you really want to update all the signals?", false))
1634 {
1635 int32_t signo = signals.GetFirstSignalNumber();
1636 while (signo != LLDB_INVALID_SIGNAL_NUMBER)
1637 {
1638 if (notify_action != -1)
1639 signals.SetShouldNotify (signo, (bool) notify_action);
1640 if (stop_action != -1)
1641 signals.SetShouldStop (signo, (bool) stop_action);
1642 if (pass_action != -1)
1643 {
1644 bool suppress = ! ((bool) pass_action);
1645 signals.SetShouldSuppress (signo, suppress);
1646 }
1647 signo = signals.GetNextSignalNumber (signo);
1648 }
1649 }
1650 }
1651 }
1652
1653 PrintSignalInformation (result.GetOutputStream(), signal_args, num_signals_set, signals);
Caroline Tice23d6f272010-10-13 20:44:39 +00001654
1655 if (num_signals_set > 0)
1656 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1657 else
1658 result.SetStatus (eReturnStatusFailed);
1659
1660 return result.Succeeded();
1661 }
1662
1663protected:
1664
1665 CommandOptions m_options;
1666};
1667
Greg Claytonb3448432011-03-24 21:19:54 +00001668OptionDefinition
Caroline Tice23d6f272010-10-13 20:44:39 +00001669CommandObjectProcessHandle::CommandOptions::g_option_table[] =
1670{
1671{ 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." },
1672{ 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." },
1673{ LLDB_OPT_SET_1, false, "pass", 'p', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." },
1674{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1675};
1676
1677//-------------------------------------------------------------------------
Chris Lattner24943d22010-06-08 16:52:24 +00001678// CommandObjectMultiwordProcess
1679//-------------------------------------------------------------------------
1680
Greg Clayton63094e02010-06-23 01:19:29 +00001681CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001682 CommandObjectMultiword (interpreter,
1683 "process",
1684 "A set of commands for operating on a process.",
1685 "process <subcommand> [<subcommand-options>]")
Chris Lattner24943d22010-06-08 16:52:24 +00001686{
Greg Claytona9eb8272011-07-02 21:07:54 +00001687 LoadSubCommand ("attach", CommandObjectSP (new CommandObjectProcessAttach (interpreter)));
1688 LoadSubCommand ("launch", CommandObjectSP (new CommandObjectProcessLaunch (interpreter)));
1689 LoadSubCommand ("continue", CommandObjectSP (new CommandObjectProcessContinue (interpreter)));
1690 LoadSubCommand ("connect", CommandObjectSP (new CommandObjectProcessConnect (interpreter)));
1691 LoadSubCommand ("detach", CommandObjectSP (new CommandObjectProcessDetach (interpreter)));
1692 LoadSubCommand ("load", CommandObjectSP (new CommandObjectProcessLoad (interpreter)));
1693 LoadSubCommand ("unload", CommandObjectSP (new CommandObjectProcessUnload (interpreter)));
1694 LoadSubCommand ("signal", CommandObjectSP (new CommandObjectProcessSignal (interpreter)));
1695 LoadSubCommand ("handle", CommandObjectSP (new CommandObjectProcessHandle (interpreter)));
1696 LoadSubCommand ("status", CommandObjectSP (new CommandObjectProcessStatus (interpreter)));
Greg Clayton238c0a12010-09-18 01:14:36 +00001697 LoadSubCommand ("interrupt", CommandObjectSP (new CommandObjectProcessInterrupt (interpreter)));
Greg Claytona9eb8272011-07-02 21:07:54 +00001698 LoadSubCommand ("kill", CommandObjectSP (new CommandObjectProcessKill (interpreter)));
Chris Lattner24943d22010-06-08 16:52:24 +00001699}
1700
1701CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess ()
1702{
1703}
1704