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