15ffd83dbSDimitry Andric //===-- CommandObjectProcess.cpp ------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "CommandObjectProcess.h"
10*5f7ddb14SDimitry Andric #include "CommandObjectTrace.h"
11af732203SDimitry Andric #include "CommandOptionsProcessLaunch.h"
120b57cec5SDimitry Andric #include "lldb/Breakpoint/Breakpoint.h"
130b57cec5SDimitry Andric #include "lldb/Breakpoint/BreakpointLocation.h"
140b57cec5SDimitry Andric #include "lldb/Breakpoint/BreakpointSite.h"
150b57cec5SDimitry Andric #include "lldb/Core/Module.h"
160b57cec5SDimitry Andric #include "lldb/Core/PluginManager.h"
170b57cec5SDimitry Andric #include "lldb/Host/OptionParser.h"
180b57cec5SDimitry Andric #include "lldb/Interpreter/CommandInterpreter.h"
190b57cec5SDimitry Andric #include "lldb/Interpreter/CommandReturnObject.h"
200b57cec5SDimitry Andric #include "lldb/Interpreter/OptionArgParser.h"
21*5f7ddb14SDimitry Andric #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"
220b57cec5SDimitry Andric #include "lldb/Interpreter/Options.h"
230b57cec5SDimitry Andric #include "lldb/Target/Platform.h"
240b57cec5SDimitry Andric #include "lldb/Target/Process.h"
250b57cec5SDimitry Andric #include "lldb/Target/StopInfo.h"
260b57cec5SDimitry Andric #include "lldb/Target/Target.h"
270b57cec5SDimitry Andric #include "lldb/Target/Thread.h"
280b57cec5SDimitry Andric #include "lldb/Target/UnixSignals.h"
290b57cec5SDimitry Andric #include "lldb/Utility/Args.h"
300b57cec5SDimitry Andric #include "lldb/Utility/State.h"
310b57cec5SDimitry Andric 
32*5f7ddb14SDimitry Andric #include <bitset>
33*5f7ddb14SDimitry Andric 
340b57cec5SDimitry Andric using namespace lldb;
350b57cec5SDimitry Andric using namespace lldb_private;
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric class CommandObjectProcessLaunchOrAttach : public CommandObjectParsed {
380b57cec5SDimitry Andric public:
CommandObjectProcessLaunchOrAttach(CommandInterpreter & interpreter,const char * name,const char * help,const char * syntax,uint32_t flags,const char * new_process_action)390b57cec5SDimitry Andric   CommandObjectProcessLaunchOrAttach(CommandInterpreter &interpreter,
400b57cec5SDimitry Andric                                      const char *name, const char *help,
410b57cec5SDimitry Andric                                      const char *syntax, uint32_t flags,
420b57cec5SDimitry Andric                                      const char *new_process_action)
430b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, name, help, syntax, flags),
440b57cec5SDimitry Andric         m_new_process_action(new_process_action) {}
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric   ~CommandObjectProcessLaunchOrAttach() override = default;
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric protected:
StopProcessIfNecessary(Process * process,StateType & state,CommandReturnObject & result)490b57cec5SDimitry Andric   bool StopProcessIfNecessary(Process *process, StateType &state,
500b57cec5SDimitry Andric                               CommandReturnObject &result) {
510b57cec5SDimitry Andric     state = eStateInvalid;
520b57cec5SDimitry Andric     if (process) {
530b57cec5SDimitry Andric       state = process->GetState();
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric       if (process->IsAlive() && state != eStateConnected) {
56af732203SDimitry Andric         std::string message;
570b57cec5SDimitry Andric         if (process->GetState() == eStateAttaching)
58af732203SDimitry Andric           message =
59af732203SDimitry Andric               llvm::formatv("There is a pending attach, abort it and {0}?",
60af732203SDimitry Andric                             m_new_process_action);
610b57cec5SDimitry Andric         else if (process->GetShouldDetach())
62af732203SDimitry Andric           message = llvm::formatv(
63af732203SDimitry Andric               "There is a running process, detach from it and {0}?",
64af732203SDimitry Andric               m_new_process_action);
650b57cec5SDimitry Andric         else
66af732203SDimitry Andric           message =
67af732203SDimitry Andric               llvm::formatv("There is a running process, kill it and {0}?",
68af732203SDimitry Andric                             m_new_process_action);
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric         if (!m_interpreter.Confirm(message, true)) {
710b57cec5SDimitry Andric           result.SetStatus(eReturnStatusFailed);
720b57cec5SDimitry Andric           return false;
730b57cec5SDimitry Andric         } else {
740b57cec5SDimitry Andric           if (process->GetShouldDetach()) {
750b57cec5SDimitry Andric             bool keep_stopped = false;
760b57cec5SDimitry Andric             Status detach_error(process->Detach(keep_stopped));
770b57cec5SDimitry Andric             if (detach_error.Success()) {
780b57cec5SDimitry Andric               result.SetStatus(eReturnStatusSuccessFinishResult);
790b57cec5SDimitry Andric               process = nullptr;
800b57cec5SDimitry Andric             } else {
810b57cec5SDimitry Andric               result.AppendErrorWithFormat(
820b57cec5SDimitry Andric                   "Failed to detach from process: %s\n",
830b57cec5SDimitry Andric                   detach_error.AsCString());
840b57cec5SDimitry Andric             }
850b57cec5SDimitry Andric           } else {
860b57cec5SDimitry Andric             Status destroy_error(process->Destroy(false));
870b57cec5SDimitry Andric             if (destroy_error.Success()) {
880b57cec5SDimitry Andric               result.SetStatus(eReturnStatusSuccessFinishResult);
890b57cec5SDimitry Andric               process = nullptr;
900b57cec5SDimitry Andric             } else {
910b57cec5SDimitry Andric               result.AppendErrorWithFormat("Failed to kill process: %s\n",
920b57cec5SDimitry Andric                                            destroy_error.AsCString());
930b57cec5SDimitry Andric             }
940b57cec5SDimitry Andric           }
950b57cec5SDimitry Andric         }
960b57cec5SDimitry Andric       }
970b57cec5SDimitry Andric     }
980b57cec5SDimitry Andric     return result.Succeeded();
990b57cec5SDimitry Andric   }
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric   std::string m_new_process_action;
1020b57cec5SDimitry Andric };
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric // CommandObjectProcessLaunch
1050b57cec5SDimitry Andric #pragma mark CommandObjectProcessLaunch
1060b57cec5SDimitry Andric class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach {
1070b57cec5SDimitry Andric public:
CommandObjectProcessLaunch(CommandInterpreter & interpreter)1080b57cec5SDimitry Andric   CommandObjectProcessLaunch(CommandInterpreter &interpreter)
1090b57cec5SDimitry Andric       : CommandObjectProcessLaunchOrAttach(
1100b57cec5SDimitry Andric             interpreter, "process launch",
1110b57cec5SDimitry Andric             "Launch the executable in the debugger.", nullptr,
1120b57cec5SDimitry Andric             eCommandRequiresTarget, "restart"),
113*5f7ddb14SDimitry Andric         m_options(),
114*5f7ddb14SDimitry Andric         m_class_options("scripted process", true, 'C', 'k', 'v', 0),
115*5f7ddb14SDimitry Andric         m_all_options() {
116*5f7ddb14SDimitry Andric     m_all_options.Append(&m_options);
117*5f7ddb14SDimitry Andric     m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2,
118*5f7ddb14SDimitry Andric                          LLDB_OPT_SET_ALL);
119*5f7ddb14SDimitry Andric     m_all_options.Finalize();
120*5f7ddb14SDimitry Andric 
1210b57cec5SDimitry Andric     CommandArgumentEntry arg;
1220b57cec5SDimitry Andric     CommandArgumentData run_args_arg;
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric     // Define the first (and only) variant of this arg.
1250b57cec5SDimitry Andric     run_args_arg.arg_type = eArgTypeRunArgs;
1260b57cec5SDimitry Andric     run_args_arg.arg_repetition = eArgRepeatOptional;
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric     // There is only one variant this argument could be; put it into the
1290b57cec5SDimitry Andric     // argument entry.
1300b57cec5SDimitry Andric     arg.push_back(run_args_arg);
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric     // Push the data for the first argument into the m_arguments vector.
1330b57cec5SDimitry Andric     m_arguments.push_back(arg);
1340b57cec5SDimitry Andric   }
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric   ~CommandObjectProcessLaunch() override = default;
1370b57cec5SDimitry Andric 
1389dba64beSDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)1399dba64beSDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
1400b57cec5SDimitry Andric                            OptionElementVector &opt_element_vector) override {
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric     CommandCompletions::InvokeCommonCompletionCallbacks(
1430b57cec5SDimitry Andric         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
1440b57cec5SDimitry Andric         request, nullptr);
1450b57cec5SDimitry Andric   }
1460b57cec5SDimitry Andric 
GetOptions()147*5f7ddb14SDimitry Andric   Options *GetOptions() override { return &m_all_options; }
1480b57cec5SDimitry Andric 
GetRepeatCommand(Args & current_command_args,uint32_t index)1490b57cec5SDimitry Andric   const char *GetRepeatCommand(Args &current_command_args,
1500b57cec5SDimitry Andric                                uint32_t index) override {
1510b57cec5SDimitry Andric     // No repeat for "process launch"...
1520b57cec5SDimitry Andric     return "";
1530b57cec5SDimitry Andric   }
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric protected:
DoExecute(Args & launch_args,CommandReturnObject & result)1560b57cec5SDimitry Andric   bool DoExecute(Args &launch_args, CommandReturnObject &result) override {
1570b57cec5SDimitry Andric     Debugger &debugger = GetDebugger();
1580b57cec5SDimitry Andric     Target *target = debugger.GetSelectedTarget().get();
1590b57cec5SDimitry Andric     // If our listener is nullptr, users aren't allows to launch
1600b57cec5SDimitry Andric     ModuleSP exe_module_sp = target->GetExecutableModule();
1610b57cec5SDimitry Andric 
1620b57cec5SDimitry Andric     if (exe_module_sp == nullptr) {
1630b57cec5SDimitry Andric       result.AppendError("no file in target, create a debug target using the "
1640b57cec5SDimitry Andric                          "'target create' command");
1650b57cec5SDimitry Andric       return false;
1660b57cec5SDimitry Andric     }
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric     StateType state = eStateInvalid;
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric     if (!StopProcessIfNecessary(m_exe_ctx.GetProcessPtr(), state, result))
1710b57cec5SDimitry Andric       return false;
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric     llvm::StringRef target_settings_argv0 = target->GetArg0();
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric     // Determine whether we will disable ASLR or leave it in the default state
1760b57cec5SDimitry Andric     // (i.e. enabled if the platform supports it). First check if the process
1770b57cec5SDimitry Andric     // launch options explicitly turn on/off
1780b57cec5SDimitry Andric     // disabling ASLR.  If so, use that setting;
1790b57cec5SDimitry Andric     // otherwise, use the 'settings target.disable-aslr' setting.
1800b57cec5SDimitry Andric     bool disable_aslr = false;
1810b57cec5SDimitry Andric     if (m_options.disable_aslr != eLazyBoolCalculate) {
1820b57cec5SDimitry Andric       // The user specified an explicit setting on the process launch line.
1830b57cec5SDimitry Andric       // Use it.
1840b57cec5SDimitry Andric       disable_aslr = (m_options.disable_aslr == eLazyBoolYes);
1850b57cec5SDimitry Andric     } else {
1860b57cec5SDimitry Andric       // The user did not explicitly specify whether to disable ASLR.  Fall
1870b57cec5SDimitry Andric       // back to the target.disable-aslr setting.
1880b57cec5SDimitry Andric       disable_aslr = target->GetDisableASLR();
1890b57cec5SDimitry Andric     }
1900b57cec5SDimitry Andric 
191*5f7ddb14SDimitry Andric     if (!m_class_options.GetName().empty()) {
192*5f7ddb14SDimitry Andric       m_options.launch_info.SetProcessPluginName("ScriptedProcess");
193*5f7ddb14SDimitry Andric       m_options.launch_info.SetScriptedProcessClassName(
194*5f7ddb14SDimitry Andric           m_class_options.GetName());
195*5f7ddb14SDimitry Andric       m_options.launch_info.SetScriptedProcessDictionarySP(
196*5f7ddb14SDimitry Andric           m_class_options.GetStructuredData());
197*5f7ddb14SDimitry Andric       target->SetProcessLaunchInfo(m_options.launch_info);
198*5f7ddb14SDimitry Andric     }
199*5f7ddb14SDimitry Andric 
2000b57cec5SDimitry Andric     if (disable_aslr)
2010b57cec5SDimitry Andric       m_options.launch_info.GetFlags().Set(eLaunchFlagDisableASLR);
2020b57cec5SDimitry Andric     else
2030b57cec5SDimitry Andric       m_options.launch_info.GetFlags().Clear(eLaunchFlagDisableASLR);
2040b57cec5SDimitry Andric 
205af732203SDimitry Andric     if (target->GetInheritTCC())
206af732203SDimitry Andric       m_options.launch_info.GetFlags().Set(eLaunchFlagInheritTCCFromParent);
207af732203SDimitry Andric 
2080b57cec5SDimitry Andric     if (target->GetDetachOnError())
2090b57cec5SDimitry Andric       m_options.launch_info.GetFlags().Set(eLaunchFlagDetachOnError);
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric     if (target->GetDisableSTDIO())
2120b57cec5SDimitry Andric       m_options.launch_info.GetFlags().Set(eLaunchFlagDisableSTDIO);
2130b57cec5SDimitry Andric 
2140b57cec5SDimitry Andric     // Merge the launch info environment with the target environment.
2150b57cec5SDimitry Andric     Environment target_env = target->GetEnvironment();
2160b57cec5SDimitry Andric     m_options.launch_info.GetEnvironment().insert(target_env.begin(),
2170b57cec5SDimitry Andric                                                   target_env.end());
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric     if (!target_settings_argv0.empty()) {
2200b57cec5SDimitry Andric       m_options.launch_info.GetArguments().AppendArgument(
2210b57cec5SDimitry Andric           target_settings_argv0);
2220b57cec5SDimitry Andric       m_options.launch_info.SetExecutableFile(
2230b57cec5SDimitry Andric           exe_module_sp->GetPlatformFileSpec(), false);
2240b57cec5SDimitry Andric     } else {
2250b57cec5SDimitry Andric       m_options.launch_info.SetExecutableFile(
2260b57cec5SDimitry Andric           exe_module_sp->GetPlatformFileSpec(), true);
2270b57cec5SDimitry Andric     }
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric     if (launch_args.GetArgumentCount() == 0) {
2300b57cec5SDimitry Andric       m_options.launch_info.GetArguments().AppendArguments(
2310b57cec5SDimitry Andric           target->GetProcessLaunchInfo().GetArguments());
2320b57cec5SDimitry Andric     } else {
2330b57cec5SDimitry Andric       m_options.launch_info.GetArguments().AppendArguments(launch_args);
2340b57cec5SDimitry Andric       // Save the arguments for subsequent runs in the current target.
2350b57cec5SDimitry Andric       target->SetRunArguments(launch_args);
2360b57cec5SDimitry Andric     }
2370b57cec5SDimitry Andric 
2380b57cec5SDimitry Andric     StreamString stream;
2390b57cec5SDimitry Andric     Status error = target->Launch(m_options.launch_info, &stream);
2400b57cec5SDimitry Andric 
2410b57cec5SDimitry Andric     if (error.Success()) {
2420b57cec5SDimitry Andric       ProcessSP process_sp(target->GetProcessSP());
2430b57cec5SDimitry Andric       if (process_sp) {
2440b57cec5SDimitry Andric         // There is a race condition where this thread will return up the call
2450b57cec5SDimitry Andric         // stack to the main command handler and show an (lldb) prompt before
2460b57cec5SDimitry Andric         // HandlePrivateEvent (from PrivateStateThread) has a chance to call
2470b57cec5SDimitry Andric         // PushProcessIOHandler().
2480b57cec5SDimitry Andric         process_sp->SyncIOHandler(0, std::chrono::seconds(2));
2490b57cec5SDimitry Andric 
2500b57cec5SDimitry Andric         llvm::StringRef data = stream.GetString();
2510b57cec5SDimitry Andric         if (!data.empty())
2520b57cec5SDimitry Andric           result.AppendMessage(data);
2530b57cec5SDimitry Andric         const char *archname =
2540b57cec5SDimitry Andric             exe_module_sp->GetArchitecture().GetArchitectureName();
2550b57cec5SDimitry Andric         result.AppendMessageWithFormat(
2560b57cec5SDimitry Andric             "Process %" PRIu64 " launched: '%s' (%s)\n", process_sp->GetID(),
2570b57cec5SDimitry Andric             exe_module_sp->GetFileSpec().GetPath().c_str(), archname);
2580b57cec5SDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishResult);
2590b57cec5SDimitry Andric         result.SetDidChangeProcessState(true);
2600b57cec5SDimitry Andric       } else {
2610b57cec5SDimitry Andric         result.AppendError(
2620b57cec5SDimitry Andric             "no error returned from Target::Launch, and target has no process");
2630b57cec5SDimitry Andric       }
2640b57cec5SDimitry Andric     } else {
2650b57cec5SDimitry Andric       result.AppendError(error.AsCString());
2660b57cec5SDimitry Andric     }
2670b57cec5SDimitry Andric     return result.Succeeded();
2680b57cec5SDimitry Andric   }
2690b57cec5SDimitry Andric 
270af732203SDimitry Andric   CommandOptionsProcessLaunch m_options;
271*5f7ddb14SDimitry Andric   OptionGroupPythonClassWithDict m_class_options;
272*5f7ddb14SDimitry Andric   OptionGroupOptions m_all_options;
2730b57cec5SDimitry Andric };
2740b57cec5SDimitry Andric 
2759dba64beSDimitry Andric #define LLDB_OPTIONS_process_attach
2769dba64beSDimitry Andric #include "CommandOptions.inc"
2770b57cec5SDimitry Andric 
2780b57cec5SDimitry Andric #pragma mark CommandObjectProcessAttach
2790b57cec5SDimitry Andric class CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach {
2800b57cec5SDimitry Andric public:
2810b57cec5SDimitry Andric   class CommandOptions : public Options {
2820b57cec5SDimitry Andric   public:
CommandOptions()2830b57cec5SDimitry Andric     CommandOptions() : Options() {
2840b57cec5SDimitry Andric       // Keep default values of all options in one place: OptionParsingStarting
2850b57cec5SDimitry Andric       // ()
2860b57cec5SDimitry Andric       OptionParsingStarting(nullptr);
2870b57cec5SDimitry Andric     }
2880b57cec5SDimitry Andric 
2890b57cec5SDimitry Andric     ~CommandOptions() override = default;
2900b57cec5SDimitry Andric 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)2910b57cec5SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
2920b57cec5SDimitry Andric                           ExecutionContext *execution_context) override {
2930b57cec5SDimitry Andric       Status error;
2940b57cec5SDimitry Andric       const int short_option = m_getopt_table[option_idx].val;
2950b57cec5SDimitry Andric       switch (short_option) {
2960b57cec5SDimitry Andric       case 'c':
2970b57cec5SDimitry Andric         attach_info.SetContinueOnceAttached(true);
2980b57cec5SDimitry Andric         break;
2990b57cec5SDimitry Andric 
3000b57cec5SDimitry Andric       case 'p': {
3010b57cec5SDimitry Andric         lldb::pid_t pid;
3020b57cec5SDimitry Andric         if (option_arg.getAsInteger(0, pid)) {
3030b57cec5SDimitry Andric           error.SetErrorStringWithFormat("invalid process ID '%s'",
3040b57cec5SDimitry Andric                                          option_arg.str().c_str());
3050b57cec5SDimitry Andric         } else {
3060b57cec5SDimitry Andric           attach_info.SetProcessID(pid);
3070b57cec5SDimitry Andric         }
3080b57cec5SDimitry Andric       } break;
3090b57cec5SDimitry Andric 
3100b57cec5SDimitry Andric       case 'P':
3110b57cec5SDimitry Andric         attach_info.SetProcessPluginName(option_arg);
3120b57cec5SDimitry Andric         break;
3130b57cec5SDimitry Andric 
3140b57cec5SDimitry Andric       case 'n':
3150b57cec5SDimitry Andric         attach_info.GetExecutableFile().SetFile(option_arg,
3160b57cec5SDimitry Andric                                                 FileSpec::Style::native);
3170b57cec5SDimitry Andric         break;
3180b57cec5SDimitry Andric 
3190b57cec5SDimitry Andric       case 'w':
3200b57cec5SDimitry Andric         attach_info.SetWaitForLaunch(true);
3210b57cec5SDimitry Andric         break;
3220b57cec5SDimitry Andric 
3230b57cec5SDimitry Andric       case 'i':
3240b57cec5SDimitry Andric         attach_info.SetIgnoreExisting(false);
3250b57cec5SDimitry Andric         break;
3260b57cec5SDimitry Andric 
3270b57cec5SDimitry Andric       default:
3289dba64beSDimitry Andric         llvm_unreachable("Unimplemented option");
3290b57cec5SDimitry Andric       }
3300b57cec5SDimitry Andric       return error;
3310b57cec5SDimitry Andric     }
3320b57cec5SDimitry Andric 
OptionParsingStarting(ExecutionContext * execution_context)3330b57cec5SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
3340b57cec5SDimitry Andric       attach_info.Clear();
3350b57cec5SDimitry Andric     }
3360b57cec5SDimitry Andric 
GetDefinitions()3370b57cec5SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
3380b57cec5SDimitry Andric       return llvm::makeArrayRef(g_process_attach_options);
3390b57cec5SDimitry Andric     }
3400b57cec5SDimitry Andric 
3410b57cec5SDimitry Andric     ProcessAttachInfo attach_info;
3420b57cec5SDimitry Andric   };
3430b57cec5SDimitry Andric 
CommandObjectProcessAttach(CommandInterpreter & interpreter)3440b57cec5SDimitry Andric   CommandObjectProcessAttach(CommandInterpreter &interpreter)
3450b57cec5SDimitry Andric       : CommandObjectProcessLaunchOrAttach(
3460b57cec5SDimitry Andric             interpreter, "process attach", "Attach to a process.",
3470b57cec5SDimitry Andric             "process attach <cmd-options>", 0, "attach"),
3480b57cec5SDimitry Andric         m_options() {}
3490b57cec5SDimitry Andric 
3500b57cec5SDimitry Andric   ~CommandObjectProcessAttach() override = default;
3510b57cec5SDimitry Andric 
GetOptions()3520b57cec5SDimitry Andric   Options *GetOptions() override { return &m_options; }
3530b57cec5SDimitry Andric 
3540b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)3550b57cec5SDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
3560b57cec5SDimitry Andric     PlatformSP platform_sp(
3570b57cec5SDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
3580b57cec5SDimitry Andric 
3590b57cec5SDimitry Andric     Target *target = GetDebugger().GetSelectedTarget().get();
3600b57cec5SDimitry Andric     // N.B. The attach should be synchronous.  It doesn't help much to get the
3610b57cec5SDimitry Andric     // prompt back between initiating the attach and the target actually
3620b57cec5SDimitry Andric     // stopping.  So even if the interpreter is set to be asynchronous, we wait
3630b57cec5SDimitry Andric     // for the stop ourselves here.
3640b57cec5SDimitry Andric 
3650b57cec5SDimitry Andric     StateType state = eStateInvalid;
3660b57cec5SDimitry Andric     Process *process = m_exe_ctx.GetProcessPtr();
3670b57cec5SDimitry Andric 
3680b57cec5SDimitry Andric     if (!StopProcessIfNecessary(process, state, result))
3690b57cec5SDimitry Andric       return false;
3700b57cec5SDimitry Andric 
3710b57cec5SDimitry Andric     if (target == nullptr) {
3720b57cec5SDimitry Andric       // If there isn't a current target create one.
3730b57cec5SDimitry Andric       TargetSP new_target_sp;
3740b57cec5SDimitry Andric       Status error;
3750b57cec5SDimitry Andric 
3760b57cec5SDimitry Andric       error = GetDebugger().GetTargetList().CreateTarget(
3770b57cec5SDimitry Andric           GetDebugger(), "", "", eLoadDependentsNo,
3780b57cec5SDimitry Andric           nullptr, // No platform options
3790b57cec5SDimitry Andric           new_target_sp);
3800b57cec5SDimitry Andric       target = new_target_sp.get();
3810b57cec5SDimitry Andric       if (target == nullptr || error.Fail()) {
3820b57cec5SDimitry Andric         result.AppendError(error.AsCString("Error creating target"));
3830b57cec5SDimitry Andric         return false;
3840b57cec5SDimitry Andric       }
3850b57cec5SDimitry Andric     }
3860b57cec5SDimitry Andric 
3870b57cec5SDimitry Andric     // Record the old executable module, we want to issue a warning if the
3880b57cec5SDimitry Andric     // process of attaching changed the current executable (like somebody said
3890b57cec5SDimitry Andric     // "file foo" then attached to a PID whose executable was bar.)
3900b57cec5SDimitry Andric 
3910b57cec5SDimitry Andric     ModuleSP old_exec_module_sp = target->GetExecutableModule();
3920b57cec5SDimitry Andric     ArchSpec old_arch_spec = target->GetArchitecture();
3930b57cec5SDimitry Andric 
3940b57cec5SDimitry Andric     if (command.GetArgumentCount()) {
3950b57cec5SDimitry Andric       result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: %s\n",
3960b57cec5SDimitry Andric                                    m_cmd_name.c_str(), m_cmd_syntax.c_str());
3970b57cec5SDimitry Andric       return false;
3980b57cec5SDimitry Andric     }
3990b57cec5SDimitry Andric 
4000b57cec5SDimitry Andric     StreamString stream;
4010b57cec5SDimitry Andric     const auto error = target->Attach(m_options.attach_info, &stream);
4020b57cec5SDimitry Andric     if (error.Success()) {
4030b57cec5SDimitry Andric       ProcessSP process_sp(target->GetProcessSP());
4040b57cec5SDimitry Andric       if (process_sp) {
4050b57cec5SDimitry Andric         result.AppendMessage(stream.GetString());
4060b57cec5SDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishNoResult);
4070b57cec5SDimitry Andric         result.SetDidChangeProcessState(true);
4080b57cec5SDimitry Andric       } else {
4090b57cec5SDimitry Andric         result.AppendError(
4100b57cec5SDimitry Andric             "no error returned from Target::Attach, and target has no process");
4110b57cec5SDimitry Andric       }
4120b57cec5SDimitry Andric     } else {
4130b57cec5SDimitry Andric       result.AppendErrorWithFormat("attach failed: %s\n", error.AsCString());
4140b57cec5SDimitry Andric     }
4150b57cec5SDimitry Andric 
4160b57cec5SDimitry Andric     if (!result.Succeeded())
4170b57cec5SDimitry Andric       return false;
4180b57cec5SDimitry Andric 
4190b57cec5SDimitry Andric     // Okay, we're done.  Last step is to warn if the executable module has
4200b57cec5SDimitry Andric     // changed:
4210b57cec5SDimitry Andric     char new_path[PATH_MAX];
4220b57cec5SDimitry Andric     ModuleSP new_exec_module_sp(target->GetExecutableModule());
4230b57cec5SDimitry Andric     if (!old_exec_module_sp) {
4240b57cec5SDimitry Andric       // We might not have a module if we attached to a raw pid...
4250b57cec5SDimitry Andric       if (new_exec_module_sp) {
4260b57cec5SDimitry Andric         new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX);
4270b57cec5SDimitry Andric         result.AppendMessageWithFormat("Executable module set to \"%s\".\n",
4280b57cec5SDimitry Andric                                        new_path);
4290b57cec5SDimitry Andric       }
4300b57cec5SDimitry Andric     } else if (old_exec_module_sp->GetFileSpec() !=
4310b57cec5SDimitry Andric                new_exec_module_sp->GetFileSpec()) {
4320b57cec5SDimitry Andric       char old_path[PATH_MAX];
4330b57cec5SDimitry Andric 
4340b57cec5SDimitry Andric       old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX);
4350b57cec5SDimitry Andric       new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX);
4360b57cec5SDimitry Andric 
4370b57cec5SDimitry Andric       result.AppendWarningWithFormat(
4380b57cec5SDimitry Andric           "Executable module changed from \"%s\" to \"%s\".\n", old_path,
4390b57cec5SDimitry Andric           new_path);
4400b57cec5SDimitry Andric     }
4410b57cec5SDimitry Andric 
4420b57cec5SDimitry Andric     if (!old_arch_spec.IsValid()) {
4430b57cec5SDimitry Andric       result.AppendMessageWithFormat(
4440b57cec5SDimitry Andric           "Architecture set to: %s.\n",
4450b57cec5SDimitry Andric           target->GetArchitecture().GetTriple().getTriple().c_str());
4460b57cec5SDimitry Andric     } else if (!old_arch_spec.IsExactMatch(target->GetArchitecture())) {
4470b57cec5SDimitry Andric       result.AppendWarningWithFormat(
4480b57cec5SDimitry Andric           "Architecture changed from %s to %s.\n",
4490b57cec5SDimitry Andric           old_arch_spec.GetTriple().getTriple().c_str(),
4500b57cec5SDimitry Andric           target->GetArchitecture().GetTriple().getTriple().c_str());
4510b57cec5SDimitry Andric     }
4520b57cec5SDimitry Andric 
4530b57cec5SDimitry Andric     // This supports the use-case scenario of immediately continuing the
4540b57cec5SDimitry Andric     // process once attached.
4550b57cec5SDimitry Andric     if (m_options.attach_info.GetContinueOnceAttached())
4560b57cec5SDimitry Andric       m_interpreter.HandleCommand("process continue", eLazyBoolNo, result);
4570b57cec5SDimitry Andric 
4580b57cec5SDimitry Andric     return result.Succeeded();
4590b57cec5SDimitry Andric   }
4600b57cec5SDimitry Andric 
4610b57cec5SDimitry Andric   CommandOptions m_options;
4620b57cec5SDimitry Andric };
4630b57cec5SDimitry Andric 
4640b57cec5SDimitry Andric // CommandObjectProcessContinue
4650b57cec5SDimitry Andric 
4669dba64beSDimitry Andric #define LLDB_OPTIONS_process_continue
4679dba64beSDimitry Andric #include "CommandOptions.inc"
4680b57cec5SDimitry Andric 
4690b57cec5SDimitry Andric #pragma mark CommandObjectProcessContinue
4700b57cec5SDimitry Andric 
4710b57cec5SDimitry Andric class CommandObjectProcessContinue : public CommandObjectParsed {
4720b57cec5SDimitry Andric public:
CommandObjectProcessContinue(CommandInterpreter & interpreter)4730b57cec5SDimitry Andric   CommandObjectProcessContinue(CommandInterpreter &interpreter)
4740b57cec5SDimitry Andric       : CommandObjectParsed(
4750b57cec5SDimitry Andric             interpreter, "process continue",
4760b57cec5SDimitry Andric             "Continue execution of all threads in the current process.",
4770b57cec5SDimitry Andric             "process continue",
4780b57cec5SDimitry Andric             eCommandRequiresProcess | eCommandTryTargetAPILock |
4790b57cec5SDimitry Andric                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused),
4800b57cec5SDimitry Andric         m_options() {}
4810b57cec5SDimitry Andric 
4820b57cec5SDimitry Andric   ~CommandObjectProcessContinue() override = default;
4830b57cec5SDimitry Andric 
4840b57cec5SDimitry Andric protected:
4850b57cec5SDimitry Andric   class CommandOptions : public Options {
4860b57cec5SDimitry Andric   public:
CommandOptions()4870b57cec5SDimitry Andric     CommandOptions() : Options() {
4880b57cec5SDimitry Andric       // Keep default values of all options in one place: OptionParsingStarting
4890b57cec5SDimitry Andric       // ()
4900b57cec5SDimitry Andric       OptionParsingStarting(nullptr);
4910b57cec5SDimitry Andric     }
4920b57cec5SDimitry Andric 
4930b57cec5SDimitry Andric     ~CommandOptions() override = default;
4940b57cec5SDimitry Andric 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)4950b57cec5SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
4960b57cec5SDimitry Andric                           ExecutionContext *execution_context) override {
4970b57cec5SDimitry Andric       Status error;
4980b57cec5SDimitry Andric       const int short_option = m_getopt_table[option_idx].val;
4990b57cec5SDimitry Andric       switch (short_option) {
5000b57cec5SDimitry Andric       case 'i':
5010b57cec5SDimitry Andric         if (option_arg.getAsInteger(0, m_ignore))
5020b57cec5SDimitry Andric           error.SetErrorStringWithFormat(
5030b57cec5SDimitry Andric               "invalid value for ignore option: \"%s\", should be a number.",
5040b57cec5SDimitry Andric               option_arg.str().c_str());
5050b57cec5SDimitry Andric         break;
5060b57cec5SDimitry Andric 
5070b57cec5SDimitry Andric       default:
5089dba64beSDimitry Andric         llvm_unreachable("Unimplemented option");
5090b57cec5SDimitry Andric       }
5100b57cec5SDimitry Andric       return error;
5110b57cec5SDimitry Andric     }
5120b57cec5SDimitry Andric 
OptionParsingStarting(ExecutionContext * execution_context)5130b57cec5SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
5140b57cec5SDimitry Andric       m_ignore = 0;
5150b57cec5SDimitry Andric     }
5160b57cec5SDimitry Andric 
GetDefinitions()5170b57cec5SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
5180b57cec5SDimitry Andric       return llvm::makeArrayRef(g_process_continue_options);
5190b57cec5SDimitry Andric     }
5200b57cec5SDimitry Andric 
5210b57cec5SDimitry Andric     uint32_t m_ignore;
5220b57cec5SDimitry Andric   };
5230b57cec5SDimitry Andric 
DoExecute(Args & command,CommandReturnObject & result)5240b57cec5SDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
5250b57cec5SDimitry Andric     Process *process = m_exe_ctx.GetProcessPtr();
5260b57cec5SDimitry Andric     bool synchronous_execution = m_interpreter.GetSynchronous();
5270b57cec5SDimitry Andric     StateType state = process->GetState();
5280b57cec5SDimitry Andric     if (state == eStateStopped) {
5290b57cec5SDimitry Andric       if (command.GetArgumentCount() != 0) {
5300b57cec5SDimitry Andric         result.AppendErrorWithFormat(
5310b57cec5SDimitry Andric             "The '%s' command does not take any arguments.\n",
5320b57cec5SDimitry Andric             m_cmd_name.c_str());
5330b57cec5SDimitry Andric         return false;
5340b57cec5SDimitry Andric       }
5350b57cec5SDimitry Andric 
5360b57cec5SDimitry Andric       if (m_options.m_ignore > 0) {
5370b57cec5SDimitry Andric         ThreadSP sel_thread_sp(GetDefaultThread()->shared_from_this());
5380b57cec5SDimitry Andric         if (sel_thread_sp) {
5390b57cec5SDimitry Andric           StopInfoSP stop_info_sp = sel_thread_sp->GetStopInfo();
5400b57cec5SDimitry Andric           if (stop_info_sp &&
5410b57cec5SDimitry Andric               stop_info_sp->GetStopReason() == eStopReasonBreakpoint) {
5420b57cec5SDimitry Andric             lldb::break_id_t bp_site_id =
5430b57cec5SDimitry Andric                 (lldb::break_id_t)stop_info_sp->GetValue();
5440b57cec5SDimitry Andric             BreakpointSiteSP bp_site_sp(
5450b57cec5SDimitry Andric                 process->GetBreakpointSiteList().FindByID(bp_site_id));
5460b57cec5SDimitry Andric             if (bp_site_sp) {
5470b57cec5SDimitry Andric               const size_t num_owners = bp_site_sp->GetNumberOfOwners();
5480b57cec5SDimitry Andric               for (size_t i = 0; i < num_owners; i++) {
5490b57cec5SDimitry Andric                 Breakpoint &bp_ref =
5500b57cec5SDimitry Andric                     bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint();
5510b57cec5SDimitry Andric                 if (!bp_ref.IsInternal()) {
5520b57cec5SDimitry Andric                   bp_ref.SetIgnoreCount(m_options.m_ignore);
5530b57cec5SDimitry Andric                 }
5540b57cec5SDimitry Andric               }
5550b57cec5SDimitry Andric             }
5560b57cec5SDimitry Andric           }
5570b57cec5SDimitry Andric         }
5580b57cec5SDimitry Andric       }
5590b57cec5SDimitry Andric 
5600b57cec5SDimitry Andric       { // Scope for thread list mutex:
5610b57cec5SDimitry Andric         std::lock_guard<std::recursive_mutex> guard(
5620b57cec5SDimitry Andric             process->GetThreadList().GetMutex());
5630b57cec5SDimitry Andric         const uint32_t num_threads = process->GetThreadList().GetSize();
5640b57cec5SDimitry Andric 
5650b57cec5SDimitry Andric         // Set the actions that the threads should each take when resuming
5660b57cec5SDimitry Andric         for (uint32_t idx = 0; idx < num_threads; ++idx) {
5670b57cec5SDimitry Andric           const bool override_suspend = false;
5680b57cec5SDimitry Andric           process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState(
5690b57cec5SDimitry Andric               eStateRunning, override_suspend);
5700b57cec5SDimitry Andric         }
5710b57cec5SDimitry Andric       }
5720b57cec5SDimitry Andric 
5730b57cec5SDimitry Andric       const uint32_t iohandler_id = process->GetIOHandlerID();
5740b57cec5SDimitry Andric 
5750b57cec5SDimitry Andric       StreamString stream;
5760b57cec5SDimitry Andric       Status error;
5770b57cec5SDimitry Andric       if (synchronous_execution)
5780b57cec5SDimitry Andric         error = process->ResumeSynchronous(&stream);
5790b57cec5SDimitry Andric       else
5800b57cec5SDimitry Andric         error = process->Resume();
5810b57cec5SDimitry Andric 
5820b57cec5SDimitry Andric       if (error.Success()) {
5830b57cec5SDimitry Andric         // There is a race condition where this thread will return up the call
5840b57cec5SDimitry Andric         // stack to the main command handler and show an (lldb) prompt before
5850b57cec5SDimitry Andric         // HandlePrivateEvent (from PrivateStateThread) has a chance to call
5860b57cec5SDimitry Andric         // PushProcessIOHandler().
5870b57cec5SDimitry Andric         process->SyncIOHandler(iohandler_id, std::chrono::seconds(2));
5880b57cec5SDimitry Andric 
5890b57cec5SDimitry Andric         result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n",
5900b57cec5SDimitry Andric                                        process->GetID());
5910b57cec5SDimitry Andric         if (synchronous_execution) {
5920b57cec5SDimitry Andric           // If any state changed events had anything to say, add that to the
5930b57cec5SDimitry Andric           // result
5940b57cec5SDimitry Andric           result.AppendMessage(stream.GetString());
5950b57cec5SDimitry Andric 
5960b57cec5SDimitry Andric           result.SetDidChangeProcessState(true);
5970b57cec5SDimitry Andric           result.SetStatus(eReturnStatusSuccessFinishNoResult);
5980b57cec5SDimitry Andric         } else {
5990b57cec5SDimitry Andric           result.SetStatus(eReturnStatusSuccessContinuingNoResult);
6000b57cec5SDimitry Andric         }
6010b57cec5SDimitry Andric       } else {
6020b57cec5SDimitry Andric         result.AppendErrorWithFormat("Failed to resume process: %s.\n",
6030b57cec5SDimitry Andric                                      error.AsCString());
6040b57cec5SDimitry Andric       }
6050b57cec5SDimitry Andric     } else {
6060b57cec5SDimitry Andric       result.AppendErrorWithFormat(
6070b57cec5SDimitry Andric           "Process cannot be continued from its current state (%s).\n",
6080b57cec5SDimitry Andric           StateAsCString(state));
6090b57cec5SDimitry Andric     }
6100b57cec5SDimitry Andric     return result.Succeeded();
6110b57cec5SDimitry Andric   }
6120b57cec5SDimitry Andric 
GetOptions()6130b57cec5SDimitry Andric   Options *GetOptions() override { return &m_options; }
6140b57cec5SDimitry Andric 
6150b57cec5SDimitry Andric   CommandOptions m_options;
6160b57cec5SDimitry Andric };
6170b57cec5SDimitry Andric 
6180b57cec5SDimitry Andric // CommandObjectProcessDetach
6199dba64beSDimitry Andric #define LLDB_OPTIONS_process_detach
6209dba64beSDimitry Andric #include "CommandOptions.inc"
6210b57cec5SDimitry Andric 
6220b57cec5SDimitry Andric #pragma mark CommandObjectProcessDetach
6230b57cec5SDimitry Andric 
6240b57cec5SDimitry Andric class CommandObjectProcessDetach : public CommandObjectParsed {
6250b57cec5SDimitry Andric public:
6260b57cec5SDimitry Andric   class CommandOptions : public Options {
6270b57cec5SDimitry Andric   public:
CommandOptions()6280b57cec5SDimitry Andric     CommandOptions() : Options() { OptionParsingStarting(nullptr); }
6290b57cec5SDimitry Andric 
6300b57cec5SDimitry Andric     ~CommandOptions() override = default;
6310b57cec5SDimitry Andric 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)6320b57cec5SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
6330b57cec5SDimitry Andric                           ExecutionContext *execution_context) override {
6340b57cec5SDimitry Andric       Status error;
6350b57cec5SDimitry Andric       const int short_option = m_getopt_table[option_idx].val;
6360b57cec5SDimitry Andric 
6370b57cec5SDimitry Andric       switch (short_option) {
6380b57cec5SDimitry Andric       case 's':
6390b57cec5SDimitry Andric         bool tmp_result;
6400b57cec5SDimitry Andric         bool success;
6410b57cec5SDimitry Andric         tmp_result = OptionArgParser::ToBoolean(option_arg, false, &success);
6420b57cec5SDimitry Andric         if (!success)
6430b57cec5SDimitry Andric           error.SetErrorStringWithFormat("invalid boolean option: \"%s\"",
6440b57cec5SDimitry Andric                                          option_arg.str().c_str());
6450b57cec5SDimitry Andric         else {
6460b57cec5SDimitry Andric           if (tmp_result)
6470b57cec5SDimitry Andric             m_keep_stopped = eLazyBoolYes;
6480b57cec5SDimitry Andric           else
6490b57cec5SDimitry Andric             m_keep_stopped = eLazyBoolNo;
6500b57cec5SDimitry Andric         }
6510b57cec5SDimitry Andric         break;
6520b57cec5SDimitry Andric       default:
6539dba64beSDimitry Andric         llvm_unreachable("Unimplemented option");
6540b57cec5SDimitry Andric       }
6550b57cec5SDimitry Andric       return error;
6560b57cec5SDimitry Andric     }
6570b57cec5SDimitry Andric 
OptionParsingStarting(ExecutionContext * execution_context)6580b57cec5SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
6590b57cec5SDimitry Andric       m_keep_stopped = eLazyBoolCalculate;
6600b57cec5SDimitry Andric     }
6610b57cec5SDimitry Andric 
GetDefinitions()6620b57cec5SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
6630b57cec5SDimitry Andric       return llvm::makeArrayRef(g_process_detach_options);
6640b57cec5SDimitry Andric     }
6650b57cec5SDimitry Andric 
6660b57cec5SDimitry Andric     // Instance variables to hold the values for command options.
6670b57cec5SDimitry Andric     LazyBool m_keep_stopped;
6680b57cec5SDimitry Andric   };
6690b57cec5SDimitry Andric 
CommandObjectProcessDetach(CommandInterpreter & interpreter)6700b57cec5SDimitry Andric   CommandObjectProcessDetach(CommandInterpreter &interpreter)
6710b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "process detach",
6720b57cec5SDimitry Andric                             "Detach from the current target process.",
6730b57cec5SDimitry Andric                             "process detach",
6740b57cec5SDimitry Andric                             eCommandRequiresProcess | eCommandTryTargetAPILock |
6750b57cec5SDimitry Andric                                 eCommandProcessMustBeLaunched),
6760b57cec5SDimitry Andric         m_options() {}
6770b57cec5SDimitry Andric 
6780b57cec5SDimitry Andric   ~CommandObjectProcessDetach() override = default;
6790b57cec5SDimitry Andric 
GetOptions()6800b57cec5SDimitry Andric   Options *GetOptions() override { return &m_options; }
6810b57cec5SDimitry Andric 
6820b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)6830b57cec5SDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
6840b57cec5SDimitry Andric     Process *process = m_exe_ctx.GetProcessPtr();
6850b57cec5SDimitry Andric     // FIXME: This will be a Command Option:
6860b57cec5SDimitry Andric     bool keep_stopped;
6870b57cec5SDimitry Andric     if (m_options.m_keep_stopped == eLazyBoolCalculate) {
6880b57cec5SDimitry Andric       // Check the process default:
6890b57cec5SDimitry Andric       keep_stopped = process->GetDetachKeepsStopped();
6900b57cec5SDimitry Andric     } else if (m_options.m_keep_stopped == eLazyBoolYes)
6910b57cec5SDimitry Andric       keep_stopped = true;
6920b57cec5SDimitry Andric     else
6930b57cec5SDimitry Andric       keep_stopped = false;
6940b57cec5SDimitry Andric 
6950b57cec5SDimitry Andric     Status error(process->Detach(keep_stopped));
6960b57cec5SDimitry Andric     if (error.Success()) {
6970b57cec5SDimitry Andric       result.SetStatus(eReturnStatusSuccessFinishResult);
6980b57cec5SDimitry Andric     } else {
6990b57cec5SDimitry Andric       result.AppendErrorWithFormat("Detach failed: %s\n", error.AsCString());
7000b57cec5SDimitry Andric       return false;
7010b57cec5SDimitry Andric     }
7020b57cec5SDimitry Andric     return result.Succeeded();
7030b57cec5SDimitry Andric   }
7040b57cec5SDimitry Andric 
7050b57cec5SDimitry Andric   CommandOptions m_options;
7060b57cec5SDimitry Andric };
7070b57cec5SDimitry Andric 
7080b57cec5SDimitry Andric // CommandObjectProcessConnect
7099dba64beSDimitry Andric #define LLDB_OPTIONS_process_connect
7109dba64beSDimitry Andric #include "CommandOptions.inc"
7110b57cec5SDimitry Andric 
7120b57cec5SDimitry Andric #pragma mark CommandObjectProcessConnect
7130b57cec5SDimitry Andric 
7140b57cec5SDimitry Andric class CommandObjectProcessConnect : public CommandObjectParsed {
7150b57cec5SDimitry Andric public:
7160b57cec5SDimitry Andric   class CommandOptions : public Options {
7170b57cec5SDimitry Andric   public:
CommandOptions()7180b57cec5SDimitry Andric     CommandOptions() : Options() {
7190b57cec5SDimitry Andric       // Keep default values of all options in one place: OptionParsingStarting
7200b57cec5SDimitry Andric       // ()
7210b57cec5SDimitry Andric       OptionParsingStarting(nullptr);
7220b57cec5SDimitry Andric     }
7230b57cec5SDimitry Andric 
7240b57cec5SDimitry Andric     ~CommandOptions() override = default;
7250b57cec5SDimitry Andric 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)7260b57cec5SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
7270b57cec5SDimitry Andric                           ExecutionContext *execution_context) override {
7280b57cec5SDimitry Andric       Status error;
7290b57cec5SDimitry Andric       const int short_option = m_getopt_table[option_idx].val;
7300b57cec5SDimitry Andric 
7310b57cec5SDimitry Andric       switch (short_option) {
7320b57cec5SDimitry Andric       case 'p':
7335ffd83dbSDimitry Andric         plugin_name.assign(std::string(option_arg));
7340b57cec5SDimitry Andric         break;
7350b57cec5SDimitry Andric 
7360b57cec5SDimitry Andric       default:
7379dba64beSDimitry Andric         llvm_unreachable("Unimplemented option");
7380b57cec5SDimitry Andric       }
7390b57cec5SDimitry Andric       return error;
7400b57cec5SDimitry Andric     }
7410b57cec5SDimitry Andric 
OptionParsingStarting(ExecutionContext * execution_context)7420b57cec5SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
7430b57cec5SDimitry Andric       plugin_name.clear();
7440b57cec5SDimitry Andric     }
7450b57cec5SDimitry Andric 
GetDefinitions()7460b57cec5SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
7470b57cec5SDimitry Andric       return llvm::makeArrayRef(g_process_connect_options);
7480b57cec5SDimitry Andric     }
7490b57cec5SDimitry Andric 
7500b57cec5SDimitry Andric     // Instance variables to hold the values for command options.
7510b57cec5SDimitry Andric 
7520b57cec5SDimitry Andric     std::string plugin_name;
7530b57cec5SDimitry Andric   };
7540b57cec5SDimitry Andric 
CommandObjectProcessConnect(CommandInterpreter & interpreter)7550b57cec5SDimitry Andric   CommandObjectProcessConnect(CommandInterpreter &interpreter)
7560b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "process connect",
7570b57cec5SDimitry Andric                             "Connect to a remote debug service.",
7580b57cec5SDimitry Andric                             "process connect <remote-url>", 0),
7590b57cec5SDimitry Andric         m_options() {}
7600b57cec5SDimitry Andric 
7610b57cec5SDimitry Andric   ~CommandObjectProcessConnect() override = default;
7620b57cec5SDimitry Andric 
GetOptions()7630b57cec5SDimitry Andric   Options *GetOptions() override { return &m_options; }
7640b57cec5SDimitry Andric 
7650b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)7660b57cec5SDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
7670b57cec5SDimitry Andric     if (command.GetArgumentCount() != 1) {
7680b57cec5SDimitry Andric       result.AppendErrorWithFormat(
7690b57cec5SDimitry Andric           "'%s' takes exactly one argument:\nUsage: %s\n", m_cmd_name.c_str(),
7700b57cec5SDimitry Andric           m_cmd_syntax.c_str());
7710b57cec5SDimitry Andric       return false;
7720b57cec5SDimitry Andric     }
7730b57cec5SDimitry Andric 
7740b57cec5SDimitry Andric     Process *process = m_exe_ctx.GetProcessPtr();
7750b57cec5SDimitry Andric     if (process && process->IsAlive()) {
7760b57cec5SDimitry Andric       result.AppendErrorWithFormat(
7770b57cec5SDimitry Andric           "Process %" PRIu64
7780b57cec5SDimitry Andric           " is currently being debugged, kill the process before connecting.\n",
7790b57cec5SDimitry Andric           process->GetID());
7800b57cec5SDimitry Andric       return false;
7810b57cec5SDimitry Andric     }
7820b57cec5SDimitry Andric 
7830b57cec5SDimitry Andric     const char *plugin_name = nullptr;
7840b57cec5SDimitry Andric     if (!m_options.plugin_name.empty())
7850b57cec5SDimitry Andric       plugin_name = m_options.plugin_name.c_str();
7860b57cec5SDimitry Andric 
7870b57cec5SDimitry Andric     Status error;
7880b57cec5SDimitry Andric     Debugger &debugger = GetDebugger();
7890b57cec5SDimitry Andric     PlatformSP platform_sp = m_interpreter.GetPlatform(true);
7905ffd83dbSDimitry Andric     ProcessSP process_sp =
7915ffd83dbSDimitry Andric         debugger.GetAsyncExecution()
7925ffd83dbSDimitry Andric             ? platform_sp->ConnectProcess(
7930b57cec5SDimitry Andric                   command.GetArgumentAtIndex(0), plugin_name, debugger,
7945ffd83dbSDimitry Andric                   debugger.GetSelectedTarget().get(), error)
7955ffd83dbSDimitry Andric             : platform_sp->ConnectProcessSynchronous(
7965ffd83dbSDimitry Andric                   command.GetArgumentAtIndex(0), plugin_name, debugger,
7975ffd83dbSDimitry Andric                   result.GetOutputStream(), debugger.GetSelectedTarget().get(),
7985ffd83dbSDimitry Andric                   error);
7990b57cec5SDimitry Andric     if (error.Fail() || process_sp == nullptr) {
8000b57cec5SDimitry Andric       result.AppendError(error.AsCString("Error connecting to the process"));
8010b57cec5SDimitry Andric       return false;
8020b57cec5SDimitry Andric     }
8030b57cec5SDimitry Andric     return true;
8040b57cec5SDimitry Andric   }
8050b57cec5SDimitry Andric 
8060b57cec5SDimitry Andric   CommandOptions m_options;
8070b57cec5SDimitry Andric };
8080b57cec5SDimitry Andric 
8090b57cec5SDimitry Andric // CommandObjectProcessPlugin
8100b57cec5SDimitry Andric #pragma mark CommandObjectProcessPlugin
8110b57cec5SDimitry Andric 
8120b57cec5SDimitry Andric class CommandObjectProcessPlugin : public CommandObjectProxy {
8130b57cec5SDimitry Andric public:
CommandObjectProcessPlugin(CommandInterpreter & interpreter)8140b57cec5SDimitry Andric   CommandObjectProcessPlugin(CommandInterpreter &interpreter)
8150b57cec5SDimitry Andric       : CommandObjectProxy(
8160b57cec5SDimitry Andric             interpreter, "process plugin",
8170b57cec5SDimitry Andric             "Send a custom command to the current target process plug-in.",
8180b57cec5SDimitry Andric             "process plugin <args>", 0) {}
8190b57cec5SDimitry Andric 
8200b57cec5SDimitry Andric   ~CommandObjectProcessPlugin() override = default;
8210b57cec5SDimitry Andric 
GetProxyCommandObject()8220b57cec5SDimitry Andric   CommandObject *GetProxyCommandObject() override {
8230b57cec5SDimitry Andric     Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
8240b57cec5SDimitry Andric     if (process)
8250b57cec5SDimitry Andric       return process->GetPluginCommandObject();
8260b57cec5SDimitry Andric     return nullptr;
8270b57cec5SDimitry Andric   }
8280b57cec5SDimitry Andric };
8290b57cec5SDimitry Andric 
8300b57cec5SDimitry Andric // CommandObjectProcessLoad
8319dba64beSDimitry Andric #define LLDB_OPTIONS_process_load
8329dba64beSDimitry Andric #include "CommandOptions.inc"
8330b57cec5SDimitry Andric 
8340b57cec5SDimitry Andric #pragma mark CommandObjectProcessLoad
8350b57cec5SDimitry Andric 
8360b57cec5SDimitry Andric class CommandObjectProcessLoad : public CommandObjectParsed {
8370b57cec5SDimitry Andric public:
8380b57cec5SDimitry Andric   class CommandOptions : public Options {
8390b57cec5SDimitry Andric   public:
CommandOptions()8400b57cec5SDimitry Andric     CommandOptions() : Options() {
8410b57cec5SDimitry Andric       // Keep default values of all options in one place: OptionParsingStarting
8420b57cec5SDimitry Andric       // ()
8430b57cec5SDimitry Andric       OptionParsingStarting(nullptr);
8440b57cec5SDimitry Andric     }
8450b57cec5SDimitry Andric 
8460b57cec5SDimitry Andric     ~CommandOptions() override = default;
8470b57cec5SDimitry Andric 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)8480b57cec5SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
8490b57cec5SDimitry Andric                           ExecutionContext *execution_context) override {
8500b57cec5SDimitry Andric       Status error;
8510b57cec5SDimitry Andric       const int short_option = m_getopt_table[option_idx].val;
8520b57cec5SDimitry Andric       switch (short_option) {
8530b57cec5SDimitry Andric       case 'i':
8540b57cec5SDimitry Andric         do_install = true;
8550b57cec5SDimitry Andric         if (!option_arg.empty())
8560b57cec5SDimitry Andric           install_path.SetFile(option_arg, FileSpec::Style::native);
8570b57cec5SDimitry Andric         break;
8580b57cec5SDimitry Andric       default:
8599dba64beSDimitry Andric         llvm_unreachable("Unimplemented option");
8600b57cec5SDimitry Andric       }
8610b57cec5SDimitry Andric       return error;
8620b57cec5SDimitry Andric     }
8630b57cec5SDimitry Andric 
OptionParsingStarting(ExecutionContext * execution_context)8640b57cec5SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
8650b57cec5SDimitry Andric       do_install = false;
8660b57cec5SDimitry Andric       install_path.Clear();
8670b57cec5SDimitry Andric     }
8680b57cec5SDimitry Andric 
GetDefinitions()8690b57cec5SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
8700b57cec5SDimitry Andric       return llvm::makeArrayRef(g_process_load_options);
8710b57cec5SDimitry Andric     }
8720b57cec5SDimitry Andric 
8730b57cec5SDimitry Andric     // Instance variables to hold the values for command options.
8740b57cec5SDimitry Andric     bool do_install;
8750b57cec5SDimitry Andric     FileSpec install_path;
8760b57cec5SDimitry Andric   };
8770b57cec5SDimitry Andric 
CommandObjectProcessLoad(CommandInterpreter & interpreter)8780b57cec5SDimitry Andric   CommandObjectProcessLoad(CommandInterpreter &interpreter)
8790b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "process load",
8800b57cec5SDimitry Andric                             "Load a shared library into the current process.",
8810b57cec5SDimitry Andric                             "process load <filename> [<filename> ...]",
8820b57cec5SDimitry Andric                             eCommandRequiresProcess | eCommandTryTargetAPILock |
8830b57cec5SDimitry Andric                                 eCommandProcessMustBeLaunched |
8840b57cec5SDimitry Andric                                 eCommandProcessMustBePaused),
8850b57cec5SDimitry Andric         m_options() {}
8860b57cec5SDimitry Andric 
8870b57cec5SDimitry Andric   ~CommandObjectProcessLoad() override = default;
8880b57cec5SDimitry Andric 
889af732203SDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)890af732203SDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
891af732203SDimitry Andric                            OptionElementVector &opt_element_vector) override {
892af732203SDimitry Andric     if (!m_exe_ctx.HasProcessScope())
893af732203SDimitry Andric       return;
894af732203SDimitry Andric 
895af732203SDimitry Andric     CommandCompletions::InvokeCommonCompletionCallbacks(
896af732203SDimitry Andric         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
897af732203SDimitry Andric         request, nullptr);
898af732203SDimitry Andric   }
899af732203SDimitry Andric 
GetOptions()9000b57cec5SDimitry Andric   Options *GetOptions() override { return &m_options; }
9010b57cec5SDimitry Andric 
9020b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)9030b57cec5SDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
9040b57cec5SDimitry Andric     Process *process = m_exe_ctx.GetProcessPtr();
9050b57cec5SDimitry Andric 
9060b57cec5SDimitry Andric     for (auto &entry : command.entries()) {
9070b57cec5SDimitry Andric       Status error;
9080b57cec5SDimitry Andric       PlatformSP platform = process->GetTarget().GetPlatform();
9099dba64beSDimitry Andric       llvm::StringRef image_path = entry.ref();
9100b57cec5SDimitry Andric       uint32_t image_token = LLDB_INVALID_IMAGE_TOKEN;
9110b57cec5SDimitry Andric 
9120b57cec5SDimitry Andric       if (!m_options.do_install) {
9130b57cec5SDimitry Andric         FileSpec image_spec(image_path);
9140b57cec5SDimitry Andric         platform->ResolveRemotePath(image_spec, image_spec);
9150b57cec5SDimitry Andric         image_token =
9160b57cec5SDimitry Andric             platform->LoadImage(process, FileSpec(), image_spec, error);
9170b57cec5SDimitry Andric       } else if (m_options.install_path) {
9180b57cec5SDimitry Andric         FileSpec image_spec(image_path);
9190b57cec5SDimitry Andric         FileSystem::Instance().Resolve(image_spec);
9200b57cec5SDimitry Andric         platform->ResolveRemotePath(m_options.install_path,
9210b57cec5SDimitry Andric                                     m_options.install_path);
9220b57cec5SDimitry Andric         image_token = platform->LoadImage(process, image_spec,
9230b57cec5SDimitry Andric                                           m_options.install_path, error);
9240b57cec5SDimitry Andric       } else {
9250b57cec5SDimitry Andric         FileSpec image_spec(image_path);
9260b57cec5SDimitry Andric         FileSystem::Instance().Resolve(image_spec);
9270b57cec5SDimitry Andric         image_token =
9280b57cec5SDimitry Andric             platform->LoadImage(process, image_spec, FileSpec(), error);
9290b57cec5SDimitry Andric       }
9300b57cec5SDimitry Andric 
9310b57cec5SDimitry Andric       if (image_token != LLDB_INVALID_IMAGE_TOKEN) {
9320b57cec5SDimitry Andric         result.AppendMessageWithFormat(
9330b57cec5SDimitry Andric             "Loading \"%s\"...ok\nImage %u loaded.\n", image_path.str().c_str(),
9340b57cec5SDimitry Andric             image_token);
9350b57cec5SDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishResult);
9360b57cec5SDimitry Andric       } else {
9370b57cec5SDimitry Andric         result.AppendErrorWithFormat("failed to load '%s': %s",
9380b57cec5SDimitry Andric                                      image_path.str().c_str(),
9390b57cec5SDimitry Andric                                      error.AsCString());
9400b57cec5SDimitry Andric       }
9410b57cec5SDimitry Andric     }
9420b57cec5SDimitry Andric     return result.Succeeded();
9430b57cec5SDimitry Andric   }
9440b57cec5SDimitry Andric 
9450b57cec5SDimitry Andric   CommandOptions m_options;
9460b57cec5SDimitry Andric };
9470b57cec5SDimitry Andric 
9480b57cec5SDimitry Andric // CommandObjectProcessUnload
9490b57cec5SDimitry Andric #pragma mark CommandObjectProcessUnload
9500b57cec5SDimitry Andric 
9510b57cec5SDimitry Andric class CommandObjectProcessUnload : public CommandObjectParsed {
9520b57cec5SDimitry Andric public:
CommandObjectProcessUnload(CommandInterpreter & interpreter)9530b57cec5SDimitry Andric   CommandObjectProcessUnload(CommandInterpreter &interpreter)
9540b57cec5SDimitry Andric       : CommandObjectParsed(
9550b57cec5SDimitry Andric             interpreter, "process unload",
9560b57cec5SDimitry Andric             "Unload a shared library from the current process using the index "
9570b57cec5SDimitry Andric             "returned by a previous call to \"process load\".",
9580b57cec5SDimitry Andric             "process unload <index>",
9590b57cec5SDimitry Andric             eCommandRequiresProcess | eCommandTryTargetAPILock |
9600b57cec5SDimitry Andric                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {}
9610b57cec5SDimitry Andric 
9620b57cec5SDimitry Andric   ~CommandObjectProcessUnload() override = default;
9630b57cec5SDimitry Andric 
964af732203SDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)965af732203SDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
966af732203SDimitry Andric                            OptionElementVector &opt_element_vector) override {
967af732203SDimitry Andric 
968af732203SDimitry Andric     if (request.GetCursorIndex() || !m_exe_ctx.HasProcessScope())
969af732203SDimitry Andric       return;
970af732203SDimitry Andric 
971af732203SDimitry Andric     Process *process = m_exe_ctx.GetProcessPtr();
972af732203SDimitry Andric 
973af732203SDimitry Andric     const std::vector<lldb::addr_t> &tokens = process->GetImageTokens();
974af732203SDimitry Andric     const size_t token_num = tokens.size();
975af732203SDimitry Andric     for (size_t i = 0; i < token_num; ++i) {
976af732203SDimitry Andric       if (tokens[i] == LLDB_INVALID_IMAGE_TOKEN)
977af732203SDimitry Andric         continue;
978af732203SDimitry Andric       request.TryCompleteCurrentArg(std::to_string(i));
979af732203SDimitry Andric     }
980af732203SDimitry Andric   }
981af732203SDimitry Andric 
9820b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)9830b57cec5SDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
9840b57cec5SDimitry Andric     Process *process = m_exe_ctx.GetProcessPtr();
9850b57cec5SDimitry Andric 
9860b57cec5SDimitry Andric     for (auto &entry : command.entries()) {
9870b57cec5SDimitry Andric       uint32_t image_token;
9889dba64beSDimitry Andric       if (entry.ref().getAsInteger(0, image_token)) {
9890b57cec5SDimitry Andric         result.AppendErrorWithFormat("invalid image index argument '%s'",
9909dba64beSDimitry Andric                                      entry.ref().str().c_str());
9910b57cec5SDimitry Andric         break;
9920b57cec5SDimitry Andric       } else {
9930b57cec5SDimitry Andric         Status error(process->GetTarget().GetPlatform()->UnloadImage(
9940b57cec5SDimitry Andric             process, image_token));
9950b57cec5SDimitry Andric         if (error.Success()) {
9960b57cec5SDimitry Andric           result.AppendMessageWithFormat(
9970b57cec5SDimitry Andric               "Unloading shared library with index %u...ok\n", image_token);
9980b57cec5SDimitry Andric           result.SetStatus(eReturnStatusSuccessFinishResult);
9990b57cec5SDimitry Andric         } else {
10000b57cec5SDimitry Andric           result.AppendErrorWithFormat("failed to unload image: %s",
10010b57cec5SDimitry Andric                                        error.AsCString());
10020b57cec5SDimitry Andric           break;
10030b57cec5SDimitry Andric         }
10040b57cec5SDimitry Andric       }
10050b57cec5SDimitry Andric     }
10060b57cec5SDimitry Andric     return result.Succeeded();
10070b57cec5SDimitry Andric   }
10080b57cec5SDimitry Andric };
10090b57cec5SDimitry Andric 
10100b57cec5SDimitry Andric // CommandObjectProcessSignal
10110b57cec5SDimitry Andric #pragma mark CommandObjectProcessSignal
10120b57cec5SDimitry Andric 
10130b57cec5SDimitry Andric class CommandObjectProcessSignal : public CommandObjectParsed {
10140b57cec5SDimitry Andric public:
CommandObjectProcessSignal(CommandInterpreter & interpreter)10150b57cec5SDimitry Andric   CommandObjectProcessSignal(CommandInterpreter &interpreter)
1016480093f4SDimitry Andric       : CommandObjectParsed(
1017480093f4SDimitry Andric             interpreter, "process signal",
1018480093f4SDimitry Andric             "Send a UNIX signal to the current target process.", nullptr,
1019480093f4SDimitry Andric             eCommandRequiresProcess | eCommandTryTargetAPILock) {
10200b57cec5SDimitry Andric     CommandArgumentEntry arg;
10210b57cec5SDimitry Andric     CommandArgumentData signal_arg;
10220b57cec5SDimitry Andric 
10230b57cec5SDimitry Andric     // Define the first (and only) variant of this arg.
10240b57cec5SDimitry Andric     signal_arg.arg_type = eArgTypeUnixSignal;
10250b57cec5SDimitry Andric     signal_arg.arg_repetition = eArgRepeatPlain;
10260b57cec5SDimitry Andric 
10270b57cec5SDimitry Andric     // There is only one variant this argument could be; put it into the
10280b57cec5SDimitry Andric     // argument entry.
10290b57cec5SDimitry Andric     arg.push_back(signal_arg);
10300b57cec5SDimitry Andric 
10310b57cec5SDimitry Andric     // Push the data for the first argument into the m_arguments vector.
10320b57cec5SDimitry Andric     m_arguments.push_back(arg);
10330b57cec5SDimitry Andric   }
10340b57cec5SDimitry Andric 
10350b57cec5SDimitry Andric   ~CommandObjectProcessSignal() override = default;
10360b57cec5SDimitry Andric 
10375ffd83dbSDimitry Andric   void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)10385ffd83dbSDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
10395ffd83dbSDimitry Andric                            OptionElementVector &opt_element_vector) override {
10405ffd83dbSDimitry Andric     if (!m_exe_ctx.HasProcessScope() || request.GetCursorIndex() != 0)
10415ffd83dbSDimitry Andric       return;
10425ffd83dbSDimitry Andric 
10435ffd83dbSDimitry Andric     UnixSignalsSP signals = m_exe_ctx.GetProcessPtr()->GetUnixSignals();
10445ffd83dbSDimitry Andric     int signo = signals->GetFirstSignalNumber();
10455ffd83dbSDimitry Andric     while (signo != LLDB_INVALID_SIGNAL_NUMBER) {
1046*5f7ddb14SDimitry Andric       request.TryCompleteCurrentArg(signals->GetSignalAsCString(signo));
10475ffd83dbSDimitry Andric       signo = signals->GetNextSignalNumber(signo);
10485ffd83dbSDimitry Andric     }
10495ffd83dbSDimitry Andric   }
10505ffd83dbSDimitry Andric 
10510b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)10520b57cec5SDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
10530b57cec5SDimitry Andric     Process *process = m_exe_ctx.GetProcessPtr();
10540b57cec5SDimitry Andric 
10550b57cec5SDimitry Andric     if (command.GetArgumentCount() == 1) {
10560b57cec5SDimitry Andric       int signo = LLDB_INVALID_SIGNAL_NUMBER;
10570b57cec5SDimitry Andric 
10580b57cec5SDimitry Andric       const char *signal_name = command.GetArgumentAtIndex(0);
10595ffd83dbSDimitry Andric       if (::isxdigit(signal_name[0])) {
10605ffd83dbSDimitry Andric         if (!llvm::to_integer(signal_name, signo))
10615ffd83dbSDimitry Andric           signo = LLDB_INVALID_SIGNAL_NUMBER;
10625ffd83dbSDimitry Andric       } else
10630b57cec5SDimitry Andric         signo = process->GetUnixSignals()->GetSignalNumberFromName(signal_name);
10640b57cec5SDimitry Andric 
10650b57cec5SDimitry Andric       if (signo == LLDB_INVALID_SIGNAL_NUMBER) {
10660b57cec5SDimitry Andric         result.AppendErrorWithFormat("Invalid signal argument '%s'.\n",
10670b57cec5SDimitry Andric                                      command.GetArgumentAtIndex(0));
10680b57cec5SDimitry Andric       } else {
10690b57cec5SDimitry Andric         Status error(process->Signal(signo));
10700b57cec5SDimitry Andric         if (error.Success()) {
10710b57cec5SDimitry Andric           result.SetStatus(eReturnStatusSuccessFinishResult);
10720b57cec5SDimitry Andric         } else {
10730b57cec5SDimitry Andric           result.AppendErrorWithFormat("Failed to send signal %i: %s\n", signo,
10740b57cec5SDimitry Andric                                        error.AsCString());
10750b57cec5SDimitry Andric         }
10760b57cec5SDimitry Andric       }
10770b57cec5SDimitry Andric     } else {
10780b57cec5SDimitry Andric       result.AppendErrorWithFormat(
10790b57cec5SDimitry Andric           "'%s' takes exactly one signal number argument:\nUsage: %s\n",
10800b57cec5SDimitry Andric           m_cmd_name.c_str(), m_cmd_syntax.c_str());
10810b57cec5SDimitry Andric     }
10820b57cec5SDimitry Andric     return result.Succeeded();
10830b57cec5SDimitry Andric   }
10840b57cec5SDimitry Andric };
10850b57cec5SDimitry Andric 
10860b57cec5SDimitry Andric // CommandObjectProcessInterrupt
10870b57cec5SDimitry Andric #pragma mark CommandObjectProcessInterrupt
10880b57cec5SDimitry Andric 
10890b57cec5SDimitry Andric class CommandObjectProcessInterrupt : public CommandObjectParsed {
10900b57cec5SDimitry Andric public:
CommandObjectProcessInterrupt(CommandInterpreter & interpreter)10910b57cec5SDimitry Andric   CommandObjectProcessInterrupt(CommandInterpreter &interpreter)
10920b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "process interrupt",
10930b57cec5SDimitry Andric                             "Interrupt the current target process.",
10940b57cec5SDimitry Andric                             "process interrupt",
10950b57cec5SDimitry Andric                             eCommandRequiresProcess | eCommandTryTargetAPILock |
10960b57cec5SDimitry Andric                                 eCommandProcessMustBeLaunched) {}
10970b57cec5SDimitry Andric 
10980b57cec5SDimitry Andric   ~CommandObjectProcessInterrupt() override = default;
10990b57cec5SDimitry Andric 
11000b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)11010b57cec5SDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
11020b57cec5SDimitry Andric     Process *process = m_exe_ctx.GetProcessPtr();
11030b57cec5SDimitry Andric     if (process == nullptr) {
11040b57cec5SDimitry Andric       result.AppendError("no process to halt");
11050b57cec5SDimitry Andric       return false;
11060b57cec5SDimitry Andric     }
11070b57cec5SDimitry Andric 
11080b57cec5SDimitry Andric     if (command.GetArgumentCount() == 0) {
11090b57cec5SDimitry Andric       bool clear_thread_plans = true;
11100b57cec5SDimitry Andric       Status error(process->Halt(clear_thread_plans));
11110b57cec5SDimitry Andric       if (error.Success()) {
11120b57cec5SDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishResult);
11130b57cec5SDimitry Andric       } else {
11140b57cec5SDimitry Andric         result.AppendErrorWithFormat("Failed to halt process: %s\n",
11150b57cec5SDimitry Andric                                      error.AsCString());
11160b57cec5SDimitry Andric       }
11170b57cec5SDimitry Andric     } else {
11180b57cec5SDimitry Andric       result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n",
11190b57cec5SDimitry Andric                                    m_cmd_name.c_str(), m_cmd_syntax.c_str());
11200b57cec5SDimitry Andric     }
11210b57cec5SDimitry Andric     return result.Succeeded();
11220b57cec5SDimitry Andric   }
11230b57cec5SDimitry Andric };
11240b57cec5SDimitry Andric 
11250b57cec5SDimitry Andric // CommandObjectProcessKill
11260b57cec5SDimitry Andric #pragma mark CommandObjectProcessKill
11270b57cec5SDimitry Andric 
11280b57cec5SDimitry Andric class CommandObjectProcessKill : public CommandObjectParsed {
11290b57cec5SDimitry Andric public:
CommandObjectProcessKill(CommandInterpreter & interpreter)11300b57cec5SDimitry Andric   CommandObjectProcessKill(CommandInterpreter &interpreter)
11310b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "process kill",
11320b57cec5SDimitry Andric                             "Terminate the current target process.",
11330b57cec5SDimitry Andric                             "process kill",
11340b57cec5SDimitry Andric                             eCommandRequiresProcess | eCommandTryTargetAPILock |
11350b57cec5SDimitry Andric                                 eCommandProcessMustBeLaunched) {}
11360b57cec5SDimitry Andric 
11370b57cec5SDimitry Andric   ~CommandObjectProcessKill() override = default;
11380b57cec5SDimitry Andric 
11390b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)11400b57cec5SDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
11410b57cec5SDimitry Andric     Process *process = m_exe_ctx.GetProcessPtr();
11420b57cec5SDimitry Andric     if (process == nullptr) {
11430b57cec5SDimitry Andric       result.AppendError("no process to kill");
11440b57cec5SDimitry Andric       return false;
11450b57cec5SDimitry Andric     }
11460b57cec5SDimitry Andric 
11470b57cec5SDimitry Andric     if (command.GetArgumentCount() == 0) {
11480b57cec5SDimitry Andric       Status error(process->Destroy(true));
11490b57cec5SDimitry Andric       if (error.Success()) {
11500b57cec5SDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishResult);
11510b57cec5SDimitry Andric       } else {
11520b57cec5SDimitry Andric         result.AppendErrorWithFormat("Failed to kill process: %s\n",
11530b57cec5SDimitry Andric                                      error.AsCString());
11540b57cec5SDimitry Andric       }
11550b57cec5SDimitry Andric     } else {
11560b57cec5SDimitry Andric       result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n",
11570b57cec5SDimitry Andric                                    m_cmd_name.c_str(), m_cmd_syntax.c_str());
11580b57cec5SDimitry Andric     }
11590b57cec5SDimitry Andric     return result.Succeeded();
11600b57cec5SDimitry Andric   }
11610b57cec5SDimitry Andric };
11620b57cec5SDimitry Andric 
11630b57cec5SDimitry Andric // CommandObjectProcessSaveCore
11640b57cec5SDimitry Andric #pragma mark CommandObjectProcessSaveCore
11650b57cec5SDimitry Andric 
1166*5f7ddb14SDimitry Andric static constexpr OptionEnumValueElement g_corefile_save_style[] = {
1167*5f7ddb14SDimitry Andric     {eSaveCoreFull, "full", "Create a core file with all memory saved"},
1168*5f7ddb14SDimitry Andric     {eSaveCoreDirtyOnly, "modified-memory",
1169*5f7ddb14SDimitry Andric      "Create a corefile with only modified memory saved"}};
1170*5f7ddb14SDimitry Andric 
SaveCoreStyles()1171*5f7ddb14SDimitry Andric static constexpr OptionEnumValues SaveCoreStyles() {
1172*5f7ddb14SDimitry Andric   return OptionEnumValues(g_corefile_save_style);
1173*5f7ddb14SDimitry Andric }
1174*5f7ddb14SDimitry Andric 
1175*5f7ddb14SDimitry Andric #define LLDB_OPTIONS_process_save_core
1176*5f7ddb14SDimitry Andric #include "CommandOptions.inc"
1177*5f7ddb14SDimitry Andric 
11780b57cec5SDimitry Andric class CommandObjectProcessSaveCore : public CommandObjectParsed {
11790b57cec5SDimitry Andric public:
CommandObjectProcessSaveCore(CommandInterpreter & interpreter)11800b57cec5SDimitry Andric   CommandObjectProcessSaveCore(CommandInterpreter &interpreter)
11810b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "process save-core",
11820b57cec5SDimitry Andric                             "Save the current process as a core file using an "
11830b57cec5SDimitry Andric                             "appropriate file type.",
1184*5f7ddb14SDimitry Andric                             "process save-core [-s corefile-style] FILE",
11850b57cec5SDimitry Andric                             eCommandRequiresProcess | eCommandTryTargetAPILock |
11860b57cec5SDimitry Andric                                 eCommandProcessMustBeLaunched) {}
11870b57cec5SDimitry Andric 
11880b57cec5SDimitry Andric   ~CommandObjectProcessSaveCore() override = default;
11890b57cec5SDimitry Andric 
GetOptions()1190*5f7ddb14SDimitry Andric   Options *GetOptions() override { return &m_options; }
1191*5f7ddb14SDimitry Andric 
1192*5f7ddb14SDimitry Andric   class CommandOptions : public Options {
1193*5f7ddb14SDimitry Andric   public:
CommandOptions()1194*5f7ddb14SDimitry Andric     CommandOptions()
1195*5f7ddb14SDimitry Andric         : Options(), m_requested_save_core_style(eSaveCoreUnspecified) {}
1196*5f7ddb14SDimitry Andric 
1197*5f7ddb14SDimitry Andric     ~CommandOptions() override = default;
1198*5f7ddb14SDimitry Andric 
GetDefinitions()1199*5f7ddb14SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1200*5f7ddb14SDimitry Andric       return llvm::makeArrayRef(g_process_save_core_options);
1201*5f7ddb14SDimitry Andric     }
1202*5f7ddb14SDimitry Andric 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)1203*5f7ddb14SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1204*5f7ddb14SDimitry Andric                           ExecutionContext *execution_context) override {
1205*5f7ddb14SDimitry Andric       const int short_option = m_getopt_table[option_idx].val;
1206*5f7ddb14SDimitry Andric       Status error;
1207*5f7ddb14SDimitry Andric 
1208*5f7ddb14SDimitry Andric       switch (short_option) {
1209*5f7ddb14SDimitry Andric       case 's':
1210*5f7ddb14SDimitry Andric         m_requested_save_core_style =
1211*5f7ddb14SDimitry Andric             (lldb::SaveCoreStyle)OptionArgParser::ToOptionEnum(
1212*5f7ddb14SDimitry Andric                 option_arg, GetDefinitions()[option_idx].enum_values,
1213*5f7ddb14SDimitry Andric                 eSaveCoreUnspecified, error);
1214*5f7ddb14SDimitry Andric         break;
1215*5f7ddb14SDimitry Andric       default:
1216*5f7ddb14SDimitry Andric         llvm_unreachable("Unimplemented option");
1217*5f7ddb14SDimitry Andric       }
1218*5f7ddb14SDimitry Andric 
1219*5f7ddb14SDimitry Andric       return {};
1220*5f7ddb14SDimitry Andric     }
1221*5f7ddb14SDimitry Andric 
OptionParsingStarting(ExecutionContext * execution_context)1222*5f7ddb14SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
1223*5f7ddb14SDimitry Andric       m_requested_save_core_style = eSaveCoreUnspecified;
1224*5f7ddb14SDimitry Andric     }
1225*5f7ddb14SDimitry Andric 
1226*5f7ddb14SDimitry Andric     // Instance variables to hold the values for command options.
1227*5f7ddb14SDimitry Andric     SaveCoreStyle m_requested_save_core_style;
1228*5f7ddb14SDimitry Andric   };
1229*5f7ddb14SDimitry Andric 
12300b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)12310b57cec5SDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
12320b57cec5SDimitry Andric     ProcessSP process_sp = m_exe_ctx.GetProcessSP();
12330b57cec5SDimitry Andric     if (process_sp) {
12340b57cec5SDimitry Andric       if (command.GetArgumentCount() == 1) {
12350b57cec5SDimitry Andric         FileSpec output_file(command.GetArgumentAtIndex(0));
1236*5f7ddb14SDimitry Andric         SaveCoreStyle corefile_style = m_options.m_requested_save_core_style;
1237*5f7ddb14SDimitry Andric         Status error =
1238*5f7ddb14SDimitry Andric             PluginManager::SaveCore(process_sp, output_file, corefile_style);
12390b57cec5SDimitry Andric         if (error.Success()) {
1240*5f7ddb14SDimitry Andric           if (corefile_style == SaveCoreStyle::eSaveCoreDirtyOnly) {
1241*5f7ddb14SDimitry Andric             result.AppendMessageWithFormat(
1242*5f7ddb14SDimitry Andric                 "\nModified-memory only corefile "
1243*5f7ddb14SDimitry Andric                 "created.  This corefile may not show \n"
1244*5f7ddb14SDimitry Andric                 "library/framework/app binaries "
1245*5f7ddb14SDimitry Andric                 "on a different system, or when \n"
1246*5f7ddb14SDimitry Andric                 "those binaries have "
1247*5f7ddb14SDimitry Andric                 "been updated/modified. Copies are not included\n"
1248*5f7ddb14SDimitry Andric                 "in this corefile.  Use --style full to include all "
1249*5f7ddb14SDimitry Andric                 "process memory.\n");
1250*5f7ddb14SDimitry Andric           }
12510b57cec5SDimitry Andric           result.SetStatus(eReturnStatusSuccessFinishResult);
12520b57cec5SDimitry Andric         } else {
12530b57cec5SDimitry Andric           result.AppendErrorWithFormat(
12540b57cec5SDimitry Andric               "Failed to save core file for process: %s\n", error.AsCString());
12550b57cec5SDimitry Andric         }
12560b57cec5SDimitry Andric       } else {
12570b57cec5SDimitry Andric         result.AppendErrorWithFormat("'%s' takes one arguments:\nUsage: %s\n",
12580b57cec5SDimitry Andric                                      m_cmd_name.c_str(), m_cmd_syntax.c_str());
12590b57cec5SDimitry Andric       }
12600b57cec5SDimitry Andric     } else {
12610b57cec5SDimitry Andric       result.AppendError("invalid process");
12620b57cec5SDimitry Andric       return false;
12630b57cec5SDimitry Andric     }
12640b57cec5SDimitry Andric 
12650b57cec5SDimitry Andric     return result.Succeeded();
12660b57cec5SDimitry Andric   }
1267*5f7ddb14SDimitry Andric 
1268*5f7ddb14SDimitry Andric   CommandOptions m_options;
12690b57cec5SDimitry Andric };
12700b57cec5SDimitry Andric 
12710b57cec5SDimitry Andric // CommandObjectProcessStatus
12720b57cec5SDimitry Andric #pragma mark CommandObjectProcessStatus
12735ffd83dbSDimitry Andric #define LLDB_OPTIONS_process_status
12745ffd83dbSDimitry Andric #include "CommandOptions.inc"
12750b57cec5SDimitry Andric 
12760b57cec5SDimitry Andric class CommandObjectProcessStatus : public CommandObjectParsed {
12770b57cec5SDimitry Andric public:
CommandObjectProcessStatus(CommandInterpreter & interpreter)12780b57cec5SDimitry Andric   CommandObjectProcessStatus(CommandInterpreter &interpreter)
12790b57cec5SDimitry Andric       : CommandObjectParsed(
12800b57cec5SDimitry Andric             interpreter, "process status",
12810b57cec5SDimitry Andric             "Show status and stop location for the current target process.",
12820b57cec5SDimitry Andric             "process status",
12835ffd83dbSDimitry Andric             eCommandRequiresProcess | eCommandTryTargetAPILock),
12845ffd83dbSDimitry Andric         m_options() {}
12850b57cec5SDimitry Andric 
12860b57cec5SDimitry Andric   ~CommandObjectProcessStatus() override = default;
12870b57cec5SDimitry Andric 
GetOptions()12885ffd83dbSDimitry Andric   Options *GetOptions() override { return &m_options; }
12895ffd83dbSDimitry Andric 
12905ffd83dbSDimitry Andric   class CommandOptions : public Options {
12915ffd83dbSDimitry Andric   public:
CommandOptions()1292*5f7ddb14SDimitry Andric     CommandOptions() : Options() {}
12935ffd83dbSDimitry Andric 
12945ffd83dbSDimitry Andric     ~CommandOptions() override = default;
12955ffd83dbSDimitry Andric 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)12965ffd83dbSDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
12975ffd83dbSDimitry Andric                           ExecutionContext *execution_context) override {
12985ffd83dbSDimitry Andric       const int short_option = m_getopt_table[option_idx].val;
12995ffd83dbSDimitry Andric 
13005ffd83dbSDimitry Andric       switch (short_option) {
13015ffd83dbSDimitry Andric       case 'v':
13025ffd83dbSDimitry Andric         m_verbose = true;
13035ffd83dbSDimitry Andric         break;
13045ffd83dbSDimitry Andric       default:
13055ffd83dbSDimitry Andric         llvm_unreachable("Unimplemented option");
13065ffd83dbSDimitry Andric       }
13075ffd83dbSDimitry Andric 
13085ffd83dbSDimitry Andric       return {};
13095ffd83dbSDimitry Andric     }
13105ffd83dbSDimitry Andric 
OptionParsingStarting(ExecutionContext * execution_context)13115ffd83dbSDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
13125ffd83dbSDimitry Andric       m_verbose = false;
13135ffd83dbSDimitry Andric     }
13145ffd83dbSDimitry Andric 
GetDefinitions()13155ffd83dbSDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
13165ffd83dbSDimitry Andric       return llvm::makeArrayRef(g_process_status_options);
13175ffd83dbSDimitry Andric     }
13185ffd83dbSDimitry Andric 
13195ffd83dbSDimitry Andric     // Instance variables to hold the values for command options.
1320*5f7ddb14SDimitry Andric     bool m_verbose = false;
13215ffd83dbSDimitry Andric   };
13225ffd83dbSDimitry Andric 
13235ffd83dbSDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)13240b57cec5SDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
13250b57cec5SDimitry Andric     Stream &strm = result.GetOutputStream();
13260b57cec5SDimitry Andric     result.SetStatus(eReturnStatusSuccessFinishNoResult);
13275ffd83dbSDimitry Andric 
13285ffd83dbSDimitry Andric     if (command.GetArgumentCount()) {
13295ffd83dbSDimitry Andric       result.AppendError("'process status' takes no arguments");
13305ffd83dbSDimitry Andric       return result.Succeeded();
13315ffd83dbSDimitry Andric     }
13325ffd83dbSDimitry Andric 
13330b57cec5SDimitry Andric     // No need to check "process" for validity as eCommandRequiresProcess
13340b57cec5SDimitry Andric     // ensures it is valid
13350b57cec5SDimitry Andric     Process *process = m_exe_ctx.GetProcessPtr();
13360b57cec5SDimitry Andric     const bool only_threads_with_stop_reason = true;
13370b57cec5SDimitry Andric     const uint32_t start_frame = 0;
13380b57cec5SDimitry Andric     const uint32_t num_frames = 1;
13390b57cec5SDimitry Andric     const uint32_t num_frames_with_source = 1;
13400b57cec5SDimitry Andric     const bool stop_format = true;
13410b57cec5SDimitry Andric     process->GetStatus(strm);
13420b57cec5SDimitry Andric     process->GetThreadStatus(strm, only_threads_with_stop_reason, start_frame,
13430b57cec5SDimitry Andric                              num_frames, num_frames_with_source, stop_format);
13445ffd83dbSDimitry Andric 
13455ffd83dbSDimitry Andric     if (m_options.m_verbose) {
1346*5f7ddb14SDimitry Andric       addr_t code_mask = process->GetCodeAddressMask();
1347*5f7ddb14SDimitry Andric       addr_t data_mask = process->GetDataAddressMask();
1348*5f7ddb14SDimitry Andric       if (code_mask != 0) {
1349*5f7ddb14SDimitry Andric         int bits = std::bitset<64>(~code_mask).count();
1350*5f7ddb14SDimitry Andric         result.AppendMessageWithFormat(
1351*5f7ddb14SDimitry Andric             "Addressable code address mask: 0x%" PRIx64 "\n", code_mask);
1352*5f7ddb14SDimitry Andric         result.AppendMessageWithFormat(
1353*5f7ddb14SDimitry Andric             "Addressable data address mask: 0x%" PRIx64 "\n", data_mask);
1354*5f7ddb14SDimitry Andric         result.AppendMessageWithFormat(
1355*5f7ddb14SDimitry Andric             "Number of bits used in addressing (code): %d\n", bits);
1356*5f7ddb14SDimitry Andric       }
1357*5f7ddb14SDimitry Andric 
13585ffd83dbSDimitry Andric       PlatformSP platform_sp = process->GetTarget().GetPlatform();
13595ffd83dbSDimitry Andric       if (!platform_sp) {
13605ffd83dbSDimitry Andric         result.AppendError("Couldn'retrieve the target's platform");
13610b57cec5SDimitry Andric         return result.Succeeded();
13620b57cec5SDimitry Andric       }
13635ffd83dbSDimitry Andric 
13645ffd83dbSDimitry Andric       auto expected_crash_info =
13655ffd83dbSDimitry Andric           platform_sp->FetchExtendedCrashInformation(*process);
13665ffd83dbSDimitry Andric 
13675ffd83dbSDimitry Andric       if (!expected_crash_info) {
13685ffd83dbSDimitry Andric         result.AppendError(llvm::toString(expected_crash_info.takeError()));
13695ffd83dbSDimitry Andric         return result.Succeeded();
13705ffd83dbSDimitry Andric       }
13715ffd83dbSDimitry Andric 
13725ffd83dbSDimitry Andric       StructuredData::DictionarySP crash_info_sp = *expected_crash_info;
13735ffd83dbSDimitry Andric 
13745ffd83dbSDimitry Andric       if (crash_info_sp) {
13755ffd83dbSDimitry Andric         strm.PutCString("Extended Crash Information:\n");
13765ffd83dbSDimitry Andric         crash_info_sp->Dump(strm);
13775ffd83dbSDimitry Andric       }
13785ffd83dbSDimitry Andric     }
13795ffd83dbSDimitry Andric 
13805ffd83dbSDimitry Andric     return result.Succeeded();
13815ffd83dbSDimitry Andric   }
13825ffd83dbSDimitry Andric 
13835ffd83dbSDimitry Andric private:
13845ffd83dbSDimitry Andric   CommandOptions m_options;
13850b57cec5SDimitry Andric };
13860b57cec5SDimitry Andric 
13870b57cec5SDimitry Andric // CommandObjectProcessHandle
13889dba64beSDimitry Andric #define LLDB_OPTIONS_process_handle
13899dba64beSDimitry Andric #include "CommandOptions.inc"
13900b57cec5SDimitry Andric 
13910b57cec5SDimitry Andric #pragma mark CommandObjectProcessHandle
13920b57cec5SDimitry Andric 
13930b57cec5SDimitry Andric class CommandObjectProcessHandle : public CommandObjectParsed {
13940b57cec5SDimitry Andric public:
13950b57cec5SDimitry Andric   class CommandOptions : public Options {
13960b57cec5SDimitry Andric   public:
CommandOptions()13970b57cec5SDimitry Andric     CommandOptions() : Options() { OptionParsingStarting(nullptr); }
13980b57cec5SDimitry Andric 
13990b57cec5SDimitry Andric     ~CommandOptions() override = default;
14000b57cec5SDimitry Andric 
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)14010b57cec5SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
14020b57cec5SDimitry Andric                           ExecutionContext *execution_context) override {
14030b57cec5SDimitry Andric       Status error;
14040b57cec5SDimitry Andric       const int short_option = m_getopt_table[option_idx].val;
14050b57cec5SDimitry Andric 
14060b57cec5SDimitry Andric       switch (short_option) {
14070b57cec5SDimitry Andric       case 's':
14085ffd83dbSDimitry Andric         stop = std::string(option_arg);
14090b57cec5SDimitry Andric         break;
14100b57cec5SDimitry Andric       case 'n':
14115ffd83dbSDimitry Andric         notify = std::string(option_arg);
14120b57cec5SDimitry Andric         break;
14130b57cec5SDimitry Andric       case 'p':
14145ffd83dbSDimitry Andric         pass = std::string(option_arg);
14150b57cec5SDimitry Andric         break;
14160b57cec5SDimitry Andric       default:
14179dba64beSDimitry Andric         llvm_unreachable("Unimplemented option");
14180b57cec5SDimitry Andric       }
14190b57cec5SDimitry Andric       return error;
14200b57cec5SDimitry Andric     }
14210b57cec5SDimitry Andric 
OptionParsingStarting(ExecutionContext * execution_context)14220b57cec5SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
14230b57cec5SDimitry Andric       stop.clear();
14240b57cec5SDimitry Andric       notify.clear();
14250b57cec5SDimitry Andric       pass.clear();
14260b57cec5SDimitry Andric     }
14270b57cec5SDimitry Andric 
GetDefinitions()14280b57cec5SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
14290b57cec5SDimitry Andric       return llvm::makeArrayRef(g_process_handle_options);
14300b57cec5SDimitry Andric     }
14310b57cec5SDimitry Andric 
14320b57cec5SDimitry Andric     // Instance variables to hold the values for command options.
14330b57cec5SDimitry Andric 
14340b57cec5SDimitry Andric     std::string stop;
14350b57cec5SDimitry Andric     std::string notify;
14360b57cec5SDimitry Andric     std::string pass;
14370b57cec5SDimitry Andric   };
14380b57cec5SDimitry Andric 
CommandObjectProcessHandle(CommandInterpreter & interpreter)14390b57cec5SDimitry Andric   CommandObjectProcessHandle(CommandInterpreter &interpreter)
14400b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "process handle",
14410b57cec5SDimitry Andric                             "Manage LLDB handling of OS signals for the "
14420b57cec5SDimitry Andric                             "current target process.  Defaults to showing "
14430b57cec5SDimitry Andric                             "current policy.",
14449dba64beSDimitry Andric                             nullptr, eCommandRequiresTarget),
14450b57cec5SDimitry Andric         m_options() {
14460b57cec5SDimitry Andric     SetHelpLong("\nIf no signals are specified, update them all.  If no update "
14470b57cec5SDimitry Andric                 "option is specified, list the current values.");
14480b57cec5SDimitry Andric     CommandArgumentEntry arg;
14490b57cec5SDimitry Andric     CommandArgumentData signal_arg;
14500b57cec5SDimitry Andric 
14510b57cec5SDimitry Andric     signal_arg.arg_type = eArgTypeUnixSignal;
14520b57cec5SDimitry Andric     signal_arg.arg_repetition = eArgRepeatStar;
14530b57cec5SDimitry Andric 
14540b57cec5SDimitry Andric     arg.push_back(signal_arg);
14550b57cec5SDimitry Andric 
14560b57cec5SDimitry Andric     m_arguments.push_back(arg);
14570b57cec5SDimitry Andric   }
14580b57cec5SDimitry Andric 
14590b57cec5SDimitry Andric   ~CommandObjectProcessHandle() override = default;
14600b57cec5SDimitry Andric 
GetOptions()14610b57cec5SDimitry Andric   Options *GetOptions() override { return &m_options; }
14620b57cec5SDimitry Andric 
VerifyCommandOptionValue(const std::string & option,int & real_value)14630b57cec5SDimitry Andric   bool VerifyCommandOptionValue(const std::string &option, int &real_value) {
14640b57cec5SDimitry Andric     bool okay = true;
14650b57cec5SDimitry Andric     bool success = false;
14660b57cec5SDimitry Andric     bool tmp_value = OptionArgParser::ToBoolean(option, false, &success);
14670b57cec5SDimitry Andric 
14680b57cec5SDimitry Andric     if (success && tmp_value)
14690b57cec5SDimitry Andric       real_value = 1;
14700b57cec5SDimitry Andric     else if (success && !tmp_value)
14710b57cec5SDimitry Andric       real_value = 0;
14720b57cec5SDimitry Andric     else {
14730b57cec5SDimitry Andric       // If the value isn't 'true' or 'false', it had better be 0 or 1.
14745ffd83dbSDimitry Andric       if (!llvm::to_integer(option, real_value))
14755ffd83dbSDimitry Andric         real_value = 3;
14760b57cec5SDimitry Andric       if (real_value != 0 && real_value != 1)
14770b57cec5SDimitry Andric         okay = false;
14780b57cec5SDimitry Andric     }
14790b57cec5SDimitry Andric 
14800b57cec5SDimitry Andric     return okay;
14810b57cec5SDimitry Andric   }
14820b57cec5SDimitry Andric 
PrintSignalHeader(Stream & str)14830b57cec5SDimitry Andric   void PrintSignalHeader(Stream &str) {
14840b57cec5SDimitry Andric     str.Printf("NAME         PASS   STOP   NOTIFY\n");
14850b57cec5SDimitry Andric     str.Printf("===========  =====  =====  ======\n");
14860b57cec5SDimitry Andric   }
14870b57cec5SDimitry Andric 
PrintSignal(Stream & str,int32_t signo,const char * sig_name,const UnixSignalsSP & signals_sp)14880b57cec5SDimitry Andric   void PrintSignal(Stream &str, int32_t signo, const char *sig_name,
14890b57cec5SDimitry Andric                    const UnixSignalsSP &signals_sp) {
14900b57cec5SDimitry Andric     bool stop;
14910b57cec5SDimitry Andric     bool suppress;
14920b57cec5SDimitry Andric     bool notify;
14930b57cec5SDimitry Andric 
14940b57cec5SDimitry Andric     str.Printf("%-11s  ", sig_name);
14950b57cec5SDimitry Andric     if (signals_sp->GetSignalInfo(signo, suppress, stop, notify)) {
14960b57cec5SDimitry Andric       bool pass = !suppress;
14970b57cec5SDimitry Andric       str.Printf("%s  %s  %s", (pass ? "true " : "false"),
14980b57cec5SDimitry Andric                  (stop ? "true " : "false"), (notify ? "true " : "false"));
14990b57cec5SDimitry Andric     }
15000b57cec5SDimitry Andric     str.Printf("\n");
15010b57cec5SDimitry Andric   }
15020b57cec5SDimitry Andric 
PrintSignalInformation(Stream & str,Args & signal_args,int num_valid_signals,const UnixSignalsSP & signals_sp)15030b57cec5SDimitry Andric   void PrintSignalInformation(Stream &str, Args &signal_args,
15040b57cec5SDimitry Andric                               int num_valid_signals,
15050b57cec5SDimitry Andric                               const UnixSignalsSP &signals_sp) {
15060b57cec5SDimitry Andric     PrintSignalHeader(str);
15070b57cec5SDimitry Andric 
15080b57cec5SDimitry Andric     if (num_valid_signals > 0) {
15090b57cec5SDimitry Andric       size_t num_args = signal_args.GetArgumentCount();
15100b57cec5SDimitry Andric       for (size_t i = 0; i < num_args; ++i) {
15110b57cec5SDimitry Andric         int32_t signo = signals_sp->GetSignalNumberFromName(
15120b57cec5SDimitry Andric             signal_args.GetArgumentAtIndex(i));
15130b57cec5SDimitry Andric         if (signo != LLDB_INVALID_SIGNAL_NUMBER)
15140b57cec5SDimitry Andric           PrintSignal(str, signo, signal_args.GetArgumentAtIndex(i),
15150b57cec5SDimitry Andric                       signals_sp);
15160b57cec5SDimitry Andric       }
15170b57cec5SDimitry Andric     } else // Print info for ALL signals
15180b57cec5SDimitry Andric     {
15190b57cec5SDimitry Andric       int32_t signo = signals_sp->GetFirstSignalNumber();
15200b57cec5SDimitry Andric       while (signo != LLDB_INVALID_SIGNAL_NUMBER) {
15210b57cec5SDimitry Andric         PrintSignal(str, signo, signals_sp->GetSignalAsCString(signo),
15220b57cec5SDimitry Andric                     signals_sp);
15230b57cec5SDimitry Andric         signo = signals_sp->GetNextSignalNumber(signo);
15240b57cec5SDimitry Andric       }
15250b57cec5SDimitry Andric     }
15260b57cec5SDimitry Andric   }
15270b57cec5SDimitry Andric 
15280b57cec5SDimitry Andric protected:
DoExecute(Args & signal_args,CommandReturnObject & result)15290b57cec5SDimitry Andric   bool DoExecute(Args &signal_args, CommandReturnObject &result) override {
15309dba64beSDimitry Andric     Target *target_sp = &GetSelectedTarget();
15310b57cec5SDimitry Andric 
15320b57cec5SDimitry Andric     ProcessSP process_sp = target_sp->GetProcessSP();
15330b57cec5SDimitry Andric 
15340b57cec5SDimitry Andric     if (!process_sp) {
15350b57cec5SDimitry Andric       result.AppendError("No current process; cannot handle signals until you "
15360b57cec5SDimitry Andric                          "have a valid process.\n");
15370b57cec5SDimitry Andric       return false;
15380b57cec5SDimitry Andric     }
15390b57cec5SDimitry Andric 
15400b57cec5SDimitry Andric     int stop_action = -1;   // -1 means leave the current setting alone
15410b57cec5SDimitry Andric     int pass_action = -1;   // -1 means leave the current setting alone
15420b57cec5SDimitry Andric     int notify_action = -1; // -1 means leave the current setting alone
15430b57cec5SDimitry Andric 
15440b57cec5SDimitry Andric     if (!m_options.stop.empty() &&
15450b57cec5SDimitry Andric         !VerifyCommandOptionValue(m_options.stop, stop_action)) {
15460b57cec5SDimitry Andric       result.AppendError("Invalid argument for command option --stop; must be "
15470b57cec5SDimitry Andric                          "true or false.\n");
15480b57cec5SDimitry Andric       return false;
15490b57cec5SDimitry Andric     }
15500b57cec5SDimitry Andric 
15510b57cec5SDimitry Andric     if (!m_options.notify.empty() &&
15520b57cec5SDimitry Andric         !VerifyCommandOptionValue(m_options.notify, notify_action)) {
15530b57cec5SDimitry Andric       result.AppendError("Invalid argument for command option --notify; must "
15540b57cec5SDimitry Andric                          "be true or false.\n");
15550b57cec5SDimitry Andric       return false;
15560b57cec5SDimitry Andric     }
15570b57cec5SDimitry Andric 
15580b57cec5SDimitry Andric     if (!m_options.pass.empty() &&
15590b57cec5SDimitry Andric         !VerifyCommandOptionValue(m_options.pass, pass_action)) {
15600b57cec5SDimitry Andric       result.AppendError("Invalid argument for command option --pass; must be "
15610b57cec5SDimitry Andric                          "true or false.\n");
15620b57cec5SDimitry Andric       return false;
15630b57cec5SDimitry Andric     }
15640b57cec5SDimitry Andric 
15650b57cec5SDimitry Andric     size_t num_args = signal_args.GetArgumentCount();
15660b57cec5SDimitry Andric     UnixSignalsSP signals_sp = process_sp->GetUnixSignals();
15670b57cec5SDimitry Andric     int num_signals_set = 0;
15680b57cec5SDimitry Andric 
15690b57cec5SDimitry Andric     if (num_args > 0) {
15700b57cec5SDimitry Andric       for (const auto &arg : signal_args) {
15710b57cec5SDimitry Andric         int32_t signo = signals_sp->GetSignalNumberFromName(arg.c_str());
15720b57cec5SDimitry Andric         if (signo != LLDB_INVALID_SIGNAL_NUMBER) {
15730b57cec5SDimitry Andric           // Casting the actions as bools here should be okay, because
15740b57cec5SDimitry Andric           // VerifyCommandOptionValue guarantees the value is either 0 or 1.
15750b57cec5SDimitry Andric           if (stop_action != -1)
15760b57cec5SDimitry Andric             signals_sp->SetShouldStop(signo, stop_action);
15770b57cec5SDimitry Andric           if (pass_action != -1) {
15780b57cec5SDimitry Andric             bool suppress = !pass_action;
15790b57cec5SDimitry Andric             signals_sp->SetShouldSuppress(signo, suppress);
15800b57cec5SDimitry Andric           }
15810b57cec5SDimitry Andric           if (notify_action != -1)
15820b57cec5SDimitry Andric             signals_sp->SetShouldNotify(signo, notify_action);
15830b57cec5SDimitry Andric           ++num_signals_set;
15840b57cec5SDimitry Andric         } else {
15850b57cec5SDimitry Andric           result.AppendErrorWithFormat("Invalid signal name '%s'\n",
15860b57cec5SDimitry Andric                                        arg.c_str());
15870b57cec5SDimitry Andric         }
15880b57cec5SDimitry Andric       }
15890b57cec5SDimitry Andric     } else {
15900b57cec5SDimitry Andric       // No signal specified, if any command options were specified, update ALL
15910b57cec5SDimitry Andric       // signals.
15920b57cec5SDimitry Andric       if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1)) {
15930b57cec5SDimitry Andric         if (m_interpreter.Confirm(
15940b57cec5SDimitry Andric                 "Do you really want to update all the signals?", false)) {
15950b57cec5SDimitry Andric           int32_t signo = signals_sp->GetFirstSignalNumber();
15960b57cec5SDimitry Andric           while (signo != LLDB_INVALID_SIGNAL_NUMBER) {
15970b57cec5SDimitry Andric             if (notify_action != -1)
15980b57cec5SDimitry Andric               signals_sp->SetShouldNotify(signo, notify_action);
15990b57cec5SDimitry Andric             if (stop_action != -1)
16000b57cec5SDimitry Andric               signals_sp->SetShouldStop(signo, stop_action);
16010b57cec5SDimitry Andric             if (pass_action != -1) {
16020b57cec5SDimitry Andric               bool suppress = !pass_action;
16030b57cec5SDimitry Andric               signals_sp->SetShouldSuppress(signo, suppress);
16040b57cec5SDimitry Andric             }
16050b57cec5SDimitry Andric             signo = signals_sp->GetNextSignalNumber(signo);
16060b57cec5SDimitry Andric           }
16070b57cec5SDimitry Andric         }
16080b57cec5SDimitry Andric       }
16090b57cec5SDimitry Andric     }
16100b57cec5SDimitry Andric 
16110b57cec5SDimitry Andric     PrintSignalInformation(result.GetOutputStream(), signal_args,
16120b57cec5SDimitry Andric                            num_signals_set, signals_sp);
16130b57cec5SDimitry Andric 
16140b57cec5SDimitry Andric     if (num_signals_set > 0)
16150b57cec5SDimitry Andric       result.SetStatus(eReturnStatusSuccessFinishNoResult);
16160b57cec5SDimitry Andric     else
16170b57cec5SDimitry Andric       result.SetStatus(eReturnStatusFailed);
16180b57cec5SDimitry Andric 
16190b57cec5SDimitry Andric     return result.Succeeded();
16200b57cec5SDimitry Andric   }
16210b57cec5SDimitry Andric 
16220b57cec5SDimitry Andric   CommandOptions m_options;
16230b57cec5SDimitry Andric };
16240b57cec5SDimitry Andric 
1625*5f7ddb14SDimitry Andric // Next are the subcommands of CommandObjectMultiwordProcessTrace
1626*5f7ddb14SDimitry Andric 
1627*5f7ddb14SDimitry Andric // CommandObjectProcessTraceStart
1628*5f7ddb14SDimitry Andric class CommandObjectProcessTraceStart : public CommandObjectTraceProxy {
1629*5f7ddb14SDimitry Andric public:
CommandObjectProcessTraceStart(CommandInterpreter & interpreter)1630*5f7ddb14SDimitry Andric   CommandObjectProcessTraceStart(CommandInterpreter &interpreter)
1631*5f7ddb14SDimitry Andric       : CommandObjectTraceProxy(
1632*5f7ddb14SDimitry Andric             /*live_debug_session_only*/ true, interpreter,
1633*5f7ddb14SDimitry Andric             "process trace start",
1634*5f7ddb14SDimitry Andric             "Start tracing this process with the corresponding trace "
1635*5f7ddb14SDimitry Andric             "plug-in.",
1636*5f7ddb14SDimitry Andric             "process trace start [<trace-options>]") {}
1637*5f7ddb14SDimitry Andric 
1638*5f7ddb14SDimitry Andric protected:
GetDelegateCommand(Trace & trace)1639*5f7ddb14SDimitry Andric   lldb::CommandObjectSP GetDelegateCommand(Trace &trace) override {
1640*5f7ddb14SDimitry Andric     return trace.GetProcessTraceStartCommand(m_interpreter);
1641*5f7ddb14SDimitry Andric   }
1642*5f7ddb14SDimitry Andric };
1643*5f7ddb14SDimitry Andric 
1644*5f7ddb14SDimitry Andric // CommandObjectProcessTraceStop
1645*5f7ddb14SDimitry Andric class CommandObjectProcessTraceStop : public CommandObjectParsed {
1646*5f7ddb14SDimitry Andric public:
CommandObjectProcessTraceStop(CommandInterpreter & interpreter)1647*5f7ddb14SDimitry Andric   CommandObjectProcessTraceStop(CommandInterpreter &interpreter)
1648*5f7ddb14SDimitry Andric       : CommandObjectParsed(interpreter, "process trace stop",
1649*5f7ddb14SDimitry Andric                             "Stop tracing this process. This does not affect "
1650*5f7ddb14SDimitry Andric                             "traces started with the "
1651*5f7ddb14SDimitry Andric                             "\"thread trace start\" command.",
1652*5f7ddb14SDimitry Andric                             "process trace stop",
1653*5f7ddb14SDimitry Andric                             eCommandRequiresProcess | eCommandTryTargetAPILock |
1654*5f7ddb14SDimitry Andric                                 eCommandProcessMustBeLaunched |
1655*5f7ddb14SDimitry Andric                                 eCommandProcessMustBePaused |
1656*5f7ddb14SDimitry Andric                                 eCommandProcessMustBeTraced) {}
1657*5f7ddb14SDimitry Andric 
1658*5f7ddb14SDimitry Andric   ~CommandObjectProcessTraceStop() override = default;
1659*5f7ddb14SDimitry Andric 
DoExecute(Args & command,CommandReturnObject & result)1660*5f7ddb14SDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
1661*5f7ddb14SDimitry Andric     ProcessSP process_sp = m_exe_ctx.GetProcessSP();
1662*5f7ddb14SDimitry Andric 
1663*5f7ddb14SDimitry Andric     TraceSP trace_sp = process_sp->GetTarget().GetTrace();
1664*5f7ddb14SDimitry Andric 
1665*5f7ddb14SDimitry Andric     if (llvm::Error err = trace_sp->Stop())
1666*5f7ddb14SDimitry Andric       result.AppendError(toString(std::move(err)));
1667*5f7ddb14SDimitry Andric     else
1668*5f7ddb14SDimitry Andric       result.SetStatus(eReturnStatusSuccessFinishResult);
1669*5f7ddb14SDimitry Andric 
1670*5f7ddb14SDimitry Andric     return result.Succeeded();
1671*5f7ddb14SDimitry Andric   }
1672*5f7ddb14SDimitry Andric };
1673*5f7ddb14SDimitry Andric 
1674*5f7ddb14SDimitry Andric // CommandObjectMultiwordProcessTrace
1675*5f7ddb14SDimitry Andric class CommandObjectMultiwordProcessTrace : public CommandObjectMultiword {
1676*5f7ddb14SDimitry Andric public:
CommandObjectMultiwordProcessTrace(CommandInterpreter & interpreter)1677*5f7ddb14SDimitry Andric   CommandObjectMultiwordProcessTrace(CommandInterpreter &interpreter)
1678*5f7ddb14SDimitry Andric       : CommandObjectMultiword(
1679*5f7ddb14SDimitry Andric             interpreter, "trace", "Commands for tracing the current process.",
1680*5f7ddb14SDimitry Andric             "process trace <subcommand> [<subcommand objects>]") {
1681*5f7ddb14SDimitry Andric     LoadSubCommand("start", CommandObjectSP(new CommandObjectProcessTraceStart(
1682*5f7ddb14SDimitry Andric                                 interpreter)));
1683*5f7ddb14SDimitry Andric     LoadSubCommand("stop", CommandObjectSP(
1684*5f7ddb14SDimitry Andric                                new CommandObjectProcessTraceStop(interpreter)));
1685*5f7ddb14SDimitry Andric   }
1686*5f7ddb14SDimitry Andric 
1687*5f7ddb14SDimitry Andric   ~CommandObjectMultiwordProcessTrace() override = default;
1688*5f7ddb14SDimitry Andric };
1689*5f7ddb14SDimitry Andric 
16900b57cec5SDimitry Andric // CommandObjectMultiwordProcess
16910b57cec5SDimitry Andric 
CommandObjectMultiwordProcess(CommandInterpreter & interpreter)16920b57cec5SDimitry Andric CommandObjectMultiwordProcess::CommandObjectMultiwordProcess(
16930b57cec5SDimitry Andric     CommandInterpreter &interpreter)
16940b57cec5SDimitry Andric     : CommandObjectMultiword(
16950b57cec5SDimitry Andric           interpreter, "process",
16960b57cec5SDimitry Andric           "Commands for interacting with processes on the current platform.",
16970b57cec5SDimitry Andric           "process <subcommand> [<subcommand-options>]") {
16980b57cec5SDimitry Andric   LoadSubCommand("attach",
16990b57cec5SDimitry Andric                  CommandObjectSP(new CommandObjectProcessAttach(interpreter)));
17000b57cec5SDimitry Andric   LoadSubCommand("launch",
17010b57cec5SDimitry Andric                  CommandObjectSP(new CommandObjectProcessLaunch(interpreter)));
17020b57cec5SDimitry Andric   LoadSubCommand("continue", CommandObjectSP(new CommandObjectProcessContinue(
17030b57cec5SDimitry Andric                                  interpreter)));
17040b57cec5SDimitry Andric   LoadSubCommand("connect",
17050b57cec5SDimitry Andric                  CommandObjectSP(new CommandObjectProcessConnect(interpreter)));
17060b57cec5SDimitry Andric   LoadSubCommand("detach",
17070b57cec5SDimitry Andric                  CommandObjectSP(new CommandObjectProcessDetach(interpreter)));
17080b57cec5SDimitry Andric   LoadSubCommand("load",
17090b57cec5SDimitry Andric                  CommandObjectSP(new CommandObjectProcessLoad(interpreter)));
17100b57cec5SDimitry Andric   LoadSubCommand("unload",
17110b57cec5SDimitry Andric                  CommandObjectSP(new CommandObjectProcessUnload(interpreter)));
17120b57cec5SDimitry Andric   LoadSubCommand("signal",
17130b57cec5SDimitry Andric                  CommandObjectSP(new CommandObjectProcessSignal(interpreter)));
17140b57cec5SDimitry Andric   LoadSubCommand("handle",
17150b57cec5SDimitry Andric                  CommandObjectSP(new CommandObjectProcessHandle(interpreter)));
17160b57cec5SDimitry Andric   LoadSubCommand("status",
17170b57cec5SDimitry Andric                  CommandObjectSP(new CommandObjectProcessStatus(interpreter)));
17180b57cec5SDimitry Andric   LoadSubCommand("interrupt", CommandObjectSP(new CommandObjectProcessInterrupt(
17190b57cec5SDimitry Andric                                   interpreter)));
17200b57cec5SDimitry Andric   LoadSubCommand("kill",
17210b57cec5SDimitry Andric                  CommandObjectSP(new CommandObjectProcessKill(interpreter)));
17220b57cec5SDimitry Andric   LoadSubCommand("plugin",
17230b57cec5SDimitry Andric                  CommandObjectSP(new CommandObjectProcessPlugin(interpreter)));
17240b57cec5SDimitry Andric   LoadSubCommand("save-core", CommandObjectSP(new CommandObjectProcessSaveCore(
17250b57cec5SDimitry Andric                                   interpreter)));
1726*5f7ddb14SDimitry Andric   LoadSubCommand(
1727*5f7ddb14SDimitry Andric       "trace",
1728*5f7ddb14SDimitry Andric       CommandObjectSP(new CommandObjectMultiwordProcessTrace(interpreter)));
17290b57cec5SDimitry Andric }
17300b57cec5SDimitry Andric 
17310b57cec5SDimitry Andric CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess() = default;
1732