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"
1081ad6265SDimitry Andric #include "CommandObjectBreakpoint.h"
11fcaf7f86SDimitry Andric #include "CommandObjectTrace.h"
12*fe013be4SDimitry Andric #include "CommandOptionsProcessAttach.h"
13e8d8bef9SDimitry Andric #include "CommandOptionsProcessLaunch.h"
140b57cec5SDimitry Andric #include "lldb/Breakpoint/Breakpoint.h"
1581ad6265SDimitry Andric #include "lldb/Breakpoint/BreakpointIDList.h"
160b57cec5SDimitry Andric #include "lldb/Breakpoint/BreakpointLocation.h"
1781ad6265SDimitry Andric #include "lldb/Breakpoint/BreakpointName.h"
180b57cec5SDimitry Andric #include "lldb/Breakpoint/BreakpointSite.h"
190b57cec5SDimitry Andric #include "lldb/Core/Module.h"
200b57cec5SDimitry Andric #include "lldb/Core/PluginManager.h"
210b57cec5SDimitry Andric #include "lldb/Host/OptionParser.h"
220b57cec5SDimitry Andric #include "lldb/Interpreter/CommandInterpreter.h"
23fcaf7f86SDimitry Andric #include "lldb/Interpreter/CommandOptionArgumentTable.h"
240b57cec5SDimitry Andric #include "lldb/Interpreter/CommandReturnObject.h"
250b57cec5SDimitry Andric #include "lldb/Interpreter/OptionArgParser.h"
26fe6060f1SDimitry Andric #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h"
270b57cec5SDimitry Andric #include "lldb/Interpreter/Options.h"
280b57cec5SDimitry Andric #include "lldb/Target/Platform.h"
290b57cec5SDimitry Andric #include "lldb/Target/Process.h"
300b57cec5SDimitry Andric #include "lldb/Target/StopInfo.h"
310b57cec5SDimitry Andric #include "lldb/Target/Target.h"
320b57cec5SDimitry Andric #include "lldb/Target/Thread.h"
330b57cec5SDimitry Andric #include "lldb/Target/UnixSignals.h"
340b57cec5SDimitry Andric #include "lldb/Utility/Args.h"
35*fe013be4SDimitry Andric #include "lldb/Utility/ScriptedMetadata.h"
360b57cec5SDimitry Andric #include "lldb/Utility/State.h"
370b57cec5SDimitry Andric 
3881ad6265SDimitry Andric #include "llvm/ADT/ScopeExit.h"
3981ad6265SDimitry Andric 
40fe6060f1SDimitry Andric #include <bitset>
41bdd1243dSDimitry Andric #include <optional>
42fe6060f1SDimitry Andric 
430b57cec5SDimitry Andric using namespace lldb;
440b57cec5SDimitry Andric using namespace lldb_private;
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric class CommandObjectProcessLaunchOrAttach : public CommandObjectParsed {
470b57cec5SDimitry Andric public:
480b57cec5SDimitry Andric   CommandObjectProcessLaunchOrAttach(CommandInterpreter &interpreter,
490b57cec5SDimitry Andric                                      const char *name, const char *help,
500b57cec5SDimitry Andric                                      const char *syntax, uint32_t flags,
510b57cec5SDimitry Andric                                      const char *new_process_action)
520b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, name, help, syntax, flags),
530b57cec5SDimitry Andric         m_new_process_action(new_process_action) {}
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric   ~CommandObjectProcessLaunchOrAttach() override = default;
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric protected:
580b57cec5SDimitry Andric   bool StopProcessIfNecessary(Process *process, StateType &state,
590b57cec5SDimitry Andric                               CommandReturnObject &result) {
600b57cec5SDimitry Andric     state = eStateInvalid;
610b57cec5SDimitry Andric     if (process) {
620b57cec5SDimitry Andric       state = process->GetState();
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric       if (process->IsAlive() && state != eStateConnected) {
65e8d8bef9SDimitry Andric         std::string message;
660b57cec5SDimitry Andric         if (process->GetState() == eStateAttaching)
67e8d8bef9SDimitry Andric           message =
68e8d8bef9SDimitry Andric               llvm::formatv("There is a pending attach, abort it and {0}?",
69e8d8bef9SDimitry Andric                             m_new_process_action);
700b57cec5SDimitry Andric         else if (process->GetShouldDetach())
71e8d8bef9SDimitry Andric           message = llvm::formatv(
72e8d8bef9SDimitry Andric               "There is a running process, detach from it and {0}?",
73e8d8bef9SDimitry Andric               m_new_process_action);
740b57cec5SDimitry Andric         else
75e8d8bef9SDimitry Andric           message =
76e8d8bef9SDimitry Andric               llvm::formatv("There is a running process, kill it and {0}?",
77e8d8bef9SDimitry Andric                             m_new_process_action);
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric         if (!m_interpreter.Confirm(message, true)) {
800b57cec5SDimitry Andric           result.SetStatus(eReturnStatusFailed);
810b57cec5SDimitry Andric           return false;
820b57cec5SDimitry Andric         } else {
830b57cec5SDimitry Andric           if (process->GetShouldDetach()) {
840b57cec5SDimitry Andric             bool keep_stopped = false;
850b57cec5SDimitry Andric             Status detach_error(process->Detach(keep_stopped));
860b57cec5SDimitry Andric             if (detach_error.Success()) {
870b57cec5SDimitry Andric               result.SetStatus(eReturnStatusSuccessFinishResult);
880b57cec5SDimitry Andric               process = nullptr;
890b57cec5SDimitry Andric             } else {
900b57cec5SDimitry Andric               result.AppendErrorWithFormat(
910b57cec5SDimitry Andric                   "Failed to detach from process: %s\n",
920b57cec5SDimitry Andric                   detach_error.AsCString());
930b57cec5SDimitry Andric             }
940b57cec5SDimitry Andric           } else {
950b57cec5SDimitry Andric             Status destroy_error(process->Destroy(false));
960b57cec5SDimitry Andric             if (destroy_error.Success()) {
970b57cec5SDimitry Andric               result.SetStatus(eReturnStatusSuccessFinishResult);
980b57cec5SDimitry Andric               process = nullptr;
990b57cec5SDimitry Andric             } else {
1000b57cec5SDimitry Andric               result.AppendErrorWithFormat("Failed to kill process: %s\n",
1010b57cec5SDimitry Andric                                            destroy_error.AsCString());
1020b57cec5SDimitry Andric             }
1030b57cec5SDimitry Andric           }
1040b57cec5SDimitry Andric         }
1050b57cec5SDimitry Andric       }
1060b57cec5SDimitry Andric     }
1070b57cec5SDimitry Andric     return result.Succeeded();
1080b57cec5SDimitry Andric   }
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric   std::string m_new_process_action;
1110b57cec5SDimitry Andric };
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric // CommandObjectProcessLaunch
1140b57cec5SDimitry Andric #pragma mark CommandObjectProcessLaunch
1150b57cec5SDimitry Andric class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach {
1160b57cec5SDimitry Andric public:
1170b57cec5SDimitry Andric   CommandObjectProcessLaunch(CommandInterpreter &interpreter)
1180b57cec5SDimitry Andric       : CommandObjectProcessLaunchOrAttach(
1190b57cec5SDimitry Andric             interpreter, "process launch",
1200b57cec5SDimitry Andric             "Launch the executable in the debugger.", nullptr,
1210b57cec5SDimitry Andric             eCommandRequiresTarget, "restart"),
12204eeddc0SDimitry Andric 
12304eeddc0SDimitry Andric         m_class_options("scripted process", true, 'C', 'k', 'v', 0) {
124fe6060f1SDimitry Andric     m_all_options.Append(&m_options);
125fe6060f1SDimitry Andric     m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2,
126fe6060f1SDimitry Andric                          LLDB_OPT_SET_ALL);
127fe6060f1SDimitry Andric     m_all_options.Finalize();
128fe6060f1SDimitry Andric 
1290b57cec5SDimitry Andric     CommandArgumentEntry arg;
1300b57cec5SDimitry Andric     CommandArgumentData run_args_arg;
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric     // Define the first (and only) variant of this arg.
1330b57cec5SDimitry Andric     run_args_arg.arg_type = eArgTypeRunArgs;
1340b57cec5SDimitry Andric     run_args_arg.arg_repetition = eArgRepeatOptional;
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric     // There is only one variant this argument could be; put it into the
1370b57cec5SDimitry Andric     // argument entry.
1380b57cec5SDimitry Andric     arg.push_back(run_args_arg);
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric     // Push the data for the first argument into the m_arguments vector.
1410b57cec5SDimitry Andric     m_arguments.push_back(arg);
1420b57cec5SDimitry Andric   }
1430b57cec5SDimitry Andric 
1440b57cec5SDimitry Andric   ~CommandObjectProcessLaunch() override = default;
1450b57cec5SDimitry Andric 
1469dba64beSDimitry Andric   void
1479dba64beSDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
1480b57cec5SDimitry Andric                            OptionElementVector &opt_element_vector) override {
1490b57cec5SDimitry Andric 
150*fe013be4SDimitry Andric     lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
151*fe013be4SDimitry Andric         GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr);
1520b57cec5SDimitry Andric   }
1530b57cec5SDimitry Andric 
154fe6060f1SDimitry Andric   Options *GetOptions() override { return &m_all_options; }
1550b57cec5SDimitry Andric 
156bdd1243dSDimitry Andric   std::optional<std::string> GetRepeatCommand(Args &current_command_args,
1570b57cec5SDimitry Andric                                               uint32_t index) override {
1580b57cec5SDimitry Andric     // No repeat for "process launch"...
15981ad6265SDimitry Andric     return std::string("");
1600b57cec5SDimitry Andric   }
1610b57cec5SDimitry Andric 
1620b57cec5SDimitry Andric protected:
1630b57cec5SDimitry Andric   bool DoExecute(Args &launch_args, CommandReturnObject &result) override {
1640b57cec5SDimitry Andric     Debugger &debugger = GetDebugger();
1650b57cec5SDimitry Andric     Target *target = debugger.GetSelectedTarget().get();
1660b57cec5SDimitry Andric     // If our listener is nullptr, users aren't allows to launch
1670b57cec5SDimitry Andric     ModuleSP exe_module_sp = target->GetExecutableModule();
1680b57cec5SDimitry Andric 
169349cc55cSDimitry Andric     // If the target already has an executable module, then use that.  If it
170349cc55cSDimitry Andric     // doesn't then someone must be trying to launch using a path that will
171349cc55cSDimitry Andric     // make sense to the remote stub, but doesn't exist on the local host.
172349cc55cSDimitry Andric     // In that case use the ExecutableFile that was set in the target's
173349cc55cSDimitry Andric     // ProcessLaunchInfo.
174349cc55cSDimitry Andric     if (exe_module_sp == nullptr && !target->GetProcessLaunchInfo().GetExecutableFile()) {
1750b57cec5SDimitry Andric       result.AppendError("no file in target, create a debug target using the "
1760b57cec5SDimitry Andric                          "'target create' command");
1770b57cec5SDimitry Andric       return false;
1780b57cec5SDimitry Andric     }
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric     StateType state = eStateInvalid;
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric     if (!StopProcessIfNecessary(m_exe_ctx.GetProcessPtr(), state, result))
1830b57cec5SDimitry Andric       return false;
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric     // Determine whether we will disable ASLR or leave it in the default state
1860b57cec5SDimitry Andric     // (i.e. enabled if the platform supports it). First check if the process
1870b57cec5SDimitry Andric     // launch options explicitly turn on/off
1880b57cec5SDimitry Andric     // disabling ASLR.  If so, use that setting;
1890b57cec5SDimitry Andric     // otherwise, use the 'settings target.disable-aslr' setting.
1900b57cec5SDimitry Andric     bool disable_aslr = false;
1910b57cec5SDimitry Andric     if (m_options.disable_aslr != eLazyBoolCalculate) {
1920b57cec5SDimitry Andric       // The user specified an explicit setting on the process launch line.
1930b57cec5SDimitry Andric       // Use it.
1940b57cec5SDimitry Andric       disable_aslr = (m_options.disable_aslr == eLazyBoolYes);
1950b57cec5SDimitry Andric     } else {
1960b57cec5SDimitry Andric       // The user did not explicitly specify whether to disable ASLR.  Fall
1970b57cec5SDimitry Andric       // back to the target.disable-aslr setting.
1980b57cec5SDimitry Andric       disable_aslr = target->GetDisableASLR();
1990b57cec5SDimitry Andric     }
2000b57cec5SDimitry Andric 
201fe6060f1SDimitry Andric     if (!m_class_options.GetName().empty()) {
202fe6060f1SDimitry Andric       m_options.launch_info.SetProcessPluginName("ScriptedProcess");
203*fe013be4SDimitry Andric       ScriptedMetadataSP metadata_sp = std::make_shared<ScriptedMetadata>(
204*fe013be4SDimitry Andric           m_class_options.GetName(), m_class_options.GetStructuredData());
205*fe013be4SDimitry Andric       m_options.launch_info.SetScriptedMetadata(metadata_sp);
206fe6060f1SDimitry Andric       target->SetProcessLaunchInfo(m_options.launch_info);
207fe6060f1SDimitry Andric     }
208fe6060f1SDimitry Andric 
2090b57cec5SDimitry Andric     if (disable_aslr)
2100b57cec5SDimitry Andric       m_options.launch_info.GetFlags().Set(eLaunchFlagDisableASLR);
2110b57cec5SDimitry Andric     else
2120b57cec5SDimitry Andric       m_options.launch_info.GetFlags().Clear(eLaunchFlagDisableASLR);
2130b57cec5SDimitry Andric 
214e8d8bef9SDimitry Andric     if (target->GetInheritTCC())
215e8d8bef9SDimitry Andric       m_options.launch_info.GetFlags().Set(eLaunchFlagInheritTCCFromParent);
216e8d8bef9SDimitry Andric 
2170b57cec5SDimitry Andric     if (target->GetDetachOnError())
2180b57cec5SDimitry Andric       m_options.launch_info.GetFlags().Set(eLaunchFlagDetachOnError);
2190b57cec5SDimitry Andric 
2200b57cec5SDimitry Andric     if (target->GetDisableSTDIO())
2210b57cec5SDimitry Andric       m_options.launch_info.GetFlags().Set(eLaunchFlagDisableSTDIO);
2220b57cec5SDimitry Andric 
2230b57cec5SDimitry Andric     // Merge the launch info environment with the target environment.
2240b57cec5SDimitry Andric     Environment target_env = target->GetEnvironment();
2250b57cec5SDimitry Andric     m_options.launch_info.GetEnvironment().insert(target_env.begin(),
2260b57cec5SDimitry Andric                                                   target_env.end());
2270b57cec5SDimitry Andric 
228349cc55cSDimitry Andric     llvm::StringRef target_settings_argv0 = target->GetArg0();
229349cc55cSDimitry Andric 
2300b57cec5SDimitry Andric     if (!target_settings_argv0.empty()) {
2310b57cec5SDimitry Andric       m_options.launch_info.GetArguments().AppendArgument(
2320b57cec5SDimitry Andric           target_settings_argv0);
233349cc55cSDimitry Andric       if (exe_module_sp)
2340b57cec5SDimitry Andric         m_options.launch_info.SetExecutableFile(
2350b57cec5SDimitry Andric             exe_module_sp->GetPlatformFileSpec(), false);
236349cc55cSDimitry Andric       else
237349cc55cSDimitry Andric         m_options.launch_info.SetExecutableFile(target->GetProcessLaunchInfo().GetExecutableFile(), false);
2380b57cec5SDimitry Andric     } else {
239349cc55cSDimitry Andric       if (exe_module_sp)
2400b57cec5SDimitry Andric         m_options.launch_info.SetExecutableFile(
2410b57cec5SDimitry Andric             exe_module_sp->GetPlatformFileSpec(), true);
242349cc55cSDimitry Andric       else
243349cc55cSDimitry Andric         m_options.launch_info.SetExecutableFile(target->GetProcessLaunchInfo().GetExecutableFile(), true);
2440b57cec5SDimitry Andric     }
2450b57cec5SDimitry Andric 
2460b57cec5SDimitry Andric     if (launch_args.GetArgumentCount() == 0) {
2470b57cec5SDimitry Andric       m_options.launch_info.GetArguments().AppendArguments(
2480b57cec5SDimitry Andric           target->GetProcessLaunchInfo().GetArguments());
2490b57cec5SDimitry Andric     } else {
2500b57cec5SDimitry Andric       m_options.launch_info.GetArguments().AppendArguments(launch_args);
2510b57cec5SDimitry Andric       // Save the arguments for subsequent runs in the current target.
2520b57cec5SDimitry Andric       target->SetRunArguments(launch_args);
2530b57cec5SDimitry Andric     }
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric     StreamString stream;
2560b57cec5SDimitry Andric     Status error = target->Launch(m_options.launch_info, &stream);
2570b57cec5SDimitry Andric 
2580b57cec5SDimitry Andric     if (error.Success()) {
2590b57cec5SDimitry Andric       ProcessSP process_sp(target->GetProcessSP());
2600b57cec5SDimitry Andric       if (process_sp) {
2610b57cec5SDimitry Andric         // There is a race condition where this thread will return up the call
2620b57cec5SDimitry Andric         // stack to the main command handler and show an (lldb) prompt before
2630b57cec5SDimitry Andric         // HandlePrivateEvent (from PrivateStateThread) has a chance to call
2640b57cec5SDimitry Andric         // PushProcessIOHandler().
2650b57cec5SDimitry Andric         process_sp->SyncIOHandler(0, std::chrono::seconds(2));
2660b57cec5SDimitry Andric 
2670b57cec5SDimitry Andric         llvm::StringRef data = stream.GetString();
2680b57cec5SDimitry Andric         if (!data.empty())
2690b57cec5SDimitry Andric           result.AppendMessage(data);
270349cc55cSDimitry Andric         // If we didn't have a local executable, then we wouldn't have had an
271349cc55cSDimitry Andric         // executable module before launch.
272349cc55cSDimitry Andric         if (!exe_module_sp)
273349cc55cSDimitry Andric           exe_module_sp = target->GetExecutableModule();
274349cc55cSDimitry Andric         if (!exe_module_sp) {
275349cc55cSDimitry Andric           result.AppendWarning("Could not get executable module after launch.");
276349cc55cSDimitry Andric         } else {
277349cc55cSDimitry Andric 
2780b57cec5SDimitry Andric           const char *archname =
2790b57cec5SDimitry Andric               exe_module_sp->GetArchitecture().GetArchitectureName();
2800b57cec5SDimitry Andric           result.AppendMessageWithFormat(
2810b57cec5SDimitry Andric               "Process %" PRIu64 " launched: '%s' (%s)\n", process_sp->GetID(),
2820b57cec5SDimitry Andric               exe_module_sp->GetFileSpec().GetPath().c_str(), archname);
283349cc55cSDimitry Andric         }
2840b57cec5SDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishResult);
2850b57cec5SDimitry Andric         result.SetDidChangeProcessState(true);
2860b57cec5SDimitry Andric       } else {
2870b57cec5SDimitry Andric         result.AppendError(
2880b57cec5SDimitry Andric             "no error returned from Target::Launch, and target has no process");
2890b57cec5SDimitry Andric       }
2900b57cec5SDimitry Andric     } else {
2910b57cec5SDimitry Andric       result.AppendError(error.AsCString());
2920b57cec5SDimitry Andric     }
2930b57cec5SDimitry Andric     return result.Succeeded();
2940b57cec5SDimitry Andric   }
2950b57cec5SDimitry Andric 
296e8d8bef9SDimitry Andric   CommandOptionsProcessLaunch m_options;
297fe6060f1SDimitry Andric   OptionGroupPythonClassWithDict m_class_options;
298fe6060f1SDimitry Andric   OptionGroupOptions m_all_options;
2990b57cec5SDimitry Andric };
3000b57cec5SDimitry Andric 
3019dba64beSDimitry Andric #define LLDB_OPTIONS_process_attach
3029dba64beSDimitry Andric #include "CommandOptions.inc"
3030b57cec5SDimitry Andric 
3040b57cec5SDimitry Andric #pragma mark CommandObjectProcessAttach
3050b57cec5SDimitry Andric class CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach {
3060b57cec5SDimitry Andric public:
3070b57cec5SDimitry Andric   CommandObjectProcessAttach(CommandInterpreter &interpreter)
3080b57cec5SDimitry Andric       : CommandObjectProcessLaunchOrAttach(
3090b57cec5SDimitry Andric             interpreter, "process attach", "Attach to a process.",
310*fe013be4SDimitry Andric             "process attach <cmd-options>", 0, "attach"),
311*fe013be4SDimitry Andric         m_class_options("scripted process", true, 'C', 'k', 'v', 0) {
312*fe013be4SDimitry Andric     m_all_options.Append(&m_options);
313*fe013be4SDimitry Andric     m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2,
314*fe013be4SDimitry Andric                          LLDB_OPT_SET_ALL);
315*fe013be4SDimitry Andric     m_all_options.Finalize();
316*fe013be4SDimitry Andric   }
3170b57cec5SDimitry Andric 
3180b57cec5SDimitry Andric   ~CommandObjectProcessAttach() override = default;
3190b57cec5SDimitry Andric 
320*fe013be4SDimitry Andric   Options *GetOptions() override { return &m_all_options; }
3210b57cec5SDimitry Andric 
3220b57cec5SDimitry Andric protected:
3230b57cec5SDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
3240b57cec5SDimitry Andric     PlatformSP platform_sp(
3250b57cec5SDimitry Andric         GetDebugger().GetPlatformList().GetSelectedPlatform());
3260b57cec5SDimitry Andric 
3270b57cec5SDimitry Andric     Target *target = GetDebugger().GetSelectedTarget().get();
3280b57cec5SDimitry Andric     // N.B. The attach should be synchronous.  It doesn't help much to get the
3290b57cec5SDimitry Andric     // prompt back between initiating the attach and the target actually
3300b57cec5SDimitry Andric     // stopping.  So even if the interpreter is set to be asynchronous, we wait
3310b57cec5SDimitry Andric     // for the stop ourselves here.
3320b57cec5SDimitry Andric 
3330b57cec5SDimitry Andric     StateType state = eStateInvalid;
3340b57cec5SDimitry Andric     Process *process = m_exe_ctx.GetProcessPtr();
3350b57cec5SDimitry Andric 
3360b57cec5SDimitry Andric     if (!StopProcessIfNecessary(process, state, result))
3370b57cec5SDimitry Andric       return false;
3380b57cec5SDimitry Andric 
3390b57cec5SDimitry Andric     if (target == nullptr) {
3400b57cec5SDimitry Andric       // If there isn't a current target create one.
3410b57cec5SDimitry Andric       TargetSP new_target_sp;
3420b57cec5SDimitry Andric       Status error;
3430b57cec5SDimitry Andric 
3440b57cec5SDimitry Andric       error = GetDebugger().GetTargetList().CreateTarget(
3450b57cec5SDimitry Andric           GetDebugger(), "", "", eLoadDependentsNo,
3460b57cec5SDimitry Andric           nullptr, // No platform options
3470b57cec5SDimitry Andric           new_target_sp);
3480b57cec5SDimitry Andric       target = new_target_sp.get();
3490b57cec5SDimitry Andric       if (target == nullptr || error.Fail()) {
3500b57cec5SDimitry Andric         result.AppendError(error.AsCString("Error creating target"));
3510b57cec5SDimitry Andric         return false;
3520b57cec5SDimitry Andric       }
3530b57cec5SDimitry Andric     }
3540b57cec5SDimitry Andric 
355*fe013be4SDimitry Andric     if (!m_class_options.GetName().empty()) {
356*fe013be4SDimitry Andric       m_options.attach_info.SetProcessPluginName("ScriptedProcess");
357*fe013be4SDimitry Andric       ScriptedMetadataSP metadata_sp = std::make_shared<ScriptedMetadata>(
358*fe013be4SDimitry Andric           m_class_options.GetName(), m_class_options.GetStructuredData());
359*fe013be4SDimitry Andric       m_options.attach_info.SetScriptedMetadata(metadata_sp);
360*fe013be4SDimitry Andric     }
361*fe013be4SDimitry Andric 
3620b57cec5SDimitry Andric     // Record the old executable module, we want to issue a warning if the
3630b57cec5SDimitry Andric     // process of attaching changed the current executable (like somebody said
3640b57cec5SDimitry Andric     // "file foo" then attached to a PID whose executable was bar.)
3650b57cec5SDimitry Andric 
3660b57cec5SDimitry Andric     ModuleSP old_exec_module_sp = target->GetExecutableModule();
3670b57cec5SDimitry Andric     ArchSpec old_arch_spec = target->GetArchitecture();
3680b57cec5SDimitry Andric 
3690b57cec5SDimitry Andric     StreamString stream;
370349cc55cSDimitry Andric     ProcessSP process_sp;
3710b57cec5SDimitry Andric     const auto error = target->Attach(m_options.attach_info, &stream);
3720b57cec5SDimitry Andric     if (error.Success()) {
373349cc55cSDimitry Andric       process_sp = target->GetProcessSP();
3740b57cec5SDimitry Andric       if (process_sp) {
3750b57cec5SDimitry Andric         result.AppendMessage(stream.GetString());
3760b57cec5SDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishNoResult);
3770b57cec5SDimitry Andric         result.SetDidChangeProcessState(true);
3780b57cec5SDimitry Andric       } else {
3790b57cec5SDimitry Andric         result.AppendError(
3800b57cec5SDimitry Andric             "no error returned from Target::Attach, and target has no process");
3810b57cec5SDimitry Andric       }
3820b57cec5SDimitry Andric     } else {
3830b57cec5SDimitry Andric       result.AppendErrorWithFormat("attach failed: %s\n", error.AsCString());
3840b57cec5SDimitry Andric     }
3850b57cec5SDimitry Andric 
3860b57cec5SDimitry Andric     if (!result.Succeeded())
3870b57cec5SDimitry Andric       return false;
3880b57cec5SDimitry Andric 
3890b57cec5SDimitry Andric     // Okay, we're done.  Last step is to warn if the executable module has
3900b57cec5SDimitry Andric     // changed:
3910b57cec5SDimitry Andric     char new_path[PATH_MAX];
3920b57cec5SDimitry Andric     ModuleSP new_exec_module_sp(target->GetExecutableModule());
3930b57cec5SDimitry Andric     if (!old_exec_module_sp) {
3940b57cec5SDimitry Andric       // We might not have a module if we attached to a raw pid...
3950b57cec5SDimitry Andric       if (new_exec_module_sp) {
3960b57cec5SDimitry Andric         new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX);
3970b57cec5SDimitry Andric         result.AppendMessageWithFormat("Executable module set to \"%s\".\n",
3980b57cec5SDimitry Andric                                        new_path);
3990b57cec5SDimitry Andric       }
4000b57cec5SDimitry Andric     } else if (old_exec_module_sp->GetFileSpec() !=
4010b57cec5SDimitry Andric                new_exec_module_sp->GetFileSpec()) {
4020b57cec5SDimitry Andric       char old_path[PATH_MAX];
4030b57cec5SDimitry Andric 
4040b57cec5SDimitry Andric       old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX);
4050b57cec5SDimitry Andric       new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX);
4060b57cec5SDimitry Andric 
4070b57cec5SDimitry Andric       result.AppendWarningWithFormat(
4080b57cec5SDimitry Andric           "Executable module changed from \"%s\" to \"%s\".\n", old_path,
4090b57cec5SDimitry Andric           new_path);
4100b57cec5SDimitry Andric     }
4110b57cec5SDimitry Andric 
4120b57cec5SDimitry Andric     if (!old_arch_spec.IsValid()) {
4130b57cec5SDimitry Andric       result.AppendMessageWithFormat(
4140b57cec5SDimitry Andric           "Architecture set to: %s.\n",
4150b57cec5SDimitry Andric           target->GetArchitecture().GetTriple().getTriple().c_str());
4160b57cec5SDimitry Andric     } else if (!old_arch_spec.IsExactMatch(target->GetArchitecture())) {
4170b57cec5SDimitry Andric       result.AppendWarningWithFormat(
4180b57cec5SDimitry Andric           "Architecture changed from %s to %s.\n",
4190b57cec5SDimitry Andric           old_arch_spec.GetTriple().getTriple().c_str(),
4200b57cec5SDimitry Andric           target->GetArchitecture().GetTriple().getTriple().c_str());
4210b57cec5SDimitry Andric     }
4220b57cec5SDimitry Andric 
4230b57cec5SDimitry Andric     // This supports the use-case scenario of immediately continuing the
4240b57cec5SDimitry Andric     // process once attached.
425349cc55cSDimitry Andric     if (m_options.attach_info.GetContinueOnceAttached()) {
426349cc55cSDimitry Andric       // We have made a process but haven't told the interpreter about it yet,
427349cc55cSDimitry Andric       // so CheckRequirements will fail for "process continue".  Set the override
428349cc55cSDimitry Andric       // here:
429349cc55cSDimitry Andric       ExecutionContext exe_ctx(process_sp);
430349cc55cSDimitry Andric       m_interpreter.HandleCommand("process continue", eLazyBoolNo, exe_ctx, result);
431349cc55cSDimitry Andric     }
4320b57cec5SDimitry Andric 
4330b57cec5SDimitry Andric     return result.Succeeded();
4340b57cec5SDimitry Andric   }
4350b57cec5SDimitry Andric 
436*fe013be4SDimitry Andric   CommandOptionsProcessAttach m_options;
437*fe013be4SDimitry Andric   OptionGroupPythonClassWithDict m_class_options;
438*fe013be4SDimitry Andric   OptionGroupOptions m_all_options;
4390b57cec5SDimitry Andric };
4400b57cec5SDimitry Andric 
4410b57cec5SDimitry Andric // CommandObjectProcessContinue
4420b57cec5SDimitry Andric 
4439dba64beSDimitry Andric #define LLDB_OPTIONS_process_continue
4449dba64beSDimitry Andric #include "CommandOptions.inc"
4450b57cec5SDimitry Andric 
4460b57cec5SDimitry Andric #pragma mark CommandObjectProcessContinue
4470b57cec5SDimitry Andric 
4480b57cec5SDimitry Andric class CommandObjectProcessContinue : public CommandObjectParsed {
4490b57cec5SDimitry Andric public:
4500b57cec5SDimitry Andric   CommandObjectProcessContinue(CommandInterpreter &interpreter)
4510b57cec5SDimitry Andric       : CommandObjectParsed(
4520b57cec5SDimitry Andric             interpreter, "process continue",
4530b57cec5SDimitry Andric             "Continue execution of all threads in the current process.",
4540b57cec5SDimitry Andric             "process continue",
4550b57cec5SDimitry Andric             eCommandRequiresProcess | eCommandTryTargetAPILock |
45604eeddc0SDimitry Andric                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {}
4570b57cec5SDimitry Andric 
4580b57cec5SDimitry Andric   ~CommandObjectProcessContinue() override = default;
4590b57cec5SDimitry Andric 
4600b57cec5SDimitry Andric protected:
4610b57cec5SDimitry Andric   class CommandOptions : public Options {
4620b57cec5SDimitry Andric   public:
46304eeddc0SDimitry Andric     CommandOptions() {
4640b57cec5SDimitry Andric       // Keep default values of all options in one place: OptionParsingStarting
4650b57cec5SDimitry Andric       // ()
4660b57cec5SDimitry Andric       OptionParsingStarting(nullptr);
4670b57cec5SDimitry Andric     }
4680b57cec5SDimitry Andric 
4690b57cec5SDimitry Andric     ~CommandOptions() override = default;
4700b57cec5SDimitry Andric 
4710b57cec5SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
47281ad6265SDimitry Andric                           ExecutionContext *exe_ctx) override {
4730b57cec5SDimitry Andric       Status error;
4740b57cec5SDimitry Andric       const int short_option = m_getopt_table[option_idx].val;
4750b57cec5SDimitry Andric       switch (short_option) {
4760b57cec5SDimitry Andric       case 'i':
4770b57cec5SDimitry Andric         if (option_arg.getAsInteger(0, m_ignore))
4780b57cec5SDimitry Andric           error.SetErrorStringWithFormat(
4790b57cec5SDimitry Andric               "invalid value for ignore option: \"%s\", should be a number.",
4800b57cec5SDimitry Andric               option_arg.str().c_str());
4810b57cec5SDimitry Andric         break;
48281ad6265SDimitry Andric       case 'b':
48381ad6265SDimitry Andric         m_run_to_bkpt_args.AppendArgument(option_arg);
48481ad6265SDimitry Andric         m_any_bkpts_specified = true;
48581ad6265SDimitry Andric       break;
4860b57cec5SDimitry Andric       default:
4879dba64beSDimitry Andric         llvm_unreachable("Unimplemented option");
4880b57cec5SDimitry Andric       }
4890b57cec5SDimitry Andric       return error;
4900b57cec5SDimitry Andric     }
4910b57cec5SDimitry Andric 
4920b57cec5SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
4930b57cec5SDimitry Andric       m_ignore = 0;
49481ad6265SDimitry Andric       m_run_to_bkpt_args.Clear();
49581ad6265SDimitry Andric       m_any_bkpts_specified = false;
4960b57cec5SDimitry Andric     }
4970b57cec5SDimitry Andric 
4980b57cec5SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
499bdd1243dSDimitry Andric       return llvm::ArrayRef(g_process_continue_options);
5000b57cec5SDimitry Andric     }
5010b57cec5SDimitry Andric 
50281ad6265SDimitry Andric     uint32_t m_ignore = 0;
50381ad6265SDimitry Andric     Args m_run_to_bkpt_args;
50481ad6265SDimitry Andric     bool m_any_bkpts_specified = false;
5050b57cec5SDimitry Andric   };
5060b57cec5SDimitry Andric 
50781ad6265SDimitry Andric 
5080b57cec5SDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
5090b57cec5SDimitry Andric     Process *process = m_exe_ctx.GetProcessPtr();
5100b57cec5SDimitry Andric     bool synchronous_execution = m_interpreter.GetSynchronous();
5110b57cec5SDimitry Andric     StateType state = process->GetState();
5120b57cec5SDimitry Andric     if (state == eStateStopped) {
5130b57cec5SDimitry Andric       if (m_options.m_ignore > 0) {
5140b57cec5SDimitry Andric         ThreadSP sel_thread_sp(GetDefaultThread()->shared_from_this());
5150b57cec5SDimitry Andric         if (sel_thread_sp) {
5160b57cec5SDimitry Andric           StopInfoSP stop_info_sp = sel_thread_sp->GetStopInfo();
5170b57cec5SDimitry Andric           if (stop_info_sp &&
5180b57cec5SDimitry Andric               stop_info_sp->GetStopReason() == eStopReasonBreakpoint) {
5190b57cec5SDimitry Andric             lldb::break_id_t bp_site_id =
5200b57cec5SDimitry Andric                 (lldb::break_id_t)stop_info_sp->GetValue();
5210b57cec5SDimitry Andric             BreakpointSiteSP bp_site_sp(
5220b57cec5SDimitry Andric                 process->GetBreakpointSiteList().FindByID(bp_site_id));
5230b57cec5SDimitry Andric             if (bp_site_sp) {
5240b57cec5SDimitry Andric               const size_t num_owners = bp_site_sp->GetNumberOfOwners();
5250b57cec5SDimitry Andric               for (size_t i = 0; i < num_owners; i++) {
5260b57cec5SDimitry Andric                 Breakpoint &bp_ref =
5270b57cec5SDimitry Andric                     bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint();
5280b57cec5SDimitry Andric                 if (!bp_ref.IsInternal()) {
5290b57cec5SDimitry Andric                   bp_ref.SetIgnoreCount(m_options.m_ignore);
5300b57cec5SDimitry Andric                 }
5310b57cec5SDimitry Andric               }
5320b57cec5SDimitry Andric             }
5330b57cec5SDimitry Andric           }
5340b57cec5SDimitry Andric         }
5350b57cec5SDimitry Andric       }
5360b57cec5SDimitry Andric 
53781ad6265SDimitry Andric       Target *target = m_exe_ctx.GetTargetPtr();
53881ad6265SDimitry Andric       BreakpointIDList run_to_bkpt_ids;
53981ad6265SDimitry Andric       // Don't pass an empty run_to_breakpoint list, as Verify will look for the
54081ad6265SDimitry Andric       // default breakpoint.
54181ad6265SDimitry Andric       if (m_options.m_run_to_bkpt_args.GetArgumentCount() > 0)
54281ad6265SDimitry Andric         CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
54381ad6265SDimitry Andric             m_options.m_run_to_bkpt_args, target, result, &run_to_bkpt_ids,
54481ad6265SDimitry Andric             BreakpointName::Permissions::disablePerm);
54581ad6265SDimitry Andric       if (!result.Succeeded()) {
54681ad6265SDimitry Andric         return false;
54781ad6265SDimitry Andric       }
54881ad6265SDimitry Andric       result.Clear();
54981ad6265SDimitry Andric       if (m_options.m_any_bkpts_specified && run_to_bkpt_ids.GetSize() == 0) {
55081ad6265SDimitry Andric         result.AppendError("continue-to breakpoints did not specify any actual "
55181ad6265SDimitry Andric                            "breakpoints or locations");
55281ad6265SDimitry Andric         return false;
55381ad6265SDimitry Andric       }
55481ad6265SDimitry Andric 
55581ad6265SDimitry Andric       // First figure out which breakpoints & locations were specified by the
55681ad6265SDimitry Andric       // user:
55781ad6265SDimitry Andric       size_t num_run_to_bkpt_ids = run_to_bkpt_ids.GetSize();
55881ad6265SDimitry Andric       std::vector<break_id_t> bkpts_disabled;
55981ad6265SDimitry Andric       std::vector<BreakpointID> locs_disabled;
56081ad6265SDimitry Andric       if (num_run_to_bkpt_ids != 0) {
56181ad6265SDimitry Andric         // Go through the ID's specified, and separate the breakpoints from are
56281ad6265SDimitry Andric         // the breakpoint.location specifications since the latter require
56381ad6265SDimitry Andric         // special handling.  We also figure out whether there's at least one
56481ad6265SDimitry Andric         // specifier in the set that is enabled.
56581ad6265SDimitry Andric         BreakpointList &bkpt_list = target->GetBreakpointList();
56681ad6265SDimitry Andric         std::unordered_set<break_id_t> bkpts_seen;
56781ad6265SDimitry Andric         std::unordered_set<break_id_t> bkpts_with_locs_seen;
56881ad6265SDimitry Andric         BreakpointIDList with_locs;
56981ad6265SDimitry Andric         bool any_enabled = false;
57081ad6265SDimitry Andric 
57181ad6265SDimitry Andric         for (size_t idx = 0; idx < num_run_to_bkpt_ids; idx++) {
57281ad6265SDimitry Andric           BreakpointID bkpt_id = run_to_bkpt_ids.GetBreakpointIDAtIndex(idx);
57381ad6265SDimitry Andric           break_id_t bp_id = bkpt_id.GetBreakpointID();
57481ad6265SDimitry Andric           break_id_t loc_id = bkpt_id.GetLocationID();
57581ad6265SDimitry Andric           BreakpointSP bp_sp
57681ad6265SDimitry Andric               = bkpt_list.FindBreakpointByID(bp_id);
57781ad6265SDimitry Andric           // Note, VerifyBreakpointOrLocationIDs checks for existence, so we
57881ad6265SDimitry Andric           // don't need to do it again here.
57981ad6265SDimitry Andric           if (bp_sp->IsEnabled()) {
58081ad6265SDimitry Andric             if (loc_id == LLDB_INVALID_BREAK_ID) {
58181ad6265SDimitry Andric               // A breakpoint (without location) was specified.  Make sure that
58281ad6265SDimitry Andric               // at least one of the locations is enabled.
58381ad6265SDimitry Andric               size_t num_locations = bp_sp->GetNumLocations();
58481ad6265SDimitry Andric               for (size_t loc_idx = 0; loc_idx < num_locations; loc_idx++) {
58581ad6265SDimitry Andric                 BreakpointLocationSP loc_sp
58681ad6265SDimitry Andric                     = bp_sp->GetLocationAtIndex(loc_idx);
58781ad6265SDimitry Andric                 if (loc_sp->IsEnabled()) {
58881ad6265SDimitry Andric                   any_enabled = true;
58981ad6265SDimitry Andric                   break;
59081ad6265SDimitry Andric                 }
59181ad6265SDimitry Andric               }
59281ad6265SDimitry Andric             } else {
59381ad6265SDimitry Andric               // A location was specified, check if it was enabled:
59481ad6265SDimitry Andric               BreakpointLocationSP loc_sp = bp_sp->FindLocationByID(loc_id);
59581ad6265SDimitry Andric               if (loc_sp->IsEnabled())
59681ad6265SDimitry Andric                 any_enabled = true;
59781ad6265SDimitry Andric             }
59881ad6265SDimitry Andric 
59981ad6265SDimitry Andric             // Then sort the bp & bp.loc entries for later use:
60081ad6265SDimitry Andric             if (bkpt_id.GetLocationID() == LLDB_INVALID_BREAK_ID)
60181ad6265SDimitry Andric               bkpts_seen.insert(bkpt_id.GetBreakpointID());
60281ad6265SDimitry Andric             else {
60381ad6265SDimitry Andric               bkpts_with_locs_seen.insert(bkpt_id.GetBreakpointID());
60481ad6265SDimitry Andric               with_locs.AddBreakpointID(bkpt_id);
60581ad6265SDimitry Andric             }
60681ad6265SDimitry Andric           }
60781ad6265SDimitry Andric         }
60881ad6265SDimitry Andric         // Do all the error checking here so once we start disabling we don't
60981ad6265SDimitry Andric         // have to back out half-way through.
61081ad6265SDimitry Andric 
61181ad6265SDimitry Andric         // Make sure at least one of the specified breakpoints is enabled.
61281ad6265SDimitry Andric         if (!any_enabled) {
61381ad6265SDimitry Andric           result.AppendError("at least one of the continue-to breakpoints must "
61481ad6265SDimitry Andric                              "be enabled.");
61581ad6265SDimitry Andric           return false;
61681ad6265SDimitry Andric         }
61781ad6265SDimitry Andric 
61881ad6265SDimitry Andric         // Also, if you specify BOTH a breakpoint and one of it's locations,
61981ad6265SDimitry Andric         // we flag that as an error, since it won't do what you expect, the
62081ad6265SDimitry Andric         // breakpoint directive will mean "run to all locations", which is not
62181ad6265SDimitry Andric         // what the location directive means...
62281ad6265SDimitry Andric         for (break_id_t bp_id : bkpts_with_locs_seen) {
62381ad6265SDimitry Andric           if (bkpts_seen.count(bp_id)) {
62481ad6265SDimitry Andric             result.AppendErrorWithFormatv("can't specify both a breakpoint and "
62581ad6265SDimitry Andric                                "one of its locations: {0}", bp_id);
62681ad6265SDimitry Andric           }
62781ad6265SDimitry Andric         }
62881ad6265SDimitry Andric 
62981ad6265SDimitry Andric         // Now go through the breakpoints in the target, disabling all the ones
63081ad6265SDimitry Andric         // that the user didn't mention:
63181ad6265SDimitry Andric         for (BreakpointSP bp_sp : bkpt_list.Breakpoints()) {
63281ad6265SDimitry Andric           break_id_t bp_id = bp_sp->GetID();
63381ad6265SDimitry Andric           // Handle the case where no locations were specified.  Note we don't
63481ad6265SDimitry Andric           // have to worry about the case where a breakpoint and one of its
63581ad6265SDimitry Andric           // locations are both in the lists, we've already disallowed that.
63681ad6265SDimitry Andric           if (!bkpts_with_locs_seen.count(bp_id)) {
63781ad6265SDimitry Andric             if (!bkpts_seen.count(bp_id) && bp_sp->IsEnabled()) {
63881ad6265SDimitry Andric               bkpts_disabled.push_back(bp_id);
63981ad6265SDimitry Andric               bp_sp->SetEnabled(false);
64081ad6265SDimitry Andric             }
64181ad6265SDimitry Andric             continue;
64281ad6265SDimitry Andric           }
64381ad6265SDimitry Andric           // Next, handle the case where a location was specified:
64481ad6265SDimitry Andric           // Run through all the locations of this breakpoint and disable
64581ad6265SDimitry Andric           // the ones that aren't on our "with locations" BreakpointID list:
64681ad6265SDimitry Andric           size_t num_locations = bp_sp->GetNumLocations();
64781ad6265SDimitry Andric           BreakpointID tmp_id(bp_id, LLDB_INVALID_BREAK_ID);
64881ad6265SDimitry Andric           for (size_t loc_idx = 0; loc_idx < num_locations; loc_idx++) {
64981ad6265SDimitry Andric             BreakpointLocationSP loc_sp = bp_sp->GetLocationAtIndex(loc_idx);
65081ad6265SDimitry Andric             tmp_id.SetBreakpointLocationID(loc_idx);
65181ad6265SDimitry Andric             size_t position = 0;
65281ad6265SDimitry Andric             if (!with_locs.FindBreakpointID(tmp_id, &position)
65381ad6265SDimitry Andric                 && loc_sp->IsEnabled()) {
65481ad6265SDimitry Andric               locs_disabled.push_back(tmp_id);
65581ad6265SDimitry Andric               loc_sp->SetEnabled(false);
65681ad6265SDimitry Andric             }
65781ad6265SDimitry Andric           }
65881ad6265SDimitry Andric         }
65981ad6265SDimitry Andric       }
66081ad6265SDimitry Andric 
6610b57cec5SDimitry Andric       { // Scope for thread list mutex:
6620b57cec5SDimitry Andric         std::lock_guard<std::recursive_mutex> guard(
6630b57cec5SDimitry Andric             process->GetThreadList().GetMutex());
6640b57cec5SDimitry Andric         const uint32_t num_threads = process->GetThreadList().GetSize();
6650b57cec5SDimitry Andric 
6660b57cec5SDimitry Andric         // Set the actions that the threads should each take when resuming
6670b57cec5SDimitry Andric         for (uint32_t idx = 0; idx < num_threads; ++idx) {
6680b57cec5SDimitry Andric           const bool override_suspend = false;
6690b57cec5SDimitry Andric           process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState(
6700b57cec5SDimitry Andric               eStateRunning, override_suspend);
6710b57cec5SDimitry Andric         }
6720b57cec5SDimitry Andric       }
6730b57cec5SDimitry Andric 
6740b57cec5SDimitry Andric       const uint32_t iohandler_id = process->GetIOHandlerID();
6750b57cec5SDimitry Andric 
6760b57cec5SDimitry Andric       StreamString stream;
6770b57cec5SDimitry Andric       Status error;
67881ad6265SDimitry Andric       // For now we can only do -b with synchronous:
67981ad6265SDimitry Andric       bool old_sync = GetDebugger().GetAsyncExecution();
68081ad6265SDimitry Andric 
68181ad6265SDimitry Andric       if (run_to_bkpt_ids.GetSize() != 0) {
68281ad6265SDimitry Andric         GetDebugger().SetAsyncExecution(false);
68381ad6265SDimitry Andric         synchronous_execution = true;
68481ad6265SDimitry Andric       }
6850b57cec5SDimitry Andric       if (synchronous_execution)
6860b57cec5SDimitry Andric         error = process->ResumeSynchronous(&stream);
6870b57cec5SDimitry Andric       else
6880b57cec5SDimitry Andric         error = process->Resume();
6890b57cec5SDimitry Andric 
69081ad6265SDimitry Andric       if (run_to_bkpt_ids.GetSize() != 0) {
69181ad6265SDimitry Andric         GetDebugger().SetAsyncExecution(old_sync);
69281ad6265SDimitry Andric       }
69381ad6265SDimitry Andric 
69481ad6265SDimitry Andric       // Now re-enable the breakpoints we disabled:
69581ad6265SDimitry Andric       BreakpointList &bkpt_list = target->GetBreakpointList();
69681ad6265SDimitry Andric       for (break_id_t bp_id : bkpts_disabled) {
69781ad6265SDimitry Andric         BreakpointSP bp_sp = bkpt_list.FindBreakpointByID(bp_id);
69881ad6265SDimitry Andric         if (bp_sp)
69981ad6265SDimitry Andric           bp_sp->SetEnabled(true);
70081ad6265SDimitry Andric       }
70181ad6265SDimitry Andric       for (const BreakpointID &bkpt_id : locs_disabled) {
70281ad6265SDimitry Andric         BreakpointSP bp_sp
70381ad6265SDimitry Andric             = bkpt_list.FindBreakpointByID(bkpt_id.GetBreakpointID());
70481ad6265SDimitry Andric         if (bp_sp) {
70581ad6265SDimitry Andric           BreakpointLocationSP loc_sp
70681ad6265SDimitry Andric               = bp_sp->FindLocationByID(bkpt_id.GetLocationID());
70781ad6265SDimitry Andric           if (loc_sp)
70881ad6265SDimitry Andric             loc_sp->SetEnabled(true);
70981ad6265SDimitry Andric         }
71081ad6265SDimitry Andric       }
71181ad6265SDimitry Andric 
7120b57cec5SDimitry Andric       if (error.Success()) {
7130b57cec5SDimitry Andric         // There is a race condition where this thread will return up the call
7140b57cec5SDimitry Andric         // stack to the main command handler and show an (lldb) prompt before
7150b57cec5SDimitry Andric         // HandlePrivateEvent (from PrivateStateThread) has a chance to call
7160b57cec5SDimitry Andric         // PushProcessIOHandler().
7170b57cec5SDimitry Andric         process->SyncIOHandler(iohandler_id, std::chrono::seconds(2));
7180b57cec5SDimitry Andric 
7190b57cec5SDimitry Andric         result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n",
7200b57cec5SDimitry Andric                                        process->GetID());
7210b57cec5SDimitry Andric         if (synchronous_execution) {
7220b57cec5SDimitry Andric           // If any state changed events had anything to say, add that to the
7230b57cec5SDimitry Andric           // result
7240b57cec5SDimitry Andric           result.AppendMessage(stream.GetString());
7250b57cec5SDimitry Andric 
7260b57cec5SDimitry Andric           result.SetDidChangeProcessState(true);
7270b57cec5SDimitry Andric           result.SetStatus(eReturnStatusSuccessFinishNoResult);
7280b57cec5SDimitry Andric         } else {
7290b57cec5SDimitry Andric           result.SetStatus(eReturnStatusSuccessContinuingNoResult);
7300b57cec5SDimitry Andric         }
7310b57cec5SDimitry Andric       } else {
7320b57cec5SDimitry Andric         result.AppendErrorWithFormat("Failed to resume process: %s.\n",
7330b57cec5SDimitry Andric                                      error.AsCString());
7340b57cec5SDimitry Andric       }
7350b57cec5SDimitry Andric     } else {
7360b57cec5SDimitry Andric       result.AppendErrorWithFormat(
7370b57cec5SDimitry Andric           "Process cannot be continued from its current state (%s).\n",
7380b57cec5SDimitry Andric           StateAsCString(state));
7390b57cec5SDimitry Andric     }
7400b57cec5SDimitry Andric     return result.Succeeded();
7410b57cec5SDimitry Andric   }
7420b57cec5SDimitry Andric 
7430b57cec5SDimitry Andric   Options *GetOptions() override { return &m_options; }
7440b57cec5SDimitry Andric 
7450b57cec5SDimitry Andric   CommandOptions m_options;
7460b57cec5SDimitry Andric };
7470b57cec5SDimitry Andric 
7480b57cec5SDimitry Andric // CommandObjectProcessDetach
7499dba64beSDimitry Andric #define LLDB_OPTIONS_process_detach
7509dba64beSDimitry Andric #include "CommandOptions.inc"
7510b57cec5SDimitry Andric 
7520b57cec5SDimitry Andric #pragma mark CommandObjectProcessDetach
7530b57cec5SDimitry Andric 
7540b57cec5SDimitry Andric class CommandObjectProcessDetach : public CommandObjectParsed {
7550b57cec5SDimitry Andric public:
7560b57cec5SDimitry Andric   class CommandOptions : public Options {
7570b57cec5SDimitry Andric   public:
75804eeddc0SDimitry Andric     CommandOptions() { OptionParsingStarting(nullptr); }
7590b57cec5SDimitry Andric 
7600b57cec5SDimitry Andric     ~CommandOptions() override = default;
7610b57cec5SDimitry Andric 
7620b57cec5SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
7630b57cec5SDimitry Andric                           ExecutionContext *execution_context) override {
7640b57cec5SDimitry Andric       Status error;
7650b57cec5SDimitry Andric       const int short_option = m_getopt_table[option_idx].val;
7660b57cec5SDimitry Andric 
7670b57cec5SDimitry Andric       switch (short_option) {
7680b57cec5SDimitry Andric       case 's':
7690b57cec5SDimitry Andric         bool tmp_result;
7700b57cec5SDimitry Andric         bool success;
7710b57cec5SDimitry Andric         tmp_result = OptionArgParser::ToBoolean(option_arg, false, &success);
7720b57cec5SDimitry Andric         if (!success)
7730b57cec5SDimitry Andric           error.SetErrorStringWithFormat("invalid boolean option: \"%s\"",
7740b57cec5SDimitry Andric                                          option_arg.str().c_str());
7750b57cec5SDimitry Andric         else {
7760b57cec5SDimitry Andric           if (tmp_result)
7770b57cec5SDimitry Andric             m_keep_stopped = eLazyBoolYes;
7780b57cec5SDimitry Andric           else
7790b57cec5SDimitry Andric             m_keep_stopped = eLazyBoolNo;
7800b57cec5SDimitry Andric         }
7810b57cec5SDimitry Andric         break;
7820b57cec5SDimitry Andric       default:
7839dba64beSDimitry Andric         llvm_unreachable("Unimplemented option");
7840b57cec5SDimitry Andric       }
7850b57cec5SDimitry Andric       return error;
7860b57cec5SDimitry Andric     }
7870b57cec5SDimitry Andric 
7880b57cec5SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
7890b57cec5SDimitry Andric       m_keep_stopped = eLazyBoolCalculate;
7900b57cec5SDimitry Andric     }
7910b57cec5SDimitry Andric 
7920b57cec5SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
793bdd1243dSDimitry Andric       return llvm::ArrayRef(g_process_detach_options);
7940b57cec5SDimitry Andric     }
7950b57cec5SDimitry Andric 
7960b57cec5SDimitry Andric     // Instance variables to hold the values for command options.
7970b57cec5SDimitry Andric     LazyBool m_keep_stopped;
7980b57cec5SDimitry Andric   };
7990b57cec5SDimitry Andric 
8000b57cec5SDimitry Andric   CommandObjectProcessDetach(CommandInterpreter &interpreter)
8010b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "process detach",
8020b57cec5SDimitry Andric                             "Detach from the current target process.",
8030b57cec5SDimitry Andric                             "process detach",
8040b57cec5SDimitry Andric                             eCommandRequiresProcess | eCommandTryTargetAPILock |
80504eeddc0SDimitry Andric                                 eCommandProcessMustBeLaunched) {}
8060b57cec5SDimitry Andric 
8070b57cec5SDimitry Andric   ~CommandObjectProcessDetach() override = default;
8080b57cec5SDimitry Andric 
8090b57cec5SDimitry Andric   Options *GetOptions() override { return &m_options; }
8100b57cec5SDimitry Andric 
8110b57cec5SDimitry Andric protected:
8120b57cec5SDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
8130b57cec5SDimitry Andric     Process *process = m_exe_ctx.GetProcessPtr();
8140b57cec5SDimitry Andric     // FIXME: This will be a Command Option:
8150b57cec5SDimitry Andric     bool keep_stopped;
8160b57cec5SDimitry Andric     if (m_options.m_keep_stopped == eLazyBoolCalculate) {
8170b57cec5SDimitry Andric       // Check the process default:
8180b57cec5SDimitry Andric       keep_stopped = process->GetDetachKeepsStopped();
8190b57cec5SDimitry Andric     } else if (m_options.m_keep_stopped == eLazyBoolYes)
8200b57cec5SDimitry Andric       keep_stopped = true;
8210b57cec5SDimitry Andric     else
8220b57cec5SDimitry Andric       keep_stopped = false;
8230b57cec5SDimitry Andric 
8240b57cec5SDimitry Andric     Status error(process->Detach(keep_stopped));
8250b57cec5SDimitry Andric     if (error.Success()) {
8260b57cec5SDimitry Andric       result.SetStatus(eReturnStatusSuccessFinishResult);
8270b57cec5SDimitry Andric     } else {
8280b57cec5SDimitry Andric       result.AppendErrorWithFormat("Detach failed: %s\n", error.AsCString());
8290b57cec5SDimitry Andric       return false;
8300b57cec5SDimitry Andric     }
8310b57cec5SDimitry Andric     return result.Succeeded();
8320b57cec5SDimitry Andric   }
8330b57cec5SDimitry Andric 
8340b57cec5SDimitry Andric   CommandOptions m_options;
8350b57cec5SDimitry Andric };
8360b57cec5SDimitry Andric 
8370b57cec5SDimitry Andric // CommandObjectProcessConnect
8389dba64beSDimitry Andric #define LLDB_OPTIONS_process_connect
8399dba64beSDimitry Andric #include "CommandOptions.inc"
8400b57cec5SDimitry Andric 
8410b57cec5SDimitry Andric #pragma mark CommandObjectProcessConnect
8420b57cec5SDimitry Andric 
8430b57cec5SDimitry Andric class CommandObjectProcessConnect : public CommandObjectParsed {
8440b57cec5SDimitry Andric public:
8450b57cec5SDimitry Andric   class CommandOptions : public Options {
8460b57cec5SDimitry Andric   public:
84704eeddc0SDimitry Andric     CommandOptions() {
8480b57cec5SDimitry Andric       // Keep default values of all options in one place: OptionParsingStarting
8490b57cec5SDimitry Andric       // ()
8500b57cec5SDimitry Andric       OptionParsingStarting(nullptr);
8510b57cec5SDimitry Andric     }
8520b57cec5SDimitry Andric 
8530b57cec5SDimitry Andric     ~CommandOptions() override = default;
8540b57cec5SDimitry Andric 
8550b57cec5SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
8560b57cec5SDimitry Andric                           ExecutionContext *execution_context) override {
8570b57cec5SDimitry Andric       Status error;
8580b57cec5SDimitry Andric       const int short_option = m_getopt_table[option_idx].val;
8590b57cec5SDimitry Andric 
8600b57cec5SDimitry Andric       switch (short_option) {
8610b57cec5SDimitry Andric       case 'p':
8625ffd83dbSDimitry Andric         plugin_name.assign(std::string(option_arg));
8630b57cec5SDimitry Andric         break;
8640b57cec5SDimitry Andric 
8650b57cec5SDimitry Andric       default:
8669dba64beSDimitry Andric         llvm_unreachable("Unimplemented option");
8670b57cec5SDimitry Andric       }
8680b57cec5SDimitry Andric       return error;
8690b57cec5SDimitry Andric     }
8700b57cec5SDimitry Andric 
8710b57cec5SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
8720b57cec5SDimitry Andric       plugin_name.clear();
8730b57cec5SDimitry Andric     }
8740b57cec5SDimitry Andric 
8750b57cec5SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
876bdd1243dSDimitry Andric       return llvm::ArrayRef(g_process_connect_options);
8770b57cec5SDimitry Andric     }
8780b57cec5SDimitry Andric 
8790b57cec5SDimitry Andric     // Instance variables to hold the values for command options.
8800b57cec5SDimitry Andric 
8810b57cec5SDimitry Andric     std::string plugin_name;
8820b57cec5SDimitry Andric   };
8830b57cec5SDimitry Andric 
8840b57cec5SDimitry Andric   CommandObjectProcessConnect(CommandInterpreter &interpreter)
8850b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "process connect",
8860b57cec5SDimitry Andric                             "Connect to a remote debug service.",
88781ad6265SDimitry Andric                             "process connect <remote-url>", 0) {
88881ad6265SDimitry Andric     CommandArgumentData connect_arg{eArgTypeConnectURL, eArgRepeatPlain};
88981ad6265SDimitry Andric     m_arguments.push_back({connect_arg});
89081ad6265SDimitry Andric   }
8910b57cec5SDimitry Andric 
8920b57cec5SDimitry Andric   ~CommandObjectProcessConnect() override = default;
8930b57cec5SDimitry Andric 
8940b57cec5SDimitry Andric   Options *GetOptions() override { return &m_options; }
8950b57cec5SDimitry Andric 
8960b57cec5SDimitry Andric protected:
8970b57cec5SDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
8980b57cec5SDimitry Andric     if (command.GetArgumentCount() != 1) {
8990b57cec5SDimitry Andric       result.AppendErrorWithFormat(
9000b57cec5SDimitry Andric           "'%s' takes exactly one argument:\nUsage: %s\n", m_cmd_name.c_str(),
9010b57cec5SDimitry Andric           m_cmd_syntax.c_str());
9020b57cec5SDimitry Andric       return false;
9030b57cec5SDimitry Andric     }
9040b57cec5SDimitry Andric 
9050b57cec5SDimitry Andric     Process *process = m_exe_ctx.GetProcessPtr();
9060b57cec5SDimitry Andric     if (process && process->IsAlive()) {
9070b57cec5SDimitry Andric       result.AppendErrorWithFormat(
9080b57cec5SDimitry Andric           "Process %" PRIu64
9090b57cec5SDimitry Andric           " is currently being debugged, kill the process before connecting.\n",
9100b57cec5SDimitry Andric           process->GetID());
9110b57cec5SDimitry Andric       return false;
9120b57cec5SDimitry Andric     }
9130b57cec5SDimitry Andric 
9140b57cec5SDimitry Andric     const char *plugin_name = nullptr;
9150b57cec5SDimitry Andric     if (!m_options.plugin_name.empty())
9160b57cec5SDimitry Andric       plugin_name = m_options.plugin_name.c_str();
9170b57cec5SDimitry Andric 
9180b57cec5SDimitry Andric     Status error;
9190b57cec5SDimitry Andric     Debugger &debugger = GetDebugger();
9200b57cec5SDimitry Andric     PlatformSP platform_sp = m_interpreter.GetPlatform(true);
9215ffd83dbSDimitry Andric     ProcessSP process_sp =
9225ffd83dbSDimitry Andric         debugger.GetAsyncExecution()
9235ffd83dbSDimitry Andric             ? platform_sp->ConnectProcess(
9240b57cec5SDimitry Andric                   command.GetArgumentAtIndex(0), plugin_name, debugger,
9255ffd83dbSDimitry Andric                   debugger.GetSelectedTarget().get(), error)
9265ffd83dbSDimitry Andric             : platform_sp->ConnectProcessSynchronous(
9275ffd83dbSDimitry Andric                   command.GetArgumentAtIndex(0), plugin_name, debugger,
9285ffd83dbSDimitry Andric                   result.GetOutputStream(), debugger.GetSelectedTarget().get(),
9295ffd83dbSDimitry Andric                   error);
9300b57cec5SDimitry Andric     if (error.Fail() || process_sp == nullptr) {
9310b57cec5SDimitry Andric       result.AppendError(error.AsCString("Error connecting to the process"));
9320b57cec5SDimitry Andric       return false;
9330b57cec5SDimitry Andric     }
9340b57cec5SDimitry Andric     return true;
9350b57cec5SDimitry Andric   }
9360b57cec5SDimitry Andric 
9370b57cec5SDimitry Andric   CommandOptions m_options;
9380b57cec5SDimitry Andric };
9390b57cec5SDimitry Andric 
9400b57cec5SDimitry Andric // CommandObjectProcessPlugin
9410b57cec5SDimitry Andric #pragma mark CommandObjectProcessPlugin
9420b57cec5SDimitry Andric 
9430b57cec5SDimitry Andric class CommandObjectProcessPlugin : public CommandObjectProxy {
9440b57cec5SDimitry Andric public:
9450b57cec5SDimitry Andric   CommandObjectProcessPlugin(CommandInterpreter &interpreter)
9460b57cec5SDimitry Andric       : CommandObjectProxy(
9470b57cec5SDimitry Andric             interpreter, "process plugin",
9480b57cec5SDimitry Andric             "Send a custom command to the current target process plug-in.",
9490b57cec5SDimitry Andric             "process plugin <args>", 0) {}
9500b57cec5SDimitry Andric 
9510b57cec5SDimitry Andric   ~CommandObjectProcessPlugin() override = default;
9520b57cec5SDimitry Andric 
9530b57cec5SDimitry Andric   CommandObject *GetProxyCommandObject() override {
9540b57cec5SDimitry Andric     Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
9550b57cec5SDimitry Andric     if (process)
9560b57cec5SDimitry Andric       return process->GetPluginCommandObject();
9570b57cec5SDimitry Andric     return nullptr;
9580b57cec5SDimitry Andric   }
9590b57cec5SDimitry Andric };
9600b57cec5SDimitry Andric 
9610b57cec5SDimitry Andric // CommandObjectProcessLoad
9629dba64beSDimitry Andric #define LLDB_OPTIONS_process_load
9639dba64beSDimitry Andric #include "CommandOptions.inc"
9640b57cec5SDimitry Andric 
9650b57cec5SDimitry Andric #pragma mark CommandObjectProcessLoad
9660b57cec5SDimitry Andric 
9670b57cec5SDimitry Andric class CommandObjectProcessLoad : public CommandObjectParsed {
9680b57cec5SDimitry Andric public:
9690b57cec5SDimitry Andric   class CommandOptions : public Options {
9700b57cec5SDimitry Andric   public:
97104eeddc0SDimitry Andric     CommandOptions() {
9720b57cec5SDimitry Andric       // Keep default values of all options in one place: OptionParsingStarting
9730b57cec5SDimitry Andric       // ()
9740b57cec5SDimitry Andric       OptionParsingStarting(nullptr);
9750b57cec5SDimitry Andric     }
9760b57cec5SDimitry Andric 
9770b57cec5SDimitry Andric     ~CommandOptions() override = default;
9780b57cec5SDimitry Andric 
9790b57cec5SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
9800b57cec5SDimitry Andric                           ExecutionContext *execution_context) override {
9810b57cec5SDimitry Andric       Status error;
9820b57cec5SDimitry Andric       const int short_option = m_getopt_table[option_idx].val;
9830b57cec5SDimitry Andric       switch (short_option) {
9840b57cec5SDimitry Andric       case 'i':
9850b57cec5SDimitry Andric         do_install = true;
9860b57cec5SDimitry Andric         if (!option_arg.empty())
9870b57cec5SDimitry Andric           install_path.SetFile(option_arg, FileSpec::Style::native);
9880b57cec5SDimitry Andric         break;
9890b57cec5SDimitry Andric       default:
9909dba64beSDimitry Andric         llvm_unreachable("Unimplemented option");
9910b57cec5SDimitry Andric       }
9920b57cec5SDimitry Andric       return error;
9930b57cec5SDimitry Andric     }
9940b57cec5SDimitry Andric 
9950b57cec5SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
9960b57cec5SDimitry Andric       do_install = false;
9970b57cec5SDimitry Andric       install_path.Clear();
9980b57cec5SDimitry Andric     }
9990b57cec5SDimitry Andric 
10000b57cec5SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1001bdd1243dSDimitry Andric       return llvm::ArrayRef(g_process_load_options);
10020b57cec5SDimitry Andric     }
10030b57cec5SDimitry Andric 
10040b57cec5SDimitry Andric     // Instance variables to hold the values for command options.
10050b57cec5SDimitry Andric     bool do_install;
10060b57cec5SDimitry Andric     FileSpec install_path;
10070b57cec5SDimitry Andric   };
10080b57cec5SDimitry Andric 
10090b57cec5SDimitry Andric   CommandObjectProcessLoad(CommandInterpreter &interpreter)
10100b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "process load",
10110b57cec5SDimitry Andric                             "Load a shared library into the current process.",
10120b57cec5SDimitry Andric                             "process load <filename> [<filename> ...]",
10130b57cec5SDimitry Andric                             eCommandRequiresProcess | eCommandTryTargetAPILock |
10140b57cec5SDimitry Andric                                 eCommandProcessMustBeLaunched |
101581ad6265SDimitry Andric                                 eCommandProcessMustBePaused) {
101681ad6265SDimitry Andric     CommandArgumentData file_arg{eArgTypePath, eArgRepeatPlus};
101781ad6265SDimitry Andric     m_arguments.push_back({file_arg});
101881ad6265SDimitry Andric   }
10190b57cec5SDimitry Andric 
10200b57cec5SDimitry Andric   ~CommandObjectProcessLoad() override = default;
10210b57cec5SDimitry Andric 
1022e8d8bef9SDimitry Andric   void
1023e8d8bef9SDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
1024e8d8bef9SDimitry Andric                            OptionElementVector &opt_element_vector) override {
1025e8d8bef9SDimitry Andric     if (!m_exe_ctx.HasProcessScope())
1026e8d8bef9SDimitry Andric       return;
1027e8d8bef9SDimitry Andric 
1028*fe013be4SDimitry Andric     lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1029*fe013be4SDimitry Andric         GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr);
1030e8d8bef9SDimitry Andric   }
1031e8d8bef9SDimitry Andric 
10320b57cec5SDimitry Andric   Options *GetOptions() override { return &m_options; }
10330b57cec5SDimitry Andric 
10340b57cec5SDimitry Andric protected:
10350b57cec5SDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
10360b57cec5SDimitry Andric     Process *process = m_exe_ctx.GetProcessPtr();
10370b57cec5SDimitry Andric 
10380b57cec5SDimitry Andric     for (auto &entry : command.entries()) {
10390b57cec5SDimitry Andric       Status error;
10400b57cec5SDimitry Andric       PlatformSP platform = process->GetTarget().GetPlatform();
10419dba64beSDimitry Andric       llvm::StringRef image_path = entry.ref();
10420b57cec5SDimitry Andric       uint32_t image_token = LLDB_INVALID_IMAGE_TOKEN;
10430b57cec5SDimitry Andric 
10440b57cec5SDimitry Andric       if (!m_options.do_install) {
10450b57cec5SDimitry Andric         FileSpec image_spec(image_path);
10460b57cec5SDimitry Andric         platform->ResolveRemotePath(image_spec, image_spec);
10470b57cec5SDimitry Andric         image_token =
10480b57cec5SDimitry Andric             platform->LoadImage(process, FileSpec(), image_spec, error);
10490b57cec5SDimitry Andric       } else if (m_options.install_path) {
10500b57cec5SDimitry Andric         FileSpec image_spec(image_path);
10510b57cec5SDimitry Andric         FileSystem::Instance().Resolve(image_spec);
10520b57cec5SDimitry Andric         platform->ResolveRemotePath(m_options.install_path,
10530b57cec5SDimitry Andric                                     m_options.install_path);
10540b57cec5SDimitry Andric         image_token = platform->LoadImage(process, image_spec,
10550b57cec5SDimitry Andric                                           m_options.install_path, error);
10560b57cec5SDimitry Andric       } else {
10570b57cec5SDimitry Andric         FileSpec image_spec(image_path);
10580b57cec5SDimitry Andric         FileSystem::Instance().Resolve(image_spec);
10590b57cec5SDimitry Andric         image_token =
10600b57cec5SDimitry Andric             platform->LoadImage(process, image_spec, FileSpec(), error);
10610b57cec5SDimitry Andric       }
10620b57cec5SDimitry Andric 
10630b57cec5SDimitry Andric       if (image_token != LLDB_INVALID_IMAGE_TOKEN) {
10640b57cec5SDimitry Andric         result.AppendMessageWithFormat(
10650b57cec5SDimitry Andric             "Loading \"%s\"...ok\nImage %u loaded.\n", image_path.str().c_str(),
10660b57cec5SDimitry Andric             image_token);
10670b57cec5SDimitry Andric         result.SetStatus(eReturnStatusSuccessFinishResult);
10680b57cec5SDimitry Andric       } else {
10690b57cec5SDimitry Andric         result.AppendErrorWithFormat("failed to load '%s': %s",
10700b57cec5SDimitry Andric                                      image_path.str().c_str(),
10710b57cec5SDimitry Andric                                      error.AsCString());
10720b57cec5SDimitry Andric       }
10730b57cec5SDimitry Andric     }
10740b57cec5SDimitry Andric     return result.Succeeded();
10750b57cec5SDimitry Andric   }
10760b57cec5SDimitry Andric 
10770b57cec5SDimitry Andric   CommandOptions m_options;
10780b57cec5SDimitry Andric };
10790b57cec5SDimitry Andric 
10800b57cec5SDimitry Andric // CommandObjectProcessUnload
10810b57cec5SDimitry Andric #pragma mark CommandObjectProcessUnload
10820b57cec5SDimitry Andric 
10830b57cec5SDimitry Andric class CommandObjectProcessUnload : public CommandObjectParsed {
10840b57cec5SDimitry Andric public:
10850b57cec5SDimitry Andric   CommandObjectProcessUnload(CommandInterpreter &interpreter)
10860b57cec5SDimitry Andric       : CommandObjectParsed(
10870b57cec5SDimitry Andric             interpreter, "process unload",
10880b57cec5SDimitry Andric             "Unload a shared library from the current process using the index "
10890b57cec5SDimitry Andric             "returned by a previous call to \"process load\".",
10900b57cec5SDimitry Andric             "process unload <index>",
10910b57cec5SDimitry Andric             eCommandRequiresProcess | eCommandTryTargetAPILock |
109281ad6265SDimitry Andric                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {
109381ad6265SDimitry Andric     CommandArgumentData load_idx_arg{eArgTypeUnsignedInteger, eArgRepeatPlain};
109481ad6265SDimitry Andric     m_arguments.push_back({load_idx_arg});
109581ad6265SDimitry Andric   }
10960b57cec5SDimitry Andric 
10970b57cec5SDimitry Andric   ~CommandObjectProcessUnload() override = default;
10980b57cec5SDimitry Andric 
1099e8d8bef9SDimitry Andric   void
1100e8d8bef9SDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
1101e8d8bef9SDimitry Andric                            OptionElementVector &opt_element_vector) override {
1102e8d8bef9SDimitry Andric 
1103e8d8bef9SDimitry Andric     if (request.GetCursorIndex() || !m_exe_ctx.HasProcessScope())
1104e8d8bef9SDimitry Andric       return;
1105e8d8bef9SDimitry Andric 
1106e8d8bef9SDimitry Andric     Process *process = m_exe_ctx.GetProcessPtr();
1107e8d8bef9SDimitry Andric 
1108e8d8bef9SDimitry Andric     const std::vector<lldb::addr_t> &tokens = process->GetImageTokens();
1109e8d8bef9SDimitry Andric     const size_t token_num = tokens.size();
1110e8d8bef9SDimitry Andric     for (size_t i = 0; i < token_num; ++i) {
1111e8d8bef9SDimitry Andric       if (tokens[i] == LLDB_INVALID_IMAGE_TOKEN)
1112e8d8bef9SDimitry Andric         continue;
1113e8d8bef9SDimitry Andric       request.TryCompleteCurrentArg(std::to_string(i));
1114e8d8bef9SDimitry Andric     }
1115e8d8bef9SDimitry Andric   }
1116e8d8bef9SDimitry Andric 
11170b57cec5SDimitry Andric protected:
11180b57cec5SDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
11190b57cec5SDimitry Andric     Process *process = m_exe_ctx.GetProcessPtr();
11200b57cec5SDimitry Andric 
11210b57cec5SDimitry Andric     for (auto &entry : command.entries()) {
11220b57cec5SDimitry Andric       uint32_t image_token;
11239dba64beSDimitry Andric       if (entry.ref().getAsInteger(0, image_token)) {
11240b57cec5SDimitry Andric         result.AppendErrorWithFormat("invalid image index argument '%s'",
11259dba64beSDimitry Andric                                      entry.ref().str().c_str());
11260b57cec5SDimitry Andric         break;
11270b57cec5SDimitry Andric       } else {
11280b57cec5SDimitry Andric         Status error(process->GetTarget().GetPlatform()->UnloadImage(
11290b57cec5SDimitry Andric             process, image_token));
11300b57cec5SDimitry Andric         if (error.Success()) {
11310b57cec5SDimitry Andric           result.AppendMessageWithFormat(
11320b57cec5SDimitry Andric               "Unloading shared library with index %u...ok\n", image_token);
11330b57cec5SDimitry Andric           result.SetStatus(eReturnStatusSuccessFinishResult);
11340b57cec5SDimitry Andric         } else {
11350b57cec5SDimitry Andric           result.AppendErrorWithFormat("failed to unload image: %s",
11360b57cec5SDimitry Andric                                        error.AsCString());
11370b57cec5SDimitry Andric           break;
11380b57cec5SDimitry Andric         }
11390b57cec5SDimitry Andric       }
11400b57cec5SDimitry Andric     }
11410b57cec5SDimitry Andric     return result.Succeeded();
11420b57cec5SDimitry Andric   }
11430b57cec5SDimitry Andric };
11440b57cec5SDimitry Andric 
11450b57cec5SDimitry Andric // CommandObjectProcessSignal
11460b57cec5SDimitry Andric #pragma mark CommandObjectProcessSignal
11470b57cec5SDimitry Andric 
11480b57cec5SDimitry Andric class CommandObjectProcessSignal : public CommandObjectParsed {
11490b57cec5SDimitry Andric public:
11500b57cec5SDimitry Andric   CommandObjectProcessSignal(CommandInterpreter &interpreter)
1151480093f4SDimitry Andric       : CommandObjectParsed(
1152480093f4SDimitry Andric             interpreter, "process signal",
1153480093f4SDimitry Andric             "Send a UNIX signal to the current target process.", nullptr,
1154480093f4SDimitry Andric             eCommandRequiresProcess | eCommandTryTargetAPILock) {
11550b57cec5SDimitry Andric     CommandArgumentEntry arg;
11560b57cec5SDimitry Andric     CommandArgumentData signal_arg;
11570b57cec5SDimitry Andric 
11580b57cec5SDimitry Andric     // Define the first (and only) variant of this arg.
11590b57cec5SDimitry Andric     signal_arg.arg_type = eArgTypeUnixSignal;
11600b57cec5SDimitry Andric     signal_arg.arg_repetition = eArgRepeatPlain;
11610b57cec5SDimitry Andric 
11620b57cec5SDimitry Andric     // There is only one variant this argument could be; put it into the
11630b57cec5SDimitry Andric     // argument entry.
11640b57cec5SDimitry Andric     arg.push_back(signal_arg);
11650b57cec5SDimitry Andric 
11660b57cec5SDimitry Andric     // Push the data for the first argument into the m_arguments vector.
11670b57cec5SDimitry Andric     m_arguments.push_back(arg);
11680b57cec5SDimitry Andric   }
11690b57cec5SDimitry Andric 
11700b57cec5SDimitry Andric   ~CommandObjectProcessSignal() override = default;
11710b57cec5SDimitry Andric 
11725ffd83dbSDimitry Andric   void
11735ffd83dbSDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
11745ffd83dbSDimitry Andric                            OptionElementVector &opt_element_vector) override {
11755ffd83dbSDimitry Andric     if (!m_exe_ctx.HasProcessScope() || request.GetCursorIndex() != 0)
11765ffd83dbSDimitry Andric       return;
11775ffd83dbSDimitry Andric 
11785ffd83dbSDimitry Andric     UnixSignalsSP signals = m_exe_ctx.GetProcessPtr()->GetUnixSignals();
11795ffd83dbSDimitry Andric     int signo = signals->GetFirstSignalNumber();
11805ffd83dbSDimitry Andric     while (signo != LLDB_INVALID_SIGNAL_NUMBER) {
1181fe6060f1SDimitry Andric       request.TryCompleteCurrentArg(signals->GetSignalAsCString(signo));
11825ffd83dbSDimitry Andric       signo = signals->GetNextSignalNumber(signo);
11835ffd83dbSDimitry Andric     }
11845ffd83dbSDimitry Andric   }
11855ffd83dbSDimitry Andric 
11860b57cec5SDimitry Andric protected:
11870b57cec5SDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
11880b57cec5SDimitry Andric     Process *process = m_exe_ctx.GetProcessPtr();
11890b57cec5SDimitry Andric 
11900b57cec5SDimitry Andric     if (command.GetArgumentCount() == 1) {
11910b57cec5SDimitry Andric       int signo = LLDB_INVALID_SIGNAL_NUMBER;
11920b57cec5SDimitry Andric 
11930b57cec5SDimitry Andric       const char *signal_name = command.GetArgumentAtIndex(0);
11945ffd83dbSDimitry Andric       if (::isxdigit(signal_name[0])) {
11955ffd83dbSDimitry Andric         if (!llvm::to_integer(signal_name, signo))
11965ffd83dbSDimitry Andric           signo = LLDB_INVALID_SIGNAL_NUMBER;
11975ffd83dbSDimitry Andric       } else
11980b57cec5SDimitry Andric         signo = process->GetUnixSignals()->GetSignalNumberFromName(signal_name);
11990b57cec5SDimitry Andric 
12000b57cec5SDimitry Andric       if (signo == LLDB_INVALID_SIGNAL_NUMBER) {
12010b57cec5SDimitry Andric         result.AppendErrorWithFormat("Invalid signal argument '%s'.\n",
12020b57cec5SDimitry Andric                                      command.GetArgumentAtIndex(0));
12030b57cec5SDimitry Andric       } else {
12040b57cec5SDimitry Andric         Status error(process->Signal(signo));
12050b57cec5SDimitry Andric         if (error.Success()) {
12060b57cec5SDimitry Andric           result.SetStatus(eReturnStatusSuccessFinishResult);
12070b57cec5SDimitry Andric         } else {
12080b57cec5SDimitry Andric           result.AppendErrorWithFormat("Failed to send signal %i: %s\n", signo,
12090b57cec5SDimitry Andric                                        error.AsCString());
12100b57cec5SDimitry Andric         }
12110b57cec5SDimitry Andric       }
12120b57cec5SDimitry Andric     } else {
12130b57cec5SDimitry Andric       result.AppendErrorWithFormat(
12140b57cec5SDimitry Andric           "'%s' takes exactly one signal number argument:\nUsage: %s\n",
12150b57cec5SDimitry Andric           m_cmd_name.c_str(), m_cmd_syntax.c_str());
12160b57cec5SDimitry Andric     }
12170b57cec5SDimitry Andric     return result.Succeeded();
12180b57cec5SDimitry Andric   }
12190b57cec5SDimitry Andric };
12200b57cec5SDimitry Andric 
12210b57cec5SDimitry Andric // CommandObjectProcessInterrupt
12220b57cec5SDimitry Andric #pragma mark CommandObjectProcessInterrupt
12230b57cec5SDimitry Andric 
12240b57cec5SDimitry Andric class CommandObjectProcessInterrupt : public CommandObjectParsed {
12250b57cec5SDimitry Andric public:
12260b57cec5SDimitry Andric   CommandObjectProcessInterrupt(CommandInterpreter &interpreter)
12270b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "process interrupt",
12280b57cec5SDimitry Andric                             "Interrupt the current target process.",
12290b57cec5SDimitry Andric                             "process interrupt",
12300b57cec5SDimitry Andric                             eCommandRequiresProcess | eCommandTryTargetAPILock |
12310b57cec5SDimitry Andric                                 eCommandProcessMustBeLaunched) {}
12320b57cec5SDimitry Andric 
12330b57cec5SDimitry Andric   ~CommandObjectProcessInterrupt() override = default;
12340b57cec5SDimitry Andric 
12350b57cec5SDimitry Andric protected:
12360b57cec5SDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
12370b57cec5SDimitry Andric     Process *process = m_exe_ctx.GetProcessPtr();
12380b57cec5SDimitry Andric     if (process == nullptr) {
12390b57cec5SDimitry Andric       result.AppendError("no process to halt");
12400b57cec5SDimitry Andric       return false;
12410b57cec5SDimitry Andric     }
12420b57cec5SDimitry Andric 
12430b57cec5SDimitry Andric     bool clear_thread_plans = true;
12440b57cec5SDimitry Andric     Status error(process->Halt(clear_thread_plans));
12450b57cec5SDimitry Andric     if (error.Success()) {
12460b57cec5SDimitry Andric       result.SetStatus(eReturnStatusSuccessFinishResult);
12470b57cec5SDimitry Andric     } else {
12480b57cec5SDimitry Andric       result.AppendErrorWithFormat("Failed to halt process: %s\n",
12490b57cec5SDimitry Andric                                    error.AsCString());
12500b57cec5SDimitry Andric     }
12510b57cec5SDimitry Andric     return result.Succeeded();
12520b57cec5SDimitry Andric   }
12530b57cec5SDimitry Andric };
12540b57cec5SDimitry Andric 
12550b57cec5SDimitry Andric // CommandObjectProcessKill
12560b57cec5SDimitry Andric #pragma mark CommandObjectProcessKill
12570b57cec5SDimitry Andric 
12580b57cec5SDimitry Andric class CommandObjectProcessKill : public CommandObjectParsed {
12590b57cec5SDimitry Andric public:
12600b57cec5SDimitry Andric   CommandObjectProcessKill(CommandInterpreter &interpreter)
12610b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "process kill",
12620b57cec5SDimitry Andric                             "Terminate the current target process.",
12630b57cec5SDimitry Andric                             "process kill",
12640b57cec5SDimitry Andric                             eCommandRequiresProcess | eCommandTryTargetAPILock |
12650b57cec5SDimitry Andric                                 eCommandProcessMustBeLaunched) {}
12660b57cec5SDimitry Andric 
12670b57cec5SDimitry Andric   ~CommandObjectProcessKill() override = default;
12680b57cec5SDimitry Andric 
12690b57cec5SDimitry Andric protected:
12700b57cec5SDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
12710b57cec5SDimitry Andric     Process *process = m_exe_ctx.GetProcessPtr();
12720b57cec5SDimitry Andric     if (process == nullptr) {
12730b57cec5SDimitry Andric       result.AppendError("no process to kill");
12740b57cec5SDimitry Andric       return false;
12750b57cec5SDimitry Andric     }
12760b57cec5SDimitry Andric 
12770b57cec5SDimitry Andric     Status error(process->Destroy(true));
12780b57cec5SDimitry Andric     if (error.Success()) {
12790b57cec5SDimitry Andric       result.SetStatus(eReturnStatusSuccessFinishResult);
12800b57cec5SDimitry Andric     } else {
12810b57cec5SDimitry Andric       result.AppendErrorWithFormat("Failed to kill process: %s\n",
12820b57cec5SDimitry Andric                                    error.AsCString());
12830b57cec5SDimitry Andric     }
12840b57cec5SDimitry Andric     return result.Succeeded();
12850b57cec5SDimitry Andric   }
12860b57cec5SDimitry Andric };
12870b57cec5SDimitry Andric 
1288fe6060f1SDimitry Andric #define LLDB_OPTIONS_process_save_core
1289fe6060f1SDimitry Andric #include "CommandOptions.inc"
1290fe6060f1SDimitry Andric 
12910b57cec5SDimitry Andric class CommandObjectProcessSaveCore : public CommandObjectParsed {
12920b57cec5SDimitry Andric public:
12930b57cec5SDimitry Andric   CommandObjectProcessSaveCore(CommandInterpreter &interpreter)
1294349cc55cSDimitry Andric       : CommandObjectParsed(
1295349cc55cSDimitry Andric             interpreter, "process save-core",
12960b57cec5SDimitry Andric             "Save the current process as a core file using an "
12970b57cec5SDimitry Andric             "appropriate file type.",
1298349cc55cSDimitry Andric             "process save-core [-s corefile-style -p plugin-name] FILE",
12990b57cec5SDimitry Andric             eCommandRequiresProcess | eCommandTryTargetAPILock |
130081ad6265SDimitry Andric                 eCommandProcessMustBeLaunched) {
130181ad6265SDimitry Andric     CommandArgumentData file_arg{eArgTypePath, eArgRepeatPlain};
130281ad6265SDimitry Andric     m_arguments.push_back({file_arg});
130381ad6265SDimitry Andric   }
13040b57cec5SDimitry Andric 
13050b57cec5SDimitry Andric   ~CommandObjectProcessSaveCore() override = default;
13060b57cec5SDimitry Andric 
1307fe6060f1SDimitry Andric   Options *GetOptions() override { return &m_options; }
1308fe6060f1SDimitry Andric 
1309*fe013be4SDimitry Andric   void
1310*fe013be4SDimitry Andric   HandleArgumentCompletion(CompletionRequest &request,
1311*fe013be4SDimitry Andric                            OptionElementVector &opt_element_vector) override {
1312*fe013be4SDimitry Andric     CommandCompletions::InvokeCommonCompletionCallbacks(
1313*fe013be4SDimitry Andric         GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr);
1314*fe013be4SDimitry Andric   }
1315*fe013be4SDimitry Andric 
1316fe6060f1SDimitry Andric   class CommandOptions : public Options {
1317fe6060f1SDimitry Andric   public:
131881ad6265SDimitry Andric     CommandOptions() = default;
1319fe6060f1SDimitry Andric 
1320fe6060f1SDimitry Andric     ~CommandOptions() override = default;
1321fe6060f1SDimitry Andric 
1322fe6060f1SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1323bdd1243dSDimitry Andric       return llvm::ArrayRef(g_process_save_core_options);
1324fe6060f1SDimitry Andric     }
1325fe6060f1SDimitry Andric 
1326fe6060f1SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1327fe6060f1SDimitry Andric                           ExecutionContext *execution_context) override {
1328fe6060f1SDimitry Andric       const int short_option = m_getopt_table[option_idx].val;
1329fe6060f1SDimitry Andric       Status error;
1330fe6060f1SDimitry Andric 
1331fe6060f1SDimitry Andric       switch (short_option) {
1332349cc55cSDimitry Andric       case 'p':
1333349cc55cSDimitry Andric         m_requested_plugin_name = option_arg.str();
1334349cc55cSDimitry Andric         break;
1335fe6060f1SDimitry Andric       case 's':
1336fe6060f1SDimitry Andric         m_requested_save_core_style =
1337fe6060f1SDimitry Andric             (lldb::SaveCoreStyle)OptionArgParser::ToOptionEnum(
1338fe6060f1SDimitry Andric                 option_arg, GetDefinitions()[option_idx].enum_values,
1339fe6060f1SDimitry Andric                 eSaveCoreUnspecified, error);
1340fe6060f1SDimitry Andric         break;
1341fe6060f1SDimitry Andric       default:
1342fe6060f1SDimitry Andric         llvm_unreachable("Unimplemented option");
1343fe6060f1SDimitry Andric       }
1344fe6060f1SDimitry Andric 
1345fe6060f1SDimitry Andric       return {};
1346fe6060f1SDimitry Andric     }
1347fe6060f1SDimitry Andric 
1348fe6060f1SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
1349fe6060f1SDimitry Andric       m_requested_save_core_style = eSaveCoreUnspecified;
1350349cc55cSDimitry Andric       m_requested_plugin_name.clear();
1351fe6060f1SDimitry Andric     }
1352fe6060f1SDimitry Andric 
1353fe6060f1SDimitry Andric     // Instance variables to hold the values for command options.
135481ad6265SDimitry Andric     SaveCoreStyle m_requested_save_core_style = eSaveCoreUnspecified;
1355349cc55cSDimitry Andric     std::string m_requested_plugin_name;
1356fe6060f1SDimitry Andric   };
1357fe6060f1SDimitry Andric 
13580b57cec5SDimitry Andric protected:
13590b57cec5SDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
13600b57cec5SDimitry Andric     ProcessSP process_sp = m_exe_ctx.GetProcessSP();
13610b57cec5SDimitry Andric     if (process_sp) {
13620b57cec5SDimitry Andric       if (command.GetArgumentCount() == 1) {
13630b57cec5SDimitry Andric         FileSpec output_file(command.GetArgumentAtIndex(0));
1364*fe013be4SDimitry Andric         FileSystem::Instance().Resolve(output_file);
1365fe6060f1SDimitry Andric         SaveCoreStyle corefile_style = m_options.m_requested_save_core_style;
1366fe6060f1SDimitry Andric         Status error =
1367349cc55cSDimitry Andric             PluginManager::SaveCore(process_sp, output_file, corefile_style,
1368349cc55cSDimitry Andric                                     m_options.m_requested_plugin_name);
13690b57cec5SDimitry Andric         if (error.Success()) {
1370349cc55cSDimitry Andric           if (corefile_style == SaveCoreStyle::eSaveCoreDirtyOnly ||
1371349cc55cSDimitry Andric               corefile_style == SaveCoreStyle::eSaveCoreStackOnly) {
1372fe6060f1SDimitry Andric             result.AppendMessageWithFormat(
1373349cc55cSDimitry Andric                 "\nModified-memory or stack-memory only corefile "
1374349cc55cSDimitry Andric                 "created.  This corefile may \n"
1375349cc55cSDimitry Andric                 "not show library/framework/app binaries "
1376fe6060f1SDimitry Andric                 "on a different system, or when \n"
1377fe6060f1SDimitry Andric                 "those binaries have "
1378fe6060f1SDimitry Andric                 "been updated/modified. Copies are not included\n"
1379fe6060f1SDimitry Andric                 "in this corefile.  Use --style full to include all "
1380fe6060f1SDimitry Andric                 "process memory.\n");
1381fe6060f1SDimitry Andric           }
13820b57cec5SDimitry Andric           result.SetStatus(eReturnStatusSuccessFinishResult);
13830b57cec5SDimitry Andric         } else {
13840b57cec5SDimitry Andric           result.AppendErrorWithFormat(
13850b57cec5SDimitry Andric               "Failed to save core file for process: %s\n", error.AsCString());
13860b57cec5SDimitry Andric         }
13870b57cec5SDimitry Andric       } else {
13880b57cec5SDimitry Andric         result.AppendErrorWithFormat("'%s' takes one arguments:\nUsage: %s\n",
13890b57cec5SDimitry Andric                                      m_cmd_name.c_str(), m_cmd_syntax.c_str());
13900b57cec5SDimitry Andric       }
13910b57cec5SDimitry Andric     } else {
13920b57cec5SDimitry Andric       result.AppendError("invalid process");
13930b57cec5SDimitry Andric       return false;
13940b57cec5SDimitry Andric     }
13950b57cec5SDimitry Andric 
13960b57cec5SDimitry Andric     return result.Succeeded();
13970b57cec5SDimitry Andric   }
1398fe6060f1SDimitry Andric 
1399fe6060f1SDimitry Andric   CommandOptions m_options;
14000b57cec5SDimitry Andric };
14010b57cec5SDimitry Andric 
14020b57cec5SDimitry Andric // CommandObjectProcessStatus
14030b57cec5SDimitry Andric #pragma mark CommandObjectProcessStatus
14045ffd83dbSDimitry Andric #define LLDB_OPTIONS_process_status
14055ffd83dbSDimitry Andric #include "CommandOptions.inc"
14060b57cec5SDimitry Andric 
14070b57cec5SDimitry Andric class CommandObjectProcessStatus : public CommandObjectParsed {
14080b57cec5SDimitry Andric public:
14090b57cec5SDimitry Andric   CommandObjectProcessStatus(CommandInterpreter &interpreter)
14100b57cec5SDimitry Andric       : CommandObjectParsed(
14110b57cec5SDimitry Andric             interpreter, "process status",
14120b57cec5SDimitry Andric             "Show status and stop location for the current target process.",
14130b57cec5SDimitry Andric             "process status",
141404eeddc0SDimitry Andric             eCommandRequiresProcess | eCommandTryTargetAPILock) {}
14150b57cec5SDimitry Andric 
14160b57cec5SDimitry Andric   ~CommandObjectProcessStatus() override = default;
14170b57cec5SDimitry Andric 
14185ffd83dbSDimitry Andric   Options *GetOptions() override { return &m_options; }
14195ffd83dbSDimitry Andric 
14205ffd83dbSDimitry Andric   class CommandOptions : public Options {
14215ffd83dbSDimitry Andric   public:
142281ad6265SDimitry Andric     CommandOptions() = default;
14235ffd83dbSDimitry Andric 
14245ffd83dbSDimitry Andric     ~CommandOptions() override = default;
14255ffd83dbSDimitry Andric 
14265ffd83dbSDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
14275ffd83dbSDimitry Andric                           ExecutionContext *execution_context) override {
14285ffd83dbSDimitry Andric       const int short_option = m_getopt_table[option_idx].val;
14295ffd83dbSDimitry Andric 
14305ffd83dbSDimitry Andric       switch (short_option) {
14315ffd83dbSDimitry Andric       case 'v':
14325ffd83dbSDimitry Andric         m_verbose = true;
14335ffd83dbSDimitry Andric         break;
14345ffd83dbSDimitry Andric       default:
14355ffd83dbSDimitry Andric         llvm_unreachable("Unimplemented option");
14365ffd83dbSDimitry Andric       }
14375ffd83dbSDimitry Andric 
14385ffd83dbSDimitry Andric       return {};
14395ffd83dbSDimitry Andric     }
14405ffd83dbSDimitry Andric 
14415ffd83dbSDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
14425ffd83dbSDimitry Andric       m_verbose = false;
14435ffd83dbSDimitry Andric     }
14445ffd83dbSDimitry Andric 
14455ffd83dbSDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1446bdd1243dSDimitry Andric       return llvm::ArrayRef(g_process_status_options);
14475ffd83dbSDimitry Andric     }
14485ffd83dbSDimitry Andric 
14495ffd83dbSDimitry Andric     // Instance variables to hold the values for command options.
1450fe6060f1SDimitry Andric     bool m_verbose = false;
14515ffd83dbSDimitry Andric   };
14525ffd83dbSDimitry Andric 
14535ffd83dbSDimitry Andric protected:
14540b57cec5SDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
14550b57cec5SDimitry Andric     Stream &strm = result.GetOutputStream();
14560b57cec5SDimitry Andric     result.SetStatus(eReturnStatusSuccessFinishNoResult);
14575ffd83dbSDimitry Andric 
14580b57cec5SDimitry Andric     // No need to check "process" for validity as eCommandRequiresProcess
14590b57cec5SDimitry Andric     // ensures it is valid
14600b57cec5SDimitry Andric     Process *process = m_exe_ctx.GetProcessPtr();
14610b57cec5SDimitry Andric     const bool only_threads_with_stop_reason = true;
14620b57cec5SDimitry Andric     const uint32_t start_frame = 0;
14630b57cec5SDimitry Andric     const uint32_t num_frames = 1;
14640b57cec5SDimitry Andric     const uint32_t num_frames_with_source = 1;
14650b57cec5SDimitry Andric     const bool stop_format = true;
14660b57cec5SDimitry Andric     process->GetStatus(strm);
14670b57cec5SDimitry Andric     process->GetThreadStatus(strm, only_threads_with_stop_reason, start_frame,
14680b57cec5SDimitry Andric                              num_frames, num_frames_with_source, stop_format);
14695ffd83dbSDimitry Andric 
14705ffd83dbSDimitry Andric     if (m_options.m_verbose) {
1471fe6060f1SDimitry Andric       addr_t code_mask = process->GetCodeAddressMask();
1472fe6060f1SDimitry Andric       addr_t data_mask = process->GetDataAddressMask();
1473fe6060f1SDimitry Andric       if (code_mask != 0) {
1474fe6060f1SDimitry Andric         int bits = std::bitset<64>(~code_mask).count();
1475fe6060f1SDimitry Andric         result.AppendMessageWithFormat(
1476fe6060f1SDimitry Andric             "Addressable code address mask: 0x%" PRIx64 "\n", code_mask);
1477fe6060f1SDimitry Andric         result.AppendMessageWithFormat(
1478fe6060f1SDimitry Andric             "Addressable data address mask: 0x%" PRIx64 "\n", data_mask);
1479fe6060f1SDimitry Andric         result.AppendMessageWithFormat(
1480fe6060f1SDimitry Andric             "Number of bits used in addressing (code): %d\n", bits);
1481fe6060f1SDimitry Andric       }
1482fe6060f1SDimitry Andric 
14835ffd83dbSDimitry Andric       PlatformSP platform_sp = process->GetTarget().GetPlatform();
14845ffd83dbSDimitry Andric       if (!platform_sp) {
14855ffd83dbSDimitry Andric         result.AppendError("Couldn'retrieve the target's platform");
14860b57cec5SDimitry Andric         return result.Succeeded();
14870b57cec5SDimitry Andric       }
14885ffd83dbSDimitry Andric 
14895ffd83dbSDimitry Andric       auto expected_crash_info =
14905ffd83dbSDimitry Andric           platform_sp->FetchExtendedCrashInformation(*process);
14915ffd83dbSDimitry Andric 
14925ffd83dbSDimitry Andric       if (!expected_crash_info) {
14935ffd83dbSDimitry Andric         result.AppendError(llvm::toString(expected_crash_info.takeError()));
14945ffd83dbSDimitry Andric         return result.Succeeded();
14955ffd83dbSDimitry Andric       }
14965ffd83dbSDimitry Andric 
14975ffd83dbSDimitry Andric       StructuredData::DictionarySP crash_info_sp = *expected_crash_info;
14985ffd83dbSDimitry Andric 
14995ffd83dbSDimitry Andric       if (crash_info_sp) {
1500bdd1243dSDimitry Andric         strm.EOL();
15015ffd83dbSDimitry Andric         strm.PutCString("Extended Crash Information:\n");
1502bdd1243dSDimitry Andric         crash_info_sp->GetDescription(strm);
15035ffd83dbSDimitry Andric       }
15045ffd83dbSDimitry Andric     }
15055ffd83dbSDimitry Andric 
15065ffd83dbSDimitry Andric     return result.Succeeded();
15075ffd83dbSDimitry Andric   }
15085ffd83dbSDimitry Andric 
15095ffd83dbSDimitry Andric private:
15105ffd83dbSDimitry Andric   CommandOptions m_options;
15110b57cec5SDimitry Andric };
15120b57cec5SDimitry Andric 
15130b57cec5SDimitry Andric // CommandObjectProcessHandle
15149dba64beSDimitry Andric #define LLDB_OPTIONS_process_handle
15159dba64beSDimitry Andric #include "CommandOptions.inc"
15160b57cec5SDimitry Andric 
15170b57cec5SDimitry Andric #pragma mark CommandObjectProcessHandle
15180b57cec5SDimitry Andric 
15190b57cec5SDimitry Andric class CommandObjectProcessHandle : public CommandObjectParsed {
15200b57cec5SDimitry Andric public:
15210b57cec5SDimitry Andric   class CommandOptions : public Options {
15220b57cec5SDimitry Andric   public:
152304eeddc0SDimitry Andric     CommandOptions() { OptionParsingStarting(nullptr); }
15240b57cec5SDimitry Andric 
15250b57cec5SDimitry Andric     ~CommandOptions() override = default;
15260b57cec5SDimitry Andric 
15270b57cec5SDimitry Andric     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
15280b57cec5SDimitry Andric                           ExecutionContext *execution_context) override {
15290b57cec5SDimitry Andric       Status error;
15300b57cec5SDimitry Andric       const int short_option = m_getopt_table[option_idx].val;
15310b57cec5SDimitry Andric 
15320b57cec5SDimitry Andric       switch (short_option) {
153381ad6265SDimitry Andric       case 'c':
153481ad6265SDimitry Andric         do_clear = true;
153581ad6265SDimitry Andric         break;
153681ad6265SDimitry Andric       case 'd':
153781ad6265SDimitry Andric         dummy = true;
153881ad6265SDimitry Andric         break;
15390b57cec5SDimitry Andric       case 's':
15405ffd83dbSDimitry Andric         stop = std::string(option_arg);
15410b57cec5SDimitry Andric         break;
15420b57cec5SDimitry Andric       case 'n':
15435ffd83dbSDimitry Andric         notify = std::string(option_arg);
15440b57cec5SDimitry Andric         break;
15450b57cec5SDimitry Andric       case 'p':
15465ffd83dbSDimitry Andric         pass = std::string(option_arg);
15470b57cec5SDimitry Andric         break;
154881ad6265SDimitry Andric       case 't':
154981ad6265SDimitry Andric         only_target_values = true;
155081ad6265SDimitry Andric         break;
15510b57cec5SDimitry Andric       default:
15529dba64beSDimitry Andric         llvm_unreachable("Unimplemented option");
15530b57cec5SDimitry Andric       }
15540b57cec5SDimitry Andric       return error;
15550b57cec5SDimitry Andric     }
15560b57cec5SDimitry Andric 
15570b57cec5SDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
15580b57cec5SDimitry Andric       stop.clear();
15590b57cec5SDimitry Andric       notify.clear();
15600b57cec5SDimitry Andric       pass.clear();
156181ad6265SDimitry Andric       only_target_values = false;
156281ad6265SDimitry Andric       do_clear = false;
156381ad6265SDimitry Andric       dummy = false;
15640b57cec5SDimitry Andric     }
15650b57cec5SDimitry Andric 
15660b57cec5SDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1567bdd1243dSDimitry Andric       return llvm::ArrayRef(g_process_handle_options);
15680b57cec5SDimitry Andric     }
15690b57cec5SDimitry Andric 
15700b57cec5SDimitry Andric     // Instance variables to hold the values for command options.
15710b57cec5SDimitry Andric 
15720b57cec5SDimitry Andric     std::string stop;
15730b57cec5SDimitry Andric     std::string notify;
15740b57cec5SDimitry Andric     std::string pass;
157581ad6265SDimitry Andric     bool only_target_values = false;
157681ad6265SDimitry Andric     bool do_clear = false;
157781ad6265SDimitry Andric     bool dummy = false;
15780b57cec5SDimitry Andric   };
15790b57cec5SDimitry Andric 
15800b57cec5SDimitry Andric   CommandObjectProcessHandle(CommandInterpreter &interpreter)
15810b57cec5SDimitry Andric       : CommandObjectParsed(interpreter, "process handle",
15820b57cec5SDimitry Andric                             "Manage LLDB handling of OS signals for the "
15830b57cec5SDimitry Andric                             "current target process.  Defaults to showing "
15840b57cec5SDimitry Andric                             "current policy.",
158581ad6265SDimitry Andric                             nullptr) {
158681ad6265SDimitry Andric     SetHelpLong("\nIf no signals are specified but one or more actions are, "
158781ad6265SDimitry Andric                 "and there is a live process, update them all.  If no action "
158881ad6265SDimitry Andric                 "is specified, list the current values.\n"
158981ad6265SDimitry Andric                 "If you specify actions with no target (e.g. in an init file) "
159081ad6265SDimitry Andric                 "or in a target with no process "
159181ad6265SDimitry Andric                 "the values will get copied into subsequent targets, but "
159281ad6265SDimitry Andric                 "lldb won't be able to spell-check the options since it can't "
159381ad6265SDimitry Andric                 "know which signal set will later be in force."
159481ad6265SDimitry Andric                 "\nYou can see the signal modifications held by the target"
159581ad6265SDimitry Andric                 "by passing the -t option."
159681ad6265SDimitry Andric                 "\nYou can also clear the target modification for a signal"
159781ad6265SDimitry Andric                 "by passing the -c option");
15980b57cec5SDimitry Andric     CommandArgumentEntry arg;
15990b57cec5SDimitry Andric     CommandArgumentData signal_arg;
16000b57cec5SDimitry Andric 
16010b57cec5SDimitry Andric     signal_arg.arg_type = eArgTypeUnixSignal;
16020b57cec5SDimitry Andric     signal_arg.arg_repetition = eArgRepeatStar;
16030b57cec5SDimitry Andric 
16040b57cec5SDimitry Andric     arg.push_back(signal_arg);
16050b57cec5SDimitry Andric 
16060b57cec5SDimitry Andric     m_arguments.push_back(arg);
16070b57cec5SDimitry Andric   }
16080b57cec5SDimitry Andric 
16090b57cec5SDimitry Andric   ~CommandObjectProcessHandle() override = default;
16100b57cec5SDimitry Andric 
16110b57cec5SDimitry Andric   Options *GetOptions() override { return &m_options; }
16120b57cec5SDimitry Andric 
16130b57cec5SDimitry Andric   bool VerifyCommandOptionValue(const std::string &option, int &real_value) {
16140b57cec5SDimitry Andric     bool okay = true;
16150b57cec5SDimitry Andric     bool success = false;
16160b57cec5SDimitry Andric     bool tmp_value = OptionArgParser::ToBoolean(option, false, &success);
16170b57cec5SDimitry Andric 
16180b57cec5SDimitry Andric     if (success && tmp_value)
16190b57cec5SDimitry Andric       real_value = 1;
16200b57cec5SDimitry Andric     else if (success && !tmp_value)
16210b57cec5SDimitry Andric       real_value = 0;
16220b57cec5SDimitry Andric     else {
16230b57cec5SDimitry Andric       // If the value isn't 'true' or 'false', it had better be 0 or 1.
16245ffd83dbSDimitry Andric       if (!llvm::to_integer(option, real_value))
16255ffd83dbSDimitry Andric         real_value = 3;
16260b57cec5SDimitry Andric       if (real_value != 0 && real_value != 1)
16270b57cec5SDimitry Andric         okay = false;
16280b57cec5SDimitry Andric     }
16290b57cec5SDimitry Andric 
16300b57cec5SDimitry Andric     return okay;
16310b57cec5SDimitry Andric   }
16320b57cec5SDimitry Andric 
16330b57cec5SDimitry Andric   void PrintSignalHeader(Stream &str) {
16340b57cec5SDimitry Andric     str.Printf("NAME         PASS   STOP   NOTIFY\n");
16350b57cec5SDimitry Andric     str.Printf("===========  =====  =====  ======\n");
16360b57cec5SDimitry Andric   }
16370b57cec5SDimitry Andric 
16380b57cec5SDimitry Andric   void PrintSignal(Stream &str, int32_t signo, const char *sig_name,
16390b57cec5SDimitry Andric                    const UnixSignalsSP &signals_sp) {
16400b57cec5SDimitry Andric     bool stop;
16410b57cec5SDimitry Andric     bool suppress;
16420b57cec5SDimitry Andric     bool notify;
16430b57cec5SDimitry Andric 
16440b57cec5SDimitry Andric     str.Printf("%-11s  ", sig_name);
16450b57cec5SDimitry Andric     if (signals_sp->GetSignalInfo(signo, suppress, stop, notify)) {
16460b57cec5SDimitry Andric       bool pass = !suppress;
16470b57cec5SDimitry Andric       str.Printf("%s  %s  %s", (pass ? "true " : "false"),
16480b57cec5SDimitry Andric                  (stop ? "true " : "false"), (notify ? "true " : "false"));
16490b57cec5SDimitry Andric     }
16500b57cec5SDimitry Andric     str.Printf("\n");
16510b57cec5SDimitry Andric   }
16520b57cec5SDimitry Andric 
16530b57cec5SDimitry Andric   void PrintSignalInformation(Stream &str, Args &signal_args,
16540b57cec5SDimitry Andric                               int num_valid_signals,
16550b57cec5SDimitry Andric                               const UnixSignalsSP &signals_sp) {
16560b57cec5SDimitry Andric     PrintSignalHeader(str);
16570b57cec5SDimitry Andric 
16580b57cec5SDimitry Andric     if (num_valid_signals > 0) {
16590b57cec5SDimitry Andric       size_t num_args = signal_args.GetArgumentCount();
16600b57cec5SDimitry Andric       for (size_t i = 0; i < num_args; ++i) {
16610b57cec5SDimitry Andric         int32_t signo = signals_sp->GetSignalNumberFromName(
16620b57cec5SDimitry Andric             signal_args.GetArgumentAtIndex(i));
16630b57cec5SDimitry Andric         if (signo != LLDB_INVALID_SIGNAL_NUMBER)
16640b57cec5SDimitry Andric           PrintSignal(str, signo, signal_args.GetArgumentAtIndex(i),
16650b57cec5SDimitry Andric                       signals_sp);
16660b57cec5SDimitry Andric       }
16670b57cec5SDimitry Andric     } else // Print info for ALL signals
16680b57cec5SDimitry Andric     {
16690b57cec5SDimitry Andric       int32_t signo = signals_sp->GetFirstSignalNumber();
16700b57cec5SDimitry Andric       while (signo != LLDB_INVALID_SIGNAL_NUMBER) {
16710b57cec5SDimitry Andric         PrintSignal(str, signo, signals_sp->GetSignalAsCString(signo),
16720b57cec5SDimitry Andric                     signals_sp);
16730b57cec5SDimitry Andric         signo = signals_sp->GetNextSignalNumber(signo);
16740b57cec5SDimitry Andric       }
16750b57cec5SDimitry Andric     }
16760b57cec5SDimitry Andric   }
16770b57cec5SDimitry Andric 
16780b57cec5SDimitry Andric protected:
16790b57cec5SDimitry Andric   bool DoExecute(Args &signal_args, CommandReturnObject &result) override {
168081ad6265SDimitry Andric     Target &target = GetSelectedOrDummyTarget();
16810b57cec5SDimitry Andric 
168281ad6265SDimitry Andric     // Any signals that are being set should be added to the Target's
168381ad6265SDimitry Andric     // DummySignals so they will get applied on rerun, etc.
168481ad6265SDimitry Andric     // If we have a process, however, we can do a more accurate job of vetting
168581ad6265SDimitry Andric     // the user's options.
168681ad6265SDimitry Andric     ProcessSP process_sp = target.GetProcessSP();
16870b57cec5SDimitry Andric 
16880b57cec5SDimitry Andric     int stop_action = -1;   // -1 means leave the current setting alone
16890b57cec5SDimitry Andric     int pass_action = -1;   // -1 means leave the current setting alone
16900b57cec5SDimitry Andric     int notify_action = -1; // -1 means leave the current setting alone
16910b57cec5SDimitry Andric 
16920b57cec5SDimitry Andric     if (!m_options.stop.empty() &&
16930b57cec5SDimitry Andric         !VerifyCommandOptionValue(m_options.stop, stop_action)) {
16940b57cec5SDimitry Andric       result.AppendError("Invalid argument for command option --stop; must be "
16950b57cec5SDimitry Andric                          "true or false.\n");
16960b57cec5SDimitry Andric       return false;
16970b57cec5SDimitry Andric     }
16980b57cec5SDimitry Andric 
16990b57cec5SDimitry Andric     if (!m_options.notify.empty() &&
17000b57cec5SDimitry Andric         !VerifyCommandOptionValue(m_options.notify, notify_action)) {
17010b57cec5SDimitry Andric       result.AppendError("Invalid argument for command option --notify; must "
17020b57cec5SDimitry Andric                          "be true or false.\n");
17030b57cec5SDimitry Andric       return false;
17040b57cec5SDimitry Andric     }
17050b57cec5SDimitry Andric 
17060b57cec5SDimitry Andric     if (!m_options.pass.empty() &&
17070b57cec5SDimitry Andric         !VerifyCommandOptionValue(m_options.pass, pass_action)) {
17080b57cec5SDimitry Andric       result.AppendError("Invalid argument for command option --pass; must be "
17090b57cec5SDimitry Andric                          "true or false.\n");
17100b57cec5SDimitry Andric       return false;
17110b57cec5SDimitry Andric     }
17120b57cec5SDimitry Andric 
171381ad6265SDimitry Andric     bool no_actions = (stop_action == -1 && pass_action == -1
171481ad6265SDimitry Andric         && notify_action == -1);
171581ad6265SDimitry Andric     if (m_options.only_target_values && !no_actions) {
171681ad6265SDimitry Andric       result.AppendError("-t is for reporting, not setting, target values.");
171781ad6265SDimitry Andric       return false;
171881ad6265SDimitry Andric     }
171981ad6265SDimitry Andric 
17200b57cec5SDimitry Andric     size_t num_args = signal_args.GetArgumentCount();
172181ad6265SDimitry Andric     UnixSignalsSP signals_sp;
172281ad6265SDimitry Andric     if (process_sp)
172381ad6265SDimitry Andric       signals_sp = process_sp->GetUnixSignals();
172481ad6265SDimitry Andric 
17250b57cec5SDimitry Andric     int num_signals_set = 0;
17260b57cec5SDimitry Andric 
172781ad6265SDimitry Andric     // If we were just asked to print the target values, do that here and
172881ad6265SDimitry Andric     // return:
172981ad6265SDimitry Andric     if (m_options.only_target_values) {
173081ad6265SDimitry Andric       target.PrintDummySignals(result.GetOutputStream(), signal_args);
173181ad6265SDimitry Andric       result.SetStatus(eReturnStatusSuccessFinishResult);
173281ad6265SDimitry Andric       return true;
173381ad6265SDimitry Andric     }
173481ad6265SDimitry Andric 
173581ad6265SDimitry Andric     // This handles clearing values:
173681ad6265SDimitry Andric     if (m_options.do_clear) {
173781ad6265SDimitry Andric       target.ClearDummySignals(signal_args);
173881ad6265SDimitry Andric       if (m_options.dummy)
173981ad6265SDimitry Andric         GetDummyTarget().ClearDummySignals(signal_args);
174081ad6265SDimitry Andric       result.SetStatus(eReturnStatusSuccessFinishNoResult);
174181ad6265SDimitry Andric       return true;
174281ad6265SDimitry Andric     }
174381ad6265SDimitry Andric 
174481ad6265SDimitry Andric     // This rest handles setting values:
17450b57cec5SDimitry Andric     if (num_args > 0) {
17460b57cec5SDimitry Andric       for (const auto &arg : signal_args) {
174781ad6265SDimitry Andric         // Do the process first.  If we have a process we can catch
174881ad6265SDimitry Andric         // invalid signal names, which we do here.
174981ad6265SDimitry Andric         if (signals_sp) {
17500b57cec5SDimitry Andric           int32_t signo = signals_sp->GetSignalNumberFromName(arg.c_str());
17510b57cec5SDimitry Andric           if (signo != LLDB_INVALID_SIGNAL_NUMBER) {
17520b57cec5SDimitry Andric             // Casting the actions as bools here should be okay, because
17530b57cec5SDimitry Andric             // VerifyCommandOptionValue guarantees the value is either 0 or 1.
17540b57cec5SDimitry Andric             if (stop_action != -1)
17550b57cec5SDimitry Andric               signals_sp->SetShouldStop(signo, stop_action);
17560b57cec5SDimitry Andric             if (pass_action != -1) {
17570b57cec5SDimitry Andric               bool suppress = !pass_action;
17580b57cec5SDimitry Andric               signals_sp->SetShouldSuppress(signo, suppress);
17590b57cec5SDimitry Andric             }
17600b57cec5SDimitry Andric             if (notify_action != -1)
17610b57cec5SDimitry Andric               signals_sp->SetShouldNotify(signo, notify_action);
17620b57cec5SDimitry Andric             ++num_signals_set;
17630b57cec5SDimitry Andric           } else {
17640b57cec5SDimitry Andric             result.AppendErrorWithFormat("Invalid signal name '%s'\n",
17650b57cec5SDimitry Andric                                           arg.c_str());
176681ad6265SDimitry Andric             continue;
17670b57cec5SDimitry Andric           }
176881ad6265SDimitry Andric         } else {
176981ad6265SDimitry Andric           // If there's no process we can't check, so we just set them all.
177081ad6265SDimitry Andric           // But since the map signal name -> signal number across all platforms
177181ad6265SDimitry Andric           // is not 1-1, we can't sensibly set signal actions by number before
177281ad6265SDimitry Andric           // we have a process.  Check that here:
177381ad6265SDimitry Andric           int32_t signo;
177481ad6265SDimitry Andric           if (llvm::to_integer(arg.c_str(), signo)) {
177581ad6265SDimitry Andric             result.AppendErrorWithFormat("Can't set signal handling by signal "
177681ad6265SDimitry Andric                                          "number with no process");
177781ad6265SDimitry Andric             return false;
177881ad6265SDimitry Andric           }
177981ad6265SDimitry Andric          num_signals_set = num_args;
178081ad6265SDimitry Andric         }
178181ad6265SDimitry Andric         auto set_lazy_bool = [] (int action) -> LazyBool {
178281ad6265SDimitry Andric           LazyBool lazy;
178381ad6265SDimitry Andric           if (action == -1)
178481ad6265SDimitry Andric             lazy = eLazyBoolCalculate;
178581ad6265SDimitry Andric           else if (action)
178681ad6265SDimitry Andric             lazy = eLazyBoolYes;
178781ad6265SDimitry Andric           else
178881ad6265SDimitry Andric             lazy = eLazyBoolNo;
178981ad6265SDimitry Andric           return lazy;
179081ad6265SDimitry Andric         };
179181ad6265SDimitry Andric 
179281ad6265SDimitry Andric         // If there were no actions, we're just listing, don't add the dummy:
179381ad6265SDimitry Andric         if (!no_actions)
179481ad6265SDimitry Andric           target.AddDummySignal(arg.ref(),
179581ad6265SDimitry Andric                                 set_lazy_bool(pass_action),
179681ad6265SDimitry Andric                                 set_lazy_bool(notify_action),
179781ad6265SDimitry Andric                                 set_lazy_bool(stop_action));
17980b57cec5SDimitry Andric       }
17990b57cec5SDimitry Andric     } else {
18000b57cec5SDimitry Andric       // No signal specified, if any command options were specified, update ALL
180181ad6265SDimitry Andric       // signals.  But we can't do this without a process since we don't know
180281ad6265SDimitry Andric       // all the possible signals that might be valid for this target.
180381ad6265SDimitry Andric       if (((notify_action != -1) || (stop_action != -1) || (pass_action != -1))
180481ad6265SDimitry Andric           && process_sp) {
18050b57cec5SDimitry Andric         if (m_interpreter.Confirm(
18060b57cec5SDimitry Andric                 "Do you really want to update all the signals?", false)) {
18070b57cec5SDimitry Andric           int32_t signo = signals_sp->GetFirstSignalNumber();
18080b57cec5SDimitry Andric           while (signo != LLDB_INVALID_SIGNAL_NUMBER) {
18090b57cec5SDimitry Andric             if (notify_action != -1)
18100b57cec5SDimitry Andric               signals_sp->SetShouldNotify(signo, notify_action);
18110b57cec5SDimitry Andric             if (stop_action != -1)
18120b57cec5SDimitry Andric               signals_sp->SetShouldStop(signo, stop_action);
18130b57cec5SDimitry Andric             if (pass_action != -1) {
18140b57cec5SDimitry Andric               bool suppress = !pass_action;
18150b57cec5SDimitry Andric               signals_sp->SetShouldSuppress(signo, suppress);
18160b57cec5SDimitry Andric             }
18170b57cec5SDimitry Andric             signo = signals_sp->GetNextSignalNumber(signo);
18180b57cec5SDimitry Andric           }
18190b57cec5SDimitry Andric         }
18200b57cec5SDimitry Andric       }
18210b57cec5SDimitry Andric     }
18220b57cec5SDimitry Andric 
182381ad6265SDimitry Andric     if (signals_sp)
18240b57cec5SDimitry Andric       PrintSignalInformation(result.GetOutputStream(), signal_args,
18250b57cec5SDimitry Andric                              num_signals_set, signals_sp);
182681ad6265SDimitry Andric     else
182781ad6265SDimitry Andric       target.PrintDummySignals(result.GetOutputStream(),
182881ad6265SDimitry Andric           signal_args);
18290b57cec5SDimitry Andric 
18300b57cec5SDimitry Andric     if (num_signals_set > 0)
183181ad6265SDimitry Andric       result.SetStatus(eReturnStatusSuccessFinishResult);
18320b57cec5SDimitry Andric     else
18330b57cec5SDimitry Andric       result.SetStatus(eReturnStatusFailed);
18340b57cec5SDimitry Andric 
18350b57cec5SDimitry Andric     return result.Succeeded();
18360b57cec5SDimitry Andric   }
18370b57cec5SDimitry Andric 
18380b57cec5SDimitry Andric   CommandOptions m_options;
18390b57cec5SDimitry Andric };
18400b57cec5SDimitry Andric 
1841fe6060f1SDimitry Andric // Next are the subcommands of CommandObjectMultiwordProcessTrace
1842fe6060f1SDimitry Andric 
1843fe6060f1SDimitry Andric // CommandObjectProcessTraceStart
1844fe6060f1SDimitry Andric class CommandObjectProcessTraceStart : public CommandObjectTraceProxy {
1845fe6060f1SDimitry Andric public:
1846fe6060f1SDimitry Andric   CommandObjectProcessTraceStart(CommandInterpreter &interpreter)
1847fe6060f1SDimitry Andric       : CommandObjectTraceProxy(
1848fe6060f1SDimitry Andric             /*live_debug_session_only*/ true, interpreter,
1849fe6060f1SDimitry Andric             "process trace start",
1850fe6060f1SDimitry Andric             "Start tracing this process with the corresponding trace "
1851fe6060f1SDimitry Andric             "plug-in.",
1852fe6060f1SDimitry Andric             "process trace start [<trace-options>]") {}
1853fe6060f1SDimitry Andric 
1854fe6060f1SDimitry Andric protected:
1855fe6060f1SDimitry Andric   lldb::CommandObjectSP GetDelegateCommand(Trace &trace) override {
1856fe6060f1SDimitry Andric     return trace.GetProcessTraceStartCommand(m_interpreter);
1857fe6060f1SDimitry Andric   }
1858fe6060f1SDimitry Andric };
1859fe6060f1SDimitry Andric 
1860fe6060f1SDimitry Andric // CommandObjectProcessTraceStop
1861fe6060f1SDimitry Andric class CommandObjectProcessTraceStop : public CommandObjectParsed {
1862fe6060f1SDimitry Andric public:
1863fe6060f1SDimitry Andric   CommandObjectProcessTraceStop(CommandInterpreter &interpreter)
1864fe6060f1SDimitry Andric       : CommandObjectParsed(interpreter, "process trace stop",
1865fe6060f1SDimitry Andric                             "Stop tracing this process. This does not affect "
1866fe6060f1SDimitry Andric                             "traces started with the "
1867fe6060f1SDimitry Andric                             "\"thread trace start\" command.",
1868fe6060f1SDimitry Andric                             "process trace stop",
1869fe6060f1SDimitry Andric                             eCommandRequiresProcess | eCommandTryTargetAPILock |
1870fe6060f1SDimitry Andric                                 eCommandProcessMustBeLaunched |
1871fe6060f1SDimitry Andric                                 eCommandProcessMustBePaused |
1872fe6060f1SDimitry Andric                                 eCommandProcessMustBeTraced) {}
1873fe6060f1SDimitry Andric 
1874fe6060f1SDimitry Andric   ~CommandObjectProcessTraceStop() override = default;
1875fe6060f1SDimitry Andric 
1876fe6060f1SDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
1877fe6060f1SDimitry Andric     ProcessSP process_sp = m_exe_ctx.GetProcessSP();
1878fe6060f1SDimitry Andric 
1879fe6060f1SDimitry Andric     TraceSP trace_sp = process_sp->GetTarget().GetTrace();
1880fe6060f1SDimitry Andric 
1881fe6060f1SDimitry Andric     if (llvm::Error err = trace_sp->Stop())
1882fe6060f1SDimitry Andric       result.AppendError(toString(std::move(err)));
1883fe6060f1SDimitry Andric     else
1884fe6060f1SDimitry Andric       result.SetStatus(eReturnStatusSuccessFinishResult);
1885fe6060f1SDimitry Andric 
1886fe6060f1SDimitry Andric     return result.Succeeded();
1887fe6060f1SDimitry Andric   }
1888fe6060f1SDimitry Andric };
1889fe6060f1SDimitry Andric 
1890fe6060f1SDimitry Andric // CommandObjectMultiwordProcessTrace
1891fe6060f1SDimitry Andric class CommandObjectMultiwordProcessTrace : public CommandObjectMultiword {
1892fe6060f1SDimitry Andric public:
1893fe6060f1SDimitry Andric   CommandObjectMultiwordProcessTrace(CommandInterpreter &interpreter)
1894fe6060f1SDimitry Andric       : CommandObjectMultiword(
1895fe6060f1SDimitry Andric             interpreter, "trace", "Commands for tracing the current process.",
1896fe6060f1SDimitry Andric             "process trace <subcommand> [<subcommand objects>]") {
1897fe6060f1SDimitry Andric     LoadSubCommand("start", CommandObjectSP(new CommandObjectProcessTraceStart(
1898fe6060f1SDimitry Andric                                 interpreter)));
1899fe6060f1SDimitry Andric     LoadSubCommand("stop", CommandObjectSP(
1900fe6060f1SDimitry Andric                                new CommandObjectProcessTraceStop(interpreter)));
1901fe6060f1SDimitry Andric   }
1902fe6060f1SDimitry Andric 
1903fe6060f1SDimitry Andric   ~CommandObjectMultiwordProcessTrace() override = default;
1904fe6060f1SDimitry Andric };
1905fe6060f1SDimitry Andric 
19060b57cec5SDimitry Andric // CommandObjectMultiwordProcess
19070b57cec5SDimitry Andric 
19080b57cec5SDimitry Andric CommandObjectMultiwordProcess::CommandObjectMultiwordProcess(
19090b57cec5SDimitry Andric     CommandInterpreter &interpreter)
19100b57cec5SDimitry Andric     : CommandObjectMultiword(
19110b57cec5SDimitry Andric           interpreter, "process",
19120b57cec5SDimitry Andric           "Commands for interacting with processes on the current platform.",
19130b57cec5SDimitry Andric           "process <subcommand> [<subcommand-options>]") {
19140b57cec5SDimitry Andric   LoadSubCommand("attach",
19150b57cec5SDimitry Andric                  CommandObjectSP(new CommandObjectProcessAttach(interpreter)));
19160b57cec5SDimitry Andric   LoadSubCommand("launch",
19170b57cec5SDimitry Andric                  CommandObjectSP(new CommandObjectProcessLaunch(interpreter)));
19180b57cec5SDimitry Andric   LoadSubCommand("continue", CommandObjectSP(new CommandObjectProcessContinue(
19190b57cec5SDimitry Andric                                  interpreter)));
19200b57cec5SDimitry Andric   LoadSubCommand("connect",
19210b57cec5SDimitry Andric                  CommandObjectSP(new CommandObjectProcessConnect(interpreter)));
19220b57cec5SDimitry Andric   LoadSubCommand("detach",
19230b57cec5SDimitry Andric                  CommandObjectSP(new CommandObjectProcessDetach(interpreter)));
19240b57cec5SDimitry Andric   LoadSubCommand("load",
19250b57cec5SDimitry Andric                  CommandObjectSP(new CommandObjectProcessLoad(interpreter)));
19260b57cec5SDimitry Andric   LoadSubCommand("unload",
19270b57cec5SDimitry Andric                  CommandObjectSP(new CommandObjectProcessUnload(interpreter)));
19280b57cec5SDimitry Andric   LoadSubCommand("signal",
19290b57cec5SDimitry Andric                  CommandObjectSP(new CommandObjectProcessSignal(interpreter)));
19300b57cec5SDimitry Andric   LoadSubCommand("handle",
19310b57cec5SDimitry Andric                  CommandObjectSP(new CommandObjectProcessHandle(interpreter)));
19320b57cec5SDimitry Andric   LoadSubCommand("status",
19330b57cec5SDimitry Andric                  CommandObjectSP(new CommandObjectProcessStatus(interpreter)));
19340b57cec5SDimitry Andric   LoadSubCommand("interrupt", CommandObjectSP(new CommandObjectProcessInterrupt(
19350b57cec5SDimitry Andric                                   interpreter)));
19360b57cec5SDimitry Andric   LoadSubCommand("kill",
19370b57cec5SDimitry Andric                  CommandObjectSP(new CommandObjectProcessKill(interpreter)));
19380b57cec5SDimitry Andric   LoadSubCommand("plugin",
19390b57cec5SDimitry Andric                  CommandObjectSP(new CommandObjectProcessPlugin(interpreter)));
19400b57cec5SDimitry Andric   LoadSubCommand("save-core", CommandObjectSP(new CommandObjectProcessSaveCore(
19410b57cec5SDimitry Andric                                   interpreter)));
1942fe6060f1SDimitry Andric   LoadSubCommand(
1943fe6060f1SDimitry Andric       "trace",
1944fe6060f1SDimitry Andric       CommandObjectSP(new CommandObjectMultiwordProcessTrace(interpreter)));
19450b57cec5SDimitry Andric }
19460b57cec5SDimitry Andric 
19470b57cec5SDimitry Andric CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess() = default;
1948