xref: /llvm-project/lldb/source/Commands/CommandObjectProcess.cpp (revision bf4b7be68ee9da3cc43fedee101457140d3330cd)
1 //===-- 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 "lldb/lldb-python.h"
11 
12 #include "CommandObjectProcess.h"
13 
14 // C Includes
15 // C++ Includes
16 // Other libraries and framework includes
17 // Project includes
18 #include "lldb/Breakpoint/Breakpoint.h"
19 #include "lldb/Breakpoint/BreakpointLocation.h"
20 #include "lldb/Breakpoint/BreakpointSite.h"
21 #include "lldb/Core/State.h"
22 #include "lldb/Core/Module.h"
23 #include "lldb/Host/Host.h"
24 #include "lldb/Interpreter/Args.h"
25 #include "lldb/Interpreter/Options.h"
26 #include "lldb/Interpreter/CommandInterpreter.h"
27 #include "lldb/Interpreter/CommandReturnObject.h"
28 #include "lldb/Target/Platform.h"
29 #include "lldb/Target/Process.h"
30 #include "lldb/Target/StopInfo.h"
31 #include "lldb/Target/Target.h"
32 #include "lldb/Target/Thread.h"
33 
34 using namespace lldb;
35 using namespace lldb_private;
36 
37 //-------------------------------------------------------------------------
38 // CommandObjectProcessLaunch
39 //-------------------------------------------------------------------------
40 #pragma mark CommandObjectProcessLaunch
41 class CommandObjectProcessLaunch : public CommandObjectParsed
42 {
43 public:
44 
45     CommandObjectProcessLaunch (CommandInterpreter &interpreter) :
46         CommandObjectParsed (interpreter,
47                              "process launch",
48                              "Launch the executable in the debugger.",
49                              NULL),
50         m_options (interpreter)
51     {
52         CommandArgumentEntry arg;
53         CommandArgumentData run_args_arg;
54 
55         // Define the first (and only) variant of this arg.
56         run_args_arg.arg_type = eArgTypeRunArgs;
57         run_args_arg.arg_repetition = eArgRepeatOptional;
58 
59         // There is only one variant this argument could be; put it into the argument entry.
60         arg.push_back (run_args_arg);
61 
62         // Push the data for the first argument into the m_arguments vector.
63         m_arguments.push_back (arg);
64     }
65 
66 
67     ~CommandObjectProcessLaunch ()
68     {
69     }
70 
71     int
72     HandleArgumentCompletion (Args &input,
73                               int &cursor_index,
74                               int &cursor_char_position,
75                               OptionElementVector &opt_element_vector,
76                               int match_start_point,
77                               int max_return_elements,
78                               bool &word_complete,
79                               StringList &matches)
80     {
81         std::string completion_str (input.GetArgumentAtIndex(cursor_index));
82         completion_str.erase (cursor_char_position);
83 
84         CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter,
85                                                              CommandCompletions::eDiskFileCompletion,
86                                                              completion_str.c_str(),
87                                                              match_start_point,
88                                                              max_return_elements,
89                                                              NULL,
90                                                              word_complete,
91                                                              matches);
92         return matches.GetSize();
93     }
94 
95     Options *
96     GetOptions ()
97     {
98         return &m_options;
99     }
100 
101     virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
102     {
103         // No repeat for "process launch"...
104         return "";
105     }
106 
107 protected:
108     bool
109     DoExecute (Args& launch_args, CommandReturnObject &result)
110     {
111         Debugger &debugger = m_interpreter.GetDebugger();
112         Target *target = debugger.GetSelectedTarget().get();
113         Error error;
114 
115         if (target == NULL)
116         {
117             result.AppendError ("invalid target, create a debug target using the 'target create' command");
118             result.SetStatus (eReturnStatusFailed);
119             return false;
120         }
121         // If our listener is NULL, users aren't allows to launch
122         char filename[PATH_MAX];
123         const Module *exe_module = target->GetExecutableModulePointer();
124 
125         if (exe_module == NULL)
126         {
127             result.AppendError ("no file in target, create a debug target using the 'target create' command");
128             result.SetStatus (eReturnStatusFailed);
129             return false;
130         }
131 
132         StateType state = eStateInvalid;
133         Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
134         if (process)
135         {
136             state = process->GetState();
137 
138             if (process->IsAlive() && state != eStateConnected)
139             {
140                 char message[1024];
141                 if (process->GetState() == eStateAttaching)
142                     ::strncpy (message, "There is a pending attach, abort it and launch a new process?", sizeof(message));
143                 else
144                     ::strncpy (message, "There is a running process, kill it and restart?", sizeof(message));
145 
146                 if (!m_interpreter.Confirm (message, true))
147                 {
148                     result.SetStatus (eReturnStatusFailed);
149                     return false;
150                 }
151                 else
152                 {
153                     Error destroy_error (process->Destroy());
154                     if (destroy_error.Success())
155                     {
156                         result.SetStatus (eReturnStatusSuccessFinishResult);
157                     }
158                     else
159                     {
160                         result.AppendErrorWithFormat ("Failed to kill process: %s\n", destroy_error.AsCString());
161                         result.SetStatus (eReturnStatusFailed);
162                     }
163                 }
164             }
165         }
166 
167         const char *target_settings_argv0 = target->GetArg0();
168 
169         exe_module->GetFileSpec().GetPath (filename, sizeof(filename));
170 
171         if (target_settings_argv0)
172         {
173             m_options.launch_info.GetArguments().AppendArgument (target_settings_argv0);
174             m_options.launch_info.SetExecutableFile(exe_module->GetPlatformFileSpec(), false);
175         }
176         else
177         {
178             m_options.launch_info.SetExecutableFile(exe_module->GetPlatformFileSpec(), true);
179         }
180 
181         if (launch_args.GetArgumentCount() == 0)
182         {
183             Args target_setting_args;
184             if (target->GetRunArguments(target_setting_args))
185                 m_options.launch_info.GetArguments().AppendArguments (target_setting_args);
186         }
187         else
188         {
189             m_options.launch_info.GetArguments().AppendArguments (launch_args);
190 
191             // Save the arguments for subsequent runs in the current target.
192             target->SetRunArguments (launch_args);
193         }
194 
195         if (target->GetDisableASLR())
196             m_options.launch_info.GetFlags().Set (eLaunchFlagDisableASLR);
197 
198         if (target->GetDisableSTDIO())
199             m_options.launch_info.GetFlags().Set (eLaunchFlagDisableSTDIO);
200 
201         m_options.launch_info.GetFlags().Set (eLaunchFlagDebug);
202 
203         Args environment;
204         target->GetEnvironmentAsArgs (environment);
205         if (environment.GetArgumentCount() > 0)
206             m_options.launch_info.GetEnvironmentEntries ().AppendArguments (environment);
207 
208         // Finalize the file actions, and if none were given, default to opening
209         // up a pseudo terminal
210         const bool default_to_use_pty = true;
211         m_options.launch_info.FinalizeFileActions (target, default_to_use_pty);
212 
213         if (state == eStateConnected)
214         {
215             if (m_options.launch_info.GetFlags().Test (eLaunchFlagLaunchInTTY))
216             {
217                 result.AppendWarning("can't launch in tty when launching through a remote connection");
218                 m_options.launch_info.GetFlags().Clear (eLaunchFlagLaunchInTTY);
219             }
220         }
221         else
222         {
223             if (!m_options.launch_info.GetArchitecture().IsValid())
224                 m_options.launch_info.GetArchitecture() = target->GetArchitecture();
225 
226             PlatformSP platform_sp (target->GetPlatform());
227 
228             if (platform_sp && platform_sp->CanDebugProcess ())
229             {
230                 process = target->GetPlatform()->DebugProcess (m_options.launch_info,
231                                                                debugger,
232                                                                target,
233                                                                debugger.GetListener(),
234                                                                error).get();
235             }
236             else
237             {
238                 const char *plugin_name = m_options.launch_info.GetProcessPluginName();
239                 process = target->CreateProcess (debugger.GetListener(), plugin_name, NULL).get();
240                 if (process)
241                     error = process->Launch (m_options.launch_info);
242             }
243 
244             if (process == NULL)
245             {
246                 result.SetError (error, "failed to launch or debug process");
247                 return false;
248             }
249         }
250 
251         if (error.Success())
252         {
253             const char *archname = exe_module->GetArchitecture().GetArchitectureName();
254 
255             result.AppendMessageWithFormat ("Process %" PRIu64 " launched: '%s' (%s)\n", process->GetID(), filename, archname);
256             result.SetDidChangeProcessState (true);
257             if (m_options.launch_info.GetFlags().Test(eLaunchFlagStopAtEntry) == false)
258             {
259                 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
260                 StateType state = process->WaitForProcessToStop (NULL);
261 
262                 if (state == eStateStopped)
263                 {
264                     error = process->Resume();
265                     if (error.Success())
266                     {
267                         bool synchronous_execution = m_interpreter.GetSynchronous ();
268                         if (synchronous_execution)
269                         {
270                             state = process->WaitForProcessToStop (NULL);
271                             const bool must_be_alive = true;
272                             if (!StateIsStoppedState(state, must_be_alive))
273                             {
274                                 result.AppendErrorWithFormat ("process isn't stopped: %s", StateAsCString(state));
275                             }
276                             result.SetDidChangeProcessState (true);
277                             result.SetStatus (eReturnStatusSuccessFinishResult);
278                         }
279                         else
280                         {
281                             result.SetStatus (eReturnStatusSuccessContinuingNoResult);
282                         }
283                     }
284                     else
285                     {
286                         result.AppendErrorWithFormat ("process resume at entry point failed: %s", error.AsCString());
287                         result.SetStatus (eReturnStatusFailed);
288                     }
289                 }
290                 else
291                 {
292                     result.AppendErrorWithFormat ("initial process state wasn't stopped: %s", StateAsCString(state));
293                     result.SetStatus (eReturnStatusFailed);
294                 }
295             }
296         }
297         else
298         {
299             result.AppendErrorWithFormat ("process launch failed: %s", error.AsCString());
300             result.SetStatus (eReturnStatusFailed);
301         }
302 
303         return result.Succeeded();
304     }
305 
306 protected:
307     ProcessLaunchCommandOptions m_options;
308 };
309 
310 
311 //#define SET1 LLDB_OPT_SET_1
312 //#define SET2 LLDB_OPT_SET_2
313 //#define SET3 LLDB_OPT_SET_3
314 //
315 //OptionDefinition
316 //CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
317 //{
318 //{ 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."},
319 //{ SET1              , false, "stdin",         'i', required_argument, NULL, 0, eArgTypeDirectoryName,    "Redirect stdin for the process to <path>."},
320 //{ SET1              , false, "stdout",        'o', required_argument, NULL, 0, eArgTypeDirectoryName,    "Redirect stdout for the process to <path>."},
321 //{ SET1              , false, "stderr",        'e', required_argument, NULL, 0, eArgTypeDirectoryName,    "Redirect stderr for the process to <path>."},
322 //{ SET1 | SET2 | SET3, false, "plugin",        'p', required_argument, NULL, 0, eArgTypePlugin,  "Name of the process plugin you want to use."},
323 //{        SET2       , false, "tty",           't', optional_argument, NULL, 0, eArgTypeDirectoryName,    "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."},
324 //{               SET3, false, "no-stdio",      'n', no_argument,       NULL, 0, eArgTypeNone,    "Do not set up for terminal I/O to go to running process."},
325 //{ SET1 | SET2 | SET3, false, "working-dir",   'w', required_argument, NULL, 0, eArgTypeDirectoryName,    "Set the current working directory to <path> when running the inferior."},
326 //{ 0,                  false, NULL,             0,  0,                 NULL, 0, eArgTypeNone,    NULL }
327 //};
328 //
329 //#undef SET1
330 //#undef SET2
331 //#undef SET3
332 
333 //-------------------------------------------------------------------------
334 // CommandObjectProcessAttach
335 //-------------------------------------------------------------------------
336 #pragma mark CommandObjectProcessAttach
337 class CommandObjectProcessAttach : public CommandObjectParsed
338 {
339 public:
340 
341     class CommandOptions : public Options
342     {
343     public:
344 
345         CommandOptions (CommandInterpreter &interpreter) :
346             Options(interpreter)
347         {
348             // Keep default values of all options in one place: OptionParsingStarting ()
349             OptionParsingStarting ();
350         }
351 
352         ~CommandOptions ()
353         {
354         }
355 
356         Error
357         SetOptionValue (uint32_t option_idx, const char *option_arg)
358         {
359             Error error;
360             const int short_option = m_getopt_table[option_idx].val;
361             bool success = false;
362             switch (short_option)
363             {
364                 case 'c':
365                     attach_info.SetContinueOnceAttached(true);
366                     break;
367 
368                 case 'p':
369                     {
370                         lldb::pid_t pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success);
371                         if (!success || pid == LLDB_INVALID_PROCESS_ID)
372                         {
373                             error.SetErrorStringWithFormat("invalid process ID '%s'", option_arg);
374                         }
375                         else
376                         {
377                             attach_info.SetProcessID (pid);
378                         }
379                     }
380                     break;
381 
382                 case 'P':
383                     attach_info.SetProcessPluginName (option_arg);
384                     break;
385 
386                 case 'n':
387                     attach_info.GetExecutableFile().SetFile(option_arg, false);
388                     break;
389 
390                 case 'w':
391                     attach_info.SetWaitForLaunch(true);
392                     break;
393 
394                 case 'i':
395                     attach_info.SetIgnoreExisting(false);
396                     break;
397 
398                 default:
399                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
400                     break;
401             }
402             return error;
403         }
404 
405         void
406         OptionParsingStarting ()
407         {
408             attach_info.Clear();
409         }
410 
411         const OptionDefinition*
412         GetDefinitions ()
413         {
414             return g_option_table;
415         }
416 
417         virtual bool
418         HandleOptionArgumentCompletion (Args &input,
419                                         int cursor_index,
420                                         int char_pos,
421                                         OptionElementVector &opt_element_vector,
422                                         int opt_element_index,
423                                         int match_start_point,
424                                         int max_return_elements,
425                                         bool &word_complete,
426                                         StringList &matches)
427         {
428             int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
429             int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
430 
431             // We are only completing the name option for now...
432 
433             const OptionDefinition *opt_defs = GetDefinitions();
434             if (opt_defs[opt_defs_index].short_option == 'n')
435             {
436                 // Are we in the name?
437 
438                 // Look to see if there is a -P argument provided, and if so use that plugin, otherwise
439                 // use the default plugin.
440 
441                 const char *partial_name = NULL;
442                 partial_name = input.GetArgumentAtIndex(opt_arg_pos);
443 
444                 PlatformSP platform_sp (m_interpreter.GetPlatform (true));
445                 if (platform_sp)
446                 {
447                     ProcessInstanceInfoList process_infos;
448                     ProcessInstanceInfoMatch match_info;
449                     if (partial_name)
450                     {
451                         match_info.GetProcessInfo().GetExecutableFile().SetFile(partial_name, false);
452                         match_info.SetNameMatchType(eNameMatchStartsWith);
453                     }
454                     platform_sp->FindProcesses (match_info, process_infos);
455                     const uint32_t num_matches = process_infos.GetSize();
456                     if (num_matches > 0)
457                     {
458                         for (uint32_t i=0; i<num_matches; ++i)
459                         {
460                             matches.AppendString (process_infos.GetProcessNameAtIndex(i),
461                                                   process_infos.GetProcessNameLengthAtIndex(i));
462                         }
463                     }
464                 }
465             }
466 
467             return false;
468         }
469 
470         // Options table: Required for subclasses of Options.
471 
472         static OptionDefinition g_option_table[];
473 
474         // Instance variables to hold the values for command options.
475 
476         ProcessAttachInfo attach_info;
477     };
478 
479     CommandObjectProcessAttach (CommandInterpreter &interpreter) :
480         CommandObjectParsed (interpreter,
481                              "process attach",
482                              "Attach to a process.",
483                              "process attach <cmd-options>"),
484         m_options (interpreter)
485     {
486     }
487 
488     ~CommandObjectProcessAttach ()
489     {
490     }
491 
492     Options *
493     GetOptions ()
494     {
495         return &m_options;
496     }
497 
498 protected:
499     bool
500     DoExecute (Args& command,
501              CommandReturnObject &result)
502     {
503         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
504         // N.B. The attach should be synchronous.  It doesn't help much to get the prompt back between initiating the attach
505         // and the target actually stopping.  So even if the interpreter is set to be asynchronous, we wait for the stop
506         // ourselves here.
507 
508         Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
509         StateType state = eStateInvalid;
510         if (process)
511         {
512             state = process->GetState();
513             if (process->IsAlive() && state != eStateConnected)
514             {
515                 result.AppendErrorWithFormat ("Process %" PRIu64 " is currently being debugged, kill the process before attaching.\n",
516                                               process->GetID());
517                 result.SetStatus (eReturnStatusFailed);
518                 return false;
519             }
520         }
521 
522         if (target == NULL)
523         {
524             // If there isn't a current target create one.
525             TargetSP new_target_sp;
526             Error error;
527 
528             error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(),
529                                                                               NULL,
530                                                                               NULL,
531                                                                               false,
532                                                                               NULL, // No platform options
533                                                                               new_target_sp);
534             target = new_target_sp.get();
535             if (target == NULL || error.Fail())
536             {
537                 result.AppendError(error.AsCString("Error creating target"));
538                 return false;
539             }
540             m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target);
541         }
542 
543         // Record the old executable module, we want to issue a warning if the process of attaching changed the
544         // current executable (like somebody said "file foo" then attached to a PID whose executable was bar.)
545 
546         ModuleSP old_exec_module_sp = target->GetExecutableModule();
547         ArchSpec old_arch_spec = target->GetArchitecture();
548 
549         if (command.GetArgumentCount())
550         {
551             result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: %s\n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
552             result.SetStatus (eReturnStatusFailed);
553         }
554         else
555         {
556             if (state != eStateConnected)
557             {
558                 const char *plugin_name = m_options.attach_info.GetProcessPluginName();
559                 process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name, NULL).get();
560             }
561 
562             if (process)
563             {
564                 Error error;
565                 // If no process info was specified, then use the target executable
566                 // name as the process to attach to by default
567                 if (!m_options.attach_info.ProcessInfoSpecified ())
568                 {
569                     if (old_exec_module_sp)
570                         m_options.attach_info.GetExecutableFile().GetFilename() = old_exec_module_sp->GetPlatformFileSpec().GetFilename();
571 
572                     if (!m_options.attach_info.ProcessInfoSpecified ())
573                     {
574                         error.SetErrorString ("no process specified, create a target with a file, or specify the --pid or --name command option");
575                     }
576                 }
577 
578                 if (error.Success())
579                 {
580                     error = process->Attach (m_options.attach_info);
581 
582                     if (error.Success())
583                     {
584                         result.SetStatus (eReturnStatusSuccessContinuingNoResult);
585                     }
586                     else
587                     {
588                         result.AppendErrorWithFormat ("attach failed: %s\n", error.AsCString());
589                         result.SetStatus (eReturnStatusFailed);
590                         return false;
591                     }
592                     // If we're synchronous, wait for the stopped event and report that.
593                     // Otherwise just return.
594                     // FIXME: in the async case it will now be possible to get to the command
595                     // interpreter with a state eStateAttaching.  Make sure we handle that correctly.
596                     StateType state = process->WaitForProcessToStop (NULL);
597 
598                     result.SetDidChangeProcessState (true);
599 
600                     if (state == eStateStopped)
601                     {
602                         result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state));
603                         result.SetStatus (eReturnStatusSuccessFinishNoResult);
604                     }
605                     else
606                     {
607                         result.AppendError ("attach failed: process did not stop (no such process or permission problem?)");
608                         process->Destroy();
609                         result.SetStatus (eReturnStatusFailed);
610                         return false;
611                     }
612                 }
613             }
614         }
615 
616         if (result.Succeeded())
617         {
618             // Okay, we're done.  Last step is to warn if the executable module has changed:
619             char new_path[PATH_MAX];
620             ModuleSP new_exec_module_sp (target->GetExecutableModule());
621             if (!old_exec_module_sp)
622             {
623                 // We might not have a module if we attached to a raw pid...
624                 if (new_exec_module_sp)
625                 {
626                     new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX);
627                     result.AppendMessageWithFormat("Executable module set to \"%s\".\n", new_path);
628                 }
629             }
630             else if (old_exec_module_sp->GetFileSpec() != new_exec_module_sp->GetFileSpec())
631             {
632                 char old_path[PATH_MAX];
633 
634                 old_exec_module_sp->GetFileSpec().GetPath (old_path, PATH_MAX);
635                 new_exec_module_sp->GetFileSpec().GetPath (new_path, PATH_MAX);
636 
637                 result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n",
638                                                     old_path, new_path);
639             }
640 
641             if (!old_arch_spec.IsValid())
642             {
643                 result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().GetTriple().getTriple().c_str());
644             }
645             else if (!old_arch_spec.IsExactMatch(target->GetArchitecture()))
646             {
647                 result.AppendWarningWithFormat("Architecture changed from %s to %s.\n",
648                                                old_arch_spec.GetTriple().getTriple().c_str(),
649                                                target->GetArchitecture().GetTriple().getTriple().c_str());
650             }
651 
652             // This supports the use-case scenario of immediately continuing the process once attached.
653             if (m_options.attach_info.GetContinueOnceAttached())
654                 m_interpreter.HandleCommand("process continue", eLazyBoolNo, result);
655         }
656         return result.Succeeded();
657     }
658 
659     CommandOptions m_options;
660 };
661 
662 
663 OptionDefinition
664 CommandObjectProcessAttach::CommandOptions::g_option_table[] =
665 {
666 { LLDB_OPT_SET_ALL, false, "continue",'c', no_argument,         NULL, 0, eArgTypeNone,         "Immediately continue the process once attached."},
667 { LLDB_OPT_SET_ALL, false, "plugin",  'P', required_argument,   NULL, 0, eArgTypePlugin,       "Name of the process plugin you want to use."},
668 { LLDB_OPT_SET_1,   false, "pid",     'p', required_argument,   NULL, 0, eArgTypePid,          "The process ID of an existing process to attach to."},
669 { LLDB_OPT_SET_2,   false, "name",    'n', required_argument,   NULL, 0, eArgTypeProcessName,  "The name of the process to attach to."},
670 { LLDB_OPT_SET_2,   false, "include-existing", 'i', no_argument, NULL, 0, eArgTypeNone,         "Include existing processes when doing attach -w."},
671 { LLDB_OPT_SET_2,   false, "waitfor", 'w', no_argument,         NULL, 0, eArgTypeNone,         "Wait for the process with <process-name> to launch."},
672 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
673 };
674 
675 //-------------------------------------------------------------------------
676 // CommandObjectProcessContinue
677 //-------------------------------------------------------------------------
678 #pragma mark CommandObjectProcessContinue
679 
680 class CommandObjectProcessContinue : public CommandObjectParsed
681 {
682 public:
683 
684     CommandObjectProcessContinue (CommandInterpreter &interpreter) :
685         CommandObjectParsed (interpreter,
686                              "process continue",
687                              "Continue execution of all threads in the current process.",
688                              "process continue",
689                              eFlagProcessMustBeLaunched | eFlagProcessMustBePaused),
690         m_options(interpreter)
691     {
692     }
693 
694 
695     ~CommandObjectProcessContinue ()
696     {
697     }
698 
699 protected:
700 
701     class CommandOptions : public Options
702     {
703     public:
704 
705         CommandOptions (CommandInterpreter &interpreter) :
706             Options(interpreter)
707         {
708             // Keep default values of all options in one place: OptionParsingStarting ()
709             OptionParsingStarting ();
710         }
711 
712         ~CommandOptions ()
713         {
714         }
715 
716         Error
717         SetOptionValue (uint32_t option_idx, const char *option_arg)
718         {
719             Error error;
720             const int short_option = m_getopt_table[option_idx].val;
721             bool success = false;
722             switch (short_option)
723             {
724                 case 'i':
725                     m_ignore = Args::StringToUInt32 (option_arg, 0, 0, &success);
726                     if (!success)
727                         error.SetErrorStringWithFormat ("invalid value for ignore option: \"%s\", should be a number.", option_arg);
728                     break;
729 
730                 default:
731                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
732                     break;
733             }
734             return error;
735         }
736 
737         void
738         OptionParsingStarting ()
739         {
740             m_ignore = 0;
741         }
742 
743         const OptionDefinition*
744         GetDefinitions ()
745         {
746             return g_option_table;
747         }
748 
749         // Options table: Required for subclasses of Options.
750 
751         static OptionDefinition g_option_table[];
752 
753         uint32_t m_ignore;
754     };
755 
756     bool
757     DoExecute (Args& command,
758              CommandReturnObject &result)
759     {
760         Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
761         bool synchronous_execution = m_interpreter.GetSynchronous ();
762 
763         if (process == NULL)
764         {
765             result.AppendError ("no process to continue");
766             result.SetStatus (eReturnStatusFailed);
767             return false;
768          }
769 
770         StateType state = process->GetState();
771         if (state == eStateStopped)
772         {
773             if (command.GetArgumentCount() != 0)
774             {
775                 result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str());
776                 result.SetStatus (eReturnStatusFailed);
777                 return false;
778             }
779 
780             if (m_options.m_ignore > 0)
781             {
782                 ThreadSP sel_thread_sp(process->GetThreadList().GetSelectedThread());
783                 if (sel_thread_sp)
784                 {
785                     StopInfoSP stop_info_sp = sel_thread_sp->GetStopInfo();
786                     if (stop_info_sp && stop_info_sp->GetStopReason() == eStopReasonBreakpoint)
787                     {
788                         uint64_t bp_site_id = stop_info_sp->GetValue();
789                         BreakpointSiteSP bp_site_sp(process->GetBreakpointSiteList().FindByID(bp_site_id));
790                         if (bp_site_sp)
791                         {
792                             uint32_t num_owners = bp_site_sp->GetNumberOfOwners();
793                             for (uint32_t i = 0; i < num_owners; i++)
794                             {
795                                 Breakpoint &bp_ref = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint();
796                                 if (!bp_ref.IsInternal())
797                                 {
798                                     bp_ref.SetIgnoreCount(m_options.m_ignore);
799                                 }
800                             }
801                         }
802                     }
803                 }
804             }
805 
806             {  // Scope for thread list mutex:
807                 Mutex::Locker locker (process->GetThreadList().GetMutex());
808                 const uint32_t num_threads = process->GetThreadList().GetSize();
809 
810                 // Set the actions that the threads should each take when resuming
811                 for (uint32_t idx=0; idx<num_threads; ++idx)
812                 {
813                     process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning);
814                 }
815             }
816 
817             Error error(process->Resume());
818             if (error.Success())
819             {
820                 result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID());
821                 if (synchronous_execution)
822                 {
823                     state = process->WaitForProcessToStop (NULL);
824 
825                     result.SetDidChangeProcessState (true);
826                     result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state));
827                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
828                 }
829                 else
830                 {
831                     result.SetStatus (eReturnStatusSuccessContinuingNoResult);
832                 }
833             }
834             else
835             {
836                 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
837                 result.SetStatus (eReturnStatusFailed);
838             }
839         }
840         else
841         {
842             result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
843                                          StateAsCString(state));
844             result.SetStatus (eReturnStatusFailed);
845         }
846         return result.Succeeded();
847     }
848 
849     Options *
850     GetOptions ()
851     {
852         return &m_options;
853     }
854 
855     CommandOptions m_options;
856 
857 };
858 
859 OptionDefinition
860 CommandObjectProcessContinue::CommandOptions::g_option_table[] =
861 {
862 { LLDB_OPT_SET_ALL, false, "ignore-count",'i', required_argument,         NULL, 0, eArgTypeUnsignedInteger,
863                            "Ignore <N> crossings of the breakpoint (if it exists) for the currently selected thread."},
864 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
865 };
866 
867 //-------------------------------------------------------------------------
868 // CommandObjectProcessDetach
869 //-------------------------------------------------------------------------
870 #pragma mark CommandObjectProcessDetach
871 
872 class CommandObjectProcessDetach : public CommandObjectParsed
873 {
874 public:
875 
876     CommandObjectProcessDetach (CommandInterpreter &interpreter) :
877         CommandObjectParsed (interpreter,
878                              "process detach",
879                              "Detach from the current process being debugged.",
880                              "process detach",
881                              eFlagProcessMustBeLaunched)
882     {
883     }
884 
885     ~CommandObjectProcessDetach ()
886     {
887     }
888 
889 protected:
890     bool
891     DoExecute (Args& command,
892              CommandReturnObject &result)
893     {
894         Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
895         if (process == NULL)
896         {
897             result.AppendError ("must have a valid process in order to detach");
898             result.SetStatus (eReturnStatusFailed);
899             return false;
900         }
901 
902         result.AppendMessageWithFormat ("Detaching from process %" PRIu64 "\n", process->GetID());
903         Error error (process->Detach());
904         if (error.Success())
905         {
906             result.SetStatus (eReturnStatusSuccessFinishResult);
907         }
908         else
909         {
910             result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString());
911             result.SetStatus (eReturnStatusFailed);
912             return false;
913         }
914         return result.Succeeded();
915     }
916 };
917 
918 //-------------------------------------------------------------------------
919 // CommandObjectProcessConnect
920 //-------------------------------------------------------------------------
921 #pragma mark CommandObjectProcessConnect
922 
923 class CommandObjectProcessConnect : public CommandObjectParsed
924 {
925 public:
926 
927     class CommandOptions : public Options
928     {
929     public:
930 
931         CommandOptions (CommandInterpreter &interpreter) :
932             Options(interpreter)
933         {
934             // Keep default values of all options in one place: OptionParsingStarting ()
935             OptionParsingStarting ();
936         }
937 
938         ~CommandOptions ()
939         {
940         }
941 
942         Error
943         SetOptionValue (uint32_t option_idx, const char *option_arg)
944         {
945             Error error;
946             const int short_option = m_getopt_table[option_idx].val;
947 
948             switch (short_option)
949             {
950             case 'p':
951                 plugin_name.assign (option_arg);
952                 break;
953 
954             default:
955                 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
956                 break;
957             }
958             return error;
959         }
960 
961         void
962         OptionParsingStarting ()
963         {
964             plugin_name.clear();
965         }
966 
967         const OptionDefinition*
968         GetDefinitions ()
969         {
970             return g_option_table;
971         }
972 
973         // Options table: Required for subclasses of Options.
974 
975         static OptionDefinition g_option_table[];
976 
977         // Instance variables to hold the values for command options.
978 
979         std::string plugin_name;
980     };
981 
982     CommandObjectProcessConnect (CommandInterpreter &interpreter) :
983         CommandObjectParsed (interpreter,
984                              "process connect",
985                              "Connect to a remote debug service.",
986                              "process connect <remote-url>",
987                              0),
988         m_options (interpreter)
989     {
990     }
991 
992     ~CommandObjectProcessConnect ()
993     {
994     }
995 
996 
997     Options *
998     GetOptions ()
999     {
1000         return &m_options;
1001     }
1002 
1003 protected:
1004     bool
1005     DoExecute (Args& command,
1006              CommandReturnObject &result)
1007     {
1008 
1009         TargetSP target_sp (m_interpreter.GetDebugger().GetSelectedTarget());
1010         Error error;
1011         Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
1012         if (process)
1013         {
1014             if (process->IsAlive())
1015             {
1016                 result.AppendErrorWithFormat ("Process %" PRIu64 " is currently being debugged, kill the process before connecting.\n",
1017                                               process->GetID());
1018                 result.SetStatus (eReturnStatusFailed);
1019                 return false;
1020             }
1021         }
1022 
1023         if (!target_sp)
1024         {
1025             // If there isn't a current target create one.
1026 
1027             error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(),
1028                                                                               NULL,
1029                                                                               NULL,
1030                                                                               false,
1031                                                                               NULL, // No platform options
1032                                                                               target_sp);
1033             if (!target_sp || error.Fail())
1034             {
1035                 result.AppendError(error.AsCString("Error creating target"));
1036                 result.SetStatus (eReturnStatusFailed);
1037                 return false;
1038             }
1039             m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target_sp.get());
1040         }
1041 
1042         if (command.GetArgumentCount() == 1)
1043         {
1044             const char *plugin_name = NULL;
1045             if (!m_options.plugin_name.empty())
1046                 plugin_name = m_options.plugin_name.c_str();
1047 
1048             const char *remote_url = command.GetArgumentAtIndex(0);
1049             process = target_sp->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name, NULL).get();
1050 
1051             if (process)
1052             {
1053                 error = process->ConnectRemote (&process->GetTarget().GetDebugger().GetOutputStream(), remote_url);
1054 
1055                 if (error.Fail())
1056                 {
1057                     result.AppendError(error.AsCString("Remote connect failed"));
1058                     result.SetStatus (eReturnStatusFailed);
1059                     target_sp->DeleteCurrentProcess();
1060                     return false;
1061                 }
1062             }
1063             else
1064             {
1065                 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",
1066                                               m_cmd_name.c_str());
1067                 result.SetStatus (eReturnStatusFailed);
1068             }
1069         }
1070         else
1071         {
1072             result.AppendErrorWithFormat ("'%s' takes exactly one argument:\nUsage: %s\n",
1073                                           m_cmd_name.c_str(),
1074                                           m_cmd_syntax.c_str());
1075             result.SetStatus (eReturnStatusFailed);
1076         }
1077         return result.Succeeded();
1078     }
1079 
1080     CommandOptions m_options;
1081 };
1082 
1083 OptionDefinition
1084 CommandObjectProcessConnect::CommandOptions::g_option_table[] =
1085 {
1086     { LLDB_OPT_SET_ALL, false, "plugin", 'p', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
1087     { 0,                false, NULL,      0 , 0,                 NULL, 0, eArgTypeNone,   NULL }
1088 };
1089 
1090 //-------------------------------------------------------------------------
1091 // CommandObjectProcessPlugin
1092 //-------------------------------------------------------------------------
1093 #pragma mark CommandObjectProcessPlugin
1094 
1095 class CommandObjectProcessPlugin : public CommandObjectProxy
1096 {
1097 public:
1098 
1099     CommandObjectProcessPlugin (CommandInterpreter &interpreter) :
1100         CommandObjectProxy (interpreter,
1101                             "process plugin",
1102                             "Send a custom command to the current process plug-in.",
1103                             "process plugin <args>",
1104                             0)
1105     {
1106     }
1107 
1108     ~CommandObjectProcessPlugin ()
1109     {
1110     }
1111 
1112     virtual CommandObject *
1113     GetProxyCommandObject()
1114     {
1115         Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
1116         if (process)
1117             return process->GetPluginCommandObject();
1118         return NULL;
1119     }
1120 };
1121 
1122 
1123 //-------------------------------------------------------------------------
1124 // CommandObjectProcessLoad
1125 //-------------------------------------------------------------------------
1126 #pragma mark CommandObjectProcessLoad
1127 
1128 class CommandObjectProcessLoad : public CommandObjectParsed
1129 {
1130 public:
1131 
1132     CommandObjectProcessLoad (CommandInterpreter &interpreter) :
1133         CommandObjectParsed (interpreter,
1134                              "process load",
1135                              "Load a shared library into the current process.",
1136                              "process load <filename> [<filename> ...]",
1137                              eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
1138     {
1139     }
1140 
1141     ~CommandObjectProcessLoad ()
1142     {
1143     }
1144 
1145 protected:
1146     bool
1147     DoExecute (Args& command,
1148              CommandReturnObject &result)
1149     {
1150         Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
1151         if (process == NULL)
1152         {
1153             result.AppendError ("must have a valid process in order to load a shared library");
1154             result.SetStatus (eReturnStatusFailed);
1155             return false;
1156         }
1157 
1158         const uint32_t argc = command.GetArgumentCount();
1159 
1160         for (uint32_t i=0; i<argc; ++i)
1161         {
1162             Error error;
1163             const char *image_path = command.GetArgumentAtIndex(i);
1164             FileSpec image_spec (image_path, false);
1165             process->GetTarget().GetPlatform()->ResolveRemotePath(image_spec, image_spec);
1166             uint32_t image_token = process->LoadImage(image_spec, error);
1167             if (image_token != LLDB_INVALID_IMAGE_TOKEN)
1168             {
1169                 result.AppendMessageWithFormat ("Loading \"%s\"...ok\nImage %u loaded.\n", image_path, image_token);
1170                 result.SetStatus (eReturnStatusSuccessFinishResult);
1171             }
1172             else
1173             {
1174                 result.AppendErrorWithFormat ("failed to load '%s': %s", image_path, error.AsCString());
1175                 result.SetStatus (eReturnStatusFailed);
1176             }
1177         }
1178         return result.Succeeded();
1179     }
1180 };
1181 
1182 
1183 //-------------------------------------------------------------------------
1184 // CommandObjectProcessUnload
1185 //-------------------------------------------------------------------------
1186 #pragma mark CommandObjectProcessUnload
1187 
1188 class CommandObjectProcessUnload : public CommandObjectParsed
1189 {
1190 public:
1191 
1192     CommandObjectProcessUnload (CommandInterpreter &interpreter) :
1193         CommandObjectParsed (interpreter,
1194                              "process unload",
1195                              "Unload a shared library from the current process using the index returned by a previous call to \"process load\".",
1196                              "process unload <index>",
1197                              eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
1198     {
1199     }
1200 
1201     ~CommandObjectProcessUnload ()
1202     {
1203     }
1204 
1205 protected:
1206     bool
1207     DoExecute (Args& command,
1208              CommandReturnObject &result)
1209     {
1210         Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
1211         if (process == NULL)
1212         {
1213             result.AppendError ("must have a valid process in order to load a shared library");
1214             result.SetStatus (eReturnStatusFailed);
1215             return false;
1216         }
1217 
1218         const uint32_t argc = command.GetArgumentCount();
1219 
1220         for (uint32_t i=0; i<argc; ++i)
1221         {
1222             const char *image_token_cstr = command.GetArgumentAtIndex(i);
1223             uint32_t image_token = Args::StringToUInt32(image_token_cstr, LLDB_INVALID_IMAGE_TOKEN, 0);
1224             if (image_token == LLDB_INVALID_IMAGE_TOKEN)
1225             {
1226                 result.AppendErrorWithFormat ("invalid image index argument '%s'", image_token_cstr);
1227                 result.SetStatus (eReturnStatusFailed);
1228                 break;
1229             }
1230             else
1231             {
1232                 Error error (process->UnloadImage(image_token));
1233                 if (error.Success())
1234                 {
1235                     result.AppendMessageWithFormat ("Unloading shared library with index %u...ok\n", image_token);
1236                     result.SetStatus (eReturnStatusSuccessFinishResult);
1237                 }
1238                 else
1239                 {
1240                     result.AppendErrorWithFormat ("failed to unload image: %s", error.AsCString());
1241                     result.SetStatus (eReturnStatusFailed);
1242                     break;
1243                 }
1244             }
1245         }
1246         return result.Succeeded();
1247     }
1248 };
1249 
1250 //-------------------------------------------------------------------------
1251 // CommandObjectProcessSignal
1252 //-------------------------------------------------------------------------
1253 #pragma mark CommandObjectProcessSignal
1254 
1255 class CommandObjectProcessSignal : public CommandObjectParsed
1256 {
1257 public:
1258 
1259     CommandObjectProcessSignal (CommandInterpreter &interpreter) :
1260         CommandObjectParsed (interpreter,
1261                              "process signal",
1262                              "Send a UNIX signal to the current process being debugged.",
1263                              NULL)
1264     {
1265         CommandArgumentEntry arg;
1266         CommandArgumentData signal_arg;
1267 
1268         // Define the first (and only) variant of this arg.
1269         signal_arg.arg_type = eArgTypeUnixSignal;
1270         signal_arg.arg_repetition = eArgRepeatPlain;
1271 
1272         // There is only one variant this argument could be; put it into the argument entry.
1273         arg.push_back (signal_arg);
1274 
1275         // Push the data for the first argument into the m_arguments vector.
1276         m_arguments.push_back (arg);
1277     }
1278 
1279     ~CommandObjectProcessSignal ()
1280     {
1281     }
1282 
1283 protected:
1284     bool
1285     DoExecute (Args& command,
1286              CommandReturnObject &result)
1287     {
1288         Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
1289         if (process == NULL)
1290         {
1291             result.AppendError ("no process to signal");
1292             result.SetStatus (eReturnStatusFailed);
1293             return false;
1294         }
1295 
1296         if (command.GetArgumentCount() == 1)
1297         {
1298             int signo = LLDB_INVALID_SIGNAL_NUMBER;
1299 
1300             const char *signal_name = command.GetArgumentAtIndex(0);
1301             if (::isxdigit (signal_name[0]))
1302                 signo = Args::StringToSInt32(signal_name, LLDB_INVALID_SIGNAL_NUMBER, 0);
1303             else
1304                 signo = process->GetUnixSignals().GetSignalNumberFromName (signal_name);
1305 
1306             if (signo == LLDB_INVALID_SIGNAL_NUMBER)
1307             {
1308                 result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0));
1309                 result.SetStatus (eReturnStatusFailed);
1310             }
1311             else
1312             {
1313                 Error error (process->Signal (signo));
1314                 if (error.Success())
1315                 {
1316                     result.SetStatus (eReturnStatusSuccessFinishResult);
1317                 }
1318                 else
1319                 {
1320                     result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString());
1321                     result.SetStatus (eReturnStatusFailed);
1322                 }
1323             }
1324         }
1325         else
1326         {
1327             result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: %s\n", m_cmd_name.c_str(),
1328                                         m_cmd_syntax.c_str());
1329             result.SetStatus (eReturnStatusFailed);
1330         }
1331         return result.Succeeded();
1332     }
1333 };
1334 
1335 
1336 //-------------------------------------------------------------------------
1337 // CommandObjectProcessInterrupt
1338 //-------------------------------------------------------------------------
1339 #pragma mark CommandObjectProcessInterrupt
1340 
1341 class CommandObjectProcessInterrupt : public CommandObjectParsed
1342 {
1343 public:
1344 
1345 
1346     CommandObjectProcessInterrupt (CommandInterpreter &interpreter) :
1347         CommandObjectParsed (interpreter,
1348                              "process interrupt",
1349                              "Interrupt the current process being debugged.",
1350                              "process interrupt",
1351                              eFlagProcessMustBeLaunched)
1352     {
1353     }
1354 
1355     ~CommandObjectProcessInterrupt ()
1356     {
1357     }
1358 
1359 protected:
1360     bool
1361     DoExecute (Args& command,
1362              CommandReturnObject &result)
1363     {
1364         Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
1365         if (process == NULL)
1366         {
1367             result.AppendError ("no process to halt");
1368             result.SetStatus (eReturnStatusFailed);
1369             return false;
1370         }
1371 
1372         if (command.GetArgumentCount() == 0)
1373         {
1374             Error error(process->Halt ());
1375             if (error.Success())
1376             {
1377                 result.SetStatus (eReturnStatusSuccessFinishResult);
1378 
1379                 // Maybe we should add a "SuspendThreadPlans so we
1380                 // can halt, and keep in place all the current thread plans.
1381                 process->GetThreadList().DiscardThreadPlans();
1382             }
1383             else
1384             {
1385                 result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString());
1386                 result.SetStatus (eReturnStatusFailed);
1387             }
1388         }
1389         else
1390         {
1391             result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n",
1392                                         m_cmd_name.c_str(),
1393                                         m_cmd_syntax.c_str());
1394             result.SetStatus (eReturnStatusFailed);
1395         }
1396         return result.Succeeded();
1397     }
1398 };
1399 
1400 //-------------------------------------------------------------------------
1401 // CommandObjectProcessKill
1402 //-------------------------------------------------------------------------
1403 #pragma mark CommandObjectProcessKill
1404 
1405 class CommandObjectProcessKill : public CommandObjectParsed
1406 {
1407 public:
1408 
1409     CommandObjectProcessKill (CommandInterpreter &interpreter) :
1410         CommandObjectParsed (interpreter,
1411                              "process kill",
1412                              "Terminate the current process being debugged.",
1413                              "process kill",
1414                              eFlagProcessMustBeLaunched)
1415     {
1416     }
1417 
1418     ~CommandObjectProcessKill ()
1419     {
1420     }
1421 
1422 protected:
1423     bool
1424     DoExecute (Args& command,
1425              CommandReturnObject &result)
1426     {
1427         Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
1428         if (process == NULL)
1429         {
1430             result.AppendError ("no process to kill");
1431             result.SetStatus (eReturnStatusFailed);
1432             return false;
1433         }
1434 
1435         if (command.GetArgumentCount() == 0)
1436         {
1437             Error error (process->Destroy());
1438             if (error.Success())
1439             {
1440                 result.SetStatus (eReturnStatusSuccessFinishResult);
1441             }
1442             else
1443             {
1444                 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString());
1445                 result.SetStatus (eReturnStatusFailed);
1446             }
1447         }
1448         else
1449         {
1450             result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n",
1451                                         m_cmd_name.c_str(),
1452                                         m_cmd_syntax.c_str());
1453             result.SetStatus (eReturnStatusFailed);
1454         }
1455         return result.Succeeded();
1456     }
1457 };
1458 
1459 //-------------------------------------------------------------------------
1460 // CommandObjectProcessStatus
1461 //-------------------------------------------------------------------------
1462 #pragma mark CommandObjectProcessStatus
1463 
1464 class CommandObjectProcessStatus : public CommandObjectParsed
1465 {
1466 public:
1467     CommandObjectProcessStatus (CommandInterpreter &interpreter) :
1468         CommandObjectParsed (interpreter,
1469                              "process status",
1470                              "Show the current status and location of executing process.",
1471                              "process status",
1472                              0)
1473     {
1474     }
1475 
1476     ~CommandObjectProcessStatus()
1477     {
1478     }
1479 
1480 
1481     bool
1482     DoExecute (Args& command, CommandReturnObject &result)
1483     {
1484         Stream &strm = result.GetOutputStream();
1485         result.SetStatus (eReturnStatusSuccessFinishNoResult);
1486         ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
1487         Process *process = exe_ctx.GetProcessPtr();
1488         if (process)
1489         {
1490             const bool only_threads_with_stop_reason = true;
1491             const uint32_t start_frame = 0;
1492             const uint32_t num_frames = 1;
1493             const uint32_t num_frames_with_source = 1;
1494             process->GetStatus(strm);
1495             process->GetThreadStatus (strm,
1496                                       only_threads_with_stop_reason,
1497                                       start_frame,
1498                                       num_frames,
1499                                       num_frames_with_source);
1500 
1501         }
1502         else
1503         {
1504             result.AppendError ("No process.");
1505             result.SetStatus (eReturnStatusFailed);
1506         }
1507         return result.Succeeded();
1508     }
1509 };
1510 
1511 //-------------------------------------------------------------------------
1512 // CommandObjectProcessHandle
1513 //-------------------------------------------------------------------------
1514 #pragma mark CommandObjectProcessHandle
1515 
1516 class CommandObjectProcessHandle : public CommandObjectParsed
1517 {
1518 public:
1519 
1520     class CommandOptions : public Options
1521     {
1522     public:
1523 
1524         CommandOptions (CommandInterpreter &interpreter) :
1525             Options (interpreter)
1526         {
1527             OptionParsingStarting ();
1528         }
1529 
1530         ~CommandOptions ()
1531         {
1532         }
1533 
1534         Error
1535         SetOptionValue (uint32_t option_idx, const char *option_arg)
1536         {
1537             Error error;
1538             const int short_option = m_getopt_table[option_idx].val;
1539 
1540             switch (short_option)
1541             {
1542                 case 's':
1543                     stop = option_arg;
1544                     break;
1545                 case 'n':
1546                     notify = option_arg;
1547                     break;
1548                 case 'p':
1549                     pass = option_arg;
1550                     break;
1551                 default:
1552                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
1553                     break;
1554             }
1555             return error;
1556         }
1557 
1558         void
1559         OptionParsingStarting ()
1560         {
1561             stop.clear();
1562             notify.clear();
1563             pass.clear();
1564         }
1565 
1566         const OptionDefinition*
1567         GetDefinitions ()
1568         {
1569             return g_option_table;
1570         }
1571 
1572         // Options table: Required for subclasses of Options.
1573 
1574         static OptionDefinition g_option_table[];
1575 
1576         // Instance variables to hold the values for command options.
1577 
1578         std::string stop;
1579         std::string notify;
1580         std::string pass;
1581     };
1582 
1583 
1584     CommandObjectProcessHandle (CommandInterpreter &interpreter) :
1585         CommandObjectParsed (interpreter,
1586                              "process handle",
1587                              "Show or update what the process and debugger should do with various signals received from the OS.",
1588                              NULL),
1589         m_options (interpreter)
1590     {
1591         SetHelpLong ("If no signals are specified, update them all.  If no update option is specified, list the current values.\n");
1592         CommandArgumentEntry arg;
1593         CommandArgumentData signal_arg;
1594 
1595         signal_arg.arg_type = eArgTypeUnixSignal;
1596         signal_arg.arg_repetition = eArgRepeatStar;
1597 
1598         arg.push_back (signal_arg);
1599 
1600         m_arguments.push_back (arg);
1601     }
1602 
1603     ~CommandObjectProcessHandle ()
1604     {
1605     }
1606 
1607     Options *
1608     GetOptions ()
1609     {
1610         return &m_options;
1611     }
1612 
1613     bool
1614     VerifyCommandOptionValue (const std::string &option, int &real_value)
1615     {
1616         bool okay = true;
1617 
1618         bool success = false;
1619         bool tmp_value = Args::StringToBoolean (option.c_str(), false, &success);
1620 
1621         if (success && tmp_value)
1622             real_value = 1;
1623         else if (success && !tmp_value)
1624             real_value = 0;
1625         else
1626         {
1627             // If the value isn't 'true' or 'false', it had better be 0 or 1.
1628             real_value = Args::StringToUInt32 (option.c_str(), 3);
1629             if (real_value != 0 && real_value != 1)
1630                 okay = false;
1631         }
1632 
1633         return okay;
1634     }
1635 
1636     void
1637     PrintSignalHeader (Stream &str)
1638     {
1639         str.Printf ("NAME        PASS   STOP   NOTIFY\n");
1640         str.Printf ("==========  =====  =====  ======\n");
1641     }
1642 
1643     void
1644     PrintSignal (Stream &str, int32_t signo, const char *sig_name, UnixSignals &signals)
1645     {
1646         bool stop;
1647         bool suppress;
1648         bool notify;
1649 
1650         str.Printf ("%-10s  ", sig_name);
1651         if (signals.GetSignalInfo (signo, suppress, stop, notify))
1652         {
1653             bool pass = !suppress;
1654             str.Printf ("%s  %s  %s",
1655                         (pass ? "true " : "false"),
1656                         (stop ? "true " : "false"),
1657                         (notify ? "true " : "false"));
1658         }
1659         str.Printf ("\n");
1660     }
1661 
1662     void
1663     PrintSignalInformation (Stream &str, Args &signal_args, int num_valid_signals, UnixSignals &signals)
1664     {
1665         PrintSignalHeader (str);
1666 
1667         if (num_valid_signals > 0)
1668         {
1669             size_t num_args = signal_args.GetArgumentCount();
1670             for (size_t i = 0; i < num_args; ++i)
1671             {
1672                 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
1673                 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
1674                     PrintSignal (str, signo, signal_args.GetArgumentAtIndex (i), signals);
1675             }
1676         }
1677         else // Print info for ALL signals
1678         {
1679             int32_t signo = signals.GetFirstSignalNumber();
1680             while (signo != LLDB_INVALID_SIGNAL_NUMBER)
1681             {
1682                 PrintSignal (str, signo, signals.GetSignalAsCString (signo), signals);
1683                 signo = signals.GetNextSignalNumber (signo);
1684             }
1685         }
1686     }
1687 
1688 protected:
1689     bool
1690     DoExecute (Args &signal_args, CommandReturnObject &result)
1691     {
1692         TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
1693 
1694         if (!target_sp)
1695         {
1696             result.AppendError ("No current target;"
1697                                 " cannot handle signals until you have a valid target and process.\n");
1698             result.SetStatus (eReturnStatusFailed);
1699             return false;
1700         }
1701 
1702         ProcessSP process_sp = target_sp->GetProcessSP();
1703 
1704         if (!process_sp)
1705         {
1706             result.AppendError ("No current process; cannot handle signals until you have a valid process.\n");
1707             result.SetStatus (eReturnStatusFailed);
1708             return false;
1709         }
1710 
1711         int stop_action = -1;   // -1 means leave the current setting alone
1712         int pass_action = -1;   // -1 means leave the current setting alone
1713         int notify_action = -1; // -1 means leave the current setting alone
1714 
1715         if (! m_options.stop.empty()
1716             && ! VerifyCommandOptionValue (m_options.stop, stop_action))
1717         {
1718             result.AppendError ("Invalid argument for command option --stop; must be true or false.\n");
1719             result.SetStatus (eReturnStatusFailed);
1720             return false;
1721         }
1722 
1723         if (! m_options.notify.empty()
1724             && ! VerifyCommandOptionValue (m_options.notify, notify_action))
1725         {
1726             result.AppendError ("Invalid argument for command option --notify; must be true or false.\n");
1727             result.SetStatus (eReturnStatusFailed);
1728             return false;
1729         }
1730 
1731         if (! m_options.pass.empty()
1732             && ! VerifyCommandOptionValue (m_options.pass, pass_action))
1733         {
1734             result.AppendError ("Invalid argument for command option --pass; must be true or false.\n");
1735             result.SetStatus (eReturnStatusFailed);
1736             return false;
1737         }
1738 
1739         size_t num_args = signal_args.GetArgumentCount();
1740         UnixSignals &signals = process_sp->GetUnixSignals();
1741         int num_signals_set = 0;
1742 
1743         if (num_args > 0)
1744         {
1745             for (size_t i = 0; i < num_args; ++i)
1746             {
1747                 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
1748                 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
1749                 {
1750                     // Casting the actions as bools here should be okay, because VerifyCommandOptionValue guarantees
1751                     // the value is either 0 or 1.
1752                     if (stop_action != -1)
1753                         signals.SetShouldStop (signo, (bool) stop_action);
1754                     if (pass_action != -1)
1755                     {
1756                         bool suppress = ! ((bool) pass_action);
1757                         signals.SetShouldSuppress (signo, suppress);
1758                     }
1759                     if (notify_action != -1)
1760                         signals.SetShouldNotify (signo, (bool) notify_action);
1761                     ++num_signals_set;
1762                 }
1763                 else
1764                 {
1765                     result.AppendErrorWithFormat ("Invalid signal name '%s'\n", signal_args.GetArgumentAtIndex (i));
1766                 }
1767             }
1768         }
1769         else
1770         {
1771             // No signal specified, if any command options were specified, update ALL signals.
1772             if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1))
1773             {
1774                 if (m_interpreter.Confirm ("Do you really want to update all the signals?", false))
1775                 {
1776                     int32_t signo = signals.GetFirstSignalNumber();
1777                     while (signo != LLDB_INVALID_SIGNAL_NUMBER)
1778                     {
1779                         if (notify_action != -1)
1780                             signals.SetShouldNotify (signo, (bool) notify_action);
1781                         if (stop_action != -1)
1782                             signals.SetShouldStop (signo, (bool) stop_action);
1783                         if (pass_action != -1)
1784                         {
1785                             bool suppress = ! ((bool) pass_action);
1786                             signals.SetShouldSuppress (signo, suppress);
1787                         }
1788                         signo = signals.GetNextSignalNumber (signo);
1789                     }
1790                 }
1791             }
1792         }
1793 
1794         PrintSignalInformation (result.GetOutputStream(), signal_args, num_signals_set, signals);
1795 
1796         if (num_signals_set > 0)
1797             result.SetStatus (eReturnStatusSuccessFinishNoResult);
1798         else
1799             result.SetStatus (eReturnStatusFailed);
1800 
1801         return result.Succeeded();
1802     }
1803 
1804     CommandOptions m_options;
1805 };
1806 
1807 OptionDefinition
1808 CommandObjectProcessHandle::CommandOptions::g_option_table[] =
1809 {
1810 { 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." },
1811 { 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." },
1812 { LLDB_OPT_SET_1, false, "pass",  'p', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." },
1813 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1814 };
1815 
1816 //-------------------------------------------------------------------------
1817 // CommandObjectMultiwordProcess
1818 //-------------------------------------------------------------------------
1819 
1820 CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter &interpreter) :
1821     CommandObjectMultiword (interpreter,
1822                             "process",
1823                             "A set of commands for operating on a process.",
1824                             "process <subcommand> [<subcommand-options>]")
1825 {
1826     LoadSubCommand ("attach",      CommandObjectSP (new CommandObjectProcessAttach    (interpreter)));
1827     LoadSubCommand ("launch",      CommandObjectSP (new CommandObjectProcessLaunch    (interpreter)));
1828     LoadSubCommand ("continue",    CommandObjectSP (new CommandObjectProcessContinue  (interpreter)));
1829     LoadSubCommand ("connect",     CommandObjectSP (new CommandObjectProcessConnect   (interpreter)));
1830     LoadSubCommand ("detach",      CommandObjectSP (new CommandObjectProcessDetach    (interpreter)));
1831     LoadSubCommand ("load",        CommandObjectSP (new CommandObjectProcessLoad      (interpreter)));
1832     LoadSubCommand ("unload",      CommandObjectSP (new CommandObjectProcessUnload    (interpreter)));
1833     LoadSubCommand ("signal",      CommandObjectSP (new CommandObjectProcessSignal    (interpreter)));
1834     LoadSubCommand ("handle",      CommandObjectSP (new CommandObjectProcessHandle    (interpreter)));
1835     LoadSubCommand ("status",      CommandObjectSP (new CommandObjectProcessStatus    (interpreter)));
1836     LoadSubCommand ("interrupt",   CommandObjectSP (new CommandObjectProcessInterrupt (interpreter)));
1837     LoadSubCommand ("kill",        CommandObjectSP (new CommandObjectProcessKill      (interpreter)));
1838     LoadSubCommand ("plugin",      CommandObjectSP (new CommandObjectProcessPlugin    (interpreter)));
1839 }
1840 
1841 CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess ()
1842 {
1843 }
1844 
1845