1ac7ddfbfSEd Maste //===-- CommandObjectProcess.cpp --------------------------------*- C++ -*-===//
2ac7ddfbfSEd Maste //
3ac7ddfbfSEd Maste // The LLVM Compiler Infrastructure
4ac7ddfbfSEd Maste //
5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source
6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details.
7ac7ddfbfSEd Maste //
8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===//
9ac7ddfbfSEd Maste
104bb0738eSEd Maste #include "CommandObjectProcess.h"
11ac7ddfbfSEd Maste #include "lldb/Breakpoint/Breakpoint.h"
12ac7ddfbfSEd Maste #include "lldb/Breakpoint/BreakpointLocation.h"
13ac7ddfbfSEd Maste #include "lldb/Breakpoint/BreakpointSite.h"
14ac7ddfbfSEd Maste #include "lldb/Core/Module.h"
150127ef0fSEd Maste #include "lldb/Core/PluginManager.h"
16ac7ddfbfSEd Maste #include "lldb/Host/Host.h"
17f678e45dSDimitry Andric #include "lldb/Host/OptionParser.h"
181c3bbb01SEd Maste #include "lldb/Host/StringConvert.h"
19ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandInterpreter.h"
20ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandReturnObject.h"
214ba319b5SDimitry Andric #include "lldb/Interpreter/OptionArgParser.h"
22435933ddSDimitry Andric #include "lldb/Interpreter/Options.h"
23ac7ddfbfSEd Maste #include "lldb/Target/Platform.h"
24ac7ddfbfSEd Maste #include "lldb/Target/Process.h"
25ac7ddfbfSEd Maste #include "lldb/Target/StopInfo.h"
26ac7ddfbfSEd Maste #include "lldb/Target/Target.h"
27ac7ddfbfSEd Maste #include "lldb/Target/Thread.h"
281c3bbb01SEd Maste #include "lldb/Target/UnixSignals.h"
294ba319b5SDimitry Andric #include "lldb/Utility/Args.h"
30*b5893f02SDimitry Andric #include "lldb/Utility/State.h"
31ac7ddfbfSEd Maste
32ac7ddfbfSEd Maste using namespace lldb;
33ac7ddfbfSEd Maste using namespace lldb_private;
34ac7ddfbfSEd Maste
35435933ddSDimitry Andric class CommandObjectProcessLaunchOrAttach : public CommandObjectParsed {
36ac7ddfbfSEd Maste public:
CommandObjectProcessLaunchOrAttach(CommandInterpreter & interpreter,const char * name,const char * help,const char * syntax,uint32_t flags,const char * new_process_action)37ac7ddfbfSEd Maste CommandObjectProcessLaunchOrAttach(CommandInterpreter &interpreter,
38435933ddSDimitry Andric const char *name, const char *help,
39435933ddSDimitry Andric const char *syntax, uint32_t flags,
40435933ddSDimitry Andric const char *new_process_action)
41435933ddSDimitry Andric : CommandObjectParsed(interpreter, name, help, syntax, flags),
42ac7ddfbfSEd Maste m_new_process_action(new_process_action) {}
43ac7ddfbfSEd Maste
444bb0738eSEd Maste ~CommandObjectProcessLaunchOrAttach() override = default;
454bb0738eSEd Maste
46ac7ddfbfSEd Maste protected:
StopProcessIfNecessary(Process * process,StateType & state,CommandReturnObject & result)47435933ddSDimitry Andric bool StopProcessIfNecessary(Process *process, StateType &state,
48435933ddSDimitry Andric CommandReturnObject &result) {
49ac7ddfbfSEd Maste state = eStateInvalid;
50435933ddSDimitry Andric if (process) {
51ac7ddfbfSEd Maste state = process->GetState();
52ac7ddfbfSEd Maste
53435933ddSDimitry Andric if (process->IsAlive() && state != eStateConnected) {
54ac7ddfbfSEd Maste char message[1024];
55ac7ddfbfSEd Maste if (process->GetState() == eStateAttaching)
56435933ddSDimitry Andric ::snprintf(message, sizeof(message),
57435933ddSDimitry Andric "There is a pending attach, abort it and %s?",
58435933ddSDimitry Andric m_new_process_action.c_str());
59ac7ddfbfSEd Maste else if (process->GetShouldDetach())
60435933ddSDimitry Andric ::snprintf(message, sizeof(message),
61435933ddSDimitry Andric "There is a running process, detach from it and %s?",
62435933ddSDimitry Andric m_new_process_action.c_str());
63ac7ddfbfSEd Maste else
64435933ddSDimitry Andric ::snprintf(message, sizeof(message),
65435933ddSDimitry Andric "There is a running process, kill it and %s?",
66435933ddSDimitry Andric m_new_process_action.c_str());
67ac7ddfbfSEd Maste
68435933ddSDimitry Andric if (!m_interpreter.Confirm(message, true)) {
69ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
70ac7ddfbfSEd Maste return false;
71435933ddSDimitry Andric } else {
72435933ddSDimitry Andric if (process->GetShouldDetach()) {
73ac7ddfbfSEd Maste bool keep_stopped = false;
745517e702SDimitry Andric Status detach_error(process->Detach(keep_stopped));
75435933ddSDimitry Andric if (detach_error.Success()) {
76ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult);
774bb0738eSEd Maste process = nullptr;
78435933ddSDimitry Andric } else {
79435933ddSDimitry Andric result.AppendErrorWithFormat(
80435933ddSDimitry Andric "Failed to detach from process: %s\n",
81435933ddSDimitry Andric detach_error.AsCString());
82ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
83ac7ddfbfSEd Maste }
84435933ddSDimitry Andric } else {
855517e702SDimitry Andric Status destroy_error(process->Destroy(false));
86435933ddSDimitry Andric if (destroy_error.Success()) {
87ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult);
884bb0738eSEd Maste process = nullptr;
89435933ddSDimitry Andric } else {
90435933ddSDimitry Andric result.AppendErrorWithFormat("Failed to kill process: %s\n",
91435933ddSDimitry Andric destroy_error.AsCString());
92ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
93ac7ddfbfSEd Maste }
94ac7ddfbfSEd Maste }
95ac7ddfbfSEd Maste }
96ac7ddfbfSEd Maste }
97ac7ddfbfSEd Maste }
98ac7ddfbfSEd Maste return result.Succeeded();
99ac7ddfbfSEd Maste }
1004bb0738eSEd Maste
101ac7ddfbfSEd Maste std::string m_new_process_action;
102ac7ddfbfSEd Maste };
1034bb0738eSEd Maste
104ac7ddfbfSEd Maste //-------------------------------------------------------------------------
105ac7ddfbfSEd Maste // CommandObjectProcessLaunch
106ac7ddfbfSEd Maste //-------------------------------------------------------------------------
107ac7ddfbfSEd Maste #pragma mark CommandObjectProcessLaunch
108435933ddSDimitry Andric class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach {
109ac7ddfbfSEd Maste public:
CommandObjectProcessLaunch(CommandInterpreter & interpreter)110435933ddSDimitry Andric CommandObjectProcessLaunch(CommandInterpreter &interpreter)
111435933ddSDimitry Andric : CommandObjectProcessLaunchOrAttach(
112435933ddSDimitry Andric interpreter, "process launch",
113435933ddSDimitry Andric "Launch the executable in the debugger.", nullptr,
114435933ddSDimitry Andric eCommandRequiresTarget, "restart"),
115435933ddSDimitry Andric m_options() {
116ac7ddfbfSEd Maste CommandArgumentEntry arg;
117ac7ddfbfSEd Maste CommandArgumentData run_args_arg;
118ac7ddfbfSEd Maste
119ac7ddfbfSEd Maste // Define the first (and only) variant of this arg.
120ac7ddfbfSEd Maste run_args_arg.arg_type = eArgTypeRunArgs;
121ac7ddfbfSEd Maste run_args_arg.arg_repetition = eArgRepeatOptional;
122ac7ddfbfSEd Maste
123435933ddSDimitry Andric // There is only one variant this argument could be; put it into the
124435933ddSDimitry Andric // argument entry.
125ac7ddfbfSEd Maste arg.push_back(run_args_arg);
126ac7ddfbfSEd Maste
127ac7ddfbfSEd Maste // Push the data for the first argument into the m_arguments vector.
128ac7ddfbfSEd Maste m_arguments.push_back(arg);
129ac7ddfbfSEd Maste }
130ac7ddfbfSEd Maste
1314bb0738eSEd Maste ~CommandObjectProcessLaunch() override = default;
132ac7ddfbfSEd Maste
HandleArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector)1334ba319b5SDimitry Andric int HandleArgumentCompletion(
1344ba319b5SDimitry Andric CompletionRequest &request,
1354ba319b5SDimitry Andric OptionElementVector &opt_element_vector) override {
136ac7ddfbfSEd Maste
137435933ddSDimitry Andric CommandCompletions::InvokeCommonCompletionCallbacks(
138435933ddSDimitry Andric GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
1394ba319b5SDimitry Andric request, nullptr);
1404ba319b5SDimitry Andric return request.GetNumberOfMatches();
141ac7ddfbfSEd Maste }
142ac7ddfbfSEd Maste
GetOptions()143435933ddSDimitry Andric Options *GetOptions() override { return &m_options; }
144ac7ddfbfSEd Maste
GetRepeatCommand(Args & current_command_args,uint32_t index)145435933ddSDimitry Andric const char *GetRepeatCommand(Args ¤t_command_args,
146435933ddSDimitry Andric uint32_t index) override {
147ac7ddfbfSEd Maste // No repeat for "process launch"...
148ac7ddfbfSEd Maste return "";
149ac7ddfbfSEd Maste }
150ac7ddfbfSEd Maste
151ac7ddfbfSEd Maste protected:
DoExecute(Args & launch_args,CommandReturnObject & result)152435933ddSDimitry Andric bool DoExecute(Args &launch_args, CommandReturnObject &result) override {
153ac7ddfbfSEd Maste Debugger &debugger = m_interpreter.GetDebugger();
154ac7ddfbfSEd Maste Target *target = debugger.GetSelectedTarget().get();
1554bb0738eSEd Maste // If our listener is nullptr, users aren't allows to launch
15612b93ac6SEd Maste ModuleSP exe_module_sp = target->GetExecutableModule();
157ac7ddfbfSEd Maste
158435933ddSDimitry Andric if (exe_module_sp == nullptr) {
159435933ddSDimitry Andric result.AppendError("no file in target, create a debug target using the "
160435933ddSDimitry Andric "'target create' command");
161ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
162ac7ddfbfSEd Maste return false;
163ac7ddfbfSEd Maste }
164ac7ddfbfSEd Maste
165ac7ddfbfSEd Maste StateType state = eStateInvalid;
166ac7ddfbfSEd Maste
16712b93ac6SEd Maste if (!StopProcessIfNecessary(m_exe_ctx.GetProcessPtr(), state, result))
168ac7ddfbfSEd Maste return false;
169ac7ddfbfSEd Maste
170435933ddSDimitry Andric llvm::StringRef target_settings_argv0 = target->GetArg0();
171ac7ddfbfSEd Maste
172435933ddSDimitry Andric // Determine whether we will disable ASLR or leave it in the default state
1734ba319b5SDimitry Andric // (i.e. enabled if the platform supports it). First check if the process
1744ba319b5SDimitry Andric // launch options explicitly turn on/off
175435933ddSDimitry Andric // disabling ASLR. If so, use that setting;
1760127ef0fSEd Maste // otherwise, use the 'settings target.disable-aslr' setting.
1770127ef0fSEd Maste bool disable_aslr = false;
178435933ddSDimitry Andric if (m_options.disable_aslr != eLazyBoolCalculate) {
1794ba319b5SDimitry Andric // The user specified an explicit setting on the process launch line.
1804ba319b5SDimitry Andric // Use it.
1810127ef0fSEd Maste disable_aslr = (m_options.disable_aslr == eLazyBoolYes);
182435933ddSDimitry Andric } else {
1834ba319b5SDimitry Andric // The user did not explicitly specify whether to disable ASLR. Fall
1844ba319b5SDimitry Andric // back to the target.disable-aslr setting.
1850127ef0fSEd Maste disable_aslr = target->GetDisableASLR();
1860127ef0fSEd Maste }
1870127ef0fSEd Maste
1880127ef0fSEd Maste if (disable_aslr)
18912b93ac6SEd Maste m_options.launch_info.GetFlags().Set(eLaunchFlagDisableASLR);
1900127ef0fSEd Maste else
1910127ef0fSEd Maste m_options.launch_info.GetFlags().Clear(eLaunchFlagDisableASLR);
1920127ef0fSEd Maste
1930127ef0fSEd Maste if (target->GetDetachOnError())
1940127ef0fSEd Maste m_options.launch_info.GetFlags().Set(eLaunchFlagDetachOnError);
19512b93ac6SEd Maste
19612b93ac6SEd Maste if (target->GetDisableSTDIO())
19712b93ac6SEd Maste m_options.launch_info.GetFlags().Set(eLaunchFlagDisableSTDIO);
19812b93ac6SEd Maste
1994ba319b5SDimitry Andric m_options.launch_info.GetEnvironment() = target->GetEnvironment();
200ac7ddfbfSEd Maste
201435933ddSDimitry Andric if (!target_settings_argv0.empty()) {
202435933ddSDimitry Andric m_options.launch_info.GetArguments().AppendArgument(
203435933ddSDimitry Andric target_settings_argv0);
204435933ddSDimitry Andric m_options.launch_info.SetExecutableFile(
205435933ddSDimitry Andric exe_module_sp->GetPlatformFileSpec(), false);
206435933ddSDimitry Andric } else {
207435933ddSDimitry Andric m_options.launch_info.SetExecutableFile(
208435933ddSDimitry Andric exe_module_sp->GetPlatformFileSpec(), true);
209ac7ddfbfSEd Maste }
210ac7ddfbfSEd Maste
211435933ddSDimitry Andric if (launch_args.GetArgumentCount() == 0) {
212435933ddSDimitry Andric m_options.launch_info.GetArguments().AppendArguments(
213435933ddSDimitry Andric target->GetProcessLaunchInfo().GetArguments());
214435933ddSDimitry Andric } else {
215ac7ddfbfSEd Maste m_options.launch_info.GetArguments().AppendArguments(launch_args);
216ac7ddfbfSEd Maste // Save the arguments for subsequent runs in the current target.
217ac7ddfbfSEd Maste target->SetRunArguments(launch_args);
218ac7ddfbfSEd Maste }
219ac7ddfbfSEd Maste
2207aa51b79SEd Maste StreamString stream;
2215517e702SDimitry Andric Status error = target->Launch(m_options.launch_info, &stream);
222ac7ddfbfSEd Maste
223435933ddSDimitry Andric if (error.Success()) {
22412b93ac6SEd Maste ProcessSP process_sp(target->GetProcessSP());
225435933ddSDimitry Andric if (process_sp) {
226435933ddSDimitry Andric // There is a race condition where this thread will return up the call
2274ba319b5SDimitry Andric // stack to the main command handler and show an (lldb) prompt before
2284ba319b5SDimitry Andric // HandlePrivateEvent (from PrivateStateThread) has a chance to call
2294ba319b5SDimitry Andric // PushProcessIOHandler().
2304ba319b5SDimitry Andric process_sp->SyncIOHandler(0, std::chrono::seconds(2));
2311c3bbb01SEd Maste
232435933ddSDimitry Andric llvm::StringRef data = stream.GetString();
233435933ddSDimitry Andric if (!data.empty())
234435933ddSDimitry Andric result.AppendMessage(data);
235435933ddSDimitry Andric const char *archname =
236435933ddSDimitry Andric exe_module_sp->GetArchitecture().GetArchitectureName();
237435933ddSDimitry Andric result.AppendMessageWithFormat(
238435933ddSDimitry Andric "Process %" PRIu64 " launched: '%s' (%s)\n", process_sp->GetID(),
239435933ddSDimitry Andric exe_module_sp->GetFileSpec().GetPath().c_str(), archname);
240ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult);
24112b93ac6SEd Maste result.SetDidChangeProcessState(true);
242435933ddSDimitry Andric } else {
243435933ddSDimitry Andric result.AppendError(
244435933ddSDimitry Andric "no error returned from Target::Launch, and target has no process");
245ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
246ac7ddfbfSEd Maste }
247435933ddSDimitry Andric } else {
24812b93ac6SEd Maste result.AppendError(error.AsCString());
249ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
250ac7ddfbfSEd Maste }
251ac7ddfbfSEd Maste return result.Succeeded();
252ac7ddfbfSEd Maste }
253ac7ddfbfSEd Maste
254ac7ddfbfSEd Maste protected:
255ac7ddfbfSEd Maste ProcessLaunchCommandOptions m_options;
256ac7ddfbfSEd Maste };
257ac7ddfbfSEd Maste
258ac7ddfbfSEd Maste //#define SET1 LLDB_OPT_SET_1
259ac7ddfbfSEd Maste //#define SET2 LLDB_OPT_SET_2
260ac7ddfbfSEd Maste //#define SET3 LLDB_OPT_SET_3
261ac7ddfbfSEd Maste //
262ac7ddfbfSEd Maste // OptionDefinition
263ac7ddfbfSEd Maste // CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
264ac7ddfbfSEd Maste //{
265435933ddSDimitry Andric // // clang-format off
266435933ddSDimitry Andric // {SET1 | SET2 | SET3, false, "stop-at-entry", 's', OptionParser::eNoArgument,
267435933ddSDimitry Andric // nullptr, 0, eArgTypeNone, "Stop at the entry point of the program
268435933ddSDimitry Andric // when launching a process."},
269435933ddSDimitry Andric // {SET1, false, "stdin", 'i',
270435933ddSDimitry Andric // OptionParser::eRequiredArgument, nullptr, 0, eArgTypeDirectoryName,
271435933ddSDimitry Andric // "Redirect stdin for the process to <path>."},
272435933ddSDimitry Andric // {SET1, false, "stdout", 'o',
273435933ddSDimitry Andric // OptionParser::eRequiredArgument, nullptr, 0, eArgTypeDirectoryName,
274435933ddSDimitry Andric // "Redirect stdout for the process to <path>."},
275435933ddSDimitry Andric // {SET1, false, "stderr", 'e',
276435933ddSDimitry Andric // OptionParser::eRequiredArgument, nullptr, 0, eArgTypeDirectoryName,
277435933ddSDimitry Andric // "Redirect stderr for the process to <path>."},
278435933ddSDimitry Andric // {SET1 | SET2 | SET3, false, "plugin", 'p',
279435933ddSDimitry Andric // OptionParser::eRequiredArgument, nullptr, 0, eArgTypePlugin, "Name of
280435933ddSDimitry Andric // the process plugin you want to use."},
281435933ddSDimitry Andric // { SET2, false, "tty", 't',
282435933ddSDimitry Andric // OptionParser::eOptionalArgument, nullptr, 0, eArgTypeDirectoryName, "Start
283435933ddSDimitry Andric // the process in a terminal. If <path> is specified, look for a terminal whose
284435933ddSDimitry Andric // name contains <path>, else start the process in a new terminal."},
285435933ddSDimitry Andric // { SET3, false, "no-stdio", 'n', OptionParser::eNoArgument,
286435933ddSDimitry Andric // nullptr, 0, eArgTypeNone, "Do not set up for terminal I/O to go to
287435933ddSDimitry Andric // running process."},
288435933ddSDimitry Andric // {SET1 | SET2 | SET3, false, "working-dir", 'w',
289435933ddSDimitry Andric // OptionParser::eRequiredArgument, nullptr, 0, eArgTypeDirectoryName, "Set the
290435933ddSDimitry Andric // current working directory to <path> when running the inferior."},
2914bb0738eSEd Maste // {0, false, nullptr, 0, 0, nullptr, 0, eArgTypeNone, nullptr}
292435933ddSDimitry Andric // // clang-format on
293ac7ddfbfSEd Maste //};
294ac7ddfbfSEd Maste //
295ac7ddfbfSEd Maste //#undef SET1
296ac7ddfbfSEd Maste //#undef SET2
297ac7ddfbfSEd Maste //#undef SET3
298ac7ddfbfSEd Maste
299ac7ddfbfSEd Maste //-------------------------------------------------------------------------
300ac7ddfbfSEd Maste // CommandObjectProcessAttach
301ac7ddfbfSEd Maste //-------------------------------------------------------------------------
302435933ddSDimitry Andric
303*b5893f02SDimitry Andric static constexpr OptionDefinition g_process_attach_options[] = {
304435933ddSDimitry Andric // clang-format off
305*b5893f02SDimitry Andric { LLDB_OPT_SET_ALL, false, "continue", 'c', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Immediately continue the process once attached." },
306*b5893f02SDimitry Andric { LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePlugin, "Name of the process plugin you want to use." },
307*b5893f02SDimitry Andric { LLDB_OPT_SET_1, false, "pid", 'p', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePid, "The process ID of an existing process to attach to." },
308*b5893f02SDimitry Andric { LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeProcessName, "The name of the process to attach to." },
309*b5893f02SDimitry Andric { LLDB_OPT_SET_2, false, "include-existing", 'i', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Include existing processes when doing attach -w." },
310*b5893f02SDimitry Andric { LLDB_OPT_SET_2, false, "waitfor", 'w', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Wait for the process with <process-name> to launch." },
311435933ddSDimitry Andric // clang-format on
312435933ddSDimitry Andric };
313435933ddSDimitry Andric
314ac7ddfbfSEd Maste #pragma mark CommandObjectProcessAttach
315435933ddSDimitry Andric class CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach {
316ac7ddfbfSEd Maste public:
317435933ddSDimitry Andric class CommandOptions : public Options {
318ac7ddfbfSEd Maste public:
CommandOptions()319435933ddSDimitry Andric CommandOptions() : Options() {
320435933ddSDimitry Andric // Keep default values of all options in one place: OptionParsingStarting
321435933ddSDimitry Andric // ()
322435933ddSDimitry Andric OptionParsingStarting(nullptr);
323ac7ddfbfSEd Maste }
324ac7ddfbfSEd Maste
3254bb0738eSEd Maste ~CommandOptions() override = default;
326ac7ddfbfSEd Maste
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)3275517e702SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
328435933ddSDimitry Andric ExecutionContext *execution_context) override {
3295517e702SDimitry Andric Status error;
330ac7ddfbfSEd Maste const int short_option = m_getopt_table[option_idx].val;
331435933ddSDimitry Andric switch (short_option) {
332ac7ddfbfSEd Maste case 'c':
333ac7ddfbfSEd Maste attach_info.SetContinueOnceAttached(true);
334ac7ddfbfSEd Maste break;
335ac7ddfbfSEd Maste
336435933ddSDimitry Andric case 'p': {
337435933ddSDimitry Andric lldb::pid_t pid;
338435933ddSDimitry Andric if (option_arg.getAsInteger(0, pid)) {
339435933ddSDimitry Andric error.SetErrorStringWithFormat("invalid process ID '%s'",
340435933ddSDimitry Andric option_arg.str().c_str());
341435933ddSDimitry Andric } else {
342ac7ddfbfSEd Maste attach_info.SetProcessID(pid);
343ac7ddfbfSEd Maste }
344435933ddSDimitry Andric } break;
345ac7ddfbfSEd Maste
346ac7ddfbfSEd Maste case 'P':
347ac7ddfbfSEd Maste attach_info.SetProcessPluginName(option_arg);
348ac7ddfbfSEd Maste break;
349ac7ddfbfSEd Maste
350ac7ddfbfSEd Maste case 'n':
351*b5893f02SDimitry Andric attach_info.GetExecutableFile().SetFile(option_arg,
3524ba319b5SDimitry Andric FileSpec::Style::native);
353ac7ddfbfSEd Maste break;
354ac7ddfbfSEd Maste
355ac7ddfbfSEd Maste case 'w':
356ac7ddfbfSEd Maste attach_info.SetWaitForLaunch(true);
357ac7ddfbfSEd Maste break;
358ac7ddfbfSEd Maste
359ac7ddfbfSEd Maste case 'i':
360ac7ddfbfSEd Maste attach_info.SetIgnoreExisting(false);
361ac7ddfbfSEd Maste break;
362ac7ddfbfSEd Maste
363ac7ddfbfSEd Maste default:
364435933ddSDimitry Andric error.SetErrorStringWithFormat("invalid short option character '%c'",
365435933ddSDimitry Andric short_option);
366ac7ddfbfSEd Maste break;
367ac7ddfbfSEd Maste }
368ac7ddfbfSEd Maste return error;
369ac7ddfbfSEd Maste }
370ac7ddfbfSEd Maste
OptionParsingStarting(ExecutionContext * execution_context)371435933ddSDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
372ac7ddfbfSEd Maste attach_info.Clear();
373ac7ddfbfSEd Maste }
374ac7ddfbfSEd Maste
GetDefinitions()375435933ddSDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
376435933ddSDimitry Andric return llvm::makeArrayRef(g_process_attach_options);
377ac7ddfbfSEd Maste }
378ac7ddfbfSEd Maste
HandleOptionArgumentCompletion(CompletionRequest & request,OptionElementVector & opt_element_vector,int opt_element_index,CommandInterpreter & interpreter)379435933ddSDimitry Andric bool HandleOptionArgumentCompletion(
3804ba319b5SDimitry Andric CompletionRequest &request, OptionElementVector &opt_element_vector,
3814ba319b5SDimitry Andric int opt_element_index, CommandInterpreter &interpreter) override {
382ac7ddfbfSEd Maste int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
383ac7ddfbfSEd Maste int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
384ac7ddfbfSEd Maste
385ac7ddfbfSEd Maste // We are only completing the name option for now...
386ac7ddfbfSEd Maste
387435933ddSDimitry Andric if (GetDefinitions()[opt_defs_index].short_option == 'n') {
388ac7ddfbfSEd Maste // Are we in the name?
389ac7ddfbfSEd Maste
390435933ddSDimitry Andric // Look to see if there is a -P argument provided, and if so use that
3914ba319b5SDimitry Andric // plugin, otherwise use the default plugin.
392ac7ddfbfSEd Maste
3934bb0738eSEd Maste const char *partial_name = nullptr;
3944ba319b5SDimitry Andric partial_name = request.GetParsedLine().GetArgumentAtIndex(opt_arg_pos);
395ac7ddfbfSEd Maste
396435933ddSDimitry Andric PlatformSP platform_sp(interpreter.GetPlatform(true));
397435933ddSDimitry Andric if (platform_sp) {
398ac7ddfbfSEd Maste ProcessInstanceInfoList process_infos;
399ac7ddfbfSEd Maste ProcessInstanceInfoMatch match_info;
400435933ddSDimitry Andric if (partial_name) {
401435933ddSDimitry Andric match_info.GetProcessInfo().GetExecutableFile().SetFile(
402*b5893f02SDimitry Andric partial_name, FileSpec::Style::native);
403f678e45dSDimitry Andric match_info.SetNameMatchType(NameMatch::StartsWith);
404ac7ddfbfSEd Maste }
405ac7ddfbfSEd Maste platform_sp->FindProcesses(match_info, process_infos);
406ac7ddfbfSEd Maste const size_t num_matches = process_infos.GetSize();
407435933ddSDimitry Andric if (num_matches > 0) {
408435933ddSDimitry Andric for (size_t i = 0; i < num_matches; ++i) {
4094ba319b5SDimitry Andric request.AddCompletion(llvm::StringRef(
410435933ddSDimitry Andric process_infos.GetProcessNameAtIndex(i),
4114ba319b5SDimitry Andric process_infos.GetProcessNameLengthAtIndex(i)));
412ac7ddfbfSEd Maste }
413ac7ddfbfSEd Maste }
414ac7ddfbfSEd Maste }
415ac7ddfbfSEd Maste }
416ac7ddfbfSEd Maste
417ac7ddfbfSEd Maste return false;
418ac7ddfbfSEd Maste }
419ac7ddfbfSEd Maste
420ac7ddfbfSEd Maste // Instance variables to hold the values for command options.
421ac7ddfbfSEd Maste
422ac7ddfbfSEd Maste ProcessAttachInfo attach_info;
423ac7ddfbfSEd Maste };
424ac7ddfbfSEd Maste
CommandObjectProcessAttach(CommandInterpreter & interpreter)425435933ddSDimitry Andric CommandObjectProcessAttach(CommandInterpreter &interpreter)
426435933ddSDimitry Andric : CommandObjectProcessLaunchOrAttach(
427435933ddSDimitry Andric interpreter, "process attach", "Attach to a process.",
428435933ddSDimitry Andric "process attach <cmd-options>", 0, "attach"),
429435933ddSDimitry Andric m_options() {}
430ac7ddfbfSEd Maste
4314bb0738eSEd Maste ~CommandObjectProcessAttach() override = default;
432ac7ddfbfSEd Maste
GetOptions()433435933ddSDimitry Andric Options *GetOptions() override { return &m_options; }
434ac7ddfbfSEd Maste
435ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)436435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override {
437435933ddSDimitry Andric PlatformSP platform_sp(
438435933ddSDimitry Andric m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
4391c3bbb01SEd Maste
440ac7ddfbfSEd Maste Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
441435933ddSDimitry Andric // N.B. The attach should be synchronous. It doesn't help much to get the
4424ba319b5SDimitry Andric // prompt back between initiating the attach and the target actually
4434ba319b5SDimitry Andric // stopping. So even if the interpreter is set to be asynchronous, we wait
4444ba319b5SDimitry Andric // for the stop ourselves here.
445ac7ddfbfSEd Maste
446ac7ddfbfSEd Maste StateType state = eStateInvalid;
447ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr();
448ac7ddfbfSEd Maste
449ac7ddfbfSEd Maste if (!StopProcessIfNecessary(process, state, result))
450ac7ddfbfSEd Maste return false;
451ac7ddfbfSEd Maste
452435933ddSDimitry Andric if (target == nullptr) {
453ac7ddfbfSEd Maste // If there isn't a current target create one.
454ac7ddfbfSEd Maste TargetSP new_target_sp;
4555517e702SDimitry Andric Status error;
456ac7ddfbfSEd Maste
457435933ddSDimitry Andric error = m_interpreter.GetDebugger().GetTargetList().CreateTarget(
458*b5893f02SDimitry Andric m_interpreter.GetDebugger(), "", "", eLoadDependentsNo,
4594bb0738eSEd Maste nullptr, // No platform options
460ac7ddfbfSEd Maste new_target_sp);
461ac7ddfbfSEd Maste target = new_target_sp.get();
462435933ddSDimitry Andric if (target == nullptr || error.Fail()) {
463ac7ddfbfSEd Maste result.AppendError(error.AsCString("Error creating target"));
464ac7ddfbfSEd Maste return false;
465ac7ddfbfSEd Maste }
466ac7ddfbfSEd Maste m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target);
467ac7ddfbfSEd Maste }
468ac7ddfbfSEd Maste
469435933ddSDimitry Andric // Record the old executable module, we want to issue a warning if the
4704ba319b5SDimitry Andric // process of attaching changed the current executable (like somebody said
4714ba319b5SDimitry Andric // "file foo" then attached to a PID whose executable was bar.)
472ac7ddfbfSEd Maste
473ac7ddfbfSEd Maste ModuleSP old_exec_module_sp = target->GetExecutableModule();
474ac7ddfbfSEd Maste ArchSpec old_arch_spec = target->GetArchitecture();
475ac7ddfbfSEd Maste
476435933ddSDimitry Andric if (command.GetArgumentCount()) {
477435933ddSDimitry Andric result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: %s\n",
478435933ddSDimitry Andric m_cmd_name.c_str(), m_cmd_syntax.c_str());
479ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
4801c3bbb01SEd Maste return false;
481ac7ddfbfSEd Maste }
482ac7ddfbfSEd Maste
4831c3bbb01SEd Maste m_interpreter.UpdateExecutionContext(nullptr);
4847aa51b79SEd Maste StreamString stream;
4851c3bbb01SEd Maste const auto error = target->Attach(m_options.attach_info, &stream);
486435933ddSDimitry Andric if (error.Success()) {
4871c3bbb01SEd Maste ProcessSP process_sp(target->GetProcessSP());
488435933ddSDimitry Andric if (process_sp) {
489435933ddSDimitry Andric result.AppendMessage(stream.GetString());
490ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult);
4911c3bbb01SEd Maste result.SetDidChangeProcessState(true);
492444ed5c5SDimitry Andric result.SetAbnormalStopWasExpected(true);
493435933ddSDimitry Andric } else {
494435933ddSDimitry Andric result.AppendError(
495435933ddSDimitry Andric "no error returned from Target::Attach, and target has no process");
496ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
49712b93ac6SEd Maste }
498435933ddSDimitry Andric } else {
49912b93ac6SEd Maste result.AppendErrorWithFormat("attach failed: %s\n", error.AsCString());
50012b93ac6SEd Maste result.SetStatus(eReturnStatusFailed);
501ac7ddfbfSEd Maste }
502ac7ddfbfSEd Maste
5031c3bbb01SEd Maste if (!result.Succeeded())
5041c3bbb01SEd Maste return false;
5051c3bbb01SEd Maste
506435933ddSDimitry Andric // Okay, we're done. Last step is to warn if the executable module has
507435933ddSDimitry Andric // changed:
508ac7ddfbfSEd Maste char new_path[PATH_MAX];
509ac7ddfbfSEd Maste ModuleSP new_exec_module_sp(target->GetExecutableModule());
510435933ddSDimitry Andric if (!old_exec_module_sp) {
511ac7ddfbfSEd Maste // We might not have a module if we attached to a raw pid...
512435933ddSDimitry Andric if (new_exec_module_sp) {
513ac7ddfbfSEd Maste new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX);
514435933ddSDimitry Andric result.AppendMessageWithFormat("Executable module set to \"%s\".\n",
515435933ddSDimitry Andric new_path);
516ac7ddfbfSEd Maste }
517435933ddSDimitry Andric } else if (old_exec_module_sp->GetFileSpec() !=
518435933ddSDimitry Andric new_exec_module_sp->GetFileSpec()) {
519ac7ddfbfSEd Maste char old_path[PATH_MAX];
520ac7ddfbfSEd Maste
521ac7ddfbfSEd Maste old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX);
522ac7ddfbfSEd Maste new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX);
523ac7ddfbfSEd Maste
524435933ddSDimitry Andric result.AppendWarningWithFormat(
525435933ddSDimitry Andric "Executable module changed from \"%s\" to \"%s\".\n", old_path,
526435933ddSDimitry Andric new_path);
527ac7ddfbfSEd Maste }
528ac7ddfbfSEd Maste
529435933ddSDimitry Andric if (!old_arch_spec.IsValid()) {
530435933ddSDimitry Andric result.AppendMessageWithFormat(
531435933ddSDimitry Andric "Architecture set to: %s.\n",
532435933ddSDimitry Andric target->GetArchitecture().GetTriple().getTriple().c_str());
533435933ddSDimitry Andric } else if (!old_arch_spec.IsExactMatch(target->GetArchitecture())) {
534435933ddSDimitry Andric result.AppendWarningWithFormat(
535435933ddSDimitry Andric "Architecture changed from %s to %s.\n",
536ac7ddfbfSEd Maste old_arch_spec.GetTriple().getTriple().c_str(),
537ac7ddfbfSEd Maste target->GetArchitecture().GetTriple().getTriple().c_str());
538ac7ddfbfSEd Maste }
539ac7ddfbfSEd Maste
5404ba319b5SDimitry Andric // This supports the use-case scenario of immediately continuing the
5414ba319b5SDimitry Andric // process once attached.
542ac7ddfbfSEd Maste if (m_options.attach_info.GetContinueOnceAttached())
543ac7ddfbfSEd Maste m_interpreter.HandleCommand("process continue", eLazyBoolNo, result);
5441c3bbb01SEd Maste
545ac7ddfbfSEd Maste return result.Succeeded();
546ac7ddfbfSEd Maste }
547ac7ddfbfSEd Maste
548ac7ddfbfSEd Maste CommandOptions m_options;
549ac7ddfbfSEd Maste };
550ac7ddfbfSEd Maste
551ac7ddfbfSEd Maste //-------------------------------------------------------------------------
552ac7ddfbfSEd Maste // CommandObjectProcessContinue
553ac7ddfbfSEd Maste //-------------------------------------------------------------------------
554435933ddSDimitry Andric
555*b5893f02SDimitry Andric static constexpr OptionDefinition g_process_continue_options[] = {
556435933ddSDimitry Andric // clang-format off
557*b5893f02SDimitry Andric { LLDB_OPT_SET_ALL, false, "ignore-count",'i', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Ignore <N> crossings of the breakpoint (if it exists) for the currently selected thread." }
558435933ddSDimitry Andric // clang-format on
559435933ddSDimitry Andric };
560435933ddSDimitry Andric
561ac7ddfbfSEd Maste #pragma mark CommandObjectProcessContinue
562ac7ddfbfSEd Maste
563435933ddSDimitry Andric class CommandObjectProcessContinue : public CommandObjectParsed {
564ac7ddfbfSEd Maste public:
CommandObjectProcessContinue(CommandInterpreter & interpreter)565435933ddSDimitry Andric CommandObjectProcessContinue(CommandInterpreter &interpreter)
566435933ddSDimitry Andric : CommandObjectParsed(
567435933ddSDimitry Andric interpreter, "process continue",
568ac7ddfbfSEd Maste "Continue execution of all threads in the current process.",
569ac7ddfbfSEd Maste "process continue",
570435933ddSDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock |
571435933ddSDimitry Andric eCommandProcessMustBeLaunched | eCommandProcessMustBePaused),
572435933ddSDimitry Andric m_options() {}
573ac7ddfbfSEd Maste
5744bb0738eSEd Maste ~CommandObjectProcessContinue() override = default;
575ac7ddfbfSEd Maste
576ac7ddfbfSEd Maste protected:
577435933ddSDimitry Andric class CommandOptions : public Options {
578ac7ddfbfSEd Maste public:
CommandOptions()579435933ddSDimitry Andric CommandOptions() : Options() {
580435933ddSDimitry Andric // Keep default values of all options in one place: OptionParsingStarting
581435933ddSDimitry Andric // ()
582435933ddSDimitry Andric OptionParsingStarting(nullptr);
583ac7ddfbfSEd Maste }
584ac7ddfbfSEd Maste
5854bb0738eSEd Maste ~CommandOptions() override = default;
586ac7ddfbfSEd Maste
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)5875517e702SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
588435933ddSDimitry Andric ExecutionContext *execution_context) override {
5895517e702SDimitry Andric Status error;
590ac7ddfbfSEd Maste const int short_option = m_getopt_table[option_idx].val;
591435933ddSDimitry Andric switch (short_option) {
592ac7ddfbfSEd Maste case 'i':
593435933ddSDimitry Andric if (option_arg.getAsInteger(0, m_ignore))
594435933ddSDimitry Andric error.SetErrorStringWithFormat(
595435933ddSDimitry Andric "invalid value for ignore option: \"%s\", should be a number.",
596435933ddSDimitry Andric option_arg.str().c_str());
597ac7ddfbfSEd Maste break;
598ac7ddfbfSEd Maste
599ac7ddfbfSEd Maste default:
600435933ddSDimitry Andric error.SetErrorStringWithFormat("invalid short option character '%c'",
601435933ddSDimitry Andric short_option);
602ac7ddfbfSEd Maste break;
603ac7ddfbfSEd Maste }
604ac7ddfbfSEd Maste return error;
605ac7ddfbfSEd Maste }
606ac7ddfbfSEd Maste
OptionParsingStarting(ExecutionContext * execution_context)607435933ddSDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
608ac7ddfbfSEd Maste m_ignore = 0;
609ac7ddfbfSEd Maste }
610ac7ddfbfSEd Maste
GetDefinitions()611435933ddSDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
612435933ddSDimitry Andric return llvm::makeArrayRef(g_process_continue_options);
613ac7ddfbfSEd Maste }
614ac7ddfbfSEd Maste
615ac7ddfbfSEd Maste uint32_t m_ignore;
616ac7ddfbfSEd Maste };
617ac7ddfbfSEd Maste
DoExecute(Args & command,CommandReturnObject & result)618435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override {
619ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr();
620ac7ddfbfSEd Maste bool synchronous_execution = m_interpreter.GetSynchronous();
621ac7ddfbfSEd Maste StateType state = process->GetState();
622435933ddSDimitry Andric if (state == eStateStopped) {
623435933ddSDimitry Andric if (command.GetArgumentCount() != 0) {
624435933ddSDimitry Andric result.AppendErrorWithFormat(
625435933ddSDimitry Andric "The '%s' command does not take any arguments.\n",
626435933ddSDimitry Andric m_cmd_name.c_str());
627ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
628ac7ddfbfSEd Maste return false;
629ac7ddfbfSEd Maste }
630ac7ddfbfSEd Maste
631435933ddSDimitry Andric if (m_options.m_ignore > 0) {
6324bb0738eSEd Maste ThreadSP sel_thread_sp(GetDefaultThread()->shared_from_this());
633435933ddSDimitry Andric if (sel_thread_sp) {
634ac7ddfbfSEd Maste StopInfoSP stop_info_sp = sel_thread_sp->GetStopInfo();
635435933ddSDimitry Andric if (stop_info_sp &&
636435933ddSDimitry Andric stop_info_sp->GetStopReason() == eStopReasonBreakpoint) {
637435933ddSDimitry Andric lldb::break_id_t bp_site_id =
638435933ddSDimitry Andric (lldb::break_id_t)stop_info_sp->GetValue();
639435933ddSDimitry Andric BreakpointSiteSP bp_site_sp(
640435933ddSDimitry Andric process->GetBreakpointSiteList().FindByID(bp_site_id));
641435933ddSDimitry Andric if (bp_site_sp) {
642ac7ddfbfSEd Maste const size_t num_owners = bp_site_sp->GetNumberOfOwners();
643435933ddSDimitry Andric for (size_t i = 0; i < num_owners; i++) {
644435933ddSDimitry Andric Breakpoint &bp_ref =
645435933ddSDimitry Andric bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint();
646435933ddSDimitry Andric if (!bp_ref.IsInternal()) {
647ac7ddfbfSEd Maste bp_ref.SetIgnoreCount(m_options.m_ignore);
648ac7ddfbfSEd Maste }
649ac7ddfbfSEd Maste }
650ac7ddfbfSEd Maste }
651ac7ddfbfSEd Maste }
652ac7ddfbfSEd Maste }
653ac7ddfbfSEd Maste }
654ac7ddfbfSEd Maste
655ac7ddfbfSEd Maste { // Scope for thread list mutex:
656435933ddSDimitry Andric std::lock_guard<std::recursive_mutex> guard(
657435933ddSDimitry Andric process->GetThreadList().GetMutex());
658ac7ddfbfSEd Maste const uint32_t num_threads = process->GetThreadList().GetSize();
659ac7ddfbfSEd Maste
660ac7ddfbfSEd Maste // Set the actions that the threads should each take when resuming
661435933ddSDimitry Andric for (uint32_t idx = 0; idx < num_threads; ++idx) {
6620127ef0fSEd Maste const bool override_suspend = false;
663435933ddSDimitry Andric process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState(
664435933ddSDimitry Andric eStateRunning, override_suspend);
665ac7ddfbfSEd Maste }
666ac7ddfbfSEd Maste }
667ac7ddfbfSEd Maste
6681c3bbb01SEd Maste const uint32_t iohandler_id = process->GetIOHandlerID();
6691c3bbb01SEd Maste
6707aa51b79SEd Maste StreamString stream;
6715517e702SDimitry Andric Status error;
6727aa51b79SEd Maste if (synchronous_execution)
6737aa51b79SEd Maste error = process->ResumeSynchronous(&stream);
6747aa51b79SEd Maste else
6757aa51b79SEd Maste error = process->Resume();
6760127ef0fSEd Maste
677435933ddSDimitry Andric if (error.Success()) {
678435933ddSDimitry Andric // There is a race condition where this thread will return up the call
6794ba319b5SDimitry Andric // stack to the main command handler and show an (lldb) prompt before
6804ba319b5SDimitry Andric // HandlePrivateEvent (from PrivateStateThread) has a chance to call
6814ba319b5SDimitry Andric // PushProcessIOHandler().
6824ba319b5SDimitry Andric process->SyncIOHandler(iohandler_id, std::chrono::seconds(2));
6830127ef0fSEd Maste
684435933ddSDimitry Andric result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n",
685435933ddSDimitry Andric process->GetID());
686435933ddSDimitry Andric if (synchronous_execution) {
687435933ddSDimitry Andric // If any state changed events had anything to say, add that to the
688435933ddSDimitry Andric // result
689435933ddSDimitry Andric result.AppendMessage(stream.GetString());
690ac7ddfbfSEd Maste
691ac7ddfbfSEd Maste result.SetDidChangeProcessState(true);
692ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult);
693435933ddSDimitry Andric } else {
694ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessContinuingNoResult);
695ac7ddfbfSEd Maste }
696435933ddSDimitry Andric } else {
697435933ddSDimitry Andric result.AppendErrorWithFormat("Failed to resume process: %s.\n",
698435933ddSDimitry Andric error.AsCString());
699ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
700ac7ddfbfSEd Maste }
701435933ddSDimitry Andric } else {
702435933ddSDimitry Andric result.AppendErrorWithFormat(
703435933ddSDimitry Andric "Process cannot be continued from its current state (%s).\n",
704ac7ddfbfSEd Maste StateAsCString(state));
705ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
706ac7ddfbfSEd Maste }
707ac7ddfbfSEd Maste return result.Succeeded();
708ac7ddfbfSEd Maste }
709ac7ddfbfSEd Maste
GetOptions()710435933ddSDimitry Andric Options *GetOptions() override { return &m_options; }
711ac7ddfbfSEd Maste
712ac7ddfbfSEd Maste CommandOptions m_options;
713ac7ddfbfSEd Maste };
714ac7ddfbfSEd Maste
715ac7ddfbfSEd Maste //-------------------------------------------------------------------------
716ac7ddfbfSEd Maste // CommandObjectProcessDetach
717ac7ddfbfSEd Maste //-------------------------------------------------------------------------
718*b5893f02SDimitry Andric static constexpr OptionDefinition g_process_detach_options[] = {
719435933ddSDimitry Andric // clang-format off
720*b5893f02SDimitry Andric { LLDB_OPT_SET_1, false, "keep-stopped", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Whether or not the process should be kept stopped on detach (if possible)." },
721435933ddSDimitry Andric // clang-format on
722435933ddSDimitry Andric };
723435933ddSDimitry Andric
724ac7ddfbfSEd Maste #pragma mark CommandObjectProcessDetach
725ac7ddfbfSEd Maste
726435933ddSDimitry Andric class CommandObjectProcessDetach : public CommandObjectParsed {
727ac7ddfbfSEd Maste public:
728435933ddSDimitry Andric class CommandOptions : public Options {
729ac7ddfbfSEd Maste public:
CommandOptions()730435933ddSDimitry Andric CommandOptions() : Options() { OptionParsingStarting(nullptr); }
731ac7ddfbfSEd Maste
7324bb0738eSEd Maste ~CommandOptions() override = default;
733ac7ddfbfSEd Maste
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)7345517e702SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
735435933ddSDimitry Andric ExecutionContext *execution_context) override {
7365517e702SDimitry Andric Status error;
737ac7ddfbfSEd Maste const int short_option = m_getopt_table[option_idx].val;
738ac7ddfbfSEd Maste
739435933ddSDimitry Andric switch (short_option) {
740ac7ddfbfSEd Maste case 's':
741ac7ddfbfSEd Maste bool tmp_result;
742ac7ddfbfSEd Maste bool success;
7434ba319b5SDimitry Andric tmp_result = OptionArgParser::ToBoolean(option_arg, false, &success);
744ac7ddfbfSEd Maste if (!success)
745435933ddSDimitry Andric error.SetErrorStringWithFormat("invalid boolean option: \"%s\"",
746435933ddSDimitry Andric option_arg.str().c_str());
747435933ddSDimitry Andric else {
748ac7ddfbfSEd Maste if (tmp_result)
749ac7ddfbfSEd Maste m_keep_stopped = eLazyBoolYes;
750ac7ddfbfSEd Maste else
751ac7ddfbfSEd Maste m_keep_stopped = eLazyBoolNo;
752ac7ddfbfSEd Maste }
753ac7ddfbfSEd Maste break;
754ac7ddfbfSEd Maste default:
755435933ddSDimitry Andric error.SetErrorStringWithFormat("invalid short option character '%c'",
756435933ddSDimitry Andric short_option);
757ac7ddfbfSEd Maste break;
758ac7ddfbfSEd Maste }
759ac7ddfbfSEd Maste return error;
760ac7ddfbfSEd Maste }
761ac7ddfbfSEd Maste
OptionParsingStarting(ExecutionContext * execution_context)762435933ddSDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
763ac7ddfbfSEd Maste m_keep_stopped = eLazyBoolCalculate;
764ac7ddfbfSEd Maste }
765ac7ddfbfSEd Maste
GetDefinitions()766435933ddSDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
767435933ddSDimitry Andric return llvm::makeArrayRef(g_process_detach_options);
768ac7ddfbfSEd Maste }
769ac7ddfbfSEd Maste
770ac7ddfbfSEd Maste // Instance variables to hold the values for command options.
771ac7ddfbfSEd Maste LazyBool m_keep_stopped;
772ac7ddfbfSEd Maste };
773ac7ddfbfSEd Maste
CommandObjectProcessDetach(CommandInterpreter & interpreter)7744bb0738eSEd Maste CommandObjectProcessDetach(CommandInterpreter &interpreter)
775435933ddSDimitry Andric : CommandObjectParsed(interpreter, "process detach",
776435933ddSDimitry Andric "Detach from the current target process.",
777ac7ddfbfSEd Maste "process detach",
778435933ddSDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock |
779435933ddSDimitry Andric eCommandProcessMustBeLaunched),
780435933ddSDimitry Andric m_options() {}
781ac7ddfbfSEd Maste
7824bb0738eSEd Maste ~CommandObjectProcessDetach() override = default;
783ac7ddfbfSEd Maste
GetOptions()784435933ddSDimitry Andric Options *GetOptions() override { return &m_options; }
785ac7ddfbfSEd Maste
786ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)787435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override {
788ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr();
789ac7ddfbfSEd Maste // FIXME: This will be a Command Option:
790ac7ddfbfSEd Maste bool keep_stopped;
791435933ddSDimitry Andric if (m_options.m_keep_stopped == eLazyBoolCalculate) {
792ac7ddfbfSEd Maste // Check the process default:
7934bb0738eSEd Maste keep_stopped = process->GetDetachKeepsStopped();
794435933ddSDimitry Andric } else if (m_options.m_keep_stopped == eLazyBoolYes)
795ac7ddfbfSEd Maste keep_stopped = true;
796ac7ddfbfSEd Maste else
797ac7ddfbfSEd Maste keep_stopped = false;
798ac7ddfbfSEd Maste
7995517e702SDimitry Andric Status error(process->Detach(keep_stopped));
800435933ddSDimitry Andric if (error.Success()) {
801ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult);
802435933ddSDimitry Andric } else {
803ac7ddfbfSEd Maste result.AppendErrorWithFormat("Detach failed: %s\n", error.AsCString());
804ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
805ac7ddfbfSEd Maste return false;
806ac7ddfbfSEd Maste }
807ac7ddfbfSEd Maste return result.Succeeded();
808ac7ddfbfSEd Maste }
809ac7ddfbfSEd Maste
810ac7ddfbfSEd Maste CommandOptions m_options;
811ac7ddfbfSEd Maste };
812ac7ddfbfSEd Maste
813ac7ddfbfSEd Maste //-------------------------------------------------------------------------
814ac7ddfbfSEd Maste // CommandObjectProcessConnect
815ac7ddfbfSEd Maste //-------------------------------------------------------------------------
816435933ddSDimitry Andric
817*b5893f02SDimitry Andric static constexpr OptionDefinition g_process_connect_options[] = {
818435933ddSDimitry Andric // clang-format off
819*b5893f02SDimitry Andric { LLDB_OPT_SET_ALL, false, "plugin", 'p', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePlugin, "Name of the process plugin you want to use." },
820435933ddSDimitry Andric // clang-format on
821435933ddSDimitry Andric };
822435933ddSDimitry Andric
823ac7ddfbfSEd Maste #pragma mark CommandObjectProcessConnect
824ac7ddfbfSEd Maste
825435933ddSDimitry Andric class CommandObjectProcessConnect : public CommandObjectParsed {
826ac7ddfbfSEd Maste public:
827435933ddSDimitry Andric class CommandOptions : public Options {
828ac7ddfbfSEd Maste public:
CommandOptions()829435933ddSDimitry Andric CommandOptions() : Options() {
830435933ddSDimitry Andric // Keep default values of all options in one place: OptionParsingStarting
831435933ddSDimitry Andric // ()
832435933ddSDimitry Andric OptionParsingStarting(nullptr);
833ac7ddfbfSEd Maste }
834ac7ddfbfSEd Maste
8354bb0738eSEd Maste ~CommandOptions() override = default;
836ac7ddfbfSEd Maste
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)8375517e702SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
838435933ddSDimitry Andric ExecutionContext *execution_context) override {
8395517e702SDimitry Andric Status error;
840ac7ddfbfSEd Maste const int short_option = m_getopt_table[option_idx].val;
841ac7ddfbfSEd Maste
842435933ddSDimitry Andric switch (short_option) {
843ac7ddfbfSEd Maste case 'p':
844ac7ddfbfSEd Maste plugin_name.assign(option_arg);
845ac7ddfbfSEd Maste break;
846ac7ddfbfSEd Maste
847ac7ddfbfSEd Maste default:
848435933ddSDimitry Andric error.SetErrorStringWithFormat("invalid short option character '%c'",
849435933ddSDimitry Andric short_option);
850ac7ddfbfSEd Maste break;
851ac7ddfbfSEd Maste }
852ac7ddfbfSEd Maste return error;
853ac7ddfbfSEd Maste }
854ac7ddfbfSEd Maste
OptionParsingStarting(ExecutionContext * execution_context)855435933ddSDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
856ac7ddfbfSEd Maste plugin_name.clear();
857ac7ddfbfSEd Maste }
858ac7ddfbfSEd Maste
GetDefinitions()859435933ddSDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
860435933ddSDimitry Andric return llvm::makeArrayRef(g_process_connect_options);
861ac7ddfbfSEd Maste }
862ac7ddfbfSEd Maste
863ac7ddfbfSEd Maste // Instance variables to hold the values for command options.
864ac7ddfbfSEd Maste
865ac7ddfbfSEd Maste std::string plugin_name;
866ac7ddfbfSEd Maste };
867ac7ddfbfSEd Maste
CommandObjectProcessConnect(CommandInterpreter & interpreter)868435933ddSDimitry Andric CommandObjectProcessConnect(CommandInterpreter &interpreter)
869435933ddSDimitry Andric : CommandObjectParsed(interpreter, "process connect",
870ac7ddfbfSEd Maste "Connect to a remote debug service.",
871435933ddSDimitry Andric "process connect <remote-url>", 0),
872435933ddSDimitry Andric m_options() {}
873ac7ddfbfSEd Maste
8744bb0738eSEd Maste ~CommandObjectProcessConnect() override = default;
875ac7ddfbfSEd Maste
GetOptions()876435933ddSDimitry Andric Options *GetOptions() override { return &m_options; }
877ac7ddfbfSEd Maste
878ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)879435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override {
880435933ddSDimitry Andric if (command.GetArgumentCount() != 1) {
881435933ddSDimitry Andric result.AppendErrorWithFormat(
882435933ddSDimitry Andric "'%s' takes exactly one argument:\nUsage: %s\n", m_cmd_name.c_str(),
8839f2f44ceSEd Maste m_cmd_syntax.c_str());
8849f2f44ceSEd Maste result.SetStatus(eReturnStatusFailed);
8859f2f44ceSEd Maste return false;
8869f2f44ceSEd Maste }
887ac7ddfbfSEd Maste
888ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr();
889435933ddSDimitry Andric if (process && process->IsAlive()) {
890435933ddSDimitry Andric result.AppendErrorWithFormat(
891435933ddSDimitry Andric "Process %" PRIu64
892435933ddSDimitry Andric " is currently being debugged, kill the process before connecting.\n",
893ac7ddfbfSEd Maste process->GetID());
894ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
895ac7ddfbfSEd Maste return false;
896ac7ddfbfSEd Maste }
897ac7ddfbfSEd Maste
8989f2f44ceSEd Maste const char *plugin_name = nullptr;
899ac7ddfbfSEd Maste if (!m_options.plugin_name.empty())
900ac7ddfbfSEd Maste plugin_name = m_options.plugin_name.c_str();
901ac7ddfbfSEd Maste
9025517e702SDimitry Andric Status error;
9039f2f44ceSEd Maste Debugger &debugger = m_interpreter.GetDebugger();
9049f2f44ceSEd Maste PlatformSP platform_sp = m_interpreter.GetPlatform(true);
905435933ddSDimitry Andric ProcessSP process_sp = platform_sp->ConnectProcess(
906435933ddSDimitry Andric command.GetArgumentAtIndex(0), plugin_name, debugger,
907435933ddSDimitry Andric debugger.GetSelectedTarget().get(), error);
908435933ddSDimitry Andric if (error.Fail() || process_sp == nullptr) {
9099f2f44ceSEd Maste result.AppendError(error.AsCString("Error connecting to the process"));
910ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
911ac7ddfbfSEd Maste return false;
912ac7ddfbfSEd Maste }
9139f2f44ceSEd Maste return true;
914ac7ddfbfSEd Maste }
915ac7ddfbfSEd Maste
916ac7ddfbfSEd Maste CommandOptions m_options;
917ac7ddfbfSEd Maste };
918ac7ddfbfSEd Maste
919ac7ddfbfSEd Maste //-------------------------------------------------------------------------
920ac7ddfbfSEd Maste // CommandObjectProcessPlugin
921ac7ddfbfSEd Maste //-------------------------------------------------------------------------
922ac7ddfbfSEd Maste #pragma mark CommandObjectProcessPlugin
923ac7ddfbfSEd Maste
924435933ddSDimitry Andric class CommandObjectProcessPlugin : public CommandObjectProxy {
925ac7ddfbfSEd Maste public:
CommandObjectProcessPlugin(CommandInterpreter & interpreter)9264bb0738eSEd Maste CommandObjectProcessPlugin(CommandInterpreter &interpreter)
927435933ddSDimitry Andric : CommandObjectProxy(
928435933ddSDimitry Andric interpreter, "process plugin",
929435933ddSDimitry Andric "Send a custom command to the current target process plug-in.",
930435933ddSDimitry Andric "process plugin <args>", 0) {}
931ac7ddfbfSEd Maste
9324bb0738eSEd Maste ~CommandObjectProcessPlugin() override = default;
933ac7ddfbfSEd Maste
GetProxyCommandObject()934435933ddSDimitry Andric CommandObject *GetProxyCommandObject() override {
935ac7ddfbfSEd Maste Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
936ac7ddfbfSEd Maste if (process)
937ac7ddfbfSEd Maste return process->GetPluginCommandObject();
9384bb0738eSEd Maste return nullptr;
939ac7ddfbfSEd Maste }
940ac7ddfbfSEd Maste };
941ac7ddfbfSEd Maste
942ac7ddfbfSEd Maste //-------------------------------------------------------------------------
943ac7ddfbfSEd Maste // CommandObjectProcessLoad
944ac7ddfbfSEd Maste //-------------------------------------------------------------------------
945435933ddSDimitry Andric
946*b5893f02SDimitry Andric static constexpr OptionDefinition g_process_load_options[] = {
947435933ddSDimitry Andric // clang-format off
948*b5893f02SDimitry Andric { LLDB_OPT_SET_ALL, false, "install", 'i', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypePath, "Install the shared library to the target. If specified without an argument then the library will installed in the current working directory." },
949435933ddSDimitry Andric // clang-format on
950435933ddSDimitry Andric };
951435933ddSDimitry Andric
952ac7ddfbfSEd Maste #pragma mark CommandObjectProcessLoad
953ac7ddfbfSEd Maste
954435933ddSDimitry Andric class CommandObjectProcessLoad : public CommandObjectParsed {
955ac7ddfbfSEd Maste public:
956435933ddSDimitry Andric class CommandOptions : public Options {
9579f2f44ceSEd Maste public:
CommandOptions()958435933ddSDimitry Andric CommandOptions() : Options() {
959435933ddSDimitry Andric // Keep default values of all options in one place: OptionParsingStarting
960435933ddSDimitry Andric // ()
961435933ddSDimitry Andric OptionParsingStarting(nullptr);
9629f2f44ceSEd Maste }
9639f2f44ceSEd Maste
9649f2f44ceSEd Maste ~CommandOptions() override = default;
9659f2f44ceSEd Maste
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)9665517e702SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
967435933ddSDimitry Andric ExecutionContext *execution_context) override {
9685517e702SDimitry Andric Status error;
9699f2f44ceSEd Maste const int short_option = m_getopt_table[option_idx].val;
970435933ddSDimitry Andric switch (short_option) {
9719f2f44ceSEd Maste case 'i':
9729f2f44ceSEd Maste do_install = true;
973435933ddSDimitry Andric if (!option_arg.empty())
974*b5893f02SDimitry Andric install_path.SetFile(option_arg, FileSpec::Style::native);
9759f2f44ceSEd Maste break;
9769f2f44ceSEd Maste default:
977435933ddSDimitry Andric error.SetErrorStringWithFormat("invalid short option character '%c'",
978435933ddSDimitry Andric short_option);
9799f2f44ceSEd Maste break;
9809f2f44ceSEd Maste }
9819f2f44ceSEd Maste return error;
9829f2f44ceSEd Maste }
9839f2f44ceSEd Maste
OptionParsingStarting(ExecutionContext * execution_context)984435933ddSDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
9859f2f44ceSEd Maste do_install = false;
9869f2f44ceSEd Maste install_path.Clear();
9879f2f44ceSEd Maste }
9889f2f44ceSEd Maste
GetDefinitions()989435933ddSDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
990435933ddSDimitry Andric return llvm::makeArrayRef(g_process_load_options);
9919f2f44ceSEd Maste }
9929f2f44ceSEd Maste
9939f2f44ceSEd Maste // Instance variables to hold the values for command options.
9949f2f44ceSEd Maste bool do_install;
9959f2f44ceSEd Maste FileSpec install_path;
9969f2f44ceSEd Maste };
997ac7ddfbfSEd Maste
CommandObjectProcessLoad(CommandInterpreter & interpreter)998435933ddSDimitry Andric CommandObjectProcessLoad(CommandInterpreter &interpreter)
999435933ddSDimitry Andric : CommandObjectParsed(interpreter, "process load",
1000ac7ddfbfSEd Maste "Load a shared library into the current process.",
1001ac7ddfbfSEd Maste "process load <filename> [<filename> ...]",
1002435933ddSDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock |
10031c3bbb01SEd Maste eCommandProcessMustBeLaunched |
10049f2f44ceSEd Maste eCommandProcessMustBePaused),
1005435933ddSDimitry Andric m_options() {}
1006ac7ddfbfSEd Maste
10079f2f44ceSEd Maste ~CommandObjectProcessLoad() override = default;
10089f2f44ceSEd Maste
GetOptions()1009435933ddSDimitry Andric Options *GetOptions() override { return &m_options; }
1010ac7ddfbfSEd Maste
1011ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)1012435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override {
1013ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr();
1014ac7ddfbfSEd Maste
1015435933ddSDimitry Andric for (auto &entry : command.entries()) {
10165517e702SDimitry Andric Status error;
10179f2f44ceSEd Maste PlatformSP platform = process->GetTarget().GetPlatform();
1018435933ddSDimitry Andric llvm::StringRef image_path = entry.ref;
10199f2f44ceSEd Maste uint32_t image_token = LLDB_INVALID_IMAGE_TOKEN;
10209f2f44ceSEd Maste
1021435933ddSDimitry Andric if (!m_options.do_install) {
1022*b5893f02SDimitry Andric FileSpec image_spec(image_path);
10239f2f44ceSEd Maste platform->ResolveRemotePath(image_spec, image_spec);
1024435933ddSDimitry Andric image_token =
1025435933ddSDimitry Andric platform->LoadImage(process, FileSpec(), image_spec, error);
1026435933ddSDimitry Andric } else if (m_options.install_path) {
1027*b5893f02SDimitry Andric FileSpec image_spec(image_path);
1028*b5893f02SDimitry Andric FileSystem::Instance().Resolve(image_spec);
1029435933ddSDimitry Andric platform->ResolveRemotePath(m_options.install_path,
1030435933ddSDimitry Andric m_options.install_path);
1031435933ddSDimitry Andric image_token = platform->LoadImage(process, image_spec,
1032435933ddSDimitry Andric m_options.install_path, error);
1033435933ddSDimitry Andric } else {
1034*b5893f02SDimitry Andric FileSpec image_spec(image_path);
1035*b5893f02SDimitry Andric FileSystem::Instance().Resolve(image_spec);
1036435933ddSDimitry Andric image_token =
1037435933ddSDimitry Andric platform->LoadImage(process, image_spec, FileSpec(), error);
10389f2f44ceSEd Maste }
10399f2f44ceSEd Maste
1040435933ddSDimitry Andric if (image_token != LLDB_INVALID_IMAGE_TOKEN) {
1041435933ddSDimitry Andric result.AppendMessageWithFormat(
1042435933ddSDimitry Andric "Loading \"%s\"...ok\nImage %u loaded.\n", image_path.str().c_str(),
1043435933ddSDimitry Andric image_token);
1044ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult);
1045435933ddSDimitry Andric } else {
1046435933ddSDimitry Andric result.AppendErrorWithFormat("failed to load '%s': %s",
1047435933ddSDimitry Andric image_path.str().c_str(),
1048435933ddSDimitry Andric error.AsCString());
1049ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
1050ac7ddfbfSEd Maste }
1051ac7ddfbfSEd Maste }
1052ac7ddfbfSEd Maste return result.Succeeded();
1053ac7ddfbfSEd Maste }
10549f2f44ceSEd Maste
10559f2f44ceSEd Maste CommandOptions m_options;
1056ac7ddfbfSEd Maste };
1057ac7ddfbfSEd Maste
1058ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1059ac7ddfbfSEd Maste // CommandObjectProcessUnload
1060ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1061ac7ddfbfSEd Maste #pragma mark CommandObjectProcessUnload
1062ac7ddfbfSEd Maste
1063435933ddSDimitry Andric class CommandObjectProcessUnload : public CommandObjectParsed {
1064ac7ddfbfSEd Maste public:
CommandObjectProcessUnload(CommandInterpreter & interpreter)1065435933ddSDimitry Andric CommandObjectProcessUnload(CommandInterpreter &interpreter)
1066435933ddSDimitry Andric : CommandObjectParsed(
1067435933ddSDimitry Andric interpreter, "process unload",
1068435933ddSDimitry Andric "Unload a shared library from the current process using the index "
1069435933ddSDimitry Andric "returned by a previous call to \"process load\".",
1070ac7ddfbfSEd Maste "process unload <index>",
1071435933ddSDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock |
1072435933ddSDimitry Andric eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {}
1073ac7ddfbfSEd Maste
10744bb0738eSEd Maste ~CommandObjectProcessUnload() override = default;
1075ac7ddfbfSEd Maste
1076ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)1077435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override {
1078ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr();
1079ac7ddfbfSEd Maste
1080435933ddSDimitry Andric for (auto &entry : command.entries()) {
1081435933ddSDimitry Andric uint32_t image_token;
1082435933ddSDimitry Andric if (entry.ref.getAsInteger(0, image_token)) {
1083435933ddSDimitry Andric result.AppendErrorWithFormat("invalid image index argument '%s'",
1084435933ddSDimitry Andric entry.ref.str().c_str());
1085ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
1086ac7ddfbfSEd Maste break;
1087435933ddSDimitry Andric } else {
10885517e702SDimitry Andric Status error(process->GetTarget().GetPlatform()->UnloadImage(
1089435933ddSDimitry Andric process, image_token));
1090435933ddSDimitry Andric if (error.Success()) {
1091435933ddSDimitry Andric result.AppendMessageWithFormat(
1092435933ddSDimitry Andric "Unloading shared library with index %u...ok\n", image_token);
1093ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult);
1094435933ddSDimitry Andric } else {
1095435933ddSDimitry Andric result.AppendErrorWithFormat("failed to unload image: %s",
1096435933ddSDimitry Andric error.AsCString());
1097ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
1098ac7ddfbfSEd Maste break;
1099ac7ddfbfSEd Maste }
1100ac7ddfbfSEd Maste }
1101ac7ddfbfSEd Maste }
1102ac7ddfbfSEd Maste return result.Succeeded();
1103ac7ddfbfSEd Maste }
1104ac7ddfbfSEd Maste };
1105ac7ddfbfSEd Maste
1106ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1107ac7ddfbfSEd Maste // CommandObjectProcessSignal
1108ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1109ac7ddfbfSEd Maste #pragma mark CommandObjectProcessSignal
1110ac7ddfbfSEd Maste
1111435933ddSDimitry Andric class CommandObjectProcessSignal : public CommandObjectParsed {
1112ac7ddfbfSEd Maste public:
CommandObjectProcessSignal(CommandInterpreter & interpreter)11134bb0738eSEd Maste CommandObjectProcessSignal(CommandInterpreter &interpreter)
1114435933ddSDimitry Andric : CommandObjectParsed(interpreter, "process signal",
1115435933ddSDimitry Andric "Send a UNIX signal to the current target process.",
1116435933ddSDimitry Andric nullptr, eCommandRequiresProcess |
1117435933ddSDimitry Andric eCommandTryTargetAPILock) {
1118ac7ddfbfSEd Maste CommandArgumentEntry arg;
1119ac7ddfbfSEd Maste CommandArgumentData signal_arg;
1120ac7ddfbfSEd Maste
1121ac7ddfbfSEd Maste // Define the first (and only) variant of this arg.
1122ac7ddfbfSEd Maste signal_arg.arg_type = eArgTypeUnixSignal;
1123ac7ddfbfSEd Maste signal_arg.arg_repetition = eArgRepeatPlain;
1124ac7ddfbfSEd Maste
1125435933ddSDimitry Andric // There is only one variant this argument could be; put it into the
1126435933ddSDimitry Andric // argument entry.
1127ac7ddfbfSEd Maste arg.push_back(signal_arg);
1128ac7ddfbfSEd Maste
1129ac7ddfbfSEd Maste // Push the data for the first argument into the m_arguments vector.
1130ac7ddfbfSEd Maste m_arguments.push_back(arg);
1131ac7ddfbfSEd Maste }
1132ac7ddfbfSEd Maste
11334bb0738eSEd Maste ~CommandObjectProcessSignal() override = default;
1134ac7ddfbfSEd Maste
1135ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)1136435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override {
1137ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr();
1138ac7ddfbfSEd Maste
1139435933ddSDimitry Andric if (command.GetArgumentCount() == 1) {
1140ac7ddfbfSEd Maste int signo = LLDB_INVALID_SIGNAL_NUMBER;
1141ac7ddfbfSEd Maste
1142ac7ddfbfSEd Maste const char *signal_name = command.GetArgumentAtIndex(0);
1143ac7ddfbfSEd Maste if (::isxdigit(signal_name[0]))
1144435933ddSDimitry Andric signo =
1145435933ddSDimitry Andric StringConvert::ToSInt32(signal_name, LLDB_INVALID_SIGNAL_NUMBER, 0);
1146ac7ddfbfSEd Maste else
1147b91a7dfcSDimitry Andric signo = process->GetUnixSignals()->GetSignalNumberFromName(signal_name);
1148ac7ddfbfSEd Maste
1149435933ddSDimitry Andric if (signo == LLDB_INVALID_SIGNAL_NUMBER) {
1150435933ddSDimitry Andric result.AppendErrorWithFormat("Invalid signal argument '%s'.\n",
1151435933ddSDimitry Andric command.GetArgumentAtIndex(0));
1152ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
1153435933ddSDimitry Andric } else {
11545517e702SDimitry Andric Status error(process->Signal(signo));
1155435933ddSDimitry Andric if (error.Success()) {
1156ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult);
1157435933ddSDimitry Andric } else {
1158435933ddSDimitry Andric result.AppendErrorWithFormat("Failed to send signal %i: %s\n", signo,
1159435933ddSDimitry Andric error.AsCString());
1160ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
1161ac7ddfbfSEd Maste }
1162ac7ddfbfSEd Maste }
1163435933ddSDimitry Andric } else {
1164435933ddSDimitry Andric result.AppendErrorWithFormat(
1165435933ddSDimitry Andric "'%s' takes exactly one signal number argument:\nUsage: %s\n",
1166435933ddSDimitry Andric m_cmd_name.c_str(), m_cmd_syntax.c_str());
1167ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
1168ac7ddfbfSEd Maste }
1169ac7ddfbfSEd Maste return result.Succeeded();
1170ac7ddfbfSEd Maste }
1171ac7ddfbfSEd Maste };
1172ac7ddfbfSEd Maste
1173ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1174ac7ddfbfSEd Maste // CommandObjectProcessInterrupt
1175ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1176ac7ddfbfSEd Maste #pragma mark CommandObjectProcessInterrupt
1177ac7ddfbfSEd Maste
1178435933ddSDimitry Andric class CommandObjectProcessInterrupt : public CommandObjectParsed {
1179ac7ddfbfSEd Maste public:
CommandObjectProcessInterrupt(CommandInterpreter & interpreter)11804bb0738eSEd Maste CommandObjectProcessInterrupt(CommandInterpreter &interpreter)
1181435933ddSDimitry Andric : CommandObjectParsed(interpreter, "process interrupt",
1182435933ddSDimitry Andric "Interrupt the current target process.",
1183ac7ddfbfSEd Maste "process interrupt",
1184435933ddSDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock |
1185435933ddSDimitry Andric eCommandProcessMustBeLaunched) {}
1186ac7ddfbfSEd Maste
11874bb0738eSEd Maste ~CommandObjectProcessInterrupt() override = default;
1188ac7ddfbfSEd Maste
1189ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)1190435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override {
1191ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr();
1192435933ddSDimitry Andric if (process == nullptr) {
1193ac7ddfbfSEd Maste result.AppendError("no process to halt");
1194ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
1195ac7ddfbfSEd Maste return false;
1196ac7ddfbfSEd Maste }
1197ac7ddfbfSEd Maste
1198435933ddSDimitry Andric if (command.GetArgumentCount() == 0) {
1199ac7ddfbfSEd Maste bool clear_thread_plans = true;
12005517e702SDimitry Andric Status error(process->Halt(clear_thread_plans));
1201435933ddSDimitry Andric if (error.Success()) {
1202ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult);
1203435933ddSDimitry Andric } else {
1204435933ddSDimitry Andric result.AppendErrorWithFormat("Failed to halt process: %s\n",
1205435933ddSDimitry Andric error.AsCString());
1206ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
1207ac7ddfbfSEd Maste }
1208435933ddSDimitry Andric } else {
1209ac7ddfbfSEd Maste result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n",
1210435933ddSDimitry Andric m_cmd_name.c_str(), m_cmd_syntax.c_str());
1211ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
1212ac7ddfbfSEd Maste }
1213ac7ddfbfSEd Maste return result.Succeeded();
1214ac7ddfbfSEd Maste }
1215ac7ddfbfSEd Maste };
1216ac7ddfbfSEd Maste
1217ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1218ac7ddfbfSEd Maste // CommandObjectProcessKill
1219ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1220ac7ddfbfSEd Maste #pragma mark CommandObjectProcessKill
1221ac7ddfbfSEd Maste
1222435933ddSDimitry Andric class CommandObjectProcessKill : public CommandObjectParsed {
1223ac7ddfbfSEd Maste public:
CommandObjectProcessKill(CommandInterpreter & interpreter)12244bb0738eSEd Maste CommandObjectProcessKill(CommandInterpreter &interpreter)
1225435933ddSDimitry Andric : CommandObjectParsed(interpreter, "process kill",
1226435933ddSDimitry Andric "Terminate the current target process.",
1227435933ddSDimitry Andric "process kill",
1228435933ddSDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock |
1229435933ddSDimitry Andric eCommandProcessMustBeLaunched) {}
1230ac7ddfbfSEd Maste
12314bb0738eSEd Maste ~CommandObjectProcessKill() override = default;
1232ac7ddfbfSEd Maste
1233ac7ddfbfSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)1234435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override {
1235ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr();
1236435933ddSDimitry Andric if (process == nullptr) {
1237ac7ddfbfSEd Maste result.AppendError("no process to kill");
1238ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
1239ac7ddfbfSEd Maste return false;
1240ac7ddfbfSEd Maste }
1241ac7ddfbfSEd Maste
1242435933ddSDimitry Andric if (command.GetArgumentCount() == 0) {
12435517e702SDimitry Andric Status error(process->Destroy(true));
1244435933ddSDimitry Andric if (error.Success()) {
1245ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult);
1246435933ddSDimitry Andric } else {
1247435933ddSDimitry Andric result.AppendErrorWithFormat("Failed to kill process: %s\n",
1248435933ddSDimitry Andric error.AsCString());
1249ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
1250ac7ddfbfSEd Maste }
1251435933ddSDimitry Andric } else {
1252ac7ddfbfSEd Maste result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n",
1253435933ddSDimitry Andric m_cmd_name.c_str(), m_cmd_syntax.c_str());
1254ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
1255ac7ddfbfSEd Maste }
1256ac7ddfbfSEd Maste return result.Succeeded();
1257ac7ddfbfSEd Maste }
1258ac7ddfbfSEd Maste };
1259ac7ddfbfSEd Maste
1260ac7ddfbfSEd Maste //-------------------------------------------------------------------------
12610127ef0fSEd Maste // CommandObjectProcessSaveCore
12620127ef0fSEd Maste //-------------------------------------------------------------------------
12630127ef0fSEd Maste #pragma mark CommandObjectProcessSaveCore
12640127ef0fSEd Maste
1265435933ddSDimitry Andric class CommandObjectProcessSaveCore : public CommandObjectParsed {
12660127ef0fSEd Maste public:
CommandObjectProcessSaveCore(CommandInterpreter & interpreter)1267435933ddSDimitry Andric CommandObjectProcessSaveCore(CommandInterpreter &interpreter)
1268435933ddSDimitry Andric : CommandObjectParsed(interpreter, "process save-core",
1269435933ddSDimitry Andric "Save the current process as a core file using an "
1270435933ddSDimitry Andric "appropriate file type.",
12710127ef0fSEd Maste "process save-core FILE",
1272435933ddSDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock |
1273435933ddSDimitry Andric eCommandProcessMustBeLaunched) {}
12740127ef0fSEd Maste
12754bb0738eSEd Maste ~CommandObjectProcessSaveCore() override = default;
12760127ef0fSEd Maste
12770127ef0fSEd Maste protected:
DoExecute(Args & command,CommandReturnObject & result)1278435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override {
12790127ef0fSEd Maste ProcessSP process_sp = m_exe_ctx.GetProcessSP();
1280435933ddSDimitry Andric if (process_sp) {
1281435933ddSDimitry Andric if (command.GetArgumentCount() == 1) {
1282*b5893f02SDimitry Andric FileSpec output_file(command.GetArgumentAtIndex(0));
12835517e702SDimitry Andric Status error = PluginManager::SaveCore(process_sp, output_file);
1284435933ddSDimitry Andric if (error.Success()) {
12850127ef0fSEd Maste result.SetStatus(eReturnStatusSuccessFinishResult);
1286435933ddSDimitry Andric } else {
1287435933ddSDimitry Andric result.AppendErrorWithFormat(
1288435933ddSDimitry Andric "Failed to save core file for process: %s\n", error.AsCString());
12890127ef0fSEd Maste result.SetStatus(eReturnStatusFailed);
12900127ef0fSEd Maste }
1291435933ddSDimitry Andric } else {
12920127ef0fSEd Maste result.AppendErrorWithFormat("'%s' takes one arguments:\nUsage: %s\n",
1293435933ddSDimitry Andric m_cmd_name.c_str(), m_cmd_syntax.c_str());
12940127ef0fSEd Maste result.SetStatus(eReturnStatusFailed);
12950127ef0fSEd Maste }
1296435933ddSDimitry Andric } else {
12970127ef0fSEd Maste result.AppendError("invalid process");
12980127ef0fSEd Maste result.SetStatus(eReturnStatusFailed);
12990127ef0fSEd Maste return false;
13000127ef0fSEd Maste }
13010127ef0fSEd Maste
13020127ef0fSEd Maste return result.Succeeded();
13030127ef0fSEd Maste }
13040127ef0fSEd Maste };
13050127ef0fSEd Maste
13060127ef0fSEd Maste //-------------------------------------------------------------------------
1307ac7ddfbfSEd Maste // CommandObjectProcessStatus
1308ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1309ac7ddfbfSEd Maste #pragma mark CommandObjectProcessStatus
1310ac7ddfbfSEd Maste
1311435933ddSDimitry Andric class CommandObjectProcessStatus : public CommandObjectParsed {
1312ac7ddfbfSEd Maste public:
CommandObjectProcessStatus(CommandInterpreter & interpreter)13134bb0738eSEd Maste CommandObjectProcessStatus(CommandInterpreter &interpreter)
1314435933ddSDimitry Andric : CommandObjectParsed(
1315435933ddSDimitry Andric interpreter, "process status",
1316435933ddSDimitry Andric "Show status and stop location for the current target process.",
1317435933ddSDimitry Andric "process status",
1318435933ddSDimitry Andric eCommandRequiresProcess | eCommandTryTargetAPILock) {}
1319ac7ddfbfSEd Maste
13204bb0738eSEd Maste ~CommandObjectProcessStatus() override = default;
1321ac7ddfbfSEd Maste
DoExecute(Args & command,CommandReturnObject & result)1322435933ddSDimitry Andric bool DoExecute(Args &command, CommandReturnObject &result) override {
1323ac7ddfbfSEd Maste Stream &strm = result.GetOutputStream();
1324ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult);
1325435933ddSDimitry Andric // No need to check "process" for validity as eCommandRequiresProcess
1326435933ddSDimitry Andric // ensures it is valid
1327ac7ddfbfSEd Maste Process *process = m_exe_ctx.GetProcessPtr();
1328ac7ddfbfSEd Maste const bool only_threads_with_stop_reason = true;
1329ac7ddfbfSEd Maste const uint32_t start_frame = 0;
1330ac7ddfbfSEd Maste const uint32_t num_frames = 1;
1331ac7ddfbfSEd Maste const uint32_t num_frames_with_source = 1;
1332435933ddSDimitry Andric const bool stop_format = true;
1333ac7ddfbfSEd Maste process->GetStatus(strm);
1334435933ddSDimitry Andric process->GetThreadStatus(strm, only_threads_with_stop_reason, start_frame,
1335435933ddSDimitry Andric num_frames, num_frames_with_source, stop_format);
1336ac7ddfbfSEd Maste return result.Succeeded();
1337ac7ddfbfSEd Maste }
1338ac7ddfbfSEd Maste };
1339ac7ddfbfSEd Maste
1340ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1341ac7ddfbfSEd Maste // CommandObjectProcessHandle
1342ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1343435933ddSDimitry Andric
1344*b5893f02SDimitry Andric static constexpr OptionDefinition g_process_handle_options[] = {
1345435933ddSDimitry Andric // clang-format off
1346*b5893f02SDimitry Andric { LLDB_OPT_SET_1, false, "stop", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Whether or not the process should be stopped if the signal is received." },
1347*b5893f02SDimitry Andric { LLDB_OPT_SET_1, false, "notify", 'n', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Whether or not the debugger should notify the user if the signal is received." },
1348*b5893f02SDimitry Andric { LLDB_OPT_SET_1, false, "pass", 'p', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." }
1349435933ddSDimitry Andric // clang-format on
1350435933ddSDimitry Andric };
1351435933ddSDimitry Andric
1352ac7ddfbfSEd Maste #pragma mark CommandObjectProcessHandle
1353ac7ddfbfSEd Maste
1354435933ddSDimitry Andric class CommandObjectProcessHandle : public CommandObjectParsed {
1355ac7ddfbfSEd Maste public:
1356435933ddSDimitry Andric class CommandOptions : public Options {
1357ac7ddfbfSEd Maste public:
CommandOptions()1358435933ddSDimitry Andric CommandOptions() : Options() { OptionParsingStarting(nullptr); }
1359ac7ddfbfSEd Maste
13604bb0738eSEd Maste ~CommandOptions() override = default;
1361ac7ddfbfSEd Maste
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)13625517e702SDimitry Andric Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1363435933ddSDimitry Andric ExecutionContext *execution_context) override {
13645517e702SDimitry Andric Status error;
1365ac7ddfbfSEd Maste const int short_option = m_getopt_table[option_idx].val;
1366ac7ddfbfSEd Maste
1367435933ddSDimitry Andric switch (short_option) {
1368ac7ddfbfSEd Maste case 's':
1369ac7ddfbfSEd Maste stop = option_arg;
1370ac7ddfbfSEd Maste break;
1371ac7ddfbfSEd Maste case 'n':
1372ac7ddfbfSEd Maste notify = option_arg;
1373ac7ddfbfSEd Maste break;
1374ac7ddfbfSEd Maste case 'p':
1375ac7ddfbfSEd Maste pass = option_arg;
1376ac7ddfbfSEd Maste break;
1377ac7ddfbfSEd Maste default:
1378435933ddSDimitry Andric error.SetErrorStringWithFormat("invalid short option character '%c'",
1379435933ddSDimitry Andric short_option);
1380ac7ddfbfSEd Maste break;
1381ac7ddfbfSEd Maste }
1382ac7ddfbfSEd Maste return error;
1383ac7ddfbfSEd Maste }
1384ac7ddfbfSEd Maste
OptionParsingStarting(ExecutionContext * execution_context)1385435933ddSDimitry Andric void OptionParsingStarting(ExecutionContext *execution_context) override {
1386ac7ddfbfSEd Maste stop.clear();
1387ac7ddfbfSEd Maste notify.clear();
1388ac7ddfbfSEd Maste pass.clear();
1389ac7ddfbfSEd Maste }
1390ac7ddfbfSEd Maste
GetDefinitions()1391435933ddSDimitry Andric llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1392435933ddSDimitry Andric return llvm::makeArrayRef(g_process_handle_options);
1393ac7ddfbfSEd Maste }
1394ac7ddfbfSEd Maste
1395ac7ddfbfSEd Maste // Instance variables to hold the values for command options.
1396ac7ddfbfSEd Maste
1397ac7ddfbfSEd Maste std::string stop;
1398ac7ddfbfSEd Maste std::string notify;
1399ac7ddfbfSEd Maste std::string pass;
1400ac7ddfbfSEd Maste };
1401ac7ddfbfSEd Maste
CommandObjectProcessHandle(CommandInterpreter & interpreter)14024bb0738eSEd Maste CommandObjectProcessHandle(CommandInterpreter &interpreter)
1403435933ddSDimitry Andric : CommandObjectParsed(interpreter, "process handle",
1404435933ddSDimitry Andric "Manage LLDB handling of OS signals for the "
1405435933ddSDimitry Andric "current target process. Defaults to showing "
1406435933ddSDimitry Andric "current policy.",
14074bb0738eSEd Maste nullptr),
1408435933ddSDimitry Andric m_options() {
1409b91a7dfcSDimitry Andric SetHelpLong("\nIf no signals are specified, update them all. If no update "
1410b91a7dfcSDimitry Andric "option is specified, list the current values.");
1411ac7ddfbfSEd Maste CommandArgumentEntry arg;
1412ac7ddfbfSEd Maste CommandArgumentData signal_arg;
1413ac7ddfbfSEd Maste
1414ac7ddfbfSEd Maste signal_arg.arg_type = eArgTypeUnixSignal;
1415ac7ddfbfSEd Maste signal_arg.arg_repetition = eArgRepeatStar;
1416ac7ddfbfSEd Maste
1417ac7ddfbfSEd Maste arg.push_back(signal_arg);
1418ac7ddfbfSEd Maste
1419ac7ddfbfSEd Maste m_arguments.push_back(arg);
1420ac7ddfbfSEd Maste }
1421ac7ddfbfSEd Maste
14224bb0738eSEd Maste ~CommandObjectProcessHandle() override = default;
1423ac7ddfbfSEd Maste
GetOptions()1424435933ddSDimitry Andric Options *GetOptions() override { return &m_options; }
1425ac7ddfbfSEd Maste
VerifyCommandOptionValue(const std::string & option,int & real_value)1426435933ddSDimitry Andric bool VerifyCommandOptionValue(const std::string &option, int &real_value) {
1427ac7ddfbfSEd Maste bool okay = true;
1428ac7ddfbfSEd Maste bool success = false;
14294ba319b5SDimitry Andric bool tmp_value = OptionArgParser::ToBoolean(option, false, &success);
1430ac7ddfbfSEd Maste
1431ac7ddfbfSEd Maste if (success && tmp_value)
1432ac7ddfbfSEd Maste real_value = 1;
1433ac7ddfbfSEd Maste else if (success && !tmp_value)
1434ac7ddfbfSEd Maste real_value = 0;
1435435933ddSDimitry Andric else {
1436ac7ddfbfSEd Maste // If the value isn't 'true' or 'false', it had better be 0 or 1.
14371c3bbb01SEd Maste real_value = StringConvert::ToUInt32(option.c_str(), 3);
1438ac7ddfbfSEd Maste if (real_value != 0 && real_value != 1)
1439ac7ddfbfSEd Maste okay = false;
1440ac7ddfbfSEd Maste }
1441ac7ddfbfSEd Maste
1442ac7ddfbfSEd Maste return okay;
1443ac7ddfbfSEd Maste }
1444ac7ddfbfSEd Maste
PrintSignalHeader(Stream & str)1445435933ddSDimitry Andric void PrintSignalHeader(Stream &str) {
1446ac7ddfbfSEd Maste str.Printf("NAME PASS STOP NOTIFY\n");
14471c3bbb01SEd Maste str.Printf("=========== ===== ===== ======\n");
1448ac7ddfbfSEd Maste }
1449ac7ddfbfSEd Maste
PrintSignal(Stream & str,int32_t signo,const char * sig_name,const UnixSignalsSP & signals_sp)1450435933ddSDimitry Andric void PrintSignal(Stream &str, int32_t signo, const char *sig_name,
1451435933ddSDimitry Andric const UnixSignalsSP &signals_sp) {
1452ac7ddfbfSEd Maste bool stop;
1453ac7ddfbfSEd Maste bool suppress;
1454ac7ddfbfSEd Maste bool notify;
1455ac7ddfbfSEd Maste
14561c3bbb01SEd Maste str.Printf("%-11s ", sig_name);
1457435933ddSDimitry Andric if (signals_sp->GetSignalInfo(signo, suppress, stop, notify)) {
1458ac7ddfbfSEd Maste bool pass = !suppress;
1459435933ddSDimitry Andric str.Printf("%s %s %s", (pass ? "true " : "false"),
1460435933ddSDimitry Andric (stop ? "true " : "false"), (notify ? "true " : "false"));
1461ac7ddfbfSEd Maste }
1462ac7ddfbfSEd Maste str.Printf("\n");
1463ac7ddfbfSEd Maste }
1464ac7ddfbfSEd Maste
PrintSignalInformation(Stream & str,Args & signal_args,int num_valid_signals,const UnixSignalsSP & signals_sp)1465435933ddSDimitry Andric void PrintSignalInformation(Stream &str, Args &signal_args,
1466435933ddSDimitry Andric int num_valid_signals,
1467435933ddSDimitry Andric const UnixSignalsSP &signals_sp) {
1468ac7ddfbfSEd Maste PrintSignalHeader(str);
1469ac7ddfbfSEd Maste
1470435933ddSDimitry Andric if (num_valid_signals > 0) {
1471ac7ddfbfSEd Maste size_t num_args = signal_args.GetArgumentCount();
1472435933ddSDimitry Andric for (size_t i = 0; i < num_args; ++i) {
1473435933ddSDimitry Andric int32_t signo = signals_sp->GetSignalNumberFromName(
1474435933ddSDimitry Andric signal_args.GetArgumentAtIndex(i));
1475ac7ddfbfSEd Maste if (signo != LLDB_INVALID_SIGNAL_NUMBER)
1476435933ddSDimitry Andric PrintSignal(str, signo, signal_args.GetArgumentAtIndex(i),
1477435933ddSDimitry Andric signals_sp);
1478ac7ddfbfSEd Maste }
1479435933ddSDimitry Andric } else // Print info for ALL signals
1480ac7ddfbfSEd Maste {
1481b91a7dfcSDimitry Andric int32_t signo = signals_sp->GetFirstSignalNumber();
1482435933ddSDimitry Andric while (signo != LLDB_INVALID_SIGNAL_NUMBER) {
1483435933ddSDimitry Andric PrintSignal(str, signo, signals_sp->GetSignalAsCString(signo),
1484435933ddSDimitry Andric signals_sp);
1485b91a7dfcSDimitry Andric signo = signals_sp->GetNextSignalNumber(signo);
1486ac7ddfbfSEd Maste }
1487ac7ddfbfSEd Maste }
1488ac7ddfbfSEd Maste }
1489ac7ddfbfSEd Maste
1490ac7ddfbfSEd Maste protected:
DoExecute(Args & signal_args,CommandReturnObject & result)1491435933ddSDimitry Andric bool DoExecute(Args &signal_args, CommandReturnObject &result) override {
1492ac7ddfbfSEd Maste TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
1493ac7ddfbfSEd Maste
1494435933ddSDimitry Andric if (!target_sp) {
1495ac7ddfbfSEd Maste result.AppendError("No current target;"
1496435933ddSDimitry Andric " cannot handle signals until you have a valid target "
1497435933ddSDimitry Andric "and process.\n");
1498ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
1499ac7ddfbfSEd Maste return false;
1500ac7ddfbfSEd Maste }
1501ac7ddfbfSEd Maste
1502ac7ddfbfSEd Maste ProcessSP process_sp = target_sp->GetProcessSP();
1503ac7ddfbfSEd Maste
1504435933ddSDimitry Andric if (!process_sp) {
1505435933ddSDimitry Andric result.AppendError("No current process; cannot handle signals until you "
1506435933ddSDimitry Andric "have a valid process.\n");
1507ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
1508ac7ddfbfSEd Maste return false;
1509ac7ddfbfSEd Maste }
1510ac7ddfbfSEd Maste
1511ac7ddfbfSEd Maste int stop_action = -1; // -1 means leave the current setting alone
1512ac7ddfbfSEd Maste int pass_action = -1; // -1 means leave the current setting alone
1513ac7ddfbfSEd Maste int notify_action = -1; // -1 means leave the current setting alone
1514ac7ddfbfSEd Maste
1515435933ddSDimitry Andric if (!m_options.stop.empty() &&
1516435933ddSDimitry Andric !VerifyCommandOptionValue(m_options.stop, stop_action)) {
1517435933ddSDimitry Andric result.AppendError("Invalid argument for command option --stop; must be "
1518435933ddSDimitry Andric "true or false.\n");
1519ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
1520ac7ddfbfSEd Maste return false;
1521ac7ddfbfSEd Maste }
1522ac7ddfbfSEd Maste
1523435933ddSDimitry Andric if (!m_options.notify.empty() &&
1524435933ddSDimitry Andric !VerifyCommandOptionValue(m_options.notify, notify_action)) {
1525435933ddSDimitry Andric result.AppendError("Invalid argument for command option --notify; must "
1526435933ddSDimitry Andric "be true or false.\n");
1527ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
1528ac7ddfbfSEd Maste return false;
1529ac7ddfbfSEd Maste }
1530ac7ddfbfSEd Maste
1531435933ddSDimitry Andric if (!m_options.pass.empty() &&
1532435933ddSDimitry Andric !VerifyCommandOptionValue(m_options.pass, pass_action)) {
1533435933ddSDimitry Andric result.AppendError("Invalid argument for command option --pass; must be "
1534435933ddSDimitry Andric "true or false.\n");
1535ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
1536ac7ddfbfSEd Maste return false;
1537ac7ddfbfSEd Maste }
1538ac7ddfbfSEd Maste
1539ac7ddfbfSEd Maste size_t num_args = signal_args.GetArgumentCount();
1540b91a7dfcSDimitry Andric UnixSignalsSP signals_sp = process_sp->GetUnixSignals();
1541ac7ddfbfSEd Maste int num_signals_set = 0;
1542ac7ddfbfSEd Maste
1543435933ddSDimitry Andric if (num_args > 0) {
1544435933ddSDimitry Andric for (const auto &arg : signal_args) {
1545435933ddSDimitry Andric int32_t signo = signals_sp->GetSignalNumberFromName(arg.c_str());
1546435933ddSDimitry Andric if (signo != LLDB_INVALID_SIGNAL_NUMBER) {
1547435933ddSDimitry Andric // Casting the actions as bools here should be okay, because
15484ba319b5SDimitry Andric // VerifyCommandOptionValue guarantees the value is either 0 or 1.
1549ac7ddfbfSEd Maste if (stop_action != -1)
1550b91a7dfcSDimitry Andric signals_sp->SetShouldStop(signo, stop_action);
1551435933ddSDimitry Andric if (pass_action != -1) {
1552b91a7dfcSDimitry Andric bool suppress = !pass_action;
1553b91a7dfcSDimitry Andric signals_sp->SetShouldSuppress(signo, suppress);
1554ac7ddfbfSEd Maste }
1555ac7ddfbfSEd Maste if (notify_action != -1)
1556b91a7dfcSDimitry Andric signals_sp->SetShouldNotify(signo, notify_action);
1557ac7ddfbfSEd Maste ++num_signals_set;
1558435933ddSDimitry Andric } else {
1559435933ddSDimitry Andric result.AppendErrorWithFormat("Invalid signal name '%s'\n",
1560435933ddSDimitry Andric arg.c_str());
1561ac7ddfbfSEd Maste }
1562ac7ddfbfSEd Maste }
1563435933ddSDimitry Andric } else {
1564435933ddSDimitry Andric // No signal specified, if any command options were specified, update ALL
1565435933ddSDimitry Andric // signals.
1566435933ddSDimitry Andric if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1)) {
1567435933ddSDimitry Andric if (m_interpreter.Confirm(
1568435933ddSDimitry Andric "Do you really want to update all the signals?", false)) {
1569b91a7dfcSDimitry Andric int32_t signo = signals_sp->GetFirstSignalNumber();
1570435933ddSDimitry Andric while (signo != LLDB_INVALID_SIGNAL_NUMBER) {
1571ac7ddfbfSEd Maste if (notify_action != -1)
1572b91a7dfcSDimitry Andric signals_sp->SetShouldNotify(signo, notify_action);
1573ac7ddfbfSEd Maste if (stop_action != -1)
1574b91a7dfcSDimitry Andric signals_sp->SetShouldStop(signo, stop_action);
1575435933ddSDimitry Andric if (pass_action != -1) {
1576b91a7dfcSDimitry Andric bool suppress = !pass_action;
1577b91a7dfcSDimitry Andric signals_sp->SetShouldSuppress(signo, suppress);
1578ac7ddfbfSEd Maste }
1579b91a7dfcSDimitry Andric signo = signals_sp->GetNextSignalNumber(signo);
1580ac7ddfbfSEd Maste }
1581ac7ddfbfSEd Maste }
1582ac7ddfbfSEd Maste }
1583ac7ddfbfSEd Maste }
1584ac7ddfbfSEd Maste
1585435933ddSDimitry Andric PrintSignalInformation(result.GetOutputStream(), signal_args,
1586435933ddSDimitry Andric num_signals_set, signals_sp);
1587ac7ddfbfSEd Maste
1588ac7ddfbfSEd Maste if (num_signals_set > 0)
1589ac7ddfbfSEd Maste result.SetStatus(eReturnStatusSuccessFinishNoResult);
1590ac7ddfbfSEd Maste else
1591ac7ddfbfSEd Maste result.SetStatus(eReturnStatusFailed);
1592ac7ddfbfSEd Maste
1593ac7ddfbfSEd Maste return result.Succeeded();
1594ac7ddfbfSEd Maste }
1595ac7ddfbfSEd Maste
1596ac7ddfbfSEd Maste CommandOptions m_options;
1597ac7ddfbfSEd Maste };
1598ac7ddfbfSEd Maste
1599ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1600ac7ddfbfSEd Maste // CommandObjectMultiwordProcess
1601ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1602ac7ddfbfSEd Maste
CommandObjectMultiwordProcess(CommandInterpreter & interpreter)1603435933ddSDimitry Andric CommandObjectMultiwordProcess::CommandObjectMultiwordProcess(
1604435933ddSDimitry Andric CommandInterpreter &interpreter)
1605435933ddSDimitry Andric : CommandObjectMultiword(
1606435933ddSDimitry Andric interpreter, "process",
1607435933ddSDimitry Andric "Commands for interacting with processes on the current platform.",
1608435933ddSDimitry Andric "process <subcommand> [<subcommand-options>]") {
1609435933ddSDimitry Andric LoadSubCommand("attach",
1610435933ddSDimitry Andric CommandObjectSP(new CommandObjectProcessAttach(interpreter)));
1611435933ddSDimitry Andric LoadSubCommand("launch",
1612435933ddSDimitry Andric CommandObjectSP(new CommandObjectProcessLaunch(interpreter)));
1613435933ddSDimitry Andric LoadSubCommand("continue", CommandObjectSP(new CommandObjectProcessContinue(
1614435933ddSDimitry Andric interpreter)));
1615435933ddSDimitry Andric LoadSubCommand("connect",
1616435933ddSDimitry Andric CommandObjectSP(new CommandObjectProcessConnect(interpreter)));
1617435933ddSDimitry Andric LoadSubCommand("detach",
1618435933ddSDimitry Andric CommandObjectSP(new CommandObjectProcessDetach(interpreter)));
1619435933ddSDimitry Andric LoadSubCommand("load",
1620435933ddSDimitry Andric CommandObjectSP(new CommandObjectProcessLoad(interpreter)));
1621435933ddSDimitry Andric LoadSubCommand("unload",
1622435933ddSDimitry Andric CommandObjectSP(new CommandObjectProcessUnload(interpreter)));
1623435933ddSDimitry Andric LoadSubCommand("signal",
1624435933ddSDimitry Andric CommandObjectSP(new CommandObjectProcessSignal(interpreter)));
1625435933ddSDimitry Andric LoadSubCommand("handle",
1626435933ddSDimitry Andric CommandObjectSP(new CommandObjectProcessHandle(interpreter)));
1627435933ddSDimitry Andric LoadSubCommand("status",
1628435933ddSDimitry Andric CommandObjectSP(new CommandObjectProcessStatus(interpreter)));
1629435933ddSDimitry Andric LoadSubCommand("interrupt", CommandObjectSP(new CommandObjectProcessInterrupt(
1630435933ddSDimitry Andric interpreter)));
1631435933ddSDimitry Andric LoadSubCommand("kill",
1632435933ddSDimitry Andric CommandObjectSP(new CommandObjectProcessKill(interpreter)));
1633435933ddSDimitry Andric LoadSubCommand("plugin",
1634435933ddSDimitry Andric CommandObjectSP(new CommandObjectProcessPlugin(interpreter)));
1635435933ddSDimitry Andric LoadSubCommand("save-core", CommandObjectSP(new CommandObjectProcessSaveCore(
1636435933ddSDimitry Andric interpreter)));
1637ac7ddfbfSEd Maste }
1638ac7ddfbfSEd Maste
16394bb0738eSEd Maste CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess() = default;
1640