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 
10ac7ddfbfSEd Maste // C Includes
11ac7ddfbfSEd Maste // C++ Includes
12ac7ddfbfSEd Maste // Other libraries and framework includes
13ac7ddfbfSEd Maste // Project includes
144bb0738eSEd Maste #include "CommandObjectProcess.h"
15ac7ddfbfSEd Maste #include "lldb/Breakpoint/Breakpoint.h"
16ac7ddfbfSEd Maste #include "lldb/Breakpoint/BreakpointLocation.h"
17ac7ddfbfSEd Maste #include "lldb/Breakpoint/BreakpointSite.h"
18ac7ddfbfSEd Maste #include "lldb/Core/Module.h"
190127ef0fSEd Maste #include "lldb/Core/PluginManager.h"
20435933ddSDimitry Andric #include "lldb/Core/State.h"
21ac7ddfbfSEd Maste #include "lldb/Host/Host.h"
22f678e45dSDimitry Andric #include "lldb/Host/OptionParser.h"
231c3bbb01SEd Maste #include "lldb/Host/StringConvert.h"
24ac7ddfbfSEd Maste #include "lldb/Interpreter/Args.h"
25ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandInterpreter.h"
26ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandReturnObject.h"
27435933ddSDimitry Andric #include "lldb/Interpreter/Options.h"
28ac7ddfbfSEd Maste #include "lldb/Target/Platform.h"
29ac7ddfbfSEd Maste #include "lldb/Target/Process.h"
30ac7ddfbfSEd Maste #include "lldb/Target/StopInfo.h"
31ac7ddfbfSEd Maste #include "lldb/Target/Target.h"
32ac7ddfbfSEd Maste #include "lldb/Target/Thread.h"
331c3bbb01SEd Maste #include "lldb/Target/UnixSignals.h"
34ac7ddfbfSEd Maste 
35ac7ddfbfSEd Maste using namespace lldb;
36ac7ddfbfSEd Maste using namespace lldb_private;
37ac7ddfbfSEd Maste 
38435933ddSDimitry Andric class CommandObjectProcessLaunchOrAttach : public CommandObjectParsed {
39ac7ddfbfSEd Maste public:
40ac7ddfbfSEd Maste   CommandObjectProcessLaunchOrAttach(CommandInterpreter &interpreter,
41435933ddSDimitry Andric                                      const char *name, const char *help,
42435933ddSDimitry Andric                                      const char *syntax, uint32_t flags,
43435933ddSDimitry Andric                                      const char *new_process_action)
44435933ddSDimitry Andric       : CommandObjectParsed(interpreter, name, help, syntax, flags),
45ac7ddfbfSEd Maste         m_new_process_action(new_process_action) {}
46ac7ddfbfSEd Maste 
474bb0738eSEd Maste   ~CommandObjectProcessLaunchOrAttach() override = default;
484bb0738eSEd Maste 
49ac7ddfbfSEd Maste protected:
50435933ddSDimitry Andric   bool StopProcessIfNecessary(Process *process, StateType &state,
51435933ddSDimitry Andric                               CommandReturnObject &result) {
52ac7ddfbfSEd Maste     state = eStateInvalid;
53435933ddSDimitry Andric     if (process) {
54ac7ddfbfSEd Maste       state = process->GetState();
55ac7ddfbfSEd Maste 
56435933ddSDimitry Andric       if (process->IsAlive() && state != eStateConnected) {
57ac7ddfbfSEd Maste         char message[1024];
58ac7ddfbfSEd Maste         if (process->GetState() == eStateAttaching)
59435933ddSDimitry Andric           ::snprintf(message, sizeof(message),
60435933ddSDimitry Andric                      "There is a pending attach, abort it and %s?",
61435933ddSDimitry Andric                      m_new_process_action.c_str());
62ac7ddfbfSEd Maste         else if (process->GetShouldDetach())
63435933ddSDimitry Andric           ::snprintf(message, sizeof(message),
64435933ddSDimitry Andric                      "There is a running process, detach from it and %s?",
65435933ddSDimitry Andric                      m_new_process_action.c_str());
66ac7ddfbfSEd Maste         else
67435933ddSDimitry Andric           ::snprintf(message, sizeof(message),
68435933ddSDimitry Andric                      "There is a running process, kill it and %s?",
69435933ddSDimitry Andric                      m_new_process_action.c_str());
70ac7ddfbfSEd Maste 
71435933ddSDimitry Andric         if (!m_interpreter.Confirm(message, true)) {
72ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusFailed);
73ac7ddfbfSEd Maste           return false;
74435933ddSDimitry Andric         } else {
75435933ddSDimitry Andric           if (process->GetShouldDetach()) {
76ac7ddfbfSEd Maste             bool keep_stopped = false;
77ac7ddfbfSEd Maste             Error detach_error(process->Detach(keep_stopped));
78435933ddSDimitry Andric             if (detach_error.Success()) {
79ac7ddfbfSEd Maste               result.SetStatus(eReturnStatusSuccessFinishResult);
804bb0738eSEd Maste               process = nullptr;
81435933ddSDimitry Andric             } else {
82435933ddSDimitry Andric               result.AppendErrorWithFormat(
83435933ddSDimitry Andric                   "Failed to detach from process: %s\n",
84435933ddSDimitry Andric                   detach_error.AsCString());
85ac7ddfbfSEd Maste               result.SetStatus(eReturnStatusFailed);
86ac7ddfbfSEd Maste             }
87435933ddSDimitry Andric           } else {
881c3bbb01SEd Maste             Error destroy_error(process->Destroy(false));
89435933ddSDimitry Andric             if (destroy_error.Success()) {
90ac7ddfbfSEd Maste               result.SetStatus(eReturnStatusSuccessFinishResult);
914bb0738eSEd Maste               process = nullptr;
92435933ddSDimitry Andric             } else {
93435933ddSDimitry Andric               result.AppendErrorWithFormat("Failed to kill process: %s\n",
94435933ddSDimitry Andric                                            destroy_error.AsCString());
95ac7ddfbfSEd Maste               result.SetStatus(eReturnStatusFailed);
96ac7ddfbfSEd Maste             }
97ac7ddfbfSEd Maste           }
98ac7ddfbfSEd Maste         }
99ac7ddfbfSEd Maste       }
100ac7ddfbfSEd Maste     }
101ac7ddfbfSEd Maste     return result.Succeeded();
102ac7ddfbfSEd Maste   }
1034bb0738eSEd Maste 
104ac7ddfbfSEd Maste   std::string m_new_process_action;
105ac7ddfbfSEd Maste };
1064bb0738eSEd Maste 
107ac7ddfbfSEd Maste //-------------------------------------------------------------------------
108ac7ddfbfSEd Maste // CommandObjectProcessLaunch
109ac7ddfbfSEd Maste //-------------------------------------------------------------------------
110ac7ddfbfSEd Maste #pragma mark CommandObjectProcessLaunch
111435933ddSDimitry Andric class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach {
112ac7ddfbfSEd Maste public:
113435933ddSDimitry Andric   CommandObjectProcessLaunch(CommandInterpreter &interpreter)
114435933ddSDimitry Andric       : CommandObjectProcessLaunchOrAttach(
115435933ddSDimitry Andric             interpreter, "process launch",
116435933ddSDimitry Andric             "Launch the executable in the debugger.", nullptr,
117435933ddSDimitry Andric             eCommandRequiresTarget, "restart"),
118435933ddSDimitry Andric         m_options() {
119ac7ddfbfSEd Maste     CommandArgumentEntry arg;
120ac7ddfbfSEd Maste     CommandArgumentData run_args_arg;
121ac7ddfbfSEd Maste 
122ac7ddfbfSEd Maste     // Define the first (and only) variant of this arg.
123ac7ddfbfSEd Maste     run_args_arg.arg_type = eArgTypeRunArgs;
124ac7ddfbfSEd Maste     run_args_arg.arg_repetition = eArgRepeatOptional;
125ac7ddfbfSEd Maste 
126435933ddSDimitry Andric     // There is only one variant this argument could be; put it into the
127435933ddSDimitry Andric     // argument entry.
128ac7ddfbfSEd Maste     arg.push_back(run_args_arg);
129ac7ddfbfSEd Maste 
130ac7ddfbfSEd Maste     // Push the data for the first argument into the m_arguments vector.
131ac7ddfbfSEd Maste     m_arguments.push_back(arg);
132ac7ddfbfSEd Maste   }
133ac7ddfbfSEd Maste 
1344bb0738eSEd Maste   ~CommandObjectProcessLaunch() override = default;
135ac7ddfbfSEd Maste 
136435933ddSDimitry Andric   int HandleArgumentCompletion(Args &input, int &cursor_index,
137ac7ddfbfSEd Maste                                int &cursor_char_position,
138ac7ddfbfSEd Maste                                OptionElementVector &opt_element_vector,
139435933ddSDimitry Andric                                int match_start_point, int max_return_elements,
140ac7ddfbfSEd Maste                                bool &word_complete,
141435933ddSDimitry Andric                                StringList &matches) override {
142ac7ddfbfSEd Maste     std::string completion_str(input.GetArgumentAtIndex(cursor_index));
143ac7ddfbfSEd Maste     completion_str.erase(cursor_char_position);
144ac7ddfbfSEd Maste 
145435933ddSDimitry Andric     CommandCompletions::InvokeCommonCompletionCallbacks(
146435933ddSDimitry Andric         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
147435933ddSDimitry Andric         completion_str.c_str(), match_start_point, max_return_elements, nullptr,
148435933ddSDimitry Andric         word_complete, matches);
149ac7ddfbfSEd Maste     return matches.GetSize();
150ac7ddfbfSEd Maste   }
151ac7ddfbfSEd Maste 
152435933ddSDimitry Andric   Options *GetOptions() override { return &m_options; }
153ac7ddfbfSEd Maste 
154435933ddSDimitry Andric   const char *GetRepeatCommand(Args &current_command_args,
155435933ddSDimitry Andric                                uint32_t index) override {
156ac7ddfbfSEd Maste     // No repeat for "process launch"...
157ac7ddfbfSEd Maste     return "";
158ac7ddfbfSEd Maste   }
159ac7ddfbfSEd Maste 
160ac7ddfbfSEd Maste protected:
161435933ddSDimitry Andric   bool DoExecute(Args &launch_args, CommandReturnObject &result) override {
162ac7ddfbfSEd Maste     Debugger &debugger = m_interpreter.GetDebugger();
163ac7ddfbfSEd Maste     Target *target = debugger.GetSelectedTarget().get();
1644bb0738eSEd Maste     // If our listener is nullptr, users aren't allows to launch
16512b93ac6SEd Maste     ModuleSP exe_module_sp = target->GetExecutableModule();
166ac7ddfbfSEd Maste 
167435933ddSDimitry Andric     if (exe_module_sp == nullptr) {
168435933ddSDimitry Andric       result.AppendError("no file in target, create a debug target using the "
169435933ddSDimitry Andric                          "'target create' command");
170ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
171ac7ddfbfSEd Maste       return false;
172ac7ddfbfSEd Maste     }
173ac7ddfbfSEd Maste 
174ac7ddfbfSEd Maste     StateType state = eStateInvalid;
175ac7ddfbfSEd Maste 
17612b93ac6SEd Maste     if (!StopProcessIfNecessary(m_exe_ctx.GetProcessPtr(), state, result))
177ac7ddfbfSEd Maste       return false;
178ac7ddfbfSEd Maste 
179435933ddSDimitry Andric     llvm::StringRef target_settings_argv0 = target->GetArg0();
180ac7ddfbfSEd Maste 
181435933ddSDimitry Andric     // Determine whether we will disable ASLR or leave it in the default state
182435933ddSDimitry Andric     // (i.e. enabled if the platform supports it).
183435933ddSDimitry Andric     // First check if the process launch options explicitly turn on/off
184435933ddSDimitry Andric     // disabling ASLR.  If so, use that setting;
1850127ef0fSEd Maste     // otherwise, use the 'settings target.disable-aslr' setting.
1860127ef0fSEd Maste     bool disable_aslr = false;
187435933ddSDimitry Andric     if (m_options.disable_aslr != eLazyBoolCalculate) {
188435933ddSDimitry Andric       // The user specified an explicit setting on the process launch line.  Use
189435933ddSDimitry Andric       // it.
1900127ef0fSEd Maste       disable_aslr = (m_options.disable_aslr == eLazyBoolYes);
191435933ddSDimitry Andric     } else {
192435933ddSDimitry Andric       // The user did not explicitly specify whether to disable ASLR.  Fall back
193435933ddSDimitry Andric       // to the target.disable-aslr setting.
1940127ef0fSEd Maste       disable_aslr = target->GetDisableASLR();
1950127ef0fSEd Maste     }
1960127ef0fSEd Maste 
1970127ef0fSEd Maste     if (disable_aslr)
19812b93ac6SEd Maste       m_options.launch_info.GetFlags().Set(eLaunchFlagDisableASLR);
1990127ef0fSEd Maste     else
2000127ef0fSEd Maste       m_options.launch_info.GetFlags().Clear(eLaunchFlagDisableASLR);
2010127ef0fSEd Maste 
2020127ef0fSEd Maste     if (target->GetDetachOnError())
2030127ef0fSEd Maste       m_options.launch_info.GetFlags().Set(eLaunchFlagDetachOnError);
20412b93ac6SEd Maste 
20512b93ac6SEd Maste     if (target->GetDisableSTDIO())
20612b93ac6SEd Maste       m_options.launch_info.GetFlags().Set(eLaunchFlagDisableSTDIO);
20712b93ac6SEd Maste 
20812b93ac6SEd Maste     Args environment;
20912b93ac6SEd Maste     target->GetEnvironmentAsArgs(environment);
21012b93ac6SEd Maste     if (environment.GetArgumentCount() > 0)
211435933ddSDimitry Andric       m_options.launch_info.GetEnvironmentEntries().AppendArguments(
212435933ddSDimitry Andric           environment);
213ac7ddfbfSEd Maste 
214435933ddSDimitry Andric     if (!target_settings_argv0.empty()) {
215435933ddSDimitry Andric       m_options.launch_info.GetArguments().AppendArgument(
216435933ddSDimitry Andric           target_settings_argv0);
217435933ddSDimitry Andric       m_options.launch_info.SetExecutableFile(
218435933ddSDimitry Andric           exe_module_sp->GetPlatformFileSpec(), false);
219435933ddSDimitry Andric     } else {
220435933ddSDimitry Andric       m_options.launch_info.SetExecutableFile(
221435933ddSDimitry Andric           exe_module_sp->GetPlatformFileSpec(), true);
222ac7ddfbfSEd Maste     }
223ac7ddfbfSEd Maste 
224435933ddSDimitry Andric     if (launch_args.GetArgumentCount() == 0) {
225435933ddSDimitry Andric       m_options.launch_info.GetArguments().AppendArguments(
226435933ddSDimitry Andric           target->GetProcessLaunchInfo().GetArguments());
227435933ddSDimitry Andric     } else {
228ac7ddfbfSEd Maste       m_options.launch_info.GetArguments().AppendArguments(launch_args);
229ac7ddfbfSEd Maste       // Save the arguments for subsequent runs in the current target.
230ac7ddfbfSEd Maste       target->SetRunArguments(launch_args);
231ac7ddfbfSEd Maste     }
232ac7ddfbfSEd Maste 
2337aa51b79SEd Maste     StreamString stream;
2347aa51b79SEd Maste     Error error = target->Launch(m_options.launch_info, &stream);
235ac7ddfbfSEd Maste 
236435933ddSDimitry Andric     if (error.Success()) {
23712b93ac6SEd Maste       ProcessSP process_sp(target->GetProcessSP());
238435933ddSDimitry Andric       if (process_sp) {
239435933ddSDimitry Andric         // There is a race condition where this thread will return up the call
240435933ddSDimitry Andric         // stack to the main command
241435933ddSDimitry Andric         // handler and show an (lldb) prompt before HandlePrivateEvent (from
242435933ddSDimitry Andric         // PrivateStateThread) has
2431c3bbb01SEd Maste         // a chance to call PushProcessIOHandler().
2441c3bbb01SEd Maste         process_sp->SyncIOHandler(0, 2000);
2451c3bbb01SEd Maste 
246435933ddSDimitry Andric         llvm::StringRef data = stream.GetString();
247435933ddSDimitry Andric         if (!data.empty())
248435933ddSDimitry Andric           result.AppendMessage(data);
249435933ddSDimitry Andric         const char *archname =
250435933ddSDimitry Andric             exe_module_sp->GetArchitecture().GetArchitectureName();
251435933ddSDimitry Andric         result.AppendMessageWithFormat(
252435933ddSDimitry Andric             "Process %" PRIu64 " launched: '%s' (%s)\n", process_sp->GetID(),
253435933ddSDimitry Andric             exe_module_sp->GetFileSpec().GetPath().c_str(), archname);
254ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusSuccessFinishResult);
25512b93ac6SEd Maste         result.SetDidChangeProcessState(true);
256435933ddSDimitry Andric       } else {
257435933ddSDimitry Andric         result.AppendError(
258435933ddSDimitry Andric             "no error returned from Target::Launch, and target has no process");
259ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
260ac7ddfbfSEd Maste       }
261435933ddSDimitry Andric     } else {
26212b93ac6SEd Maste       result.AppendError(error.AsCString());
263ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
264ac7ddfbfSEd Maste     }
265ac7ddfbfSEd Maste     return result.Succeeded();
266ac7ddfbfSEd Maste   }
267ac7ddfbfSEd Maste 
268ac7ddfbfSEd Maste protected:
269ac7ddfbfSEd Maste   ProcessLaunchCommandOptions m_options;
270ac7ddfbfSEd Maste };
271ac7ddfbfSEd Maste 
272ac7ddfbfSEd Maste //#define SET1 LLDB_OPT_SET_1
273ac7ddfbfSEd Maste //#define SET2 LLDB_OPT_SET_2
274ac7ddfbfSEd Maste //#define SET3 LLDB_OPT_SET_3
275ac7ddfbfSEd Maste //
276ac7ddfbfSEd Maste // OptionDefinition
277ac7ddfbfSEd Maste // CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
278ac7ddfbfSEd Maste //{
279435933ddSDimitry Andric //  // clang-format off
280435933ddSDimitry Andric //  {SET1 | SET2 | SET3, false, "stop-at-entry", 's', OptionParser::eNoArgument,
281435933ddSDimitry Andric //  nullptr, 0, eArgTypeNone,          "Stop at the entry point of the program
282435933ddSDimitry Andric //  when launching a process."},
283435933ddSDimitry Andric //  {SET1,               false, "stdin",         'i',
284435933ddSDimitry Andric //  OptionParser::eRequiredArgument, nullptr, 0, eArgTypeDirectoryName,
285435933ddSDimitry Andric //  "Redirect stdin for the process to <path>."},
286435933ddSDimitry Andric //  {SET1,               false, "stdout",        'o',
287435933ddSDimitry Andric //  OptionParser::eRequiredArgument, nullptr, 0, eArgTypeDirectoryName,
288435933ddSDimitry Andric //  "Redirect stdout for the process to <path>."},
289435933ddSDimitry Andric //  {SET1,               false, "stderr",        'e',
290435933ddSDimitry Andric //  OptionParser::eRequiredArgument, nullptr, 0, eArgTypeDirectoryName,
291435933ddSDimitry Andric //  "Redirect stderr for the process to <path>."},
292435933ddSDimitry Andric //  {SET1 | SET2 | SET3, false, "plugin",        'p',
293435933ddSDimitry Andric //  OptionParser::eRequiredArgument, nullptr, 0, eArgTypePlugin,        "Name of
294435933ddSDimitry Andric //  the process plugin you want to use."},
295435933ddSDimitry Andric //  {       SET2,        false, "tty",           't',
296435933ddSDimitry Andric //  OptionParser::eOptionalArgument, nullptr, 0, eArgTypeDirectoryName, "Start
297435933ddSDimitry Andric //  the process in a terminal. If <path> is specified, look for a terminal whose
298435933ddSDimitry Andric //  name contains <path>, else start the process in a new terminal."},
299435933ddSDimitry Andric //  {              SET3, false, "no-stdio",      'n', OptionParser::eNoArgument,
300435933ddSDimitry Andric //  nullptr, 0, eArgTypeNone,          "Do not set up for terminal I/O to go to
301435933ddSDimitry Andric //  running process."},
302435933ddSDimitry Andric //  {SET1 | SET2 | SET3, false, "working-dir",   'w',
303435933ddSDimitry Andric //  OptionParser::eRequiredArgument, nullptr, 0, eArgTypeDirectoryName, "Set the
304435933ddSDimitry Andric //  current working directory to <path> when running the inferior."},
3054bb0738eSEd Maste //  {0, false, nullptr, 0, 0, nullptr, 0, eArgTypeNone, nullptr}
306435933ddSDimitry Andric //  // clang-format on
307ac7ddfbfSEd Maste //};
308ac7ddfbfSEd Maste //
309ac7ddfbfSEd Maste //#undef SET1
310ac7ddfbfSEd Maste //#undef SET2
311ac7ddfbfSEd Maste //#undef SET3
312ac7ddfbfSEd Maste 
313ac7ddfbfSEd Maste //-------------------------------------------------------------------------
314ac7ddfbfSEd Maste // CommandObjectProcessAttach
315ac7ddfbfSEd Maste //-------------------------------------------------------------------------
316435933ddSDimitry Andric 
317435933ddSDimitry Andric static OptionDefinition g_process_attach_options[] = {
318435933ddSDimitry Andric     // clang-format off
319435933ddSDimitry Andric   { LLDB_OPT_SET_ALL, false, "continue",         'c', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,         "Immediately continue the process once attached." },
320435933ddSDimitry Andric   { LLDB_OPT_SET_ALL, false, "plugin",           'P', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePlugin,       "Name of the process plugin you want to use." },
321435933ddSDimitry Andric   { LLDB_OPT_SET_1,   false, "pid",              'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePid,          "The process ID of an existing process to attach to." },
322435933ddSDimitry Andric   { LLDB_OPT_SET_2,   false, "name",             'n', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeProcessName,  "The name of the process to attach to." },
323435933ddSDimitry Andric   { LLDB_OPT_SET_2,   false, "include-existing", 'i', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,         "Include existing processes when doing attach -w." },
324435933ddSDimitry Andric   { LLDB_OPT_SET_2,   false, "waitfor",          'w', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,         "Wait for the process with <process-name> to launch." },
325435933ddSDimitry Andric     // clang-format on
326435933ddSDimitry Andric };
327435933ddSDimitry Andric 
328ac7ddfbfSEd Maste #pragma mark CommandObjectProcessAttach
329435933ddSDimitry Andric class CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach {
330ac7ddfbfSEd Maste public:
331435933ddSDimitry Andric   class CommandOptions : public Options {
332ac7ddfbfSEd Maste   public:
333435933ddSDimitry Andric     CommandOptions() : Options() {
334435933ddSDimitry Andric       // Keep default values of all options in one place: OptionParsingStarting
335435933ddSDimitry Andric       // ()
336435933ddSDimitry Andric       OptionParsingStarting(nullptr);
337ac7ddfbfSEd Maste     }
338ac7ddfbfSEd Maste 
3394bb0738eSEd Maste     ~CommandOptions() override = default;
340ac7ddfbfSEd Maste 
341435933ddSDimitry Andric     Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
342435933ddSDimitry Andric                          ExecutionContext *execution_context) override {
343ac7ddfbfSEd Maste       Error error;
344ac7ddfbfSEd Maste       const int short_option = m_getopt_table[option_idx].val;
345435933ddSDimitry Andric       switch (short_option) {
346ac7ddfbfSEd Maste       case 'c':
347ac7ddfbfSEd Maste         attach_info.SetContinueOnceAttached(true);
348ac7ddfbfSEd Maste         break;
349ac7ddfbfSEd Maste 
350435933ddSDimitry Andric       case 'p': {
351435933ddSDimitry Andric         lldb::pid_t pid;
352435933ddSDimitry Andric         if (option_arg.getAsInteger(0, pid)) {
353435933ddSDimitry Andric           error.SetErrorStringWithFormat("invalid process ID '%s'",
354435933ddSDimitry Andric                                          option_arg.str().c_str());
355435933ddSDimitry Andric         } else {
356ac7ddfbfSEd Maste           attach_info.SetProcessID(pid);
357ac7ddfbfSEd Maste         }
358435933ddSDimitry Andric       } break;
359ac7ddfbfSEd Maste 
360ac7ddfbfSEd Maste       case 'P':
361ac7ddfbfSEd Maste         attach_info.SetProcessPluginName(option_arg);
362ac7ddfbfSEd Maste         break;
363ac7ddfbfSEd Maste 
364ac7ddfbfSEd Maste       case 'n':
365ac7ddfbfSEd Maste         attach_info.GetExecutableFile().SetFile(option_arg, false);
366ac7ddfbfSEd Maste         break;
367ac7ddfbfSEd Maste 
368ac7ddfbfSEd Maste       case 'w':
369ac7ddfbfSEd Maste         attach_info.SetWaitForLaunch(true);
370ac7ddfbfSEd Maste         break;
371ac7ddfbfSEd Maste 
372ac7ddfbfSEd Maste       case 'i':
373ac7ddfbfSEd Maste         attach_info.SetIgnoreExisting(false);
374ac7ddfbfSEd Maste         break;
375ac7ddfbfSEd Maste 
376ac7ddfbfSEd Maste       default:
377435933ddSDimitry Andric         error.SetErrorStringWithFormat("invalid short option character '%c'",
378435933ddSDimitry Andric                                        short_option);
379ac7ddfbfSEd Maste         break;
380ac7ddfbfSEd Maste       }
381ac7ddfbfSEd Maste       return error;
382ac7ddfbfSEd Maste     }
383ac7ddfbfSEd Maste 
384435933ddSDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
385ac7ddfbfSEd Maste       attach_info.Clear();
386ac7ddfbfSEd Maste     }
387ac7ddfbfSEd Maste 
388435933ddSDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
389435933ddSDimitry Andric       return llvm::makeArrayRef(g_process_attach_options);
390ac7ddfbfSEd Maste     }
391ac7ddfbfSEd Maste 
392435933ddSDimitry Andric     bool HandleOptionArgumentCompletion(
393435933ddSDimitry Andric         Args &input, int cursor_index, int char_pos,
394435933ddSDimitry Andric         OptionElementVector &opt_element_vector, int opt_element_index,
395435933ddSDimitry Andric         int match_start_point, int max_return_elements,
396435933ddSDimitry Andric         CommandInterpreter &interpreter, bool &word_complete,
397435933ddSDimitry Andric         StringList &matches) override {
398ac7ddfbfSEd Maste       int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
399ac7ddfbfSEd Maste       int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
400ac7ddfbfSEd Maste 
401ac7ddfbfSEd Maste       // We are only completing the name option for now...
402ac7ddfbfSEd Maste 
403435933ddSDimitry Andric       if (GetDefinitions()[opt_defs_index].short_option == 'n') {
404ac7ddfbfSEd Maste         // Are we in the name?
405ac7ddfbfSEd Maste 
406435933ddSDimitry Andric         // Look to see if there is a -P argument provided, and if so use that
407435933ddSDimitry Andric         // plugin, otherwise
408ac7ddfbfSEd Maste         // use the default plugin.
409ac7ddfbfSEd Maste 
4104bb0738eSEd Maste         const char *partial_name = nullptr;
411ac7ddfbfSEd Maste         partial_name = input.GetArgumentAtIndex(opt_arg_pos);
412ac7ddfbfSEd Maste 
413435933ddSDimitry Andric         PlatformSP platform_sp(interpreter.GetPlatform(true));
414435933ddSDimitry Andric         if (platform_sp) {
415ac7ddfbfSEd Maste           ProcessInstanceInfoList process_infos;
416ac7ddfbfSEd Maste           ProcessInstanceInfoMatch match_info;
417435933ddSDimitry Andric           if (partial_name) {
418435933ddSDimitry Andric             match_info.GetProcessInfo().GetExecutableFile().SetFile(
419435933ddSDimitry Andric                 partial_name, false);
420f678e45dSDimitry Andric             match_info.SetNameMatchType(NameMatch::StartsWith);
421ac7ddfbfSEd Maste           }
422ac7ddfbfSEd Maste           platform_sp->FindProcesses(match_info, process_infos);
423ac7ddfbfSEd Maste           const size_t num_matches = process_infos.GetSize();
424435933ddSDimitry Andric           if (num_matches > 0) {
425435933ddSDimitry Andric             for (size_t i = 0; i < num_matches; ++i) {
426435933ddSDimitry Andric               matches.AppendString(
427435933ddSDimitry Andric                   process_infos.GetProcessNameAtIndex(i),
428ac7ddfbfSEd Maste                   process_infos.GetProcessNameLengthAtIndex(i));
429ac7ddfbfSEd Maste             }
430ac7ddfbfSEd Maste           }
431ac7ddfbfSEd Maste         }
432ac7ddfbfSEd Maste       }
433ac7ddfbfSEd Maste 
434ac7ddfbfSEd Maste       return false;
435ac7ddfbfSEd Maste     }
436ac7ddfbfSEd Maste 
437ac7ddfbfSEd Maste     // Instance variables to hold the values for command options.
438ac7ddfbfSEd Maste 
439ac7ddfbfSEd Maste     ProcessAttachInfo attach_info;
440ac7ddfbfSEd Maste   };
441ac7ddfbfSEd Maste 
442435933ddSDimitry Andric   CommandObjectProcessAttach(CommandInterpreter &interpreter)
443435933ddSDimitry Andric       : CommandObjectProcessLaunchOrAttach(
444435933ddSDimitry Andric             interpreter, "process attach", "Attach to a process.",
445435933ddSDimitry Andric             "process attach <cmd-options>", 0, "attach"),
446435933ddSDimitry Andric         m_options() {}
447ac7ddfbfSEd Maste 
4484bb0738eSEd Maste   ~CommandObjectProcessAttach() override = default;
449ac7ddfbfSEd Maste 
450435933ddSDimitry Andric   Options *GetOptions() override { return &m_options; }
451ac7ddfbfSEd Maste 
452ac7ddfbfSEd Maste protected:
453435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
454435933ddSDimitry Andric     PlatformSP platform_sp(
455435933ddSDimitry Andric         m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
4561c3bbb01SEd Maste 
457ac7ddfbfSEd Maste     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
458435933ddSDimitry Andric     // N.B. The attach should be synchronous.  It doesn't help much to get the
459435933ddSDimitry Andric     // prompt back between initiating the attach
460435933ddSDimitry Andric     // and the target actually stopping.  So even if the interpreter is set to
461435933ddSDimitry Andric     // be asynchronous, we wait for the stop
462ac7ddfbfSEd Maste     // ourselves here.
463ac7ddfbfSEd Maste 
464ac7ddfbfSEd Maste     StateType state = eStateInvalid;
465ac7ddfbfSEd Maste     Process *process = m_exe_ctx.GetProcessPtr();
466ac7ddfbfSEd Maste 
467ac7ddfbfSEd Maste     if (!StopProcessIfNecessary(process, state, result))
468ac7ddfbfSEd Maste       return false;
469ac7ddfbfSEd Maste 
470435933ddSDimitry Andric     if (target == nullptr) {
471ac7ddfbfSEd Maste       // If there isn't a current target create one.
472ac7ddfbfSEd Maste       TargetSP new_target_sp;
473ac7ddfbfSEd Maste       Error error;
474ac7ddfbfSEd Maste 
475435933ddSDimitry Andric       error = m_interpreter.GetDebugger().GetTargetList().CreateTarget(
476435933ddSDimitry Andric           m_interpreter.GetDebugger(), "", "", false,
4774bb0738eSEd Maste           nullptr, // No platform options
478ac7ddfbfSEd Maste           new_target_sp);
479ac7ddfbfSEd Maste       target = new_target_sp.get();
480435933ddSDimitry Andric       if (target == nullptr || error.Fail()) {
481ac7ddfbfSEd Maste         result.AppendError(error.AsCString("Error creating target"));
482ac7ddfbfSEd Maste         return false;
483ac7ddfbfSEd Maste       }
484ac7ddfbfSEd Maste       m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target);
485ac7ddfbfSEd Maste     }
486ac7ddfbfSEd Maste 
487435933ddSDimitry Andric     // Record the old executable module, we want to issue a warning if the
488435933ddSDimitry Andric     // process of attaching changed the
489435933ddSDimitry Andric     // current executable (like somebody said "file foo" then attached to a PID
490435933ddSDimitry Andric     // whose executable was bar.)
491ac7ddfbfSEd Maste 
492ac7ddfbfSEd Maste     ModuleSP old_exec_module_sp = target->GetExecutableModule();
493ac7ddfbfSEd Maste     ArchSpec old_arch_spec = target->GetArchitecture();
494ac7ddfbfSEd Maste 
495435933ddSDimitry Andric     if (command.GetArgumentCount()) {
496435933ddSDimitry Andric       result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: %s\n",
497435933ddSDimitry Andric                                    m_cmd_name.c_str(), m_cmd_syntax.c_str());
498ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
4991c3bbb01SEd Maste       return false;
500ac7ddfbfSEd Maste     }
501ac7ddfbfSEd Maste 
5021c3bbb01SEd Maste     m_interpreter.UpdateExecutionContext(nullptr);
5037aa51b79SEd Maste     StreamString stream;
5041c3bbb01SEd Maste     const auto error = target->Attach(m_options.attach_info, &stream);
505435933ddSDimitry Andric     if (error.Success()) {
5061c3bbb01SEd Maste       ProcessSP process_sp(target->GetProcessSP());
507435933ddSDimitry Andric       if (process_sp) {
508435933ddSDimitry Andric         result.AppendMessage(stream.GetString());
509ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusSuccessFinishNoResult);
5101c3bbb01SEd Maste         result.SetDidChangeProcessState(true);
511444ed5c5SDimitry Andric         result.SetAbnormalStopWasExpected(true);
512435933ddSDimitry Andric       } else {
513435933ddSDimitry Andric         result.AppendError(
514435933ddSDimitry Andric             "no error returned from Target::Attach, and target has no process");
515ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
51612b93ac6SEd Maste       }
517435933ddSDimitry Andric     } else {
51812b93ac6SEd Maste       result.AppendErrorWithFormat("attach failed: %s\n", error.AsCString());
51912b93ac6SEd Maste       result.SetStatus(eReturnStatusFailed);
520ac7ddfbfSEd Maste     }
521ac7ddfbfSEd Maste 
5221c3bbb01SEd Maste     if (!result.Succeeded())
5231c3bbb01SEd Maste       return false;
5241c3bbb01SEd Maste 
525435933ddSDimitry Andric     // Okay, we're done.  Last step is to warn if the executable module has
526435933ddSDimitry Andric     // changed:
527ac7ddfbfSEd Maste     char new_path[PATH_MAX];
528ac7ddfbfSEd Maste     ModuleSP new_exec_module_sp(target->GetExecutableModule());
529435933ddSDimitry Andric     if (!old_exec_module_sp) {
530ac7ddfbfSEd Maste       // We might not have a module if we attached to a raw pid...
531435933ddSDimitry Andric       if (new_exec_module_sp) {
532ac7ddfbfSEd Maste         new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX);
533435933ddSDimitry Andric         result.AppendMessageWithFormat("Executable module set to \"%s\".\n",
534435933ddSDimitry Andric                                        new_path);
535ac7ddfbfSEd Maste       }
536435933ddSDimitry Andric     } else if (old_exec_module_sp->GetFileSpec() !=
537435933ddSDimitry Andric                new_exec_module_sp->GetFileSpec()) {
538ac7ddfbfSEd Maste       char old_path[PATH_MAX];
539ac7ddfbfSEd Maste 
540ac7ddfbfSEd Maste       old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX);
541ac7ddfbfSEd Maste       new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX);
542ac7ddfbfSEd Maste 
543435933ddSDimitry Andric       result.AppendWarningWithFormat(
544435933ddSDimitry Andric           "Executable module changed from \"%s\" to \"%s\".\n", old_path,
545435933ddSDimitry Andric           new_path);
546ac7ddfbfSEd Maste     }
547ac7ddfbfSEd Maste 
548435933ddSDimitry Andric     if (!old_arch_spec.IsValid()) {
549435933ddSDimitry Andric       result.AppendMessageWithFormat(
550435933ddSDimitry Andric           "Architecture set to: %s.\n",
551435933ddSDimitry Andric           target->GetArchitecture().GetTriple().getTriple().c_str());
552435933ddSDimitry Andric     } else if (!old_arch_spec.IsExactMatch(target->GetArchitecture())) {
553435933ddSDimitry Andric       result.AppendWarningWithFormat(
554435933ddSDimitry Andric           "Architecture changed from %s to %s.\n",
555ac7ddfbfSEd Maste           old_arch_spec.GetTriple().getTriple().c_str(),
556ac7ddfbfSEd Maste           target->GetArchitecture().GetTriple().getTriple().c_str());
557ac7ddfbfSEd Maste     }
558ac7ddfbfSEd Maste 
559435933ddSDimitry Andric     // This supports the use-case scenario of immediately continuing the process
560435933ddSDimitry Andric     // once attached.
561ac7ddfbfSEd Maste     if (m_options.attach_info.GetContinueOnceAttached())
562ac7ddfbfSEd Maste       m_interpreter.HandleCommand("process continue", eLazyBoolNo, result);
5631c3bbb01SEd Maste 
564ac7ddfbfSEd Maste     return result.Succeeded();
565ac7ddfbfSEd Maste   }
566ac7ddfbfSEd Maste 
567ac7ddfbfSEd Maste   CommandOptions m_options;
568ac7ddfbfSEd Maste };
569ac7ddfbfSEd Maste 
570ac7ddfbfSEd Maste //-------------------------------------------------------------------------
571ac7ddfbfSEd Maste // CommandObjectProcessContinue
572ac7ddfbfSEd Maste //-------------------------------------------------------------------------
573435933ddSDimitry Andric 
574435933ddSDimitry Andric static OptionDefinition g_process_continue_options[] = {
575435933ddSDimitry Andric     // clang-format off
576435933ddSDimitry Andric   { LLDB_OPT_SET_ALL, false, "ignore-count",'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeUnsignedInteger, "Ignore <N> crossings of the breakpoint (if it exists) for the currently selected thread." }
577435933ddSDimitry Andric     // clang-format on
578435933ddSDimitry Andric };
579435933ddSDimitry Andric 
580ac7ddfbfSEd Maste #pragma mark CommandObjectProcessContinue
581ac7ddfbfSEd Maste 
582435933ddSDimitry Andric class CommandObjectProcessContinue : public CommandObjectParsed {
583ac7ddfbfSEd Maste public:
584435933ddSDimitry Andric   CommandObjectProcessContinue(CommandInterpreter &interpreter)
585435933ddSDimitry Andric       : CommandObjectParsed(
586435933ddSDimitry Andric             interpreter, "process continue",
587ac7ddfbfSEd Maste             "Continue execution of all threads in the current process.",
588ac7ddfbfSEd Maste             "process continue",
589435933ddSDimitry Andric             eCommandRequiresProcess | eCommandTryTargetAPILock |
590435933ddSDimitry Andric                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused),
591435933ddSDimitry Andric         m_options() {}
592ac7ddfbfSEd Maste 
5934bb0738eSEd Maste   ~CommandObjectProcessContinue() override = default;
594ac7ddfbfSEd Maste 
595ac7ddfbfSEd Maste protected:
596435933ddSDimitry Andric   class CommandOptions : public Options {
597ac7ddfbfSEd Maste   public:
598435933ddSDimitry Andric     CommandOptions() : Options() {
599435933ddSDimitry Andric       // Keep default values of all options in one place: OptionParsingStarting
600435933ddSDimitry Andric       // ()
601435933ddSDimitry Andric       OptionParsingStarting(nullptr);
602ac7ddfbfSEd Maste     }
603ac7ddfbfSEd Maste 
6044bb0738eSEd Maste     ~CommandOptions() override = default;
605ac7ddfbfSEd Maste 
606435933ddSDimitry Andric     Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
607435933ddSDimitry Andric                          ExecutionContext *execution_context) override {
608ac7ddfbfSEd Maste       Error error;
609ac7ddfbfSEd Maste       const int short_option = m_getopt_table[option_idx].val;
610435933ddSDimitry Andric       switch (short_option) {
611ac7ddfbfSEd Maste       case 'i':
612435933ddSDimitry Andric         if (option_arg.getAsInteger(0, m_ignore))
613435933ddSDimitry Andric           error.SetErrorStringWithFormat(
614435933ddSDimitry Andric               "invalid value for ignore option: \"%s\", should be a number.",
615435933ddSDimitry Andric               option_arg.str().c_str());
616ac7ddfbfSEd Maste         break;
617ac7ddfbfSEd Maste 
618ac7ddfbfSEd Maste       default:
619435933ddSDimitry Andric         error.SetErrorStringWithFormat("invalid short option character '%c'",
620435933ddSDimitry Andric                                        short_option);
621ac7ddfbfSEd Maste         break;
622ac7ddfbfSEd Maste       }
623ac7ddfbfSEd Maste       return error;
624ac7ddfbfSEd Maste     }
625ac7ddfbfSEd Maste 
626435933ddSDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
627ac7ddfbfSEd Maste       m_ignore = 0;
628ac7ddfbfSEd Maste     }
629ac7ddfbfSEd Maste 
630435933ddSDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
631435933ddSDimitry Andric       return llvm::makeArrayRef(g_process_continue_options);
632ac7ddfbfSEd Maste     }
633ac7ddfbfSEd Maste 
634ac7ddfbfSEd Maste     uint32_t m_ignore;
635ac7ddfbfSEd Maste   };
636ac7ddfbfSEd Maste 
637435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
638ac7ddfbfSEd Maste     Process *process = m_exe_ctx.GetProcessPtr();
639ac7ddfbfSEd Maste     bool synchronous_execution = m_interpreter.GetSynchronous();
640ac7ddfbfSEd Maste     StateType state = process->GetState();
641435933ddSDimitry Andric     if (state == eStateStopped) {
642435933ddSDimitry Andric       if (command.GetArgumentCount() != 0) {
643435933ddSDimitry Andric         result.AppendErrorWithFormat(
644435933ddSDimitry Andric             "The '%s' command does not take any arguments.\n",
645435933ddSDimitry Andric             m_cmd_name.c_str());
646ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
647ac7ddfbfSEd Maste         return false;
648ac7ddfbfSEd Maste       }
649ac7ddfbfSEd Maste 
650435933ddSDimitry Andric       if (m_options.m_ignore > 0) {
6514bb0738eSEd Maste         ThreadSP sel_thread_sp(GetDefaultThread()->shared_from_this());
652435933ddSDimitry Andric         if (sel_thread_sp) {
653ac7ddfbfSEd Maste           StopInfoSP stop_info_sp = sel_thread_sp->GetStopInfo();
654435933ddSDimitry Andric           if (stop_info_sp &&
655435933ddSDimitry Andric               stop_info_sp->GetStopReason() == eStopReasonBreakpoint) {
656435933ddSDimitry Andric             lldb::break_id_t bp_site_id =
657435933ddSDimitry Andric                 (lldb::break_id_t)stop_info_sp->GetValue();
658435933ddSDimitry Andric             BreakpointSiteSP bp_site_sp(
659435933ddSDimitry Andric                 process->GetBreakpointSiteList().FindByID(bp_site_id));
660435933ddSDimitry Andric             if (bp_site_sp) {
661ac7ddfbfSEd Maste               const size_t num_owners = bp_site_sp->GetNumberOfOwners();
662435933ddSDimitry Andric               for (size_t i = 0; i < num_owners; i++) {
663435933ddSDimitry Andric                 Breakpoint &bp_ref =
664435933ddSDimitry Andric                     bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint();
665435933ddSDimitry Andric                 if (!bp_ref.IsInternal()) {
666ac7ddfbfSEd Maste                   bp_ref.SetIgnoreCount(m_options.m_ignore);
667ac7ddfbfSEd Maste                 }
668ac7ddfbfSEd Maste               }
669ac7ddfbfSEd Maste             }
670ac7ddfbfSEd Maste           }
671ac7ddfbfSEd Maste         }
672ac7ddfbfSEd Maste       }
673ac7ddfbfSEd Maste 
674ac7ddfbfSEd Maste       { // Scope for thread list mutex:
675435933ddSDimitry Andric         std::lock_guard<std::recursive_mutex> guard(
676435933ddSDimitry Andric             process->GetThreadList().GetMutex());
677ac7ddfbfSEd Maste         const uint32_t num_threads = process->GetThreadList().GetSize();
678ac7ddfbfSEd Maste 
679ac7ddfbfSEd Maste         // Set the actions that the threads should each take when resuming
680435933ddSDimitry Andric         for (uint32_t idx = 0; idx < num_threads; ++idx) {
6810127ef0fSEd Maste           const bool override_suspend = false;
682435933ddSDimitry Andric           process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState(
683435933ddSDimitry Andric               eStateRunning, override_suspend);
684ac7ddfbfSEd Maste         }
685ac7ddfbfSEd Maste       }
686ac7ddfbfSEd Maste 
6871c3bbb01SEd Maste       const uint32_t iohandler_id = process->GetIOHandlerID();
6881c3bbb01SEd Maste 
6897aa51b79SEd Maste       StreamString stream;
6907aa51b79SEd Maste       Error error;
6917aa51b79SEd Maste       if (synchronous_execution)
6927aa51b79SEd Maste         error = process->ResumeSynchronous(&stream);
6937aa51b79SEd Maste       else
6947aa51b79SEd Maste         error = process->Resume();
6950127ef0fSEd Maste 
696435933ddSDimitry Andric       if (error.Success()) {
697435933ddSDimitry Andric         // There is a race condition where this thread will return up the call
698435933ddSDimitry Andric         // stack to the main command
699435933ddSDimitry Andric         // handler and show an (lldb) prompt before HandlePrivateEvent (from
700435933ddSDimitry Andric         // PrivateStateThread) has
7010127ef0fSEd Maste         // a chance to call PushProcessIOHandler().
7021c3bbb01SEd Maste         process->SyncIOHandler(iohandler_id, 2000);
7030127ef0fSEd Maste 
704435933ddSDimitry Andric         result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n",
705435933ddSDimitry Andric                                        process->GetID());
706435933ddSDimitry Andric         if (synchronous_execution) {
707435933ddSDimitry Andric           // If any state changed events had anything to say, add that to the
708435933ddSDimitry Andric           // result
709435933ddSDimitry Andric           result.AppendMessage(stream.GetString());
710ac7ddfbfSEd Maste 
711ac7ddfbfSEd Maste           result.SetDidChangeProcessState(true);
712ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusSuccessFinishNoResult);
713435933ddSDimitry Andric         } else {
714ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusSuccessContinuingNoResult);
715ac7ddfbfSEd Maste         }
716435933ddSDimitry Andric       } else {
717435933ddSDimitry Andric         result.AppendErrorWithFormat("Failed to resume process: %s.\n",
718435933ddSDimitry Andric                                      error.AsCString());
719ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
720ac7ddfbfSEd Maste       }
721435933ddSDimitry Andric     } else {
722435933ddSDimitry Andric       result.AppendErrorWithFormat(
723435933ddSDimitry Andric           "Process cannot be continued from its current state (%s).\n",
724ac7ddfbfSEd Maste           StateAsCString(state));
725ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
726ac7ddfbfSEd Maste     }
727ac7ddfbfSEd Maste     return result.Succeeded();
728ac7ddfbfSEd Maste   }
729ac7ddfbfSEd Maste 
730435933ddSDimitry Andric   Options *GetOptions() override { return &m_options; }
731ac7ddfbfSEd Maste 
732ac7ddfbfSEd Maste   CommandOptions m_options;
733ac7ddfbfSEd Maste };
734ac7ddfbfSEd Maste 
735ac7ddfbfSEd Maste //-------------------------------------------------------------------------
736ac7ddfbfSEd Maste // CommandObjectProcessDetach
737ac7ddfbfSEd Maste //-------------------------------------------------------------------------
738435933ddSDimitry Andric static OptionDefinition g_process_detach_options[] = {
739435933ddSDimitry Andric     // clang-format off
740435933ddSDimitry Andric   { LLDB_OPT_SET_1, false, "keep-stopped", 's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Whether or not the process should be kept stopped on detach (if possible)." },
741435933ddSDimitry Andric     // clang-format on
742435933ddSDimitry Andric };
743435933ddSDimitry Andric 
744ac7ddfbfSEd Maste #pragma mark CommandObjectProcessDetach
745ac7ddfbfSEd Maste 
746435933ddSDimitry Andric class CommandObjectProcessDetach : public CommandObjectParsed {
747ac7ddfbfSEd Maste public:
748435933ddSDimitry Andric   class CommandOptions : public Options {
749ac7ddfbfSEd Maste   public:
750435933ddSDimitry Andric     CommandOptions() : Options() { OptionParsingStarting(nullptr); }
751ac7ddfbfSEd Maste 
7524bb0738eSEd Maste     ~CommandOptions() override = default;
753ac7ddfbfSEd Maste 
754435933ddSDimitry Andric     Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
755435933ddSDimitry Andric                          ExecutionContext *execution_context) override {
756ac7ddfbfSEd Maste       Error error;
757ac7ddfbfSEd Maste       const int short_option = m_getopt_table[option_idx].val;
758ac7ddfbfSEd Maste 
759435933ddSDimitry Andric       switch (short_option) {
760ac7ddfbfSEd Maste       case 's':
761ac7ddfbfSEd Maste         bool tmp_result;
762ac7ddfbfSEd Maste         bool success;
763ac7ddfbfSEd Maste         tmp_result = Args::StringToBoolean(option_arg, false, &success);
764ac7ddfbfSEd Maste         if (!success)
765435933ddSDimitry Andric           error.SetErrorStringWithFormat("invalid boolean option: \"%s\"",
766435933ddSDimitry Andric                                          option_arg.str().c_str());
767435933ddSDimitry Andric         else {
768ac7ddfbfSEd Maste           if (tmp_result)
769ac7ddfbfSEd Maste             m_keep_stopped = eLazyBoolYes;
770ac7ddfbfSEd Maste           else
771ac7ddfbfSEd Maste             m_keep_stopped = eLazyBoolNo;
772ac7ddfbfSEd Maste         }
773ac7ddfbfSEd Maste         break;
774ac7ddfbfSEd Maste       default:
775435933ddSDimitry Andric         error.SetErrorStringWithFormat("invalid short option character '%c'",
776435933ddSDimitry Andric                                        short_option);
777ac7ddfbfSEd Maste         break;
778ac7ddfbfSEd Maste       }
779ac7ddfbfSEd Maste       return error;
780ac7ddfbfSEd Maste     }
781ac7ddfbfSEd Maste 
782435933ddSDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
783ac7ddfbfSEd Maste       m_keep_stopped = eLazyBoolCalculate;
784ac7ddfbfSEd Maste     }
785ac7ddfbfSEd Maste 
786435933ddSDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
787435933ddSDimitry Andric       return llvm::makeArrayRef(g_process_detach_options);
788ac7ddfbfSEd Maste     }
789ac7ddfbfSEd Maste 
790ac7ddfbfSEd Maste     // Instance variables to hold the values for command options.
791ac7ddfbfSEd Maste     LazyBool m_keep_stopped;
792ac7ddfbfSEd Maste   };
793ac7ddfbfSEd Maste 
7944bb0738eSEd Maste   CommandObjectProcessDetach(CommandInterpreter &interpreter)
795435933ddSDimitry Andric       : CommandObjectParsed(interpreter, "process detach",
796435933ddSDimitry Andric                             "Detach from the current target process.",
797ac7ddfbfSEd Maste                             "process detach",
798435933ddSDimitry Andric                             eCommandRequiresProcess | eCommandTryTargetAPILock |
799435933ddSDimitry Andric                                 eCommandProcessMustBeLaunched),
800435933ddSDimitry Andric         m_options() {}
801ac7ddfbfSEd Maste 
8024bb0738eSEd Maste   ~CommandObjectProcessDetach() override = default;
803ac7ddfbfSEd Maste 
804435933ddSDimitry Andric   Options *GetOptions() override { return &m_options; }
805ac7ddfbfSEd Maste 
806ac7ddfbfSEd Maste protected:
807435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
808ac7ddfbfSEd Maste     Process *process = m_exe_ctx.GetProcessPtr();
809ac7ddfbfSEd Maste     // FIXME: This will be a Command Option:
810ac7ddfbfSEd Maste     bool keep_stopped;
811435933ddSDimitry Andric     if (m_options.m_keep_stopped == eLazyBoolCalculate) {
812ac7ddfbfSEd Maste       // Check the process default:
8134bb0738eSEd Maste       keep_stopped = process->GetDetachKeepsStopped();
814435933ddSDimitry Andric     } else if (m_options.m_keep_stopped == eLazyBoolYes)
815ac7ddfbfSEd Maste       keep_stopped = true;
816ac7ddfbfSEd Maste     else
817ac7ddfbfSEd Maste       keep_stopped = false;
818ac7ddfbfSEd Maste 
819ac7ddfbfSEd Maste     Error error(process->Detach(keep_stopped));
820435933ddSDimitry Andric     if (error.Success()) {
821ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusSuccessFinishResult);
822435933ddSDimitry Andric     } else {
823ac7ddfbfSEd Maste       result.AppendErrorWithFormat("Detach failed: %s\n", error.AsCString());
824ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
825ac7ddfbfSEd Maste       return false;
826ac7ddfbfSEd Maste     }
827ac7ddfbfSEd Maste     return result.Succeeded();
828ac7ddfbfSEd Maste   }
829ac7ddfbfSEd Maste 
830ac7ddfbfSEd Maste   CommandOptions m_options;
831ac7ddfbfSEd Maste };
832ac7ddfbfSEd Maste 
833ac7ddfbfSEd Maste //-------------------------------------------------------------------------
834ac7ddfbfSEd Maste // CommandObjectProcessConnect
835ac7ddfbfSEd Maste //-------------------------------------------------------------------------
836435933ddSDimitry Andric 
837435933ddSDimitry Andric static OptionDefinition g_process_connect_options[] = {
838435933ddSDimitry Andric     // clang-format off
839435933ddSDimitry Andric   { LLDB_OPT_SET_ALL, false, "plugin", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePlugin, "Name of the process plugin you want to use." },
840435933ddSDimitry Andric     // clang-format on
841435933ddSDimitry Andric };
842435933ddSDimitry Andric 
843ac7ddfbfSEd Maste #pragma mark CommandObjectProcessConnect
844ac7ddfbfSEd Maste 
845435933ddSDimitry Andric class CommandObjectProcessConnect : public CommandObjectParsed {
846ac7ddfbfSEd Maste public:
847435933ddSDimitry Andric   class CommandOptions : public Options {
848ac7ddfbfSEd Maste   public:
849435933ddSDimitry Andric     CommandOptions() : Options() {
850435933ddSDimitry Andric       // Keep default values of all options in one place: OptionParsingStarting
851435933ddSDimitry Andric       // ()
852435933ddSDimitry Andric       OptionParsingStarting(nullptr);
853ac7ddfbfSEd Maste     }
854ac7ddfbfSEd Maste 
8554bb0738eSEd Maste     ~CommandOptions() override = default;
856ac7ddfbfSEd Maste 
857435933ddSDimitry Andric     Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
858435933ddSDimitry Andric                          ExecutionContext *execution_context) override {
859ac7ddfbfSEd Maste       Error error;
860ac7ddfbfSEd Maste       const int short_option = m_getopt_table[option_idx].val;
861ac7ddfbfSEd Maste 
862435933ddSDimitry Andric       switch (short_option) {
863ac7ddfbfSEd Maste       case 'p':
864ac7ddfbfSEd Maste         plugin_name.assign(option_arg);
865ac7ddfbfSEd Maste         break;
866ac7ddfbfSEd Maste 
867ac7ddfbfSEd Maste       default:
868435933ddSDimitry Andric         error.SetErrorStringWithFormat("invalid short option character '%c'",
869435933ddSDimitry Andric                                        short_option);
870ac7ddfbfSEd Maste         break;
871ac7ddfbfSEd Maste       }
872ac7ddfbfSEd Maste       return error;
873ac7ddfbfSEd Maste     }
874ac7ddfbfSEd Maste 
875435933ddSDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
876ac7ddfbfSEd Maste       plugin_name.clear();
877ac7ddfbfSEd Maste     }
878ac7ddfbfSEd Maste 
879435933ddSDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
880435933ddSDimitry Andric       return llvm::makeArrayRef(g_process_connect_options);
881ac7ddfbfSEd Maste     }
882ac7ddfbfSEd Maste 
883ac7ddfbfSEd Maste     // Instance variables to hold the values for command options.
884ac7ddfbfSEd Maste 
885ac7ddfbfSEd Maste     std::string plugin_name;
886ac7ddfbfSEd Maste   };
887ac7ddfbfSEd Maste 
888435933ddSDimitry Andric   CommandObjectProcessConnect(CommandInterpreter &interpreter)
889435933ddSDimitry Andric       : CommandObjectParsed(interpreter, "process connect",
890ac7ddfbfSEd Maste                             "Connect to a remote debug service.",
891435933ddSDimitry Andric                             "process connect <remote-url>", 0),
892435933ddSDimitry Andric         m_options() {}
893ac7ddfbfSEd Maste 
8944bb0738eSEd Maste   ~CommandObjectProcessConnect() override = default;
895ac7ddfbfSEd Maste 
896435933ddSDimitry Andric   Options *GetOptions() override { return &m_options; }
897ac7ddfbfSEd Maste 
898ac7ddfbfSEd Maste protected:
899435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
900435933ddSDimitry Andric     if (command.GetArgumentCount() != 1) {
901435933ddSDimitry Andric       result.AppendErrorWithFormat(
902435933ddSDimitry Andric           "'%s' takes exactly one argument:\nUsage: %s\n", m_cmd_name.c_str(),
9039f2f44ceSEd Maste           m_cmd_syntax.c_str());
9049f2f44ceSEd Maste       result.SetStatus(eReturnStatusFailed);
9059f2f44ceSEd Maste       return false;
9069f2f44ceSEd Maste     }
907ac7ddfbfSEd Maste 
908ac7ddfbfSEd Maste     Process *process = m_exe_ctx.GetProcessPtr();
909435933ddSDimitry Andric     if (process && process->IsAlive()) {
910435933ddSDimitry Andric       result.AppendErrorWithFormat(
911435933ddSDimitry Andric           "Process %" PRIu64
912435933ddSDimitry Andric           " is currently being debugged, kill the process before connecting.\n",
913ac7ddfbfSEd Maste           process->GetID());
914ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
915ac7ddfbfSEd Maste       return false;
916ac7ddfbfSEd Maste     }
917ac7ddfbfSEd Maste 
9189f2f44ceSEd Maste     const char *plugin_name = nullptr;
919ac7ddfbfSEd Maste     if (!m_options.plugin_name.empty())
920ac7ddfbfSEd Maste       plugin_name = m_options.plugin_name.c_str();
921ac7ddfbfSEd Maste 
9229f2f44ceSEd Maste     Error error;
9239f2f44ceSEd Maste     Debugger &debugger = m_interpreter.GetDebugger();
9249f2f44ceSEd Maste     PlatformSP platform_sp = m_interpreter.GetPlatform(true);
925435933ddSDimitry Andric     ProcessSP process_sp = platform_sp->ConnectProcess(
926435933ddSDimitry Andric         command.GetArgumentAtIndex(0), plugin_name, debugger,
927435933ddSDimitry Andric         debugger.GetSelectedTarget().get(), error);
928435933ddSDimitry Andric     if (error.Fail() || process_sp == nullptr) {
9299f2f44ceSEd Maste       result.AppendError(error.AsCString("Error connecting to the process"));
930ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
931ac7ddfbfSEd Maste       return false;
932ac7ddfbfSEd Maste     }
9339f2f44ceSEd Maste     return true;
934ac7ddfbfSEd Maste   }
935ac7ddfbfSEd Maste 
936ac7ddfbfSEd Maste   CommandOptions m_options;
937ac7ddfbfSEd Maste };
938ac7ddfbfSEd Maste 
939ac7ddfbfSEd Maste //-------------------------------------------------------------------------
940ac7ddfbfSEd Maste // CommandObjectProcessPlugin
941ac7ddfbfSEd Maste //-------------------------------------------------------------------------
942ac7ddfbfSEd Maste #pragma mark CommandObjectProcessPlugin
943ac7ddfbfSEd Maste 
944435933ddSDimitry Andric class CommandObjectProcessPlugin : public CommandObjectProxy {
945ac7ddfbfSEd Maste public:
9464bb0738eSEd Maste   CommandObjectProcessPlugin(CommandInterpreter &interpreter)
947435933ddSDimitry Andric       : CommandObjectProxy(
948435933ddSDimitry Andric             interpreter, "process plugin",
949435933ddSDimitry Andric             "Send a custom command to the current target process plug-in.",
950435933ddSDimitry Andric             "process plugin <args>", 0) {}
951ac7ddfbfSEd Maste 
9524bb0738eSEd Maste   ~CommandObjectProcessPlugin() override = default;
953ac7ddfbfSEd Maste 
954435933ddSDimitry Andric   CommandObject *GetProxyCommandObject() override {
955ac7ddfbfSEd Maste     Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
956ac7ddfbfSEd Maste     if (process)
957ac7ddfbfSEd Maste       return process->GetPluginCommandObject();
9584bb0738eSEd Maste     return nullptr;
959ac7ddfbfSEd Maste   }
960ac7ddfbfSEd Maste };
961ac7ddfbfSEd Maste 
962ac7ddfbfSEd Maste //-------------------------------------------------------------------------
963ac7ddfbfSEd Maste // CommandObjectProcessLoad
964ac7ddfbfSEd Maste //-------------------------------------------------------------------------
965435933ddSDimitry Andric 
966435933ddSDimitry Andric static OptionDefinition g_process_load_options[] = {
967435933ddSDimitry Andric     // clang-format off
968435933ddSDimitry Andric   { LLDB_OPT_SET_ALL, false, "install", 'i', OptionParser::eOptionalArgument, nullptr, 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." },
969435933ddSDimitry Andric     // clang-format on
970435933ddSDimitry Andric };
971435933ddSDimitry Andric 
972ac7ddfbfSEd Maste #pragma mark CommandObjectProcessLoad
973ac7ddfbfSEd Maste 
974435933ddSDimitry Andric class CommandObjectProcessLoad : public CommandObjectParsed {
975ac7ddfbfSEd Maste public:
976435933ddSDimitry Andric   class CommandOptions : public Options {
9779f2f44ceSEd Maste   public:
978435933ddSDimitry Andric     CommandOptions() : Options() {
979435933ddSDimitry Andric       // Keep default values of all options in one place: OptionParsingStarting
980435933ddSDimitry Andric       // ()
981435933ddSDimitry Andric       OptionParsingStarting(nullptr);
9829f2f44ceSEd Maste     }
9839f2f44ceSEd Maste 
9849f2f44ceSEd Maste     ~CommandOptions() override = default;
9859f2f44ceSEd Maste 
986435933ddSDimitry Andric     Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
987435933ddSDimitry Andric                          ExecutionContext *execution_context) override {
9889f2f44ceSEd Maste       Error error;
9899f2f44ceSEd Maste       const int short_option = m_getopt_table[option_idx].val;
990435933ddSDimitry Andric       switch (short_option) {
9919f2f44ceSEd Maste       case 'i':
9929f2f44ceSEd Maste         do_install = true;
993435933ddSDimitry Andric         if (!option_arg.empty())
9949f2f44ceSEd Maste           install_path.SetFile(option_arg, false);
9959f2f44ceSEd Maste         break;
9969f2f44ceSEd Maste       default:
997435933ddSDimitry Andric         error.SetErrorStringWithFormat("invalid short option character '%c'",
998435933ddSDimitry Andric                                        short_option);
9999f2f44ceSEd Maste         break;
10009f2f44ceSEd Maste       }
10019f2f44ceSEd Maste       return error;
10029f2f44ceSEd Maste     }
10039f2f44ceSEd Maste 
1004435933ddSDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
10059f2f44ceSEd Maste       do_install = false;
10069f2f44ceSEd Maste       install_path.Clear();
10079f2f44ceSEd Maste     }
10089f2f44ceSEd Maste 
1009435933ddSDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1010435933ddSDimitry Andric       return llvm::makeArrayRef(g_process_load_options);
10119f2f44ceSEd Maste     }
10129f2f44ceSEd Maste 
10139f2f44ceSEd Maste     // Instance variables to hold the values for command options.
10149f2f44ceSEd Maste     bool do_install;
10159f2f44ceSEd Maste     FileSpec install_path;
10169f2f44ceSEd Maste   };
1017ac7ddfbfSEd Maste 
1018435933ddSDimitry Andric   CommandObjectProcessLoad(CommandInterpreter &interpreter)
1019435933ddSDimitry Andric       : CommandObjectParsed(interpreter, "process load",
1020ac7ddfbfSEd Maste                             "Load a shared library into the current process.",
1021ac7ddfbfSEd Maste                             "process load <filename> [<filename> ...]",
1022435933ddSDimitry Andric                             eCommandRequiresProcess | eCommandTryTargetAPILock |
10231c3bbb01SEd Maste                                 eCommandProcessMustBeLaunched |
10249f2f44ceSEd Maste                                 eCommandProcessMustBePaused),
1025435933ddSDimitry Andric         m_options() {}
1026ac7ddfbfSEd Maste 
10279f2f44ceSEd Maste   ~CommandObjectProcessLoad() override = default;
10289f2f44ceSEd Maste 
1029435933ddSDimitry Andric   Options *GetOptions() override { return &m_options; }
1030ac7ddfbfSEd Maste 
1031ac7ddfbfSEd Maste protected:
1032435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
1033ac7ddfbfSEd Maste     Process *process = m_exe_ctx.GetProcessPtr();
1034ac7ddfbfSEd Maste 
1035435933ddSDimitry Andric     for (auto &entry : command.entries()) {
1036ac7ddfbfSEd Maste       Error error;
10379f2f44ceSEd Maste       PlatformSP platform = process->GetTarget().GetPlatform();
1038435933ddSDimitry Andric       llvm::StringRef image_path = entry.ref;
10399f2f44ceSEd Maste       uint32_t image_token = LLDB_INVALID_IMAGE_TOKEN;
10409f2f44ceSEd Maste 
1041435933ddSDimitry Andric       if (!m_options.do_install) {
1042ac7ddfbfSEd Maste         FileSpec image_spec(image_path, false);
10439f2f44ceSEd Maste         platform->ResolveRemotePath(image_spec, image_spec);
1044435933ddSDimitry Andric         image_token =
1045435933ddSDimitry Andric             platform->LoadImage(process, FileSpec(), image_spec, error);
1046435933ddSDimitry Andric       } else if (m_options.install_path) {
10479f2f44ceSEd Maste         FileSpec image_spec(image_path, true);
1048435933ddSDimitry Andric         platform->ResolveRemotePath(m_options.install_path,
1049435933ddSDimitry Andric                                     m_options.install_path);
1050435933ddSDimitry Andric         image_token = platform->LoadImage(process, image_spec,
1051435933ddSDimitry Andric                                           m_options.install_path, error);
1052435933ddSDimitry Andric       } else {
10539f2f44ceSEd Maste         FileSpec image_spec(image_path, true);
1054435933ddSDimitry Andric         image_token =
1055435933ddSDimitry Andric             platform->LoadImage(process, image_spec, FileSpec(), error);
10569f2f44ceSEd Maste       }
10579f2f44ceSEd Maste 
1058435933ddSDimitry Andric       if (image_token != LLDB_INVALID_IMAGE_TOKEN) {
1059435933ddSDimitry Andric         result.AppendMessageWithFormat(
1060435933ddSDimitry Andric             "Loading \"%s\"...ok\nImage %u loaded.\n", image_path.str().c_str(),
1061435933ddSDimitry Andric             image_token);
1062ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusSuccessFinishResult);
1063435933ddSDimitry Andric       } else {
1064435933ddSDimitry Andric         result.AppendErrorWithFormat("failed to load '%s': %s",
1065435933ddSDimitry Andric                                      image_path.str().c_str(),
1066435933ddSDimitry Andric                                      error.AsCString());
1067ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
1068ac7ddfbfSEd Maste       }
1069ac7ddfbfSEd Maste     }
1070ac7ddfbfSEd Maste     return result.Succeeded();
1071ac7ddfbfSEd Maste   }
10729f2f44ceSEd Maste 
10739f2f44ceSEd Maste   CommandOptions m_options;
1074ac7ddfbfSEd Maste };
1075ac7ddfbfSEd Maste 
1076ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1077ac7ddfbfSEd Maste // CommandObjectProcessUnload
1078ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1079ac7ddfbfSEd Maste #pragma mark CommandObjectProcessUnload
1080ac7ddfbfSEd Maste 
1081435933ddSDimitry Andric class CommandObjectProcessUnload : public CommandObjectParsed {
1082ac7ddfbfSEd Maste public:
1083435933ddSDimitry Andric   CommandObjectProcessUnload(CommandInterpreter &interpreter)
1084435933ddSDimitry Andric       : CommandObjectParsed(
1085435933ddSDimitry Andric             interpreter, "process unload",
1086435933ddSDimitry Andric             "Unload a shared library from the current process using the index "
1087435933ddSDimitry Andric             "returned by a previous call to \"process load\".",
1088ac7ddfbfSEd Maste             "process unload <index>",
1089435933ddSDimitry Andric             eCommandRequiresProcess | eCommandTryTargetAPILock |
1090435933ddSDimitry Andric                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {}
1091ac7ddfbfSEd Maste 
10924bb0738eSEd Maste   ~CommandObjectProcessUnload() override = default;
1093ac7ddfbfSEd Maste 
1094ac7ddfbfSEd Maste protected:
1095435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
1096ac7ddfbfSEd Maste     Process *process = m_exe_ctx.GetProcessPtr();
1097ac7ddfbfSEd Maste 
1098435933ddSDimitry Andric     for (auto &entry : command.entries()) {
1099435933ddSDimitry Andric       uint32_t image_token;
1100435933ddSDimitry Andric       if (entry.ref.getAsInteger(0, image_token)) {
1101435933ddSDimitry Andric         result.AppendErrorWithFormat("invalid image index argument '%s'",
1102435933ddSDimitry Andric                                      entry.ref.str().c_str());
1103ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
1104ac7ddfbfSEd Maste         break;
1105435933ddSDimitry Andric       } else {
1106435933ddSDimitry Andric         Error error(process->GetTarget().GetPlatform()->UnloadImage(
1107435933ddSDimitry Andric             process, image_token));
1108435933ddSDimitry Andric         if (error.Success()) {
1109435933ddSDimitry Andric           result.AppendMessageWithFormat(
1110435933ddSDimitry Andric               "Unloading shared library with index %u...ok\n", image_token);
1111ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusSuccessFinishResult);
1112435933ddSDimitry Andric         } else {
1113435933ddSDimitry Andric           result.AppendErrorWithFormat("failed to unload image: %s",
1114435933ddSDimitry Andric                                        error.AsCString());
1115ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusFailed);
1116ac7ddfbfSEd Maste           break;
1117ac7ddfbfSEd Maste         }
1118ac7ddfbfSEd Maste       }
1119ac7ddfbfSEd Maste     }
1120ac7ddfbfSEd Maste     return result.Succeeded();
1121ac7ddfbfSEd Maste   }
1122ac7ddfbfSEd Maste };
1123ac7ddfbfSEd Maste 
1124ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1125ac7ddfbfSEd Maste // CommandObjectProcessSignal
1126ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1127ac7ddfbfSEd Maste #pragma mark CommandObjectProcessSignal
1128ac7ddfbfSEd Maste 
1129435933ddSDimitry Andric class CommandObjectProcessSignal : public CommandObjectParsed {
1130ac7ddfbfSEd Maste public:
11314bb0738eSEd Maste   CommandObjectProcessSignal(CommandInterpreter &interpreter)
1132435933ddSDimitry Andric       : CommandObjectParsed(interpreter, "process signal",
1133435933ddSDimitry Andric                             "Send a UNIX signal to the current target process.",
1134435933ddSDimitry Andric                             nullptr, eCommandRequiresProcess |
1135435933ddSDimitry Andric                                          eCommandTryTargetAPILock) {
1136ac7ddfbfSEd Maste     CommandArgumentEntry arg;
1137ac7ddfbfSEd Maste     CommandArgumentData signal_arg;
1138ac7ddfbfSEd Maste 
1139ac7ddfbfSEd Maste     // Define the first (and only) variant of this arg.
1140ac7ddfbfSEd Maste     signal_arg.arg_type = eArgTypeUnixSignal;
1141ac7ddfbfSEd Maste     signal_arg.arg_repetition = eArgRepeatPlain;
1142ac7ddfbfSEd Maste 
1143435933ddSDimitry Andric     // There is only one variant this argument could be; put it into the
1144435933ddSDimitry Andric     // argument entry.
1145ac7ddfbfSEd Maste     arg.push_back(signal_arg);
1146ac7ddfbfSEd Maste 
1147ac7ddfbfSEd Maste     // Push the data for the first argument into the m_arguments vector.
1148ac7ddfbfSEd Maste     m_arguments.push_back(arg);
1149ac7ddfbfSEd Maste   }
1150ac7ddfbfSEd Maste 
11514bb0738eSEd Maste   ~CommandObjectProcessSignal() override = default;
1152ac7ddfbfSEd Maste 
1153ac7ddfbfSEd Maste protected:
1154435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
1155ac7ddfbfSEd Maste     Process *process = m_exe_ctx.GetProcessPtr();
1156ac7ddfbfSEd Maste 
1157435933ddSDimitry Andric     if (command.GetArgumentCount() == 1) {
1158ac7ddfbfSEd Maste       int signo = LLDB_INVALID_SIGNAL_NUMBER;
1159ac7ddfbfSEd Maste 
1160ac7ddfbfSEd Maste       const char *signal_name = command.GetArgumentAtIndex(0);
1161ac7ddfbfSEd Maste       if (::isxdigit(signal_name[0]))
1162435933ddSDimitry Andric         signo =
1163435933ddSDimitry Andric             StringConvert::ToSInt32(signal_name, LLDB_INVALID_SIGNAL_NUMBER, 0);
1164ac7ddfbfSEd Maste       else
1165b91a7dfcSDimitry Andric         signo = process->GetUnixSignals()->GetSignalNumberFromName(signal_name);
1166ac7ddfbfSEd Maste 
1167435933ddSDimitry Andric       if (signo == LLDB_INVALID_SIGNAL_NUMBER) {
1168435933ddSDimitry Andric         result.AppendErrorWithFormat("Invalid signal argument '%s'.\n",
1169435933ddSDimitry Andric                                      command.GetArgumentAtIndex(0));
1170ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
1171435933ddSDimitry Andric       } else {
1172ac7ddfbfSEd Maste         Error error(process->Signal(signo));
1173435933ddSDimitry Andric         if (error.Success()) {
1174ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusSuccessFinishResult);
1175435933ddSDimitry Andric         } else {
1176435933ddSDimitry Andric           result.AppendErrorWithFormat("Failed to send signal %i: %s\n", signo,
1177435933ddSDimitry Andric                                        error.AsCString());
1178ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusFailed);
1179ac7ddfbfSEd Maste         }
1180ac7ddfbfSEd Maste       }
1181435933ddSDimitry Andric     } else {
1182435933ddSDimitry Andric       result.AppendErrorWithFormat(
1183435933ddSDimitry Andric           "'%s' takes exactly one signal number argument:\nUsage: %s\n",
1184435933ddSDimitry Andric           m_cmd_name.c_str(), m_cmd_syntax.c_str());
1185ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1186ac7ddfbfSEd Maste     }
1187ac7ddfbfSEd Maste     return result.Succeeded();
1188ac7ddfbfSEd Maste   }
1189ac7ddfbfSEd Maste };
1190ac7ddfbfSEd Maste 
1191ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1192ac7ddfbfSEd Maste // CommandObjectProcessInterrupt
1193ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1194ac7ddfbfSEd Maste #pragma mark CommandObjectProcessInterrupt
1195ac7ddfbfSEd Maste 
1196435933ddSDimitry Andric class CommandObjectProcessInterrupt : public CommandObjectParsed {
1197ac7ddfbfSEd Maste public:
11984bb0738eSEd Maste   CommandObjectProcessInterrupt(CommandInterpreter &interpreter)
1199435933ddSDimitry Andric       : CommandObjectParsed(interpreter, "process interrupt",
1200435933ddSDimitry Andric                             "Interrupt the current target process.",
1201ac7ddfbfSEd Maste                             "process interrupt",
1202435933ddSDimitry Andric                             eCommandRequiresProcess | eCommandTryTargetAPILock |
1203435933ddSDimitry Andric                                 eCommandProcessMustBeLaunched) {}
1204ac7ddfbfSEd Maste 
12054bb0738eSEd Maste   ~CommandObjectProcessInterrupt() override = default;
1206ac7ddfbfSEd Maste 
1207ac7ddfbfSEd Maste protected:
1208435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
1209ac7ddfbfSEd Maste     Process *process = m_exe_ctx.GetProcessPtr();
1210435933ddSDimitry Andric     if (process == nullptr) {
1211ac7ddfbfSEd Maste       result.AppendError("no process to halt");
1212ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1213ac7ddfbfSEd Maste       return false;
1214ac7ddfbfSEd Maste     }
1215ac7ddfbfSEd Maste 
1216435933ddSDimitry Andric     if (command.GetArgumentCount() == 0) {
1217ac7ddfbfSEd Maste       bool clear_thread_plans = true;
1218ac7ddfbfSEd Maste       Error error(process->Halt(clear_thread_plans));
1219435933ddSDimitry Andric       if (error.Success()) {
1220ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusSuccessFinishResult);
1221435933ddSDimitry Andric       } else {
1222435933ddSDimitry Andric         result.AppendErrorWithFormat("Failed to halt process: %s\n",
1223435933ddSDimitry Andric                                      error.AsCString());
1224ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
1225ac7ddfbfSEd Maste       }
1226435933ddSDimitry Andric     } else {
1227ac7ddfbfSEd Maste       result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n",
1228435933ddSDimitry Andric                                    m_cmd_name.c_str(), m_cmd_syntax.c_str());
1229ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1230ac7ddfbfSEd Maste     }
1231ac7ddfbfSEd Maste     return result.Succeeded();
1232ac7ddfbfSEd Maste   }
1233ac7ddfbfSEd Maste };
1234ac7ddfbfSEd Maste 
1235ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1236ac7ddfbfSEd Maste // CommandObjectProcessKill
1237ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1238ac7ddfbfSEd Maste #pragma mark CommandObjectProcessKill
1239ac7ddfbfSEd Maste 
1240435933ddSDimitry Andric class CommandObjectProcessKill : public CommandObjectParsed {
1241ac7ddfbfSEd Maste public:
12424bb0738eSEd Maste   CommandObjectProcessKill(CommandInterpreter &interpreter)
1243435933ddSDimitry Andric       : CommandObjectParsed(interpreter, "process kill",
1244435933ddSDimitry Andric                             "Terminate the current target process.",
1245435933ddSDimitry Andric                             "process kill",
1246435933ddSDimitry Andric                             eCommandRequiresProcess | eCommandTryTargetAPILock |
1247435933ddSDimitry Andric                                 eCommandProcessMustBeLaunched) {}
1248ac7ddfbfSEd Maste 
12494bb0738eSEd Maste   ~CommandObjectProcessKill() override = default;
1250ac7ddfbfSEd Maste 
1251ac7ddfbfSEd Maste protected:
1252435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
1253ac7ddfbfSEd Maste     Process *process = m_exe_ctx.GetProcessPtr();
1254435933ddSDimitry Andric     if (process == nullptr) {
1255ac7ddfbfSEd Maste       result.AppendError("no process to kill");
1256ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1257ac7ddfbfSEd Maste       return false;
1258ac7ddfbfSEd Maste     }
1259ac7ddfbfSEd Maste 
1260435933ddSDimitry Andric     if (command.GetArgumentCount() == 0) {
12611c3bbb01SEd Maste       Error error(process->Destroy(true));
1262435933ddSDimitry Andric       if (error.Success()) {
1263ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusSuccessFinishResult);
1264435933ddSDimitry Andric       } else {
1265435933ddSDimitry Andric         result.AppendErrorWithFormat("Failed to kill process: %s\n",
1266435933ddSDimitry Andric                                      error.AsCString());
1267ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
1268ac7ddfbfSEd Maste       }
1269435933ddSDimitry Andric     } else {
1270ac7ddfbfSEd Maste       result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n",
1271435933ddSDimitry Andric                                    m_cmd_name.c_str(), m_cmd_syntax.c_str());
1272ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1273ac7ddfbfSEd Maste     }
1274ac7ddfbfSEd Maste     return result.Succeeded();
1275ac7ddfbfSEd Maste   }
1276ac7ddfbfSEd Maste };
1277ac7ddfbfSEd Maste 
1278ac7ddfbfSEd Maste //-------------------------------------------------------------------------
12790127ef0fSEd Maste // CommandObjectProcessSaveCore
12800127ef0fSEd Maste //-------------------------------------------------------------------------
12810127ef0fSEd Maste #pragma mark CommandObjectProcessSaveCore
12820127ef0fSEd Maste 
1283435933ddSDimitry Andric class CommandObjectProcessSaveCore : public CommandObjectParsed {
12840127ef0fSEd Maste public:
1285435933ddSDimitry Andric   CommandObjectProcessSaveCore(CommandInterpreter &interpreter)
1286435933ddSDimitry Andric       : CommandObjectParsed(interpreter, "process save-core",
1287435933ddSDimitry Andric                             "Save the current process as a core file using an "
1288435933ddSDimitry Andric                             "appropriate file type.",
12890127ef0fSEd Maste                             "process save-core FILE",
1290435933ddSDimitry Andric                             eCommandRequiresProcess | eCommandTryTargetAPILock |
1291435933ddSDimitry Andric                                 eCommandProcessMustBeLaunched) {}
12920127ef0fSEd Maste 
12934bb0738eSEd Maste   ~CommandObjectProcessSaveCore() override = default;
12940127ef0fSEd Maste 
12950127ef0fSEd Maste protected:
1296435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
12970127ef0fSEd Maste     ProcessSP process_sp = m_exe_ctx.GetProcessSP();
1298435933ddSDimitry Andric     if (process_sp) {
1299435933ddSDimitry Andric       if (command.GetArgumentCount() == 1) {
13000127ef0fSEd Maste         FileSpec output_file(command.GetArgumentAtIndex(0), false);
13010127ef0fSEd Maste         Error error = PluginManager::SaveCore(process_sp, output_file);
1302435933ddSDimitry Andric         if (error.Success()) {
13030127ef0fSEd Maste           result.SetStatus(eReturnStatusSuccessFinishResult);
1304435933ddSDimitry Andric         } else {
1305435933ddSDimitry Andric           result.AppendErrorWithFormat(
1306435933ddSDimitry Andric               "Failed to save core file for process: %s\n", error.AsCString());
13070127ef0fSEd Maste           result.SetStatus(eReturnStatusFailed);
13080127ef0fSEd Maste         }
1309435933ddSDimitry Andric       } else {
13100127ef0fSEd Maste         result.AppendErrorWithFormat("'%s' takes one arguments:\nUsage: %s\n",
1311435933ddSDimitry Andric                                      m_cmd_name.c_str(), m_cmd_syntax.c_str());
13120127ef0fSEd Maste         result.SetStatus(eReturnStatusFailed);
13130127ef0fSEd Maste       }
1314435933ddSDimitry Andric     } else {
13150127ef0fSEd Maste       result.AppendError("invalid process");
13160127ef0fSEd Maste       result.SetStatus(eReturnStatusFailed);
13170127ef0fSEd Maste       return false;
13180127ef0fSEd Maste     }
13190127ef0fSEd Maste 
13200127ef0fSEd Maste     return result.Succeeded();
13210127ef0fSEd Maste   }
13220127ef0fSEd Maste };
13230127ef0fSEd Maste 
13240127ef0fSEd Maste //-------------------------------------------------------------------------
1325ac7ddfbfSEd Maste // CommandObjectProcessStatus
1326ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1327ac7ddfbfSEd Maste #pragma mark CommandObjectProcessStatus
1328ac7ddfbfSEd Maste 
1329435933ddSDimitry Andric class CommandObjectProcessStatus : public CommandObjectParsed {
1330ac7ddfbfSEd Maste public:
13314bb0738eSEd Maste   CommandObjectProcessStatus(CommandInterpreter &interpreter)
1332435933ddSDimitry Andric       : CommandObjectParsed(
1333435933ddSDimitry Andric             interpreter, "process status",
1334435933ddSDimitry Andric             "Show status and stop location for the current target process.",
1335435933ddSDimitry Andric             "process status",
1336435933ddSDimitry Andric             eCommandRequiresProcess | eCommandTryTargetAPILock) {}
1337ac7ddfbfSEd Maste 
13384bb0738eSEd Maste   ~CommandObjectProcessStatus() override = default;
1339ac7ddfbfSEd Maste 
1340435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
1341ac7ddfbfSEd Maste     Stream &strm = result.GetOutputStream();
1342ac7ddfbfSEd Maste     result.SetStatus(eReturnStatusSuccessFinishNoResult);
1343435933ddSDimitry Andric     // No need to check "process" for validity as eCommandRequiresProcess
1344435933ddSDimitry Andric     // ensures it is valid
1345ac7ddfbfSEd Maste     Process *process = m_exe_ctx.GetProcessPtr();
1346ac7ddfbfSEd Maste     const bool only_threads_with_stop_reason = true;
1347ac7ddfbfSEd Maste     const uint32_t start_frame = 0;
1348ac7ddfbfSEd Maste     const uint32_t num_frames = 1;
1349ac7ddfbfSEd Maste     const uint32_t num_frames_with_source = 1;
1350435933ddSDimitry Andric     const bool     stop_format = true;
1351ac7ddfbfSEd Maste     process->GetStatus(strm);
1352435933ddSDimitry Andric     process->GetThreadStatus(strm, only_threads_with_stop_reason, start_frame,
1353435933ddSDimitry Andric                              num_frames, num_frames_with_source, stop_format);
1354ac7ddfbfSEd Maste     return result.Succeeded();
1355ac7ddfbfSEd Maste   }
1356ac7ddfbfSEd Maste };
1357ac7ddfbfSEd Maste 
1358ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1359ac7ddfbfSEd Maste // CommandObjectProcessHandle
1360ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1361435933ddSDimitry Andric 
1362435933ddSDimitry Andric static OptionDefinition g_process_handle_options[] = {
1363435933ddSDimitry Andric     // clang-format off
1364435933ddSDimitry Andric   { LLDB_OPT_SET_1, false, "stop",   's', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Whether or not the process should be stopped if the signal is received." },
1365435933ddSDimitry Andric   { LLDB_OPT_SET_1, false, "notify", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Whether or not the debugger should notify the user if the signal is received." },
1366435933ddSDimitry Andric   { LLDB_OPT_SET_1, false, "pass",   'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." }
1367435933ddSDimitry Andric     // clang-format on
1368435933ddSDimitry Andric };
1369435933ddSDimitry Andric 
1370ac7ddfbfSEd Maste #pragma mark CommandObjectProcessHandle
1371ac7ddfbfSEd Maste 
1372435933ddSDimitry Andric class CommandObjectProcessHandle : public CommandObjectParsed {
1373ac7ddfbfSEd Maste public:
1374435933ddSDimitry Andric   class CommandOptions : public Options {
1375ac7ddfbfSEd Maste   public:
1376435933ddSDimitry Andric     CommandOptions() : Options() { OptionParsingStarting(nullptr); }
1377ac7ddfbfSEd Maste 
13784bb0738eSEd Maste     ~CommandOptions() override = default;
1379ac7ddfbfSEd Maste 
1380435933ddSDimitry Andric     Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1381435933ddSDimitry Andric                          ExecutionContext *execution_context) override {
1382ac7ddfbfSEd Maste       Error error;
1383ac7ddfbfSEd Maste       const int short_option = m_getopt_table[option_idx].val;
1384ac7ddfbfSEd Maste 
1385435933ddSDimitry Andric       switch (short_option) {
1386ac7ddfbfSEd Maste       case 's':
1387ac7ddfbfSEd Maste         stop = option_arg;
1388ac7ddfbfSEd Maste         break;
1389ac7ddfbfSEd Maste       case 'n':
1390ac7ddfbfSEd Maste         notify = option_arg;
1391ac7ddfbfSEd Maste         break;
1392ac7ddfbfSEd Maste       case 'p':
1393ac7ddfbfSEd Maste         pass = option_arg;
1394ac7ddfbfSEd Maste         break;
1395ac7ddfbfSEd Maste       default:
1396435933ddSDimitry Andric         error.SetErrorStringWithFormat("invalid short option character '%c'",
1397435933ddSDimitry Andric                                        short_option);
1398ac7ddfbfSEd Maste         break;
1399ac7ddfbfSEd Maste       }
1400ac7ddfbfSEd Maste       return error;
1401ac7ddfbfSEd Maste     }
1402ac7ddfbfSEd Maste 
1403435933ddSDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
1404ac7ddfbfSEd Maste       stop.clear();
1405ac7ddfbfSEd Maste       notify.clear();
1406ac7ddfbfSEd Maste       pass.clear();
1407ac7ddfbfSEd Maste     }
1408ac7ddfbfSEd Maste 
1409435933ddSDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1410435933ddSDimitry Andric       return llvm::makeArrayRef(g_process_handle_options);
1411ac7ddfbfSEd Maste     }
1412ac7ddfbfSEd Maste 
1413ac7ddfbfSEd Maste     // Instance variables to hold the values for command options.
1414ac7ddfbfSEd Maste 
1415ac7ddfbfSEd Maste     std::string stop;
1416ac7ddfbfSEd Maste     std::string notify;
1417ac7ddfbfSEd Maste     std::string pass;
1418ac7ddfbfSEd Maste   };
1419ac7ddfbfSEd Maste 
14204bb0738eSEd Maste   CommandObjectProcessHandle(CommandInterpreter &interpreter)
1421435933ddSDimitry Andric       : CommandObjectParsed(interpreter, "process handle",
1422435933ddSDimitry Andric                             "Manage LLDB handling of OS signals for the "
1423435933ddSDimitry Andric                             "current target process.  Defaults to showing "
1424435933ddSDimitry Andric                             "current policy.",
14254bb0738eSEd Maste                             nullptr),
1426435933ddSDimitry Andric         m_options() {
1427b91a7dfcSDimitry Andric     SetHelpLong("\nIf no signals are specified, update them all.  If no update "
1428b91a7dfcSDimitry Andric                 "option is specified, list the current values.");
1429ac7ddfbfSEd Maste     CommandArgumentEntry arg;
1430ac7ddfbfSEd Maste     CommandArgumentData signal_arg;
1431ac7ddfbfSEd Maste 
1432ac7ddfbfSEd Maste     signal_arg.arg_type = eArgTypeUnixSignal;
1433ac7ddfbfSEd Maste     signal_arg.arg_repetition = eArgRepeatStar;
1434ac7ddfbfSEd Maste 
1435ac7ddfbfSEd Maste     arg.push_back(signal_arg);
1436ac7ddfbfSEd Maste 
1437ac7ddfbfSEd Maste     m_arguments.push_back(arg);
1438ac7ddfbfSEd Maste   }
1439ac7ddfbfSEd Maste 
14404bb0738eSEd Maste   ~CommandObjectProcessHandle() override = default;
1441ac7ddfbfSEd Maste 
1442435933ddSDimitry Andric   Options *GetOptions() override { return &m_options; }
1443ac7ddfbfSEd Maste 
1444435933ddSDimitry Andric   bool VerifyCommandOptionValue(const std::string &option, int &real_value) {
1445ac7ddfbfSEd Maste     bool okay = true;
1446ac7ddfbfSEd Maste     bool success = false;
1447435933ddSDimitry Andric     bool tmp_value = Args::StringToBoolean(option, false, &success);
1448ac7ddfbfSEd Maste 
1449ac7ddfbfSEd Maste     if (success && tmp_value)
1450ac7ddfbfSEd Maste       real_value = 1;
1451ac7ddfbfSEd Maste     else if (success && !tmp_value)
1452ac7ddfbfSEd Maste       real_value = 0;
1453435933ddSDimitry Andric     else {
1454ac7ddfbfSEd Maste       // If the value isn't 'true' or 'false', it had better be 0 or 1.
14551c3bbb01SEd Maste       real_value = StringConvert::ToUInt32(option.c_str(), 3);
1456ac7ddfbfSEd Maste       if (real_value != 0 && real_value != 1)
1457ac7ddfbfSEd Maste         okay = false;
1458ac7ddfbfSEd Maste     }
1459ac7ddfbfSEd Maste 
1460ac7ddfbfSEd Maste     return okay;
1461ac7ddfbfSEd Maste   }
1462ac7ddfbfSEd Maste 
1463435933ddSDimitry Andric   void PrintSignalHeader(Stream &str) {
1464ac7ddfbfSEd Maste     str.Printf("NAME         PASS   STOP   NOTIFY\n");
14651c3bbb01SEd Maste     str.Printf("===========  =====  =====  ======\n");
1466ac7ddfbfSEd Maste   }
1467ac7ddfbfSEd Maste 
1468435933ddSDimitry Andric   void PrintSignal(Stream &str, int32_t signo, const char *sig_name,
1469435933ddSDimitry Andric                    const UnixSignalsSP &signals_sp) {
1470ac7ddfbfSEd Maste     bool stop;
1471ac7ddfbfSEd Maste     bool suppress;
1472ac7ddfbfSEd Maste     bool notify;
1473ac7ddfbfSEd Maste 
14741c3bbb01SEd Maste     str.Printf("%-11s  ", sig_name);
1475435933ddSDimitry Andric     if (signals_sp->GetSignalInfo(signo, suppress, stop, notify)) {
1476ac7ddfbfSEd Maste       bool pass = !suppress;
1477435933ddSDimitry Andric       str.Printf("%s  %s  %s", (pass ? "true " : "false"),
1478435933ddSDimitry Andric                  (stop ? "true " : "false"), (notify ? "true " : "false"));
1479ac7ddfbfSEd Maste     }
1480ac7ddfbfSEd Maste     str.Printf("\n");
1481ac7ddfbfSEd Maste   }
1482ac7ddfbfSEd Maste 
1483435933ddSDimitry Andric   void PrintSignalInformation(Stream &str, Args &signal_args,
1484435933ddSDimitry Andric                               int num_valid_signals,
1485435933ddSDimitry Andric                               const UnixSignalsSP &signals_sp) {
1486ac7ddfbfSEd Maste     PrintSignalHeader(str);
1487ac7ddfbfSEd Maste 
1488435933ddSDimitry Andric     if (num_valid_signals > 0) {
1489ac7ddfbfSEd Maste       size_t num_args = signal_args.GetArgumentCount();
1490435933ddSDimitry Andric       for (size_t i = 0; i < num_args; ++i) {
1491435933ddSDimitry Andric         int32_t signo = signals_sp->GetSignalNumberFromName(
1492435933ddSDimitry Andric             signal_args.GetArgumentAtIndex(i));
1493ac7ddfbfSEd Maste         if (signo != LLDB_INVALID_SIGNAL_NUMBER)
1494435933ddSDimitry Andric           PrintSignal(str, signo, signal_args.GetArgumentAtIndex(i),
1495435933ddSDimitry Andric                       signals_sp);
1496ac7ddfbfSEd Maste       }
1497435933ddSDimitry Andric     } else // Print info for ALL signals
1498ac7ddfbfSEd Maste     {
1499b91a7dfcSDimitry Andric       int32_t signo = signals_sp->GetFirstSignalNumber();
1500435933ddSDimitry Andric       while (signo != LLDB_INVALID_SIGNAL_NUMBER) {
1501435933ddSDimitry Andric         PrintSignal(str, signo, signals_sp->GetSignalAsCString(signo),
1502435933ddSDimitry Andric                     signals_sp);
1503b91a7dfcSDimitry Andric         signo = signals_sp->GetNextSignalNumber(signo);
1504ac7ddfbfSEd Maste       }
1505ac7ddfbfSEd Maste     }
1506ac7ddfbfSEd Maste   }
1507ac7ddfbfSEd Maste 
1508ac7ddfbfSEd Maste protected:
1509435933ddSDimitry Andric   bool DoExecute(Args &signal_args, CommandReturnObject &result) override {
1510ac7ddfbfSEd Maste     TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
1511ac7ddfbfSEd Maste 
1512435933ddSDimitry Andric     if (!target_sp) {
1513ac7ddfbfSEd Maste       result.AppendError("No current target;"
1514435933ddSDimitry Andric                          " cannot handle signals until you have a valid target "
1515435933ddSDimitry Andric                          "and process.\n");
1516ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1517ac7ddfbfSEd Maste       return false;
1518ac7ddfbfSEd Maste     }
1519ac7ddfbfSEd Maste 
1520ac7ddfbfSEd Maste     ProcessSP process_sp = target_sp->GetProcessSP();
1521ac7ddfbfSEd Maste 
1522435933ddSDimitry Andric     if (!process_sp) {
1523435933ddSDimitry Andric       result.AppendError("No current process; cannot handle signals until you "
1524435933ddSDimitry Andric                          "have a valid process.\n");
1525ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1526ac7ddfbfSEd Maste       return false;
1527ac7ddfbfSEd Maste     }
1528ac7ddfbfSEd Maste 
1529ac7ddfbfSEd Maste     int stop_action = -1;   // -1 means leave the current setting alone
1530ac7ddfbfSEd Maste     int pass_action = -1;   // -1 means leave the current setting alone
1531ac7ddfbfSEd Maste     int notify_action = -1; // -1 means leave the current setting alone
1532ac7ddfbfSEd Maste 
1533435933ddSDimitry Andric     if (!m_options.stop.empty() &&
1534435933ddSDimitry Andric         !VerifyCommandOptionValue(m_options.stop, stop_action)) {
1535435933ddSDimitry Andric       result.AppendError("Invalid argument for command option --stop; must be "
1536435933ddSDimitry Andric                          "true or false.\n");
1537ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1538ac7ddfbfSEd Maste       return false;
1539ac7ddfbfSEd Maste     }
1540ac7ddfbfSEd Maste 
1541435933ddSDimitry Andric     if (!m_options.notify.empty() &&
1542435933ddSDimitry Andric         !VerifyCommandOptionValue(m_options.notify, notify_action)) {
1543435933ddSDimitry Andric       result.AppendError("Invalid argument for command option --notify; must "
1544435933ddSDimitry Andric                          "be true or false.\n");
1545ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1546ac7ddfbfSEd Maste       return false;
1547ac7ddfbfSEd Maste     }
1548ac7ddfbfSEd Maste 
1549435933ddSDimitry Andric     if (!m_options.pass.empty() &&
1550435933ddSDimitry Andric         !VerifyCommandOptionValue(m_options.pass, pass_action)) {
1551435933ddSDimitry Andric       result.AppendError("Invalid argument for command option --pass; must be "
1552435933ddSDimitry Andric                          "true or false.\n");
1553ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1554ac7ddfbfSEd Maste       return false;
1555ac7ddfbfSEd Maste     }
1556ac7ddfbfSEd Maste 
1557ac7ddfbfSEd Maste     size_t num_args = signal_args.GetArgumentCount();
1558b91a7dfcSDimitry Andric     UnixSignalsSP signals_sp = process_sp->GetUnixSignals();
1559ac7ddfbfSEd Maste     int num_signals_set = 0;
1560ac7ddfbfSEd Maste 
1561435933ddSDimitry Andric     if (num_args > 0) {
1562435933ddSDimitry Andric       for (const auto &arg : signal_args) {
1563435933ddSDimitry Andric         int32_t signo = signals_sp->GetSignalNumberFromName(arg.c_str());
1564435933ddSDimitry Andric         if (signo != LLDB_INVALID_SIGNAL_NUMBER) {
1565435933ddSDimitry Andric           // Casting the actions as bools here should be okay, because
1566435933ddSDimitry Andric           // VerifyCommandOptionValue guarantees
1567ac7ddfbfSEd Maste           // the value is either 0 or 1.
1568ac7ddfbfSEd Maste           if (stop_action != -1)
1569b91a7dfcSDimitry Andric             signals_sp->SetShouldStop(signo, stop_action);
1570435933ddSDimitry Andric           if (pass_action != -1) {
1571b91a7dfcSDimitry Andric             bool suppress = !pass_action;
1572b91a7dfcSDimitry Andric             signals_sp->SetShouldSuppress(signo, suppress);
1573ac7ddfbfSEd Maste           }
1574ac7ddfbfSEd Maste           if (notify_action != -1)
1575b91a7dfcSDimitry Andric             signals_sp->SetShouldNotify(signo, notify_action);
1576ac7ddfbfSEd Maste           ++num_signals_set;
1577435933ddSDimitry Andric         } else {
1578435933ddSDimitry Andric           result.AppendErrorWithFormat("Invalid signal name '%s'\n",
1579435933ddSDimitry Andric                                        arg.c_str());
1580ac7ddfbfSEd Maste         }
1581ac7ddfbfSEd Maste       }
1582435933ddSDimitry Andric     } else {
1583435933ddSDimitry Andric       // No signal specified, if any command options were specified, update ALL
1584435933ddSDimitry Andric       // signals.
1585435933ddSDimitry Andric       if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1)) {
1586435933ddSDimitry Andric         if (m_interpreter.Confirm(
1587435933ddSDimitry Andric                 "Do you really want to update all the signals?", false)) {
1588b91a7dfcSDimitry Andric           int32_t signo = signals_sp->GetFirstSignalNumber();
1589435933ddSDimitry Andric           while (signo != LLDB_INVALID_SIGNAL_NUMBER) {
1590ac7ddfbfSEd Maste             if (notify_action != -1)
1591b91a7dfcSDimitry Andric               signals_sp->SetShouldNotify(signo, notify_action);
1592ac7ddfbfSEd Maste             if (stop_action != -1)
1593b91a7dfcSDimitry Andric               signals_sp->SetShouldStop(signo, stop_action);
1594435933ddSDimitry Andric             if (pass_action != -1) {
1595b91a7dfcSDimitry Andric               bool suppress = !pass_action;
1596b91a7dfcSDimitry Andric               signals_sp->SetShouldSuppress(signo, suppress);
1597ac7ddfbfSEd Maste             }
1598b91a7dfcSDimitry Andric             signo = signals_sp->GetNextSignalNumber(signo);
1599ac7ddfbfSEd Maste           }
1600ac7ddfbfSEd Maste         }
1601ac7ddfbfSEd Maste       }
1602ac7ddfbfSEd Maste     }
1603ac7ddfbfSEd Maste 
1604435933ddSDimitry Andric     PrintSignalInformation(result.GetOutputStream(), signal_args,
1605435933ddSDimitry Andric                            num_signals_set, signals_sp);
1606ac7ddfbfSEd Maste 
1607ac7ddfbfSEd Maste     if (num_signals_set > 0)
1608ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1609ac7ddfbfSEd Maste     else
1610ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1611ac7ddfbfSEd Maste 
1612ac7ddfbfSEd Maste     return result.Succeeded();
1613ac7ddfbfSEd Maste   }
1614ac7ddfbfSEd Maste 
1615ac7ddfbfSEd Maste   CommandOptions m_options;
1616ac7ddfbfSEd Maste };
1617ac7ddfbfSEd Maste 
1618ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1619ac7ddfbfSEd Maste // CommandObjectMultiwordProcess
1620ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1621ac7ddfbfSEd Maste 
1622435933ddSDimitry Andric CommandObjectMultiwordProcess::CommandObjectMultiwordProcess(
1623435933ddSDimitry Andric     CommandInterpreter &interpreter)
1624435933ddSDimitry Andric     : CommandObjectMultiword(
1625435933ddSDimitry Andric           interpreter, "process",
1626435933ddSDimitry Andric           "Commands for interacting with processes on the current platform.",
1627435933ddSDimitry Andric           "process <subcommand> [<subcommand-options>]") {
1628435933ddSDimitry Andric   LoadSubCommand("attach",
1629435933ddSDimitry Andric                  CommandObjectSP(new CommandObjectProcessAttach(interpreter)));
1630435933ddSDimitry Andric   LoadSubCommand("launch",
1631435933ddSDimitry Andric                  CommandObjectSP(new CommandObjectProcessLaunch(interpreter)));
1632435933ddSDimitry Andric   LoadSubCommand("continue", CommandObjectSP(new CommandObjectProcessContinue(
1633435933ddSDimitry Andric                                  interpreter)));
1634435933ddSDimitry Andric   LoadSubCommand("connect",
1635435933ddSDimitry Andric                  CommandObjectSP(new CommandObjectProcessConnect(interpreter)));
1636435933ddSDimitry Andric   LoadSubCommand("detach",
1637435933ddSDimitry Andric                  CommandObjectSP(new CommandObjectProcessDetach(interpreter)));
1638435933ddSDimitry Andric   LoadSubCommand("load",
1639435933ddSDimitry Andric                  CommandObjectSP(new CommandObjectProcessLoad(interpreter)));
1640435933ddSDimitry Andric   LoadSubCommand("unload",
1641435933ddSDimitry Andric                  CommandObjectSP(new CommandObjectProcessUnload(interpreter)));
1642435933ddSDimitry Andric   LoadSubCommand("signal",
1643435933ddSDimitry Andric                  CommandObjectSP(new CommandObjectProcessSignal(interpreter)));
1644435933ddSDimitry Andric   LoadSubCommand("handle",
1645435933ddSDimitry Andric                  CommandObjectSP(new CommandObjectProcessHandle(interpreter)));
1646435933ddSDimitry Andric   LoadSubCommand("status",
1647435933ddSDimitry Andric                  CommandObjectSP(new CommandObjectProcessStatus(interpreter)));
1648435933ddSDimitry Andric   LoadSubCommand("interrupt", CommandObjectSP(new CommandObjectProcessInterrupt(
1649435933ddSDimitry Andric                                   interpreter)));
1650435933ddSDimitry Andric   LoadSubCommand("kill",
1651435933ddSDimitry Andric                  CommandObjectSP(new CommandObjectProcessKill(interpreter)));
1652435933ddSDimitry Andric   LoadSubCommand("plugin",
1653435933ddSDimitry Andric                  CommandObjectSP(new CommandObjectProcessPlugin(interpreter)));
1654435933ddSDimitry Andric   LoadSubCommand("save-core", CommandObjectSP(new CommandObjectProcessSaveCore(
1655435933ddSDimitry Andric                                   interpreter)));
1656ac7ddfbfSEd Maste }
1657ac7ddfbfSEd Maste 
16584bb0738eSEd Maste CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess() = default;
1659