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