blob: 7e18e124d678191fe1f634cee12c1ccbe69d8d3c [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- CommandObjectProcess.cpp --------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "CommandObjectProcess.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
Jim Ingham84cdc152010-06-15 19:49:27 +000016#include "lldb/Interpreter/Args.h"
17#include "lldb/Interpreter/Options.h"
Chris Lattner24943d22010-06-08 16:52:24 +000018#include "lldb/Core/State.h"
19#include "lldb/Interpreter/CommandInterpreter.h"
20#include "lldb/Interpreter/CommandReturnObject.h"
Jim Ingham41313fc2010-06-18 01:23:09 +000021#include "./CommandObjectThread.h"
Greg Claytoncd548032011-02-01 01:31:41 +000022#include "lldb/Host/Host.h"
Chris Lattner24943d22010-06-08 16:52:24 +000023#include "lldb/Target/Process.h"
24#include "lldb/Target/Target.h"
25#include "lldb/Target/Thread.h"
26
27using namespace lldb;
28using namespace lldb_private;
29
30//-------------------------------------------------------------------------
31// CommandObjectProcessLaunch
32//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +000033#pragma mark CommandObjectProjectLaunch
Chris Lattner24943d22010-06-08 16:52:24 +000034class CommandObjectProcessLaunch : public CommandObject
35{
36public:
37
38 class CommandOptions : public Options
39 {
40 public:
41
42 CommandOptions () :
43 Options()
44 {
45 // Keep default values of all options in one place: ResetOptionValues ()
46 ResetOptionValues ();
47 }
48
49 ~CommandOptions ()
50 {
51 }
52
53 Error
54 SetOptionValue (int option_idx, const char *option_arg)
55 {
56 Error error;
57 char short_option = (char) m_getopt_table[option_idx].val;
58
59 switch (short_option)
60 {
Greg Claytonde915be2011-01-23 05:56:20 +000061 case 's': stop_at_entry = true; break;
62 case 'e': stderr_path.assign (option_arg); break;
63 case 'i': stdin_path.assign (option_arg); break;
64 case 'o': stdout_path.assign (option_arg); break;
65 case 'p': plugin_name.assign (option_arg); break;
66 case 'n': no_stdio = true; break;
67 case 'w': working_dir.assign (option_arg); break;
Greg Claytonbb0c91f2010-10-19 23:16:00 +000068 case 't':
69 if (option_arg && option_arg[0])
70 tty_name.assign (option_arg);
71 in_new_tty = true;
72 break;
Chris Lattner24943d22010-06-08 16:52:24 +000073 default:
74 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
75 break;
76
77 }
78 return error;
79 }
80
81 void
82 ResetOptionValues ()
83 {
84 Options::ResetOptionValues();
85 stop_at_entry = false;
Greg Claytonc1d37752010-10-18 01:45:30 +000086 in_new_tty = false;
Greg Claytonbb0c91f2010-10-19 23:16:00 +000087 tty_name.clear();
Chris Lattner24943d22010-06-08 16:52:24 +000088 stdin_path.clear();
89 stdout_path.clear();
90 stderr_path.clear();
91 plugin_name.clear();
Greg Claytonde915be2011-01-23 05:56:20 +000092 working_dir.clear();
Caroline Ticebd666012010-12-03 18:46:09 +000093 no_stdio = false;
Chris Lattner24943d22010-06-08 16:52:24 +000094 }
95
96 const lldb::OptionDefinition*
97 GetDefinitions ()
98 {
99 return g_option_table;
100 }
101
102 // Options table: Required for subclasses of Options.
103
104 static lldb::OptionDefinition g_option_table[];
105
106 // Instance variables to hold the values for command options.
107
108 bool stop_at_entry;
Greg Claytonc1d37752010-10-18 01:45:30 +0000109 bool in_new_tty;
Caroline Ticebd666012010-12-03 18:46:09 +0000110 bool no_stdio;
Greg Claytonbb0c91f2010-10-19 23:16:00 +0000111 std::string tty_name;
Chris Lattner24943d22010-06-08 16:52:24 +0000112 std::string stderr_path;
113 std::string stdin_path;
114 std::string stdout_path;
115 std::string plugin_name;
Greg Claytonde915be2011-01-23 05:56:20 +0000116 std::string working_dir;
Chris Lattner24943d22010-06-08 16:52:24 +0000117
118 };
119
Greg Clayton238c0a12010-09-18 01:14:36 +0000120 CommandObjectProcessLaunch (CommandInterpreter &interpreter) :
121 CommandObject (interpreter,
122 "process launch",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000123 "Launch the executable in the debugger.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000124 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000125 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000126 CommandArgumentEntry arg;
127 CommandArgumentData run_args_arg;
128
129 // Define the first (and only) variant of this arg.
130 run_args_arg.arg_type = eArgTypeRunArgs;
131 run_args_arg.arg_repetition = eArgRepeatOptional;
132
133 // There is only one variant this argument could be; put it into the argument entry.
134 arg.push_back (run_args_arg);
135
136 // Push the data for the first argument into the m_arguments vector.
137 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000138 }
139
140
141 ~CommandObjectProcessLaunch ()
142 {
143 }
144
145 Options *
146 GetOptions ()
147 {
148 return &m_options;
149 }
150
151 bool
Greg Claytond8c62532010-10-07 04:19:01 +0000152 Execute (Args& launch_args, CommandReturnObject &result)
Chris Lattner24943d22010-06-08 16:52:24 +0000153 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000154 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000155
156 if (target == NULL)
157 {
158 result.AppendError ("invalid target, set executable file using 'file' command");
159 result.SetStatus (eReturnStatusFailed);
160 return false;
161 }
162
163 // If our listener is NULL, users aren't allows to launch
Chris Lattner24943d22010-06-08 16:52:24 +0000164 char filename[PATH_MAX];
Greg Claytonc1d37752010-10-18 01:45:30 +0000165 const Module *exe_module = target->GetExecutableModule().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000166 exe_module->GetFileSpec().GetPath(filename, sizeof(filename));
167
Greg Clayton238c0a12010-09-18 01:14:36 +0000168 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
169 if (process && process->IsAlive())
Jim Ingham22dc9722010-12-09 18:58:16 +0000170 {
Greg Clayton7e2f91c2011-01-29 07:10:55 +0000171 char message[1024];
172 if (process->GetState() == eStateAttaching)
173 ::strncpy (message, "There is a pending attach, abort it and launch a new process?", sizeof(message));
174 else
175 ::strncpy (message, "There is a running process, kill it and restart?", sizeof(message));
176
177 if (!m_interpreter.Confirm (message, true))
Jim Ingham22dc9722010-12-09 18:58:16 +0000178 {
Jim Ingham22dc9722010-12-09 18:58:16 +0000179 result.SetStatus (eReturnStatusFailed);
180 return false;
181 }
182 else
183 {
184 Error error (process->Destroy());
185 if (error.Success())
186 {
187 result.SetStatus (eReturnStatusSuccessFinishResult);
188 }
189 else
190 {
191 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString());
192 result.SetStatus (eReturnStatusFailed);
193 }
194 }
Chris Lattner24943d22010-06-08 16:52:24 +0000195 }
Jim Ingham22dc9722010-12-09 18:58:16 +0000196
Chris Lattner24943d22010-06-08 16:52:24 +0000197 const char *plugin_name;
198 if (!m_options.plugin_name.empty())
199 plugin_name = m_options.plugin_name.c_str();
200 else
201 plugin_name = NULL;
202
Greg Clayton238c0a12010-09-18 01:14:36 +0000203 process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
Chris Lattner24943d22010-06-08 16:52:24 +0000204
Greg Clayton238c0a12010-09-18 01:14:36 +0000205 if (process == NULL)
Caroline Tice6e4c5ce2010-09-04 00:03:46 +0000206 {
Caroline Tice734b4832010-10-15 21:52:38 +0000207 result.AppendErrorWithFormat ("Failed to find a process plugin for executable.\n");
Chris Lattner24943d22010-06-08 16:52:24 +0000208 result.SetStatus (eReturnStatusFailed);
209 return false;
210 }
211
Greg Clayton238c0a12010-09-18 01:14:36 +0000212 // If no launch args were given on the command line, then use any that
213 // might have been set using the "run-args" set variable.
214 if (launch_args.GetArgumentCount() == 0)
215 {
216 if (process->GetRunArguments().GetArgumentCount() > 0)
217 launch_args = process->GetRunArguments();
218 }
219
Greg Claytonc1d37752010-10-18 01:45:30 +0000220 if (m_options.in_new_tty)
221 {
222 char exec_file_path[PATH_MAX];
223 if (exe_module->GetFileSpec().GetPath(exec_file_path, sizeof(exec_file_path)))
224 {
225 launch_args.InsertArgumentAtIndex(0, exec_file_path);
226 }
227 else
228 {
229 result.AppendError("invalid executable");
230 result.SetStatus (eReturnStatusFailed);
231 return false;
232 }
233 }
234
Greg Clayton238c0a12010-09-18 01:14:36 +0000235 Args environment;
236
237 process->GetEnvironmentAsArgs (environment);
238
239 uint32_t launch_flags = eLaunchFlagNone;
240
241 if (process->GetDisableASLR())
242 launch_flags |= eLaunchFlagDisableASLR;
Greg Claytonc1d37752010-10-18 01:45:30 +0000243
Caroline Ticebd666012010-12-03 18:46:09 +0000244 if (m_options.no_stdio)
245 launch_flags |= eLaunchFlagDisableSTDIO;
246 else if (!m_options.in_new_tty
247 && m_options.stdin_path.empty()
248 && m_options.stdout_path.empty()
249 && m_options.stderr_path.empty())
250 {
251 // Only use the settings value if the user hasn't specified any options that would override it.
252 if (process->GetDisableSTDIO())
253 launch_flags |= eLaunchFlagDisableSTDIO;
254 }
255
Greg Claytonc1d37752010-10-18 01:45:30 +0000256 const char **inferior_argv = launch_args.GetArgumentCount() ? launch_args.GetConstArgumentVector() : NULL;
257 const char **inferior_envp = environment.GetArgumentCount() ? environment.GetConstArgumentVector() : NULL;
Greg Clayton238c0a12010-09-18 01:14:36 +0000258
Greg Claytonc1d37752010-10-18 01:45:30 +0000259 Error error;
Greg Claytonde915be2011-01-23 05:56:20 +0000260 const char *working_dir = NULL;
261 if (!m_options.working_dir.empty())
262 working_dir = m_options.working_dir.c_str();
Greg Clayton238c0a12010-09-18 01:14:36 +0000263
Greg Claytonc1d37752010-10-18 01:45:30 +0000264 if (m_options.in_new_tty)
Greg Clayton238c0a12010-09-18 01:14:36 +0000265 {
Greg Claytonc1d37752010-10-18 01:45:30 +0000266
Greg Claytonbb0c91f2010-10-19 23:16:00 +0000267 lldb::pid_t pid = Host::LaunchInNewTerminal (m_options.tty_name.c_str(),
268 inferior_argv,
Greg Clayton36f63a92010-10-19 03:25:40 +0000269 inferior_envp,
Greg Claytonde915be2011-01-23 05:56:20 +0000270 working_dir,
Greg Clayton36f63a92010-10-19 03:25:40 +0000271 &exe_module->GetArchitecture(),
272 true,
273 process->GetDisableASLR());
Greg Claytonc1d37752010-10-18 01:45:30 +0000274
Greg Clayton36f63a92010-10-19 03:25:40 +0000275 if (pid != LLDB_INVALID_PROCESS_ID)
276 error = process->Attach (pid);
Greg Clayton238c0a12010-09-18 01:14:36 +0000277 }
278 else
279 {
Greg Claytonc1d37752010-10-18 01:45:30 +0000280 const char * stdin_path = NULL;
281 const char * stdout_path = NULL;
282 const char * stderr_path = NULL;
283
284 // Were any standard input/output/error paths given on the command line?
285 if (m_options.stdin_path.empty() &&
286 m_options.stdout_path.empty() &&
287 m_options.stderr_path.empty())
288 {
289 // No standard file handles were given on the command line, check
290 // with the process object in case they were give using "set settings"
291 stdin_path = process->GetStandardInputPath();
292 stdout_path = process->GetStandardOutputPath();
293 stderr_path = process->GetStandardErrorPath();
294 }
295 else
296 {
297 stdin_path = m_options.stdin_path.empty() ? NULL : m_options.stdin_path.c_str();
298 stdout_path = m_options.stdout_path.empty() ? NULL : m_options.stdout_path.c_str();
299 stderr_path = m_options.stderr_path.empty() ? NULL : m_options.stderr_path.c_str();
300 }
301
Greg Claytonc1d37752010-10-18 01:45:30 +0000302 error = process->Launch (inferior_argv,
303 inferior_envp,
304 launch_flags,
305 stdin_path,
306 stdout_path,
Greg Claytonde915be2011-01-23 05:56:20 +0000307 stderr_path,
308 working_dir);
Greg Clayton238c0a12010-09-18 01:14:36 +0000309 }
Greg Clayton238c0a12010-09-18 01:14:36 +0000310
311 if (error.Success())
312 {
Greg Clayton940b1032011-02-23 00:35:02 +0000313 const char *archname = exe_module->GetArchitecture().GetArchitectureName();
Greg Claytonc1d37752010-10-18 01:45:30 +0000314
315 result.AppendMessageWithFormat ("Process %i launched: '%s' (%s)\n", process->GetID(), filename, archname);
Greg Claytond8c62532010-10-07 04:19:01 +0000316 result.SetDidChangeProcessState (true);
Greg Clayton238c0a12010-09-18 01:14:36 +0000317 if (m_options.stop_at_entry == false)
318 {
Greg Claytond8c62532010-10-07 04:19:01 +0000319 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
Greg Clayton238c0a12010-09-18 01:14:36 +0000320 StateType state = process->WaitForProcessToStop (NULL);
321
322 if (state == eStateStopped)
323 {
Greg Claytond8c62532010-10-07 04:19:01 +0000324 error = process->Resume();
325 if (error.Success())
326 {
327 bool synchronous_execution = m_interpreter.GetSynchronous ();
328 if (synchronous_execution)
329 {
330 state = process->WaitForProcessToStop (NULL);
Greg Clayton940b1032011-02-23 00:35:02 +0000331 if (!StateIsStoppedState(state))
Greg Clayton395fc332011-02-15 21:59:32 +0000332 {
333 result.AppendErrorWithFormat ("Process isn't stopped: %s", StateAsCString(state));
334 }
Greg Claytond8c62532010-10-07 04:19:01 +0000335 result.SetDidChangeProcessState (true);
336 result.SetStatus (eReturnStatusSuccessFinishResult);
337 }
338 else
339 {
340 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
341 }
342 }
Greg Clayton395fc332011-02-15 21:59:32 +0000343 else
344 {
345 result.AppendErrorWithFormat ("Process resume at entry point failed: %s", error.AsCString());
346 result.SetStatus (eReturnStatusFailed);
347 }
Greg Clayton238c0a12010-09-18 01:14:36 +0000348 }
Greg Clayton395fc332011-02-15 21:59:32 +0000349 else
350 {
351 result.AppendErrorWithFormat ("Initial process state wasn't stopped: %s", StateAsCString(state));
352 result.SetStatus (eReturnStatusFailed);
353 }
Greg Clayton238c0a12010-09-18 01:14:36 +0000354 }
355 }
Greg Clayton395fc332011-02-15 21:59:32 +0000356 else
357 {
358 result.AppendErrorWithFormat ("Process launch failed: %s", error.AsCString());
359 result.SetStatus (eReturnStatusFailed);
360 }
Greg Clayton238c0a12010-09-18 01:14:36 +0000361
Chris Lattner24943d22010-06-08 16:52:24 +0000362 return result.Succeeded();
363 }
364
Jim Ingham767af882010-07-07 03:36:20 +0000365 virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
366 {
367 // No repeat for "process launch"...
368 return "";
369 }
370
Chris Lattner24943d22010-06-08 16:52:24 +0000371protected:
372
373 CommandOptions m_options;
374};
375
376
Greg Claytonc1d37752010-10-18 01:45:30 +0000377#define SET1 LLDB_OPT_SET_1
378#define SET2 LLDB_OPT_SET_2
Caroline Ticebd666012010-12-03 18:46:09 +0000379#define SET3 LLDB_OPT_SET_3
Greg Claytonc1d37752010-10-18 01:45:30 +0000380
Chris Lattner24943d22010-06-08 16:52:24 +0000381lldb::OptionDefinition
382CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
383{
Caroline Ticebd666012010-12-03 18:46:09 +0000384{ 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."},
385{ SET1 , false, "stdin", 'i', required_argument, NULL, 0, eArgTypePath, "Redirect stdin for the process to <path>."},
386{ SET1 , false, "stdout", 'o', required_argument, NULL, 0, eArgTypePath, "Redirect stdout for the process to <path>."},
387{ SET1 , false, "stderr", 'e', required_argument, NULL, 0, eArgTypePath, "Redirect stderr for the process to <path>."},
388{ SET1 | SET2 | SET3, false, "plugin", 'p', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
389{ 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."},
390{ SET3, false, "no-stdio", 'n', no_argument, NULL, 0, eArgTypeNone, "Do not set up for terminal I/O to go to running process."},
Greg Claytonde915be2011-01-23 05:56:20 +0000391{ SET1 | SET2 | SET3, false, "working-dir", 'w', required_argument, NULL, 0, eArgTypePath, "Set the current working directory to <path> when running the inferior."},
Caroline Ticebd666012010-12-03 18:46:09 +0000392{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +0000393};
394
Greg Claytonc1d37752010-10-18 01:45:30 +0000395#undef SET1
396#undef SET2
Caroline Ticebd666012010-12-03 18:46:09 +0000397#undef SET3
Chris Lattner24943d22010-06-08 16:52:24 +0000398
399//-------------------------------------------------------------------------
400// CommandObjectProcessAttach
401//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +0000402#pragma mark CommandObjectProcessAttach
Chris Lattner24943d22010-06-08 16:52:24 +0000403class CommandObjectProcessAttach : public CommandObject
404{
405public:
406
Chris Lattner24943d22010-06-08 16:52:24 +0000407 class CommandOptions : public Options
408 {
409 public:
410
411 CommandOptions () :
412 Options()
413 {
414 // Keep default values of all options in one place: ResetOptionValues ()
415 ResetOptionValues ();
416 }
417
418 ~CommandOptions ()
419 {
420 }
421
422 Error
423 SetOptionValue (int option_idx, const char *option_arg)
424 {
425 Error error;
426 char short_option = (char) m_getopt_table[option_idx].val;
427 bool success = false;
428 switch (short_option)
429 {
430 case 'p':
431 pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success);
432 if (!success || pid == LLDB_INVALID_PROCESS_ID)
433 {
434 error.SetErrorStringWithFormat("Invalid process ID '%s'.\n", option_arg);
435 }
436 break;
437
438 case 'P':
439 plugin_name = option_arg;
440 break;
441
442 case 'n':
443 name.assign(option_arg);
444 break;
445
446 case 'w':
447 waitfor = true;
448 break;
449
450 default:
451 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
452 break;
453 }
454 return error;
455 }
456
457 void
458 ResetOptionValues ()
459 {
460 Options::ResetOptionValues();
461 pid = LLDB_INVALID_PROCESS_ID;
462 name.clear();
463 waitfor = false;
464 }
465
466 const lldb::OptionDefinition*
467 GetDefinitions ()
468 {
469 return g_option_table;
470 }
471
Jim Ingham7508e732010-08-09 23:31:02 +0000472 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000473 HandleOptionArgumentCompletion (CommandInterpreter &interpeter,
Jim Ingham7508e732010-08-09 23:31:02 +0000474 Args &input,
475 int cursor_index,
476 int char_pos,
477 OptionElementVector &opt_element_vector,
478 int opt_element_index,
479 int match_start_point,
480 int max_return_elements,
481 bool &word_complete,
482 StringList &matches)
483 {
484 int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
485 int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
486
487 // We are only completing the name option for now...
488
489 const lldb::OptionDefinition *opt_defs = GetDefinitions();
490 if (opt_defs[opt_defs_index].short_option == 'n')
491 {
492 // Are we in the name?
493
494 // Look to see if there is a -P argument provided, and if so use that plugin, otherwise
495 // use the default plugin.
Greg Clayton238c0a12010-09-18 01:14:36 +0000496 Process *process = interpeter.GetDebugger().GetExecutionContext().process;
Jim Ingham7508e732010-08-09 23:31:02 +0000497 bool need_to_delete_process = false;
498
499 const char *partial_name = NULL;
500 partial_name = input.GetArgumentAtIndex(opt_arg_pos);
501
502 if (process && process->IsAlive())
503 return true;
504
Greg Clayton238c0a12010-09-18 01:14:36 +0000505 Target *target = interpeter.GetDebugger().GetSelectedTarget().get();
Jim Ingham7508e732010-08-09 23:31:02 +0000506 if (target == NULL)
507 {
508 // No target has been set yet, for now do host completion. Otherwise I don't know how we would
509 // figure out what the right target to use is...
510 std::vector<lldb::pid_t> pids;
511 Host::ListProcessesMatchingName (partial_name, matches, pids);
512 return true;
513 }
514 if (!process)
515 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000516 process = target->CreateProcess (interpeter.GetDebugger().GetListener(), partial_name).get();
Jim Ingham7508e732010-08-09 23:31:02 +0000517 need_to_delete_process = true;
518 }
519
520 if (process)
521 {
522 matches.Clear();
523 std::vector<lldb::pid_t> pids;
524 process->ListProcessesMatchingName (NULL, matches, pids);
525 if (need_to_delete_process)
526 target->DeleteCurrentProcess();
527 return true;
528 }
529 }
530
531 return false;
532 }
533
Chris Lattner24943d22010-06-08 16:52:24 +0000534 // Options table: Required for subclasses of Options.
535
536 static lldb::OptionDefinition g_option_table[];
537
538 // Instance variables to hold the values for command options.
539
540 lldb::pid_t pid;
541 std::string plugin_name;
542 std::string name;
543 bool waitfor;
544 };
545
Greg Clayton238c0a12010-09-18 01:14:36 +0000546 CommandObjectProcessAttach (CommandInterpreter &interpreter) :
547 CommandObject (interpreter,
548 "process attach",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000549 "Attach to a process.",
Jim Ingham7508e732010-08-09 23:31:02 +0000550 "process attach <cmd-options>")
551 {
Jim Ingham7508e732010-08-09 23:31:02 +0000552 }
553
554 ~CommandObjectProcessAttach ()
555 {
556 }
557
558 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000559 Execute (Args& command,
Jim Ingham7508e732010-08-09 23:31:02 +0000560 CommandReturnObject &result)
561 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000562 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Jim Inghamc2dc7c82011-01-29 01:49:25 +0000563 bool synchronous_execution = m_interpreter.GetSynchronous ();
564
Greg Clayton238c0a12010-09-18 01:14:36 +0000565 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Jim Ingham7508e732010-08-09 23:31:02 +0000566 if (process)
567 {
568 if (process->IsAlive())
569 {
570 result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before attaching.\n",
571 process->GetID());
572 result.SetStatus (eReturnStatusFailed);
573 return false;
574 }
575 }
576
577 if (target == NULL)
578 {
579 // If there isn't a current target create one.
580 TargetSP new_target_sp;
581 FileSpec emptyFileSpec;
582 ArchSpec emptyArchSpec;
583 Error error;
584
Greg Clayton238c0a12010-09-18 01:14:36 +0000585 error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(),
586 emptyFileSpec,
587 emptyArchSpec,
588 NULL,
589 false,
590 new_target_sp);
Jim Ingham7508e732010-08-09 23:31:02 +0000591 target = new_target_sp.get();
592 if (target == NULL || error.Fail())
593 {
Greg Claytone71e2582011-02-04 01:58:07 +0000594 result.AppendError(error.AsCString("Error creating target"));
Jim Ingham7508e732010-08-09 23:31:02 +0000595 return false;
596 }
Greg Clayton238c0a12010-09-18 01:14:36 +0000597 m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target);
Jim Ingham7508e732010-08-09 23:31:02 +0000598 }
599
600 // Record the old executable module, we want to issue a warning if the process of attaching changed the
601 // current executable (like somebody said "file foo" then attached to a PID whose executable was bar.)
602
603 ModuleSP old_exec_module_sp = target->GetExecutableModule();
604 ArchSpec old_arch_spec = target->GetArchitecture();
605
606 if (command.GetArgumentCount())
607 {
608 result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
609 result.SetStatus (eReturnStatusFailed);
610 }
611 else
612 {
613 const char *plugin_name = NULL;
614
615 if (!m_options.plugin_name.empty())
616 plugin_name = m_options.plugin_name.c_str();
617
Greg Clayton238c0a12010-09-18 01:14:36 +0000618 process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
Jim Ingham7508e732010-08-09 23:31:02 +0000619
620 if (process)
621 {
622 Error error;
623 int attach_pid = m_options.pid;
624
Jim Ingham4805a1c2010-09-15 01:34:14 +0000625 const char *wait_name = NULL;
626
627 if (m_options.name.empty())
628 {
629 if (old_exec_module_sp)
630 {
631 wait_name = old_exec_module_sp->GetFileSpec().GetFilename().AsCString();
632 }
633 }
634 else
635 {
636 wait_name = m_options.name.c_str();
637 }
638
Jim Ingham7508e732010-08-09 23:31:02 +0000639 // If we are waiting for a process with this name to show up, do that first.
640 if (m_options.waitfor)
641 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000642
643 if (wait_name == NULL)
Jim Ingham7508e732010-08-09 23:31:02 +0000644 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000645 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 +0000646 result.SetStatus (eReturnStatusFailed);
647 return false;
648 }
Jim Ingham4805a1c2010-09-15 01:34:14 +0000649
Greg Clayton7e2f91c2011-01-29 07:10:55 +0000650 result.AppendMessageWithFormat("Waiting to attach to a process named \"%s\".\n", wait_name);
Jim Ingham4805a1c2010-09-15 01:34:14 +0000651 error = process->Attach (wait_name, m_options.waitfor);
652 if (error.Success())
653 {
654 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
655 }
Jim Ingham7508e732010-08-09 23:31:02 +0000656 else
657 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000658 result.AppendErrorWithFormat ("Waiting for a process to launch named '%s': %s\n",
659 wait_name,
660 error.AsCString());
661 result.SetStatus (eReturnStatusFailed);
662 return false;
Jim Ingham7508e732010-08-09 23:31:02 +0000663 }
Jim Inghamc2dc7c82011-01-29 01:49:25 +0000664 // If we're synchronous, wait for the stopped event and report that.
665 // Otherwise just return.
666 // FIXME: in the async case it will now be possible to get to the command
667 // interpreter with a state eStateAttaching. Make sure we handle that correctly.
668 if (synchronous_execution)
669 {
670 StateType state = process->WaitForProcessToStop (NULL);
671
672 result.SetDidChangeProcessState (true);
673 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
674 result.SetStatus (eReturnStatusSuccessFinishNoResult);
675 }
676 else
677 {
678 result.SetDidChangeProcessState (true);
Jim Inghamc2dc7c82011-01-29 01:49:25 +0000679 result.SetStatus (eReturnStatusSuccessFinishNoResult);
680 }
Jim Ingham7508e732010-08-09 23:31:02 +0000681 }
682 else
683 {
684 // If the process was specified by name look it up, so we can warn if there are multiple
685 // processes with this pid.
686
Jim Ingham4805a1c2010-09-15 01:34:14 +0000687 if (attach_pid == LLDB_INVALID_PROCESS_ID && wait_name != NULL)
Jim Ingham7508e732010-08-09 23:31:02 +0000688 {
689 std::vector<lldb::pid_t> pids;
690 StringList matches;
691
Jim Ingham4805a1c2010-09-15 01:34:14 +0000692 process->ListProcessesMatchingName(wait_name, matches, pids);
Jim Ingham7508e732010-08-09 23:31:02 +0000693 if (matches.GetSize() > 1)
694 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000695 result.AppendErrorWithFormat("More than one process named %s\n", wait_name);
Jim Ingham7508e732010-08-09 23:31:02 +0000696 result.SetStatus (eReturnStatusFailed);
697 return false;
698 }
699 else if (matches.GetSize() == 0)
700 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000701 result.AppendErrorWithFormat("Could not find a process named %s\n", wait_name);
Jim Ingham7508e732010-08-09 23:31:02 +0000702 result.SetStatus (eReturnStatusFailed);
703 return false;
704 }
705 else
706 {
707 attach_pid = pids[0];
708 }
709
710 }
711
712 if (attach_pid != LLDB_INVALID_PROCESS_ID)
713 {
714 error = process->Attach (attach_pid);
715 if (error.Success())
716 {
717 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
718 }
719 else
720 {
721 result.AppendErrorWithFormat ("Attaching to process %i failed: %s.\n",
722 attach_pid,
723 error.AsCString());
724 result.SetStatus (eReturnStatusFailed);
725 }
Jim Inghamc2dc7c82011-01-29 01:49:25 +0000726 // See comment for synchronous_execution above.
727 if (synchronous_execution)
728 {
729 StateType state = process->WaitForProcessToStop (NULL);
730
731 result.SetDidChangeProcessState (true);
732 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
733 result.SetStatus (eReturnStatusSuccessFinishNoResult);
734 }
735 else
736 {
737 result.SetDidChangeProcessState (true);
Jim Inghamc2dc7c82011-01-29 01:49:25 +0000738 result.SetStatus (eReturnStatusSuccessFinishNoResult);
739 }
Jim Ingham7508e732010-08-09 23:31:02 +0000740 }
741 else
742 {
743 result.AppendErrorWithFormat ("No PID specified for attach\n",
744 attach_pid,
745 error.AsCString());
746 result.SetStatus (eReturnStatusFailed);
747
748 }
749 }
750 }
751 }
752
753 if (result.Succeeded())
754 {
755 // Okay, we're done. Last step is to warn if the executable module has changed:
Greg Clayton7e2f91c2011-01-29 07:10:55 +0000756 char new_path[PATH_MAX];
Jim Ingham7508e732010-08-09 23:31:02 +0000757 if (!old_exec_module_sp)
758 {
Greg Clayton7e2f91c2011-01-29 07:10:55 +0000759 // We might not have a module if we attached to a raw pid...
760 ModuleSP new_module_sp (target->GetExecutableModule());
761 if (new_module_sp)
762 {
763 new_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX);
764 result.AppendMessageWithFormat("Executable module set to \"%s\".\n", new_path);
765 }
Jim Ingham7508e732010-08-09 23:31:02 +0000766 }
767 else if (old_exec_module_sp->GetFileSpec() != target->GetExecutableModule()->GetFileSpec())
768 {
Greg Clayton7e2f91c2011-01-29 07:10:55 +0000769 char old_path[PATH_MAX];
Jim Ingham7508e732010-08-09 23:31:02 +0000770
771 old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX);
772 target->GetExecutableModule()->GetFileSpec().GetPath (new_path, PATH_MAX);
773
774 result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n",
775 old_path, new_path);
776 }
777
778 if (!old_arch_spec.IsValid())
779 {
Greg Clayton940b1032011-02-23 00:35:02 +0000780 result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().GetArchitectureName());
Jim Ingham7508e732010-08-09 23:31:02 +0000781 }
782 else if (old_arch_spec != target->GetArchitecture())
783 {
784 result.AppendWarningWithFormat("Architecture changed from %s to %s.\n",
Greg Clayton940b1032011-02-23 00:35:02 +0000785 old_arch_spec.GetArchitectureName(), target->GetArchitecture().GetArchitectureName());
Jim Ingham7508e732010-08-09 23:31:02 +0000786 }
787 }
788 return result.Succeeded();
789 }
790
791 Options *
792 GetOptions ()
793 {
794 return &m_options;
795 }
796
Chris Lattner24943d22010-06-08 16:52:24 +0000797protected:
798
799 CommandOptions m_options;
800};
801
802
803lldb::OptionDefinition
804CommandObjectProcessAttach::CommandOptions::g_option_table[] =
805{
Caroline Tice4d6675c2010-10-01 19:59:14 +0000806{ LLDB_OPT_SET_ALL, false, "plugin", 'P', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
807{ LLDB_OPT_SET_1, false, "pid", 'p', required_argument, NULL, 0, eArgTypePid, "The process ID of an existing process to attach to."},
808{ LLDB_OPT_SET_2, false, "name", 'n', required_argument, NULL, 0, eArgTypeProcessName, "The name of the process to attach to."},
809{ LLDB_OPT_SET_2, false, "waitfor",'w', no_argument, NULL, 0, eArgTypeNone, "Wait for the the process with <process-name> to launch."},
810{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +0000811};
812
813//-------------------------------------------------------------------------
814// CommandObjectProcessContinue
815//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +0000816#pragma mark CommandObjectProcessContinue
Chris Lattner24943d22010-06-08 16:52:24 +0000817
818class CommandObjectProcessContinue : public CommandObject
819{
820public:
821
Greg Clayton238c0a12010-09-18 01:14:36 +0000822 CommandObjectProcessContinue (CommandInterpreter &interpreter) :
823 CommandObject (interpreter,
824 "process continue",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000825 "Continue execution of all threads in the current process.",
Chris Lattner24943d22010-06-08 16:52:24 +0000826 "process continue",
827 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
828 {
829 }
830
831
832 ~CommandObjectProcessContinue ()
833 {
834 }
835
836 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000837 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000838 CommandReturnObject &result)
839 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000840 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
841 bool synchronous_execution = m_interpreter.GetSynchronous ();
Chris Lattner24943d22010-06-08 16:52:24 +0000842
843 if (process == NULL)
844 {
845 result.AppendError ("no process to continue");
846 result.SetStatus (eReturnStatusFailed);
847 return false;
848 }
849
850 StateType state = process->GetState();
851 if (state == eStateStopped)
852 {
853 if (command.GetArgumentCount() != 0)
854 {
855 result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str());
856 result.SetStatus (eReturnStatusFailed);
857 return false;
858 }
859
860 const uint32_t num_threads = process->GetThreadList().GetSize();
861
862 // Set the actions that the threads should each take when resuming
863 for (uint32_t idx=0; idx<num_threads; ++idx)
864 {
865 process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning);
866 }
867
868 Error error(process->Resume());
869 if (error.Success())
870 {
Greg Claytonc1d37752010-10-18 01:45:30 +0000871 result.AppendMessageWithFormat ("Process %i resuming\n", process->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000872 if (synchronous_execution)
873 {
Greg Claytonbef15832010-07-14 00:18:15 +0000874 state = process->WaitForProcessToStop (NULL);
Chris Lattner24943d22010-06-08 16:52:24 +0000875
876 result.SetDidChangeProcessState (true);
877 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
878 result.SetStatus (eReturnStatusSuccessFinishNoResult);
879 }
880 else
881 {
882 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
883 }
884 }
885 else
886 {
887 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
888 result.SetStatus (eReturnStatusFailed);
889 }
890 }
891 else
892 {
893 result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
894 StateAsCString(state));
895 result.SetStatus (eReturnStatusFailed);
896 }
897 return result.Succeeded();
898 }
899};
900
901//-------------------------------------------------------------------------
902// CommandObjectProcessDetach
903//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +0000904#pragma mark CommandObjectProcessDetach
Chris Lattner24943d22010-06-08 16:52:24 +0000905
906class CommandObjectProcessDetach : public CommandObject
907{
908public:
909
Greg Clayton238c0a12010-09-18 01:14:36 +0000910 CommandObjectProcessDetach (CommandInterpreter &interpreter) :
911 CommandObject (interpreter,
912 "process detach",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000913 "Detach from the current process being debugged.",
Chris Lattner24943d22010-06-08 16:52:24 +0000914 "process detach",
915 eFlagProcessMustBeLaunched)
916 {
917 }
918
919 ~CommandObjectProcessDetach ()
920 {
921 }
922
923 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000924 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000925 CommandReturnObject &result)
926 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000927 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000928 if (process == NULL)
929 {
930 result.AppendError ("must have a valid process in order to detach");
931 result.SetStatus (eReturnStatusFailed);
932 return false;
933 }
934
Caroline Tice90b42252010-11-02 16:16:53 +0000935 result.AppendMessageWithFormat ("Detaching from process %i\n", process->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000936 Error error (process->Detach());
937 if (error.Success())
938 {
939 result.SetStatus (eReturnStatusSuccessFinishResult);
940 }
941 else
942 {
943 result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString());
944 result.SetStatus (eReturnStatusFailed);
945 return false;
946 }
947 return result.Succeeded();
948 }
949};
950
951//-------------------------------------------------------------------------
Greg Claytone71e2582011-02-04 01:58:07 +0000952// CommandObjectProcessConnect
953//-------------------------------------------------------------------------
954#pragma mark CommandObjectProcessConnect
955
956class CommandObjectProcessConnect : public CommandObject
957{
958public:
959
960 class CommandOptions : public Options
961 {
962 public:
963
964 CommandOptions () :
965 Options()
966 {
967 // Keep default values of all options in one place: ResetOptionValues ()
968 ResetOptionValues ();
969 }
970
971 ~CommandOptions ()
972 {
973 }
974
975 Error
976 SetOptionValue (int option_idx, const char *option_arg)
977 {
978 Error error;
979 char short_option = (char) m_getopt_table[option_idx].val;
980
981 switch (short_option)
982 {
983 case 'p':
984 plugin_name.assign (option_arg);
985 break;
986
987 default:
988 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
989 break;
990 }
991 return error;
992 }
993
994 void
995 ResetOptionValues ()
996 {
997 Options::ResetOptionValues();
998 plugin_name.clear();
999 }
1000
1001 const lldb::OptionDefinition*
1002 GetDefinitions ()
1003 {
1004 return g_option_table;
1005 }
1006
1007 // Options table: Required for subclasses of Options.
1008
1009 static lldb::OptionDefinition g_option_table[];
1010
1011 // Instance variables to hold the values for command options.
1012
1013 std::string plugin_name;
1014 };
1015
1016 CommandObjectProcessConnect (CommandInterpreter &interpreter) :
1017 CommandObject (interpreter,
1018 "process connect",
1019 "Connect to a remote debug service.",
1020 "process connect <remote-url>",
1021 0)
1022 {
1023 }
1024
1025 ~CommandObjectProcessConnect ()
1026 {
1027 }
1028
1029
1030 bool
1031 Execute (Args& command,
1032 CommandReturnObject &result)
1033 {
1034
1035 TargetSP target_sp (m_interpreter.GetDebugger().GetSelectedTarget());
1036 Error error;
1037 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
1038 if (process)
1039 {
1040 if (process->IsAlive())
1041 {
1042 result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before connecting.\n",
1043 process->GetID());
1044 result.SetStatus (eReturnStatusFailed);
1045 return false;
1046 }
1047 }
1048
1049 if (!target_sp)
1050 {
1051 // If there isn't a current target create one.
1052 FileSpec emptyFileSpec;
1053 ArchSpec emptyArchSpec;
1054
1055 error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(),
1056 emptyFileSpec,
1057 emptyArchSpec,
1058 NULL,
1059 false,
1060 target_sp);
1061 if (!target_sp || error.Fail())
1062 {
1063 result.AppendError(error.AsCString("Error creating target"));
1064 result.SetStatus (eReturnStatusFailed);
1065 return false;
1066 }
1067 m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target_sp.get());
1068 }
1069
1070 if (command.GetArgumentCount() == 1)
1071 {
1072 const char *plugin_name = NULL;
1073 if (!m_options.plugin_name.empty())
1074 plugin_name = m_options.plugin_name.c_str();
1075
1076 const char *remote_url = command.GetArgumentAtIndex(0);
1077 process = target_sp->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
1078
1079 if (process)
1080 {
1081 error = process->ConnectRemote (remote_url);
1082
1083 if (error.Fail())
1084 {
1085 result.AppendError(error.AsCString("Remote connect failed"));
1086 result.SetStatus (eReturnStatusFailed);
1087 return false;
1088 }
1089 }
1090 else
1091 {
1092 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",
1093 m_cmd_name.c_str(),
1094 m_cmd_syntax.c_str());
1095 result.SetStatus (eReturnStatusFailed);
1096 }
1097 }
1098 else
1099 {
1100 result.AppendErrorWithFormat ("'%s' takes exactly one argument:\nUsage: \n",
1101 m_cmd_name.c_str(),
1102 m_cmd_syntax.c_str());
1103 result.SetStatus (eReturnStatusFailed);
1104 }
1105 return result.Succeeded();
1106 }
1107
1108 Options *
1109 GetOptions ()
1110 {
1111 return &m_options;
1112 }
1113
1114protected:
1115
1116 CommandOptions m_options;
1117};
1118
1119
1120lldb::OptionDefinition
1121CommandObjectProcessConnect::CommandOptions::g_option_table[] =
1122{
1123 { LLDB_OPT_SET_ALL, false, "plugin", 'p', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
1124 { 0, false, NULL, 0 , 0, NULL, 0, eArgTypeNone, NULL }
1125};
1126
1127//-------------------------------------------------------------------------
Greg Clayton0baa3942010-11-04 01:54:29 +00001128// CommandObjectProcessLoad
1129//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +00001130#pragma mark CommandObjectProcessLoad
Greg Clayton0baa3942010-11-04 01:54:29 +00001131
1132class CommandObjectProcessLoad : public CommandObject
1133{
1134public:
1135
1136 CommandObjectProcessLoad (CommandInterpreter &interpreter) :
1137 CommandObject (interpreter,
1138 "process load",
1139 "Load a shared library into the current process.",
1140 "process load <filename> [<filename> ...]",
1141 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
1142 {
1143 }
1144
1145 ~CommandObjectProcessLoad ()
1146 {
1147 }
1148
1149 bool
1150 Execute (Args& command,
1151 CommandReturnObject &result)
1152 {
1153 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
1154 if (process == NULL)
1155 {
1156 result.AppendError ("must have a valid process in order to load a shared library");
1157 result.SetStatus (eReturnStatusFailed);
1158 return false;
1159 }
1160
1161 const uint32_t argc = command.GetArgumentCount();
1162
1163 for (uint32_t i=0; i<argc; ++i)
1164 {
1165 Error error;
1166 const char *image_path = command.GetArgumentAtIndex(i);
1167 FileSpec image_spec (image_path, false);
1168 uint32_t image_token = process->LoadImage(image_spec, error);
1169 if (image_token != LLDB_INVALID_IMAGE_TOKEN)
1170 {
1171 result.AppendMessageWithFormat ("Loading \"%s\"...ok\nImage %u loaded.\n", image_path, image_token);
1172 result.SetStatus (eReturnStatusSuccessFinishResult);
1173 }
1174 else
1175 {
1176 result.AppendErrorWithFormat ("failed to load '%s': %s", image_path, error.AsCString());
1177 result.SetStatus (eReturnStatusFailed);
1178 }
1179 }
1180 return result.Succeeded();
1181 }
1182};
1183
1184
1185//-------------------------------------------------------------------------
1186// CommandObjectProcessUnload
1187//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +00001188#pragma mark CommandObjectProcessUnload
Greg Clayton0baa3942010-11-04 01:54:29 +00001189
1190class CommandObjectProcessUnload : public CommandObject
1191{
1192public:
1193
1194 CommandObjectProcessUnload (CommandInterpreter &interpreter) :
1195 CommandObject (interpreter,
1196 "process unload",
1197 "Unload a shared library from the current process using the index returned by a previous call to \"process load\".",
1198 "process unload <index>",
1199 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
1200 {
1201 }
1202
1203 ~CommandObjectProcessUnload ()
1204 {
1205 }
1206
1207 bool
1208 Execute (Args& command,
1209 CommandReturnObject &result)
1210 {
1211 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
1212 if (process == NULL)
1213 {
1214 result.AppendError ("must have a valid process in order to load a shared library");
1215 result.SetStatus (eReturnStatusFailed);
1216 return false;
1217 }
1218
1219 const uint32_t argc = command.GetArgumentCount();
1220
1221 for (uint32_t i=0; i<argc; ++i)
1222 {
1223 const char *image_token_cstr = command.GetArgumentAtIndex(i);
1224 uint32_t image_token = Args::StringToUInt32(image_token_cstr, LLDB_INVALID_IMAGE_TOKEN, 0);
1225 if (image_token == LLDB_INVALID_IMAGE_TOKEN)
1226 {
1227 result.AppendErrorWithFormat ("invalid image index argument '%s'", image_token_cstr);
1228 result.SetStatus (eReturnStatusFailed);
1229 break;
1230 }
1231 else
1232 {
1233 Error error (process->UnloadImage(image_token));
1234 if (error.Success())
1235 {
1236 result.AppendMessageWithFormat ("Unloading shared library with index %u...ok\n", image_token);
1237 result.SetStatus (eReturnStatusSuccessFinishResult);
1238 }
1239 else
1240 {
1241 result.AppendErrorWithFormat ("failed to unload image: %s", error.AsCString());
1242 result.SetStatus (eReturnStatusFailed);
1243 break;
1244 }
1245 }
1246 }
1247 return result.Succeeded();
1248 }
1249};
1250
1251//-------------------------------------------------------------------------
Chris Lattner24943d22010-06-08 16:52:24 +00001252// CommandObjectProcessSignal
1253//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +00001254#pragma mark CommandObjectProcessSignal
Chris Lattner24943d22010-06-08 16:52:24 +00001255
1256class CommandObjectProcessSignal : public CommandObject
1257{
1258public:
1259
Greg Clayton238c0a12010-09-18 01:14:36 +00001260 CommandObjectProcessSignal (CommandInterpreter &interpreter) :
1261 CommandObject (interpreter,
1262 "process signal",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001263 "Send a UNIX signal to the current process being debugged.",
Caroline Tice43b014a2010-10-04 22:28:36 +00001264 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +00001265 {
Caroline Tice43b014a2010-10-04 22:28:36 +00001266 CommandArgumentEntry arg;
1267 CommandArgumentData signal_arg;
1268
1269 // Define the first (and only) variant of this arg.
Caroline Tice3a62e6d2010-10-18 22:56:57 +00001270 signal_arg.arg_type = eArgTypeUnixSignal;
Caroline Tice43b014a2010-10-04 22:28:36 +00001271 signal_arg.arg_repetition = eArgRepeatPlain;
1272
1273 // There is only one variant this argument could be; put it into the argument entry.
1274 arg.push_back (signal_arg);
1275
1276 // Push the data for the first argument into the m_arguments vector.
1277 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +00001278 }
1279
1280 ~CommandObjectProcessSignal ()
1281 {
1282 }
1283
1284 bool
Greg Clayton238c0a12010-09-18 01:14:36 +00001285 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +00001286 CommandReturnObject &result)
1287 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001288 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +00001289 if (process == NULL)
1290 {
1291 result.AppendError ("no process to signal");
1292 result.SetStatus (eReturnStatusFailed);
1293 return false;
1294 }
1295
1296 if (command.GetArgumentCount() == 1)
1297 {
Greg Clayton8f6be2a2010-10-09 01:40:57 +00001298 int signo = LLDB_INVALID_SIGNAL_NUMBER;
1299
1300 const char *signal_name = command.GetArgumentAtIndex(0);
1301 if (::isxdigit (signal_name[0]))
1302 signo = Args::StringToSInt32(signal_name, LLDB_INVALID_SIGNAL_NUMBER, 0);
1303 else
1304 signo = process->GetUnixSignals().GetSignalNumberFromName (signal_name);
1305
1306 if (signo == LLDB_INVALID_SIGNAL_NUMBER)
Chris Lattner24943d22010-06-08 16:52:24 +00001307 {
1308 result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0));
1309 result.SetStatus (eReturnStatusFailed);
1310 }
1311 else
1312 {
1313 Error error (process->Signal (signo));
1314 if (error.Success())
1315 {
1316 result.SetStatus (eReturnStatusSuccessFinishResult);
1317 }
1318 else
1319 {
1320 result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString());
1321 result.SetStatus (eReturnStatusFailed);
1322 }
1323 }
1324 }
1325 else
1326 {
1327 result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: \n", m_cmd_name.c_str(),
1328 m_cmd_syntax.c_str());
1329 result.SetStatus (eReturnStatusFailed);
1330 }
1331 return result.Succeeded();
1332 }
1333};
1334
1335
1336//-------------------------------------------------------------------------
1337// CommandObjectProcessInterrupt
1338//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +00001339#pragma mark CommandObjectProcessInterrupt
Chris Lattner24943d22010-06-08 16:52:24 +00001340
1341class CommandObjectProcessInterrupt : public CommandObject
1342{
1343public:
1344
1345
Greg Clayton238c0a12010-09-18 01:14:36 +00001346 CommandObjectProcessInterrupt (CommandInterpreter &interpreter) :
1347 CommandObject (interpreter,
1348 "process interrupt",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001349 "Interrupt the current process being debugged.",
Chris Lattner24943d22010-06-08 16:52:24 +00001350 "process interrupt",
1351 eFlagProcessMustBeLaunched)
1352 {
1353 }
1354
1355 ~CommandObjectProcessInterrupt ()
1356 {
1357 }
1358
1359 bool
Greg Clayton238c0a12010-09-18 01:14:36 +00001360 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +00001361 CommandReturnObject &result)
1362 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001363 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +00001364 if (process == NULL)
1365 {
1366 result.AppendError ("no process to halt");
1367 result.SetStatus (eReturnStatusFailed);
1368 return false;
1369 }
1370
1371 if (command.GetArgumentCount() == 0)
1372 {
1373 Error error(process->Halt ());
1374 if (error.Success())
1375 {
1376 result.SetStatus (eReturnStatusSuccessFinishResult);
1377
1378 // Maybe we should add a "SuspendThreadPlans so we
1379 // can halt, and keep in place all the current thread plans.
1380 process->GetThreadList().DiscardThreadPlans();
1381 }
1382 else
1383 {
1384 result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString());
1385 result.SetStatus (eReturnStatusFailed);
1386 }
1387 }
1388 else
1389 {
1390 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
1391 m_cmd_name.c_str(),
1392 m_cmd_syntax.c_str());
1393 result.SetStatus (eReturnStatusFailed);
1394 }
1395 return result.Succeeded();
1396 }
1397};
1398
1399//-------------------------------------------------------------------------
1400// CommandObjectProcessKill
1401//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +00001402#pragma mark CommandObjectProcessKill
Chris Lattner24943d22010-06-08 16:52:24 +00001403
1404class CommandObjectProcessKill : public CommandObject
1405{
1406public:
1407
Greg Clayton238c0a12010-09-18 01:14:36 +00001408 CommandObjectProcessKill (CommandInterpreter &interpreter) :
1409 CommandObject (interpreter,
1410 "process kill",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001411 "Terminate the current process being debugged.",
Chris Lattner24943d22010-06-08 16:52:24 +00001412 "process kill",
1413 eFlagProcessMustBeLaunched)
1414 {
1415 }
1416
1417 ~CommandObjectProcessKill ()
1418 {
1419 }
1420
1421 bool
Greg Clayton238c0a12010-09-18 01:14:36 +00001422 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +00001423 CommandReturnObject &result)
1424 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001425 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +00001426 if (process == NULL)
1427 {
1428 result.AppendError ("no process to kill");
1429 result.SetStatus (eReturnStatusFailed);
1430 return false;
1431 }
1432
1433 if (command.GetArgumentCount() == 0)
1434 {
1435 Error error (process->Destroy());
1436 if (error.Success())
1437 {
1438 result.SetStatus (eReturnStatusSuccessFinishResult);
1439 }
1440 else
1441 {
1442 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString());
1443 result.SetStatus (eReturnStatusFailed);
1444 }
1445 }
1446 else
1447 {
1448 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
1449 m_cmd_name.c_str(),
1450 m_cmd_syntax.c_str());
1451 result.SetStatus (eReturnStatusFailed);
1452 }
1453 return result.Succeeded();
1454 }
1455};
1456
1457//-------------------------------------------------------------------------
Jim Ingham41313fc2010-06-18 01:23:09 +00001458// CommandObjectProcessStatus
1459//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +00001460#pragma mark CommandObjectProcessStatus
1461
Jim Ingham41313fc2010-06-18 01:23:09 +00001462class CommandObjectProcessStatus : public CommandObject
1463{
1464public:
Greg Clayton238c0a12010-09-18 01:14:36 +00001465 CommandObjectProcessStatus (CommandInterpreter &interpreter) :
1466 CommandObject (interpreter,
1467 "process status",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001468 "Show the current status and location of executing process.",
1469 "process status",
Jim Ingham41313fc2010-06-18 01:23:09 +00001470 0)
1471 {
1472 }
1473
1474 ~CommandObjectProcessStatus()
1475 {
1476 }
1477
1478
1479 bool
1480 Execute
1481 (
1482 Args& command,
Jim Ingham41313fc2010-06-18 01:23:09 +00001483 CommandReturnObject &result
1484 )
1485 {
Jim Ingham2e8cb8a2011-02-19 02:53:09 +00001486 Stream &output_stream = result.GetOutputStream();
Jim Ingham41313fc2010-06-18 01:23:09 +00001487 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Greg Clayton238c0a12010-09-18 01:14:36 +00001488 ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
Jim Ingham41313fc2010-06-18 01:23:09 +00001489 if (exe_ctx.process)
1490 {
1491 const StateType state = exe_ctx.process->GetState();
1492 if (StateIsStoppedState(state))
1493 {
1494 if (state == eStateExited)
1495 {
1496 int exit_status = exe_ctx.process->GetExitStatus();
1497 const char *exit_description = exe_ctx.process->GetExitDescription();
1498 output_stream.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n",
1499 exe_ctx.process->GetID(),
1500 exit_status,
1501 exit_status,
1502 exit_description ? exit_description : "");
1503 }
1504 else
1505 {
1506 output_stream.Printf ("Process %d %s\n", exe_ctx.process->GetID(), StateAsCString (state));
1507 if (exe_ctx.thread == NULL)
1508 exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
1509 if (exe_ctx.thread != NULL)
1510 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001511 DisplayThreadsInfo (m_interpreter, &exe_ctx, result, true, true);
Jim Ingham41313fc2010-06-18 01:23:09 +00001512 }
1513 else
1514 {
1515 result.AppendError ("No valid thread found in current process.");
1516 result.SetStatus (eReturnStatusFailed);
1517 }
1518 }
1519 }
1520 else
1521 {
1522 output_stream.Printf ("Process %d is running.\n",
1523 exe_ctx.process->GetID());
1524 }
1525 }
1526 else
1527 {
1528 result.AppendError ("No current location or status available.");
1529 result.SetStatus (eReturnStatusFailed);
1530 }
1531 return result.Succeeded();
1532 }
1533};
1534
1535//-------------------------------------------------------------------------
Caroline Tice23d6f272010-10-13 20:44:39 +00001536// CommandObjectProcessHandle
1537//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +00001538#pragma mark CommandObjectProcessHandle
Caroline Tice23d6f272010-10-13 20:44:39 +00001539
1540class CommandObjectProcessHandle : public CommandObject
1541{
1542public:
1543
1544 class CommandOptions : public Options
1545 {
1546 public:
1547
1548 CommandOptions () :
1549 Options ()
1550 {
1551 ResetOptionValues ();
1552 }
1553
1554 ~CommandOptions ()
1555 {
1556 }
1557
1558 Error
1559 SetOptionValue (int option_idx, const char *option_arg)
1560 {
1561 Error error;
1562 char short_option = (char) m_getopt_table[option_idx].val;
1563
1564 switch (short_option)
1565 {
1566 case 's':
1567 stop = option_arg;
1568 break;
1569 case 'n':
1570 notify = option_arg;
1571 break;
1572 case 'p':
1573 pass = option_arg;
1574 break;
1575 default:
1576 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
1577 break;
1578 }
1579 return error;
1580 }
1581
1582 void
1583 ResetOptionValues ()
1584 {
1585 Options::ResetOptionValues();
1586 stop.clear();
1587 notify.clear();
1588 pass.clear();
1589 }
1590
1591 const lldb::OptionDefinition*
1592 GetDefinitions ()
1593 {
1594 return g_option_table;
1595 }
1596
1597 // Options table: Required for subclasses of Options.
1598
1599 static lldb::OptionDefinition g_option_table[];
1600
1601 // Instance variables to hold the values for command options.
1602
1603 std::string stop;
1604 std::string notify;
1605 std::string pass;
1606 };
1607
1608
1609 CommandObjectProcessHandle (CommandInterpreter &interpreter) :
1610 CommandObject (interpreter,
1611 "process handle",
Caroline Ticee7471982010-10-14 21:31:13 +00001612 "Show or update what the process and debugger should do with various signals received from the OS.",
Caroline Tice23d6f272010-10-13 20:44:39 +00001613 NULL)
1614 {
Caroline Ticee7471982010-10-14 21:31:13 +00001615 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 +00001616 CommandArgumentEntry arg;
Caroline Tice3a62e6d2010-10-18 22:56:57 +00001617 CommandArgumentData signal_arg;
Caroline Tice23d6f272010-10-13 20:44:39 +00001618
Caroline Tice3a62e6d2010-10-18 22:56:57 +00001619 signal_arg.arg_type = eArgTypeUnixSignal;
1620 signal_arg.arg_repetition = eArgRepeatStar;
Caroline Tice23d6f272010-10-13 20:44:39 +00001621
Caroline Tice3a62e6d2010-10-18 22:56:57 +00001622 arg.push_back (signal_arg);
Caroline Tice23d6f272010-10-13 20:44:39 +00001623
1624 m_arguments.push_back (arg);
1625 }
1626
1627 ~CommandObjectProcessHandle ()
1628 {
1629 }
1630
1631 Options *
1632 GetOptions ()
1633 {
1634 return &m_options;
1635 }
1636
1637 bool
Caroline Ticee7471982010-10-14 21:31:13 +00001638 VerifyCommandOptionValue (const std::string &option, int &real_value)
Caroline Tice23d6f272010-10-13 20:44:39 +00001639 {
1640 bool okay = true;
1641
Caroline Ticee7471982010-10-14 21:31:13 +00001642 bool success = false;
1643 bool tmp_value = Args::StringToBoolean (option.c_str(), false, &success);
1644
1645 if (success && tmp_value)
1646 real_value = 1;
1647 else if (success && !tmp_value)
1648 real_value = 0;
Caroline Tice23d6f272010-10-13 20:44:39 +00001649 else
1650 {
1651 // If the value isn't 'true' or 'false', it had better be 0 or 1.
Caroline Ticee7471982010-10-14 21:31:13 +00001652 real_value = Args::StringToUInt32 (option.c_str(), 3);
1653 if (real_value != 0 && real_value != 1)
Caroline Tice23d6f272010-10-13 20:44:39 +00001654 okay = false;
1655 }
1656
1657 return okay;
1658 }
1659
Caroline Ticee7471982010-10-14 21:31:13 +00001660 void
1661 PrintSignalHeader (Stream &str)
1662 {
1663 str.Printf ("NAME PASS STOP NOTIFY\n");
1664 str.Printf ("========== ===== ===== ======\n");
1665 }
1666
1667 void
1668 PrintSignal (Stream &str, int32_t signo, const char *sig_name, UnixSignals &signals)
1669 {
1670 bool stop;
1671 bool suppress;
1672 bool notify;
1673
1674 str.Printf ("%-10s ", sig_name);
1675 if (signals.GetSignalInfo (signo, suppress, stop, notify))
1676 {
1677 bool pass = !suppress;
1678 str.Printf ("%s %s %s",
1679 (pass ? "true " : "false"),
1680 (stop ? "true " : "false"),
1681 (notify ? "true " : "false"));
1682 }
1683 str.Printf ("\n");
1684 }
1685
1686 void
1687 PrintSignalInformation (Stream &str, Args &signal_args, int num_valid_signals, UnixSignals &signals)
1688 {
1689 PrintSignalHeader (str);
1690
1691 if (num_valid_signals > 0)
1692 {
1693 size_t num_args = signal_args.GetArgumentCount();
1694 for (size_t i = 0; i < num_args; ++i)
1695 {
1696 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
1697 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
1698 PrintSignal (str, signo, signal_args.GetArgumentAtIndex (i), signals);
1699 }
1700 }
1701 else // Print info for ALL signals
1702 {
1703 int32_t signo = signals.GetFirstSignalNumber();
1704 while (signo != LLDB_INVALID_SIGNAL_NUMBER)
1705 {
1706 PrintSignal (str, signo, signals.GetSignalAsCString (signo), signals);
1707 signo = signals.GetNextSignalNumber (signo);
1708 }
1709 }
1710 }
1711
Caroline Tice23d6f272010-10-13 20:44:39 +00001712 bool
1713 Execute (Args &signal_args, CommandReturnObject &result)
1714 {
1715 TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
1716
1717 if (!target_sp)
1718 {
1719 result.AppendError ("No current target;"
1720 " cannot handle signals until you have a valid target and process.\n");
1721 result.SetStatus (eReturnStatusFailed);
1722 return false;
1723 }
1724
1725 ProcessSP process_sp = target_sp->GetProcessSP();
1726
1727 if (!process_sp)
1728 {
1729 result.AppendError ("No current process; cannot handle signals until you have a valid process.\n");
1730 result.SetStatus (eReturnStatusFailed);
1731 return false;
1732 }
1733
Caroline Tice23d6f272010-10-13 20:44:39 +00001734 int stop_action = -1; // -1 means leave the current setting alone
Caroline Ticee7471982010-10-14 21:31:13 +00001735 int pass_action = -1; // -1 means leave the current setting alone
Caroline Tice23d6f272010-10-13 20:44:39 +00001736 int notify_action = -1; // -1 means leave the current setting alone
1737
1738 if (! m_options.stop.empty()
Caroline Ticee7471982010-10-14 21:31:13 +00001739 && ! VerifyCommandOptionValue (m_options.stop, stop_action))
Caroline Tice23d6f272010-10-13 20:44:39 +00001740 {
1741 result.AppendError ("Invalid argument for command option --stop; must be true or false.\n");
1742 result.SetStatus (eReturnStatusFailed);
1743 return false;
1744 }
1745
1746 if (! m_options.notify.empty()
Caroline Ticee7471982010-10-14 21:31:13 +00001747 && ! VerifyCommandOptionValue (m_options.notify, notify_action))
Caroline Tice23d6f272010-10-13 20:44:39 +00001748 {
1749 result.AppendError ("Invalid argument for command option --notify; must be true or false.\n");
1750 result.SetStatus (eReturnStatusFailed);
1751 return false;
1752 }
1753
1754 if (! m_options.pass.empty()
Caroline Ticee7471982010-10-14 21:31:13 +00001755 && ! VerifyCommandOptionValue (m_options.pass, pass_action))
Caroline Tice23d6f272010-10-13 20:44:39 +00001756 {
1757 result.AppendError ("Invalid argument for command option --pass; must be true or false.\n");
1758 result.SetStatus (eReturnStatusFailed);
1759 return false;
1760 }
1761
1762 size_t num_args = signal_args.GetArgumentCount();
1763 UnixSignals &signals = process_sp->GetUnixSignals();
1764 int num_signals_set = 0;
1765
Caroline Ticee7471982010-10-14 21:31:13 +00001766 if (num_args > 0)
Caroline Tice23d6f272010-10-13 20:44:39 +00001767 {
Caroline Ticee7471982010-10-14 21:31:13 +00001768 for (size_t i = 0; i < num_args; ++i)
Caroline Tice23d6f272010-10-13 20:44:39 +00001769 {
Caroline Ticee7471982010-10-14 21:31:13 +00001770 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
1771 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
Caroline Tice23d6f272010-10-13 20:44:39 +00001772 {
Caroline Ticee7471982010-10-14 21:31:13 +00001773 // Casting the actions as bools here should be okay, because VerifyCommandOptionValue guarantees
1774 // the value is either 0 or 1.
1775 if (stop_action != -1)
1776 signals.SetShouldStop (signo, (bool) stop_action);
1777 if (pass_action != -1)
1778 {
1779 bool suppress = ! ((bool) pass_action);
1780 signals.SetShouldSuppress (signo, suppress);
1781 }
1782 if (notify_action != -1)
1783 signals.SetShouldNotify (signo, (bool) notify_action);
1784 ++num_signals_set;
Caroline Tice23d6f272010-10-13 20:44:39 +00001785 }
Caroline Ticee7471982010-10-14 21:31:13 +00001786 else
1787 {
1788 result.AppendErrorWithFormat ("Invalid signal name '%s'\n", signal_args.GetArgumentAtIndex (i));
1789 }
Caroline Tice23d6f272010-10-13 20:44:39 +00001790 }
1791 }
Caroline Ticee7471982010-10-14 21:31:13 +00001792 else
1793 {
1794 // No signal specified, if any command options were specified, update ALL signals.
1795 if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1))
1796 {
1797 if (m_interpreter.Confirm ("Do you really want to update all the signals?", false))
1798 {
1799 int32_t signo = signals.GetFirstSignalNumber();
1800 while (signo != LLDB_INVALID_SIGNAL_NUMBER)
1801 {
1802 if (notify_action != -1)
1803 signals.SetShouldNotify (signo, (bool) notify_action);
1804 if (stop_action != -1)
1805 signals.SetShouldStop (signo, (bool) stop_action);
1806 if (pass_action != -1)
1807 {
1808 bool suppress = ! ((bool) pass_action);
1809 signals.SetShouldSuppress (signo, suppress);
1810 }
1811 signo = signals.GetNextSignalNumber (signo);
1812 }
1813 }
1814 }
1815 }
1816
1817 PrintSignalInformation (result.GetOutputStream(), signal_args, num_signals_set, signals);
Caroline Tice23d6f272010-10-13 20:44:39 +00001818
1819 if (num_signals_set > 0)
1820 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1821 else
1822 result.SetStatus (eReturnStatusFailed);
1823
1824 return result.Succeeded();
1825 }
1826
1827protected:
1828
1829 CommandOptions m_options;
1830};
1831
1832lldb::OptionDefinition
1833CommandObjectProcessHandle::CommandOptions::g_option_table[] =
1834{
1835{ 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." },
1836{ 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." },
1837{ LLDB_OPT_SET_1, false, "pass", 'p', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." },
1838{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1839};
1840
1841//-------------------------------------------------------------------------
Chris Lattner24943d22010-06-08 16:52:24 +00001842// CommandObjectMultiwordProcess
1843//-------------------------------------------------------------------------
1844
Greg Clayton63094e02010-06-23 01:19:29 +00001845CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001846 CommandObjectMultiword (interpreter,
1847 "process",
1848 "A set of commands for operating on a process.",
1849 "process <subcommand> [<subcommand-options>]")
Chris Lattner24943d22010-06-08 16:52:24 +00001850{
Greg Clayton238c0a12010-09-18 01:14:36 +00001851 LoadSubCommand ("attach", CommandObjectSP (new CommandObjectProcessAttach (interpreter)));
1852 LoadSubCommand ("launch", CommandObjectSP (new CommandObjectProcessLaunch (interpreter)));
1853 LoadSubCommand ("continue", CommandObjectSP (new CommandObjectProcessContinue (interpreter)));
Greg Claytone71e2582011-02-04 01:58:07 +00001854 LoadSubCommand ("connect", CommandObjectSP (new CommandObjectProcessConnect (interpreter)));
Greg Clayton238c0a12010-09-18 01:14:36 +00001855 LoadSubCommand ("detach", CommandObjectSP (new CommandObjectProcessDetach (interpreter)));
Greg Clayton0baa3942010-11-04 01:54:29 +00001856 LoadSubCommand ("load", CommandObjectSP (new CommandObjectProcessLoad (interpreter)));
1857 LoadSubCommand ("unload", CommandObjectSP (new CommandObjectProcessUnload (interpreter)));
Greg Clayton238c0a12010-09-18 01:14:36 +00001858 LoadSubCommand ("signal", CommandObjectSP (new CommandObjectProcessSignal (interpreter)));
Caroline Tice23d6f272010-10-13 20:44:39 +00001859 LoadSubCommand ("handle", CommandObjectSP (new CommandObjectProcessHandle (interpreter)));
Greg Clayton238c0a12010-09-18 01:14:36 +00001860 LoadSubCommand ("status", CommandObjectSP (new CommandObjectProcessStatus (interpreter)));
1861 LoadSubCommand ("interrupt", CommandObjectSP (new CommandObjectProcessInterrupt (interpreter)));
1862 LoadSubCommand ("kill", CommandObjectSP (new CommandObjectProcessKill (interpreter)));
Chris Lattner24943d22010-06-08 16:52:24 +00001863}
1864
1865CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess ()
1866{
1867}
1868