xref: /llvm-project/lldb/source/Commands/CommandObjectProcess.cpp (revision 0161b49cbadd54431b4acefa8dae954ebef12ec8)
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                              eFlagRequiresTarget),
51         m_options (interpreter)
52     {
53         CommandArgumentEntry arg;
54         CommandArgumentData run_args_arg;
55 
56         // Define the first (and only) variant of this arg.
57         run_args_arg.arg_type = eArgTypeRunArgs;
58         run_args_arg.arg_repetition = eArgRepeatOptional;
59 
60         // There is only one variant this argument could be; put it into the argument entry.
61         arg.push_back (run_args_arg);
62 
63         // Push the data for the first argument into the m_arguments vector.
64         m_arguments.push_back (arg);
65     }
66 
67 
68     ~CommandObjectProcessLaunch ()
69     {
70     }
71 
72     virtual int
73     HandleArgumentCompletion (Args &input,
74                               int &cursor_index,
75                               int &cursor_char_position,
76                               OptionElementVector &opt_element_vector,
77                               int match_start_point,
78                               int max_return_elements,
79                               bool &word_complete,
80                               StringList &matches)
81     {
82         std::string completion_str (input.GetArgumentAtIndex(cursor_index));
83         completion_str.erase (cursor_char_position);
84 
85         CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter,
86                                                              CommandCompletions::eDiskFileCompletion,
87                                                              completion_str.c_str(),
88                                                              match_start_point,
89                                                              max_return_elements,
90                                                              NULL,
91                                                              word_complete,
92                                                              matches);
93         return matches.GetSize();
94     }
95 
96     Options *
97     GetOptions ()
98     {
99         return &m_options;
100     }
101 
102     virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
103     {
104         // No repeat for "process launch"...
105         return "";
106     }
107 
108 protected:
109     bool
110     DoExecute (Args& launch_args, CommandReturnObject &result)
111     {
112         Debugger &debugger = m_interpreter.GetDebugger();
113         Target *target = debugger.GetSelectedTarget().get();
114         Error error;
115         // If our listener is NULL, users aren't allows to launch
116         char filename[PATH_MAX];
117         const Module *exe_module = target->GetExecutableModulePointer();
118 
119         if (exe_module == NULL)
120         {
121             result.AppendError ("no file in target, create a debug target using the 'target create' command");
122             result.SetStatus (eReturnStatusFailed);
123             return false;
124         }
125 
126         StateType state = eStateInvalid;
127         Process *process = m_exe_ctx.GetProcessPtr();
128         if (process)
129         {
130             state = process->GetState();
131 
132             if (process->IsAlive() && state != eStateConnected)
133             {
134                 char message[1024];
135                 if (process->GetState() == eStateAttaching)
136                     ::strncpy (message, "There is a pending attach, abort it and launch a new process?", sizeof(message));
137                 else
138                     ::strncpy (message, "There is a running process, kill it and restart?", sizeof(message));
139 
140                 if (!m_interpreter.Confirm (message, true))
141                 {
142                     result.SetStatus (eReturnStatusFailed);
143                     return false;
144                 }
145                 else
146                 {
147                     Error destroy_error (process->Destroy());
148                     if (destroy_error.Success())
149                     {
150                         result.SetStatus (eReturnStatusSuccessFinishResult);
151                     }
152                     else
153                     {
154                         result.AppendErrorWithFormat ("Failed to kill process: %s\n", destroy_error.AsCString());
155                         result.SetStatus (eReturnStatusFailed);
156                     }
157                 }
158             }
159         }
160 
161         const char *target_settings_argv0 = target->GetArg0();
162 
163         exe_module->GetFileSpec().GetPath (filename, sizeof(filename));
164 
165         if (target_settings_argv0)
166         {
167             m_options.launch_info.GetArguments().AppendArgument (target_settings_argv0);
168             m_options.launch_info.SetExecutableFile(exe_module->GetPlatformFileSpec(), false);
169         }
170         else
171         {
172             m_options.launch_info.SetExecutableFile(exe_module->GetPlatformFileSpec(), true);
173         }
174 
175         if (launch_args.GetArgumentCount() == 0)
176         {
177             Args target_setting_args;
178             if (target->GetRunArguments(target_setting_args))
179                 m_options.launch_info.GetArguments().AppendArguments (target_setting_args);
180         }
181         else
182         {
183             m_options.launch_info.GetArguments().AppendArguments (launch_args);
184 
185             // Save the arguments for subsequent runs in the current target.
186             target->SetRunArguments (launch_args);
187         }
188 
189         if (target->GetDisableASLR())
190             m_options.launch_info.GetFlags().Set (eLaunchFlagDisableASLR);
191 
192         if (target->GetDisableSTDIO())
193             m_options.launch_info.GetFlags().Set (eLaunchFlagDisableSTDIO);
194 
195         m_options.launch_info.GetFlags().Set (eLaunchFlagDebug);
196 
197         Args environment;
198         target->GetEnvironmentAsArgs (environment);
199         if (environment.GetArgumentCount() > 0)
200             m_options.launch_info.GetEnvironmentEntries ().AppendArguments (environment);
201 
202         // Get the value of synchronous execution here.  If you wait till after you have started to
203         // run, then you could have hit a breakpoint, whose command might switch the value, and
204         // then you'll pick up that incorrect value.
205         bool synchronous_execution = m_interpreter.GetSynchronous ();
206 
207         // Finalize the file actions, and if none were given, default to opening
208         // up a pseudo terminal
209         const bool default_to_use_pty = true;
210         m_options.launch_info.FinalizeFileActions (target, default_to_use_pty);
211 
212         if (state == eStateConnected)
213         {
214             if (m_options.launch_info.GetFlags().Test (eLaunchFlagLaunchInTTY))
215             {
216                 result.AppendWarning("can't launch in tty when launching through a remote connection");
217                 m_options.launch_info.GetFlags().Clear (eLaunchFlagLaunchInTTY);
218             }
219         }
220         else
221         {
222             if (!m_options.launch_info.GetArchitecture().IsValid())
223                 m_options.launch_info.GetArchitecture() = target->GetArchitecture();
224 
225             PlatformSP platform_sp (target->GetPlatform());
226 
227             if (platform_sp && platform_sp->CanDebugProcess ())
228             {
229                 process = target->GetPlatform()->DebugProcess (m_options.launch_info,
230                                                                debugger,
231                                                                target,
232                                                                debugger.GetListener(),
233                                                                error).get();
234             }
235             else
236             {
237                 const char *plugin_name = m_options.launch_info.GetProcessPluginName();
238                 process = target->CreateProcess (debugger.GetListener(), plugin_name, NULL).get();
239                 if (process)
240                     error = process->Launch (m_options.launch_info);
241             }
242 
243             if (process == NULL)
244             {
245                 result.SetError (error, "failed to launch or debug process");
246                 return false;
247             }
248         }
249 
250         if (error.Success())
251         {
252             const char *archname = exe_module->GetArchitecture().GetArchitectureName();
253 
254             result.AppendMessageWithFormat ("Process %" PRIu64 " launched: '%s' (%s)\n", process->GetID(), filename, archname);
255             result.SetDidChangeProcessState (true);
256             if (m_options.launch_info.GetFlags().Test(eLaunchFlagStopAtEntry) == false)
257             {
258                 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
259                 StateType state = process->WaitForProcessToStop (NULL);
260 
261                 if (state == eStateStopped)
262                 {
263                     error = process->Resume();
264                     if (error.Success())
265                     {
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             const int short_option = 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 size_t num_matches = process_infos.GetSize();
454                     if (num_matches > 0)
455                     {
456                         for (size_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_exe_ctx.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.IsExactMatch(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                              eFlagRequiresProcess       |
688                              eFlagTryTargetAPILock      |
689                              eFlagProcessMustBeLaunched |
690                              eFlagProcessMustBePaused   ),
691         m_options(interpreter)
692     {
693     }
694 
695 
696     ~CommandObjectProcessContinue ()
697     {
698     }
699 
700 protected:
701 
702     class CommandOptions : public Options
703     {
704     public:
705 
706         CommandOptions (CommandInterpreter &interpreter) :
707             Options(interpreter)
708         {
709             // Keep default values of all options in one place: OptionParsingStarting ()
710             OptionParsingStarting ();
711         }
712 
713         ~CommandOptions ()
714         {
715         }
716 
717         Error
718         SetOptionValue (uint32_t option_idx, const char *option_arg)
719         {
720             Error error;
721             const int short_option = m_getopt_table[option_idx].val;
722             bool success = false;
723             switch (short_option)
724             {
725                 case 'i':
726                     m_ignore = Args::StringToUInt32 (option_arg, 0, 0, &success);
727                     if (!success)
728                         error.SetErrorStringWithFormat ("invalid value for ignore option: \"%s\", should be a number.", option_arg);
729                     break;
730 
731                 default:
732                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
733                     break;
734             }
735             return error;
736         }
737 
738         void
739         OptionParsingStarting ()
740         {
741             m_ignore = 0;
742         }
743 
744         const OptionDefinition*
745         GetDefinitions ()
746         {
747             return g_option_table;
748         }
749 
750         // Options table: Required for subclasses of Options.
751 
752         static OptionDefinition g_option_table[];
753 
754         uint32_t m_ignore;
755     };
756 
757     bool
758     DoExecute (Args& command, CommandReturnObject &result)
759     {
760         Process *process = m_exe_ctx.GetProcessPtr();
761         bool synchronous_execution = m_interpreter.GetSynchronous ();
762         StateType state = process->GetState();
763         if (state == eStateStopped)
764         {
765             if (command.GetArgumentCount() != 0)
766             {
767                 result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str());
768                 result.SetStatus (eReturnStatusFailed);
769                 return false;
770             }
771 
772             if (m_options.m_ignore > 0)
773             {
774                 ThreadSP sel_thread_sp(process->GetThreadList().GetSelectedThread());
775                 if (sel_thread_sp)
776                 {
777                     StopInfoSP stop_info_sp = sel_thread_sp->GetStopInfo();
778                     if (stop_info_sp && stop_info_sp->GetStopReason() == eStopReasonBreakpoint)
779                     {
780                         lldb::break_id_t bp_site_id = (lldb::break_id_t)stop_info_sp->GetValue();
781                         BreakpointSiteSP bp_site_sp(process->GetBreakpointSiteList().FindByID(bp_site_id));
782                         if (bp_site_sp)
783                         {
784                             const size_t num_owners = bp_site_sp->GetNumberOfOwners();
785                             for (size_t i = 0; i < num_owners; i++)
786                             {
787                                 Breakpoint &bp_ref = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint();
788                                 if (!bp_ref.IsInternal())
789                                 {
790                                     bp_ref.SetIgnoreCount(m_options.m_ignore);
791                                 }
792                             }
793                         }
794                     }
795                 }
796             }
797 
798             {  // Scope for thread list mutex:
799                 Mutex::Locker locker (process->GetThreadList().GetMutex());
800                 const uint32_t num_threads = process->GetThreadList().GetSize();
801 
802                 // Set the actions that the threads should each take when resuming
803                 for (uint32_t idx=0; idx<num_threads; ++idx)
804                 {
805                     process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning);
806                 }
807             }
808 
809             Error error(process->Resume());
810             if (error.Success())
811             {
812                 result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID());
813                 if (synchronous_execution)
814                 {
815                     state = process->WaitForProcessToStop (NULL);
816 
817                     result.SetDidChangeProcessState (true);
818                     result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state));
819                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
820                 }
821                 else
822                 {
823                     result.SetStatus (eReturnStatusSuccessContinuingNoResult);
824                 }
825             }
826             else
827             {
828                 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
829                 result.SetStatus (eReturnStatusFailed);
830             }
831         }
832         else
833         {
834             result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
835                                          StateAsCString(state));
836             result.SetStatus (eReturnStatusFailed);
837         }
838         return result.Succeeded();
839     }
840 
841     Options *
842     GetOptions ()
843     {
844         return &m_options;
845     }
846 
847     CommandOptions m_options;
848 
849 };
850 
851 OptionDefinition
852 CommandObjectProcessContinue::CommandOptions::g_option_table[] =
853 {
854 { LLDB_OPT_SET_ALL, false, "ignore-count",'i', required_argument,         NULL, 0, eArgTypeUnsignedInteger,
855                            "Ignore <N> crossings of the breakpoint (if it exists) for the currently selected thread."},
856 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
857 };
858 
859 //-------------------------------------------------------------------------
860 // CommandObjectProcessDetach
861 //-------------------------------------------------------------------------
862 #pragma mark CommandObjectProcessDetach
863 
864 class CommandObjectProcessDetach : public CommandObjectParsed
865 {
866 public:
867 
868     CommandObjectProcessDetach (CommandInterpreter &interpreter) :
869         CommandObjectParsed (interpreter,
870                              "process detach",
871                              "Detach from the current process being debugged.",
872                              "process detach",
873                              eFlagRequiresProcess      |
874                              eFlagTryTargetAPILock     |
875                              eFlagProcessMustBeLaunched)
876     {
877     }
878 
879     ~CommandObjectProcessDetach ()
880     {
881     }
882 
883 protected:
884     bool
885     DoExecute (Args& command, CommandReturnObject &result)
886     {
887         Process *process = m_exe_ctx.GetProcessPtr();
888         result.AppendMessageWithFormat ("Detaching from process %" PRIu64 "\n", process->GetID());
889         Error error (process->Detach());
890         if (error.Success())
891         {
892             result.SetStatus (eReturnStatusSuccessFinishResult);
893         }
894         else
895         {
896             result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString());
897             result.SetStatus (eReturnStatusFailed);
898             return false;
899         }
900         return result.Succeeded();
901     }
902 };
903 
904 //-------------------------------------------------------------------------
905 // CommandObjectProcessConnect
906 //-------------------------------------------------------------------------
907 #pragma mark CommandObjectProcessConnect
908 
909 class CommandObjectProcessConnect : public CommandObjectParsed
910 {
911 public:
912 
913     class CommandOptions : public Options
914     {
915     public:
916 
917         CommandOptions (CommandInterpreter &interpreter) :
918             Options(interpreter)
919         {
920             // Keep default values of all options in one place: OptionParsingStarting ()
921             OptionParsingStarting ();
922         }
923 
924         ~CommandOptions ()
925         {
926         }
927 
928         Error
929         SetOptionValue (uint32_t option_idx, const char *option_arg)
930         {
931             Error error;
932             const int short_option = m_getopt_table[option_idx].val;
933 
934             switch (short_option)
935             {
936             case 'p':
937                 plugin_name.assign (option_arg);
938                 break;
939 
940             default:
941                 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
942                 break;
943             }
944             return error;
945         }
946 
947         void
948         OptionParsingStarting ()
949         {
950             plugin_name.clear();
951         }
952 
953         const OptionDefinition*
954         GetDefinitions ()
955         {
956             return g_option_table;
957         }
958 
959         // Options table: Required for subclasses of Options.
960 
961         static OptionDefinition g_option_table[];
962 
963         // Instance variables to hold the values for command options.
964 
965         std::string plugin_name;
966     };
967 
968     CommandObjectProcessConnect (CommandInterpreter &interpreter) :
969         CommandObjectParsed (interpreter,
970                              "process connect",
971                              "Connect to a remote debug service.",
972                              "process connect <remote-url>",
973                              0),
974         m_options (interpreter)
975     {
976     }
977 
978     ~CommandObjectProcessConnect ()
979     {
980     }
981 
982 
983     Options *
984     GetOptions ()
985     {
986         return &m_options;
987     }
988 
989 protected:
990     bool
991     DoExecute (Args& command,
992              CommandReturnObject &result)
993     {
994 
995         TargetSP target_sp (m_interpreter.GetDebugger().GetSelectedTarget());
996         Error error;
997         Process *process = m_exe_ctx.GetProcessPtr();
998         if (process)
999         {
1000             if (process->IsAlive())
1001             {
1002                 result.AppendErrorWithFormat ("Process %" PRIu64 " is currently being debugged, kill the process before connecting.\n",
1003                                               process->GetID());
1004                 result.SetStatus (eReturnStatusFailed);
1005                 return false;
1006             }
1007         }
1008 
1009         if (!target_sp)
1010         {
1011             // If there isn't a current target create one.
1012 
1013             error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(),
1014                                                                               NULL,
1015                                                                               NULL,
1016                                                                               false,
1017                                                                               NULL, // No platform options
1018                                                                               target_sp);
1019             if (!target_sp || error.Fail())
1020             {
1021                 result.AppendError(error.AsCString("Error creating target"));
1022                 result.SetStatus (eReturnStatusFailed);
1023                 return false;
1024             }
1025             m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target_sp.get());
1026         }
1027 
1028         if (command.GetArgumentCount() == 1)
1029         {
1030             const char *plugin_name = NULL;
1031             if (!m_options.plugin_name.empty())
1032                 plugin_name = m_options.plugin_name.c_str();
1033 
1034             const char *remote_url = command.GetArgumentAtIndex(0);
1035             process = target_sp->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name, NULL).get();
1036 
1037             if (process)
1038             {
1039                 error = process->ConnectRemote (&process->GetTarget().GetDebugger().GetOutputStream(), remote_url);
1040 
1041                 if (error.Fail())
1042                 {
1043                     result.AppendError(error.AsCString("Remote connect failed"));
1044                     result.SetStatus (eReturnStatusFailed);
1045                     target_sp->DeleteCurrentProcess();
1046                     return false;
1047                 }
1048             }
1049             else
1050             {
1051                 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",
1052                                               remote_url);
1053                 result.SetStatus (eReturnStatusFailed);
1054             }
1055         }
1056         else
1057         {
1058             result.AppendErrorWithFormat ("'%s' takes exactly one argument:\nUsage: %s\n",
1059                                           m_cmd_name.c_str(),
1060                                           m_cmd_syntax.c_str());
1061             result.SetStatus (eReturnStatusFailed);
1062         }
1063         return result.Succeeded();
1064     }
1065 
1066     CommandOptions m_options;
1067 };
1068 
1069 OptionDefinition
1070 CommandObjectProcessConnect::CommandOptions::g_option_table[] =
1071 {
1072     { LLDB_OPT_SET_ALL, false, "plugin", 'p', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
1073     { 0,                false, NULL,      0 , 0,                 NULL, 0, eArgTypeNone,   NULL }
1074 };
1075 
1076 //-------------------------------------------------------------------------
1077 // CommandObjectProcessPlugin
1078 //-------------------------------------------------------------------------
1079 #pragma mark CommandObjectProcessPlugin
1080 
1081 class CommandObjectProcessPlugin : public CommandObjectProxy
1082 {
1083 public:
1084 
1085     CommandObjectProcessPlugin (CommandInterpreter &interpreter) :
1086         CommandObjectProxy (interpreter,
1087                             "process plugin",
1088                             "Send a custom command to the current process plug-in.",
1089                             "process plugin <args>",
1090                             0)
1091     {
1092     }
1093 
1094     ~CommandObjectProcessPlugin ()
1095     {
1096     }
1097 
1098     virtual CommandObject *
1099     GetProxyCommandObject()
1100     {
1101         Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
1102         if (process)
1103             return process->GetPluginCommandObject();
1104         return NULL;
1105     }
1106 };
1107 
1108 
1109 //-------------------------------------------------------------------------
1110 // CommandObjectProcessLoad
1111 //-------------------------------------------------------------------------
1112 #pragma mark CommandObjectProcessLoad
1113 
1114 class CommandObjectProcessLoad : public CommandObjectParsed
1115 {
1116 public:
1117 
1118     CommandObjectProcessLoad (CommandInterpreter &interpreter) :
1119         CommandObjectParsed (interpreter,
1120                              "process load",
1121                              "Load a shared library into the current process.",
1122                              "process load <filename> [<filename> ...]",
1123                              eFlagRequiresProcess       |
1124                              eFlagTryTargetAPILock      |
1125                              eFlagProcessMustBeLaunched |
1126                              eFlagProcessMustBePaused   )
1127     {
1128     }
1129 
1130     ~CommandObjectProcessLoad ()
1131     {
1132     }
1133 
1134 protected:
1135     bool
1136     DoExecute (Args& command,
1137              CommandReturnObject &result)
1138     {
1139         Process *process = m_exe_ctx.GetProcessPtr();
1140 
1141         const size_t argc = command.GetArgumentCount();
1142 
1143         for (uint32_t i=0; i<argc; ++i)
1144         {
1145             Error error;
1146             const char *image_path = command.GetArgumentAtIndex(i);
1147             FileSpec image_spec (image_path, false);
1148             process->GetTarget().GetPlatform()->ResolveRemotePath(image_spec, image_spec);
1149             uint32_t image_token = process->LoadImage(image_spec, error);
1150             if (image_token != LLDB_INVALID_IMAGE_TOKEN)
1151             {
1152                 result.AppendMessageWithFormat ("Loading \"%s\"...ok\nImage %u loaded.\n", image_path, image_token);
1153                 result.SetStatus (eReturnStatusSuccessFinishResult);
1154             }
1155             else
1156             {
1157                 result.AppendErrorWithFormat ("failed to load '%s': %s", image_path, error.AsCString());
1158                 result.SetStatus (eReturnStatusFailed);
1159             }
1160         }
1161         return result.Succeeded();
1162     }
1163 };
1164 
1165 
1166 //-------------------------------------------------------------------------
1167 // CommandObjectProcessUnload
1168 //-------------------------------------------------------------------------
1169 #pragma mark CommandObjectProcessUnload
1170 
1171 class CommandObjectProcessUnload : public CommandObjectParsed
1172 {
1173 public:
1174 
1175     CommandObjectProcessUnload (CommandInterpreter &interpreter) :
1176         CommandObjectParsed (interpreter,
1177                              "process unload",
1178                              "Unload a shared library from the current process using the index returned by a previous call to \"process load\".",
1179                              "process unload <index>",
1180                              eFlagRequiresProcess       |
1181                              eFlagTryTargetAPILock      |
1182                              eFlagProcessMustBeLaunched |
1183                              eFlagProcessMustBePaused   )
1184     {
1185     }
1186 
1187     ~CommandObjectProcessUnload ()
1188     {
1189     }
1190 
1191 protected:
1192     bool
1193     DoExecute (Args& command,
1194              CommandReturnObject &result)
1195     {
1196         Process *process = m_exe_ctx.GetProcessPtr();
1197 
1198         const size_t argc = command.GetArgumentCount();
1199 
1200         for (uint32_t i=0; i<argc; ++i)
1201         {
1202             const char *image_token_cstr = command.GetArgumentAtIndex(i);
1203             uint32_t image_token = Args::StringToUInt32(image_token_cstr, LLDB_INVALID_IMAGE_TOKEN, 0);
1204             if (image_token == LLDB_INVALID_IMAGE_TOKEN)
1205             {
1206                 result.AppendErrorWithFormat ("invalid image index argument '%s'", image_token_cstr);
1207                 result.SetStatus (eReturnStatusFailed);
1208                 break;
1209             }
1210             else
1211             {
1212                 Error error (process->UnloadImage(image_token));
1213                 if (error.Success())
1214                 {
1215                     result.AppendMessageWithFormat ("Unloading shared library with index %u...ok\n", image_token);
1216                     result.SetStatus (eReturnStatusSuccessFinishResult);
1217                 }
1218                 else
1219                 {
1220                     result.AppendErrorWithFormat ("failed to unload image: %s", error.AsCString());
1221                     result.SetStatus (eReturnStatusFailed);
1222                     break;
1223                 }
1224             }
1225         }
1226         return result.Succeeded();
1227     }
1228 };
1229 
1230 //-------------------------------------------------------------------------
1231 // CommandObjectProcessSignal
1232 //-------------------------------------------------------------------------
1233 #pragma mark CommandObjectProcessSignal
1234 
1235 class CommandObjectProcessSignal : public CommandObjectParsed
1236 {
1237 public:
1238 
1239     CommandObjectProcessSignal (CommandInterpreter &interpreter) :
1240         CommandObjectParsed (interpreter,
1241                              "process signal",
1242                              "Send a UNIX signal to the current process being debugged.",
1243                              NULL,
1244                              eFlagRequiresProcess | eFlagTryTargetAPILock)
1245     {
1246         CommandArgumentEntry arg;
1247         CommandArgumentData signal_arg;
1248 
1249         // Define the first (and only) variant of this arg.
1250         signal_arg.arg_type = eArgTypeUnixSignal;
1251         signal_arg.arg_repetition = eArgRepeatPlain;
1252 
1253         // There is only one variant this argument could be; put it into the argument entry.
1254         arg.push_back (signal_arg);
1255 
1256         // Push the data for the first argument into the m_arguments vector.
1257         m_arguments.push_back (arg);
1258     }
1259 
1260     ~CommandObjectProcessSignal ()
1261     {
1262     }
1263 
1264 protected:
1265     bool
1266     DoExecute (Args& command,
1267              CommandReturnObject &result)
1268     {
1269         Process *process = m_exe_ctx.GetProcessPtr();
1270 
1271         if (command.GetArgumentCount() == 1)
1272         {
1273             int signo = LLDB_INVALID_SIGNAL_NUMBER;
1274 
1275             const char *signal_name = command.GetArgumentAtIndex(0);
1276             if (::isxdigit (signal_name[0]))
1277                 signo = Args::StringToSInt32(signal_name, LLDB_INVALID_SIGNAL_NUMBER, 0);
1278             else
1279                 signo = process->GetUnixSignals().GetSignalNumberFromName (signal_name);
1280 
1281             if (signo == LLDB_INVALID_SIGNAL_NUMBER)
1282             {
1283                 result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0));
1284                 result.SetStatus (eReturnStatusFailed);
1285             }
1286             else
1287             {
1288                 Error error (process->Signal (signo));
1289                 if (error.Success())
1290                 {
1291                     result.SetStatus (eReturnStatusSuccessFinishResult);
1292                 }
1293                 else
1294                 {
1295                     result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString());
1296                     result.SetStatus (eReturnStatusFailed);
1297                 }
1298             }
1299         }
1300         else
1301         {
1302             result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: %s\n", m_cmd_name.c_str(),
1303                                         m_cmd_syntax.c_str());
1304             result.SetStatus (eReturnStatusFailed);
1305         }
1306         return result.Succeeded();
1307     }
1308 };
1309 
1310 
1311 //-------------------------------------------------------------------------
1312 // CommandObjectProcessInterrupt
1313 //-------------------------------------------------------------------------
1314 #pragma mark CommandObjectProcessInterrupt
1315 
1316 class CommandObjectProcessInterrupt : public CommandObjectParsed
1317 {
1318 public:
1319 
1320 
1321     CommandObjectProcessInterrupt (CommandInterpreter &interpreter) :
1322         CommandObjectParsed (interpreter,
1323                              "process interrupt",
1324                              "Interrupt the current process being debugged.",
1325                              "process interrupt",
1326                              eFlagRequiresProcess      |
1327                              eFlagTryTargetAPILock     |
1328                              eFlagProcessMustBeLaunched)
1329     {
1330     }
1331 
1332     ~CommandObjectProcessInterrupt ()
1333     {
1334     }
1335 
1336 protected:
1337     bool
1338     DoExecute (Args& command,
1339              CommandReturnObject &result)
1340     {
1341         Process *process = m_exe_ctx.GetProcessPtr();
1342         if (process == NULL)
1343         {
1344             result.AppendError ("no process to halt");
1345             result.SetStatus (eReturnStatusFailed);
1346             return false;
1347         }
1348 
1349         if (command.GetArgumentCount() == 0)
1350         {
1351             Error error(process->Halt ());
1352             if (error.Success())
1353             {
1354                 result.SetStatus (eReturnStatusSuccessFinishResult);
1355 
1356                 // Maybe we should add a "SuspendThreadPlans so we
1357                 // can halt, and keep in place all the current thread plans.
1358                 process->GetThreadList().DiscardThreadPlans();
1359             }
1360             else
1361             {
1362                 result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString());
1363                 result.SetStatus (eReturnStatusFailed);
1364             }
1365         }
1366         else
1367         {
1368             result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n",
1369                                         m_cmd_name.c_str(),
1370                                         m_cmd_syntax.c_str());
1371             result.SetStatus (eReturnStatusFailed);
1372         }
1373         return result.Succeeded();
1374     }
1375 };
1376 
1377 //-------------------------------------------------------------------------
1378 // CommandObjectProcessKill
1379 //-------------------------------------------------------------------------
1380 #pragma mark CommandObjectProcessKill
1381 
1382 class CommandObjectProcessKill : public CommandObjectParsed
1383 {
1384 public:
1385 
1386     CommandObjectProcessKill (CommandInterpreter &interpreter) :
1387         CommandObjectParsed (interpreter,
1388                              "process kill",
1389                              "Terminate the current process being debugged.",
1390                              "process kill",
1391                              eFlagRequiresProcess      |
1392                              eFlagTryTargetAPILock     |
1393                              eFlagProcessMustBeLaunched)
1394     {
1395     }
1396 
1397     ~CommandObjectProcessKill ()
1398     {
1399     }
1400 
1401 protected:
1402     bool
1403     DoExecute (Args& command,
1404              CommandReturnObject &result)
1405     {
1406         Process *process = m_exe_ctx.GetProcessPtr();
1407         if (process == NULL)
1408         {
1409             result.AppendError ("no process to kill");
1410             result.SetStatus (eReturnStatusFailed);
1411             return false;
1412         }
1413 
1414         if (command.GetArgumentCount() == 0)
1415         {
1416             Error error (process->Destroy());
1417             if (error.Success())
1418             {
1419                 result.SetStatus (eReturnStatusSuccessFinishResult);
1420             }
1421             else
1422             {
1423                 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString());
1424                 result.SetStatus (eReturnStatusFailed);
1425             }
1426         }
1427         else
1428         {
1429             result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n",
1430                                         m_cmd_name.c_str(),
1431                                         m_cmd_syntax.c_str());
1432             result.SetStatus (eReturnStatusFailed);
1433         }
1434         return result.Succeeded();
1435     }
1436 };
1437 
1438 //-------------------------------------------------------------------------
1439 // CommandObjectProcessStatus
1440 //-------------------------------------------------------------------------
1441 #pragma mark CommandObjectProcessStatus
1442 
1443 class CommandObjectProcessStatus : public CommandObjectParsed
1444 {
1445 public:
1446     CommandObjectProcessStatus (CommandInterpreter &interpreter) :
1447         CommandObjectParsed (interpreter,
1448                              "process status",
1449                              "Show the current status and location of executing process.",
1450                              "process status",
1451                              eFlagRequiresProcess | eFlagTryTargetAPILock)
1452     {
1453     }
1454 
1455     ~CommandObjectProcessStatus()
1456     {
1457     }
1458 
1459 
1460     bool
1461     DoExecute (Args& command, CommandReturnObject &result)
1462     {
1463         Stream &strm = result.GetOutputStream();
1464         result.SetStatus (eReturnStatusSuccessFinishNoResult);
1465         // No need to check "process" for validity as eFlagRequiresProcess ensures it is valid
1466         Process *process = m_exe_ctx.GetProcessPtr();
1467         const bool only_threads_with_stop_reason = true;
1468         const uint32_t start_frame = 0;
1469         const uint32_t num_frames = 1;
1470         const uint32_t num_frames_with_source = 1;
1471         process->GetStatus(strm);
1472         process->GetThreadStatus (strm,
1473                                   only_threads_with_stop_reason,
1474                                   start_frame,
1475                                   num_frames,
1476                                   num_frames_with_source);
1477         return result.Succeeded();
1478     }
1479 };
1480 
1481 //-------------------------------------------------------------------------
1482 // CommandObjectProcessHandle
1483 //-------------------------------------------------------------------------
1484 #pragma mark CommandObjectProcessHandle
1485 
1486 class CommandObjectProcessHandle : public CommandObjectParsed
1487 {
1488 public:
1489 
1490     class CommandOptions : public Options
1491     {
1492     public:
1493 
1494         CommandOptions (CommandInterpreter &interpreter) :
1495             Options (interpreter)
1496         {
1497             OptionParsingStarting ();
1498         }
1499 
1500         ~CommandOptions ()
1501         {
1502         }
1503 
1504         Error
1505         SetOptionValue (uint32_t option_idx, const char *option_arg)
1506         {
1507             Error error;
1508             const int short_option = m_getopt_table[option_idx].val;
1509 
1510             switch (short_option)
1511             {
1512                 case 's':
1513                     stop = option_arg;
1514                     break;
1515                 case 'n':
1516                     notify = option_arg;
1517                     break;
1518                 case 'p':
1519                     pass = option_arg;
1520                     break;
1521                 default:
1522                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
1523                     break;
1524             }
1525             return error;
1526         }
1527 
1528         void
1529         OptionParsingStarting ()
1530         {
1531             stop.clear();
1532             notify.clear();
1533             pass.clear();
1534         }
1535 
1536         const OptionDefinition*
1537         GetDefinitions ()
1538         {
1539             return g_option_table;
1540         }
1541 
1542         // Options table: Required for subclasses of Options.
1543 
1544         static OptionDefinition g_option_table[];
1545 
1546         // Instance variables to hold the values for command options.
1547 
1548         std::string stop;
1549         std::string notify;
1550         std::string pass;
1551     };
1552 
1553 
1554     CommandObjectProcessHandle (CommandInterpreter &interpreter) :
1555         CommandObjectParsed (interpreter,
1556                              "process handle",
1557                              "Show or update what the process and debugger should do with various signals received from the OS.",
1558                              NULL),
1559         m_options (interpreter)
1560     {
1561         SetHelpLong ("If no signals are specified, update them all.  If no update option is specified, list the current values.\n");
1562         CommandArgumentEntry arg;
1563         CommandArgumentData signal_arg;
1564 
1565         signal_arg.arg_type = eArgTypeUnixSignal;
1566         signal_arg.arg_repetition = eArgRepeatStar;
1567 
1568         arg.push_back (signal_arg);
1569 
1570         m_arguments.push_back (arg);
1571     }
1572 
1573     ~CommandObjectProcessHandle ()
1574     {
1575     }
1576 
1577     Options *
1578     GetOptions ()
1579     {
1580         return &m_options;
1581     }
1582 
1583     bool
1584     VerifyCommandOptionValue (const std::string &option, int &real_value)
1585     {
1586         bool okay = true;
1587 
1588         bool success = false;
1589         bool tmp_value = Args::StringToBoolean (option.c_str(), false, &success);
1590 
1591         if (success && tmp_value)
1592             real_value = 1;
1593         else if (success && !tmp_value)
1594             real_value = 0;
1595         else
1596         {
1597             // If the value isn't 'true' or 'false', it had better be 0 or 1.
1598             real_value = Args::StringToUInt32 (option.c_str(), 3);
1599             if (real_value != 0 && real_value != 1)
1600                 okay = false;
1601         }
1602 
1603         return okay;
1604     }
1605 
1606     void
1607     PrintSignalHeader (Stream &str)
1608     {
1609         str.Printf ("NAME        PASS   STOP   NOTIFY\n");
1610         str.Printf ("==========  =====  =====  ======\n");
1611     }
1612 
1613     void
1614     PrintSignal (Stream &str, int32_t signo, const char *sig_name, UnixSignals &signals)
1615     {
1616         bool stop;
1617         bool suppress;
1618         bool notify;
1619 
1620         str.Printf ("%-10s  ", sig_name);
1621         if (signals.GetSignalInfo (signo, suppress, stop, notify))
1622         {
1623             bool pass = !suppress;
1624             str.Printf ("%s  %s  %s",
1625                         (pass ? "true " : "false"),
1626                         (stop ? "true " : "false"),
1627                         (notify ? "true " : "false"));
1628         }
1629         str.Printf ("\n");
1630     }
1631 
1632     void
1633     PrintSignalInformation (Stream &str, Args &signal_args, int num_valid_signals, UnixSignals &signals)
1634     {
1635         PrintSignalHeader (str);
1636 
1637         if (num_valid_signals > 0)
1638         {
1639             size_t num_args = signal_args.GetArgumentCount();
1640             for (size_t i = 0; i < num_args; ++i)
1641             {
1642                 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
1643                 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
1644                     PrintSignal (str, signo, signal_args.GetArgumentAtIndex (i), signals);
1645             }
1646         }
1647         else // Print info for ALL signals
1648         {
1649             int32_t signo = signals.GetFirstSignalNumber();
1650             while (signo != LLDB_INVALID_SIGNAL_NUMBER)
1651             {
1652                 PrintSignal (str, signo, signals.GetSignalAsCString (signo), signals);
1653                 signo = signals.GetNextSignalNumber (signo);
1654             }
1655         }
1656     }
1657 
1658 protected:
1659     bool
1660     DoExecute (Args &signal_args, CommandReturnObject &result)
1661     {
1662         TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
1663 
1664         if (!target_sp)
1665         {
1666             result.AppendError ("No current target;"
1667                                 " cannot handle signals until you have a valid target and process.\n");
1668             result.SetStatus (eReturnStatusFailed);
1669             return false;
1670         }
1671 
1672         ProcessSP process_sp = target_sp->GetProcessSP();
1673 
1674         if (!process_sp)
1675         {
1676             result.AppendError ("No current process; cannot handle signals until you have a valid process.\n");
1677             result.SetStatus (eReturnStatusFailed);
1678             return false;
1679         }
1680 
1681         int stop_action = -1;   // -1 means leave the current setting alone
1682         int pass_action = -1;   // -1 means leave the current setting alone
1683         int notify_action = -1; // -1 means leave the current setting alone
1684 
1685         if (! m_options.stop.empty()
1686             && ! VerifyCommandOptionValue (m_options.stop, stop_action))
1687         {
1688             result.AppendError ("Invalid argument for command option --stop; must be true or false.\n");
1689             result.SetStatus (eReturnStatusFailed);
1690             return false;
1691         }
1692 
1693         if (! m_options.notify.empty()
1694             && ! VerifyCommandOptionValue (m_options.notify, notify_action))
1695         {
1696             result.AppendError ("Invalid argument for command option --notify; must be true or false.\n");
1697             result.SetStatus (eReturnStatusFailed);
1698             return false;
1699         }
1700 
1701         if (! m_options.pass.empty()
1702             && ! VerifyCommandOptionValue (m_options.pass, pass_action))
1703         {
1704             result.AppendError ("Invalid argument for command option --pass; must be true or false.\n");
1705             result.SetStatus (eReturnStatusFailed);
1706             return false;
1707         }
1708 
1709         size_t num_args = signal_args.GetArgumentCount();
1710         UnixSignals &signals = process_sp->GetUnixSignals();
1711         int num_signals_set = 0;
1712 
1713         if (num_args > 0)
1714         {
1715             for (size_t i = 0; i < num_args; ++i)
1716             {
1717                 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
1718                 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
1719                 {
1720                     // Casting the actions as bools here should be okay, because VerifyCommandOptionValue guarantees
1721                     // the value is either 0 or 1.
1722                     if (stop_action != -1)
1723                         signals.SetShouldStop (signo, (bool) stop_action);
1724                     if (pass_action != -1)
1725                     {
1726                         bool suppress = ! ((bool) pass_action);
1727                         signals.SetShouldSuppress (signo, suppress);
1728                     }
1729                     if (notify_action != -1)
1730                         signals.SetShouldNotify (signo, (bool) notify_action);
1731                     ++num_signals_set;
1732                 }
1733                 else
1734                 {
1735                     result.AppendErrorWithFormat ("Invalid signal name '%s'\n", signal_args.GetArgumentAtIndex (i));
1736                 }
1737             }
1738         }
1739         else
1740         {
1741             // No signal specified, if any command options were specified, update ALL signals.
1742             if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1))
1743             {
1744                 if (m_interpreter.Confirm ("Do you really want to update all the signals?", false))
1745                 {
1746                     int32_t signo = signals.GetFirstSignalNumber();
1747                     while (signo != LLDB_INVALID_SIGNAL_NUMBER)
1748                     {
1749                         if (notify_action != -1)
1750                             signals.SetShouldNotify (signo, (bool) notify_action);
1751                         if (stop_action != -1)
1752                             signals.SetShouldStop (signo, (bool) stop_action);
1753                         if (pass_action != -1)
1754                         {
1755                             bool suppress = ! ((bool) pass_action);
1756                             signals.SetShouldSuppress (signo, suppress);
1757                         }
1758                         signo = signals.GetNextSignalNumber (signo);
1759                     }
1760                 }
1761             }
1762         }
1763 
1764         PrintSignalInformation (result.GetOutputStream(), signal_args, num_signals_set, signals);
1765 
1766         if (num_signals_set > 0)
1767             result.SetStatus (eReturnStatusSuccessFinishNoResult);
1768         else
1769             result.SetStatus (eReturnStatusFailed);
1770 
1771         return result.Succeeded();
1772     }
1773 
1774     CommandOptions m_options;
1775 };
1776 
1777 OptionDefinition
1778 CommandObjectProcessHandle::CommandOptions::g_option_table[] =
1779 {
1780 { 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." },
1781 { 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." },
1782 { LLDB_OPT_SET_1, false, "pass",  'p', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." },
1783 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1784 };
1785 
1786 //-------------------------------------------------------------------------
1787 // CommandObjectMultiwordProcess
1788 //-------------------------------------------------------------------------
1789 
1790 CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter &interpreter) :
1791     CommandObjectMultiword (interpreter,
1792                             "process",
1793                             "A set of commands for operating on a process.",
1794                             "process <subcommand> [<subcommand-options>]")
1795 {
1796     LoadSubCommand ("attach",      CommandObjectSP (new CommandObjectProcessAttach    (interpreter)));
1797     LoadSubCommand ("launch",      CommandObjectSP (new CommandObjectProcessLaunch    (interpreter)));
1798     LoadSubCommand ("continue",    CommandObjectSP (new CommandObjectProcessContinue  (interpreter)));
1799     LoadSubCommand ("connect",     CommandObjectSP (new CommandObjectProcessConnect   (interpreter)));
1800     LoadSubCommand ("detach",      CommandObjectSP (new CommandObjectProcessDetach    (interpreter)));
1801     LoadSubCommand ("load",        CommandObjectSP (new CommandObjectProcessLoad      (interpreter)));
1802     LoadSubCommand ("unload",      CommandObjectSP (new CommandObjectProcessUnload    (interpreter)));
1803     LoadSubCommand ("signal",      CommandObjectSP (new CommandObjectProcessSignal    (interpreter)));
1804     LoadSubCommand ("handle",      CommandObjectSP (new CommandObjectProcessHandle    (interpreter)));
1805     LoadSubCommand ("status",      CommandObjectSP (new CommandObjectProcessStatus    (interpreter)));
1806     LoadSubCommand ("interrupt",   CommandObjectSP (new CommandObjectProcessInterrupt (interpreter)));
1807     LoadSubCommand ("kill",        CommandObjectSP (new CommandObjectProcessKill      (interpreter)));
1808     LoadSubCommand ("plugin",      CommandObjectSP (new CommandObjectProcessPlugin    (interpreter)));
1809 }
1810 
1811 CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess ()
1812 {
1813 }
1814 
1815