blob: 181012d12f04dd6942f6f81dbbcfeaaa21b28dd0 [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- CommandObjectProcess.cpp --------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "CommandObjectProcess.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
Jim Ingham84cdc152010-06-15 19:49:27 +000016#include "lldb/Interpreter/Args.h"
17#include "lldb/Interpreter/Options.h"
Chris Lattner24943d22010-06-08 16:52:24 +000018#include "lldb/Core/State.h"
19#include "lldb/Interpreter/CommandInterpreter.h"
20#include "lldb/Interpreter/CommandReturnObject.h"
Jim Ingham41313fc2010-06-18 01:23:09 +000021#include "./CommandObjectThread.h"
Greg Claytoncd548032011-02-01 01:31:41 +000022#include "lldb/Host/Host.h"
Chris Lattner24943d22010-06-08 16:52:24 +000023#include "lldb/Target/Process.h"
24#include "lldb/Target/Target.h"
25#include "lldb/Target/Thread.h"
26
27using namespace lldb;
28using namespace lldb_private;
29
30//-------------------------------------------------------------------------
31// CommandObjectProcessLaunch
32//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +000033#pragma mark CommandObjectProjectLaunch
Chris Lattner24943d22010-06-08 16:52:24 +000034class CommandObjectProcessLaunch : public CommandObject
35{
36public:
37
38 class CommandOptions : public Options
39 {
40 public:
41
42 CommandOptions () :
43 Options()
44 {
45 // Keep default values of all options in one place: ResetOptionValues ()
46 ResetOptionValues ();
47 }
48
49 ~CommandOptions ()
50 {
51 }
52
53 Error
54 SetOptionValue (int option_idx, const char *option_arg)
55 {
56 Error error;
57 char short_option = (char) m_getopt_table[option_idx].val;
58
59 switch (short_option)
60 {
Greg Claytonde915be2011-01-23 05:56:20 +000061 case 's': stop_at_entry = true; break;
62 case 'e': stderr_path.assign (option_arg); break;
63 case 'i': stdin_path.assign (option_arg); break;
64 case 'o': stdout_path.assign (option_arg); break;
65 case 'p': plugin_name.assign (option_arg); break;
66 case 'n': no_stdio = true; break;
67 case 'w': working_dir.assign (option_arg); break;
Greg Claytonbb0c91f2010-10-19 23:16:00 +000068 case 't':
69 if (option_arg && option_arg[0])
70 tty_name.assign (option_arg);
71 in_new_tty = true;
72 break;
Chris Lattner24943d22010-06-08 16:52:24 +000073 default:
74 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
75 break;
76
77 }
78 return error;
79 }
80
81 void
82 ResetOptionValues ()
83 {
84 Options::ResetOptionValues();
85 stop_at_entry = false;
Greg Claytonc1d37752010-10-18 01:45:30 +000086 in_new_tty = false;
Greg Claytonbb0c91f2010-10-19 23:16:00 +000087 tty_name.clear();
Chris Lattner24943d22010-06-08 16:52:24 +000088 stdin_path.clear();
89 stdout_path.clear();
90 stderr_path.clear();
91 plugin_name.clear();
Greg Claytonde915be2011-01-23 05:56:20 +000092 working_dir.clear();
Caroline Ticebd666012010-12-03 18:46:09 +000093 no_stdio = false;
Chris Lattner24943d22010-06-08 16:52:24 +000094 }
95
96 const lldb::OptionDefinition*
97 GetDefinitions ()
98 {
99 return g_option_table;
100 }
101
102 // Options table: Required for subclasses of Options.
103
104 static lldb::OptionDefinition g_option_table[];
105
106 // Instance variables to hold the values for command options.
107
108 bool stop_at_entry;
Greg Claytonc1d37752010-10-18 01:45:30 +0000109 bool in_new_tty;
Caroline Ticebd666012010-12-03 18:46:09 +0000110 bool no_stdio;
Greg Claytonbb0c91f2010-10-19 23:16:00 +0000111 std::string tty_name;
Chris Lattner24943d22010-06-08 16:52:24 +0000112 std::string stderr_path;
113 std::string stdin_path;
114 std::string stdout_path;
115 std::string plugin_name;
Greg Claytonde915be2011-01-23 05:56:20 +0000116 std::string working_dir;
Chris Lattner24943d22010-06-08 16:52:24 +0000117
118 };
119
Greg Clayton238c0a12010-09-18 01:14:36 +0000120 CommandObjectProcessLaunch (CommandInterpreter &interpreter) :
121 CommandObject (interpreter,
122 "process launch",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000123 "Launch the executable in the debugger.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000124 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000125 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000126 CommandArgumentEntry arg;
127 CommandArgumentData run_args_arg;
128
129 // Define the first (and only) variant of this arg.
130 run_args_arg.arg_type = eArgTypeRunArgs;
131 run_args_arg.arg_repetition = eArgRepeatOptional;
132
133 // There is only one variant this argument could be; put it into the argument entry.
134 arg.push_back (run_args_arg);
135
136 // Push the data for the first argument into the m_arguments vector.
137 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000138 }
139
140
141 ~CommandObjectProcessLaunch ()
142 {
143 }
144
145 Options *
146 GetOptions ()
147 {
148 return &m_options;
149 }
150
151 bool
Greg Claytond8c62532010-10-07 04:19:01 +0000152 Execute (Args& launch_args, CommandReturnObject &result)
Chris Lattner24943d22010-06-08 16:52:24 +0000153 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000154 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000155
156 if (target == NULL)
157 {
158 result.AppendError ("invalid target, set executable file using 'file' command");
159 result.SetStatus (eReturnStatusFailed);
160 return false;
161 }
162
163 // If our listener is NULL, users aren't allows to launch
Chris Lattner24943d22010-06-08 16:52:24 +0000164 char filename[PATH_MAX];
Greg Claytonc1d37752010-10-18 01:45:30 +0000165 const Module *exe_module = target->GetExecutableModule().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000166 exe_module->GetFileSpec().GetPath(filename, sizeof(filename));
167
Greg Clayton238c0a12010-09-18 01:14:36 +0000168 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
169 if (process && process->IsAlive())
Jim Ingham22dc9722010-12-09 18:58:16 +0000170 {
Greg Clayton7e2f91c2011-01-29 07:10:55 +0000171 char message[1024];
172 if (process->GetState() == eStateAttaching)
173 ::strncpy (message, "There is a pending attach, abort it and launch a new process?", sizeof(message));
174 else
175 ::strncpy (message, "There is a running process, kill it and restart?", sizeof(message));
176
177 if (!m_interpreter.Confirm (message, true))
Jim Ingham22dc9722010-12-09 18:58:16 +0000178 {
Jim Ingham22dc9722010-12-09 18:58:16 +0000179 result.SetStatus (eReturnStatusFailed);
180 return false;
181 }
182 else
183 {
184 Error error (process->Destroy());
185 if (error.Success())
186 {
187 result.SetStatus (eReturnStatusSuccessFinishResult);
188 }
189 else
190 {
191 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString());
192 result.SetStatus (eReturnStatusFailed);
193 }
194 }
Chris Lattner24943d22010-06-08 16:52:24 +0000195 }
Jim Ingham22dc9722010-12-09 18:58:16 +0000196
Chris Lattner24943d22010-06-08 16:52:24 +0000197 const char *plugin_name;
198 if (!m_options.plugin_name.empty())
199 plugin_name = m_options.plugin_name.c_str();
200 else
201 plugin_name = NULL;
202
Greg Clayton238c0a12010-09-18 01:14:36 +0000203 process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
Chris Lattner24943d22010-06-08 16:52:24 +0000204
Greg Clayton238c0a12010-09-18 01:14:36 +0000205 if (process == NULL)
Caroline Tice6e4c5ce2010-09-04 00:03:46 +0000206 {
Caroline Tice734b4832010-10-15 21:52:38 +0000207 result.AppendErrorWithFormat ("Failed to find a process plugin for executable.\n");
Chris Lattner24943d22010-06-08 16:52:24 +0000208 result.SetStatus (eReturnStatusFailed);
209 return false;
210 }
211
Greg Clayton238c0a12010-09-18 01:14:36 +0000212 // If no launch args were given on the command line, then use any that
213 // might have been set using the "run-args" set variable.
214 if (launch_args.GetArgumentCount() == 0)
215 {
216 if (process->GetRunArguments().GetArgumentCount() > 0)
217 launch_args = process->GetRunArguments();
218 }
219
Greg Claytonc1d37752010-10-18 01:45:30 +0000220 if (m_options.in_new_tty)
221 {
222 char exec_file_path[PATH_MAX];
223 if (exe_module->GetFileSpec().GetPath(exec_file_path, sizeof(exec_file_path)))
224 {
225 launch_args.InsertArgumentAtIndex(0, exec_file_path);
226 }
227 else
228 {
229 result.AppendError("invalid executable");
230 result.SetStatus (eReturnStatusFailed);
231 return false;
232 }
233 }
234
Greg Clayton238c0a12010-09-18 01:14:36 +0000235 Args environment;
236
237 process->GetEnvironmentAsArgs (environment);
238
239 uint32_t launch_flags = eLaunchFlagNone;
240
241 if (process->GetDisableASLR())
242 launch_flags |= eLaunchFlagDisableASLR;
Greg Claytonc1d37752010-10-18 01:45:30 +0000243
Caroline Ticebd666012010-12-03 18:46:09 +0000244 if (m_options.no_stdio)
245 launch_flags |= eLaunchFlagDisableSTDIO;
246 else if (!m_options.in_new_tty
247 && m_options.stdin_path.empty()
248 && m_options.stdout_path.empty()
249 && m_options.stderr_path.empty())
250 {
251 // Only use the settings value if the user hasn't specified any options that would override it.
252 if (process->GetDisableSTDIO())
253 launch_flags |= eLaunchFlagDisableSTDIO;
254 }
255
Greg Claytonc1d37752010-10-18 01:45:30 +0000256 const char **inferior_argv = launch_args.GetArgumentCount() ? launch_args.GetConstArgumentVector() : NULL;
257 const char **inferior_envp = environment.GetArgumentCount() ? environment.GetConstArgumentVector() : NULL;
Greg Clayton238c0a12010-09-18 01:14:36 +0000258
Greg Claytonc1d37752010-10-18 01:45:30 +0000259 Error error;
Greg Claytonde915be2011-01-23 05:56:20 +0000260 const char *working_dir = NULL;
261 if (!m_options.working_dir.empty())
262 working_dir = m_options.working_dir.c_str();
Greg Clayton238c0a12010-09-18 01:14:36 +0000263
Greg Claytonc1d37752010-10-18 01:45:30 +0000264 if (m_options.in_new_tty)
Greg Clayton238c0a12010-09-18 01:14:36 +0000265 {
Greg Claytonc1d37752010-10-18 01:45:30 +0000266
Greg Claytonbb0c91f2010-10-19 23:16:00 +0000267 lldb::pid_t pid = Host::LaunchInNewTerminal (m_options.tty_name.c_str(),
268 inferior_argv,
Greg Clayton36f63a92010-10-19 03:25:40 +0000269 inferior_envp,
Greg Claytonde915be2011-01-23 05:56:20 +0000270 working_dir,
Greg Clayton36f63a92010-10-19 03:25:40 +0000271 &exe_module->GetArchitecture(),
272 true,
273 process->GetDisableASLR());
Greg Claytonc1d37752010-10-18 01:45:30 +0000274
Greg Clayton36f63a92010-10-19 03:25:40 +0000275 if (pid != LLDB_INVALID_PROCESS_ID)
276 error = process->Attach (pid);
Greg Clayton238c0a12010-09-18 01:14:36 +0000277 }
278 else
279 {
Greg Claytonc1d37752010-10-18 01:45:30 +0000280 const char * stdin_path = NULL;
281 const char * stdout_path = NULL;
282 const char * stderr_path = NULL;
283
284 // Were any standard input/output/error paths given on the command line?
285 if (m_options.stdin_path.empty() &&
286 m_options.stdout_path.empty() &&
287 m_options.stderr_path.empty())
288 {
289 // No standard file handles were given on the command line, check
290 // with the process object in case they were give using "set settings"
291 stdin_path = process->GetStandardInputPath();
292 stdout_path = process->GetStandardOutputPath();
293 stderr_path = process->GetStandardErrorPath();
294 }
295 else
296 {
297 stdin_path = m_options.stdin_path.empty() ? NULL : m_options.stdin_path.c_str();
298 stdout_path = m_options.stdout_path.empty() ? NULL : m_options.stdout_path.c_str();
299 stderr_path = m_options.stderr_path.empty() ? NULL : m_options.stderr_path.c_str();
300 }
301
Greg Claytonc1d37752010-10-18 01:45:30 +0000302 error = process->Launch (inferior_argv,
303 inferior_envp,
304 launch_flags,
305 stdin_path,
306 stdout_path,
Greg Claytonde915be2011-01-23 05:56:20 +0000307 stderr_path,
308 working_dir);
Greg Clayton238c0a12010-09-18 01:14:36 +0000309 }
Greg Clayton238c0a12010-09-18 01:14:36 +0000310
311 if (error.Success())
312 {
Greg Claytonc1d37752010-10-18 01:45:30 +0000313 const char *archname = exe_module->GetArchitecture().AsCString();
314
315 result.AppendMessageWithFormat ("Process %i launched: '%s' (%s)\n", process->GetID(), filename, archname);
Greg Claytond8c62532010-10-07 04:19:01 +0000316 result.SetDidChangeProcessState (true);
Greg Clayton238c0a12010-09-18 01:14:36 +0000317 if (m_options.stop_at_entry == false)
318 {
Greg Claytond8c62532010-10-07 04:19:01 +0000319 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
Greg Clayton238c0a12010-09-18 01:14:36 +0000320 StateType state = process->WaitForProcessToStop (NULL);
321
322 if (state == eStateStopped)
323 {
Greg Claytond8c62532010-10-07 04:19:01 +0000324 error = process->Resume();
325 if (error.Success())
326 {
327 bool synchronous_execution = m_interpreter.GetSynchronous ();
328 if (synchronous_execution)
329 {
330 state = process->WaitForProcessToStop (NULL);
331 result.SetDidChangeProcessState (true);
332 result.SetStatus (eReturnStatusSuccessFinishResult);
333 }
334 else
335 {
336 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
337 }
338 }
Greg Clayton238c0a12010-09-18 01:14:36 +0000339 }
340 }
341 }
342
Chris Lattner24943d22010-06-08 16:52:24 +0000343 return result.Succeeded();
344 }
345
Jim Ingham767af882010-07-07 03:36:20 +0000346 virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
347 {
348 // No repeat for "process launch"...
349 return "";
350 }
351
Chris Lattner24943d22010-06-08 16:52:24 +0000352protected:
353
354 CommandOptions m_options;
355};
356
357
Greg Claytonc1d37752010-10-18 01:45:30 +0000358#define SET1 LLDB_OPT_SET_1
359#define SET2 LLDB_OPT_SET_2
Caroline Ticebd666012010-12-03 18:46:09 +0000360#define SET3 LLDB_OPT_SET_3
Greg Claytonc1d37752010-10-18 01:45:30 +0000361
Chris Lattner24943d22010-06-08 16:52:24 +0000362lldb::OptionDefinition
363CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
364{
Caroline Ticebd666012010-12-03 18:46:09 +0000365{ SET1 | SET2 | SET3, false, "stop-at-entry", 's', no_argument, NULL, 0, eArgTypeNone, "Stop at the entry point of the program when launching a process."},
366{ SET1 , false, "stdin", 'i', required_argument, NULL, 0, eArgTypePath, "Redirect stdin for the process to <path>."},
367{ SET1 , false, "stdout", 'o', required_argument, NULL, 0, eArgTypePath, "Redirect stdout for the process to <path>."},
368{ SET1 , false, "stderr", 'e', required_argument, NULL, 0, eArgTypePath, "Redirect stderr for the process to <path>."},
369{ SET1 | SET2 | SET3, false, "plugin", 'p', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
370{ SET2 , false, "tty", 't', optional_argument, NULL, 0, eArgTypePath, "Start the process in a terminal. If <path> is specified, look for a terminal whose name contains <path>, else start the process in a new terminal."},
371{ SET3, false, "no-stdio", 'n', no_argument, NULL, 0, eArgTypeNone, "Do not set up for terminal I/O to go to running process."},
Greg Claytonde915be2011-01-23 05:56:20 +0000372{ SET1 | SET2 | SET3, false, "working-dir", 'w', required_argument, NULL, 0, eArgTypePath, "Set the current working directory to <path> when running the inferior."},
Caroline Ticebd666012010-12-03 18:46:09 +0000373{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +0000374};
375
Greg Claytonc1d37752010-10-18 01:45:30 +0000376#undef SET1
377#undef SET2
Caroline Ticebd666012010-12-03 18:46:09 +0000378#undef SET3
Chris Lattner24943d22010-06-08 16:52:24 +0000379
380//-------------------------------------------------------------------------
381// CommandObjectProcessAttach
382//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +0000383#pragma mark CommandObjectProcessAttach
Chris Lattner24943d22010-06-08 16:52:24 +0000384class CommandObjectProcessAttach : public CommandObject
385{
386public:
387
Chris Lattner24943d22010-06-08 16:52:24 +0000388 class CommandOptions : public Options
389 {
390 public:
391
392 CommandOptions () :
393 Options()
394 {
395 // Keep default values of all options in one place: ResetOptionValues ()
396 ResetOptionValues ();
397 }
398
399 ~CommandOptions ()
400 {
401 }
402
403 Error
404 SetOptionValue (int option_idx, const char *option_arg)
405 {
406 Error error;
407 char short_option = (char) m_getopt_table[option_idx].val;
408 bool success = false;
409 switch (short_option)
410 {
411 case 'p':
412 pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success);
413 if (!success || pid == LLDB_INVALID_PROCESS_ID)
414 {
415 error.SetErrorStringWithFormat("Invalid process ID '%s'.\n", option_arg);
416 }
417 break;
418
419 case 'P':
420 plugin_name = option_arg;
421 break;
422
423 case 'n':
424 name.assign(option_arg);
425 break;
426
427 case 'w':
428 waitfor = true;
429 break;
430
431 default:
432 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
433 break;
434 }
435 return error;
436 }
437
438 void
439 ResetOptionValues ()
440 {
441 Options::ResetOptionValues();
442 pid = LLDB_INVALID_PROCESS_ID;
443 name.clear();
444 waitfor = false;
445 }
446
447 const lldb::OptionDefinition*
448 GetDefinitions ()
449 {
450 return g_option_table;
451 }
452
Jim Ingham7508e732010-08-09 23:31:02 +0000453 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000454 HandleOptionArgumentCompletion (CommandInterpreter &interpeter,
Jim Ingham7508e732010-08-09 23:31:02 +0000455 Args &input,
456 int cursor_index,
457 int char_pos,
458 OptionElementVector &opt_element_vector,
459 int opt_element_index,
460 int match_start_point,
461 int max_return_elements,
462 bool &word_complete,
463 StringList &matches)
464 {
465 int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
466 int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
467
468 // We are only completing the name option for now...
469
470 const lldb::OptionDefinition *opt_defs = GetDefinitions();
471 if (opt_defs[opt_defs_index].short_option == 'n')
472 {
473 // Are we in the name?
474
475 // Look to see if there is a -P argument provided, and if so use that plugin, otherwise
476 // use the default plugin.
Greg Clayton238c0a12010-09-18 01:14:36 +0000477 Process *process = interpeter.GetDebugger().GetExecutionContext().process;
Jim Ingham7508e732010-08-09 23:31:02 +0000478 bool need_to_delete_process = false;
479
480 const char *partial_name = NULL;
481 partial_name = input.GetArgumentAtIndex(opt_arg_pos);
482
483 if (process && process->IsAlive())
484 return true;
485
Greg Clayton238c0a12010-09-18 01:14:36 +0000486 Target *target = interpeter.GetDebugger().GetSelectedTarget().get();
Jim Ingham7508e732010-08-09 23:31:02 +0000487 if (target == NULL)
488 {
489 // No target has been set yet, for now do host completion. Otherwise I don't know how we would
490 // figure out what the right target to use is...
491 std::vector<lldb::pid_t> pids;
492 Host::ListProcessesMatchingName (partial_name, matches, pids);
493 return true;
494 }
495 if (!process)
496 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000497 process = target->CreateProcess (interpeter.GetDebugger().GetListener(), partial_name).get();
Jim Ingham7508e732010-08-09 23:31:02 +0000498 need_to_delete_process = true;
499 }
500
501 if (process)
502 {
503 matches.Clear();
504 std::vector<lldb::pid_t> pids;
505 process->ListProcessesMatchingName (NULL, matches, pids);
506 if (need_to_delete_process)
507 target->DeleteCurrentProcess();
508 return true;
509 }
510 }
511
512 return false;
513 }
514
Chris Lattner24943d22010-06-08 16:52:24 +0000515 // Options table: Required for subclasses of Options.
516
517 static lldb::OptionDefinition g_option_table[];
518
519 // Instance variables to hold the values for command options.
520
521 lldb::pid_t pid;
522 std::string plugin_name;
523 std::string name;
524 bool waitfor;
525 };
526
Greg Clayton238c0a12010-09-18 01:14:36 +0000527 CommandObjectProcessAttach (CommandInterpreter &interpreter) :
528 CommandObject (interpreter,
529 "process attach",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000530 "Attach to a process.",
Jim Ingham7508e732010-08-09 23:31:02 +0000531 "process attach <cmd-options>")
532 {
Jim Ingham7508e732010-08-09 23:31:02 +0000533 }
534
535 ~CommandObjectProcessAttach ()
536 {
537 }
538
539 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000540 Execute (Args& command,
Jim Ingham7508e732010-08-09 23:31:02 +0000541 CommandReturnObject &result)
542 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000543 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Jim Inghamc2dc7c82011-01-29 01:49:25 +0000544 bool synchronous_execution = m_interpreter.GetSynchronous ();
545
Greg Clayton238c0a12010-09-18 01:14:36 +0000546 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Jim Ingham7508e732010-08-09 23:31:02 +0000547 if (process)
548 {
549 if (process->IsAlive())
550 {
551 result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before attaching.\n",
552 process->GetID());
553 result.SetStatus (eReturnStatusFailed);
554 return false;
555 }
556 }
557
558 if (target == NULL)
559 {
560 // If there isn't a current target create one.
561 TargetSP new_target_sp;
562 FileSpec emptyFileSpec;
563 ArchSpec emptyArchSpec;
564 Error error;
565
Greg Clayton238c0a12010-09-18 01:14:36 +0000566 error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(),
567 emptyFileSpec,
568 emptyArchSpec,
569 NULL,
570 false,
571 new_target_sp);
Jim Ingham7508e732010-08-09 23:31:02 +0000572 target = new_target_sp.get();
573 if (target == NULL || error.Fail())
574 {
Greg Claytone71e2582011-02-04 01:58:07 +0000575 result.AppendError(error.AsCString("Error creating target"));
Jim Ingham7508e732010-08-09 23:31:02 +0000576 return false;
577 }
Greg Clayton238c0a12010-09-18 01:14:36 +0000578 m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target);
Jim Ingham7508e732010-08-09 23:31:02 +0000579 }
580
581 // Record the old executable module, we want to issue a warning if the process of attaching changed the
582 // current executable (like somebody said "file foo" then attached to a PID whose executable was bar.)
583
584 ModuleSP old_exec_module_sp = target->GetExecutableModule();
585 ArchSpec old_arch_spec = target->GetArchitecture();
586
587 if (command.GetArgumentCount())
588 {
589 result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
590 result.SetStatus (eReturnStatusFailed);
591 }
592 else
593 {
594 const char *plugin_name = NULL;
595
596 if (!m_options.plugin_name.empty())
597 plugin_name = m_options.plugin_name.c_str();
598
Greg Clayton238c0a12010-09-18 01:14:36 +0000599 process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
Jim Ingham7508e732010-08-09 23:31:02 +0000600
601 if (process)
602 {
603 Error error;
604 int attach_pid = m_options.pid;
605
Jim Ingham4805a1c2010-09-15 01:34:14 +0000606 const char *wait_name = NULL;
607
608 if (m_options.name.empty())
609 {
610 if (old_exec_module_sp)
611 {
612 wait_name = old_exec_module_sp->GetFileSpec().GetFilename().AsCString();
613 }
614 }
615 else
616 {
617 wait_name = m_options.name.c_str();
618 }
619
Jim Ingham7508e732010-08-09 23:31:02 +0000620 // If we are waiting for a process with this name to show up, do that first.
621 if (m_options.waitfor)
622 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000623
624 if (wait_name == NULL)
Jim Ingham7508e732010-08-09 23:31:02 +0000625 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000626 result.AppendError("Invalid arguments: must have a file loaded or supply a process name with the waitfor option.\n");
Jim Ingham7508e732010-08-09 23:31:02 +0000627 result.SetStatus (eReturnStatusFailed);
628 return false;
629 }
Jim Ingham4805a1c2010-09-15 01:34:14 +0000630
Greg Clayton7e2f91c2011-01-29 07:10:55 +0000631 result.AppendMessageWithFormat("Waiting to attach to a process named \"%s\".\n", wait_name);
Jim Ingham4805a1c2010-09-15 01:34:14 +0000632 error = process->Attach (wait_name, m_options.waitfor);
633 if (error.Success())
634 {
635 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
636 }
Jim Ingham7508e732010-08-09 23:31:02 +0000637 else
638 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000639 result.AppendErrorWithFormat ("Waiting for a process to launch named '%s': %s\n",
640 wait_name,
641 error.AsCString());
642 result.SetStatus (eReturnStatusFailed);
643 return false;
Jim Ingham7508e732010-08-09 23:31:02 +0000644 }
Jim Inghamc2dc7c82011-01-29 01:49:25 +0000645 // If we're synchronous, wait for the stopped event and report that.
646 // Otherwise just return.
647 // FIXME: in the async case it will now be possible to get to the command
648 // interpreter with a state eStateAttaching. Make sure we handle that correctly.
649 if (synchronous_execution)
650 {
651 StateType state = process->WaitForProcessToStop (NULL);
652
653 result.SetDidChangeProcessState (true);
654 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
655 result.SetStatus (eReturnStatusSuccessFinishNoResult);
656 }
657 else
658 {
659 result.SetDidChangeProcessState (true);
Jim Inghamc2dc7c82011-01-29 01:49:25 +0000660 result.SetStatus (eReturnStatusSuccessFinishNoResult);
661 }
Jim Ingham7508e732010-08-09 23:31:02 +0000662 }
663 else
664 {
665 // If the process was specified by name look it up, so we can warn if there are multiple
666 // processes with this pid.
667
Jim Ingham4805a1c2010-09-15 01:34:14 +0000668 if (attach_pid == LLDB_INVALID_PROCESS_ID && wait_name != NULL)
Jim Ingham7508e732010-08-09 23:31:02 +0000669 {
670 std::vector<lldb::pid_t> pids;
671 StringList matches;
672
Jim Ingham4805a1c2010-09-15 01:34:14 +0000673 process->ListProcessesMatchingName(wait_name, matches, pids);
Jim Ingham7508e732010-08-09 23:31:02 +0000674 if (matches.GetSize() > 1)
675 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000676 result.AppendErrorWithFormat("More than one process named %s\n", wait_name);
Jim Ingham7508e732010-08-09 23:31:02 +0000677 result.SetStatus (eReturnStatusFailed);
678 return false;
679 }
680 else if (matches.GetSize() == 0)
681 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000682 result.AppendErrorWithFormat("Could not find a process named %s\n", wait_name);
Jim Ingham7508e732010-08-09 23:31:02 +0000683 result.SetStatus (eReturnStatusFailed);
684 return false;
685 }
686 else
687 {
688 attach_pid = pids[0];
689 }
690
691 }
692
693 if (attach_pid != LLDB_INVALID_PROCESS_ID)
694 {
695 error = process->Attach (attach_pid);
696 if (error.Success())
697 {
698 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
699 }
700 else
701 {
702 result.AppendErrorWithFormat ("Attaching to process %i failed: %s.\n",
703 attach_pid,
704 error.AsCString());
705 result.SetStatus (eReturnStatusFailed);
706 }
Jim Inghamc2dc7c82011-01-29 01:49:25 +0000707 // See comment for synchronous_execution above.
708 if (synchronous_execution)
709 {
710 StateType state = process->WaitForProcessToStop (NULL);
711
712 result.SetDidChangeProcessState (true);
713 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
714 result.SetStatus (eReturnStatusSuccessFinishNoResult);
715 }
716 else
717 {
718 result.SetDidChangeProcessState (true);
Jim Inghamc2dc7c82011-01-29 01:49:25 +0000719 result.SetStatus (eReturnStatusSuccessFinishNoResult);
720 }
Jim Ingham7508e732010-08-09 23:31:02 +0000721 }
722 else
723 {
724 result.AppendErrorWithFormat ("No PID specified for attach\n",
725 attach_pid,
726 error.AsCString());
727 result.SetStatus (eReturnStatusFailed);
728
729 }
730 }
731 }
732 }
733
734 if (result.Succeeded())
735 {
736 // Okay, we're done. Last step is to warn if the executable module has changed:
Greg Clayton7e2f91c2011-01-29 07:10:55 +0000737 char new_path[PATH_MAX];
Jim Ingham7508e732010-08-09 23:31:02 +0000738 if (!old_exec_module_sp)
739 {
Greg Clayton7e2f91c2011-01-29 07:10:55 +0000740 // We might not have a module if we attached to a raw pid...
741 ModuleSP new_module_sp (target->GetExecutableModule());
742 if (new_module_sp)
743 {
744 new_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX);
745 result.AppendMessageWithFormat("Executable module set to \"%s\".\n", new_path);
746 }
Jim Ingham7508e732010-08-09 23:31:02 +0000747 }
748 else if (old_exec_module_sp->GetFileSpec() != target->GetExecutableModule()->GetFileSpec())
749 {
Greg Clayton7e2f91c2011-01-29 07:10:55 +0000750 char old_path[PATH_MAX];
Jim Ingham7508e732010-08-09 23:31:02 +0000751
752 old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX);
753 target->GetExecutableModule()->GetFileSpec().GetPath (new_path, PATH_MAX);
754
755 result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n",
756 old_path, new_path);
757 }
758
759 if (!old_arch_spec.IsValid())
760 {
761 result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().AsCString());
762 }
763 else if (old_arch_spec != target->GetArchitecture())
764 {
765 result.AppendWarningWithFormat("Architecture changed from %s to %s.\n",
766 old_arch_spec.AsCString(), target->GetArchitecture().AsCString());
767 }
768 }
769 return result.Succeeded();
770 }
771
772 Options *
773 GetOptions ()
774 {
775 return &m_options;
776 }
777
Chris Lattner24943d22010-06-08 16:52:24 +0000778protected:
779
780 CommandOptions m_options;
781};
782
783
784lldb::OptionDefinition
785CommandObjectProcessAttach::CommandOptions::g_option_table[] =
786{
Caroline Tice4d6675c2010-10-01 19:59:14 +0000787{ LLDB_OPT_SET_ALL, false, "plugin", 'P', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
788{ LLDB_OPT_SET_1, false, "pid", 'p', required_argument, NULL, 0, eArgTypePid, "The process ID of an existing process to attach to."},
789{ LLDB_OPT_SET_2, false, "name", 'n', required_argument, NULL, 0, eArgTypeProcessName, "The name of the process to attach to."},
790{ LLDB_OPT_SET_2, false, "waitfor",'w', no_argument, NULL, 0, eArgTypeNone, "Wait for the the process with <process-name> to launch."},
791{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +0000792};
793
794//-------------------------------------------------------------------------
795// CommandObjectProcessContinue
796//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +0000797#pragma mark CommandObjectProcessContinue
Chris Lattner24943d22010-06-08 16:52:24 +0000798
799class CommandObjectProcessContinue : public CommandObject
800{
801public:
802
Greg Clayton238c0a12010-09-18 01:14:36 +0000803 CommandObjectProcessContinue (CommandInterpreter &interpreter) :
804 CommandObject (interpreter,
805 "process continue",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000806 "Continue execution of all threads in the current process.",
Chris Lattner24943d22010-06-08 16:52:24 +0000807 "process continue",
808 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
809 {
810 }
811
812
813 ~CommandObjectProcessContinue ()
814 {
815 }
816
817 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000818 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000819 CommandReturnObject &result)
820 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000821 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
822 bool synchronous_execution = m_interpreter.GetSynchronous ();
Chris Lattner24943d22010-06-08 16:52:24 +0000823
824 if (process == NULL)
825 {
826 result.AppendError ("no process to continue");
827 result.SetStatus (eReturnStatusFailed);
828 return false;
829 }
830
831 StateType state = process->GetState();
832 if (state == eStateStopped)
833 {
834 if (command.GetArgumentCount() != 0)
835 {
836 result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str());
837 result.SetStatus (eReturnStatusFailed);
838 return false;
839 }
840
841 const uint32_t num_threads = process->GetThreadList().GetSize();
842
843 // Set the actions that the threads should each take when resuming
844 for (uint32_t idx=0; idx<num_threads; ++idx)
845 {
846 process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning);
847 }
848
849 Error error(process->Resume());
850 if (error.Success())
851 {
Greg Claytonc1d37752010-10-18 01:45:30 +0000852 result.AppendMessageWithFormat ("Process %i resuming\n", process->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000853 if (synchronous_execution)
854 {
Greg Claytonbef15832010-07-14 00:18:15 +0000855 state = process->WaitForProcessToStop (NULL);
Chris Lattner24943d22010-06-08 16:52:24 +0000856
857 result.SetDidChangeProcessState (true);
858 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
859 result.SetStatus (eReturnStatusSuccessFinishNoResult);
860 }
861 else
862 {
863 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
864 }
865 }
866 else
867 {
868 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
869 result.SetStatus (eReturnStatusFailed);
870 }
871 }
872 else
873 {
874 result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
875 StateAsCString(state));
876 result.SetStatus (eReturnStatusFailed);
877 }
878 return result.Succeeded();
879 }
880};
881
882//-------------------------------------------------------------------------
883// CommandObjectProcessDetach
884//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +0000885#pragma mark CommandObjectProcessDetach
Chris Lattner24943d22010-06-08 16:52:24 +0000886
887class CommandObjectProcessDetach : public CommandObject
888{
889public:
890
Greg Clayton238c0a12010-09-18 01:14:36 +0000891 CommandObjectProcessDetach (CommandInterpreter &interpreter) :
892 CommandObject (interpreter,
893 "process detach",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000894 "Detach from the current process being debugged.",
Chris Lattner24943d22010-06-08 16:52:24 +0000895 "process detach",
896 eFlagProcessMustBeLaunched)
897 {
898 }
899
900 ~CommandObjectProcessDetach ()
901 {
902 }
903
904 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000905 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000906 CommandReturnObject &result)
907 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000908 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000909 if (process == NULL)
910 {
911 result.AppendError ("must have a valid process in order to detach");
912 result.SetStatus (eReturnStatusFailed);
913 return false;
914 }
915
Caroline Tice90b42252010-11-02 16:16:53 +0000916 result.AppendMessageWithFormat ("Detaching from process %i\n", process->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000917 Error error (process->Detach());
918 if (error.Success())
919 {
920 result.SetStatus (eReturnStatusSuccessFinishResult);
921 }
922 else
923 {
924 result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString());
925 result.SetStatus (eReturnStatusFailed);
926 return false;
927 }
928 return result.Succeeded();
929 }
930};
931
932//-------------------------------------------------------------------------
Greg Claytone71e2582011-02-04 01:58:07 +0000933// CommandObjectProcessConnect
934//-------------------------------------------------------------------------
935#pragma mark CommandObjectProcessConnect
936
937class CommandObjectProcessConnect : public CommandObject
938{
939public:
940
941 class CommandOptions : public Options
942 {
943 public:
944
945 CommandOptions () :
946 Options()
947 {
948 // Keep default values of all options in one place: ResetOptionValues ()
949 ResetOptionValues ();
950 }
951
952 ~CommandOptions ()
953 {
954 }
955
956 Error
957 SetOptionValue (int option_idx, const char *option_arg)
958 {
959 Error error;
960 char short_option = (char) m_getopt_table[option_idx].val;
961
962 switch (short_option)
963 {
964 case 'p':
965 plugin_name.assign (option_arg);
966 break;
967
968 default:
969 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
970 break;
971 }
972 return error;
973 }
974
975 void
976 ResetOptionValues ()
977 {
978 Options::ResetOptionValues();
979 plugin_name.clear();
980 }
981
982 const lldb::OptionDefinition*
983 GetDefinitions ()
984 {
985 return g_option_table;
986 }
987
988 // Options table: Required for subclasses of Options.
989
990 static lldb::OptionDefinition g_option_table[];
991
992 // Instance variables to hold the values for command options.
993
994 std::string plugin_name;
995 };
996
997 CommandObjectProcessConnect (CommandInterpreter &interpreter) :
998 CommandObject (interpreter,
999 "process connect",
1000 "Connect to a remote debug service.",
1001 "process connect <remote-url>",
1002 0)
1003 {
1004 }
1005
1006 ~CommandObjectProcessConnect ()
1007 {
1008 }
1009
1010
1011 bool
1012 Execute (Args& command,
1013 CommandReturnObject &result)
1014 {
1015
1016 TargetSP target_sp (m_interpreter.GetDebugger().GetSelectedTarget());
1017 Error error;
1018 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
1019 if (process)
1020 {
1021 if (process->IsAlive())
1022 {
1023 result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before connecting.\n",
1024 process->GetID());
1025 result.SetStatus (eReturnStatusFailed);
1026 return false;
1027 }
1028 }
1029
1030 if (!target_sp)
1031 {
1032 // If there isn't a current target create one.
1033 FileSpec emptyFileSpec;
1034 ArchSpec emptyArchSpec;
1035
1036 error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(),
1037 emptyFileSpec,
1038 emptyArchSpec,
1039 NULL,
1040 false,
1041 target_sp);
1042 if (!target_sp || error.Fail())
1043 {
1044 result.AppendError(error.AsCString("Error creating target"));
1045 result.SetStatus (eReturnStatusFailed);
1046 return false;
1047 }
1048 m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target_sp.get());
1049 }
1050
1051 if (command.GetArgumentCount() == 1)
1052 {
1053 const char *plugin_name = NULL;
1054 if (!m_options.plugin_name.empty())
1055 plugin_name = m_options.plugin_name.c_str();
1056
1057 const char *remote_url = command.GetArgumentAtIndex(0);
1058 process = target_sp->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
1059
1060 if (process)
1061 {
1062 error = process->ConnectRemote (remote_url);
1063
1064 if (error.Fail())
1065 {
1066 result.AppendError(error.AsCString("Remote connect failed"));
1067 result.SetStatus (eReturnStatusFailed);
1068 return false;
1069 }
1070 }
1071 else
1072 {
1073 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",
1074 m_cmd_name.c_str(),
1075 m_cmd_syntax.c_str());
1076 result.SetStatus (eReturnStatusFailed);
1077 }
1078 }
1079 else
1080 {
1081 result.AppendErrorWithFormat ("'%s' takes exactly one argument:\nUsage: \n",
1082 m_cmd_name.c_str(),
1083 m_cmd_syntax.c_str());
1084 result.SetStatus (eReturnStatusFailed);
1085 }
1086 return result.Succeeded();
1087 }
1088
1089 Options *
1090 GetOptions ()
1091 {
1092 return &m_options;
1093 }
1094
1095protected:
1096
1097 CommandOptions m_options;
1098};
1099
1100
1101lldb::OptionDefinition
1102CommandObjectProcessConnect::CommandOptions::g_option_table[] =
1103{
1104 { LLDB_OPT_SET_ALL, false, "plugin", 'p', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
1105 { 0, false, NULL, 0 , 0, NULL, 0, eArgTypeNone, NULL }
1106};
1107
1108//-------------------------------------------------------------------------
Greg Clayton0baa3942010-11-04 01:54:29 +00001109// CommandObjectProcessLoad
1110//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +00001111#pragma mark CommandObjectProcessLoad
Greg Clayton0baa3942010-11-04 01:54:29 +00001112
1113class CommandObjectProcessLoad : public CommandObject
1114{
1115public:
1116
1117 CommandObjectProcessLoad (CommandInterpreter &interpreter) :
1118 CommandObject (interpreter,
1119 "process load",
1120 "Load a shared library into the current process.",
1121 "process load <filename> [<filename> ...]",
1122 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
1123 {
1124 }
1125
1126 ~CommandObjectProcessLoad ()
1127 {
1128 }
1129
1130 bool
1131 Execute (Args& command,
1132 CommandReturnObject &result)
1133 {
1134 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
1135 if (process == NULL)
1136 {
1137 result.AppendError ("must have a valid process in order to load a shared library");
1138 result.SetStatus (eReturnStatusFailed);
1139 return false;
1140 }
1141
1142 const uint32_t argc = command.GetArgumentCount();
1143
1144 for (uint32_t i=0; i<argc; ++i)
1145 {
1146 Error error;
1147 const char *image_path = command.GetArgumentAtIndex(i);
1148 FileSpec image_spec (image_path, false);
1149 uint32_t image_token = process->LoadImage(image_spec, error);
1150 if (image_token != LLDB_INVALID_IMAGE_TOKEN)
1151 {
1152 result.AppendMessageWithFormat ("Loading \"%s\"...ok\nImage %u loaded.\n", image_path, image_token);
1153 result.SetStatus (eReturnStatusSuccessFinishResult);
1154 }
1155 else
1156 {
1157 result.AppendErrorWithFormat ("failed to load '%s': %s", image_path, error.AsCString());
1158 result.SetStatus (eReturnStatusFailed);
1159 }
1160 }
1161 return result.Succeeded();
1162 }
1163};
1164
1165
1166//-------------------------------------------------------------------------
1167// CommandObjectProcessUnload
1168//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +00001169#pragma mark CommandObjectProcessUnload
Greg Clayton0baa3942010-11-04 01:54:29 +00001170
1171class CommandObjectProcessUnload : public CommandObject
1172{
1173public:
1174
1175 CommandObjectProcessUnload (CommandInterpreter &interpreter) :
1176 CommandObject (interpreter,
1177 "process unload",
1178 "Unload a shared library from the current process using the index returned by a previous call to \"process load\".",
1179 "process unload <index>",
1180 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
1181 {
1182 }
1183
1184 ~CommandObjectProcessUnload ()
1185 {
1186 }
1187
1188 bool
1189 Execute (Args& command,
1190 CommandReturnObject &result)
1191 {
1192 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
1193 if (process == NULL)
1194 {
1195 result.AppendError ("must have a valid process in order to load a shared library");
1196 result.SetStatus (eReturnStatusFailed);
1197 return false;
1198 }
1199
1200 const uint32_t argc = command.GetArgumentCount();
1201
1202 for (uint32_t i=0; i<argc; ++i)
1203 {
1204 const char *image_token_cstr = command.GetArgumentAtIndex(i);
1205 uint32_t image_token = Args::StringToUInt32(image_token_cstr, LLDB_INVALID_IMAGE_TOKEN, 0);
1206 if (image_token == LLDB_INVALID_IMAGE_TOKEN)
1207 {
1208 result.AppendErrorWithFormat ("invalid image index argument '%s'", image_token_cstr);
1209 result.SetStatus (eReturnStatusFailed);
1210 break;
1211 }
1212 else
1213 {
1214 Error error (process->UnloadImage(image_token));
1215 if (error.Success())
1216 {
1217 result.AppendMessageWithFormat ("Unloading shared library with index %u...ok\n", image_token);
1218 result.SetStatus (eReturnStatusSuccessFinishResult);
1219 }
1220 else
1221 {
1222 result.AppendErrorWithFormat ("failed to unload image: %s", error.AsCString());
1223 result.SetStatus (eReturnStatusFailed);
1224 break;
1225 }
1226 }
1227 }
1228 return result.Succeeded();
1229 }
1230};
1231
1232//-------------------------------------------------------------------------
Chris Lattner24943d22010-06-08 16:52:24 +00001233// CommandObjectProcessSignal
1234//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +00001235#pragma mark CommandObjectProcessSignal
Chris Lattner24943d22010-06-08 16:52:24 +00001236
1237class CommandObjectProcessSignal : public CommandObject
1238{
1239public:
1240
Greg Clayton238c0a12010-09-18 01:14:36 +00001241 CommandObjectProcessSignal (CommandInterpreter &interpreter) :
1242 CommandObject (interpreter,
1243 "process signal",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001244 "Send a UNIX signal to the current process being debugged.",
Caroline Tice43b014a2010-10-04 22:28:36 +00001245 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +00001246 {
Caroline Tice43b014a2010-10-04 22:28:36 +00001247 CommandArgumentEntry arg;
1248 CommandArgumentData signal_arg;
1249
1250 // Define the first (and only) variant of this arg.
Caroline Tice3a62e6d2010-10-18 22:56:57 +00001251 signal_arg.arg_type = eArgTypeUnixSignal;
Caroline Tice43b014a2010-10-04 22:28:36 +00001252 signal_arg.arg_repetition = eArgRepeatPlain;
1253
1254 // There is only one variant this argument could be; put it into the argument entry.
1255 arg.push_back (signal_arg);
1256
1257 // Push the data for the first argument into the m_arguments vector.
1258 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +00001259 }
1260
1261 ~CommandObjectProcessSignal ()
1262 {
1263 }
1264
1265 bool
Greg Clayton238c0a12010-09-18 01:14:36 +00001266 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +00001267 CommandReturnObject &result)
1268 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001269 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +00001270 if (process == NULL)
1271 {
1272 result.AppendError ("no process to signal");
1273 result.SetStatus (eReturnStatusFailed);
1274 return false;
1275 }
1276
1277 if (command.GetArgumentCount() == 1)
1278 {
Greg Clayton8f6be2a2010-10-09 01:40:57 +00001279 int signo = LLDB_INVALID_SIGNAL_NUMBER;
1280
1281 const char *signal_name = command.GetArgumentAtIndex(0);
1282 if (::isxdigit (signal_name[0]))
1283 signo = Args::StringToSInt32(signal_name, LLDB_INVALID_SIGNAL_NUMBER, 0);
1284 else
1285 signo = process->GetUnixSignals().GetSignalNumberFromName (signal_name);
1286
1287 if (signo == LLDB_INVALID_SIGNAL_NUMBER)
Chris Lattner24943d22010-06-08 16:52:24 +00001288 {
1289 result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0));
1290 result.SetStatus (eReturnStatusFailed);
1291 }
1292 else
1293 {
1294 Error error (process->Signal (signo));
1295 if (error.Success())
1296 {
1297 result.SetStatus (eReturnStatusSuccessFinishResult);
1298 }
1299 else
1300 {
1301 result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString());
1302 result.SetStatus (eReturnStatusFailed);
1303 }
1304 }
1305 }
1306 else
1307 {
1308 result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: \n", m_cmd_name.c_str(),
1309 m_cmd_syntax.c_str());
1310 result.SetStatus (eReturnStatusFailed);
1311 }
1312 return result.Succeeded();
1313 }
1314};
1315
1316
1317//-------------------------------------------------------------------------
1318// CommandObjectProcessInterrupt
1319//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +00001320#pragma mark CommandObjectProcessInterrupt
Chris Lattner24943d22010-06-08 16:52:24 +00001321
1322class CommandObjectProcessInterrupt : public CommandObject
1323{
1324public:
1325
1326
Greg Clayton238c0a12010-09-18 01:14:36 +00001327 CommandObjectProcessInterrupt (CommandInterpreter &interpreter) :
1328 CommandObject (interpreter,
1329 "process interrupt",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001330 "Interrupt the current process being debugged.",
Chris Lattner24943d22010-06-08 16:52:24 +00001331 "process interrupt",
1332 eFlagProcessMustBeLaunched)
1333 {
1334 }
1335
1336 ~CommandObjectProcessInterrupt ()
1337 {
1338 }
1339
1340 bool
Greg Clayton238c0a12010-09-18 01:14:36 +00001341 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +00001342 CommandReturnObject &result)
1343 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001344 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +00001345 if (process == NULL)
1346 {
1347 result.AppendError ("no process to halt");
1348 result.SetStatus (eReturnStatusFailed);
1349 return false;
1350 }
1351
1352 if (command.GetArgumentCount() == 0)
1353 {
1354 Error error(process->Halt ());
1355 if (error.Success())
1356 {
1357 result.SetStatus (eReturnStatusSuccessFinishResult);
1358
1359 // Maybe we should add a "SuspendThreadPlans so we
1360 // can halt, and keep in place all the current thread plans.
1361 process->GetThreadList().DiscardThreadPlans();
1362 }
1363 else
1364 {
1365 result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString());
1366 result.SetStatus (eReturnStatusFailed);
1367 }
1368 }
1369 else
1370 {
1371 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
1372 m_cmd_name.c_str(),
1373 m_cmd_syntax.c_str());
1374 result.SetStatus (eReturnStatusFailed);
1375 }
1376 return result.Succeeded();
1377 }
1378};
1379
1380//-------------------------------------------------------------------------
1381// CommandObjectProcessKill
1382//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +00001383#pragma mark CommandObjectProcessKill
Chris Lattner24943d22010-06-08 16:52:24 +00001384
1385class CommandObjectProcessKill : public CommandObject
1386{
1387public:
1388
Greg Clayton238c0a12010-09-18 01:14:36 +00001389 CommandObjectProcessKill (CommandInterpreter &interpreter) :
1390 CommandObject (interpreter,
1391 "process kill",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001392 "Terminate the current process being debugged.",
Chris Lattner24943d22010-06-08 16:52:24 +00001393 "process kill",
1394 eFlagProcessMustBeLaunched)
1395 {
1396 }
1397
1398 ~CommandObjectProcessKill ()
1399 {
1400 }
1401
1402 bool
Greg Clayton238c0a12010-09-18 01:14:36 +00001403 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +00001404 CommandReturnObject &result)
1405 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001406 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +00001407 if (process == NULL)
1408 {
1409 result.AppendError ("no process to kill");
1410 result.SetStatus (eReturnStatusFailed);
1411 return false;
1412 }
1413
1414 if (command.GetArgumentCount() == 0)
1415 {
1416 Error error (process->Destroy());
1417 if (error.Success())
1418 {
1419 result.SetStatus (eReturnStatusSuccessFinishResult);
1420 }
1421 else
1422 {
1423 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString());
1424 result.SetStatus (eReturnStatusFailed);
1425 }
1426 }
1427 else
1428 {
1429 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
1430 m_cmd_name.c_str(),
1431 m_cmd_syntax.c_str());
1432 result.SetStatus (eReturnStatusFailed);
1433 }
1434 return result.Succeeded();
1435 }
1436};
1437
1438//-------------------------------------------------------------------------
Jim Ingham41313fc2010-06-18 01:23:09 +00001439// CommandObjectProcessStatus
1440//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +00001441#pragma mark CommandObjectProcessStatus
1442
Jim Ingham41313fc2010-06-18 01:23:09 +00001443class CommandObjectProcessStatus : public CommandObject
1444{
1445public:
Greg Clayton238c0a12010-09-18 01:14:36 +00001446 CommandObjectProcessStatus (CommandInterpreter &interpreter) :
1447 CommandObject (interpreter,
1448 "process status",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001449 "Show the current status and location of executing process.",
1450 "process status",
Jim Ingham41313fc2010-06-18 01:23:09 +00001451 0)
1452 {
1453 }
1454
1455 ~CommandObjectProcessStatus()
1456 {
1457 }
1458
1459
1460 bool
1461 Execute
1462 (
1463 Args& command,
Jim Ingham41313fc2010-06-18 01:23:09 +00001464 CommandReturnObject &result
1465 )
1466 {
1467 StreamString &output_stream = result.GetOutputStream();
1468 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Greg Clayton238c0a12010-09-18 01:14:36 +00001469 ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
Jim Ingham41313fc2010-06-18 01:23:09 +00001470 if (exe_ctx.process)
1471 {
1472 const StateType state = exe_ctx.process->GetState();
1473 if (StateIsStoppedState(state))
1474 {
1475 if (state == eStateExited)
1476 {
1477 int exit_status = exe_ctx.process->GetExitStatus();
1478 const char *exit_description = exe_ctx.process->GetExitDescription();
1479 output_stream.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n",
1480 exe_ctx.process->GetID(),
1481 exit_status,
1482 exit_status,
1483 exit_description ? exit_description : "");
1484 }
1485 else
1486 {
1487 output_stream.Printf ("Process %d %s\n", exe_ctx.process->GetID(), StateAsCString (state));
1488 if (exe_ctx.thread == NULL)
1489 exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
1490 if (exe_ctx.thread != NULL)
1491 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001492 DisplayThreadsInfo (m_interpreter, &exe_ctx, result, true, true);
Jim Ingham41313fc2010-06-18 01:23:09 +00001493 }
1494 else
1495 {
1496 result.AppendError ("No valid thread found in current process.");
1497 result.SetStatus (eReturnStatusFailed);
1498 }
1499 }
1500 }
1501 else
1502 {
1503 output_stream.Printf ("Process %d is running.\n",
1504 exe_ctx.process->GetID());
1505 }
1506 }
1507 else
1508 {
1509 result.AppendError ("No current location or status available.");
1510 result.SetStatus (eReturnStatusFailed);
1511 }
1512 return result.Succeeded();
1513 }
1514};
1515
1516//-------------------------------------------------------------------------
Caroline Tice23d6f272010-10-13 20:44:39 +00001517// CommandObjectProcessHandle
1518//-------------------------------------------------------------------------
Jim Ingham22dc9722010-12-09 18:58:16 +00001519#pragma mark CommandObjectProcessHandle
Caroline Tice23d6f272010-10-13 20:44:39 +00001520
1521class CommandObjectProcessHandle : public CommandObject
1522{
1523public:
1524
1525 class CommandOptions : public Options
1526 {
1527 public:
1528
1529 CommandOptions () :
1530 Options ()
1531 {
1532 ResetOptionValues ();
1533 }
1534
1535 ~CommandOptions ()
1536 {
1537 }
1538
1539 Error
1540 SetOptionValue (int option_idx, const char *option_arg)
1541 {
1542 Error error;
1543 char short_option = (char) m_getopt_table[option_idx].val;
1544
1545 switch (short_option)
1546 {
1547 case 's':
1548 stop = option_arg;
1549 break;
1550 case 'n':
1551 notify = option_arg;
1552 break;
1553 case 'p':
1554 pass = option_arg;
1555 break;
1556 default:
1557 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
1558 break;
1559 }
1560 return error;
1561 }
1562
1563 void
1564 ResetOptionValues ()
1565 {
1566 Options::ResetOptionValues();
1567 stop.clear();
1568 notify.clear();
1569 pass.clear();
1570 }
1571
1572 const lldb::OptionDefinition*
1573 GetDefinitions ()
1574 {
1575 return g_option_table;
1576 }
1577
1578 // Options table: Required for subclasses of Options.
1579
1580 static lldb::OptionDefinition g_option_table[];
1581
1582 // Instance variables to hold the values for command options.
1583
1584 std::string stop;
1585 std::string notify;
1586 std::string pass;
1587 };
1588
1589
1590 CommandObjectProcessHandle (CommandInterpreter &interpreter) :
1591 CommandObject (interpreter,
1592 "process handle",
Caroline Ticee7471982010-10-14 21:31:13 +00001593 "Show or update what the process and debugger should do with various signals received from the OS.",
Caroline Tice23d6f272010-10-13 20:44:39 +00001594 NULL)
1595 {
Caroline Ticee7471982010-10-14 21:31:13 +00001596 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 +00001597 CommandArgumentEntry arg;
Caroline Tice3a62e6d2010-10-18 22:56:57 +00001598 CommandArgumentData signal_arg;
Caroline Tice23d6f272010-10-13 20:44:39 +00001599
Caroline Tice3a62e6d2010-10-18 22:56:57 +00001600 signal_arg.arg_type = eArgTypeUnixSignal;
1601 signal_arg.arg_repetition = eArgRepeatStar;
Caroline Tice23d6f272010-10-13 20:44:39 +00001602
Caroline Tice3a62e6d2010-10-18 22:56:57 +00001603 arg.push_back (signal_arg);
Caroline Tice23d6f272010-10-13 20:44:39 +00001604
1605 m_arguments.push_back (arg);
1606 }
1607
1608 ~CommandObjectProcessHandle ()
1609 {
1610 }
1611
1612 Options *
1613 GetOptions ()
1614 {
1615 return &m_options;
1616 }
1617
1618 bool
Caroline Ticee7471982010-10-14 21:31:13 +00001619 VerifyCommandOptionValue (const std::string &option, int &real_value)
Caroline Tice23d6f272010-10-13 20:44:39 +00001620 {
1621 bool okay = true;
1622
Caroline Ticee7471982010-10-14 21:31:13 +00001623 bool success = false;
1624 bool tmp_value = Args::StringToBoolean (option.c_str(), false, &success);
1625
1626 if (success && tmp_value)
1627 real_value = 1;
1628 else if (success && !tmp_value)
1629 real_value = 0;
Caroline Tice23d6f272010-10-13 20:44:39 +00001630 else
1631 {
1632 // If the value isn't 'true' or 'false', it had better be 0 or 1.
Caroline Ticee7471982010-10-14 21:31:13 +00001633 real_value = Args::StringToUInt32 (option.c_str(), 3);
1634 if (real_value != 0 && real_value != 1)
Caroline Tice23d6f272010-10-13 20:44:39 +00001635 okay = false;
1636 }
1637
1638 return okay;
1639 }
1640
Caroline Ticee7471982010-10-14 21:31:13 +00001641 void
1642 PrintSignalHeader (Stream &str)
1643 {
1644 str.Printf ("NAME PASS STOP NOTIFY\n");
1645 str.Printf ("========== ===== ===== ======\n");
1646 }
1647
1648 void
1649 PrintSignal (Stream &str, int32_t signo, const char *sig_name, UnixSignals &signals)
1650 {
1651 bool stop;
1652 bool suppress;
1653 bool notify;
1654
1655 str.Printf ("%-10s ", sig_name);
1656 if (signals.GetSignalInfo (signo, suppress, stop, notify))
1657 {
1658 bool pass = !suppress;
1659 str.Printf ("%s %s %s",
1660 (pass ? "true " : "false"),
1661 (stop ? "true " : "false"),
1662 (notify ? "true " : "false"));
1663 }
1664 str.Printf ("\n");
1665 }
1666
1667 void
1668 PrintSignalInformation (Stream &str, Args &signal_args, int num_valid_signals, UnixSignals &signals)
1669 {
1670 PrintSignalHeader (str);
1671
1672 if (num_valid_signals > 0)
1673 {
1674 size_t num_args = signal_args.GetArgumentCount();
1675 for (size_t i = 0; i < num_args; ++i)
1676 {
1677 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
1678 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
1679 PrintSignal (str, signo, signal_args.GetArgumentAtIndex (i), signals);
1680 }
1681 }
1682 else // Print info for ALL signals
1683 {
1684 int32_t signo = signals.GetFirstSignalNumber();
1685 while (signo != LLDB_INVALID_SIGNAL_NUMBER)
1686 {
1687 PrintSignal (str, signo, signals.GetSignalAsCString (signo), signals);
1688 signo = signals.GetNextSignalNumber (signo);
1689 }
1690 }
1691 }
1692
Caroline Tice23d6f272010-10-13 20:44:39 +00001693 bool
1694 Execute (Args &signal_args, CommandReturnObject &result)
1695 {
1696 TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
1697
1698 if (!target_sp)
1699 {
1700 result.AppendError ("No current target;"
1701 " cannot handle signals until you have a valid target and process.\n");
1702 result.SetStatus (eReturnStatusFailed);
1703 return false;
1704 }
1705
1706 ProcessSP process_sp = target_sp->GetProcessSP();
1707
1708 if (!process_sp)
1709 {
1710 result.AppendError ("No current process; cannot handle signals until you have a valid process.\n");
1711 result.SetStatus (eReturnStatusFailed);
1712 return false;
1713 }
1714
Caroline Tice23d6f272010-10-13 20:44:39 +00001715 int stop_action = -1; // -1 means leave the current setting alone
Caroline Ticee7471982010-10-14 21:31:13 +00001716 int pass_action = -1; // -1 means leave the current setting alone
Caroline Tice23d6f272010-10-13 20:44:39 +00001717 int notify_action = -1; // -1 means leave the current setting alone
1718
1719 if (! m_options.stop.empty()
Caroline Ticee7471982010-10-14 21:31:13 +00001720 && ! VerifyCommandOptionValue (m_options.stop, stop_action))
Caroline Tice23d6f272010-10-13 20:44:39 +00001721 {
1722 result.AppendError ("Invalid argument for command option --stop; must be true or false.\n");
1723 result.SetStatus (eReturnStatusFailed);
1724 return false;
1725 }
1726
1727 if (! m_options.notify.empty()
Caroline Ticee7471982010-10-14 21:31:13 +00001728 && ! VerifyCommandOptionValue (m_options.notify, notify_action))
Caroline Tice23d6f272010-10-13 20:44:39 +00001729 {
1730 result.AppendError ("Invalid argument for command option --notify; must be true or false.\n");
1731 result.SetStatus (eReturnStatusFailed);
1732 return false;
1733 }
1734
1735 if (! m_options.pass.empty()
Caroline Ticee7471982010-10-14 21:31:13 +00001736 && ! VerifyCommandOptionValue (m_options.pass, pass_action))
Caroline Tice23d6f272010-10-13 20:44:39 +00001737 {
1738 result.AppendError ("Invalid argument for command option --pass; must be true or false.\n");
1739 result.SetStatus (eReturnStatusFailed);
1740 return false;
1741 }
1742
1743 size_t num_args = signal_args.GetArgumentCount();
1744 UnixSignals &signals = process_sp->GetUnixSignals();
1745 int num_signals_set = 0;
1746
Caroline Ticee7471982010-10-14 21:31:13 +00001747 if (num_args > 0)
Caroline Tice23d6f272010-10-13 20:44:39 +00001748 {
Caroline Ticee7471982010-10-14 21:31:13 +00001749 for (size_t i = 0; i < num_args; ++i)
Caroline Tice23d6f272010-10-13 20:44:39 +00001750 {
Caroline Ticee7471982010-10-14 21:31:13 +00001751 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
1752 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
Caroline Tice23d6f272010-10-13 20:44:39 +00001753 {
Caroline Ticee7471982010-10-14 21:31:13 +00001754 // Casting the actions as bools here should be okay, because VerifyCommandOptionValue guarantees
1755 // the value is either 0 or 1.
1756 if (stop_action != -1)
1757 signals.SetShouldStop (signo, (bool) stop_action);
1758 if (pass_action != -1)
1759 {
1760 bool suppress = ! ((bool) pass_action);
1761 signals.SetShouldSuppress (signo, suppress);
1762 }
1763 if (notify_action != -1)
1764 signals.SetShouldNotify (signo, (bool) notify_action);
1765 ++num_signals_set;
Caroline Tice23d6f272010-10-13 20:44:39 +00001766 }
Caroline Ticee7471982010-10-14 21:31:13 +00001767 else
1768 {
1769 result.AppendErrorWithFormat ("Invalid signal name '%s'\n", signal_args.GetArgumentAtIndex (i));
1770 }
Caroline Tice23d6f272010-10-13 20:44:39 +00001771 }
1772 }
Caroline Ticee7471982010-10-14 21:31:13 +00001773 else
1774 {
1775 // No signal specified, if any command options were specified, update ALL signals.
1776 if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1))
1777 {
1778 if (m_interpreter.Confirm ("Do you really want to update all the signals?", false))
1779 {
1780 int32_t signo = signals.GetFirstSignalNumber();
1781 while (signo != LLDB_INVALID_SIGNAL_NUMBER)
1782 {
1783 if (notify_action != -1)
1784 signals.SetShouldNotify (signo, (bool) notify_action);
1785 if (stop_action != -1)
1786 signals.SetShouldStop (signo, (bool) stop_action);
1787 if (pass_action != -1)
1788 {
1789 bool suppress = ! ((bool) pass_action);
1790 signals.SetShouldSuppress (signo, suppress);
1791 }
1792 signo = signals.GetNextSignalNumber (signo);
1793 }
1794 }
1795 }
1796 }
1797
1798 PrintSignalInformation (result.GetOutputStream(), signal_args, num_signals_set, signals);
Caroline Tice23d6f272010-10-13 20:44:39 +00001799
1800 if (num_signals_set > 0)
1801 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1802 else
1803 result.SetStatus (eReturnStatusFailed);
1804
1805 return result.Succeeded();
1806 }
1807
1808protected:
1809
1810 CommandOptions m_options;
1811};
1812
1813lldb::OptionDefinition
1814CommandObjectProcessHandle::CommandOptions::g_option_table[] =
1815{
1816{ 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." },
1817{ 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." },
1818{ LLDB_OPT_SET_1, false, "pass", 'p', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." },
1819{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1820};
1821
1822//-------------------------------------------------------------------------
Chris Lattner24943d22010-06-08 16:52:24 +00001823// CommandObjectMultiwordProcess
1824//-------------------------------------------------------------------------
1825
Greg Clayton63094e02010-06-23 01:19:29 +00001826CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001827 CommandObjectMultiword (interpreter,
1828 "process",
1829 "A set of commands for operating on a process.",
1830 "process <subcommand> [<subcommand-options>]")
Chris Lattner24943d22010-06-08 16:52:24 +00001831{
Greg Clayton238c0a12010-09-18 01:14:36 +00001832 LoadSubCommand ("attach", CommandObjectSP (new CommandObjectProcessAttach (interpreter)));
1833 LoadSubCommand ("launch", CommandObjectSP (new CommandObjectProcessLaunch (interpreter)));
1834 LoadSubCommand ("continue", CommandObjectSP (new CommandObjectProcessContinue (interpreter)));
Greg Claytone71e2582011-02-04 01:58:07 +00001835 LoadSubCommand ("connect", CommandObjectSP (new CommandObjectProcessConnect (interpreter)));
Greg Clayton238c0a12010-09-18 01:14:36 +00001836 LoadSubCommand ("detach", CommandObjectSP (new CommandObjectProcessDetach (interpreter)));
Greg Clayton0baa3942010-11-04 01:54:29 +00001837 LoadSubCommand ("load", CommandObjectSP (new CommandObjectProcessLoad (interpreter)));
1838 LoadSubCommand ("unload", CommandObjectSP (new CommandObjectProcessUnload (interpreter)));
Greg Clayton238c0a12010-09-18 01:14:36 +00001839 LoadSubCommand ("signal", CommandObjectSP (new CommandObjectProcessSignal (interpreter)));
Caroline Tice23d6f272010-10-13 20:44:39 +00001840 LoadSubCommand ("handle", CommandObjectSP (new CommandObjectProcessHandle (interpreter)));
Greg Clayton238c0a12010-09-18 01:14:36 +00001841 LoadSubCommand ("status", CommandObjectSP (new CommandObjectProcessStatus (interpreter)));
1842 LoadSubCommand ("interrupt", CommandObjectSP (new CommandObjectProcessInterrupt (interpreter)));
1843 LoadSubCommand ("kill", CommandObjectSP (new CommandObjectProcessKill (interpreter)));
Chris Lattner24943d22010-06-08 16:52:24 +00001844}
1845
1846CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess ()
1847{
1848}
1849