1dda28197Spatrick //===-- CommandObjectProcess.cpp ------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "CommandObjectProcess.h"
10*be691f3bSpatrick #include "CommandObjectTrace.h"
11*be691f3bSpatrick #include "CommandOptionsProcessLaunch.h"
12061da546Spatrick #include "lldb/Breakpoint/Breakpoint.h"
13061da546Spatrick #include "lldb/Breakpoint/BreakpointLocation.h"
14061da546Spatrick #include "lldb/Breakpoint/BreakpointSite.h"
15061da546Spatrick #include "lldb/Core/Module.h"
16061da546Spatrick #include "lldb/Core/PluginManager.h"
17061da546Spatrick #include "lldb/Host/OptionParser.h"
18061da546Spatrick #include "lldb/Interpreter/CommandInterpreter.h"
19061da546Spatrick #include "lldb/Interpreter/CommandReturnObject.h"
20061da546Spatrick #include "lldb/Interpreter/OptionArgParser.h"
21*be691f3bSpatrick #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"
22061da546Spatrick #include "lldb/Interpreter/Options.h"
23061da546Spatrick #include "lldb/Target/Platform.h"
24061da546Spatrick #include "lldb/Target/Process.h"
25061da546Spatrick #include "lldb/Target/StopInfo.h"
26061da546Spatrick #include "lldb/Target/Target.h"
27061da546Spatrick #include "lldb/Target/Thread.h"
28061da546Spatrick #include "lldb/Target/UnixSignals.h"
29061da546Spatrick #include "lldb/Utility/Args.h"
30061da546Spatrick #include "lldb/Utility/State.h"
31061da546Spatrick 
32*be691f3bSpatrick #include <bitset>
33*be691f3bSpatrick 
34061da546Spatrick using namespace lldb;
35061da546Spatrick using namespace lldb_private;
36061da546Spatrick 
37061da546Spatrick class CommandObjectProcessLaunchOrAttach : public CommandObjectParsed {
38061da546Spatrick public:
39061da546Spatrick   CommandObjectProcessLaunchOrAttach(CommandInterpreter &interpreter,
40061da546Spatrick                                      const char *name, const char *help,
41061da546Spatrick                                      const char *syntax, uint32_t flags,
42061da546Spatrick                                      const char *new_process_action)
43061da546Spatrick       : CommandObjectParsed(interpreter, name, help, syntax, flags),
44061da546Spatrick         m_new_process_action(new_process_action) {}
45061da546Spatrick 
46061da546Spatrick   ~CommandObjectProcessLaunchOrAttach() override = default;
47061da546Spatrick 
48061da546Spatrick protected:
49061da546Spatrick   bool StopProcessIfNecessary(Process *process, StateType &state,
50061da546Spatrick                               CommandReturnObject &result) {
51061da546Spatrick     state = eStateInvalid;
52061da546Spatrick     if (process) {
53061da546Spatrick       state = process->GetState();
54061da546Spatrick 
55061da546Spatrick       if (process->IsAlive() && state != eStateConnected) {
56*be691f3bSpatrick         std::string message;
57061da546Spatrick         if (process->GetState() == eStateAttaching)
58*be691f3bSpatrick           message =
59*be691f3bSpatrick               llvm::formatv("There is a pending attach, abort it and {0}?",
60*be691f3bSpatrick                             m_new_process_action);
61061da546Spatrick         else if (process->GetShouldDetach())
62*be691f3bSpatrick           message = llvm::formatv(
63*be691f3bSpatrick               "There is a running process, detach from it and {0}?",
64*be691f3bSpatrick               m_new_process_action);
65061da546Spatrick         else
66*be691f3bSpatrick           message =
67*be691f3bSpatrick               llvm::formatv("There is a running process, kill it and {0}?",
68*be691f3bSpatrick                             m_new_process_action);
69061da546Spatrick 
70061da546Spatrick         if (!m_interpreter.Confirm(message, true)) {
71061da546Spatrick           result.SetStatus(eReturnStatusFailed);
72061da546Spatrick           return false;
73061da546Spatrick         } else {
74061da546Spatrick           if (process->GetShouldDetach()) {
75061da546Spatrick             bool keep_stopped = false;
76061da546Spatrick             Status detach_error(process->Detach(keep_stopped));
77061da546Spatrick             if (detach_error.Success()) {
78061da546Spatrick               result.SetStatus(eReturnStatusSuccessFinishResult);
79061da546Spatrick               process = nullptr;
80061da546Spatrick             } else {
81061da546Spatrick               result.AppendErrorWithFormat(
82061da546Spatrick                   "Failed to detach from process: %s\n",
83061da546Spatrick                   detach_error.AsCString());
84061da546Spatrick             }
85061da546Spatrick           } else {
86061da546Spatrick             Status destroy_error(process->Destroy(false));
87061da546Spatrick             if (destroy_error.Success()) {
88061da546Spatrick               result.SetStatus(eReturnStatusSuccessFinishResult);
89061da546Spatrick               process = nullptr;
90061da546Spatrick             } else {
91061da546Spatrick               result.AppendErrorWithFormat("Failed to kill process: %s\n",
92061da546Spatrick                                            destroy_error.AsCString());
93061da546Spatrick             }
94061da546Spatrick           }
95061da546Spatrick         }
96061da546Spatrick       }
97061da546Spatrick     }
98061da546Spatrick     return result.Succeeded();
99061da546Spatrick   }
100061da546Spatrick 
101061da546Spatrick   std::string m_new_process_action;
102061da546Spatrick };
103061da546Spatrick 
104061da546Spatrick // CommandObjectProcessLaunch
105061da546Spatrick #pragma mark CommandObjectProcessLaunch
106061da546Spatrick class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach {
107061da546Spatrick public:
108061da546Spatrick   CommandObjectProcessLaunch(CommandInterpreter &interpreter)
109061da546Spatrick       : CommandObjectProcessLaunchOrAttach(
110061da546Spatrick             interpreter, "process launch",
111061da546Spatrick             "Launch the executable in the debugger.", nullptr,
112061da546Spatrick             eCommandRequiresTarget, "restart"),
113*be691f3bSpatrick         m_options(),
114*be691f3bSpatrick         m_class_options("scripted process", true, 'C', 'k', 'v', 0),
115*be691f3bSpatrick         m_all_options() {
116*be691f3bSpatrick     m_all_options.Append(&m_options);
117*be691f3bSpatrick     m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2,
118*be691f3bSpatrick                          LLDB_OPT_SET_ALL);
119*be691f3bSpatrick     m_all_options.Finalize();
120*be691f3bSpatrick 
121061da546Spatrick     CommandArgumentEntry arg;
122061da546Spatrick     CommandArgumentData run_args_arg;
123061da546Spatrick 
124061da546Spatrick     // Define the first (and only) variant of this arg.
125061da546Spatrick     run_args_arg.arg_type = eArgTypeRunArgs;
126061da546Spatrick     run_args_arg.arg_repetition = eArgRepeatOptional;
127061da546Spatrick 
128061da546Spatrick     // There is only one variant this argument could be; put it into the
129061da546Spatrick     // argument entry.
130061da546Spatrick     arg.push_back(run_args_arg);
131061da546Spatrick 
132061da546Spatrick     // Push the data for the first argument into the m_arguments vector.
133061da546Spatrick     m_arguments.push_back(arg);
134061da546Spatrick   }
135061da546Spatrick 
136061da546Spatrick   ~CommandObjectProcessLaunch() override = default;
137061da546Spatrick 
138061da546Spatrick   void
139061da546Spatrick   HandleArgumentCompletion(CompletionRequest &request,
140061da546Spatrick                            OptionElementVector &opt_element_vector) override {
141061da546Spatrick 
142061da546Spatrick     CommandCompletions::InvokeCommonCompletionCallbacks(
143061da546Spatrick         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
144061da546Spatrick         request, nullptr);
145061da546Spatrick   }
146061da546Spatrick 
147*be691f3bSpatrick   Options *GetOptions() override { return &m_all_options; }
148061da546Spatrick 
149061da546Spatrick   const char *GetRepeatCommand(Args &current_command_args,
150061da546Spatrick                                uint32_t index) override {
151061da546Spatrick     // No repeat for "process launch"...
152061da546Spatrick     return "";
153061da546Spatrick   }
154061da546Spatrick 
155061da546Spatrick protected:
156061da546Spatrick   bool DoExecute(Args &launch_args, CommandReturnObject &result) override {
157061da546Spatrick     Debugger &debugger = GetDebugger();
158061da546Spatrick     Target *target = debugger.GetSelectedTarget().get();
159061da546Spatrick     // If our listener is nullptr, users aren't allows to launch
160061da546Spatrick     ModuleSP exe_module_sp = target->GetExecutableModule();
161061da546Spatrick 
162061da546Spatrick     if (exe_module_sp == nullptr) {
163061da546Spatrick       result.AppendError("no file in target, create a debug target using the "
164061da546Spatrick                          "'target create' command");
165061da546Spatrick       return false;
166061da546Spatrick     }
167061da546Spatrick 
168061da546Spatrick     StateType state = eStateInvalid;
169061da546Spatrick 
170061da546Spatrick     if (!StopProcessIfNecessary(m_exe_ctx.GetProcessPtr(), state, result))
171061da546Spatrick       return false;
172061da546Spatrick 
173061da546Spatrick     llvm::StringRef target_settings_argv0 = target->GetArg0();
174061da546Spatrick 
175061da546Spatrick     // Determine whether we will disable ASLR or leave it in the default state
176061da546Spatrick     // (i.e. enabled if the platform supports it). First check if the process
177061da546Spatrick     // launch options explicitly turn on/off
178061da546Spatrick     // disabling ASLR.  If so, use that setting;
179061da546Spatrick     // otherwise, use the 'settings target.disable-aslr' setting.
180061da546Spatrick     bool disable_aslr = false;
181061da546Spatrick     if (m_options.disable_aslr != eLazyBoolCalculate) {
182061da546Spatrick       // The user specified an explicit setting on the process launch line.
183061da546Spatrick       // Use it.
184061da546Spatrick       disable_aslr = (m_options.disable_aslr == eLazyBoolYes);
185061da546Spatrick     } else {
186061da546Spatrick       // The user did not explicitly specify whether to disable ASLR.  Fall
187061da546Spatrick       // back to the target.disable-aslr setting.
188061da546Spatrick       disable_aslr = target->GetDisableASLR();
189061da546Spatrick     }
190061da546Spatrick 
191*be691f3bSpatrick     if (!m_class_options.GetName().empty()) {
192*be691f3bSpatrick       m_options.launch_info.SetProcessPluginName("ScriptedProcess");
193*be691f3bSpatrick       m_options.launch_info.SetScriptedProcessClassName(
194*be691f3bSpatrick           m_class_options.GetName());
195*be691f3bSpatrick       m_options.launch_info.SetScriptedProcessDictionarySP(
196*be691f3bSpatrick           m_class_options.GetStructuredData());
197*be691f3bSpatrick       target->SetProcessLaunchInfo(m_options.launch_info);
198*be691f3bSpatrick     }
199*be691f3bSpatrick 
200061da546Spatrick     if (disable_aslr)
201061da546Spatrick       m_options.launch_info.GetFlags().Set(eLaunchFlagDisableASLR);
202061da546Spatrick     else
203061da546Spatrick       m_options.launch_info.GetFlags().Clear(eLaunchFlagDisableASLR);
204061da546Spatrick 
205*be691f3bSpatrick     if (target->GetInheritTCC())
206*be691f3bSpatrick       m_options.launch_info.GetFlags().Set(eLaunchFlagInheritTCCFromParent);
207*be691f3bSpatrick 
208061da546Spatrick     if (target->GetDetachOnError())
209061da546Spatrick       m_options.launch_info.GetFlags().Set(eLaunchFlagDetachOnError);
210061da546Spatrick 
211061da546Spatrick     if (target->GetDisableSTDIO())
212061da546Spatrick       m_options.launch_info.GetFlags().Set(eLaunchFlagDisableSTDIO);
213061da546Spatrick 
214061da546Spatrick     // Merge the launch info environment with the target environment.
215061da546Spatrick     Environment target_env = target->GetEnvironment();
216061da546Spatrick     m_options.launch_info.GetEnvironment().insert(target_env.begin(),
217061da546Spatrick                                                   target_env.end());
218061da546Spatrick 
219061da546Spatrick     if (!target_settings_argv0.empty()) {
220061da546Spatrick       m_options.launch_info.GetArguments().AppendArgument(
221061da546Spatrick           target_settings_argv0);
222061da546Spatrick       m_options.launch_info.SetExecutableFile(
223061da546Spatrick           exe_module_sp->GetPlatformFileSpec(), false);
224061da546Spatrick     } else {
225061da546Spatrick       m_options.launch_info.SetExecutableFile(
226061da546Spatrick           exe_module_sp->GetPlatformFileSpec(), true);
227061da546Spatrick     }
228061da546Spatrick 
229061da546Spatrick     if (launch_args.GetArgumentCount() == 0) {
230061da546Spatrick       m_options.launch_info.GetArguments().AppendArguments(
231061da546Spatrick           target->GetProcessLaunchInfo().GetArguments());
232061da546Spatrick     } else {
233061da546Spatrick       m_options.launch_info.GetArguments().AppendArguments(launch_args);
234061da546Spatrick       // Save the arguments for subsequent runs in the current target.
235061da546Spatrick       target->SetRunArguments(launch_args);
236061da546Spatrick     }
237061da546Spatrick 
238061da546Spatrick     StreamString stream;
239061da546Spatrick     Status error = target->Launch(m_options.launch_info, &stream);
240061da546Spatrick 
241061da546Spatrick     if (error.Success()) {
242061da546Spatrick       ProcessSP process_sp(target->GetProcessSP());
243061da546Spatrick       if (process_sp) {
244061da546Spatrick         // There is a race condition where this thread will return up the call
245061da546Spatrick         // stack to the main command handler and show an (lldb) prompt before
246061da546Spatrick         // HandlePrivateEvent (from PrivateStateThread) has a chance to call
247061da546Spatrick         // PushProcessIOHandler().
248061da546Spatrick         process_sp->SyncIOHandler(0, std::chrono::seconds(2));
249061da546Spatrick 
250061da546Spatrick         llvm::StringRef data = stream.GetString();
251061da546Spatrick         if (!data.empty())
252061da546Spatrick           result.AppendMessage(data);
253061da546Spatrick         const char *archname =
254061da546Spatrick             exe_module_sp->GetArchitecture().GetArchitectureName();
255061da546Spatrick         result.AppendMessageWithFormat(
256061da546Spatrick             "Process %" PRIu64 " launched: '%s' (%s)\n", process_sp->GetID(),
257061da546Spatrick             exe_module_sp->GetFileSpec().GetPath().c_str(), archname);
258061da546Spatrick         result.SetStatus(eReturnStatusSuccessFinishResult);
259061da546Spatrick         result.SetDidChangeProcessState(true);
260061da546Spatrick       } else {
261061da546Spatrick         result.AppendError(
262061da546Spatrick             "no error returned from Target::Launch, and target has no process");
263061da546Spatrick       }
264061da546Spatrick     } else {
265061da546Spatrick       result.AppendError(error.AsCString());
266061da546Spatrick     }
267061da546Spatrick     return result.Succeeded();
268061da546Spatrick   }
269061da546Spatrick 
270*be691f3bSpatrick   CommandOptionsProcessLaunch m_options;
271*be691f3bSpatrick   OptionGroupPythonClassWithDict m_class_options;
272*be691f3bSpatrick   OptionGroupOptions m_all_options;
273061da546Spatrick };
274061da546Spatrick 
275061da546Spatrick #define LLDB_OPTIONS_process_attach
276061da546Spatrick #include "CommandOptions.inc"
277061da546Spatrick 
278061da546Spatrick #pragma mark CommandObjectProcessAttach
279061da546Spatrick class CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach {
280061da546Spatrick public:
281061da546Spatrick   class CommandOptions : public Options {
282061da546Spatrick   public:
283061da546Spatrick     CommandOptions() : Options() {
284061da546Spatrick       // Keep default values of all options in one place: OptionParsingStarting
285061da546Spatrick       // ()
286061da546Spatrick       OptionParsingStarting(nullptr);
287061da546Spatrick     }
288061da546Spatrick 
289061da546Spatrick     ~CommandOptions() override = default;
290061da546Spatrick 
291061da546Spatrick     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
292061da546Spatrick                           ExecutionContext *execution_context) override {
293061da546Spatrick       Status error;
294061da546Spatrick       const int short_option = m_getopt_table[option_idx].val;
295061da546Spatrick       switch (short_option) {
296061da546Spatrick       case 'c':
297061da546Spatrick         attach_info.SetContinueOnceAttached(true);
298061da546Spatrick         break;
299061da546Spatrick 
300061da546Spatrick       case 'p': {
301061da546Spatrick         lldb::pid_t pid;
302061da546Spatrick         if (option_arg.getAsInteger(0, pid)) {
303061da546Spatrick           error.SetErrorStringWithFormat("invalid process ID '%s'",
304061da546Spatrick                                          option_arg.str().c_str());
305061da546Spatrick         } else {
306061da546Spatrick           attach_info.SetProcessID(pid);
307061da546Spatrick         }
308061da546Spatrick       } break;
309061da546Spatrick 
310061da546Spatrick       case 'P':
311061da546Spatrick         attach_info.SetProcessPluginName(option_arg);
312061da546Spatrick         break;
313061da546Spatrick 
314061da546Spatrick       case 'n':
315061da546Spatrick         attach_info.GetExecutableFile().SetFile(option_arg,
316061da546Spatrick                                                 FileSpec::Style::native);
317061da546Spatrick         break;
318061da546Spatrick 
319061da546Spatrick       case 'w':
320061da546Spatrick         attach_info.SetWaitForLaunch(true);
321061da546Spatrick         break;
322061da546Spatrick 
323061da546Spatrick       case 'i':
324061da546Spatrick         attach_info.SetIgnoreExisting(false);
325061da546Spatrick         break;
326061da546Spatrick 
327061da546Spatrick       default:
328061da546Spatrick         llvm_unreachable("Unimplemented option");
329061da546Spatrick       }
330061da546Spatrick       return error;
331061da546Spatrick     }
332061da546Spatrick 
333061da546Spatrick     void OptionParsingStarting(ExecutionContext *execution_context) override {
334061da546Spatrick       attach_info.Clear();
335061da546Spatrick     }
336061da546Spatrick 
337061da546Spatrick     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
338061da546Spatrick       return llvm::makeArrayRef(g_process_attach_options);
339061da546Spatrick     }
340061da546Spatrick 
341061da546Spatrick     ProcessAttachInfo attach_info;
342061da546Spatrick   };
343061da546Spatrick 
344061da546Spatrick   CommandObjectProcessAttach(CommandInterpreter &interpreter)
345061da546Spatrick       : CommandObjectProcessLaunchOrAttach(
346061da546Spatrick             interpreter, "process attach", "Attach to a process.",
347061da546Spatrick             "process attach <cmd-options>", 0, "attach"),
348061da546Spatrick         m_options() {}
349061da546Spatrick 
350061da546Spatrick   ~CommandObjectProcessAttach() override = default;
351061da546Spatrick 
352061da546Spatrick   Options *GetOptions() override { return &m_options; }
353061da546Spatrick 
354061da546Spatrick protected:
355061da546Spatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
356061da546Spatrick     PlatformSP platform_sp(
357061da546Spatrick         GetDebugger().GetPlatformList().GetSelectedPlatform());
358061da546Spatrick 
359061da546Spatrick     Target *target = GetDebugger().GetSelectedTarget().get();
360061da546Spatrick     // N.B. The attach should be synchronous.  It doesn't help much to get the
361061da546Spatrick     // prompt back between initiating the attach and the target actually
362061da546Spatrick     // stopping.  So even if the interpreter is set to be asynchronous, we wait
363061da546Spatrick     // for the stop ourselves here.
364061da546Spatrick 
365061da546Spatrick     StateType state = eStateInvalid;
366061da546Spatrick     Process *process = m_exe_ctx.GetProcessPtr();
367061da546Spatrick 
368061da546Spatrick     if (!StopProcessIfNecessary(process, state, result))
369061da546Spatrick       return false;
370061da546Spatrick 
371061da546Spatrick     if (target == nullptr) {
372061da546Spatrick       // If there isn't a current target create one.
373061da546Spatrick       TargetSP new_target_sp;
374061da546Spatrick       Status error;
375061da546Spatrick 
376061da546Spatrick       error = GetDebugger().GetTargetList().CreateTarget(
377061da546Spatrick           GetDebugger(), "", "", eLoadDependentsNo,
378061da546Spatrick           nullptr, // No platform options
379061da546Spatrick           new_target_sp);
380061da546Spatrick       target = new_target_sp.get();
381061da546Spatrick       if (target == nullptr || error.Fail()) {
382061da546Spatrick         result.AppendError(error.AsCString("Error creating target"));
383061da546Spatrick         return false;
384061da546Spatrick       }
385061da546Spatrick     }
386061da546Spatrick 
387061da546Spatrick     // Record the old executable module, we want to issue a warning if the
388061da546Spatrick     // process of attaching changed the current executable (like somebody said
389061da546Spatrick     // "file foo" then attached to a PID whose executable was bar.)
390061da546Spatrick 
391061da546Spatrick     ModuleSP old_exec_module_sp = target->GetExecutableModule();
392061da546Spatrick     ArchSpec old_arch_spec = target->GetArchitecture();
393061da546Spatrick 
394061da546Spatrick     if (command.GetArgumentCount()) {
395061da546Spatrick       result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: %s\n",
396061da546Spatrick                                    m_cmd_name.c_str(), m_cmd_syntax.c_str());
397061da546Spatrick       return false;
398061da546Spatrick     }
399061da546Spatrick 
400061da546Spatrick     StreamString stream;
401061da546Spatrick     const auto error = target->Attach(m_options.attach_info, &stream);
402061da546Spatrick     if (error.Success()) {
403061da546Spatrick       ProcessSP process_sp(target->GetProcessSP());
404061da546Spatrick       if (process_sp) {
405061da546Spatrick         result.AppendMessage(stream.GetString());
406061da546Spatrick         result.SetStatus(eReturnStatusSuccessFinishNoResult);
407061da546Spatrick         result.SetDidChangeProcessState(true);
408061da546Spatrick       } else {
409061da546Spatrick         result.AppendError(
410061da546Spatrick             "no error returned from Target::Attach, and target has no process");
411061da546Spatrick       }
412061da546Spatrick     } else {
413061da546Spatrick       result.AppendErrorWithFormat("attach failed: %s\n", error.AsCString());
414061da546Spatrick     }
415061da546Spatrick 
416061da546Spatrick     if (!result.Succeeded())
417061da546Spatrick       return false;
418061da546Spatrick 
419061da546Spatrick     // Okay, we're done.  Last step is to warn if the executable module has
420061da546Spatrick     // changed:
421061da546Spatrick     char new_path[PATH_MAX];
422061da546Spatrick     ModuleSP new_exec_module_sp(target->GetExecutableModule());
423061da546Spatrick     if (!old_exec_module_sp) {
424061da546Spatrick       // We might not have a module if we attached to a raw pid...
425061da546Spatrick       if (new_exec_module_sp) {
426061da546Spatrick         new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX);
427061da546Spatrick         result.AppendMessageWithFormat("Executable module set to \"%s\".\n",
428061da546Spatrick                                        new_path);
429061da546Spatrick       }
430061da546Spatrick     } else if (old_exec_module_sp->GetFileSpec() !=
431061da546Spatrick                new_exec_module_sp->GetFileSpec()) {
432061da546Spatrick       char old_path[PATH_MAX];
433061da546Spatrick 
434061da546Spatrick       old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX);
435061da546Spatrick       new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX);
436061da546Spatrick 
437061da546Spatrick       result.AppendWarningWithFormat(
438061da546Spatrick           "Executable module changed from \"%s\" to \"%s\".\n", old_path,
439061da546Spatrick           new_path);
440061da546Spatrick     }
441061da546Spatrick 
442061da546Spatrick     if (!old_arch_spec.IsValid()) {
443061da546Spatrick       result.AppendMessageWithFormat(
444061da546Spatrick           "Architecture set to: %s.\n",
445061da546Spatrick           target->GetArchitecture().GetTriple().getTriple().c_str());
446061da546Spatrick     } else if (!old_arch_spec.IsExactMatch(target->GetArchitecture())) {
447061da546Spatrick       result.AppendWarningWithFormat(
448061da546Spatrick           "Architecture changed from %s to %s.\n",
449061da546Spatrick           old_arch_spec.GetTriple().getTriple().c_str(),
450061da546Spatrick           target->GetArchitecture().GetTriple().getTriple().c_str());
451061da546Spatrick     }
452061da546Spatrick 
453061da546Spatrick     // This supports the use-case scenario of immediately continuing the
454061da546Spatrick     // process once attached.
455061da546Spatrick     if (m_options.attach_info.GetContinueOnceAttached())
456061da546Spatrick       m_interpreter.HandleCommand("process continue", eLazyBoolNo, result);
457061da546Spatrick 
458061da546Spatrick     return result.Succeeded();
459061da546Spatrick   }
460061da546Spatrick 
461061da546Spatrick   CommandOptions m_options;
462061da546Spatrick };
463061da546Spatrick 
464061da546Spatrick // CommandObjectProcessContinue
465061da546Spatrick 
466061da546Spatrick #define LLDB_OPTIONS_process_continue
467061da546Spatrick #include "CommandOptions.inc"
468061da546Spatrick 
469061da546Spatrick #pragma mark CommandObjectProcessContinue
470061da546Spatrick 
471061da546Spatrick class CommandObjectProcessContinue : public CommandObjectParsed {
472061da546Spatrick public:
473061da546Spatrick   CommandObjectProcessContinue(CommandInterpreter &interpreter)
474061da546Spatrick       : CommandObjectParsed(
475061da546Spatrick             interpreter, "process continue",
476061da546Spatrick             "Continue execution of all threads in the current process.",
477061da546Spatrick             "process continue",
478061da546Spatrick             eCommandRequiresProcess | eCommandTryTargetAPILock |
479061da546Spatrick                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused),
480061da546Spatrick         m_options() {}
481061da546Spatrick 
482061da546Spatrick   ~CommandObjectProcessContinue() override = default;
483061da546Spatrick 
484061da546Spatrick protected:
485061da546Spatrick   class CommandOptions : public Options {
486061da546Spatrick   public:
487061da546Spatrick     CommandOptions() : Options() {
488061da546Spatrick       // Keep default values of all options in one place: OptionParsingStarting
489061da546Spatrick       // ()
490061da546Spatrick       OptionParsingStarting(nullptr);
491061da546Spatrick     }
492061da546Spatrick 
493061da546Spatrick     ~CommandOptions() override = default;
494061da546Spatrick 
495061da546Spatrick     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
496061da546Spatrick                           ExecutionContext *execution_context) override {
497061da546Spatrick       Status error;
498061da546Spatrick       const int short_option = m_getopt_table[option_idx].val;
499061da546Spatrick       switch (short_option) {
500061da546Spatrick       case 'i':
501061da546Spatrick         if (option_arg.getAsInteger(0, m_ignore))
502061da546Spatrick           error.SetErrorStringWithFormat(
503061da546Spatrick               "invalid value for ignore option: \"%s\", should be a number.",
504061da546Spatrick               option_arg.str().c_str());
505061da546Spatrick         break;
506061da546Spatrick 
507061da546Spatrick       default:
508061da546Spatrick         llvm_unreachable("Unimplemented option");
509061da546Spatrick       }
510061da546Spatrick       return error;
511061da546Spatrick     }
512061da546Spatrick 
513061da546Spatrick     void OptionParsingStarting(ExecutionContext *execution_context) override {
514061da546Spatrick       m_ignore = 0;
515061da546Spatrick     }
516061da546Spatrick 
517061da546Spatrick     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
518061da546Spatrick       return llvm::makeArrayRef(g_process_continue_options);
519061da546Spatrick     }
520061da546Spatrick 
521061da546Spatrick     uint32_t m_ignore;
522061da546Spatrick   };
523061da546Spatrick 
524061da546Spatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
525061da546Spatrick     Process *process = m_exe_ctx.GetProcessPtr();
526061da546Spatrick     bool synchronous_execution = m_interpreter.GetSynchronous();
527061da546Spatrick     StateType state = process->GetState();
528061da546Spatrick     if (state == eStateStopped) {
529061da546Spatrick       if (command.GetArgumentCount() != 0) {
530061da546Spatrick         result.AppendErrorWithFormat(
531061da546Spatrick             "The '%s' command does not take any arguments.\n",
532061da546Spatrick             m_cmd_name.c_str());
533061da546Spatrick         return false;
534061da546Spatrick       }
535061da546Spatrick 
536061da546Spatrick       if (m_options.m_ignore > 0) {
537061da546Spatrick         ThreadSP sel_thread_sp(GetDefaultThread()->shared_from_this());
538061da546Spatrick         if (sel_thread_sp) {
539061da546Spatrick           StopInfoSP stop_info_sp = sel_thread_sp->GetStopInfo();
540061da546Spatrick           if (stop_info_sp &&
541061da546Spatrick               stop_info_sp->GetStopReason() == eStopReasonBreakpoint) {
542061da546Spatrick             lldb::break_id_t bp_site_id =
543061da546Spatrick                 (lldb::break_id_t)stop_info_sp->GetValue();
544061da546Spatrick             BreakpointSiteSP bp_site_sp(
545061da546Spatrick                 process->GetBreakpointSiteList().FindByID(bp_site_id));
546061da546Spatrick             if (bp_site_sp) {
547061da546Spatrick               const size_t num_owners = bp_site_sp->GetNumberOfOwners();
548061da546Spatrick               for (size_t i = 0; i < num_owners; i++) {
549061da546Spatrick                 Breakpoint &bp_ref =
550061da546Spatrick                     bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint();
551061da546Spatrick                 if (!bp_ref.IsInternal()) {
552061da546Spatrick                   bp_ref.SetIgnoreCount(m_options.m_ignore);
553061da546Spatrick                 }
554061da546Spatrick               }
555061da546Spatrick             }
556061da546Spatrick           }
557061da546Spatrick         }
558061da546Spatrick       }
559061da546Spatrick 
560061da546Spatrick       { // Scope for thread list mutex:
561061da546Spatrick         std::lock_guard<std::recursive_mutex> guard(
562061da546Spatrick             process->GetThreadList().GetMutex());
563061da546Spatrick         const uint32_t num_threads = process->GetThreadList().GetSize();
564061da546Spatrick 
565061da546Spatrick         // Set the actions that the threads should each take when resuming
566061da546Spatrick         for (uint32_t idx = 0; idx < num_threads; ++idx) {
567061da546Spatrick           const bool override_suspend = false;
568061da546Spatrick           process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState(
569061da546Spatrick               eStateRunning, override_suspend);
570061da546Spatrick         }
571061da546Spatrick       }
572061da546Spatrick 
573061da546Spatrick       const uint32_t iohandler_id = process->GetIOHandlerID();
574061da546Spatrick 
575061da546Spatrick       StreamString stream;
576061da546Spatrick       Status error;
577061da546Spatrick       if (synchronous_execution)
578061da546Spatrick         error = process->ResumeSynchronous(&stream);
579061da546Spatrick       else
580061da546Spatrick         error = process->Resume();
581061da546Spatrick 
582061da546Spatrick       if (error.Success()) {
583061da546Spatrick         // There is a race condition where this thread will return up the call
584061da546Spatrick         // stack to the main command handler and show an (lldb) prompt before
585061da546Spatrick         // HandlePrivateEvent (from PrivateStateThread) has a chance to call
586061da546Spatrick         // PushProcessIOHandler().
587061da546Spatrick         process->SyncIOHandler(iohandler_id, std::chrono::seconds(2));
588061da546Spatrick 
589061da546Spatrick         result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n",
590061da546Spatrick                                        process->GetID());
591061da546Spatrick         if (synchronous_execution) {
592061da546Spatrick           // If any state changed events had anything to say, add that to the
593061da546Spatrick           // result
594061da546Spatrick           result.AppendMessage(stream.GetString());
595061da546Spatrick 
596061da546Spatrick           result.SetDidChangeProcessState(true);
597061da546Spatrick           result.SetStatus(eReturnStatusSuccessFinishNoResult);
598061da546Spatrick         } else {
599061da546Spatrick           result.SetStatus(eReturnStatusSuccessContinuingNoResult);
600061da546Spatrick         }
601061da546Spatrick       } else {
602061da546Spatrick         result.AppendErrorWithFormat("Failed to resume process: %s.\n",
603061da546Spatrick                                      error.AsCString());
604061da546Spatrick       }
605061da546Spatrick     } else {
606061da546Spatrick       result.AppendErrorWithFormat(
607061da546Spatrick           "Process cannot be continued from its current state (%s).\n",
608061da546Spatrick           StateAsCString(state));
609061da546Spatrick     }
610061da546Spatrick     return result.Succeeded();
611061da546Spatrick   }
612061da546Spatrick 
613061da546Spatrick   Options *GetOptions() override { return &m_options; }
614061da546Spatrick 
615061da546Spatrick   CommandOptions m_options;
616061da546Spatrick };
617061da546Spatrick 
618061da546Spatrick // CommandObjectProcessDetach
619061da546Spatrick #define LLDB_OPTIONS_process_detach
620061da546Spatrick #include "CommandOptions.inc"
621061da546Spatrick 
622061da546Spatrick #pragma mark CommandObjectProcessDetach
623061da546Spatrick 
624061da546Spatrick class CommandObjectProcessDetach : public CommandObjectParsed {
625061da546Spatrick public:
626061da546Spatrick   class CommandOptions : public Options {
627061da546Spatrick   public:
628061da546Spatrick     CommandOptions() : Options() { OptionParsingStarting(nullptr); }
629061da546Spatrick 
630061da546Spatrick     ~CommandOptions() override = default;
631061da546Spatrick 
632061da546Spatrick     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
633061da546Spatrick                           ExecutionContext *execution_context) override {
634061da546Spatrick       Status error;
635061da546Spatrick       const int short_option = m_getopt_table[option_idx].val;
636061da546Spatrick 
637061da546Spatrick       switch (short_option) {
638061da546Spatrick       case 's':
639061da546Spatrick         bool tmp_result;
640061da546Spatrick         bool success;
641061da546Spatrick         tmp_result = OptionArgParser::ToBoolean(option_arg, false, &success);
642061da546Spatrick         if (!success)
643061da546Spatrick           error.SetErrorStringWithFormat("invalid boolean option: \"%s\"",
644061da546Spatrick                                          option_arg.str().c_str());
645061da546Spatrick         else {
646061da546Spatrick           if (tmp_result)
647061da546Spatrick             m_keep_stopped = eLazyBoolYes;
648061da546Spatrick           else
649061da546Spatrick             m_keep_stopped = eLazyBoolNo;
650061da546Spatrick         }
651061da546Spatrick         break;
652061da546Spatrick       default:
653061da546Spatrick         llvm_unreachable("Unimplemented option");
654061da546Spatrick       }
655061da546Spatrick       return error;
656061da546Spatrick     }
657061da546Spatrick 
658061da546Spatrick     void OptionParsingStarting(ExecutionContext *execution_context) override {
659061da546Spatrick       m_keep_stopped = eLazyBoolCalculate;
660061da546Spatrick     }
661061da546Spatrick 
662061da546Spatrick     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
663061da546Spatrick       return llvm::makeArrayRef(g_process_detach_options);
664061da546Spatrick     }
665061da546Spatrick 
666061da546Spatrick     // Instance variables to hold the values for command options.
667061da546Spatrick     LazyBool m_keep_stopped;
668061da546Spatrick   };
669061da546Spatrick 
670061da546Spatrick   CommandObjectProcessDetach(CommandInterpreter &interpreter)
671061da546Spatrick       : CommandObjectParsed(interpreter, "process detach",
672061da546Spatrick                             "Detach from the current target process.",
673061da546Spatrick                             "process detach",
674061da546Spatrick                             eCommandRequiresProcess | eCommandTryTargetAPILock |
675061da546Spatrick                                 eCommandProcessMustBeLaunched),
676061da546Spatrick         m_options() {}
677061da546Spatrick 
678061da546Spatrick   ~CommandObjectProcessDetach() override = default;
679061da546Spatrick 
680061da546Spatrick   Options *GetOptions() override { return &m_options; }
681061da546Spatrick 
682061da546Spatrick protected:
683061da546Spatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
684061da546Spatrick     Process *process = m_exe_ctx.GetProcessPtr();
685061da546Spatrick     // FIXME: This will be a Command Option:
686061da546Spatrick     bool keep_stopped;
687061da546Spatrick     if (m_options.m_keep_stopped == eLazyBoolCalculate) {
688061da546Spatrick       // Check the process default:
689061da546Spatrick       keep_stopped = process->GetDetachKeepsStopped();
690061da546Spatrick     } else if (m_options.m_keep_stopped == eLazyBoolYes)
691061da546Spatrick       keep_stopped = true;
692061da546Spatrick     else
693061da546Spatrick       keep_stopped = false;
694061da546Spatrick 
695061da546Spatrick     Status error(process->Detach(keep_stopped));
696061da546Spatrick     if (error.Success()) {
697061da546Spatrick       result.SetStatus(eReturnStatusSuccessFinishResult);
698061da546Spatrick     } else {
699061da546Spatrick       result.AppendErrorWithFormat("Detach failed: %s\n", error.AsCString());
700061da546Spatrick       return false;
701061da546Spatrick     }
702061da546Spatrick     return result.Succeeded();
703061da546Spatrick   }
704061da546Spatrick 
705061da546Spatrick   CommandOptions m_options;
706061da546Spatrick };
707061da546Spatrick 
708061da546Spatrick // CommandObjectProcessConnect
709061da546Spatrick #define LLDB_OPTIONS_process_connect
710061da546Spatrick #include "CommandOptions.inc"
711061da546Spatrick 
712061da546Spatrick #pragma mark CommandObjectProcessConnect
713061da546Spatrick 
714061da546Spatrick class CommandObjectProcessConnect : public CommandObjectParsed {
715061da546Spatrick public:
716061da546Spatrick   class CommandOptions : public Options {
717061da546Spatrick   public:
718061da546Spatrick     CommandOptions() : Options() {
719061da546Spatrick       // Keep default values of all options in one place: OptionParsingStarting
720061da546Spatrick       // ()
721061da546Spatrick       OptionParsingStarting(nullptr);
722061da546Spatrick     }
723061da546Spatrick 
724061da546Spatrick     ~CommandOptions() override = default;
725061da546Spatrick 
726061da546Spatrick     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
727061da546Spatrick                           ExecutionContext *execution_context) override {
728061da546Spatrick       Status error;
729061da546Spatrick       const int short_option = m_getopt_table[option_idx].val;
730061da546Spatrick 
731061da546Spatrick       switch (short_option) {
732061da546Spatrick       case 'p':
733dda28197Spatrick         plugin_name.assign(std::string(option_arg));
734061da546Spatrick         break;
735061da546Spatrick 
736061da546Spatrick       default:
737061da546Spatrick         llvm_unreachable("Unimplemented option");
738061da546Spatrick       }
739061da546Spatrick       return error;
740061da546Spatrick     }
741061da546Spatrick 
742061da546Spatrick     void OptionParsingStarting(ExecutionContext *execution_context) override {
743061da546Spatrick       plugin_name.clear();
744061da546Spatrick     }
745061da546Spatrick 
746061da546Spatrick     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
747061da546Spatrick       return llvm::makeArrayRef(g_process_connect_options);
748061da546Spatrick     }
749061da546Spatrick 
750061da546Spatrick     // Instance variables to hold the values for command options.
751061da546Spatrick 
752061da546Spatrick     std::string plugin_name;
753061da546Spatrick   };
754061da546Spatrick 
755061da546Spatrick   CommandObjectProcessConnect(CommandInterpreter &interpreter)
756061da546Spatrick       : CommandObjectParsed(interpreter, "process connect",
757061da546Spatrick                             "Connect to a remote debug service.",
758061da546Spatrick                             "process connect <remote-url>", 0),
759061da546Spatrick         m_options() {}
760061da546Spatrick 
761061da546Spatrick   ~CommandObjectProcessConnect() override = default;
762061da546Spatrick 
763061da546Spatrick   Options *GetOptions() override { return &m_options; }
764061da546Spatrick 
765061da546Spatrick protected:
766061da546Spatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
767061da546Spatrick     if (command.GetArgumentCount() != 1) {
768061da546Spatrick       result.AppendErrorWithFormat(
769061da546Spatrick           "'%s' takes exactly one argument:\nUsage: %s\n", m_cmd_name.c_str(),
770061da546Spatrick           m_cmd_syntax.c_str());
771061da546Spatrick       return false;
772061da546Spatrick     }
773061da546Spatrick 
774061da546Spatrick     Process *process = m_exe_ctx.GetProcessPtr();
775061da546Spatrick     if (process && process->IsAlive()) {
776061da546Spatrick       result.AppendErrorWithFormat(
777061da546Spatrick           "Process %" PRIu64
778061da546Spatrick           " is currently being debugged, kill the process before connecting.\n",
779061da546Spatrick           process->GetID());
780061da546Spatrick       return false;
781061da546Spatrick     }
782061da546Spatrick 
783061da546Spatrick     const char *plugin_name = nullptr;
784061da546Spatrick     if (!m_options.plugin_name.empty())
785061da546Spatrick       plugin_name = m_options.plugin_name.c_str();
786061da546Spatrick 
787061da546Spatrick     Status error;
788061da546Spatrick     Debugger &debugger = GetDebugger();
789061da546Spatrick     PlatformSP platform_sp = m_interpreter.GetPlatform(true);
790dda28197Spatrick     ProcessSP process_sp =
791dda28197Spatrick         debugger.GetAsyncExecution()
792dda28197Spatrick             ? platform_sp->ConnectProcess(
793061da546Spatrick                   command.GetArgumentAtIndex(0), plugin_name, debugger,
794dda28197Spatrick                   debugger.GetSelectedTarget().get(), error)
795dda28197Spatrick             : platform_sp->ConnectProcessSynchronous(
796dda28197Spatrick                   command.GetArgumentAtIndex(0), plugin_name, debugger,
797dda28197Spatrick                   result.GetOutputStream(), debugger.GetSelectedTarget().get(),
798dda28197Spatrick                   error);
799061da546Spatrick     if (error.Fail() || process_sp == nullptr) {
800061da546Spatrick       result.AppendError(error.AsCString("Error connecting to the process"));
801061da546Spatrick       return false;
802061da546Spatrick     }
803061da546Spatrick     return true;
804061da546Spatrick   }
805061da546Spatrick 
806061da546Spatrick   CommandOptions m_options;
807061da546Spatrick };
808061da546Spatrick 
809061da546Spatrick // CommandObjectProcessPlugin
810061da546Spatrick #pragma mark CommandObjectProcessPlugin
811061da546Spatrick 
812061da546Spatrick class CommandObjectProcessPlugin : public CommandObjectProxy {
813061da546Spatrick public:
814061da546Spatrick   CommandObjectProcessPlugin(CommandInterpreter &interpreter)
815061da546Spatrick       : CommandObjectProxy(
816061da546Spatrick             interpreter, "process plugin",
817061da546Spatrick             "Send a custom command to the current target process plug-in.",
818061da546Spatrick             "process plugin <args>", 0) {}
819061da546Spatrick 
820061da546Spatrick   ~CommandObjectProcessPlugin() override = default;
821061da546Spatrick 
822061da546Spatrick   CommandObject *GetProxyCommandObject() override {
823061da546Spatrick     Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
824061da546Spatrick     if (process)
825061da546Spatrick       return process->GetPluginCommandObject();
826061da546Spatrick     return nullptr;
827061da546Spatrick   }
828061da546Spatrick };
829061da546Spatrick 
830061da546Spatrick // CommandObjectProcessLoad
831061da546Spatrick #define LLDB_OPTIONS_process_load
832061da546Spatrick #include "CommandOptions.inc"
833061da546Spatrick 
834061da546Spatrick #pragma mark CommandObjectProcessLoad
835061da546Spatrick 
836061da546Spatrick class CommandObjectProcessLoad : public CommandObjectParsed {
837061da546Spatrick public:
838061da546Spatrick   class CommandOptions : public Options {
839061da546Spatrick   public:
840061da546Spatrick     CommandOptions() : Options() {
841061da546Spatrick       // Keep default values of all options in one place: OptionParsingStarting
842061da546Spatrick       // ()
843061da546Spatrick       OptionParsingStarting(nullptr);
844061da546Spatrick     }
845061da546Spatrick 
846061da546Spatrick     ~CommandOptions() override = default;
847061da546Spatrick 
848061da546Spatrick     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
849061da546Spatrick                           ExecutionContext *execution_context) override {
850061da546Spatrick       Status error;
851061da546Spatrick       const int short_option = m_getopt_table[option_idx].val;
852061da546Spatrick       switch (short_option) {
853061da546Spatrick       case 'i':
854061da546Spatrick         do_install = true;
855061da546Spatrick         if (!option_arg.empty())
856061da546Spatrick           install_path.SetFile(option_arg, FileSpec::Style::native);
857061da546Spatrick         break;
858061da546Spatrick       default:
859061da546Spatrick         llvm_unreachable("Unimplemented option");
860061da546Spatrick       }
861061da546Spatrick       return error;
862061da546Spatrick     }
863061da546Spatrick 
864061da546Spatrick     void OptionParsingStarting(ExecutionContext *execution_context) override {
865061da546Spatrick       do_install = false;
866061da546Spatrick       install_path.Clear();
867061da546Spatrick     }
868061da546Spatrick 
869061da546Spatrick     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
870061da546Spatrick       return llvm::makeArrayRef(g_process_load_options);
871061da546Spatrick     }
872061da546Spatrick 
873061da546Spatrick     // Instance variables to hold the values for command options.
874061da546Spatrick     bool do_install;
875061da546Spatrick     FileSpec install_path;
876061da546Spatrick   };
877061da546Spatrick 
878061da546Spatrick   CommandObjectProcessLoad(CommandInterpreter &interpreter)
879061da546Spatrick       : CommandObjectParsed(interpreter, "process load",
880061da546Spatrick                             "Load a shared library into the current process.",
881061da546Spatrick                             "process load <filename> [<filename> ...]",
882061da546Spatrick                             eCommandRequiresProcess | eCommandTryTargetAPILock |
883061da546Spatrick                                 eCommandProcessMustBeLaunched |
884061da546Spatrick                                 eCommandProcessMustBePaused),
885061da546Spatrick         m_options() {}
886061da546Spatrick 
887061da546Spatrick   ~CommandObjectProcessLoad() override = default;
888061da546Spatrick 
889*be691f3bSpatrick   void
890*be691f3bSpatrick   HandleArgumentCompletion(CompletionRequest &request,
891*be691f3bSpatrick                            OptionElementVector &opt_element_vector) override {
892*be691f3bSpatrick     if (!m_exe_ctx.HasProcessScope())
893*be691f3bSpatrick       return;
894*be691f3bSpatrick 
895*be691f3bSpatrick     CommandCompletions::InvokeCommonCompletionCallbacks(
896*be691f3bSpatrick         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
897*be691f3bSpatrick         request, nullptr);
898*be691f3bSpatrick   }
899*be691f3bSpatrick 
900061da546Spatrick   Options *GetOptions() override { return &m_options; }
901061da546Spatrick 
902061da546Spatrick protected:
903061da546Spatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
904061da546Spatrick     Process *process = m_exe_ctx.GetProcessPtr();
905061da546Spatrick 
906061da546Spatrick     for (auto &entry : command.entries()) {
907061da546Spatrick       Status error;
908061da546Spatrick       PlatformSP platform = process->GetTarget().GetPlatform();
909061da546Spatrick       llvm::StringRef image_path = entry.ref();
910061da546Spatrick       uint32_t image_token = LLDB_INVALID_IMAGE_TOKEN;
911061da546Spatrick 
912061da546Spatrick       if (!m_options.do_install) {
913061da546Spatrick         FileSpec image_spec(image_path);
914061da546Spatrick         platform->ResolveRemotePath(image_spec, image_spec);
915061da546Spatrick         image_token =
916061da546Spatrick             platform->LoadImage(process, FileSpec(), image_spec, error);
917061da546Spatrick       } else if (m_options.install_path) {
918061da546Spatrick         FileSpec image_spec(image_path);
919061da546Spatrick         FileSystem::Instance().Resolve(image_spec);
920061da546Spatrick         platform->ResolveRemotePath(m_options.install_path,
921061da546Spatrick                                     m_options.install_path);
922061da546Spatrick         image_token = platform->LoadImage(process, image_spec,
923061da546Spatrick                                           m_options.install_path, error);
924061da546Spatrick       } else {
925061da546Spatrick         FileSpec image_spec(image_path);
926061da546Spatrick         FileSystem::Instance().Resolve(image_spec);
927061da546Spatrick         image_token =
928061da546Spatrick             platform->LoadImage(process, image_spec, FileSpec(), error);
929061da546Spatrick       }
930061da546Spatrick 
931061da546Spatrick       if (image_token != LLDB_INVALID_IMAGE_TOKEN) {
932061da546Spatrick         result.AppendMessageWithFormat(
933061da546Spatrick             "Loading \"%s\"...ok\nImage %u loaded.\n", image_path.str().c_str(),
934061da546Spatrick             image_token);
935061da546Spatrick         result.SetStatus(eReturnStatusSuccessFinishResult);
936061da546Spatrick       } else {
937061da546Spatrick         result.AppendErrorWithFormat("failed to load '%s': %s",
938061da546Spatrick                                      image_path.str().c_str(),
939061da546Spatrick                                      error.AsCString());
940061da546Spatrick       }
941061da546Spatrick     }
942061da546Spatrick     return result.Succeeded();
943061da546Spatrick   }
944061da546Spatrick 
945061da546Spatrick   CommandOptions m_options;
946061da546Spatrick };
947061da546Spatrick 
948061da546Spatrick // CommandObjectProcessUnload
949061da546Spatrick #pragma mark CommandObjectProcessUnload
950061da546Spatrick 
951061da546Spatrick class CommandObjectProcessUnload : public CommandObjectParsed {
952061da546Spatrick public:
953061da546Spatrick   CommandObjectProcessUnload(CommandInterpreter &interpreter)
954061da546Spatrick       : CommandObjectParsed(
955061da546Spatrick             interpreter, "process unload",
956061da546Spatrick             "Unload a shared library from the current process using the index "
957061da546Spatrick             "returned by a previous call to \"process load\".",
958061da546Spatrick             "process unload <index>",
959061da546Spatrick             eCommandRequiresProcess | eCommandTryTargetAPILock |
960061da546Spatrick                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {}
961061da546Spatrick 
962061da546Spatrick   ~CommandObjectProcessUnload() override = default;
963061da546Spatrick 
964*be691f3bSpatrick   void
965*be691f3bSpatrick   HandleArgumentCompletion(CompletionRequest &request,
966*be691f3bSpatrick                            OptionElementVector &opt_element_vector) override {
967*be691f3bSpatrick 
968*be691f3bSpatrick     if (request.GetCursorIndex() || !m_exe_ctx.HasProcessScope())
969*be691f3bSpatrick       return;
970*be691f3bSpatrick 
971*be691f3bSpatrick     Process *process = m_exe_ctx.GetProcessPtr();
972*be691f3bSpatrick 
973*be691f3bSpatrick     const std::vector<lldb::addr_t> &tokens = process->GetImageTokens();
974*be691f3bSpatrick     const size_t token_num = tokens.size();
975*be691f3bSpatrick     for (size_t i = 0; i < token_num; ++i) {
976*be691f3bSpatrick       if (tokens[i] == LLDB_INVALID_IMAGE_TOKEN)
977*be691f3bSpatrick         continue;
978*be691f3bSpatrick       request.TryCompleteCurrentArg(std::to_string(i));
979*be691f3bSpatrick     }
980*be691f3bSpatrick   }
981*be691f3bSpatrick 
982061da546Spatrick protected:
983061da546Spatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
984061da546Spatrick     Process *process = m_exe_ctx.GetProcessPtr();
985061da546Spatrick 
986061da546Spatrick     for (auto &entry : command.entries()) {
987061da546Spatrick       uint32_t image_token;
988061da546Spatrick       if (entry.ref().getAsInteger(0, image_token)) {
989061da546Spatrick         result.AppendErrorWithFormat("invalid image index argument '%s'",
990061da546Spatrick                                      entry.ref().str().c_str());
991061da546Spatrick         break;
992061da546Spatrick       } else {
993061da546Spatrick         Status error(process->GetTarget().GetPlatform()->UnloadImage(
994061da546Spatrick             process, image_token));
995061da546Spatrick         if (error.Success()) {
996061da546Spatrick           result.AppendMessageWithFormat(
997061da546Spatrick               "Unloading shared library with index %u...ok\n", image_token);
998061da546Spatrick           result.SetStatus(eReturnStatusSuccessFinishResult);
999061da546Spatrick         } else {
1000061da546Spatrick           result.AppendErrorWithFormat("failed to unload image: %s",
1001061da546Spatrick                                        error.AsCString());
1002061da546Spatrick           break;
1003061da546Spatrick         }
1004061da546Spatrick       }
1005061da546Spatrick     }
1006061da546Spatrick     return result.Succeeded();
1007061da546Spatrick   }
1008061da546Spatrick };
1009061da546Spatrick 
1010061da546Spatrick // CommandObjectProcessSignal
1011061da546Spatrick #pragma mark CommandObjectProcessSignal
1012061da546Spatrick 
1013061da546Spatrick class CommandObjectProcessSignal : public CommandObjectParsed {
1014061da546Spatrick public:
1015061da546Spatrick   CommandObjectProcessSignal(CommandInterpreter &interpreter)
1016061da546Spatrick       : CommandObjectParsed(
1017061da546Spatrick             interpreter, "process signal",
1018061da546Spatrick             "Send a UNIX signal to the current target process.", nullptr,
1019061da546Spatrick             eCommandRequiresProcess | eCommandTryTargetAPILock) {
1020061da546Spatrick     CommandArgumentEntry arg;
1021061da546Spatrick     CommandArgumentData signal_arg;
1022061da546Spatrick 
1023061da546Spatrick     // Define the first (and only) variant of this arg.
1024061da546Spatrick     signal_arg.arg_type = eArgTypeUnixSignal;
1025061da546Spatrick     signal_arg.arg_repetition = eArgRepeatPlain;
1026061da546Spatrick 
1027061da546Spatrick     // There is only one variant this argument could be; put it into the
1028061da546Spatrick     // argument entry.
1029061da546Spatrick     arg.push_back(signal_arg);
1030061da546Spatrick 
1031061da546Spatrick     // Push the data for the first argument into the m_arguments vector.
1032061da546Spatrick     m_arguments.push_back(arg);
1033061da546Spatrick   }
1034061da546Spatrick 
1035061da546Spatrick   ~CommandObjectProcessSignal() override = default;
1036061da546Spatrick 
1037dda28197Spatrick   void
1038dda28197Spatrick   HandleArgumentCompletion(CompletionRequest &request,
1039dda28197Spatrick                            OptionElementVector &opt_element_vector) override {
1040dda28197Spatrick     if (!m_exe_ctx.HasProcessScope() || request.GetCursorIndex() != 0)
1041dda28197Spatrick       return;
1042dda28197Spatrick 
1043dda28197Spatrick     UnixSignalsSP signals = m_exe_ctx.GetProcessPtr()->GetUnixSignals();
1044dda28197Spatrick     int signo = signals->GetFirstSignalNumber();
1045dda28197Spatrick     while (signo != LLDB_INVALID_SIGNAL_NUMBER) {
1046*be691f3bSpatrick       request.TryCompleteCurrentArg(signals->GetSignalAsCString(signo));
1047dda28197Spatrick       signo = signals->GetNextSignalNumber(signo);
1048dda28197Spatrick     }
1049dda28197Spatrick   }
1050dda28197Spatrick 
1051061da546Spatrick protected:
1052061da546Spatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
1053061da546Spatrick     Process *process = m_exe_ctx.GetProcessPtr();
1054061da546Spatrick 
1055061da546Spatrick     if (command.GetArgumentCount() == 1) {
1056061da546Spatrick       int signo = LLDB_INVALID_SIGNAL_NUMBER;
1057061da546Spatrick 
1058061da546Spatrick       const char *signal_name = command.GetArgumentAtIndex(0);
1059dda28197Spatrick       if (::isxdigit(signal_name[0])) {
1060dda28197Spatrick         if (!llvm::to_integer(signal_name, signo))
1061dda28197Spatrick           signo = LLDB_INVALID_SIGNAL_NUMBER;
1062dda28197Spatrick       } else
1063061da546Spatrick         signo = process->GetUnixSignals()->GetSignalNumberFromName(signal_name);
1064061da546Spatrick 
1065061da546Spatrick       if (signo == LLDB_INVALID_SIGNAL_NUMBER) {
1066061da546Spatrick         result.AppendErrorWithFormat("Invalid signal argument '%s'.\n",
1067061da546Spatrick                                      command.GetArgumentAtIndex(0));
1068061da546Spatrick       } else {
1069061da546Spatrick         Status error(process->Signal(signo));
1070061da546Spatrick         if (error.Success()) {
1071061da546Spatrick           result.SetStatus(eReturnStatusSuccessFinishResult);
1072061da546Spatrick         } else {
1073061da546Spatrick           result.AppendErrorWithFormat("Failed to send signal %i: %s\n", signo,
1074061da546Spatrick                                        error.AsCString());
1075061da546Spatrick         }
1076061da546Spatrick       }
1077061da546Spatrick     } else {
1078061da546Spatrick       result.AppendErrorWithFormat(
1079061da546Spatrick           "'%s' takes exactly one signal number argument:\nUsage: %s\n",
1080061da546Spatrick           m_cmd_name.c_str(), m_cmd_syntax.c_str());
1081061da546Spatrick     }
1082061da546Spatrick     return result.Succeeded();
1083061da546Spatrick   }
1084061da546Spatrick };
1085061da546Spatrick 
1086061da546Spatrick // CommandObjectProcessInterrupt
1087061da546Spatrick #pragma mark CommandObjectProcessInterrupt
1088061da546Spatrick 
1089061da546Spatrick class CommandObjectProcessInterrupt : public CommandObjectParsed {
1090061da546Spatrick public:
1091061da546Spatrick   CommandObjectProcessInterrupt(CommandInterpreter &interpreter)
1092061da546Spatrick       : CommandObjectParsed(interpreter, "process interrupt",
1093061da546Spatrick                             "Interrupt the current target process.",
1094061da546Spatrick                             "process interrupt",
1095061da546Spatrick                             eCommandRequiresProcess | eCommandTryTargetAPILock |
1096061da546Spatrick                                 eCommandProcessMustBeLaunched) {}
1097061da546Spatrick 
1098061da546Spatrick   ~CommandObjectProcessInterrupt() override = default;
1099061da546Spatrick 
1100061da546Spatrick protected:
1101061da546Spatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
1102061da546Spatrick     Process *process = m_exe_ctx.GetProcessPtr();
1103061da546Spatrick     if (process == nullptr) {
1104061da546Spatrick       result.AppendError("no process to halt");
1105061da546Spatrick       return false;
1106061da546Spatrick     }
1107061da546Spatrick 
1108061da546Spatrick     if (command.GetArgumentCount() == 0) {
1109061da546Spatrick       bool clear_thread_plans = true;
1110061da546Spatrick       Status error(process->Halt(clear_thread_plans));
1111061da546Spatrick       if (error.Success()) {
1112061da546Spatrick         result.SetStatus(eReturnStatusSuccessFinishResult);
1113061da546Spatrick       } else {
1114061da546Spatrick         result.AppendErrorWithFormat("Failed to halt process: %s\n",
1115061da546Spatrick                                      error.AsCString());
1116061da546Spatrick       }
1117061da546Spatrick     } else {
1118061da546Spatrick       result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n",
1119061da546Spatrick                                    m_cmd_name.c_str(), m_cmd_syntax.c_str());
1120061da546Spatrick     }
1121061da546Spatrick     return result.Succeeded();
1122061da546Spatrick   }
1123061da546Spatrick };
1124061da546Spatrick 
1125061da546Spatrick // CommandObjectProcessKill
1126061da546Spatrick #pragma mark CommandObjectProcessKill
1127061da546Spatrick 
1128061da546Spatrick class CommandObjectProcessKill : public CommandObjectParsed {
1129061da546Spatrick public:
1130061da546Spatrick   CommandObjectProcessKill(CommandInterpreter &interpreter)
1131061da546Spatrick       : CommandObjectParsed(interpreter, "process kill",
1132061da546Spatrick                             "Terminate the current target process.",
1133061da546Spatrick                             "process kill",
1134061da546Spatrick                             eCommandRequiresProcess | eCommandTryTargetAPILock |
1135061da546Spatrick                                 eCommandProcessMustBeLaunched) {}
1136061da546Spatrick 
1137061da546Spatrick   ~CommandObjectProcessKill() override = default;
1138061da546Spatrick 
1139061da546Spatrick protected:
1140061da546Spatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
1141061da546Spatrick     Process *process = m_exe_ctx.GetProcessPtr();
1142061da546Spatrick     if (process == nullptr) {
1143061da546Spatrick       result.AppendError("no process to kill");
1144061da546Spatrick       return false;
1145061da546Spatrick     }
1146061da546Spatrick 
1147061da546Spatrick     if (command.GetArgumentCount() == 0) {
1148061da546Spatrick       Status error(process->Destroy(true));
1149061da546Spatrick       if (error.Success()) {
1150061da546Spatrick         result.SetStatus(eReturnStatusSuccessFinishResult);
1151061da546Spatrick       } else {
1152061da546Spatrick         result.AppendErrorWithFormat("Failed to kill process: %s\n",
1153061da546Spatrick                                      error.AsCString());
1154061da546Spatrick       }
1155061da546Spatrick     } else {
1156061da546Spatrick       result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n",
1157061da546Spatrick                                    m_cmd_name.c_str(), m_cmd_syntax.c_str());
1158061da546Spatrick     }
1159061da546Spatrick     return result.Succeeded();
1160061da546Spatrick   }
1161061da546Spatrick };
1162061da546Spatrick 
1163061da546Spatrick // CommandObjectProcessSaveCore
1164061da546Spatrick #pragma mark CommandObjectProcessSaveCore
1165061da546Spatrick 
1166*be691f3bSpatrick static constexpr OptionEnumValueElement g_corefile_save_style[] = {
1167*be691f3bSpatrick     {eSaveCoreFull, "full", "Create a core file with all memory saved"},
1168*be691f3bSpatrick     {eSaveCoreDirtyOnly, "modified-memory",
1169*be691f3bSpatrick      "Create a corefile with only modified memory saved"}};
1170*be691f3bSpatrick 
1171*be691f3bSpatrick static constexpr OptionEnumValues SaveCoreStyles() {
1172*be691f3bSpatrick   return OptionEnumValues(g_corefile_save_style);
1173*be691f3bSpatrick }
1174*be691f3bSpatrick 
1175*be691f3bSpatrick #define LLDB_OPTIONS_process_save_core
1176*be691f3bSpatrick #include "CommandOptions.inc"
1177*be691f3bSpatrick 
1178061da546Spatrick class CommandObjectProcessSaveCore : public CommandObjectParsed {
1179061da546Spatrick public:
1180061da546Spatrick   CommandObjectProcessSaveCore(CommandInterpreter &interpreter)
1181061da546Spatrick       : CommandObjectParsed(interpreter, "process save-core",
1182061da546Spatrick                             "Save the current process as a core file using an "
1183061da546Spatrick                             "appropriate file type.",
1184*be691f3bSpatrick                             "process save-core [-s corefile-style] FILE",
1185061da546Spatrick                             eCommandRequiresProcess | eCommandTryTargetAPILock |
1186061da546Spatrick                                 eCommandProcessMustBeLaunched) {}
1187061da546Spatrick 
1188061da546Spatrick   ~CommandObjectProcessSaveCore() override = default;
1189061da546Spatrick 
1190*be691f3bSpatrick   Options *GetOptions() override { return &m_options; }
1191*be691f3bSpatrick 
1192*be691f3bSpatrick   class CommandOptions : public Options {
1193*be691f3bSpatrick   public:
1194*be691f3bSpatrick     CommandOptions()
1195*be691f3bSpatrick         : Options(), m_requested_save_core_style(eSaveCoreUnspecified) {}
1196*be691f3bSpatrick 
1197*be691f3bSpatrick     ~CommandOptions() override = default;
1198*be691f3bSpatrick 
1199*be691f3bSpatrick     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1200*be691f3bSpatrick       return llvm::makeArrayRef(g_process_save_core_options);
1201*be691f3bSpatrick     }
1202*be691f3bSpatrick 
1203*be691f3bSpatrick     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1204*be691f3bSpatrick                           ExecutionContext *execution_context) override {
1205*be691f3bSpatrick       const int short_option = m_getopt_table[option_idx].val;
1206*be691f3bSpatrick       Status error;
1207*be691f3bSpatrick 
1208*be691f3bSpatrick       switch (short_option) {
1209*be691f3bSpatrick       case 's':
1210*be691f3bSpatrick         m_requested_save_core_style =
1211*be691f3bSpatrick             (lldb::SaveCoreStyle)OptionArgParser::ToOptionEnum(
1212*be691f3bSpatrick                 option_arg, GetDefinitions()[option_idx].enum_values,
1213*be691f3bSpatrick                 eSaveCoreUnspecified, error);
1214*be691f3bSpatrick         break;
1215*be691f3bSpatrick       default:
1216*be691f3bSpatrick         llvm_unreachable("Unimplemented option");
1217*be691f3bSpatrick       }
1218*be691f3bSpatrick 
1219*be691f3bSpatrick       return {};
1220*be691f3bSpatrick     }
1221*be691f3bSpatrick 
1222*be691f3bSpatrick     void OptionParsingStarting(ExecutionContext *execution_context) override {
1223*be691f3bSpatrick       m_requested_save_core_style = eSaveCoreUnspecified;
1224*be691f3bSpatrick     }
1225*be691f3bSpatrick 
1226*be691f3bSpatrick     // Instance variables to hold the values for command options.
1227*be691f3bSpatrick     SaveCoreStyle m_requested_save_core_style;
1228*be691f3bSpatrick   };
1229*be691f3bSpatrick 
1230061da546Spatrick protected:
1231061da546Spatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
1232061da546Spatrick     ProcessSP process_sp = m_exe_ctx.GetProcessSP();
1233061da546Spatrick     if (process_sp) {
1234061da546Spatrick       if (command.GetArgumentCount() == 1) {
1235061da546Spatrick         FileSpec output_file(command.GetArgumentAtIndex(0));
1236*be691f3bSpatrick         SaveCoreStyle corefile_style = m_options.m_requested_save_core_style;
1237*be691f3bSpatrick         Status error =
1238*be691f3bSpatrick             PluginManager::SaveCore(process_sp, output_file, corefile_style);
1239061da546Spatrick         if (error.Success()) {
1240*be691f3bSpatrick           if (corefile_style == SaveCoreStyle::eSaveCoreDirtyOnly) {
1241*be691f3bSpatrick             result.AppendMessageWithFormat(
1242*be691f3bSpatrick                 "\nModified-memory only corefile "
1243*be691f3bSpatrick                 "created.  This corefile may not show \n"
1244*be691f3bSpatrick                 "library/framework/app binaries "
1245*be691f3bSpatrick                 "on a different system, or when \n"
1246*be691f3bSpatrick                 "those binaries have "
1247*be691f3bSpatrick                 "been updated/modified. Copies are not included\n"
1248*be691f3bSpatrick                 "in this corefile.  Use --style full to include all "
1249*be691f3bSpatrick                 "process memory.\n");
1250*be691f3bSpatrick           }
1251061da546Spatrick           result.SetStatus(eReturnStatusSuccessFinishResult);
1252061da546Spatrick         } else {
1253061da546Spatrick           result.AppendErrorWithFormat(
1254061da546Spatrick               "Failed to save core file for process: %s\n", error.AsCString());
1255061da546Spatrick         }
1256061da546Spatrick       } else {
1257061da546Spatrick         result.AppendErrorWithFormat("'%s' takes one arguments:\nUsage: %s\n",
1258061da546Spatrick                                      m_cmd_name.c_str(), m_cmd_syntax.c_str());
1259061da546Spatrick       }
1260061da546Spatrick     } else {
1261061da546Spatrick       result.AppendError("invalid process");
1262061da546Spatrick       return false;
1263061da546Spatrick     }
1264061da546Spatrick 
1265061da546Spatrick     return result.Succeeded();
1266061da546Spatrick   }
1267*be691f3bSpatrick 
1268*be691f3bSpatrick   CommandOptions m_options;
1269061da546Spatrick };
1270061da546Spatrick 
1271061da546Spatrick // CommandObjectProcessStatus
1272061da546Spatrick #pragma mark CommandObjectProcessStatus
1273dda28197Spatrick #define LLDB_OPTIONS_process_status
1274dda28197Spatrick #include "CommandOptions.inc"
1275061da546Spatrick 
1276061da546Spatrick class CommandObjectProcessStatus : public CommandObjectParsed {
1277061da546Spatrick public:
1278061da546Spatrick   CommandObjectProcessStatus(CommandInterpreter &interpreter)
1279061da546Spatrick       : CommandObjectParsed(
1280061da546Spatrick             interpreter, "process status",
1281061da546Spatrick             "Show status and stop location for the current target process.",
1282061da546Spatrick             "process status",
1283dda28197Spatrick             eCommandRequiresProcess | eCommandTryTargetAPILock),
1284dda28197Spatrick         m_options() {}
1285061da546Spatrick 
1286061da546Spatrick   ~CommandObjectProcessStatus() override = default;
1287061da546Spatrick 
1288dda28197Spatrick   Options *GetOptions() override { return &m_options; }
1289dda28197Spatrick 
1290dda28197Spatrick   class CommandOptions : public Options {
1291dda28197Spatrick   public:
1292*be691f3bSpatrick     CommandOptions() : Options() {}
1293dda28197Spatrick 
1294dda28197Spatrick     ~CommandOptions() override = default;
1295dda28197Spatrick 
1296dda28197Spatrick     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1297dda28197Spatrick                           ExecutionContext *execution_context) override {
1298dda28197Spatrick       const int short_option = m_getopt_table[option_idx].val;
1299dda28197Spatrick 
1300dda28197Spatrick       switch (short_option) {
1301dda28197Spatrick       case 'v':
1302dda28197Spatrick         m_verbose = true;
1303dda28197Spatrick         break;
1304dda28197Spatrick       default:
1305dda28197Spatrick         llvm_unreachable("Unimplemented option");
1306dda28197Spatrick       }
1307dda28197Spatrick 
1308dda28197Spatrick       return {};
1309dda28197Spatrick     }
1310dda28197Spatrick 
1311dda28197Spatrick     void OptionParsingStarting(ExecutionContext *execution_context) override {
1312dda28197Spatrick       m_verbose = false;
1313dda28197Spatrick     }
1314dda28197Spatrick 
1315dda28197Spatrick     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1316dda28197Spatrick       return llvm::makeArrayRef(g_process_status_options);
1317dda28197Spatrick     }
1318dda28197Spatrick 
1319dda28197Spatrick     // Instance variables to hold the values for command options.
1320*be691f3bSpatrick     bool m_verbose = false;
1321dda28197Spatrick   };
1322dda28197Spatrick 
1323dda28197Spatrick protected:
1324061da546Spatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
1325061da546Spatrick     Stream &strm = result.GetOutputStream();
1326061da546Spatrick     result.SetStatus(eReturnStatusSuccessFinishNoResult);
1327dda28197Spatrick 
1328dda28197Spatrick     if (command.GetArgumentCount()) {
1329dda28197Spatrick       result.AppendError("'process status' takes no arguments");
1330dda28197Spatrick       return result.Succeeded();
1331dda28197Spatrick     }
1332dda28197Spatrick 
1333061da546Spatrick     // No need to check "process" for validity as eCommandRequiresProcess
1334061da546Spatrick     // ensures it is valid
1335061da546Spatrick     Process *process = m_exe_ctx.GetProcessPtr();
1336061da546Spatrick     const bool only_threads_with_stop_reason = true;
1337061da546Spatrick     const uint32_t start_frame = 0;
1338061da546Spatrick     const uint32_t num_frames = 1;
1339061da546Spatrick     const uint32_t num_frames_with_source = 1;
1340061da546Spatrick     const bool stop_format = true;
1341061da546Spatrick     process->GetStatus(strm);
1342061da546Spatrick     process->GetThreadStatus(strm, only_threads_with_stop_reason, start_frame,
1343061da546Spatrick                              num_frames, num_frames_with_source, stop_format);
1344dda28197Spatrick 
1345dda28197Spatrick     if (m_options.m_verbose) {
1346*be691f3bSpatrick       addr_t code_mask = process->GetCodeAddressMask();
1347*be691f3bSpatrick       addr_t data_mask = process->GetDataAddressMask();
1348*be691f3bSpatrick       if (code_mask != 0) {
1349*be691f3bSpatrick         int bits = std::bitset<64>(~code_mask).count();
1350*be691f3bSpatrick         result.AppendMessageWithFormat(
1351*be691f3bSpatrick             "Addressable code address mask: 0x%" PRIx64 "\n", code_mask);
1352*be691f3bSpatrick         result.AppendMessageWithFormat(
1353*be691f3bSpatrick             "Addressable data address mask: 0x%" PRIx64 "\n", data_mask);
1354*be691f3bSpatrick         result.AppendMessageWithFormat(
1355*be691f3bSpatrick             "Number of bits used in addressing (code): %d\n", bits);
1356*be691f3bSpatrick       }
1357*be691f3bSpatrick 
1358dda28197Spatrick       PlatformSP platform_sp = process->GetTarget().GetPlatform();
1359dda28197Spatrick       if (!platform_sp) {
1360dda28197Spatrick         result.AppendError("Couldn'retrieve the target's platform");
1361061da546Spatrick         return result.Succeeded();
1362061da546Spatrick       }
1363dda28197Spatrick 
1364dda28197Spatrick       auto expected_crash_info =
1365dda28197Spatrick           platform_sp->FetchExtendedCrashInformation(*process);
1366dda28197Spatrick 
1367dda28197Spatrick       if (!expected_crash_info) {
1368dda28197Spatrick         result.AppendError(llvm::toString(expected_crash_info.takeError()));
1369dda28197Spatrick         return result.Succeeded();
1370dda28197Spatrick       }
1371dda28197Spatrick 
1372dda28197Spatrick       StructuredData::DictionarySP crash_info_sp = *expected_crash_info;
1373dda28197Spatrick 
1374dda28197Spatrick       if (crash_info_sp) {
1375dda28197Spatrick         strm.PutCString("Extended Crash Information:\n");
1376dda28197Spatrick         crash_info_sp->Dump(strm);
1377dda28197Spatrick       }
1378dda28197Spatrick     }
1379dda28197Spatrick 
1380dda28197Spatrick     return result.Succeeded();
1381dda28197Spatrick   }
1382dda28197Spatrick 
1383dda28197Spatrick private:
1384dda28197Spatrick   CommandOptions m_options;
1385061da546Spatrick };
1386061da546Spatrick 
1387061da546Spatrick // CommandObjectProcessHandle
1388061da546Spatrick #define LLDB_OPTIONS_process_handle
1389061da546Spatrick #include "CommandOptions.inc"
1390061da546Spatrick 
1391061da546Spatrick #pragma mark CommandObjectProcessHandle
1392061da546Spatrick 
1393061da546Spatrick class CommandObjectProcessHandle : public CommandObjectParsed {
1394061da546Spatrick public:
1395061da546Spatrick   class CommandOptions : public Options {
1396061da546Spatrick   public:
1397061da546Spatrick     CommandOptions() : Options() { OptionParsingStarting(nullptr); }
1398061da546Spatrick 
1399061da546Spatrick     ~CommandOptions() override = default;
1400061da546Spatrick 
1401061da546Spatrick     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1402061da546Spatrick                           ExecutionContext *execution_context) override {
1403061da546Spatrick       Status error;
1404061da546Spatrick       const int short_option = m_getopt_table[option_idx].val;
1405061da546Spatrick 
1406061da546Spatrick       switch (short_option) {
1407061da546Spatrick       case 's':
1408dda28197Spatrick         stop = std::string(option_arg);
1409061da546Spatrick         break;
1410061da546Spatrick       case 'n':
1411dda28197Spatrick         notify = std::string(option_arg);
1412061da546Spatrick         break;
1413061da546Spatrick       case 'p':
1414dda28197Spatrick         pass = std::string(option_arg);
1415061da546Spatrick         break;
1416061da546Spatrick       default:
1417061da546Spatrick         llvm_unreachable("Unimplemented option");
1418061da546Spatrick       }
1419061da546Spatrick       return error;
1420061da546Spatrick     }
1421061da546Spatrick 
1422061da546Spatrick     void OptionParsingStarting(ExecutionContext *execution_context) override {
1423061da546Spatrick       stop.clear();
1424061da546Spatrick       notify.clear();
1425061da546Spatrick       pass.clear();
1426061da546Spatrick     }
1427061da546Spatrick 
1428061da546Spatrick     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1429061da546Spatrick       return llvm::makeArrayRef(g_process_handle_options);
1430061da546Spatrick     }
1431061da546Spatrick 
1432061da546Spatrick     // Instance variables to hold the values for command options.
1433061da546Spatrick 
1434061da546Spatrick     std::string stop;
1435061da546Spatrick     std::string notify;
1436061da546Spatrick     std::string pass;
1437061da546Spatrick   };
1438061da546Spatrick 
1439061da546Spatrick   CommandObjectProcessHandle(CommandInterpreter &interpreter)
1440061da546Spatrick       : CommandObjectParsed(interpreter, "process handle",
1441061da546Spatrick                             "Manage LLDB handling of OS signals for the "
1442061da546Spatrick                             "current target process.  Defaults to showing "
1443061da546Spatrick                             "current policy.",
1444061da546Spatrick                             nullptr, eCommandRequiresTarget),
1445061da546Spatrick         m_options() {
1446061da546Spatrick     SetHelpLong("\nIf no signals are specified, update them all.  If no update "
1447061da546Spatrick                 "option is specified, list the current values.");
1448061da546Spatrick     CommandArgumentEntry arg;
1449061da546Spatrick     CommandArgumentData signal_arg;
1450061da546Spatrick 
1451061da546Spatrick     signal_arg.arg_type = eArgTypeUnixSignal;
1452061da546Spatrick     signal_arg.arg_repetition = eArgRepeatStar;
1453061da546Spatrick 
1454061da546Spatrick     arg.push_back(signal_arg);
1455061da546Spatrick 
1456061da546Spatrick     m_arguments.push_back(arg);
1457061da546Spatrick   }
1458061da546Spatrick 
1459061da546Spatrick   ~CommandObjectProcessHandle() override = default;
1460061da546Spatrick 
1461061da546Spatrick   Options *GetOptions() override { return &m_options; }
1462061da546Spatrick 
1463061da546Spatrick   bool VerifyCommandOptionValue(const std::string &option, int &real_value) {
1464061da546Spatrick     bool okay = true;
1465061da546Spatrick     bool success = false;
1466061da546Spatrick     bool tmp_value = OptionArgParser::ToBoolean(option, false, &success);
1467061da546Spatrick 
1468061da546Spatrick     if (success && tmp_value)
1469061da546Spatrick       real_value = 1;
1470061da546Spatrick     else if (success && !tmp_value)
1471061da546Spatrick       real_value = 0;
1472061da546Spatrick     else {
1473061da546Spatrick       // If the value isn't 'true' or 'false', it had better be 0 or 1.
1474dda28197Spatrick       if (!llvm::to_integer(option, real_value))
1475dda28197Spatrick         real_value = 3;
1476061da546Spatrick       if (real_value != 0 && real_value != 1)
1477061da546Spatrick         okay = false;
1478061da546Spatrick     }
1479061da546Spatrick 
1480061da546Spatrick     return okay;
1481061da546Spatrick   }
1482061da546Spatrick 
1483061da546Spatrick   void PrintSignalHeader(Stream &str) {
1484061da546Spatrick     str.Printf("NAME         PASS   STOP   NOTIFY\n");
1485061da546Spatrick     str.Printf("===========  =====  =====  ======\n");
1486061da546Spatrick   }
1487061da546Spatrick 
1488061da546Spatrick   void PrintSignal(Stream &str, int32_t signo, const char *sig_name,
1489061da546Spatrick                    const UnixSignalsSP &signals_sp) {
1490061da546Spatrick     bool stop;
1491061da546Spatrick     bool suppress;
1492061da546Spatrick     bool notify;
1493061da546Spatrick 
1494061da546Spatrick     str.Printf("%-11s  ", sig_name);
1495061da546Spatrick     if (signals_sp->GetSignalInfo(signo, suppress, stop, notify)) {
1496061da546Spatrick       bool pass = !suppress;
1497061da546Spatrick       str.Printf("%s  %s  %s", (pass ? "true " : "false"),
1498061da546Spatrick                  (stop ? "true " : "false"), (notify ? "true " : "false"));
1499061da546Spatrick     }
1500061da546Spatrick     str.Printf("\n");
1501061da546Spatrick   }
1502061da546Spatrick 
1503061da546Spatrick   void PrintSignalInformation(Stream &str, Args &signal_args,
1504061da546Spatrick                               int num_valid_signals,
1505061da546Spatrick                               const UnixSignalsSP &signals_sp) {
1506061da546Spatrick     PrintSignalHeader(str);
1507061da546Spatrick 
1508061da546Spatrick     if (num_valid_signals > 0) {
1509061da546Spatrick       size_t num_args = signal_args.GetArgumentCount();
1510061da546Spatrick       for (size_t i = 0; i < num_args; ++i) {
1511061da546Spatrick         int32_t signo = signals_sp->GetSignalNumberFromName(
1512061da546Spatrick             signal_args.GetArgumentAtIndex(i));
1513061da546Spatrick         if (signo != LLDB_INVALID_SIGNAL_NUMBER)
1514061da546Spatrick           PrintSignal(str, signo, signal_args.GetArgumentAtIndex(i),
1515061da546Spatrick                       signals_sp);
1516061da546Spatrick       }
1517061da546Spatrick     } else // Print info for ALL signals
1518061da546Spatrick     {
1519061da546Spatrick       int32_t signo = signals_sp->GetFirstSignalNumber();
1520061da546Spatrick       while (signo != LLDB_INVALID_SIGNAL_NUMBER) {
1521061da546Spatrick         PrintSignal(str, signo, signals_sp->GetSignalAsCString(signo),
1522061da546Spatrick                     signals_sp);
1523061da546Spatrick         signo = signals_sp->GetNextSignalNumber(signo);
1524061da546Spatrick       }
1525061da546Spatrick     }
1526061da546Spatrick   }
1527061da546Spatrick 
1528061da546Spatrick protected:
1529061da546Spatrick   bool DoExecute(Args &signal_args, CommandReturnObject &result) override {
1530061da546Spatrick     Target *target_sp = &GetSelectedTarget();
1531061da546Spatrick 
1532061da546Spatrick     ProcessSP process_sp = target_sp->GetProcessSP();
1533061da546Spatrick 
1534061da546Spatrick     if (!process_sp) {
1535061da546Spatrick       result.AppendError("No current process; cannot handle signals until you "
1536061da546Spatrick                          "have a valid process.\n");
1537061da546Spatrick       return false;
1538061da546Spatrick     }
1539061da546Spatrick 
1540061da546Spatrick     int stop_action = -1;   // -1 means leave the current setting alone
1541061da546Spatrick     int pass_action = -1;   // -1 means leave the current setting alone
1542061da546Spatrick     int notify_action = -1; // -1 means leave the current setting alone
1543061da546Spatrick 
1544061da546Spatrick     if (!m_options.stop.empty() &&
1545061da546Spatrick         !VerifyCommandOptionValue(m_options.stop, stop_action)) {
1546061da546Spatrick       result.AppendError("Invalid argument for command option --stop; must be "
1547061da546Spatrick                          "true or false.\n");
1548061da546Spatrick       return false;
1549061da546Spatrick     }
1550061da546Spatrick 
1551061da546Spatrick     if (!m_options.notify.empty() &&
1552061da546Spatrick         !VerifyCommandOptionValue(m_options.notify, notify_action)) {
1553061da546Spatrick       result.AppendError("Invalid argument for command option --notify; must "
1554061da546Spatrick                          "be true or false.\n");
1555061da546Spatrick       return false;
1556061da546Spatrick     }
1557061da546Spatrick 
1558061da546Spatrick     if (!m_options.pass.empty() &&
1559061da546Spatrick         !VerifyCommandOptionValue(m_options.pass, pass_action)) {
1560061da546Spatrick       result.AppendError("Invalid argument for command option --pass; must be "
1561061da546Spatrick                          "true or false.\n");
1562061da546Spatrick       return false;
1563061da546Spatrick     }
1564061da546Spatrick 
1565061da546Spatrick     size_t num_args = signal_args.GetArgumentCount();
1566061da546Spatrick     UnixSignalsSP signals_sp = process_sp->GetUnixSignals();
1567061da546Spatrick     int num_signals_set = 0;
1568061da546Spatrick 
1569061da546Spatrick     if (num_args > 0) {
1570061da546Spatrick       for (const auto &arg : signal_args) {
1571061da546Spatrick         int32_t signo = signals_sp->GetSignalNumberFromName(arg.c_str());
1572061da546Spatrick         if (signo != LLDB_INVALID_SIGNAL_NUMBER) {
1573061da546Spatrick           // Casting the actions as bools here should be okay, because
1574061da546Spatrick           // VerifyCommandOptionValue guarantees the value is either 0 or 1.
1575061da546Spatrick           if (stop_action != -1)
1576061da546Spatrick             signals_sp->SetShouldStop(signo, stop_action);
1577061da546Spatrick           if (pass_action != -1) {
1578061da546Spatrick             bool suppress = !pass_action;
1579061da546Spatrick             signals_sp->SetShouldSuppress(signo, suppress);
1580061da546Spatrick           }
1581061da546Spatrick           if (notify_action != -1)
1582061da546Spatrick             signals_sp->SetShouldNotify(signo, notify_action);
1583061da546Spatrick           ++num_signals_set;
1584061da546Spatrick         } else {
1585061da546Spatrick           result.AppendErrorWithFormat("Invalid signal name '%s'\n",
1586061da546Spatrick                                        arg.c_str());
1587061da546Spatrick         }
1588061da546Spatrick       }
1589061da546Spatrick     } else {
1590061da546Spatrick       // No signal specified, if any command options were specified, update ALL
1591061da546Spatrick       // signals.
1592061da546Spatrick       if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1)) {
1593061da546Spatrick         if (m_interpreter.Confirm(
1594061da546Spatrick                 "Do you really want to update all the signals?", false)) {
1595061da546Spatrick           int32_t signo = signals_sp->GetFirstSignalNumber();
1596061da546Spatrick           while (signo != LLDB_INVALID_SIGNAL_NUMBER) {
1597061da546Spatrick             if (notify_action != -1)
1598061da546Spatrick               signals_sp->SetShouldNotify(signo, notify_action);
1599061da546Spatrick             if (stop_action != -1)
1600061da546Spatrick               signals_sp->SetShouldStop(signo, stop_action);
1601061da546Spatrick             if (pass_action != -1) {
1602061da546Spatrick               bool suppress = !pass_action;
1603061da546Spatrick               signals_sp->SetShouldSuppress(signo, suppress);
1604061da546Spatrick             }
1605061da546Spatrick             signo = signals_sp->GetNextSignalNumber(signo);
1606061da546Spatrick           }
1607061da546Spatrick         }
1608061da546Spatrick       }
1609061da546Spatrick     }
1610061da546Spatrick 
1611061da546Spatrick     PrintSignalInformation(result.GetOutputStream(), signal_args,
1612061da546Spatrick                            num_signals_set, signals_sp);
1613061da546Spatrick 
1614061da546Spatrick     if (num_signals_set > 0)
1615061da546Spatrick       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1616061da546Spatrick     else
1617061da546Spatrick       result.SetStatus(eReturnStatusFailed);
1618061da546Spatrick 
1619061da546Spatrick     return result.Succeeded();
1620061da546Spatrick   }
1621061da546Spatrick 
1622061da546Spatrick   CommandOptions m_options;
1623061da546Spatrick };
1624061da546Spatrick 
1625*be691f3bSpatrick // Next are the subcommands of CommandObjectMultiwordProcessTrace
1626*be691f3bSpatrick 
1627*be691f3bSpatrick // CommandObjectProcessTraceStart
1628*be691f3bSpatrick class CommandObjectProcessTraceStart : public CommandObjectTraceProxy {
1629*be691f3bSpatrick public:
1630*be691f3bSpatrick   CommandObjectProcessTraceStart(CommandInterpreter &interpreter)
1631*be691f3bSpatrick       : CommandObjectTraceProxy(
1632*be691f3bSpatrick             /*live_debug_session_only*/ true, interpreter,
1633*be691f3bSpatrick             "process trace start",
1634*be691f3bSpatrick             "Start tracing this process with the corresponding trace "
1635*be691f3bSpatrick             "plug-in.",
1636*be691f3bSpatrick             "process trace start [<trace-options>]") {}
1637*be691f3bSpatrick 
1638*be691f3bSpatrick protected:
1639*be691f3bSpatrick   lldb::CommandObjectSP GetDelegateCommand(Trace &trace) override {
1640*be691f3bSpatrick     return trace.GetProcessTraceStartCommand(m_interpreter);
1641*be691f3bSpatrick   }
1642*be691f3bSpatrick };
1643*be691f3bSpatrick 
1644*be691f3bSpatrick // CommandObjectProcessTraceStop
1645*be691f3bSpatrick class CommandObjectProcessTraceStop : public CommandObjectParsed {
1646*be691f3bSpatrick public:
1647*be691f3bSpatrick   CommandObjectProcessTraceStop(CommandInterpreter &interpreter)
1648*be691f3bSpatrick       : CommandObjectParsed(interpreter, "process trace stop",
1649*be691f3bSpatrick                             "Stop tracing this process. This does not affect "
1650*be691f3bSpatrick                             "traces started with the "
1651*be691f3bSpatrick                             "\"thread trace start\" command.",
1652*be691f3bSpatrick                             "process trace stop",
1653*be691f3bSpatrick                             eCommandRequiresProcess | eCommandTryTargetAPILock |
1654*be691f3bSpatrick                                 eCommandProcessMustBeLaunched |
1655*be691f3bSpatrick                                 eCommandProcessMustBePaused |
1656*be691f3bSpatrick                                 eCommandProcessMustBeTraced) {}
1657*be691f3bSpatrick 
1658*be691f3bSpatrick   ~CommandObjectProcessTraceStop() override = default;
1659*be691f3bSpatrick 
1660*be691f3bSpatrick   bool DoExecute(Args &command, CommandReturnObject &result) override {
1661*be691f3bSpatrick     ProcessSP process_sp = m_exe_ctx.GetProcessSP();
1662*be691f3bSpatrick 
1663*be691f3bSpatrick     TraceSP trace_sp = process_sp->GetTarget().GetTrace();
1664*be691f3bSpatrick 
1665*be691f3bSpatrick     if (llvm::Error err = trace_sp->Stop())
1666*be691f3bSpatrick       result.AppendError(toString(std::move(err)));
1667*be691f3bSpatrick     else
1668*be691f3bSpatrick       result.SetStatus(eReturnStatusSuccessFinishResult);
1669*be691f3bSpatrick 
1670*be691f3bSpatrick     return result.Succeeded();
1671*be691f3bSpatrick   }
1672*be691f3bSpatrick };
1673*be691f3bSpatrick 
1674*be691f3bSpatrick // CommandObjectMultiwordProcessTrace
1675*be691f3bSpatrick class CommandObjectMultiwordProcessTrace : public CommandObjectMultiword {
1676*be691f3bSpatrick public:
1677*be691f3bSpatrick   CommandObjectMultiwordProcessTrace(CommandInterpreter &interpreter)
1678*be691f3bSpatrick       : CommandObjectMultiword(
1679*be691f3bSpatrick             interpreter, "trace", "Commands for tracing the current process.",
1680*be691f3bSpatrick             "process trace <subcommand> [<subcommand objects>]") {
1681*be691f3bSpatrick     LoadSubCommand("start", CommandObjectSP(new CommandObjectProcessTraceStart(
1682*be691f3bSpatrick                                 interpreter)));
1683*be691f3bSpatrick     LoadSubCommand("stop", CommandObjectSP(
1684*be691f3bSpatrick                                new CommandObjectProcessTraceStop(interpreter)));
1685*be691f3bSpatrick   }
1686*be691f3bSpatrick 
1687*be691f3bSpatrick   ~CommandObjectMultiwordProcessTrace() override = default;
1688*be691f3bSpatrick };
1689*be691f3bSpatrick 
1690061da546Spatrick // CommandObjectMultiwordProcess
1691061da546Spatrick 
1692061da546Spatrick CommandObjectMultiwordProcess::CommandObjectMultiwordProcess(
1693061da546Spatrick     CommandInterpreter &interpreter)
1694061da546Spatrick     : CommandObjectMultiword(
1695061da546Spatrick           interpreter, "process",
1696061da546Spatrick           "Commands for interacting with processes on the current platform.",
1697061da546Spatrick           "process <subcommand> [<subcommand-options>]") {
1698061da546Spatrick   LoadSubCommand("attach",
1699061da546Spatrick                  CommandObjectSP(new CommandObjectProcessAttach(interpreter)));
1700061da546Spatrick   LoadSubCommand("launch",
1701061da546Spatrick                  CommandObjectSP(new CommandObjectProcessLaunch(interpreter)));
1702061da546Spatrick   LoadSubCommand("continue", CommandObjectSP(new CommandObjectProcessContinue(
1703061da546Spatrick                                  interpreter)));
1704061da546Spatrick   LoadSubCommand("connect",
1705061da546Spatrick                  CommandObjectSP(new CommandObjectProcessConnect(interpreter)));
1706061da546Spatrick   LoadSubCommand("detach",
1707061da546Spatrick                  CommandObjectSP(new CommandObjectProcessDetach(interpreter)));
1708061da546Spatrick   LoadSubCommand("load",
1709061da546Spatrick                  CommandObjectSP(new CommandObjectProcessLoad(interpreter)));
1710061da546Spatrick   LoadSubCommand("unload",
1711061da546Spatrick                  CommandObjectSP(new CommandObjectProcessUnload(interpreter)));
1712061da546Spatrick   LoadSubCommand("signal",
1713061da546Spatrick                  CommandObjectSP(new CommandObjectProcessSignal(interpreter)));
1714061da546Spatrick   LoadSubCommand("handle",
1715061da546Spatrick                  CommandObjectSP(new CommandObjectProcessHandle(interpreter)));
1716061da546Spatrick   LoadSubCommand("status",
1717061da546Spatrick                  CommandObjectSP(new CommandObjectProcessStatus(interpreter)));
1718061da546Spatrick   LoadSubCommand("interrupt", CommandObjectSP(new CommandObjectProcessInterrupt(
1719061da546Spatrick                                   interpreter)));
1720061da546Spatrick   LoadSubCommand("kill",
1721061da546Spatrick                  CommandObjectSP(new CommandObjectProcessKill(interpreter)));
1722061da546Spatrick   LoadSubCommand("plugin",
1723061da546Spatrick                  CommandObjectSP(new CommandObjectProcessPlugin(interpreter)));
1724061da546Spatrick   LoadSubCommand("save-core", CommandObjectSP(new CommandObjectProcessSaveCore(
1725061da546Spatrick                                   interpreter)));
1726*be691f3bSpatrick   LoadSubCommand(
1727*be691f3bSpatrick       "trace",
1728*be691f3bSpatrick       CommandObjectSP(new CommandObjectMultiwordProcessTrace(interpreter)));
1729061da546Spatrick }
1730061da546Spatrick 
1731061da546Spatrick CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess() = default;
1732