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