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