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