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"
12fe013be4SDimitry 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"
35fe013be4SDimitry 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:
CommandObjectProcessLaunchOrAttach(CommandInterpreter & interpreter,const char * name,const char * help,const char * syntax,uint32_t flags,const char * new_process_action)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:
StopProcessIfNecessary(Process * process,StateType & state,CommandReturnObject & result)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:
CommandObjectProcessLaunch(CommandInterpreter & interpreter)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
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)1479dba64beSDimitry Andric HandleArgumentCompletion(CompletionRequest &request,
1480b57cec5SDimitry Andric OptionElementVector &opt_element_vector) override {
1490b57cec5SDimitry Andric
150fe013be4SDimitry Andric lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
151fe013be4SDimitry Andric GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr);
1520b57cec5SDimitry Andric }
1530b57cec5SDimitry Andric
GetOptions()154fe6060f1SDimitry Andric Options *GetOptions() override { return &m_all_options; }
1550b57cec5SDimitry Andric
GetRepeatCommand(Args & current_command_args,uint32_t index)156bdd1243dSDimitry Andric std::optional<std::string> GetRepeatCommand(Args ¤t_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:
DoExecute(Args & launch_args,CommandReturnObject & result)163*c9157d92SDimitry Andric void 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");
177*c9157d92SDimitry Andric return;
1780b57cec5SDimitry Andric }
1790b57cec5SDimitry Andric
1800b57cec5SDimitry Andric StateType state = eStateInvalid;
1810b57cec5SDimitry Andric
1820b57cec5SDimitry Andric if (!StopProcessIfNecessary(m_exe_ctx.GetProcessPtr(), state, result))
183*c9157d92SDimitry Andric return;
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");
203fe013be4SDimitry Andric ScriptedMetadataSP metadata_sp = std::make_shared<ScriptedMetadata>(
204fe013be4SDimitry Andric m_class_options.GetName(), m_class_options.GetStructuredData());
205fe013be4SDimitry 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
267349cc55cSDimitry Andric // If we didn't have a local executable, then we wouldn't have had an
268349cc55cSDimitry Andric // executable module before launch.
269349cc55cSDimitry Andric if (!exe_module_sp)
270349cc55cSDimitry Andric exe_module_sp = target->GetExecutableModule();
271349cc55cSDimitry Andric if (!exe_module_sp) {
272349cc55cSDimitry Andric result.AppendWarning("Could not get executable module after launch.");
273349cc55cSDimitry Andric } else {
274349cc55cSDimitry Andric
2750b57cec5SDimitry Andric const char *archname =
2760b57cec5SDimitry Andric exe_module_sp->GetArchitecture().GetArchitectureName();
2770b57cec5SDimitry Andric result.AppendMessageWithFormat(
2780b57cec5SDimitry Andric "Process %" PRIu64 " launched: '%s' (%s)\n", process_sp->GetID(),
2790b57cec5SDimitry Andric exe_module_sp->GetFileSpec().GetPath().c_str(), archname);
280349cc55cSDimitry Andric }
2810b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult);
282*c9157d92SDimitry Andric // This message will refer to an event that happened after the process
283*c9157d92SDimitry Andric // launched.
284*c9157d92SDimitry Andric llvm::StringRef data = stream.GetString();
285*c9157d92SDimitry Andric if (!data.empty())
286*c9157d92SDimitry Andric result.AppendMessage(data);
2870b57cec5SDimitry Andric result.SetDidChangeProcessState(true);
2880b57cec5SDimitry Andric } else {
2890b57cec5SDimitry Andric result.AppendError(
2900b57cec5SDimitry Andric "no error returned from Target::Launch, and target has no process");
2910b57cec5SDimitry Andric }
2920b57cec5SDimitry Andric } else {
2930b57cec5SDimitry Andric result.AppendError(error.AsCString());
2940b57cec5SDimitry Andric }
2950b57cec5SDimitry Andric }
2960b57cec5SDimitry Andric
297e8d8bef9SDimitry Andric CommandOptionsProcessLaunch m_options;
298fe6060f1SDimitry Andric OptionGroupPythonClassWithDict m_class_options;
299fe6060f1SDimitry Andric OptionGroupOptions m_all_options;
3000b57cec5SDimitry Andric };
3010b57cec5SDimitry Andric
3029dba64beSDimitry Andric #define LLDB_OPTIONS_process_attach
3039dba64beSDimitry Andric #include "CommandOptions.inc"
3040b57cec5SDimitry Andric
3050b57cec5SDimitry Andric #pragma mark CommandObjectProcessAttach
3060b57cec5SDimitry Andric class CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach {
3070b57cec5SDimitry Andric public:
CommandObjectProcessAttach(CommandInterpreter & interpreter)3080b57cec5SDimitry Andric CommandObjectProcessAttach(CommandInterpreter &interpreter)
3090b57cec5SDimitry Andric : CommandObjectProcessLaunchOrAttach(
3100b57cec5SDimitry Andric interpreter, "process attach", "Attach to a process.",
311fe013be4SDimitry Andric "process attach <cmd-options>", 0, "attach"),
312fe013be4SDimitry Andric m_class_options("scripted process", true, 'C', 'k', 'v', 0) {
313fe013be4SDimitry Andric m_all_options.Append(&m_options);
314fe013be4SDimitry Andric m_all_options.Append(&m_class_options, LLDB_OPT_SET_1 | LLDB_OPT_SET_2,
315fe013be4SDimitry Andric LLDB_OPT_SET_ALL);
316fe013be4SDimitry Andric m_all_options.Finalize();
317fe013be4SDimitry Andric }
3180b57cec5SDimitry Andric
3190b57cec5SDimitry Andric ~CommandObjectProcessAttach() override = default;
3200b57cec5SDimitry Andric
GetOptions()321fe013be4SDimitry Andric Options *GetOptions() override { return &m_all_options; }
3220b57cec5SDimitry Andric
3230b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)324*c9157d92SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
3250b57cec5SDimitry Andric PlatformSP platform_sp(
3260b57cec5SDimitry Andric GetDebugger().GetPlatformList().GetSelectedPlatform());
3270b57cec5SDimitry Andric
3280b57cec5SDimitry Andric Target *target = GetDebugger().GetSelectedTarget().get();
3290b57cec5SDimitry Andric // N.B. The attach should be synchronous. It doesn't help much to get the
3300b57cec5SDimitry Andric // prompt back between initiating the attach and the target actually
3310b57cec5SDimitry Andric // stopping. So even if the interpreter is set to be asynchronous, we wait
3320b57cec5SDimitry Andric // for the stop ourselves here.
3330b57cec5SDimitry Andric
3340b57cec5SDimitry Andric StateType state = eStateInvalid;
3350b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr();
3360b57cec5SDimitry Andric
3370b57cec5SDimitry Andric if (!StopProcessIfNecessary(process, state, result))
338*c9157d92SDimitry Andric return;
3390b57cec5SDimitry Andric
3400b57cec5SDimitry Andric if (target == nullptr) {
3410b57cec5SDimitry Andric // If there isn't a current target create one.
3420b57cec5SDimitry Andric TargetSP new_target_sp;
3430b57cec5SDimitry Andric Status error;
3440b57cec5SDimitry Andric
3450b57cec5SDimitry Andric error = GetDebugger().GetTargetList().CreateTarget(
3460b57cec5SDimitry Andric GetDebugger(), "", "", eLoadDependentsNo,
3470b57cec5SDimitry Andric nullptr, // No platform options
3480b57cec5SDimitry Andric new_target_sp);
3490b57cec5SDimitry Andric target = new_target_sp.get();
3500b57cec5SDimitry Andric if (target == nullptr || error.Fail()) {
3510b57cec5SDimitry Andric result.AppendError(error.AsCString("Error creating target"));
352*c9157d92SDimitry Andric return;
3530b57cec5SDimitry Andric }
3540b57cec5SDimitry Andric }
3550b57cec5SDimitry Andric
356fe013be4SDimitry Andric if (!m_class_options.GetName().empty()) {
357fe013be4SDimitry Andric m_options.attach_info.SetProcessPluginName("ScriptedProcess");
358fe013be4SDimitry Andric ScriptedMetadataSP metadata_sp = std::make_shared<ScriptedMetadata>(
359fe013be4SDimitry Andric m_class_options.GetName(), m_class_options.GetStructuredData());
360fe013be4SDimitry Andric m_options.attach_info.SetScriptedMetadata(metadata_sp);
361fe013be4SDimitry Andric }
362fe013be4SDimitry Andric
3630b57cec5SDimitry Andric // Record the old executable module, we want to issue a warning if the
3640b57cec5SDimitry Andric // process of attaching changed the current executable (like somebody said
3650b57cec5SDimitry Andric // "file foo" then attached to a PID whose executable was bar.)
3660b57cec5SDimitry Andric
3670b57cec5SDimitry Andric ModuleSP old_exec_module_sp = target->GetExecutableModule();
3680b57cec5SDimitry Andric ArchSpec old_arch_spec = target->GetArchitecture();
3690b57cec5SDimitry Andric
3700b57cec5SDimitry Andric StreamString stream;
371349cc55cSDimitry Andric ProcessSP process_sp;
3720b57cec5SDimitry Andric const auto error = target->Attach(m_options.attach_info, &stream);
3730b57cec5SDimitry Andric if (error.Success()) {
374349cc55cSDimitry Andric process_sp = target->GetProcessSP();
3750b57cec5SDimitry Andric if (process_sp) {
3760b57cec5SDimitry Andric result.AppendMessage(stream.GetString());
3770b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult);
3780b57cec5SDimitry Andric result.SetDidChangeProcessState(true);
3790b57cec5SDimitry Andric } else {
3800b57cec5SDimitry Andric result.AppendError(
3810b57cec5SDimitry Andric "no error returned from Target::Attach, and target has no process");
3820b57cec5SDimitry Andric }
3830b57cec5SDimitry Andric } else {
3840b57cec5SDimitry Andric result.AppendErrorWithFormat("attach failed: %s\n", error.AsCString());
3850b57cec5SDimitry Andric }
3860b57cec5SDimitry Andric
3870b57cec5SDimitry Andric if (!result.Succeeded())
388*c9157d92SDimitry Andric return;
3890b57cec5SDimitry Andric
3900b57cec5SDimitry Andric // Okay, we're done. Last step is to warn if the executable module has
3910b57cec5SDimitry Andric // changed:
3920b57cec5SDimitry Andric char new_path[PATH_MAX];
3930b57cec5SDimitry Andric ModuleSP new_exec_module_sp(target->GetExecutableModule());
3940b57cec5SDimitry Andric if (!old_exec_module_sp) {
3950b57cec5SDimitry Andric // We might not have a module if we attached to a raw pid...
3960b57cec5SDimitry Andric if (new_exec_module_sp) {
3970b57cec5SDimitry Andric new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX);
3980b57cec5SDimitry Andric result.AppendMessageWithFormat("Executable module set to \"%s\".\n",
3990b57cec5SDimitry Andric new_path);
4000b57cec5SDimitry Andric }
4010b57cec5SDimitry Andric } else if (old_exec_module_sp->GetFileSpec() !=
4020b57cec5SDimitry Andric new_exec_module_sp->GetFileSpec()) {
4030b57cec5SDimitry Andric char old_path[PATH_MAX];
4040b57cec5SDimitry Andric
4050b57cec5SDimitry Andric old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX);
4060b57cec5SDimitry Andric new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX);
4070b57cec5SDimitry Andric
4080b57cec5SDimitry Andric result.AppendWarningWithFormat(
4090b57cec5SDimitry Andric "Executable module changed from \"%s\" to \"%s\".\n", old_path,
4100b57cec5SDimitry Andric new_path);
4110b57cec5SDimitry Andric }
4120b57cec5SDimitry Andric
4130b57cec5SDimitry Andric if (!old_arch_spec.IsValid()) {
4140b57cec5SDimitry Andric result.AppendMessageWithFormat(
4150b57cec5SDimitry Andric "Architecture set to: %s.\n",
4160b57cec5SDimitry Andric target->GetArchitecture().GetTriple().getTriple().c_str());
4170b57cec5SDimitry Andric } else if (!old_arch_spec.IsExactMatch(target->GetArchitecture())) {
4180b57cec5SDimitry Andric result.AppendWarningWithFormat(
4190b57cec5SDimitry Andric "Architecture changed from %s to %s.\n",
4200b57cec5SDimitry Andric old_arch_spec.GetTriple().getTriple().c_str(),
4210b57cec5SDimitry Andric target->GetArchitecture().GetTriple().getTriple().c_str());
4220b57cec5SDimitry Andric }
4230b57cec5SDimitry Andric
4240b57cec5SDimitry Andric // This supports the use-case scenario of immediately continuing the
4250b57cec5SDimitry Andric // process once attached.
426349cc55cSDimitry Andric if (m_options.attach_info.GetContinueOnceAttached()) {
427349cc55cSDimitry Andric // We have made a process but haven't told the interpreter about it yet,
428349cc55cSDimitry Andric // so CheckRequirements will fail for "process continue". Set the override
429349cc55cSDimitry Andric // here:
430349cc55cSDimitry Andric ExecutionContext exe_ctx(process_sp);
431349cc55cSDimitry Andric m_interpreter.HandleCommand("process continue", eLazyBoolNo, exe_ctx, result);
432349cc55cSDimitry Andric }
4330b57cec5SDimitry Andric }
4340b57cec5SDimitry Andric
435fe013be4SDimitry Andric CommandOptionsProcessAttach m_options;
436fe013be4SDimitry Andric OptionGroupPythonClassWithDict m_class_options;
437fe013be4SDimitry Andric OptionGroupOptions m_all_options;
4380b57cec5SDimitry Andric };
4390b57cec5SDimitry Andric
4400b57cec5SDimitry Andric // CommandObjectProcessContinue
4410b57cec5SDimitry Andric
4429dba64beSDimitry Andric #define LLDB_OPTIONS_process_continue
4439dba64beSDimitry Andric #include "CommandOptions.inc"
4440b57cec5SDimitry Andric
4450b57cec5SDimitry Andric #pragma mark CommandObjectProcessContinue
4460b57cec5SDimitry Andric
4470b57cec5SDimitry Andric class CommandObjectProcessContinue : public CommandObjectParsed {
4480b57cec5SDimitry Andric public:
CommandObjectProcessContinue(CommandInterpreter & interpreter)4490b57cec5SDimitry Andric CommandObjectProcessContinue(CommandInterpreter &interpreter)
4500b57cec5SDimitry Andric : CommandObjectParsed(
4510b57cec5SDimitry Andric interpreter, "process continue",
4520b57cec5SDimitry Andric "Continue execution of all threads in the current process.",
4530b57cec5SDimitry Andric "process continue",
4540b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock |
45504eeddc0SDimitry Andric eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {}
4560b57cec5SDimitry Andric
4570b57cec5SDimitry Andric ~CommandObjectProcessContinue() override = default;
4580b57cec5SDimitry Andric
4590b57cec5SDimitry Andric protected:
4600b57cec5SDimitry Andric class CommandOptions : public Options {
4610b57cec5SDimitry Andric public:
CommandOptions()46204eeddc0SDimitry Andric CommandOptions() {
4630b57cec5SDimitry Andric // Keep default values of all options in one place: OptionParsingStarting
4640b57cec5SDimitry Andric // ()
4650b57cec5SDimitry Andric OptionParsingStarting(nullptr);
4660b57cec5SDimitry Andric }
4670b57cec5SDimitry Andric
4680b57cec5SDimitry Andric ~CommandOptions() override = default;
4690b57cec5SDimitry Andric
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * exe_ctx)4700b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
47181ad6265SDimitry Andric ExecutionContext *exe_ctx) override {
4720b57cec5SDimitry Andric Status error;
4730b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val;
4740b57cec5SDimitry Andric switch (short_option) {
4750b57cec5SDimitry Andric case 'i':
4760b57cec5SDimitry Andric if (option_arg.getAsInteger(0, m_ignore))
4770b57cec5SDimitry Andric error.SetErrorStringWithFormat(
4780b57cec5SDimitry Andric "invalid value for ignore option: \"%s\", should be a number.",
4790b57cec5SDimitry Andric option_arg.str().c_str());
4800b57cec5SDimitry Andric break;
48181ad6265SDimitry Andric case 'b':
48281ad6265SDimitry Andric m_run_to_bkpt_args.AppendArgument(option_arg);
48381ad6265SDimitry Andric m_any_bkpts_specified = true;
48481ad6265SDimitry Andric break;
4850b57cec5SDimitry Andric default:
4869dba64beSDimitry Andric llvm_unreachable("Unimplemented option");
4870b57cec5SDimitry Andric }
4880b57cec5SDimitry Andric return error;
4890b57cec5SDimitry Andric }
4900b57cec5SDimitry Andric
OptionParsingStarting(ExecutionContext * execution_context)4910b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
4920b57cec5SDimitry Andric m_ignore = 0;
49381ad6265SDimitry Andric m_run_to_bkpt_args.Clear();
49481ad6265SDimitry Andric m_any_bkpts_specified = false;
4950b57cec5SDimitry Andric }
4960b57cec5SDimitry Andric
GetDefinitions()4970b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
498bdd1243dSDimitry Andric return llvm::ArrayRef(g_process_continue_options);
4990b57cec5SDimitry Andric }
5000b57cec5SDimitry Andric
50181ad6265SDimitry Andric uint32_t m_ignore = 0;
50281ad6265SDimitry Andric Args m_run_to_bkpt_args;
50381ad6265SDimitry Andric bool m_any_bkpts_specified = false;
5040b57cec5SDimitry Andric };
5050b57cec5SDimitry Andric
DoExecute(Args & command,CommandReturnObject & result)506*c9157d92SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
5070b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr();
5080b57cec5SDimitry Andric bool synchronous_execution = m_interpreter.GetSynchronous();
5090b57cec5SDimitry Andric StateType state = process->GetState();
5100b57cec5SDimitry Andric if (state == eStateStopped) {
5110b57cec5SDimitry Andric if (m_options.m_ignore > 0) {
5120b57cec5SDimitry Andric ThreadSP sel_thread_sp(GetDefaultThread()->shared_from_this());
5130b57cec5SDimitry Andric if (sel_thread_sp) {
5140b57cec5SDimitry Andric StopInfoSP stop_info_sp = sel_thread_sp->GetStopInfo();
5150b57cec5SDimitry Andric if (stop_info_sp &&
5160b57cec5SDimitry Andric stop_info_sp->GetStopReason() == eStopReasonBreakpoint) {
5170b57cec5SDimitry Andric lldb::break_id_t bp_site_id =
5180b57cec5SDimitry Andric (lldb::break_id_t)stop_info_sp->GetValue();
5190b57cec5SDimitry Andric BreakpointSiteSP bp_site_sp(
5200b57cec5SDimitry Andric process->GetBreakpointSiteList().FindByID(bp_site_id));
5210b57cec5SDimitry Andric if (bp_site_sp) {
522*c9157d92SDimitry Andric const size_t num_owners = bp_site_sp->GetNumberOfConstituents();
5230b57cec5SDimitry Andric for (size_t i = 0; i < num_owners; i++) {
5240b57cec5SDimitry Andric Breakpoint &bp_ref =
525*c9157d92SDimitry Andric bp_site_sp->GetConstituentAtIndex(i)->GetBreakpoint();
5260b57cec5SDimitry Andric if (!bp_ref.IsInternal()) {
5270b57cec5SDimitry Andric bp_ref.SetIgnoreCount(m_options.m_ignore);
5280b57cec5SDimitry Andric }
5290b57cec5SDimitry Andric }
5300b57cec5SDimitry Andric }
5310b57cec5SDimitry Andric }
5320b57cec5SDimitry Andric }
5330b57cec5SDimitry Andric }
5340b57cec5SDimitry Andric
53581ad6265SDimitry Andric Target *target = m_exe_ctx.GetTargetPtr();
53681ad6265SDimitry Andric BreakpointIDList run_to_bkpt_ids;
53781ad6265SDimitry Andric // Don't pass an empty run_to_breakpoint list, as Verify will look for the
53881ad6265SDimitry Andric // default breakpoint.
53981ad6265SDimitry Andric if (m_options.m_run_to_bkpt_args.GetArgumentCount() > 0)
54081ad6265SDimitry Andric CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs(
54181ad6265SDimitry Andric m_options.m_run_to_bkpt_args, target, result, &run_to_bkpt_ids,
54281ad6265SDimitry Andric BreakpointName::Permissions::disablePerm);
54381ad6265SDimitry Andric if (!result.Succeeded()) {
544*c9157d92SDimitry Andric return;
54581ad6265SDimitry Andric }
54681ad6265SDimitry Andric result.Clear();
54781ad6265SDimitry Andric if (m_options.m_any_bkpts_specified && run_to_bkpt_ids.GetSize() == 0) {
54881ad6265SDimitry Andric result.AppendError("continue-to breakpoints did not specify any actual "
54981ad6265SDimitry Andric "breakpoints or locations");
550*c9157d92SDimitry Andric return;
55181ad6265SDimitry Andric }
55281ad6265SDimitry Andric
55381ad6265SDimitry Andric // First figure out which breakpoints & locations were specified by the
55481ad6265SDimitry Andric // user:
55581ad6265SDimitry Andric size_t num_run_to_bkpt_ids = run_to_bkpt_ids.GetSize();
55681ad6265SDimitry Andric std::vector<break_id_t> bkpts_disabled;
55781ad6265SDimitry Andric std::vector<BreakpointID> locs_disabled;
55881ad6265SDimitry Andric if (num_run_to_bkpt_ids != 0) {
55981ad6265SDimitry Andric // Go through the ID's specified, and separate the breakpoints from are
56081ad6265SDimitry Andric // the breakpoint.location specifications since the latter require
56181ad6265SDimitry Andric // special handling. We also figure out whether there's at least one
56281ad6265SDimitry Andric // specifier in the set that is enabled.
56381ad6265SDimitry Andric BreakpointList &bkpt_list = target->GetBreakpointList();
56481ad6265SDimitry Andric std::unordered_set<break_id_t> bkpts_seen;
56581ad6265SDimitry Andric std::unordered_set<break_id_t> bkpts_with_locs_seen;
56681ad6265SDimitry Andric BreakpointIDList with_locs;
56781ad6265SDimitry Andric bool any_enabled = false;
56881ad6265SDimitry Andric
56981ad6265SDimitry Andric for (size_t idx = 0; idx < num_run_to_bkpt_ids; idx++) {
57081ad6265SDimitry Andric BreakpointID bkpt_id = run_to_bkpt_ids.GetBreakpointIDAtIndex(idx);
57181ad6265SDimitry Andric break_id_t bp_id = bkpt_id.GetBreakpointID();
57281ad6265SDimitry Andric break_id_t loc_id = bkpt_id.GetLocationID();
57381ad6265SDimitry Andric BreakpointSP bp_sp
57481ad6265SDimitry Andric = bkpt_list.FindBreakpointByID(bp_id);
57581ad6265SDimitry Andric // Note, VerifyBreakpointOrLocationIDs checks for existence, so we
57681ad6265SDimitry Andric // don't need to do it again here.
57781ad6265SDimitry Andric if (bp_sp->IsEnabled()) {
57881ad6265SDimitry Andric if (loc_id == LLDB_INVALID_BREAK_ID) {
57981ad6265SDimitry Andric // A breakpoint (without location) was specified. Make sure that
58081ad6265SDimitry Andric // at least one of the locations is enabled.
58181ad6265SDimitry Andric size_t num_locations = bp_sp->GetNumLocations();
58281ad6265SDimitry Andric for (size_t loc_idx = 0; loc_idx < num_locations; loc_idx++) {
58381ad6265SDimitry Andric BreakpointLocationSP loc_sp
58481ad6265SDimitry Andric = bp_sp->GetLocationAtIndex(loc_idx);
58581ad6265SDimitry Andric if (loc_sp->IsEnabled()) {
58681ad6265SDimitry Andric any_enabled = true;
58781ad6265SDimitry Andric break;
58881ad6265SDimitry Andric }
58981ad6265SDimitry Andric }
59081ad6265SDimitry Andric } else {
59181ad6265SDimitry Andric // A location was specified, check if it was enabled:
59281ad6265SDimitry Andric BreakpointLocationSP loc_sp = bp_sp->FindLocationByID(loc_id);
59381ad6265SDimitry Andric if (loc_sp->IsEnabled())
59481ad6265SDimitry Andric any_enabled = true;
59581ad6265SDimitry Andric }
59681ad6265SDimitry Andric
59781ad6265SDimitry Andric // Then sort the bp & bp.loc entries for later use:
59881ad6265SDimitry Andric if (bkpt_id.GetLocationID() == LLDB_INVALID_BREAK_ID)
59981ad6265SDimitry Andric bkpts_seen.insert(bkpt_id.GetBreakpointID());
60081ad6265SDimitry Andric else {
60181ad6265SDimitry Andric bkpts_with_locs_seen.insert(bkpt_id.GetBreakpointID());
60281ad6265SDimitry Andric with_locs.AddBreakpointID(bkpt_id);
60381ad6265SDimitry Andric }
60481ad6265SDimitry Andric }
60581ad6265SDimitry Andric }
60681ad6265SDimitry Andric // Do all the error checking here so once we start disabling we don't
60781ad6265SDimitry Andric // have to back out half-way through.
60881ad6265SDimitry Andric
60981ad6265SDimitry Andric // Make sure at least one of the specified breakpoints is enabled.
61081ad6265SDimitry Andric if (!any_enabled) {
61181ad6265SDimitry Andric result.AppendError("at least one of the continue-to breakpoints must "
61281ad6265SDimitry Andric "be enabled.");
613*c9157d92SDimitry Andric return;
61481ad6265SDimitry Andric }
61581ad6265SDimitry Andric
61681ad6265SDimitry Andric // Also, if you specify BOTH a breakpoint and one of it's locations,
61781ad6265SDimitry Andric // we flag that as an error, since it won't do what you expect, the
61881ad6265SDimitry Andric // breakpoint directive will mean "run to all locations", which is not
61981ad6265SDimitry Andric // what the location directive means...
62081ad6265SDimitry Andric for (break_id_t bp_id : bkpts_with_locs_seen) {
62181ad6265SDimitry Andric if (bkpts_seen.count(bp_id)) {
62281ad6265SDimitry Andric result.AppendErrorWithFormatv("can't specify both a breakpoint and "
62381ad6265SDimitry Andric "one of its locations: {0}", bp_id);
62481ad6265SDimitry Andric }
62581ad6265SDimitry Andric }
62681ad6265SDimitry Andric
62781ad6265SDimitry Andric // Now go through the breakpoints in the target, disabling all the ones
62881ad6265SDimitry Andric // that the user didn't mention:
62981ad6265SDimitry Andric for (BreakpointSP bp_sp : bkpt_list.Breakpoints()) {
63081ad6265SDimitry Andric break_id_t bp_id = bp_sp->GetID();
63181ad6265SDimitry Andric // Handle the case where no locations were specified. Note we don't
63281ad6265SDimitry Andric // have to worry about the case where a breakpoint and one of its
63381ad6265SDimitry Andric // locations are both in the lists, we've already disallowed that.
63481ad6265SDimitry Andric if (!bkpts_with_locs_seen.count(bp_id)) {
63581ad6265SDimitry Andric if (!bkpts_seen.count(bp_id) && bp_sp->IsEnabled()) {
63681ad6265SDimitry Andric bkpts_disabled.push_back(bp_id);
63781ad6265SDimitry Andric bp_sp->SetEnabled(false);
63881ad6265SDimitry Andric }
63981ad6265SDimitry Andric continue;
64081ad6265SDimitry Andric }
64181ad6265SDimitry Andric // Next, handle the case where a location was specified:
64281ad6265SDimitry Andric // Run through all the locations of this breakpoint and disable
64381ad6265SDimitry Andric // the ones that aren't on our "with locations" BreakpointID list:
64481ad6265SDimitry Andric size_t num_locations = bp_sp->GetNumLocations();
64581ad6265SDimitry Andric BreakpointID tmp_id(bp_id, LLDB_INVALID_BREAK_ID);
64681ad6265SDimitry Andric for (size_t loc_idx = 0; loc_idx < num_locations; loc_idx++) {
64781ad6265SDimitry Andric BreakpointLocationSP loc_sp = bp_sp->GetLocationAtIndex(loc_idx);
64881ad6265SDimitry Andric tmp_id.SetBreakpointLocationID(loc_idx);
64981ad6265SDimitry Andric size_t position = 0;
65081ad6265SDimitry Andric if (!with_locs.FindBreakpointID(tmp_id, &position)
65181ad6265SDimitry Andric && loc_sp->IsEnabled()) {
65281ad6265SDimitry Andric locs_disabled.push_back(tmp_id);
65381ad6265SDimitry Andric loc_sp->SetEnabled(false);
65481ad6265SDimitry Andric }
65581ad6265SDimitry Andric }
65681ad6265SDimitry Andric }
65781ad6265SDimitry Andric }
65881ad6265SDimitry Andric
6590b57cec5SDimitry Andric { // Scope for thread list mutex:
6600b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(
6610b57cec5SDimitry Andric process->GetThreadList().GetMutex());
6620b57cec5SDimitry Andric const uint32_t num_threads = process->GetThreadList().GetSize();
6630b57cec5SDimitry Andric
6640b57cec5SDimitry Andric // Set the actions that the threads should each take when resuming
6650b57cec5SDimitry Andric for (uint32_t idx = 0; idx < num_threads; ++idx) {
6660b57cec5SDimitry Andric const bool override_suspend = false;
6670b57cec5SDimitry Andric process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState(
6680b57cec5SDimitry Andric eStateRunning, override_suspend);
6690b57cec5SDimitry Andric }
6700b57cec5SDimitry Andric }
6710b57cec5SDimitry Andric
6720b57cec5SDimitry Andric const uint32_t iohandler_id = process->GetIOHandlerID();
6730b57cec5SDimitry Andric
6740b57cec5SDimitry Andric StreamString stream;
6750b57cec5SDimitry Andric Status error;
67681ad6265SDimitry Andric // For now we can only do -b with synchronous:
67781ad6265SDimitry Andric bool old_sync = GetDebugger().GetAsyncExecution();
67881ad6265SDimitry Andric
67981ad6265SDimitry Andric if (run_to_bkpt_ids.GetSize() != 0) {
68081ad6265SDimitry Andric GetDebugger().SetAsyncExecution(false);
68181ad6265SDimitry Andric synchronous_execution = true;
68281ad6265SDimitry Andric }
6830b57cec5SDimitry Andric if (synchronous_execution)
6840b57cec5SDimitry Andric error = process->ResumeSynchronous(&stream);
6850b57cec5SDimitry Andric else
6860b57cec5SDimitry Andric error = process->Resume();
6870b57cec5SDimitry Andric
68881ad6265SDimitry Andric if (run_to_bkpt_ids.GetSize() != 0) {
68981ad6265SDimitry Andric GetDebugger().SetAsyncExecution(old_sync);
69081ad6265SDimitry Andric }
69181ad6265SDimitry Andric
69281ad6265SDimitry Andric // Now re-enable the breakpoints we disabled:
69381ad6265SDimitry Andric BreakpointList &bkpt_list = target->GetBreakpointList();
69481ad6265SDimitry Andric for (break_id_t bp_id : bkpts_disabled) {
69581ad6265SDimitry Andric BreakpointSP bp_sp = bkpt_list.FindBreakpointByID(bp_id);
69681ad6265SDimitry Andric if (bp_sp)
69781ad6265SDimitry Andric bp_sp->SetEnabled(true);
69881ad6265SDimitry Andric }
69981ad6265SDimitry Andric for (const BreakpointID &bkpt_id : locs_disabled) {
70081ad6265SDimitry Andric BreakpointSP bp_sp
70181ad6265SDimitry Andric = bkpt_list.FindBreakpointByID(bkpt_id.GetBreakpointID());
70281ad6265SDimitry Andric if (bp_sp) {
70381ad6265SDimitry Andric BreakpointLocationSP loc_sp
70481ad6265SDimitry Andric = bp_sp->FindLocationByID(bkpt_id.GetLocationID());
70581ad6265SDimitry Andric if (loc_sp)
70681ad6265SDimitry Andric loc_sp->SetEnabled(true);
70781ad6265SDimitry Andric }
70881ad6265SDimitry Andric }
70981ad6265SDimitry Andric
7100b57cec5SDimitry Andric if (error.Success()) {
7110b57cec5SDimitry Andric // There is a race condition where this thread will return up the call
7120b57cec5SDimitry Andric // stack to the main command handler and show an (lldb) prompt before
7130b57cec5SDimitry Andric // HandlePrivateEvent (from PrivateStateThread) has a chance to call
7140b57cec5SDimitry Andric // PushProcessIOHandler().
7150b57cec5SDimitry Andric process->SyncIOHandler(iohandler_id, std::chrono::seconds(2));
7160b57cec5SDimitry Andric
7170b57cec5SDimitry Andric result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n",
7180b57cec5SDimitry Andric process->GetID());
7190b57cec5SDimitry Andric if (synchronous_execution) {
7200b57cec5SDimitry Andric // If any state changed events had anything to say, add that to the
7210b57cec5SDimitry Andric // result
7220b57cec5SDimitry Andric result.AppendMessage(stream.GetString());
7230b57cec5SDimitry Andric
7240b57cec5SDimitry Andric result.SetDidChangeProcessState(true);
7250b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult);
7260b57cec5SDimitry Andric } else {
7270b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessContinuingNoResult);
7280b57cec5SDimitry Andric }
7290b57cec5SDimitry Andric } else {
7300b57cec5SDimitry Andric result.AppendErrorWithFormat("Failed to resume process: %s.\n",
7310b57cec5SDimitry Andric error.AsCString());
7320b57cec5SDimitry Andric }
7330b57cec5SDimitry Andric } else {
7340b57cec5SDimitry Andric result.AppendErrorWithFormat(
7350b57cec5SDimitry Andric "Process cannot be continued from its current state (%s).\n",
7360b57cec5SDimitry Andric StateAsCString(state));
7370b57cec5SDimitry Andric }
7380b57cec5SDimitry Andric }
7390b57cec5SDimitry Andric
GetOptions()7400b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; }
7410b57cec5SDimitry Andric
7420b57cec5SDimitry Andric CommandOptions m_options;
7430b57cec5SDimitry Andric };
7440b57cec5SDimitry Andric
7450b57cec5SDimitry Andric // CommandObjectProcessDetach
7469dba64beSDimitry Andric #define LLDB_OPTIONS_process_detach
7479dba64beSDimitry Andric #include "CommandOptions.inc"
7480b57cec5SDimitry Andric
7490b57cec5SDimitry Andric #pragma mark CommandObjectProcessDetach
7500b57cec5SDimitry Andric
7510b57cec5SDimitry Andric class CommandObjectProcessDetach : public CommandObjectParsed {
7520b57cec5SDimitry Andric public:
7530b57cec5SDimitry Andric class CommandOptions : public Options {
7540b57cec5SDimitry Andric public:
CommandOptions()75504eeddc0SDimitry Andric CommandOptions() { OptionParsingStarting(nullptr); }
7560b57cec5SDimitry Andric
7570b57cec5SDimitry Andric ~CommandOptions() override = default;
7580b57cec5SDimitry Andric
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)7590b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
7600b57cec5SDimitry Andric ExecutionContext *execution_context) override {
7610b57cec5SDimitry Andric Status error;
7620b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val;
7630b57cec5SDimitry Andric
7640b57cec5SDimitry Andric switch (short_option) {
7650b57cec5SDimitry Andric case 's':
7660b57cec5SDimitry Andric bool tmp_result;
7670b57cec5SDimitry Andric bool success;
7680b57cec5SDimitry Andric tmp_result = OptionArgParser::ToBoolean(option_arg, false, &success);
7690b57cec5SDimitry Andric if (!success)
7700b57cec5SDimitry Andric error.SetErrorStringWithFormat("invalid boolean option: \"%s\"",
7710b57cec5SDimitry Andric option_arg.str().c_str());
7720b57cec5SDimitry Andric else {
7730b57cec5SDimitry Andric if (tmp_result)
7740b57cec5SDimitry Andric m_keep_stopped = eLazyBoolYes;
7750b57cec5SDimitry Andric else
7760b57cec5SDimitry Andric m_keep_stopped = eLazyBoolNo;
7770b57cec5SDimitry Andric }
7780b57cec5SDimitry Andric break;
7790b57cec5SDimitry Andric default:
7809dba64beSDimitry Andric llvm_unreachable("Unimplemented option");
7810b57cec5SDimitry Andric }
7820b57cec5SDimitry Andric return error;
7830b57cec5SDimitry Andric }
7840b57cec5SDimitry Andric
OptionParsingStarting(ExecutionContext * execution_context)7850b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
7860b57cec5SDimitry Andric m_keep_stopped = eLazyBoolCalculate;
7870b57cec5SDimitry Andric }
7880b57cec5SDimitry Andric
GetDefinitions()7890b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
790bdd1243dSDimitry Andric return llvm::ArrayRef(g_process_detach_options);
7910b57cec5SDimitry Andric }
7920b57cec5SDimitry Andric
7930b57cec5SDimitry Andric // Instance variables to hold the values for command options.
7940b57cec5SDimitry Andric LazyBool m_keep_stopped;
7950b57cec5SDimitry Andric };
7960b57cec5SDimitry Andric
CommandObjectProcessDetach(CommandInterpreter & interpreter)7970b57cec5SDimitry Andric CommandObjectProcessDetach(CommandInterpreter &interpreter)
7980b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process detach",
7990b57cec5SDimitry Andric "Detach from the current target process.",
8000b57cec5SDimitry Andric "process detach",
8010b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock |
80204eeddc0SDimitry Andric eCommandProcessMustBeLaunched) {}
8030b57cec5SDimitry Andric
8040b57cec5SDimitry Andric ~CommandObjectProcessDetach() override = default;
8050b57cec5SDimitry Andric
GetOptions()8060b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; }
8070b57cec5SDimitry Andric
8080b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)809*c9157d92SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
8100b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr();
8110b57cec5SDimitry Andric // FIXME: This will be a Command Option:
8120b57cec5SDimitry Andric bool keep_stopped;
8130b57cec5SDimitry Andric if (m_options.m_keep_stopped == eLazyBoolCalculate) {
8140b57cec5SDimitry Andric // Check the process default:
8150b57cec5SDimitry Andric keep_stopped = process->GetDetachKeepsStopped();
8160b57cec5SDimitry Andric } else if (m_options.m_keep_stopped == eLazyBoolYes)
8170b57cec5SDimitry Andric keep_stopped = true;
8180b57cec5SDimitry Andric else
8190b57cec5SDimitry Andric keep_stopped = false;
8200b57cec5SDimitry Andric
8210b57cec5SDimitry Andric Status error(process->Detach(keep_stopped));
8220b57cec5SDimitry Andric if (error.Success()) {
8230b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult);
8240b57cec5SDimitry Andric } else {
8250b57cec5SDimitry Andric result.AppendErrorWithFormat("Detach failed: %s\n", error.AsCString());
8260b57cec5SDimitry Andric }
8270b57cec5SDimitry Andric }
8280b57cec5SDimitry Andric
8290b57cec5SDimitry Andric CommandOptions m_options;
8300b57cec5SDimitry Andric };
8310b57cec5SDimitry Andric
8320b57cec5SDimitry Andric // CommandObjectProcessConnect
8339dba64beSDimitry Andric #define LLDB_OPTIONS_process_connect
8349dba64beSDimitry Andric #include "CommandOptions.inc"
8350b57cec5SDimitry Andric
8360b57cec5SDimitry Andric #pragma mark CommandObjectProcessConnect
8370b57cec5SDimitry Andric
8380b57cec5SDimitry Andric class CommandObjectProcessConnect : public CommandObjectParsed {
8390b57cec5SDimitry Andric public:
8400b57cec5SDimitry Andric class CommandOptions : public Options {
8410b57cec5SDimitry Andric public:
CommandOptions()84204eeddc0SDimitry Andric CommandOptions() {
8430b57cec5SDimitry Andric // Keep default values of all options in one place: OptionParsingStarting
8440b57cec5SDimitry Andric // ()
8450b57cec5SDimitry Andric OptionParsingStarting(nullptr);
8460b57cec5SDimitry Andric }
8470b57cec5SDimitry Andric
8480b57cec5SDimitry Andric ~CommandOptions() override = default;
8490b57cec5SDimitry Andric
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)8500b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
8510b57cec5SDimitry Andric ExecutionContext *execution_context) override {
8520b57cec5SDimitry Andric Status error;
8530b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val;
8540b57cec5SDimitry Andric
8550b57cec5SDimitry Andric switch (short_option) {
8560b57cec5SDimitry Andric case 'p':
8575ffd83dbSDimitry Andric plugin_name.assign(std::string(option_arg));
8580b57cec5SDimitry Andric break;
8590b57cec5SDimitry Andric
8600b57cec5SDimitry Andric default:
8619dba64beSDimitry Andric llvm_unreachable("Unimplemented option");
8620b57cec5SDimitry Andric }
8630b57cec5SDimitry Andric return error;
8640b57cec5SDimitry Andric }
8650b57cec5SDimitry Andric
OptionParsingStarting(ExecutionContext * execution_context)8660b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
8670b57cec5SDimitry Andric plugin_name.clear();
8680b57cec5SDimitry Andric }
8690b57cec5SDimitry Andric
GetDefinitions()8700b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
871bdd1243dSDimitry Andric return llvm::ArrayRef(g_process_connect_options);
8720b57cec5SDimitry Andric }
8730b57cec5SDimitry Andric
8740b57cec5SDimitry Andric // Instance variables to hold the values for command options.
8750b57cec5SDimitry Andric
8760b57cec5SDimitry Andric std::string plugin_name;
8770b57cec5SDimitry Andric };
8780b57cec5SDimitry Andric
CommandObjectProcessConnect(CommandInterpreter & interpreter)8790b57cec5SDimitry Andric CommandObjectProcessConnect(CommandInterpreter &interpreter)
8800b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process connect",
8810b57cec5SDimitry Andric "Connect to a remote debug service.",
88281ad6265SDimitry Andric "process connect <remote-url>", 0) {
88381ad6265SDimitry Andric CommandArgumentData connect_arg{eArgTypeConnectURL, eArgRepeatPlain};
88481ad6265SDimitry Andric m_arguments.push_back({connect_arg});
88581ad6265SDimitry Andric }
8860b57cec5SDimitry Andric
8870b57cec5SDimitry Andric ~CommandObjectProcessConnect() override = default;
8880b57cec5SDimitry Andric
GetOptions()8890b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; }
8900b57cec5SDimitry Andric
8910b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)892*c9157d92SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
8930b57cec5SDimitry Andric if (command.GetArgumentCount() != 1) {
8940b57cec5SDimitry Andric result.AppendErrorWithFormat(
8950b57cec5SDimitry Andric "'%s' takes exactly one argument:\nUsage: %s\n", m_cmd_name.c_str(),
8960b57cec5SDimitry Andric m_cmd_syntax.c_str());
897*c9157d92SDimitry Andric return;
8980b57cec5SDimitry Andric }
8990b57cec5SDimitry Andric
9000b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr();
9010b57cec5SDimitry Andric if (process && process->IsAlive()) {
9020b57cec5SDimitry Andric result.AppendErrorWithFormat(
9030b57cec5SDimitry Andric "Process %" PRIu64
9040b57cec5SDimitry Andric " is currently being debugged, kill the process before connecting.\n",
9050b57cec5SDimitry Andric process->GetID());
906*c9157d92SDimitry Andric return;
9070b57cec5SDimitry Andric }
9080b57cec5SDimitry Andric
9090b57cec5SDimitry Andric const char *plugin_name = nullptr;
9100b57cec5SDimitry Andric if (!m_options.plugin_name.empty())
9110b57cec5SDimitry Andric plugin_name = m_options.plugin_name.c_str();
9120b57cec5SDimitry Andric
9130b57cec5SDimitry Andric Status error;
9140b57cec5SDimitry Andric Debugger &debugger = GetDebugger();
9150b57cec5SDimitry Andric PlatformSP platform_sp = m_interpreter.GetPlatform(true);
9165ffd83dbSDimitry Andric ProcessSP process_sp =
9175ffd83dbSDimitry Andric debugger.GetAsyncExecution()
9185ffd83dbSDimitry Andric ? platform_sp->ConnectProcess(
9190b57cec5SDimitry Andric command.GetArgumentAtIndex(0), plugin_name, debugger,
9205ffd83dbSDimitry Andric debugger.GetSelectedTarget().get(), error)
9215ffd83dbSDimitry Andric : platform_sp->ConnectProcessSynchronous(
9225ffd83dbSDimitry Andric command.GetArgumentAtIndex(0), plugin_name, debugger,
9235ffd83dbSDimitry Andric result.GetOutputStream(), debugger.GetSelectedTarget().get(),
9245ffd83dbSDimitry Andric error);
9250b57cec5SDimitry Andric if (error.Fail() || process_sp == nullptr) {
9260b57cec5SDimitry Andric result.AppendError(error.AsCString("Error connecting to the process"));
9270b57cec5SDimitry Andric }
9280b57cec5SDimitry Andric }
9290b57cec5SDimitry Andric
9300b57cec5SDimitry Andric CommandOptions m_options;
9310b57cec5SDimitry Andric };
9320b57cec5SDimitry Andric
9330b57cec5SDimitry Andric // CommandObjectProcessPlugin
9340b57cec5SDimitry Andric #pragma mark CommandObjectProcessPlugin
9350b57cec5SDimitry Andric
9360b57cec5SDimitry Andric class CommandObjectProcessPlugin : public CommandObjectProxy {
9370b57cec5SDimitry Andric public:
CommandObjectProcessPlugin(CommandInterpreter & interpreter)9380b57cec5SDimitry Andric CommandObjectProcessPlugin(CommandInterpreter &interpreter)
9390b57cec5SDimitry Andric : CommandObjectProxy(
9400b57cec5SDimitry Andric interpreter, "process plugin",
9410b57cec5SDimitry Andric "Send a custom command to the current target process plug-in.",
9420b57cec5SDimitry Andric "process plugin <args>", 0) {}
9430b57cec5SDimitry Andric
9440b57cec5SDimitry Andric ~CommandObjectProcessPlugin() override = default;
9450b57cec5SDimitry Andric
GetProxyCommandObject()9460b57cec5SDimitry Andric CommandObject *GetProxyCommandObject() override {
9470b57cec5SDimitry Andric Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
9480b57cec5SDimitry Andric if (process)
9490b57cec5SDimitry Andric return process->GetPluginCommandObject();
9500b57cec5SDimitry Andric return nullptr;
9510b57cec5SDimitry Andric }
9520b57cec5SDimitry Andric };
9530b57cec5SDimitry Andric
9540b57cec5SDimitry Andric // CommandObjectProcessLoad
9559dba64beSDimitry Andric #define LLDB_OPTIONS_process_load
9569dba64beSDimitry Andric #include "CommandOptions.inc"
9570b57cec5SDimitry Andric
9580b57cec5SDimitry Andric #pragma mark CommandObjectProcessLoad
9590b57cec5SDimitry Andric
9600b57cec5SDimitry Andric class CommandObjectProcessLoad : public CommandObjectParsed {
9610b57cec5SDimitry Andric public:
9620b57cec5SDimitry Andric class CommandOptions : public Options {
9630b57cec5SDimitry Andric public:
CommandOptions()96404eeddc0SDimitry Andric CommandOptions() {
9650b57cec5SDimitry Andric // Keep default values of all options in one place: OptionParsingStarting
9660b57cec5SDimitry Andric // ()
9670b57cec5SDimitry Andric OptionParsingStarting(nullptr);
9680b57cec5SDimitry Andric }
9690b57cec5SDimitry Andric
9700b57cec5SDimitry Andric ~CommandOptions() override = default;
9710b57cec5SDimitry Andric
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)9720b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
9730b57cec5SDimitry Andric ExecutionContext *execution_context) override {
9740b57cec5SDimitry Andric Status error;
9750b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val;
9760b57cec5SDimitry Andric switch (short_option) {
9770b57cec5SDimitry Andric case 'i':
9780b57cec5SDimitry Andric do_install = true;
9790b57cec5SDimitry Andric if (!option_arg.empty())
9800b57cec5SDimitry Andric install_path.SetFile(option_arg, FileSpec::Style::native);
9810b57cec5SDimitry Andric break;
9820b57cec5SDimitry Andric default:
9839dba64beSDimitry Andric llvm_unreachable("Unimplemented option");
9840b57cec5SDimitry Andric }
9850b57cec5SDimitry Andric return error;
9860b57cec5SDimitry Andric }
9870b57cec5SDimitry Andric
OptionParsingStarting(ExecutionContext * execution_context)9880b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
9890b57cec5SDimitry Andric do_install = false;
9900b57cec5SDimitry Andric install_path.Clear();
9910b57cec5SDimitry Andric }
9920b57cec5SDimitry Andric
GetDefinitions()9930b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
994bdd1243dSDimitry Andric return llvm::ArrayRef(g_process_load_options);
9950b57cec5SDimitry Andric }
9960b57cec5SDimitry Andric
9970b57cec5SDimitry Andric // Instance variables to hold the values for command options.
9980b57cec5SDimitry Andric bool do_install;
9990b57cec5SDimitry Andric FileSpec install_path;
10000b57cec5SDimitry Andric };
10010b57cec5SDimitry Andric
CommandObjectProcessLoad(CommandInterpreter & interpreter)10020b57cec5SDimitry Andric CommandObjectProcessLoad(CommandInterpreter &interpreter)
10030b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process load",
10040b57cec5SDimitry Andric "Load a shared library into the current process.",
10050b57cec5SDimitry Andric "process load <filename> [<filename> ...]",
10060b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock |
10070b57cec5SDimitry Andric eCommandProcessMustBeLaunched |
100881ad6265SDimitry Andric eCommandProcessMustBePaused) {
100981ad6265SDimitry Andric CommandArgumentData file_arg{eArgTypePath, eArgRepeatPlus};
101081ad6265SDimitry Andric m_arguments.push_back({file_arg});
101181ad6265SDimitry Andric }
10120b57cec5SDimitry Andric
10130b57cec5SDimitry Andric ~CommandObjectProcessLoad() override = default;
10140b57cec5SDimitry Andric
1015e8d8bef9SDimitry Andric void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)1016e8d8bef9SDimitry Andric HandleArgumentCompletion(CompletionRequest &request,
1017e8d8bef9SDimitry Andric OptionElementVector &opt_element_vector) override {
1018e8d8bef9SDimitry Andric if (!m_exe_ctx.HasProcessScope())
1019e8d8bef9SDimitry Andric return;
1020e8d8bef9SDimitry Andric
1021fe013be4SDimitry Andric lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
1022fe013be4SDimitry Andric GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr);
1023e8d8bef9SDimitry Andric }
1024e8d8bef9SDimitry Andric
GetOptions()10250b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; }
10260b57cec5SDimitry Andric
10270b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)1028*c9157d92SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
10290b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr();
10300b57cec5SDimitry Andric
10310b57cec5SDimitry Andric for (auto &entry : command.entries()) {
10320b57cec5SDimitry Andric Status error;
10330b57cec5SDimitry Andric PlatformSP platform = process->GetTarget().GetPlatform();
10349dba64beSDimitry Andric llvm::StringRef image_path = entry.ref();
10350b57cec5SDimitry Andric uint32_t image_token = LLDB_INVALID_IMAGE_TOKEN;
10360b57cec5SDimitry Andric
10370b57cec5SDimitry Andric if (!m_options.do_install) {
10380b57cec5SDimitry Andric FileSpec image_spec(image_path);
10390b57cec5SDimitry Andric platform->ResolveRemotePath(image_spec, image_spec);
10400b57cec5SDimitry Andric image_token =
10410b57cec5SDimitry Andric platform->LoadImage(process, FileSpec(), image_spec, error);
10420b57cec5SDimitry Andric } else if (m_options.install_path) {
10430b57cec5SDimitry Andric FileSpec image_spec(image_path);
10440b57cec5SDimitry Andric FileSystem::Instance().Resolve(image_spec);
10450b57cec5SDimitry Andric platform->ResolveRemotePath(m_options.install_path,
10460b57cec5SDimitry Andric m_options.install_path);
10470b57cec5SDimitry Andric image_token = platform->LoadImage(process, image_spec,
10480b57cec5SDimitry Andric m_options.install_path, error);
10490b57cec5SDimitry Andric } else {
10500b57cec5SDimitry Andric FileSpec image_spec(image_path);
10510b57cec5SDimitry Andric FileSystem::Instance().Resolve(image_spec);
10520b57cec5SDimitry Andric image_token =
10530b57cec5SDimitry Andric platform->LoadImage(process, image_spec, FileSpec(), error);
10540b57cec5SDimitry Andric }
10550b57cec5SDimitry Andric
10560b57cec5SDimitry Andric if (image_token != LLDB_INVALID_IMAGE_TOKEN) {
10570b57cec5SDimitry Andric result.AppendMessageWithFormat(
10580b57cec5SDimitry Andric "Loading \"%s\"...ok\nImage %u loaded.\n", image_path.str().c_str(),
10590b57cec5SDimitry Andric image_token);
10600b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult);
10610b57cec5SDimitry Andric } else {
10620b57cec5SDimitry Andric result.AppendErrorWithFormat("failed to load '%s': %s",
10630b57cec5SDimitry Andric image_path.str().c_str(),
10640b57cec5SDimitry Andric error.AsCString());
10650b57cec5SDimitry Andric }
10660b57cec5SDimitry Andric }
10670b57cec5SDimitry Andric }
10680b57cec5SDimitry Andric
10690b57cec5SDimitry Andric CommandOptions m_options;
10700b57cec5SDimitry Andric };
10710b57cec5SDimitry Andric
10720b57cec5SDimitry Andric // CommandObjectProcessUnload
10730b57cec5SDimitry Andric #pragma mark CommandObjectProcessUnload
10740b57cec5SDimitry Andric
10750b57cec5SDimitry Andric class CommandObjectProcessUnload : public CommandObjectParsed {
10760b57cec5SDimitry Andric public:
CommandObjectProcessUnload(CommandInterpreter & interpreter)10770b57cec5SDimitry Andric CommandObjectProcessUnload(CommandInterpreter &interpreter)
10780b57cec5SDimitry Andric : CommandObjectParsed(
10790b57cec5SDimitry Andric interpreter, "process unload",
10800b57cec5SDimitry Andric "Unload a shared library from the current process using the index "
10810b57cec5SDimitry Andric "returned by a previous call to \"process load\".",
10820b57cec5SDimitry Andric "process unload <index>",
10830b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock |
108481ad6265SDimitry Andric eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {
108581ad6265SDimitry Andric CommandArgumentData load_idx_arg{eArgTypeUnsignedInteger, eArgRepeatPlain};
108681ad6265SDimitry Andric m_arguments.push_back({load_idx_arg});
108781ad6265SDimitry Andric }
10880b57cec5SDimitry Andric
10890b57cec5SDimitry Andric ~CommandObjectProcessUnload() override = default;
10900b57cec5SDimitry Andric
1091e8d8bef9SDimitry Andric void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)1092e8d8bef9SDimitry Andric HandleArgumentCompletion(CompletionRequest &request,
1093e8d8bef9SDimitry Andric OptionElementVector &opt_element_vector) override {
1094e8d8bef9SDimitry Andric
1095e8d8bef9SDimitry Andric if (request.GetCursorIndex() || !m_exe_ctx.HasProcessScope())
1096e8d8bef9SDimitry Andric return;
1097e8d8bef9SDimitry Andric
1098e8d8bef9SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr();
1099e8d8bef9SDimitry Andric
1100e8d8bef9SDimitry Andric const std::vector<lldb::addr_t> &tokens = process->GetImageTokens();
1101e8d8bef9SDimitry Andric const size_t token_num = tokens.size();
1102e8d8bef9SDimitry Andric for (size_t i = 0; i < token_num; ++i) {
1103e8d8bef9SDimitry Andric if (tokens[i] == LLDB_INVALID_IMAGE_TOKEN)
1104e8d8bef9SDimitry Andric continue;
1105e8d8bef9SDimitry Andric request.TryCompleteCurrentArg(std::to_string(i));
1106e8d8bef9SDimitry Andric }
1107e8d8bef9SDimitry Andric }
1108e8d8bef9SDimitry Andric
11090b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)1110*c9157d92SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
11110b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr();
11120b57cec5SDimitry Andric
11130b57cec5SDimitry Andric for (auto &entry : command.entries()) {
11140b57cec5SDimitry Andric uint32_t image_token;
11159dba64beSDimitry Andric if (entry.ref().getAsInteger(0, image_token)) {
11160b57cec5SDimitry Andric result.AppendErrorWithFormat("invalid image index argument '%s'",
11179dba64beSDimitry Andric entry.ref().str().c_str());
11180b57cec5SDimitry Andric break;
11190b57cec5SDimitry Andric } else {
11200b57cec5SDimitry Andric Status error(process->GetTarget().GetPlatform()->UnloadImage(
11210b57cec5SDimitry Andric process, image_token));
11220b57cec5SDimitry Andric if (error.Success()) {
11230b57cec5SDimitry Andric result.AppendMessageWithFormat(
11240b57cec5SDimitry Andric "Unloading shared library with index %u...ok\n", image_token);
11250b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult);
11260b57cec5SDimitry Andric } else {
11270b57cec5SDimitry Andric result.AppendErrorWithFormat("failed to unload image: %s",
11280b57cec5SDimitry Andric error.AsCString());
11290b57cec5SDimitry Andric break;
11300b57cec5SDimitry Andric }
11310b57cec5SDimitry Andric }
11320b57cec5SDimitry Andric }
11330b57cec5SDimitry Andric }
11340b57cec5SDimitry Andric };
11350b57cec5SDimitry Andric
11360b57cec5SDimitry Andric // CommandObjectProcessSignal
11370b57cec5SDimitry Andric #pragma mark CommandObjectProcessSignal
11380b57cec5SDimitry Andric
11390b57cec5SDimitry Andric class CommandObjectProcessSignal : public CommandObjectParsed {
11400b57cec5SDimitry Andric public:
CommandObjectProcessSignal(CommandInterpreter & interpreter)11410b57cec5SDimitry Andric CommandObjectProcessSignal(CommandInterpreter &interpreter)
1142480093f4SDimitry Andric : CommandObjectParsed(
1143480093f4SDimitry Andric interpreter, "process signal",
1144480093f4SDimitry Andric "Send a UNIX signal to the current target process.", nullptr,
1145480093f4SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock) {
11460b57cec5SDimitry Andric CommandArgumentEntry arg;
11470b57cec5SDimitry Andric CommandArgumentData signal_arg;
11480b57cec5SDimitry Andric
11490b57cec5SDimitry Andric // Define the first (and only) variant of this arg.
11500b57cec5SDimitry Andric signal_arg.arg_type = eArgTypeUnixSignal;
11510b57cec5SDimitry Andric signal_arg.arg_repetition = eArgRepeatPlain;
11520b57cec5SDimitry Andric
11530b57cec5SDimitry Andric // There is only one variant this argument could be; put it into the
11540b57cec5SDimitry Andric // argument entry.
11550b57cec5SDimitry Andric arg.push_back(signal_arg);
11560b57cec5SDimitry Andric
11570b57cec5SDimitry Andric // Push the data for the first argument into the m_arguments vector.
11580b57cec5SDimitry Andric m_arguments.push_back(arg);
11590b57cec5SDimitry Andric }
11600b57cec5SDimitry Andric
11610b57cec5SDimitry Andric ~CommandObjectProcessSignal() override = default;
11620b57cec5SDimitry Andric
11635ffd83dbSDimitry Andric void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)11645ffd83dbSDimitry Andric HandleArgumentCompletion(CompletionRequest &request,
11655ffd83dbSDimitry Andric OptionElementVector &opt_element_vector) override {
11665ffd83dbSDimitry Andric if (!m_exe_ctx.HasProcessScope() || request.GetCursorIndex() != 0)
11675ffd83dbSDimitry Andric return;
11685ffd83dbSDimitry Andric
11695ffd83dbSDimitry Andric UnixSignalsSP signals = m_exe_ctx.GetProcessPtr()->GetUnixSignals();
11705ffd83dbSDimitry Andric int signo = signals->GetFirstSignalNumber();
11715ffd83dbSDimitry Andric while (signo != LLDB_INVALID_SIGNAL_NUMBER) {
1172*c9157d92SDimitry Andric request.TryCompleteCurrentArg(signals->GetSignalAsStringRef(signo));
11735ffd83dbSDimitry Andric signo = signals->GetNextSignalNumber(signo);
11745ffd83dbSDimitry Andric }
11755ffd83dbSDimitry Andric }
11765ffd83dbSDimitry Andric
11770b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)1178*c9157d92SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
11790b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr();
11800b57cec5SDimitry Andric
11810b57cec5SDimitry Andric if (command.GetArgumentCount() == 1) {
11820b57cec5SDimitry Andric int signo = LLDB_INVALID_SIGNAL_NUMBER;
11830b57cec5SDimitry Andric
11840b57cec5SDimitry Andric const char *signal_name = command.GetArgumentAtIndex(0);
11855ffd83dbSDimitry Andric if (::isxdigit(signal_name[0])) {
11865ffd83dbSDimitry Andric if (!llvm::to_integer(signal_name, signo))
11875ffd83dbSDimitry Andric signo = LLDB_INVALID_SIGNAL_NUMBER;
11885ffd83dbSDimitry Andric } else
11890b57cec5SDimitry Andric signo = process->GetUnixSignals()->GetSignalNumberFromName(signal_name);
11900b57cec5SDimitry Andric
11910b57cec5SDimitry Andric if (signo == LLDB_INVALID_SIGNAL_NUMBER) {
11920b57cec5SDimitry Andric result.AppendErrorWithFormat("Invalid signal argument '%s'.\n",
11930b57cec5SDimitry Andric command.GetArgumentAtIndex(0));
11940b57cec5SDimitry Andric } else {
11950b57cec5SDimitry Andric Status error(process->Signal(signo));
11960b57cec5SDimitry Andric if (error.Success()) {
11970b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult);
11980b57cec5SDimitry Andric } else {
11990b57cec5SDimitry Andric result.AppendErrorWithFormat("Failed to send signal %i: %s\n", signo,
12000b57cec5SDimitry Andric error.AsCString());
12010b57cec5SDimitry Andric }
12020b57cec5SDimitry Andric }
12030b57cec5SDimitry Andric } else {
12040b57cec5SDimitry Andric result.AppendErrorWithFormat(
12050b57cec5SDimitry Andric "'%s' takes exactly one signal number argument:\nUsage: %s\n",
12060b57cec5SDimitry Andric m_cmd_name.c_str(), m_cmd_syntax.c_str());
12070b57cec5SDimitry Andric }
12080b57cec5SDimitry Andric }
12090b57cec5SDimitry Andric };
12100b57cec5SDimitry Andric
12110b57cec5SDimitry Andric // CommandObjectProcessInterrupt
12120b57cec5SDimitry Andric #pragma mark CommandObjectProcessInterrupt
12130b57cec5SDimitry Andric
12140b57cec5SDimitry Andric class CommandObjectProcessInterrupt : public CommandObjectParsed {
12150b57cec5SDimitry Andric public:
CommandObjectProcessInterrupt(CommandInterpreter & interpreter)12160b57cec5SDimitry Andric CommandObjectProcessInterrupt(CommandInterpreter &interpreter)
12170b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process interrupt",
12180b57cec5SDimitry Andric "Interrupt the current target process.",
12190b57cec5SDimitry Andric "process interrupt",
12200b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock |
12210b57cec5SDimitry Andric eCommandProcessMustBeLaunched) {}
12220b57cec5SDimitry Andric
12230b57cec5SDimitry Andric ~CommandObjectProcessInterrupt() override = default;
12240b57cec5SDimitry Andric
12250b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)1226*c9157d92SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
12270b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr();
12280b57cec5SDimitry Andric if (process == nullptr) {
12290b57cec5SDimitry Andric result.AppendError("no process to halt");
1230*c9157d92SDimitry Andric return;
12310b57cec5SDimitry Andric }
12320b57cec5SDimitry Andric
12330b57cec5SDimitry Andric bool clear_thread_plans = true;
12340b57cec5SDimitry Andric Status error(process->Halt(clear_thread_plans));
12350b57cec5SDimitry Andric if (error.Success()) {
12360b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult);
12370b57cec5SDimitry Andric } else {
12380b57cec5SDimitry Andric result.AppendErrorWithFormat("Failed to halt process: %s\n",
12390b57cec5SDimitry Andric error.AsCString());
12400b57cec5SDimitry Andric }
12410b57cec5SDimitry Andric }
12420b57cec5SDimitry Andric };
12430b57cec5SDimitry Andric
12440b57cec5SDimitry Andric // CommandObjectProcessKill
12450b57cec5SDimitry Andric #pragma mark CommandObjectProcessKill
12460b57cec5SDimitry Andric
12470b57cec5SDimitry Andric class CommandObjectProcessKill : public CommandObjectParsed {
12480b57cec5SDimitry Andric public:
CommandObjectProcessKill(CommandInterpreter & interpreter)12490b57cec5SDimitry Andric CommandObjectProcessKill(CommandInterpreter &interpreter)
12500b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process kill",
12510b57cec5SDimitry Andric "Terminate the current target process.",
12520b57cec5SDimitry Andric "process kill",
12530b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock |
12540b57cec5SDimitry Andric eCommandProcessMustBeLaunched) {}
12550b57cec5SDimitry Andric
12560b57cec5SDimitry Andric ~CommandObjectProcessKill() override = default;
12570b57cec5SDimitry Andric
12580b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)1259*c9157d92SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
12600b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr();
12610b57cec5SDimitry Andric if (process == nullptr) {
12620b57cec5SDimitry Andric result.AppendError("no process to kill");
1263*c9157d92SDimitry Andric return;
12640b57cec5SDimitry Andric }
12650b57cec5SDimitry Andric
12660b57cec5SDimitry Andric Status error(process->Destroy(true));
12670b57cec5SDimitry Andric if (error.Success()) {
12680b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult);
12690b57cec5SDimitry Andric } else {
12700b57cec5SDimitry Andric result.AppendErrorWithFormat("Failed to kill process: %s\n",
12710b57cec5SDimitry Andric error.AsCString());
12720b57cec5SDimitry Andric }
12730b57cec5SDimitry Andric }
12740b57cec5SDimitry Andric };
12750b57cec5SDimitry Andric
1276fe6060f1SDimitry Andric #define LLDB_OPTIONS_process_save_core
1277fe6060f1SDimitry Andric #include "CommandOptions.inc"
1278fe6060f1SDimitry Andric
12790b57cec5SDimitry Andric class CommandObjectProcessSaveCore : public CommandObjectParsed {
12800b57cec5SDimitry Andric public:
CommandObjectProcessSaveCore(CommandInterpreter & interpreter)12810b57cec5SDimitry Andric CommandObjectProcessSaveCore(CommandInterpreter &interpreter)
1282349cc55cSDimitry Andric : CommandObjectParsed(
1283349cc55cSDimitry Andric interpreter, "process save-core",
12840b57cec5SDimitry Andric "Save the current process as a core file using an "
12850b57cec5SDimitry Andric "appropriate file type.",
1286349cc55cSDimitry Andric "process save-core [-s corefile-style -p plugin-name] FILE",
12870b57cec5SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock |
128881ad6265SDimitry Andric eCommandProcessMustBeLaunched) {
128981ad6265SDimitry Andric CommandArgumentData file_arg{eArgTypePath, eArgRepeatPlain};
129081ad6265SDimitry Andric m_arguments.push_back({file_arg});
129181ad6265SDimitry Andric }
12920b57cec5SDimitry Andric
12930b57cec5SDimitry Andric ~CommandObjectProcessSaveCore() override = default;
12940b57cec5SDimitry Andric
GetOptions()1295fe6060f1SDimitry Andric Options *GetOptions() override { return &m_options; }
1296fe6060f1SDimitry Andric
1297fe013be4SDimitry Andric void
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)1298fe013be4SDimitry Andric HandleArgumentCompletion(CompletionRequest &request,
1299fe013be4SDimitry Andric OptionElementVector &opt_element_vector) override {
1300fe013be4SDimitry Andric CommandCompletions::InvokeCommonCompletionCallbacks(
1301fe013be4SDimitry Andric GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr);
1302fe013be4SDimitry Andric }
1303fe013be4SDimitry Andric
1304fe6060f1SDimitry Andric class CommandOptions : public Options {
1305fe6060f1SDimitry Andric public:
130681ad6265SDimitry Andric CommandOptions() = default;
1307fe6060f1SDimitry Andric
1308fe6060f1SDimitry Andric ~CommandOptions() override = default;
1309fe6060f1SDimitry Andric
GetDefinitions()1310fe6060f1SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1311bdd1243dSDimitry Andric return llvm::ArrayRef(g_process_save_core_options);
1312fe6060f1SDimitry Andric }
1313fe6060f1SDimitry Andric
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)1314fe6060f1SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1315fe6060f1SDimitry Andric ExecutionContext *execution_context) override {
1316fe6060f1SDimitry Andric const int short_option = m_getopt_table[option_idx].val;
1317fe6060f1SDimitry Andric Status error;
1318fe6060f1SDimitry Andric
1319fe6060f1SDimitry Andric switch (short_option) {
1320349cc55cSDimitry Andric case 'p':
1321349cc55cSDimitry Andric m_requested_plugin_name = option_arg.str();
1322349cc55cSDimitry Andric break;
1323fe6060f1SDimitry Andric case 's':
1324fe6060f1SDimitry Andric m_requested_save_core_style =
1325fe6060f1SDimitry Andric (lldb::SaveCoreStyle)OptionArgParser::ToOptionEnum(
1326fe6060f1SDimitry Andric option_arg, GetDefinitions()[option_idx].enum_values,
1327fe6060f1SDimitry Andric eSaveCoreUnspecified, error);
1328fe6060f1SDimitry Andric break;
1329fe6060f1SDimitry Andric default:
1330fe6060f1SDimitry Andric llvm_unreachable("Unimplemented option");
1331fe6060f1SDimitry Andric }
1332fe6060f1SDimitry Andric
1333fe6060f1SDimitry Andric return {};
1334fe6060f1SDimitry Andric }
1335fe6060f1SDimitry Andric
OptionParsingStarting(ExecutionContext * execution_context)1336fe6060f1SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
1337fe6060f1SDimitry Andric m_requested_save_core_style = eSaveCoreUnspecified;
1338349cc55cSDimitry Andric m_requested_plugin_name.clear();
1339fe6060f1SDimitry Andric }
1340fe6060f1SDimitry Andric
1341fe6060f1SDimitry Andric // Instance variables to hold the values for command options.
134281ad6265SDimitry Andric SaveCoreStyle m_requested_save_core_style = eSaveCoreUnspecified;
1343349cc55cSDimitry Andric std::string m_requested_plugin_name;
1344fe6060f1SDimitry Andric };
1345fe6060f1SDimitry Andric
13460b57cec5SDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)1347*c9157d92SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
13480b57cec5SDimitry Andric ProcessSP process_sp = m_exe_ctx.GetProcessSP();
13490b57cec5SDimitry Andric if (process_sp) {
13500b57cec5SDimitry Andric if (command.GetArgumentCount() == 1) {
13510b57cec5SDimitry Andric FileSpec output_file(command.GetArgumentAtIndex(0));
1352fe013be4SDimitry Andric FileSystem::Instance().Resolve(output_file);
1353fe6060f1SDimitry Andric SaveCoreStyle corefile_style = m_options.m_requested_save_core_style;
1354fe6060f1SDimitry Andric Status error =
1355349cc55cSDimitry Andric PluginManager::SaveCore(process_sp, output_file, corefile_style,
1356349cc55cSDimitry Andric m_options.m_requested_plugin_name);
13570b57cec5SDimitry Andric if (error.Success()) {
1358349cc55cSDimitry Andric if (corefile_style == SaveCoreStyle::eSaveCoreDirtyOnly ||
1359349cc55cSDimitry Andric corefile_style == SaveCoreStyle::eSaveCoreStackOnly) {
1360fe6060f1SDimitry Andric result.AppendMessageWithFormat(
1361349cc55cSDimitry Andric "\nModified-memory or stack-memory only corefile "
1362349cc55cSDimitry Andric "created. This corefile may \n"
1363349cc55cSDimitry Andric "not show library/framework/app binaries "
1364fe6060f1SDimitry Andric "on a different system, or when \n"
1365fe6060f1SDimitry Andric "those binaries have "
1366fe6060f1SDimitry Andric "been updated/modified. Copies are not included\n"
1367fe6060f1SDimitry Andric "in this corefile. Use --style full to include all "
1368fe6060f1SDimitry Andric "process memory.\n");
1369fe6060f1SDimitry Andric }
13700b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult);
13710b57cec5SDimitry Andric } else {
13720b57cec5SDimitry Andric result.AppendErrorWithFormat(
13730b57cec5SDimitry Andric "Failed to save core file for process: %s\n", error.AsCString());
13740b57cec5SDimitry Andric }
13750b57cec5SDimitry Andric } else {
13760b57cec5SDimitry Andric result.AppendErrorWithFormat("'%s' takes one arguments:\nUsage: %s\n",
13770b57cec5SDimitry Andric m_cmd_name.c_str(), m_cmd_syntax.c_str());
13780b57cec5SDimitry Andric }
13790b57cec5SDimitry Andric } else {
13800b57cec5SDimitry Andric result.AppendError("invalid process");
13810b57cec5SDimitry Andric }
13820b57cec5SDimitry Andric }
1383fe6060f1SDimitry Andric
1384fe6060f1SDimitry Andric CommandOptions m_options;
13850b57cec5SDimitry Andric };
13860b57cec5SDimitry Andric
13870b57cec5SDimitry Andric // CommandObjectProcessStatus
13880b57cec5SDimitry Andric #pragma mark CommandObjectProcessStatus
13895ffd83dbSDimitry Andric #define LLDB_OPTIONS_process_status
13905ffd83dbSDimitry Andric #include "CommandOptions.inc"
13910b57cec5SDimitry Andric
13920b57cec5SDimitry Andric class CommandObjectProcessStatus : public CommandObjectParsed {
13930b57cec5SDimitry Andric public:
CommandObjectProcessStatus(CommandInterpreter & interpreter)13940b57cec5SDimitry Andric CommandObjectProcessStatus(CommandInterpreter &interpreter)
13950b57cec5SDimitry Andric : CommandObjectParsed(
13960b57cec5SDimitry Andric interpreter, "process status",
13970b57cec5SDimitry Andric "Show status and stop location for the current target process.",
13980b57cec5SDimitry Andric "process status",
139904eeddc0SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock) {}
14000b57cec5SDimitry Andric
14010b57cec5SDimitry Andric ~CommandObjectProcessStatus() override = default;
14020b57cec5SDimitry Andric
GetOptions()14035ffd83dbSDimitry Andric Options *GetOptions() override { return &m_options; }
14045ffd83dbSDimitry Andric
14055ffd83dbSDimitry Andric class CommandOptions : public Options {
14065ffd83dbSDimitry Andric public:
140781ad6265SDimitry Andric CommandOptions() = default;
14085ffd83dbSDimitry Andric
14095ffd83dbSDimitry Andric ~CommandOptions() override = default;
14105ffd83dbSDimitry Andric
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)14115ffd83dbSDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
14125ffd83dbSDimitry Andric ExecutionContext *execution_context) override {
14135ffd83dbSDimitry Andric const int short_option = m_getopt_table[option_idx].val;
14145ffd83dbSDimitry Andric
14155ffd83dbSDimitry Andric switch (short_option) {
14165ffd83dbSDimitry Andric case 'v':
14175ffd83dbSDimitry Andric m_verbose = true;
14185ffd83dbSDimitry Andric break;
14195ffd83dbSDimitry Andric default:
14205ffd83dbSDimitry Andric llvm_unreachable("Unimplemented option");
14215ffd83dbSDimitry Andric }
14225ffd83dbSDimitry Andric
14235ffd83dbSDimitry Andric return {};
14245ffd83dbSDimitry Andric }
14255ffd83dbSDimitry Andric
OptionParsingStarting(ExecutionContext * execution_context)14265ffd83dbSDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
14275ffd83dbSDimitry Andric m_verbose = false;
14285ffd83dbSDimitry Andric }
14295ffd83dbSDimitry Andric
GetDefinitions()14305ffd83dbSDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1431bdd1243dSDimitry Andric return llvm::ArrayRef(g_process_status_options);
14325ffd83dbSDimitry Andric }
14335ffd83dbSDimitry Andric
14345ffd83dbSDimitry Andric // Instance variables to hold the values for command options.
1435fe6060f1SDimitry Andric bool m_verbose = false;
14365ffd83dbSDimitry Andric };
14375ffd83dbSDimitry Andric
14385ffd83dbSDimitry Andric protected:
DoExecute(Args & command,CommandReturnObject & result)1439*c9157d92SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
14400b57cec5SDimitry Andric Stream &strm = result.GetOutputStream();
14410b57cec5SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult);
14425ffd83dbSDimitry Andric
14430b57cec5SDimitry Andric // No need to check "process" for validity as eCommandRequiresProcess
14440b57cec5SDimitry Andric // ensures it is valid
14450b57cec5SDimitry Andric Process *process = m_exe_ctx.GetProcessPtr();
14460b57cec5SDimitry Andric const bool only_threads_with_stop_reason = true;
14470b57cec5SDimitry Andric const uint32_t start_frame = 0;
14480b57cec5SDimitry Andric const uint32_t num_frames = 1;
14490b57cec5SDimitry Andric const uint32_t num_frames_with_source = 1;
14500b57cec5SDimitry Andric const bool stop_format = true;
14510b57cec5SDimitry Andric process->GetStatus(strm);
14520b57cec5SDimitry Andric process->GetThreadStatus(strm, only_threads_with_stop_reason, start_frame,
14530b57cec5SDimitry Andric num_frames, num_frames_with_source, stop_format);
14545ffd83dbSDimitry Andric
14555ffd83dbSDimitry Andric if (m_options.m_verbose) {
1456fe6060f1SDimitry Andric addr_t code_mask = process->GetCodeAddressMask();
1457fe6060f1SDimitry Andric addr_t data_mask = process->GetDataAddressMask();
1458fe6060f1SDimitry Andric if (code_mask != 0) {
1459fe6060f1SDimitry Andric int bits = std::bitset<64>(~code_mask).count();
1460fe6060f1SDimitry Andric result.AppendMessageWithFormat(
1461fe6060f1SDimitry Andric "Addressable code address mask: 0x%" PRIx64 "\n", code_mask);
1462fe6060f1SDimitry Andric result.AppendMessageWithFormat(
1463fe6060f1SDimitry Andric "Addressable data address mask: 0x%" PRIx64 "\n", data_mask);
1464fe6060f1SDimitry Andric result.AppendMessageWithFormat(
1465fe6060f1SDimitry Andric "Number of bits used in addressing (code): %d\n", bits);
1466fe6060f1SDimitry Andric }
1467fe6060f1SDimitry Andric
14685ffd83dbSDimitry Andric PlatformSP platform_sp = process->GetTarget().GetPlatform();
14695ffd83dbSDimitry Andric if (!platform_sp) {
14705ffd83dbSDimitry Andric result.AppendError("Couldn'retrieve the target's platform");
1471*c9157d92SDimitry Andric return;
14720b57cec5SDimitry Andric }
14735ffd83dbSDimitry Andric
14745ffd83dbSDimitry Andric auto expected_crash_info =
14755ffd83dbSDimitry Andric platform_sp->FetchExtendedCrashInformation(*process);
14765ffd83dbSDimitry Andric
14775ffd83dbSDimitry Andric if (!expected_crash_info) {
14785ffd83dbSDimitry Andric result.AppendError(llvm::toString(expected_crash_info.takeError()));
1479*c9157d92SDimitry Andric return;
14805ffd83dbSDimitry Andric }
14815ffd83dbSDimitry Andric
14825ffd83dbSDimitry Andric StructuredData::DictionarySP crash_info_sp = *expected_crash_info;
14835ffd83dbSDimitry Andric
14845ffd83dbSDimitry Andric if (crash_info_sp) {
1485bdd1243dSDimitry Andric strm.EOL();
14865ffd83dbSDimitry Andric strm.PutCString("Extended Crash Information:\n");
1487bdd1243dSDimitry Andric crash_info_sp->GetDescription(strm);
14885ffd83dbSDimitry Andric }
14895ffd83dbSDimitry Andric }
14905ffd83dbSDimitry Andric }
14915ffd83dbSDimitry Andric
14925ffd83dbSDimitry Andric private:
14935ffd83dbSDimitry Andric CommandOptions m_options;
14940b57cec5SDimitry Andric };
14950b57cec5SDimitry Andric
14960b57cec5SDimitry Andric // CommandObjectProcessHandle
14979dba64beSDimitry Andric #define LLDB_OPTIONS_process_handle
14989dba64beSDimitry Andric #include "CommandOptions.inc"
14990b57cec5SDimitry Andric
15000b57cec5SDimitry Andric #pragma mark CommandObjectProcessHandle
15010b57cec5SDimitry Andric
15020b57cec5SDimitry Andric class CommandObjectProcessHandle : public CommandObjectParsed {
15030b57cec5SDimitry Andric public:
15040b57cec5SDimitry Andric class CommandOptions : public Options {
15050b57cec5SDimitry Andric public:
CommandOptions()150604eeddc0SDimitry Andric CommandOptions() { OptionParsingStarting(nullptr); }
15070b57cec5SDimitry Andric
15080b57cec5SDimitry Andric ~CommandOptions() override = default;
15090b57cec5SDimitry Andric
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)15100b57cec5SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
15110b57cec5SDimitry Andric ExecutionContext *execution_context) override {
15120b57cec5SDimitry Andric Status error;
15130b57cec5SDimitry Andric const int short_option = m_getopt_table[option_idx].val;
15140b57cec5SDimitry Andric
15150b57cec5SDimitry Andric switch (short_option) {
151681ad6265SDimitry Andric case 'c':
151781ad6265SDimitry Andric do_clear = true;
151881ad6265SDimitry Andric break;
151981ad6265SDimitry Andric case 'd':
152081ad6265SDimitry Andric dummy = true;
152181ad6265SDimitry Andric break;
15220b57cec5SDimitry Andric case 's':
15235ffd83dbSDimitry Andric stop = std::string(option_arg);
15240b57cec5SDimitry Andric break;
15250b57cec5SDimitry Andric case 'n':
15265ffd83dbSDimitry Andric notify = std::string(option_arg);
15270b57cec5SDimitry Andric break;
15280b57cec5SDimitry Andric case 'p':
15295ffd83dbSDimitry Andric pass = std::string(option_arg);
15300b57cec5SDimitry Andric break;
153181ad6265SDimitry Andric case 't':
153281ad6265SDimitry Andric only_target_values = true;
153381ad6265SDimitry Andric break;
15340b57cec5SDimitry Andric default:
15359dba64beSDimitry Andric llvm_unreachable("Unimplemented option");
15360b57cec5SDimitry Andric }
15370b57cec5SDimitry Andric return error;
15380b57cec5SDimitry Andric }
15390b57cec5SDimitry Andric
OptionParsingStarting(ExecutionContext * execution_context)15400b57cec5SDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
15410b57cec5SDimitry Andric stop.clear();
15420b57cec5SDimitry Andric notify.clear();
15430b57cec5SDimitry Andric pass.clear();
154481ad6265SDimitry Andric only_target_values = false;
154581ad6265SDimitry Andric do_clear = false;
154681ad6265SDimitry Andric dummy = false;
15470b57cec5SDimitry Andric }
15480b57cec5SDimitry Andric
GetDefinitions()15490b57cec5SDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1550bdd1243dSDimitry Andric return llvm::ArrayRef(g_process_handle_options);
15510b57cec5SDimitry Andric }
15520b57cec5SDimitry Andric
15530b57cec5SDimitry Andric // Instance variables to hold the values for command options.
15540b57cec5SDimitry Andric
15550b57cec5SDimitry Andric std::string stop;
15560b57cec5SDimitry Andric std::string notify;
15570b57cec5SDimitry Andric std::string pass;
155881ad6265SDimitry Andric bool only_target_values = false;
155981ad6265SDimitry Andric bool do_clear = false;
156081ad6265SDimitry Andric bool dummy = false;
15610b57cec5SDimitry Andric };
15620b57cec5SDimitry Andric
CommandObjectProcessHandle(CommandInterpreter & interpreter)15630b57cec5SDimitry Andric CommandObjectProcessHandle(CommandInterpreter &interpreter)
15640b57cec5SDimitry Andric : CommandObjectParsed(interpreter, "process handle",
15650b57cec5SDimitry Andric "Manage LLDB handling of OS signals for the "
15660b57cec5SDimitry Andric "current target process. Defaults to showing "
15670b57cec5SDimitry Andric "current policy.",
156881ad6265SDimitry Andric nullptr) {
156981ad6265SDimitry Andric SetHelpLong("\nIf no signals are specified but one or more actions are, "
157081ad6265SDimitry Andric "and there is a live process, update them all. If no action "
157181ad6265SDimitry Andric "is specified, list the current values.\n"
157281ad6265SDimitry Andric "If you specify actions with no target (e.g. in an init file) "
157381ad6265SDimitry Andric "or in a target with no process "
157481ad6265SDimitry Andric "the values will get copied into subsequent targets, but "
157581ad6265SDimitry Andric "lldb won't be able to spell-check the options since it can't "
157681ad6265SDimitry Andric "know which signal set will later be in force."
157781ad6265SDimitry Andric "\nYou can see the signal modifications held by the target"
157881ad6265SDimitry Andric "by passing the -t option."
157981ad6265SDimitry Andric "\nYou can also clear the target modification for a signal"
158081ad6265SDimitry Andric "by passing the -c option");
15810b57cec5SDimitry Andric CommandArgumentEntry arg;
15820b57cec5SDimitry Andric CommandArgumentData signal_arg;
15830b57cec5SDimitry Andric
15840b57cec5SDimitry Andric signal_arg.arg_type = eArgTypeUnixSignal;
15850b57cec5SDimitry Andric signal_arg.arg_repetition = eArgRepeatStar;
15860b57cec5SDimitry Andric
15870b57cec5SDimitry Andric arg.push_back(signal_arg);
15880b57cec5SDimitry Andric
15890b57cec5SDimitry Andric m_arguments.push_back(arg);
15900b57cec5SDimitry Andric }
15910b57cec5SDimitry Andric
15920b57cec5SDimitry Andric ~CommandObjectProcessHandle() override = default;
15930b57cec5SDimitry Andric
GetOptions()15940b57cec5SDimitry Andric Options *GetOptions() override { return &m_options; }
15950b57cec5SDimitry Andric
VerifyCommandOptionValue(const std::string & option,int & real_value)15960b57cec5SDimitry Andric bool VerifyCommandOptionValue(const std::string &option, int &real_value) {
15970b57cec5SDimitry Andric bool okay = true;
15980b57cec5SDimitry Andric bool success = false;
15990b57cec5SDimitry Andric bool tmp_value = OptionArgParser::ToBoolean(option, false, &success);
16000b57cec5SDimitry Andric
16010b57cec5SDimitry Andric if (success && tmp_value)
16020b57cec5SDimitry Andric real_value = 1;
16030b57cec5SDimitry Andric else if (success && !tmp_value)
16040b57cec5SDimitry Andric real_value = 0;
16050b57cec5SDimitry Andric else {
16060b57cec5SDimitry Andric // If the value isn't 'true' or 'false', it had better be 0 or 1.
16075ffd83dbSDimitry Andric if (!llvm::to_integer(option, real_value))
16085ffd83dbSDimitry Andric real_value = 3;
16090b57cec5SDimitry Andric if (real_value != 0 && real_value != 1)
16100b57cec5SDimitry Andric okay = false;
16110b57cec5SDimitry Andric }
16120b57cec5SDimitry Andric
16130b57cec5SDimitry Andric return okay;
16140b57cec5SDimitry Andric }
16150b57cec5SDimitry Andric
PrintSignalHeader(Stream & str)16160b57cec5SDimitry Andric void PrintSignalHeader(Stream &str) {
16170b57cec5SDimitry Andric str.Printf("NAME PASS STOP NOTIFY\n");
16180b57cec5SDimitry Andric str.Printf("=========== ===== ===== ======\n");
16190b57cec5SDimitry Andric }
16200b57cec5SDimitry Andric
PrintSignal(Stream & str,int32_t signo,llvm::StringRef sig_name,const UnixSignalsSP & signals_sp)1621*c9157d92SDimitry Andric void PrintSignal(Stream &str, int32_t signo, llvm::StringRef sig_name,
16220b57cec5SDimitry Andric const UnixSignalsSP &signals_sp) {
16230b57cec5SDimitry Andric bool stop;
16240b57cec5SDimitry Andric bool suppress;
16250b57cec5SDimitry Andric bool notify;
16260b57cec5SDimitry Andric
1627*c9157d92SDimitry Andric str.Format("{0, -11} ", sig_name);
16280b57cec5SDimitry Andric if (signals_sp->GetSignalInfo(signo, suppress, stop, notify)) {
16290b57cec5SDimitry Andric bool pass = !suppress;
16300b57cec5SDimitry Andric str.Printf("%s %s %s", (pass ? "true " : "false"),
16310b57cec5SDimitry Andric (stop ? "true " : "false"), (notify ? "true " : "false"));
16320b57cec5SDimitry Andric }
16330b57cec5SDimitry Andric str.Printf("\n");
16340b57cec5SDimitry Andric }
16350b57cec5SDimitry Andric
PrintSignalInformation(Stream & str,Args & signal_args,int num_valid_signals,const UnixSignalsSP & signals_sp)16360b57cec5SDimitry Andric void PrintSignalInformation(Stream &str, Args &signal_args,
16370b57cec5SDimitry Andric int num_valid_signals,
16380b57cec5SDimitry Andric const UnixSignalsSP &signals_sp) {
16390b57cec5SDimitry Andric PrintSignalHeader(str);
16400b57cec5SDimitry Andric
16410b57cec5SDimitry Andric if (num_valid_signals > 0) {
16420b57cec5SDimitry Andric size_t num_args = signal_args.GetArgumentCount();
16430b57cec5SDimitry Andric for (size_t i = 0; i < num_args; ++i) {
16440b57cec5SDimitry Andric int32_t signo = signals_sp->GetSignalNumberFromName(
16450b57cec5SDimitry Andric signal_args.GetArgumentAtIndex(i));
16460b57cec5SDimitry Andric if (signo != LLDB_INVALID_SIGNAL_NUMBER)
16470b57cec5SDimitry Andric PrintSignal(str, signo, signal_args.GetArgumentAtIndex(i),
16480b57cec5SDimitry Andric signals_sp);
16490b57cec5SDimitry Andric }
16500b57cec5SDimitry Andric } else // Print info for ALL signals
16510b57cec5SDimitry Andric {
16520b57cec5SDimitry Andric int32_t signo = signals_sp->GetFirstSignalNumber();
16530b57cec5SDimitry Andric while (signo != LLDB_INVALID_SIGNAL_NUMBER) {
1654*c9157d92SDimitry Andric PrintSignal(str, signo, signals_sp->GetSignalAsStringRef(signo),
16550b57cec5SDimitry Andric signals_sp);
16560b57cec5SDimitry Andric signo = signals_sp->GetNextSignalNumber(signo);
16570b57cec5SDimitry Andric }
16580b57cec5SDimitry Andric }
16590b57cec5SDimitry Andric }
16600b57cec5SDimitry Andric
16610b57cec5SDimitry Andric protected:
DoExecute(Args & signal_args,CommandReturnObject & result)1662*c9157d92SDimitry Andric void DoExecute(Args &signal_args, CommandReturnObject &result) override {
166381ad6265SDimitry Andric Target &target = GetSelectedOrDummyTarget();
16640b57cec5SDimitry Andric
166581ad6265SDimitry Andric // Any signals that are being set should be added to the Target's
166681ad6265SDimitry Andric // DummySignals so they will get applied on rerun, etc.
166781ad6265SDimitry Andric // If we have a process, however, we can do a more accurate job of vetting
166881ad6265SDimitry Andric // the user's options.
166981ad6265SDimitry Andric ProcessSP process_sp = target.GetProcessSP();
16700b57cec5SDimitry Andric
16710b57cec5SDimitry Andric int stop_action = -1; // -1 means leave the current setting alone
16720b57cec5SDimitry Andric int pass_action = -1; // -1 means leave the current setting alone
16730b57cec5SDimitry Andric int notify_action = -1; // -1 means leave the current setting alone
16740b57cec5SDimitry Andric
16750b57cec5SDimitry Andric if (!m_options.stop.empty() &&
16760b57cec5SDimitry Andric !VerifyCommandOptionValue(m_options.stop, stop_action)) {
16770b57cec5SDimitry Andric result.AppendError("Invalid argument for command option --stop; must be "
16780b57cec5SDimitry Andric "true or false.\n");
1679*c9157d92SDimitry Andric return;
16800b57cec5SDimitry Andric }
16810b57cec5SDimitry Andric
16820b57cec5SDimitry Andric if (!m_options.notify.empty() &&
16830b57cec5SDimitry Andric !VerifyCommandOptionValue(m_options.notify, notify_action)) {
16840b57cec5SDimitry Andric result.AppendError("Invalid argument for command option --notify; must "
16850b57cec5SDimitry Andric "be true or false.\n");
1686*c9157d92SDimitry Andric return;
16870b57cec5SDimitry Andric }
16880b57cec5SDimitry Andric
16890b57cec5SDimitry Andric if (!m_options.pass.empty() &&
16900b57cec5SDimitry Andric !VerifyCommandOptionValue(m_options.pass, pass_action)) {
16910b57cec5SDimitry Andric result.AppendError("Invalid argument for command option --pass; must be "
16920b57cec5SDimitry Andric "true or false.\n");
1693*c9157d92SDimitry Andric return;
16940b57cec5SDimitry Andric }
16950b57cec5SDimitry Andric
169681ad6265SDimitry Andric bool no_actions = (stop_action == -1 && pass_action == -1
169781ad6265SDimitry Andric && notify_action == -1);
169881ad6265SDimitry Andric if (m_options.only_target_values && !no_actions) {
169981ad6265SDimitry Andric result.AppendError("-t is for reporting, not setting, target values.");
1700*c9157d92SDimitry Andric return;
170181ad6265SDimitry Andric }
170281ad6265SDimitry Andric
17030b57cec5SDimitry Andric size_t num_args = signal_args.GetArgumentCount();
170481ad6265SDimitry Andric UnixSignalsSP signals_sp;
170581ad6265SDimitry Andric if (process_sp)
170681ad6265SDimitry Andric signals_sp = process_sp->GetUnixSignals();
170781ad6265SDimitry Andric
17080b57cec5SDimitry Andric int num_signals_set = 0;
17090b57cec5SDimitry Andric
171081ad6265SDimitry Andric // If we were just asked to print the target values, do that here and
171181ad6265SDimitry Andric // return:
171281ad6265SDimitry Andric if (m_options.only_target_values) {
171381ad6265SDimitry Andric target.PrintDummySignals(result.GetOutputStream(), signal_args);
171481ad6265SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult);
1715*c9157d92SDimitry Andric return;
171681ad6265SDimitry Andric }
171781ad6265SDimitry Andric
171881ad6265SDimitry Andric // This handles clearing values:
171981ad6265SDimitry Andric if (m_options.do_clear) {
172081ad6265SDimitry Andric target.ClearDummySignals(signal_args);
172181ad6265SDimitry Andric if (m_options.dummy)
172281ad6265SDimitry Andric GetDummyTarget().ClearDummySignals(signal_args);
172381ad6265SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishNoResult);
1724*c9157d92SDimitry Andric return;
172581ad6265SDimitry Andric }
172681ad6265SDimitry Andric
172781ad6265SDimitry Andric // This rest handles setting values:
17280b57cec5SDimitry Andric if (num_args > 0) {
17290b57cec5SDimitry Andric for (const auto &arg : signal_args) {
173081ad6265SDimitry Andric // Do the process first. If we have a process we can catch
173181ad6265SDimitry Andric // invalid signal names, which we do here.
173281ad6265SDimitry Andric if (signals_sp) {
17330b57cec5SDimitry Andric int32_t signo = signals_sp->GetSignalNumberFromName(arg.c_str());
17340b57cec5SDimitry Andric if (signo != LLDB_INVALID_SIGNAL_NUMBER) {
17350b57cec5SDimitry Andric // Casting the actions as bools here should be okay, because
17360b57cec5SDimitry Andric // VerifyCommandOptionValue guarantees the value is either 0 or 1.
17370b57cec5SDimitry Andric if (stop_action != -1)
17380b57cec5SDimitry Andric signals_sp->SetShouldStop(signo, stop_action);
17390b57cec5SDimitry Andric if (pass_action != -1) {
17400b57cec5SDimitry Andric bool suppress = !pass_action;
17410b57cec5SDimitry Andric signals_sp->SetShouldSuppress(signo, suppress);
17420b57cec5SDimitry Andric }
17430b57cec5SDimitry Andric if (notify_action != -1)
17440b57cec5SDimitry Andric signals_sp->SetShouldNotify(signo, notify_action);
17450b57cec5SDimitry Andric ++num_signals_set;
17460b57cec5SDimitry Andric } else {
17470b57cec5SDimitry Andric result.AppendErrorWithFormat("Invalid signal name '%s'\n",
17480b57cec5SDimitry Andric arg.c_str());
174981ad6265SDimitry Andric continue;
17500b57cec5SDimitry Andric }
175181ad6265SDimitry Andric } else {
175281ad6265SDimitry Andric // If there's no process we can't check, so we just set them all.
175381ad6265SDimitry Andric // But since the map signal name -> signal number across all platforms
175481ad6265SDimitry Andric // is not 1-1, we can't sensibly set signal actions by number before
175581ad6265SDimitry Andric // we have a process. Check that here:
175681ad6265SDimitry Andric int32_t signo;
175781ad6265SDimitry Andric if (llvm::to_integer(arg.c_str(), signo)) {
175881ad6265SDimitry Andric result.AppendErrorWithFormat("Can't set signal handling by signal "
175981ad6265SDimitry Andric "number with no process");
1760*c9157d92SDimitry Andric return;
176181ad6265SDimitry Andric }
176281ad6265SDimitry Andric num_signals_set = num_args;
176381ad6265SDimitry Andric }
176481ad6265SDimitry Andric auto set_lazy_bool = [] (int action) -> LazyBool {
176581ad6265SDimitry Andric LazyBool lazy;
176681ad6265SDimitry Andric if (action == -1)
176781ad6265SDimitry Andric lazy = eLazyBoolCalculate;
176881ad6265SDimitry Andric else if (action)
176981ad6265SDimitry Andric lazy = eLazyBoolYes;
177081ad6265SDimitry Andric else
177181ad6265SDimitry Andric lazy = eLazyBoolNo;
177281ad6265SDimitry Andric return lazy;
177381ad6265SDimitry Andric };
177481ad6265SDimitry Andric
177581ad6265SDimitry Andric // If there were no actions, we're just listing, don't add the dummy:
177681ad6265SDimitry Andric if (!no_actions)
177781ad6265SDimitry Andric target.AddDummySignal(arg.ref(),
177881ad6265SDimitry Andric set_lazy_bool(pass_action),
177981ad6265SDimitry Andric set_lazy_bool(notify_action),
178081ad6265SDimitry Andric set_lazy_bool(stop_action));
17810b57cec5SDimitry Andric }
17820b57cec5SDimitry Andric } else {
17830b57cec5SDimitry Andric // No signal specified, if any command options were specified, update ALL
178481ad6265SDimitry Andric // signals. But we can't do this without a process since we don't know
178581ad6265SDimitry Andric // all the possible signals that might be valid for this target.
178681ad6265SDimitry Andric if (((notify_action != -1) || (stop_action != -1) || (pass_action != -1))
178781ad6265SDimitry Andric && process_sp) {
17880b57cec5SDimitry Andric if (m_interpreter.Confirm(
17890b57cec5SDimitry Andric "Do you really want to update all the signals?", false)) {
17900b57cec5SDimitry Andric int32_t signo = signals_sp->GetFirstSignalNumber();
17910b57cec5SDimitry Andric while (signo != LLDB_INVALID_SIGNAL_NUMBER) {
17920b57cec5SDimitry Andric if (notify_action != -1)
17930b57cec5SDimitry Andric signals_sp->SetShouldNotify(signo, notify_action);
17940b57cec5SDimitry Andric if (stop_action != -1)
17950b57cec5SDimitry Andric signals_sp->SetShouldStop(signo, stop_action);
17960b57cec5SDimitry Andric if (pass_action != -1) {
17970b57cec5SDimitry Andric bool suppress = !pass_action;
17980b57cec5SDimitry Andric signals_sp->SetShouldSuppress(signo, suppress);
17990b57cec5SDimitry Andric }
18000b57cec5SDimitry Andric signo = signals_sp->GetNextSignalNumber(signo);
18010b57cec5SDimitry Andric }
18020b57cec5SDimitry Andric }
18030b57cec5SDimitry Andric }
18040b57cec5SDimitry Andric }
18050b57cec5SDimitry Andric
180681ad6265SDimitry Andric if (signals_sp)
18070b57cec5SDimitry Andric PrintSignalInformation(result.GetOutputStream(), signal_args,
18080b57cec5SDimitry Andric num_signals_set, signals_sp);
180981ad6265SDimitry Andric else
181081ad6265SDimitry Andric target.PrintDummySignals(result.GetOutputStream(),
181181ad6265SDimitry Andric signal_args);
18120b57cec5SDimitry Andric
18130b57cec5SDimitry Andric if (num_signals_set > 0)
181481ad6265SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult);
18150b57cec5SDimitry Andric else
18160b57cec5SDimitry Andric result.SetStatus(eReturnStatusFailed);
18170b57cec5SDimitry Andric }
18180b57cec5SDimitry Andric
18190b57cec5SDimitry Andric CommandOptions m_options;
18200b57cec5SDimitry Andric };
18210b57cec5SDimitry Andric
1822fe6060f1SDimitry Andric // Next are the subcommands of CommandObjectMultiwordProcessTrace
1823fe6060f1SDimitry Andric
1824fe6060f1SDimitry Andric // CommandObjectProcessTraceStart
1825fe6060f1SDimitry Andric class CommandObjectProcessTraceStart : public CommandObjectTraceProxy {
1826fe6060f1SDimitry Andric public:
CommandObjectProcessTraceStart(CommandInterpreter & interpreter)1827fe6060f1SDimitry Andric CommandObjectProcessTraceStart(CommandInterpreter &interpreter)
1828fe6060f1SDimitry Andric : CommandObjectTraceProxy(
1829fe6060f1SDimitry Andric /*live_debug_session_only*/ true, interpreter,
1830fe6060f1SDimitry Andric "process trace start",
1831fe6060f1SDimitry Andric "Start tracing this process with the corresponding trace "
1832fe6060f1SDimitry Andric "plug-in.",
1833fe6060f1SDimitry Andric "process trace start [<trace-options>]") {}
1834fe6060f1SDimitry Andric
1835fe6060f1SDimitry Andric protected:
GetDelegateCommand(Trace & trace)1836fe6060f1SDimitry Andric lldb::CommandObjectSP GetDelegateCommand(Trace &trace) override {
1837fe6060f1SDimitry Andric return trace.GetProcessTraceStartCommand(m_interpreter);
1838fe6060f1SDimitry Andric }
1839fe6060f1SDimitry Andric };
1840fe6060f1SDimitry Andric
1841fe6060f1SDimitry Andric // CommandObjectProcessTraceStop
1842fe6060f1SDimitry Andric class CommandObjectProcessTraceStop : public CommandObjectParsed {
1843fe6060f1SDimitry Andric public:
CommandObjectProcessTraceStop(CommandInterpreter & interpreter)1844fe6060f1SDimitry Andric CommandObjectProcessTraceStop(CommandInterpreter &interpreter)
1845fe6060f1SDimitry Andric : CommandObjectParsed(interpreter, "process trace stop",
1846fe6060f1SDimitry Andric "Stop tracing this process. This does not affect "
1847fe6060f1SDimitry Andric "traces started with the "
1848fe6060f1SDimitry Andric "\"thread trace start\" command.",
1849fe6060f1SDimitry Andric "process trace stop",
1850fe6060f1SDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock |
1851fe6060f1SDimitry Andric eCommandProcessMustBeLaunched |
1852fe6060f1SDimitry Andric eCommandProcessMustBePaused |
1853fe6060f1SDimitry Andric eCommandProcessMustBeTraced) {}
1854fe6060f1SDimitry Andric
1855fe6060f1SDimitry Andric ~CommandObjectProcessTraceStop() override = default;
1856fe6060f1SDimitry Andric
DoExecute(Args & command,CommandReturnObject & result)1857*c9157d92SDimitry Andric void DoExecute(Args &command, CommandReturnObject &result) override {
1858fe6060f1SDimitry Andric ProcessSP process_sp = m_exe_ctx.GetProcessSP();
1859fe6060f1SDimitry Andric
1860fe6060f1SDimitry Andric TraceSP trace_sp = process_sp->GetTarget().GetTrace();
1861fe6060f1SDimitry Andric
1862fe6060f1SDimitry Andric if (llvm::Error err = trace_sp->Stop())
1863fe6060f1SDimitry Andric result.AppendError(toString(std::move(err)));
1864fe6060f1SDimitry Andric else
1865fe6060f1SDimitry Andric result.SetStatus(eReturnStatusSuccessFinishResult);
1866fe6060f1SDimitry Andric }
1867fe6060f1SDimitry Andric };
1868fe6060f1SDimitry Andric
1869fe6060f1SDimitry Andric // CommandObjectMultiwordProcessTrace
1870fe6060f1SDimitry Andric class CommandObjectMultiwordProcessTrace : public CommandObjectMultiword {
1871fe6060f1SDimitry Andric public:
CommandObjectMultiwordProcessTrace(CommandInterpreter & interpreter)1872fe6060f1SDimitry Andric CommandObjectMultiwordProcessTrace(CommandInterpreter &interpreter)
1873fe6060f1SDimitry Andric : CommandObjectMultiword(
1874fe6060f1SDimitry Andric interpreter, "trace", "Commands for tracing the current process.",
1875fe6060f1SDimitry Andric "process trace <subcommand> [<subcommand objects>]") {
1876fe6060f1SDimitry Andric LoadSubCommand("start", CommandObjectSP(new CommandObjectProcessTraceStart(
1877fe6060f1SDimitry Andric interpreter)));
1878fe6060f1SDimitry Andric LoadSubCommand("stop", CommandObjectSP(
1879fe6060f1SDimitry Andric new CommandObjectProcessTraceStop(interpreter)));
1880fe6060f1SDimitry Andric }
1881fe6060f1SDimitry Andric
1882fe6060f1SDimitry Andric ~CommandObjectMultiwordProcessTrace() override = default;
1883fe6060f1SDimitry Andric };
1884fe6060f1SDimitry Andric
18850b57cec5SDimitry Andric // CommandObjectMultiwordProcess
18860b57cec5SDimitry Andric
CommandObjectMultiwordProcess(CommandInterpreter & interpreter)18870b57cec5SDimitry Andric CommandObjectMultiwordProcess::CommandObjectMultiwordProcess(
18880b57cec5SDimitry Andric CommandInterpreter &interpreter)
18890b57cec5SDimitry Andric : CommandObjectMultiword(
18900b57cec5SDimitry Andric interpreter, "process",
18910b57cec5SDimitry Andric "Commands for interacting with processes on the current platform.",
18920b57cec5SDimitry Andric "process <subcommand> [<subcommand-options>]") {
18930b57cec5SDimitry Andric LoadSubCommand("attach",
18940b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessAttach(interpreter)));
18950b57cec5SDimitry Andric LoadSubCommand("launch",
18960b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessLaunch(interpreter)));
18970b57cec5SDimitry Andric LoadSubCommand("continue", CommandObjectSP(new CommandObjectProcessContinue(
18980b57cec5SDimitry Andric interpreter)));
18990b57cec5SDimitry Andric LoadSubCommand("connect",
19000b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessConnect(interpreter)));
19010b57cec5SDimitry Andric LoadSubCommand("detach",
19020b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessDetach(interpreter)));
19030b57cec5SDimitry Andric LoadSubCommand("load",
19040b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessLoad(interpreter)));
19050b57cec5SDimitry Andric LoadSubCommand("unload",
19060b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessUnload(interpreter)));
19070b57cec5SDimitry Andric LoadSubCommand("signal",
19080b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessSignal(interpreter)));
19090b57cec5SDimitry Andric LoadSubCommand("handle",
19100b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessHandle(interpreter)));
19110b57cec5SDimitry Andric LoadSubCommand("status",
19120b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessStatus(interpreter)));
19130b57cec5SDimitry Andric LoadSubCommand("interrupt", CommandObjectSP(new CommandObjectProcessInterrupt(
19140b57cec5SDimitry Andric interpreter)));
19150b57cec5SDimitry Andric LoadSubCommand("kill",
19160b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessKill(interpreter)));
19170b57cec5SDimitry Andric LoadSubCommand("plugin",
19180b57cec5SDimitry Andric CommandObjectSP(new CommandObjectProcessPlugin(interpreter)));
19190b57cec5SDimitry Andric LoadSubCommand("save-core", CommandObjectSP(new CommandObjectProcessSaveCore(
19200b57cec5SDimitry Andric interpreter)));
1921fe6060f1SDimitry Andric LoadSubCommand(
1922fe6060f1SDimitry Andric "trace",
1923fe6060f1SDimitry Andric CommandObjectSP(new CommandObjectMultiwordProcessTrace(interpreter)));
19240b57cec5SDimitry Andric }
19250b57cec5SDimitry Andric
19260b57cec5SDimitry Andric CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess() = default;
1927