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 &current_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