blob: 82d664b0a1647cd2fc8e07ab98d5b69b78876d46 [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"
Chris Lattner24943d22010-06-08 16:52:24 +000022#include "lldb/Target/Process.h"
23#include "lldb/Target/Target.h"
24#include "lldb/Target/Thread.h"
25
26using namespace lldb;
27using namespace lldb_private;
28
29//-------------------------------------------------------------------------
30// CommandObjectProcessLaunch
31//-------------------------------------------------------------------------
32
33class CommandObjectProcessLaunch : public CommandObject
34{
35public:
36
37 class CommandOptions : public Options
38 {
39 public:
40
41 CommandOptions () :
42 Options()
43 {
44 // Keep default values of all options in one place: ResetOptionValues ()
45 ResetOptionValues ();
46 }
47
48 ~CommandOptions ()
49 {
50 }
51
52 Error
53 SetOptionValue (int option_idx, const char *option_arg)
54 {
55 Error error;
56 char short_option = (char) m_getopt_table[option_idx].val;
57
58 switch (short_option)
59 {
60 case 's': stop_at_entry = true; break;
61 case 'e': stderr_path = option_arg; break;
62 case 'i': stdin_path = option_arg; break;
63 case 'o': stdout_path = option_arg; break;
64 case 'p': plugin_name = option_arg; break;
Greg Claytonc1d37752010-10-18 01:45:30 +000065 case 't': in_new_tty = true; break;
Chris Lattner24943d22010-06-08 16:52:24 +000066 default:
67 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
68 break;
69
70 }
71 return error;
72 }
73
74 void
75 ResetOptionValues ()
76 {
77 Options::ResetOptionValues();
78 stop_at_entry = false;
Greg Claytonc1d37752010-10-18 01:45:30 +000079 in_new_tty = false;
Chris Lattner24943d22010-06-08 16:52:24 +000080 stdin_path.clear();
81 stdout_path.clear();
82 stderr_path.clear();
83 plugin_name.clear();
84 }
85
86 const lldb::OptionDefinition*
87 GetDefinitions ()
88 {
89 return g_option_table;
90 }
91
92 // Options table: Required for subclasses of Options.
93
94 static lldb::OptionDefinition g_option_table[];
95
96 // Instance variables to hold the values for command options.
97
98 bool stop_at_entry;
Greg Claytonc1d37752010-10-18 01:45:30 +000099 bool in_new_tty;
Chris Lattner24943d22010-06-08 16:52:24 +0000100 std::string stderr_path;
101 std::string stdin_path;
102 std::string stdout_path;
103 std::string plugin_name;
104
105 };
106
Greg Clayton238c0a12010-09-18 01:14:36 +0000107 CommandObjectProcessLaunch (CommandInterpreter &interpreter) :
108 CommandObject (interpreter,
109 "process launch",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000110 "Launch the executable in the debugger.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000111 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000112 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000113 CommandArgumentEntry arg;
114 CommandArgumentData run_args_arg;
115
116 // Define the first (and only) variant of this arg.
117 run_args_arg.arg_type = eArgTypeRunArgs;
118 run_args_arg.arg_repetition = eArgRepeatOptional;
119
120 // There is only one variant this argument could be; put it into the argument entry.
121 arg.push_back (run_args_arg);
122
123 // Push the data for the first argument into the m_arguments vector.
124 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000125 }
126
127
128 ~CommandObjectProcessLaunch ()
129 {
130 }
131
132 Options *
133 GetOptions ()
134 {
135 return &m_options;
136 }
137
138 bool
Greg Claytond8c62532010-10-07 04:19:01 +0000139 Execute (Args& launch_args, CommandReturnObject &result)
Chris Lattner24943d22010-06-08 16:52:24 +0000140 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000141 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000142
143 if (target == NULL)
144 {
145 result.AppendError ("invalid target, set executable file using 'file' command");
146 result.SetStatus (eReturnStatusFailed);
147 return false;
148 }
149
150 // If our listener is NULL, users aren't allows to launch
Chris Lattner24943d22010-06-08 16:52:24 +0000151 char filename[PATH_MAX];
Greg Claytonc1d37752010-10-18 01:45:30 +0000152 const Module *exe_module = target->GetExecutableModule().get();
Chris Lattner24943d22010-06-08 16:52:24 +0000153 exe_module->GetFileSpec().GetPath(filename, sizeof(filename));
154
Greg Clayton238c0a12010-09-18 01:14:36 +0000155 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
156 if (process && process->IsAlive())
Chris Lattner24943d22010-06-08 16:52:24 +0000157 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000158 result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before running again.\n",
159 process->GetID());
160 result.SetStatus (eReturnStatusFailed);
161 return false;
Chris Lattner24943d22010-06-08 16:52:24 +0000162 }
163
164 const char *plugin_name;
165 if (!m_options.plugin_name.empty())
166 plugin_name = m_options.plugin_name.c_str();
167 else
168 plugin_name = NULL;
169
Greg Clayton238c0a12010-09-18 01:14:36 +0000170 process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
Chris Lattner24943d22010-06-08 16:52:24 +0000171
Greg Clayton238c0a12010-09-18 01:14:36 +0000172 if (process == NULL)
Caroline Tice6e4c5ce2010-09-04 00:03:46 +0000173 {
Caroline Tice734b4832010-10-15 21:52:38 +0000174 result.AppendErrorWithFormat ("Failed to find a process plugin for executable.\n");
Chris Lattner24943d22010-06-08 16:52:24 +0000175 result.SetStatus (eReturnStatusFailed);
176 return false;
177 }
178
Greg Clayton238c0a12010-09-18 01:14:36 +0000179 // If no launch args were given on the command line, then use any that
180 // might have been set using the "run-args" set variable.
181 if (launch_args.GetArgumentCount() == 0)
182 {
183 if (process->GetRunArguments().GetArgumentCount() > 0)
184 launch_args = process->GetRunArguments();
185 }
186
Greg Claytonc1d37752010-10-18 01:45:30 +0000187 if (m_options.in_new_tty)
188 {
189 char exec_file_path[PATH_MAX];
190 if (exe_module->GetFileSpec().GetPath(exec_file_path, sizeof(exec_file_path)))
191 {
192 launch_args.InsertArgumentAtIndex(0, exec_file_path);
193 }
194 else
195 {
196 result.AppendError("invalid executable");
197 result.SetStatus (eReturnStatusFailed);
198 return false;
199 }
200 }
201
Greg Clayton238c0a12010-09-18 01:14:36 +0000202 Args environment;
203
204 process->GetEnvironmentAsArgs (environment);
205
206 uint32_t launch_flags = eLaunchFlagNone;
207
208 if (process->GetDisableASLR())
209 launch_flags |= eLaunchFlagDisableASLR;
Greg Claytonc1d37752010-10-18 01:45:30 +0000210
211 const char **inferior_argv = launch_args.GetArgumentCount() ? launch_args.GetConstArgumentVector() : NULL;
212 const char **inferior_envp = environment.GetArgumentCount() ? environment.GetConstArgumentVector() : NULL;
Greg Clayton238c0a12010-09-18 01:14:36 +0000213
Greg Claytonc1d37752010-10-18 01:45:30 +0000214 Error error;
Greg Clayton238c0a12010-09-18 01:14:36 +0000215
Greg Claytonc1d37752010-10-18 01:45:30 +0000216 if (m_options.in_new_tty)
Greg Clayton238c0a12010-09-18 01:14:36 +0000217 {
Greg Claytonc1d37752010-10-18 01:45:30 +0000218
Greg Clayton36f63a92010-10-19 03:25:40 +0000219 lldb::pid_t pid = Host::LaunchInNewTerminal (inferior_argv,
220 inferior_envp,
221 &exe_module->GetArchitecture(),
222 true,
223 process->GetDisableASLR());
Greg Claytonc1d37752010-10-18 01:45:30 +0000224
Greg Clayton36f63a92010-10-19 03:25:40 +0000225 if (pid != LLDB_INVALID_PROCESS_ID)
226 error = process->Attach (pid);
Greg Clayton238c0a12010-09-18 01:14:36 +0000227 }
228 else
229 {
Greg Claytonc1d37752010-10-18 01:45:30 +0000230 const char * stdin_path = NULL;
231 const char * stdout_path = NULL;
232 const char * stderr_path = NULL;
233
234 // Were any standard input/output/error paths given on the command line?
235 if (m_options.stdin_path.empty() &&
236 m_options.stdout_path.empty() &&
237 m_options.stderr_path.empty())
238 {
239 // No standard file handles were given on the command line, check
240 // with the process object in case they were give using "set settings"
241 stdin_path = process->GetStandardInputPath();
242 stdout_path = process->GetStandardOutputPath();
243 stderr_path = process->GetStandardErrorPath();
244 }
245 else
246 {
247 stdin_path = m_options.stdin_path.empty() ? NULL : m_options.stdin_path.c_str();
248 stdout_path = m_options.stdout_path.empty() ? NULL : m_options.stdout_path.c_str();
249 stderr_path = m_options.stderr_path.empty() ? NULL : m_options.stderr_path.c_str();
250 }
251
252 if (stdin_path == NULL)
253 stdin_path = "/dev/null";
254 if (stdout_path == NULL)
255 stdout_path = "/dev/null";
256 if (stderr_path == NULL)
257 stderr_path = "/dev/null";
258
259 error = process->Launch (inferior_argv,
260 inferior_envp,
261 launch_flags,
262 stdin_path,
263 stdout_path,
264 stderr_path);
Greg Clayton238c0a12010-09-18 01:14:36 +0000265 }
Greg Clayton238c0a12010-09-18 01:14:36 +0000266
267 if (error.Success())
268 {
Greg Claytonc1d37752010-10-18 01:45:30 +0000269 const char *archname = exe_module->GetArchitecture().AsCString();
270
271 result.AppendMessageWithFormat ("Process %i launched: '%s' (%s)\n", process->GetID(), filename, archname);
Greg Claytond8c62532010-10-07 04:19:01 +0000272 result.SetDidChangeProcessState (true);
Greg Clayton238c0a12010-09-18 01:14:36 +0000273 if (m_options.stop_at_entry == false)
274 {
Greg Claytond8c62532010-10-07 04:19:01 +0000275 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
Greg Clayton238c0a12010-09-18 01:14:36 +0000276 StateType state = process->WaitForProcessToStop (NULL);
277
278 if (state == eStateStopped)
279 {
Greg Claytond8c62532010-10-07 04:19:01 +0000280 error = process->Resume();
281 if (error.Success())
282 {
283 bool synchronous_execution = m_interpreter.GetSynchronous ();
284 if (synchronous_execution)
285 {
286 state = process->WaitForProcessToStop (NULL);
287 result.SetDidChangeProcessState (true);
288 result.SetStatus (eReturnStatusSuccessFinishResult);
289 }
290 else
291 {
292 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
293 }
294 }
Greg Clayton238c0a12010-09-18 01:14:36 +0000295 }
296 }
297 }
298
Chris Lattner24943d22010-06-08 16:52:24 +0000299 return result.Succeeded();
300 }
301
Jim Ingham767af882010-07-07 03:36:20 +0000302 virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
303 {
304 // No repeat for "process launch"...
305 return "";
306 }
307
Chris Lattner24943d22010-06-08 16:52:24 +0000308protected:
309
310 CommandOptions m_options;
311};
312
313
Greg Claytonc1d37752010-10-18 01:45:30 +0000314#define SET1 LLDB_OPT_SET_1
315#define SET2 LLDB_OPT_SET_2
316
Chris Lattner24943d22010-06-08 16:52:24 +0000317lldb::OptionDefinition
318CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
319{
Greg Claytonc1d37752010-10-18 01:45:30 +0000320{ SET1 | SET2, false, "stop-at-entry", 's', no_argument, NULL, 0, eArgTypeNone, "Stop at the entry point of the program when launching a process."},
321{ SET1 , false, "stdin", 'i', required_argument, NULL, 0, eArgTypePath, "Redirect stdin for the process to <path>."},
322{ SET1 , false, "stdout", 'o', required_argument, NULL, 0, eArgTypePath, "Redirect stdout for the process to <path>."},
323{ SET1 , false, "stderr", 'e', required_argument, NULL, 0, eArgTypePath, "Redirect stderr for the process to <path>."},
324{ SET1 | SET2, false, "plugin", 'p', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
325{ SET2, false, "tty", 't', no_argument, NULL, 0, eArgTypeNone, "Start the process in a new terminal (tty)."},
326{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +0000327};
328
Greg Claytonc1d37752010-10-18 01:45:30 +0000329#undef SET1
330#undef SET2
Chris Lattner24943d22010-06-08 16:52:24 +0000331
332//-------------------------------------------------------------------------
333// CommandObjectProcessAttach
334//-------------------------------------------------------------------------
335
336class CommandObjectProcessAttach : public CommandObject
337{
338public:
339
Chris Lattner24943d22010-06-08 16:52:24 +0000340 class CommandOptions : public Options
341 {
342 public:
343
344 CommandOptions () :
345 Options()
346 {
347 // Keep default values of all options in one place: ResetOptionValues ()
348 ResetOptionValues ();
349 }
350
351 ~CommandOptions ()
352 {
353 }
354
355 Error
356 SetOptionValue (int option_idx, const char *option_arg)
357 {
358 Error error;
359 char short_option = (char) m_getopt_table[option_idx].val;
360 bool success = false;
361 switch (short_option)
362 {
363 case 'p':
364 pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success);
365 if (!success || pid == LLDB_INVALID_PROCESS_ID)
366 {
367 error.SetErrorStringWithFormat("Invalid process ID '%s'.\n", option_arg);
368 }
369 break;
370
371 case 'P':
372 plugin_name = option_arg;
373 break;
374
375 case 'n':
376 name.assign(option_arg);
377 break;
378
379 case 'w':
380 waitfor = true;
381 break;
382
383 default:
384 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
385 break;
386 }
387 return error;
388 }
389
390 void
391 ResetOptionValues ()
392 {
393 Options::ResetOptionValues();
394 pid = LLDB_INVALID_PROCESS_ID;
395 name.clear();
396 waitfor = false;
397 }
398
399 const lldb::OptionDefinition*
400 GetDefinitions ()
401 {
402 return g_option_table;
403 }
404
Jim Ingham7508e732010-08-09 23:31:02 +0000405 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000406 HandleOptionArgumentCompletion (CommandInterpreter &interpeter,
Jim Ingham7508e732010-08-09 23:31:02 +0000407 Args &input,
408 int cursor_index,
409 int char_pos,
410 OptionElementVector &opt_element_vector,
411 int opt_element_index,
412 int match_start_point,
413 int max_return_elements,
414 bool &word_complete,
415 StringList &matches)
416 {
417 int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
418 int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
419
420 // We are only completing the name option for now...
421
422 const lldb::OptionDefinition *opt_defs = GetDefinitions();
423 if (opt_defs[opt_defs_index].short_option == 'n')
424 {
425 // Are we in the name?
426
427 // Look to see if there is a -P argument provided, and if so use that plugin, otherwise
428 // use the default plugin.
Greg Clayton238c0a12010-09-18 01:14:36 +0000429 Process *process = interpeter.GetDebugger().GetExecutionContext().process;
Jim Ingham7508e732010-08-09 23:31:02 +0000430 bool need_to_delete_process = false;
431
432 const char *partial_name = NULL;
433 partial_name = input.GetArgumentAtIndex(opt_arg_pos);
434
435 if (process && process->IsAlive())
436 return true;
437
Greg Clayton238c0a12010-09-18 01:14:36 +0000438 Target *target = interpeter.GetDebugger().GetSelectedTarget().get();
Jim Ingham7508e732010-08-09 23:31:02 +0000439 if (target == NULL)
440 {
441 // No target has been set yet, for now do host completion. Otherwise I don't know how we would
442 // figure out what the right target to use is...
443 std::vector<lldb::pid_t> pids;
444 Host::ListProcessesMatchingName (partial_name, matches, pids);
445 return true;
446 }
447 if (!process)
448 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000449 process = target->CreateProcess (interpeter.GetDebugger().GetListener(), partial_name).get();
Jim Ingham7508e732010-08-09 23:31:02 +0000450 need_to_delete_process = true;
451 }
452
453 if (process)
454 {
455 matches.Clear();
456 std::vector<lldb::pid_t> pids;
457 process->ListProcessesMatchingName (NULL, matches, pids);
458 if (need_to_delete_process)
459 target->DeleteCurrentProcess();
460 return true;
461 }
462 }
463
464 return false;
465 }
466
Chris Lattner24943d22010-06-08 16:52:24 +0000467 // Options table: Required for subclasses of Options.
468
469 static lldb::OptionDefinition g_option_table[];
470
471 // Instance variables to hold the values for command options.
472
473 lldb::pid_t pid;
474 std::string plugin_name;
475 std::string name;
476 bool waitfor;
477 };
478
Greg Clayton238c0a12010-09-18 01:14:36 +0000479 CommandObjectProcessAttach (CommandInterpreter &interpreter) :
480 CommandObject (interpreter,
481 "process attach",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000482 "Attach to a process.",
Jim Ingham7508e732010-08-09 23:31:02 +0000483 "process attach <cmd-options>")
484 {
Jim Ingham7508e732010-08-09 23:31:02 +0000485 }
486
487 ~CommandObjectProcessAttach ()
488 {
489 }
490
491 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000492 Execute (Args& command,
Jim Ingham7508e732010-08-09 23:31:02 +0000493 CommandReturnObject &result)
494 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000495 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
Jim Ingham7508e732010-08-09 23:31:02 +0000496
Greg Clayton238c0a12010-09-18 01:14:36 +0000497 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Jim Ingham7508e732010-08-09 23:31:02 +0000498 if (process)
499 {
500 if (process->IsAlive())
501 {
502 result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before attaching.\n",
503 process->GetID());
504 result.SetStatus (eReturnStatusFailed);
505 return false;
506 }
507 }
508
509 if (target == NULL)
510 {
511 // If there isn't a current target create one.
512 TargetSP new_target_sp;
513 FileSpec emptyFileSpec;
514 ArchSpec emptyArchSpec;
515 Error error;
516
Greg Clayton238c0a12010-09-18 01:14:36 +0000517 error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(),
518 emptyFileSpec,
519 emptyArchSpec,
520 NULL,
521 false,
522 new_target_sp);
Jim Ingham7508e732010-08-09 23:31:02 +0000523 target = new_target_sp.get();
524 if (target == NULL || error.Fail())
525 {
526 result.AppendError(error.AsCString("Error creating empty target"));
527 return false;
528 }
Greg Clayton238c0a12010-09-18 01:14:36 +0000529 m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target);
Jim Ingham7508e732010-08-09 23:31:02 +0000530 }
531
532 // Record the old executable module, we want to issue a warning if the process of attaching changed the
533 // current executable (like somebody said "file foo" then attached to a PID whose executable was bar.)
534
535 ModuleSP old_exec_module_sp = target->GetExecutableModule();
536 ArchSpec old_arch_spec = target->GetArchitecture();
537
538 if (command.GetArgumentCount())
539 {
540 result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
541 result.SetStatus (eReturnStatusFailed);
542 }
543 else
544 {
545 const char *plugin_name = NULL;
546
547 if (!m_options.plugin_name.empty())
548 plugin_name = m_options.plugin_name.c_str();
549
Greg Clayton238c0a12010-09-18 01:14:36 +0000550 process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
Jim Ingham7508e732010-08-09 23:31:02 +0000551
552 if (process)
553 {
554 Error error;
555 int attach_pid = m_options.pid;
556
Jim Ingham4805a1c2010-09-15 01:34:14 +0000557 const char *wait_name = NULL;
558
559 if (m_options.name.empty())
560 {
561 if (old_exec_module_sp)
562 {
563 wait_name = old_exec_module_sp->GetFileSpec().GetFilename().AsCString();
564 }
565 }
566 else
567 {
568 wait_name = m_options.name.c_str();
569 }
570
Jim Ingham7508e732010-08-09 23:31:02 +0000571 // If we are waiting for a process with this name to show up, do that first.
572 if (m_options.waitfor)
573 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000574
575 if (wait_name == NULL)
Jim Ingham7508e732010-08-09 23:31:02 +0000576 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000577 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 +0000578 result.SetStatus (eReturnStatusFailed);
579 return false;
580 }
Jim Ingham4805a1c2010-09-15 01:34:14 +0000581
Greg Clayton238c0a12010-09-18 01:14:36 +0000582 m_interpreter.GetDebugger().GetOutputStream().Printf("Waiting to attach to a process named \"%s\".\n", wait_name);
Jim Ingham4805a1c2010-09-15 01:34:14 +0000583 error = process->Attach (wait_name, m_options.waitfor);
584 if (error.Success())
585 {
586 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
587 }
Jim Ingham7508e732010-08-09 23:31:02 +0000588 else
589 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000590 result.AppendErrorWithFormat ("Waiting for a process to launch named '%s': %s\n",
591 wait_name,
592 error.AsCString());
593 result.SetStatus (eReturnStatusFailed);
594 return false;
Jim Ingham7508e732010-08-09 23:31:02 +0000595 }
596 }
597 else
598 {
599 // If the process was specified by name look it up, so we can warn if there are multiple
600 // processes with this pid.
601
Jim Ingham4805a1c2010-09-15 01:34:14 +0000602 if (attach_pid == LLDB_INVALID_PROCESS_ID && wait_name != NULL)
Jim Ingham7508e732010-08-09 23:31:02 +0000603 {
604 std::vector<lldb::pid_t> pids;
605 StringList matches;
606
Jim Ingham4805a1c2010-09-15 01:34:14 +0000607 process->ListProcessesMatchingName(wait_name, matches, pids);
Jim Ingham7508e732010-08-09 23:31:02 +0000608 if (matches.GetSize() > 1)
609 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000610 result.AppendErrorWithFormat("More than one process named %s\n", wait_name);
Jim Ingham7508e732010-08-09 23:31:02 +0000611 result.SetStatus (eReturnStatusFailed);
612 return false;
613 }
614 else if (matches.GetSize() == 0)
615 {
Jim Ingham4805a1c2010-09-15 01:34:14 +0000616 result.AppendErrorWithFormat("Could not find a process named %s\n", wait_name);
Jim Ingham7508e732010-08-09 23:31:02 +0000617 result.SetStatus (eReturnStatusFailed);
618 return false;
619 }
620 else
621 {
622 attach_pid = pids[0];
623 }
624
625 }
626
627 if (attach_pid != LLDB_INVALID_PROCESS_ID)
628 {
629 error = process->Attach (attach_pid);
630 if (error.Success())
631 {
632 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
633 }
634 else
635 {
636 result.AppendErrorWithFormat ("Attaching to process %i failed: %s.\n",
637 attach_pid,
638 error.AsCString());
639 result.SetStatus (eReturnStatusFailed);
640 }
641 }
642 else
643 {
644 result.AppendErrorWithFormat ("No PID specified for attach\n",
645 attach_pid,
646 error.AsCString());
647 result.SetStatus (eReturnStatusFailed);
648
649 }
650 }
651 }
652 }
653
654 if (result.Succeeded())
655 {
656 // Okay, we're done. Last step is to warn if the executable module has changed:
657 if (!old_exec_module_sp)
658 {
659 char new_path[PATH_MAX + 1];
660 target->GetExecutableModule()->GetFileSpec().GetPath(new_path, PATH_MAX);
661
662 result.AppendMessageWithFormat("Executable module set to \"%s\".\n",
663 new_path);
664 }
665 else if (old_exec_module_sp->GetFileSpec() != target->GetExecutableModule()->GetFileSpec())
666 {
667 char old_path[PATH_MAX + 1];
668 char new_path[PATH_MAX + 1];
669
670 old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX);
671 target->GetExecutableModule()->GetFileSpec().GetPath (new_path, PATH_MAX);
672
673 result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n",
674 old_path, new_path);
675 }
676
677 if (!old_arch_spec.IsValid())
678 {
679 result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().AsCString());
680 }
681 else if (old_arch_spec != target->GetArchitecture())
682 {
683 result.AppendWarningWithFormat("Architecture changed from %s to %s.\n",
684 old_arch_spec.AsCString(), target->GetArchitecture().AsCString());
685 }
686 }
687 return result.Succeeded();
688 }
689
690 Options *
691 GetOptions ()
692 {
693 return &m_options;
694 }
695
Chris Lattner24943d22010-06-08 16:52:24 +0000696protected:
697
698 CommandOptions m_options;
699};
700
701
702lldb::OptionDefinition
703CommandObjectProcessAttach::CommandOptions::g_option_table[] =
704{
Caroline Tice4d6675c2010-10-01 19:59:14 +0000705{ LLDB_OPT_SET_ALL, false, "plugin", 'P', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
706{ LLDB_OPT_SET_1, false, "pid", 'p', required_argument, NULL, 0, eArgTypePid, "The process ID of an existing process to attach to."},
707{ LLDB_OPT_SET_2, false, "name", 'n', required_argument, NULL, 0, eArgTypeProcessName, "The name of the process to attach to."},
708{ LLDB_OPT_SET_2, false, "waitfor",'w', no_argument, NULL, 0, eArgTypeNone, "Wait for the the process with <process-name> to launch."},
709{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +0000710};
711
712//-------------------------------------------------------------------------
713// CommandObjectProcessContinue
714//-------------------------------------------------------------------------
715
716class CommandObjectProcessContinue : public CommandObject
717{
718public:
719
Greg Clayton238c0a12010-09-18 01:14:36 +0000720 CommandObjectProcessContinue (CommandInterpreter &interpreter) :
721 CommandObject (interpreter,
722 "process continue",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000723 "Continue execution of all threads in the current process.",
Chris Lattner24943d22010-06-08 16:52:24 +0000724 "process continue",
725 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
726 {
727 }
728
729
730 ~CommandObjectProcessContinue ()
731 {
732 }
733
734 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000735 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000736 CommandReturnObject &result)
737 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000738 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
739 bool synchronous_execution = m_interpreter.GetSynchronous ();
Chris Lattner24943d22010-06-08 16:52:24 +0000740
741 if (process == NULL)
742 {
743 result.AppendError ("no process to continue");
744 result.SetStatus (eReturnStatusFailed);
745 return false;
746 }
747
748 StateType state = process->GetState();
749 if (state == eStateStopped)
750 {
751 if (command.GetArgumentCount() != 0)
752 {
753 result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str());
754 result.SetStatus (eReturnStatusFailed);
755 return false;
756 }
757
758 const uint32_t num_threads = process->GetThreadList().GetSize();
759
760 // Set the actions that the threads should each take when resuming
761 for (uint32_t idx=0; idx<num_threads; ++idx)
762 {
763 process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning);
764 }
765
766 Error error(process->Resume());
767 if (error.Success())
768 {
Greg Claytonc1d37752010-10-18 01:45:30 +0000769 result.AppendMessageWithFormat ("Process %i resuming\n", process->GetID());
Chris Lattner24943d22010-06-08 16:52:24 +0000770 if (synchronous_execution)
771 {
Greg Claytonbef15832010-07-14 00:18:15 +0000772 state = process->WaitForProcessToStop (NULL);
Chris Lattner24943d22010-06-08 16:52:24 +0000773
774 result.SetDidChangeProcessState (true);
775 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
776 result.SetStatus (eReturnStatusSuccessFinishNoResult);
777 }
778 else
779 {
780 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
781 }
782 }
783 else
784 {
785 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
786 result.SetStatus (eReturnStatusFailed);
787 }
788 }
789 else
790 {
791 result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
792 StateAsCString(state));
793 result.SetStatus (eReturnStatusFailed);
794 }
795 return result.Succeeded();
796 }
797};
798
799//-------------------------------------------------------------------------
800// CommandObjectProcessDetach
801//-------------------------------------------------------------------------
802
803class CommandObjectProcessDetach : public CommandObject
804{
805public:
806
Greg Clayton238c0a12010-09-18 01:14:36 +0000807 CommandObjectProcessDetach (CommandInterpreter &interpreter) :
808 CommandObject (interpreter,
809 "process detach",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000810 "Detach from the current process being debugged.",
Chris Lattner24943d22010-06-08 16:52:24 +0000811 "process detach",
812 eFlagProcessMustBeLaunched)
813 {
814 }
815
816 ~CommandObjectProcessDetach ()
817 {
818 }
819
820 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000821 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000822 CommandReturnObject &result)
823 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000824 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000825 if (process == NULL)
826 {
827 result.AppendError ("must have a valid process in order to detach");
828 result.SetStatus (eReturnStatusFailed);
829 return false;
830 }
831
832 Error error (process->Detach());
833 if (error.Success())
834 {
835 result.SetStatus (eReturnStatusSuccessFinishResult);
836 }
837 else
838 {
839 result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString());
840 result.SetStatus (eReturnStatusFailed);
841 return false;
842 }
843 return result.Succeeded();
844 }
845};
846
847//-------------------------------------------------------------------------
848// CommandObjectProcessSignal
849//-------------------------------------------------------------------------
850
851class CommandObjectProcessSignal : public CommandObject
852{
853public:
854
Greg Clayton238c0a12010-09-18 01:14:36 +0000855 CommandObjectProcessSignal (CommandInterpreter &interpreter) :
856 CommandObject (interpreter,
857 "process signal",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000858 "Send a UNIX signal to the current process being debugged.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000859 NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000860 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000861 CommandArgumentEntry arg;
862 CommandArgumentData signal_arg;
863
864 // Define the first (and only) variant of this arg.
Caroline Tice3a62e6d2010-10-18 22:56:57 +0000865 signal_arg.arg_type = eArgTypeUnixSignal;
Caroline Tice43b014a2010-10-04 22:28:36 +0000866 signal_arg.arg_repetition = eArgRepeatPlain;
867
868 // There is only one variant this argument could be; put it into the argument entry.
869 arg.push_back (signal_arg);
870
871 // Push the data for the first argument into the m_arguments vector.
872 m_arguments.push_back (arg);
Chris Lattner24943d22010-06-08 16:52:24 +0000873 }
874
875 ~CommandObjectProcessSignal ()
876 {
877 }
878
879 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000880 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000881 CommandReturnObject &result)
882 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000883 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000884 if (process == NULL)
885 {
886 result.AppendError ("no process to signal");
887 result.SetStatus (eReturnStatusFailed);
888 return false;
889 }
890
891 if (command.GetArgumentCount() == 1)
892 {
Greg Clayton8f6be2a2010-10-09 01:40:57 +0000893 int signo = LLDB_INVALID_SIGNAL_NUMBER;
894
895 const char *signal_name = command.GetArgumentAtIndex(0);
896 if (::isxdigit (signal_name[0]))
897 signo = Args::StringToSInt32(signal_name, LLDB_INVALID_SIGNAL_NUMBER, 0);
898 else
899 signo = process->GetUnixSignals().GetSignalNumberFromName (signal_name);
900
901 if (signo == LLDB_INVALID_SIGNAL_NUMBER)
Chris Lattner24943d22010-06-08 16:52:24 +0000902 {
903 result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0));
904 result.SetStatus (eReturnStatusFailed);
905 }
906 else
907 {
908 Error error (process->Signal (signo));
909 if (error.Success())
910 {
911 result.SetStatus (eReturnStatusSuccessFinishResult);
912 }
913 else
914 {
915 result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString());
916 result.SetStatus (eReturnStatusFailed);
917 }
918 }
919 }
920 else
921 {
922 result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: \n", m_cmd_name.c_str(),
923 m_cmd_syntax.c_str());
924 result.SetStatus (eReturnStatusFailed);
925 }
926 return result.Succeeded();
927 }
928};
929
930
931//-------------------------------------------------------------------------
932// CommandObjectProcessInterrupt
933//-------------------------------------------------------------------------
934
935class CommandObjectProcessInterrupt : public CommandObject
936{
937public:
938
939
Greg Clayton238c0a12010-09-18 01:14:36 +0000940 CommandObjectProcessInterrupt (CommandInterpreter &interpreter) :
941 CommandObject (interpreter,
942 "process interrupt",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000943 "Interrupt the current process being debugged.",
Chris Lattner24943d22010-06-08 16:52:24 +0000944 "process interrupt",
945 eFlagProcessMustBeLaunched)
946 {
947 }
948
949 ~CommandObjectProcessInterrupt ()
950 {
951 }
952
953 bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000954 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000955 CommandReturnObject &result)
956 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000957 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000958 if (process == NULL)
959 {
960 result.AppendError ("no process to halt");
961 result.SetStatus (eReturnStatusFailed);
962 return false;
963 }
964
965 if (command.GetArgumentCount() == 0)
966 {
967 Error error(process->Halt ());
968 if (error.Success())
969 {
970 result.SetStatus (eReturnStatusSuccessFinishResult);
971
972 // Maybe we should add a "SuspendThreadPlans so we
973 // can halt, and keep in place all the current thread plans.
974 process->GetThreadList().DiscardThreadPlans();
975 }
976 else
977 {
978 result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString());
979 result.SetStatus (eReturnStatusFailed);
980 }
981 }
982 else
983 {
984 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
985 m_cmd_name.c_str(),
986 m_cmd_syntax.c_str());
987 result.SetStatus (eReturnStatusFailed);
988 }
989 return result.Succeeded();
990 }
991};
992
993//-------------------------------------------------------------------------
994// CommandObjectProcessKill
995//-------------------------------------------------------------------------
996
997class CommandObjectProcessKill : public CommandObject
998{
999public:
1000
Greg Clayton238c0a12010-09-18 01:14:36 +00001001 CommandObjectProcessKill (CommandInterpreter &interpreter) :
1002 CommandObject (interpreter,
1003 "process kill",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001004 "Terminate the current process being debugged.",
Chris Lattner24943d22010-06-08 16:52:24 +00001005 "process kill",
1006 eFlagProcessMustBeLaunched)
1007 {
1008 }
1009
1010 ~CommandObjectProcessKill ()
1011 {
1012 }
1013
1014 bool
Greg Clayton238c0a12010-09-18 01:14:36 +00001015 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +00001016 CommandReturnObject &result)
1017 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001018 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +00001019 if (process == NULL)
1020 {
1021 result.AppendError ("no process to kill");
1022 result.SetStatus (eReturnStatusFailed);
1023 return false;
1024 }
1025
1026 if (command.GetArgumentCount() == 0)
1027 {
1028 Error error (process->Destroy());
1029 if (error.Success())
1030 {
1031 result.SetStatus (eReturnStatusSuccessFinishResult);
1032 }
1033 else
1034 {
1035 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString());
1036 result.SetStatus (eReturnStatusFailed);
1037 }
1038 }
1039 else
1040 {
1041 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
1042 m_cmd_name.c_str(),
1043 m_cmd_syntax.c_str());
1044 result.SetStatus (eReturnStatusFailed);
1045 }
1046 return result.Succeeded();
1047 }
1048};
1049
1050//-------------------------------------------------------------------------
Jim Ingham41313fc2010-06-18 01:23:09 +00001051// CommandObjectProcessStatus
1052//-------------------------------------------------------------------------
1053class CommandObjectProcessStatus : public CommandObject
1054{
1055public:
Greg Clayton238c0a12010-09-18 01:14:36 +00001056 CommandObjectProcessStatus (CommandInterpreter &interpreter) :
1057 CommandObject (interpreter,
1058 "process status",
Caroline Ticeabb507a2010-09-08 21:06:11 +00001059 "Show the current status and location of executing process.",
1060 "process status",
Jim Ingham41313fc2010-06-18 01:23:09 +00001061 0)
1062 {
1063 }
1064
1065 ~CommandObjectProcessStatus()
1066 {
1067 }
1068
1069
1070 bool
1071 Execute
1072 (
1073 Args& command,
Jim Ingham41313fc2010-06-18 01:23:09 +00001074 CommandReturnObject &result
1075 )
1076 {
1077 StreamString &output_stream = result.GetOutputStream();
1078 result.SetStatus (eReturnStatusSuccessFinishNoResult);
Greg Clayton238c0a12010-09-18 01:14:36 +00001079 ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
Jim Ingham41313fc2010-06-18 01:23:09 +00001080 if (exe_ctx.process)
1081 {
1082 const StateType state = exe_ctx.process->GetState();
1083 if (StateIsStoppedState(state))
1084 {
1085 if (state == eStateExited)
1086 {
1087 int exit_status = exe_ctx.process->GetExitStatus();
1088 const char *exit_description = exe_ctx.process->GetExitDescription();
1089 output_stream.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n",
1090 exe_ctx.process->GetID(),
1091 exit_status,
1092 exit_status,
1093 exit_description ? exit_description : "");
1094 }
1095 else
1096 {
1097 output_stream.Printf ("Process %d %s\n", exe_ctx.process->GetID(), StateAsCString (state));
1098 if (exe_ctx.thread == NULL)
1099 exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
1100 if (exe_ctx.thread != NULL)
1101 {
Greg Clayton238c0a12010-09-18 01:14:36 +00001102 DisplayThreadsInfo (m_interpreter, &exe_ctx, result, true, true);
Jim Ingham41313fc2010-06-18 01:23:09 +00001103 }
1104 else
1105 {
1106 result.AppendError ("No valid thread found in current process.");
1107 result.SetStatus (eReturnStatusFailed);
1108 }
1109 }
1110 }
1111 else
1112 {
1113 output_stream.Printf ("Process %d is running.\n",
1114 exe_ctx.process->GetID());
1115 }
1116 }
1117 else
1118 {
1119 result.AppendError ("No current location or status available.");
1120 result.SetStatus (eReturnStatusFailed);
1121 }
1122 return result.Succeeded();
1123 }
1124};
1125
1126//-------------------------------------------------------------------------
Caroline Tice23d6f272010-10-13 20:44:39 +00001127// CommandObjectProcessHandle
1128//-------------------------------------------------------------------------
1129
1130class CommandObjectProcessHandle : public CommandObject
1131{
1132public:
1133
1134 class CommandOptions : public Options
1135 {
1136 public:
1137
1138 CommandOptions () :
1139 Options ()
1140 {
1141 ResetOptionValues ();
1142 }
1143
1144 ~CommandOptions ()
1145 {
1146 }
1147
1148 Error
1149 SetOptionValue (int option_idx, const char *option_arg)
1150 {
1151 Error error;
1152 char short_option = (char) m_getopt_table[option_idx].val;
1153
1154 switch (short_option)
1155 {
1156 case 's':
1157 stop = option_arg;
1158 break;
1159 case 'n':
1160 notify = option_arg;
1161 break;
1162 case 'p':
1163 pass = option_arg;
1164 break;
1165 default:
1166 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
1167 break;
1168 }
1169 return error;
1170 }
1171
1172 void
1173 ResetOptionValues ()
1174 {
1175 Options::ResetOptionValues();
1176 stop.clear();
1177 notify.clear();
1178 pass.clear();
1179 }
1180
1181 const lldb::OptionDefinition*
1182 GetDefinitions ()
1183 {
1184 return g_option_table;
1185 }
1186
1187 // Options table: Required for subclasses of Options.
1188
1189 static lldb::OptionDefinition g_option_table[];
1190
1191 // Instance variables to hold the values for command options.
1192
1193 std::string stop;
1194 std::string notify;
1195 std::string pass;
1196 };
1197
1198
1199 CommandObjectProcessHandle (CommandInterpreter &interpreter) :
1200 CommandObject (interpreter,
1201 "process handle",
Caroline Ticee7471982010-10-14 21:31:13 +00001202 "Show or update what the process and debugger should do with various signals received from the OS.",
Caroline Tice23d6f272010-10-13 20:44:39 +00001203 NULL)
1204 {
Caroline Ticee7471982010-10-14 21:31:13 +00001205 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 +00001206 CommandArgumentEntry arg;
Caroline Tice3a62e6d2010-10-18 22:56:57 +00001207 CommandArgumentData signal_arg;
Caroline Tice23d6f272010-10-13 20:44:39 +00001208
Caroline Tice3a62e6d2010-10-18 22:56:57 +00001209 signal_arg.arg_type = eArgTypeUnixSignal;
1210 signal_arg.arg_repetition = eArgRepeatStar;
Caroline Tice23d6f272010-10-13 20:44:39 +00001211
Caroline Tice3a62e6d2010-10-18 22:56:57 +00001212 arg.push_back (signal_arg);
Caroline Tice23d6f272010-10-13 20:44:39 +00001213
1214 m_arguments.push_back (arg);
1215 }
1216
1217 ~CommandObjectProcessHandle ()
1218 {
1219 }
1220
1221 Options *
1222 GetOptions ()
1223 {
1224 return &m_options;
1225 }
1226
1227 bool
Caroline Ticee7471982010-10-14 21:31:13 +00001228 VerifyCommandOptionValue (const std::string &option, int &real_value)
Caroline Tice23d6f272010-10-13 20:44:39 +00001229 {
1230 bool okay = true;
1231
Caroline Ticee7471982010-10-14 21:31:13 +00001232 bool success = false;
1233 bool tmp_value = Args::StringToBoolean (option.c_str(), false, &success);
1234
1235 if (success && tmp_value)
1236 real_value = 1;
1237 else if (success && !tmp_value)
1238 real_value = 0;
Caroline Tice23d6f272010-10-13 20:44:39 +00001239 else
1240 {
1241 // If the value isn't 'true' or 'false', it had better be 0 or 1.
Caroline Ticee7471982010-10-14 21:31:13 +00001242 real_value = Args::StringToUInt32 (option.c_str(), 3);
1243 if (real_value != 0 && real_value != 1)
Caroline Tice23d6f272010-10-13 20:44:39 +00001244 okay = false;
1245 }
1246
1247 return okay;
1248 }
1249
Caroline Ticee7471982010-10-14 21:31:13 +00001250 void
1251 PrintSignalHeader (Stream &str)
1252 {
1253 str.Printf ("NAME PASS STOP NOTIFY\n");
1254 str.Printf ("========== ===== ===== ======\n");
1255 }
1256
1257 void
1258 PrintSignal (Stream &str, int32_t signo, const char *sig_name, UnixSignals &signals)
1259 {
1260 bool stop;
1261 bool suppress;
1262 bool notify;
1263
1264 str.Printf ("%-10s ", sig_name);
1265 if (signals.GetSignalInfo (signo, suppress, stop, notify))
1266 {
1267 bool pass = !suppress;
1268 str.Printf ("%s %s %s",
1269 (pass ? "true " : "false"),
1270 (stop ? "true " : "false"),
1271 (notify ? "true " : "false"));
1272 }
1273 str.Printf ("\n");
1274 }
1275
1276 void
1277 PrintSignalInformation (Stream &str, Args &signal_args, int num_valid_signals, UnixSignals &signals)
1278 {
1279 PrintSignalHeader (str);
1280
1281 if (num_valid_signals > 0)
1282 {
1283 size_t num_args = signal_args.GetArgumentCount();
1284 for (size_t i = 0; i < num_args; ++i)
1285 {
1286 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
1287 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
1288 PrintSignal (str, signo, signal_args.GetArgumentAtIndex (i), signals);
1289 }
1290 }
1291 else // Print info for ALL signals
1292 {
1293 int32_t signo = signals.GetFirstSignalNumber();
1294 while (signo != LLDB_INVALID_SIGNAL_NUMBER)
1295 {
1296 PrintSignal (str, signo, signals.GetSignalAsCString (signo), signals);
1297 signo = signals.GetNextSignalNumber (signo);
1298 }
1299 }
1300 }
1301
Caroline Tice23d6f272010-10-13 20:44:39 +00001302 bool
1303 Execute (Args &signal_args, CommandReturnObject &result)
1304 {
1305 TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
1306
1307 if (!target_sp)
1308 {
1309 result.AppendError ("No current target;"
1310 " cannot handle signals until you have a valid target and process.\n");
1311 result.SetStatus (eReturnStatusFailed);
1312 return false;
1313 }
1314
1315 ProcessSP process_sp = target_sp->GetProcessSP();
1316
1317 if (!process_sp)
1318 {
1319 result.AppendError ("No current process; cannot handle signals until you have a valid process.\n");
1320 result.SetStatus (eReturnStatusFailed);
1321 return false;
1322 }
1323
Caroline Tice23d6f272010-10-13 20:44:39 +00001324 int stop_action = -1; // -1 means leave the current setting alone
Caroline Ticee7471982010-10-14 21:31:13 +00001325 int pass_action = -1; // -1 means leave the current setting alone
Caroline Tice23d6f272010-10-13 20:44:39 +00001326 int notify_action = -1; // -1 means leave the current setting alone
1327
1328 if (! m_options.stop.empty()
Caroline Ticee7471982010-10-14 21:31:13 +00001329 && ! VerifyCommandOptionValue (m_options.stop, stop_action))
Caroline Tice23d6f272010-10-13 20:44:39 +00001330 {
1331 result.AppendError ("Invalid argument for command option --stop; must be true or false.\n");
1332 result.SetStatus (eReturnStatusFailed);
1333 return false;
1334 }
1335
1336 if (! m_options.notify.empty()
Caroline Ticee7471982010-10-14 21:31:13 +00001337 && ! VerifyCommandOptionValue (m_options.notify, notify_action))
Caroline Tice23d6f272010-10-13 20:44:39 +00001338 {
1339 result.AppendError ("Invalid argument for command option --notify; must be true or false.\n");
1340 result.SetStatus (eReturnStatusFailed);
1341 return false;
1342 }
1343
1344 if (! m_options.pass.empty()
Caroline Ticee7471982010-10-14 21:31:13 +00001345 && ! VerifyCommandOptionValue (m_options.pass, pass_action))
Caroline Tice23d6f272010-10-13 20:44:39 +00001346 {
1347 result.AppendError ("Invalid argument for command option --pass; must be true or false.\n");
1348 result.SetStatus (eReturnStatusFailed);
1349 return false;
1350 }
1351
1352 size_t num_args = signal_args.GetArgumentCount();
1353 UnixSignals &signals = process_sp->GetUnixSignals();
1354 int num_signals_set = 0;
1355
Caroline Ticee7471982010-10-14 21:31:13 +00001356 if (num_args > 0)
Caroline Tice23d6f272010-10-13 20:44:39 +00001357 {
Caroline Ticee7471982010-10-14 21:31:13 +00001358 for (size_t i = 0; i < num_args; ++i)
Caroline Tice23d6f272010-10-13 20:44:39 +00001359 {
Caroline Ticee7471982010-10-14 21:31:13 +00001360 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
1361 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
Caroline Tice23d6f272010-10-13 20:44:39 +00001362 {
Caroline Ticee7471982010-10-14 21:31:13 +00001363 // Casting the actions as bools here should be okay, because VerifyCommandOptionValue guarantees
1364 // the value is either 0 or 1.
1365 if (stop_action != -1)
1366 signals.SetShouldStop (signo, (bool) stop_action);
1367 if (pass_action != -1)
1368 {
1369 bool suppress = ! ((bool) pass_action);
1370 signals.SetShouldSuppress (signo, suppress);
1371 }
1372 if (notify_action != -1)
1373 signals.SetShouldNotify (signo, (bool) notify_action);
1374 ++num_signals_set;
Caroline Tice23d6f272010-10-13 20:44:39 +00001375 }
Caroline Ticee7471982010-10-14 21:31:13 +00001376 else
1377 {
1378 result.AppendErrorWithFormat ("Invalid signal name '%s'\n", signal_args.GetArgumentAtIndex (i));
1379 }
Caroline Tice23d6f272010-10-13 20:44:39 +00001380 }
1381 }
Caroline Ticee7471982010-10-14 21:31:13 +00001382 else
1383 {
1384 // No signal specified, if any command options were specified, update ALL signals.
1385 if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1))
1386 {
1387 if (m_interpreter.Confirm ("Do you really want to update all the signals?", false))
1388 {
1389 int32_t signo = signals.GetFirstSignalNumber();
1390 while (signo != LLDB_INVALID_SIGNAL_NUMBER)
1391 {
1392 if (notify_action != -1)
1393 signals.SetShouldNotify (signo, (bool) notify_action);
1394 if (stop_action != -1)
1395 signals.SetShouldStop (signo, (bool) stop_action);
1396 if (pass_action != -1)
1397 {
1398 bool suppress = ! ((bool) pass_action);
1399 signals.SetShouldSuppress (signo, suppress);
1400 }
1401 signo = signals.GetNextSignalNumber (signo);
1402 }
1403 }
1404 }
1405 }
1406
1407 PrintSignalInformation (result.GetOutputStream(), signal_args, num_signals_set, signals);
Caroline Tice23d6f272010-10-13 20:44:39 +00001408
1409 if (num_signals_set > 0)
1410 result.SetStatus (eReturnStatusSuccessFinishNoResult);
1411 else
1412 result.SetStatus (eReturnStatusFailed);
1413
1414 return result.Succeeded();
1415 }
1416
1417protected:
1418
1419 CommandOptions m_options;
1420};
1421
1422lldb::OptionDefinition
1423CommandObjectProcessHandle::CommandOptions::g_option_table[] =
1424{
1425{ 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." },
1426{ 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." },
1427{ LLDB_OPT_SET_1, false, "pass", 'p', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." },
1428{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1429};
1430
1431//-------------------------------------------------------------------------
Chris Lattner24943d22010-06-08 16:52:24 +00001432// CommandObjectMultiwordProcess
1433//-------------------------------------------------------------------------
1434
Greg Clayton63094e02010-06-23 01:19:29 +00001435CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001436 CommandObjectMultiword (interpreter,
1437 "process",
1438 "A set of commands for operating on a process.",
1439 "process <subcommand> [<subcommand-options>]")
Chris Lattner24943d22010-06-08 16:52:24 +00001440{
Greg Clayton238c0a12010-09-18 01:14:36 +00001441 LoadSubCommand ("attach", CommandObjectSP (new CommandObjectProcessAttach (interpreter)));
1442 LoadSubCommand ("launch", CommandObjectSP (new CommandObjectProcessLaunch (interpreter)));
1443 LoadSubCommand ("continue", CommandObjectSP (new CommandObjectProcessContinue (interpreter)));
1444 LoadSubCommand ("detach", CommandObjectSP (new CommandObjectProcessDetach (interpreter)));
1445 LoadSubCommand ("signal", CommandObjectSP (new CommandObjectProcessSignal (interpreter)));
Caroline Tice23d6f272010-10-13 20:44:39 +00001446 LoadSubCommand ("handle", CommandObjectSP (new CommandObjectProcessHandle (interpreter)));
Greg Clayton238c0a12010-09-18 01:14:36 +00001447 LoadSubCommand ("status", CommandObjectSP (new CommandObjectProcessStatus (interpreter)));
1448 LoadSubCommand ("interrupt", CommandObjectSP (new CommandObjectProcessInterrupt (interpreter)));
1449 LoadSubCommand ("kill", CommandObjectSP (new CommandObjectProcessKill (interpreter)));
Chris Lattner24943d22010-06-08 16:52:24 +00001450}
1451
1452CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess ()
1453{
1454}
1455