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