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"
221c3bbb01SEd Maste #include "lldb/Host/StringConvert.h"
23ac7ddfbfSEd Maste #include "lldb/Interpreter/Args.h"
24ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandInterpreter.h"
25ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandReturnObject.h"
26435933ddSDimitry Andric #include "lldb/Interpreter/Options.h"
27ac7ddfbfSEd Maste #include "lldb/Target/Platform.h"
28ac7ddfbfSEd Maste #include "lldb/Target/Process.h"
29ac7ddfbfSEd Maste #include "lldb/Target/StopInfo.h"
30ac7ddfbfSEd Maste #include "lldb/Target/Target.h"
31ac7ddfbfSEd Maste #include "lldb/Target/Thread.h"
321c3bbb01SEd Maste #include "lldb/Target/UnixSignals.h"
33ac7ddfbfSEd Maste 
34ac7ddfbfSEd Maste using namespace lldb;
35ac7ddfbfSEd Maste using namespace lldb_private;
36ac7ddfbfSEd Maste 
37435933ddSDimitry Andric class CommandObjectProcessLaunchOrAttach : public CommandObjectParsed {
38ac7ddfbfSEd Maste public:
39ac7ddfbfSEd Maste   CommandObjectProcessLaunchOrAttach(CommandInterpreter &interpreter,
40435933ddSDimitry Andric                                      const char *name, const char *help,
41435933ddSDimitry Andric                                      const char *syntax, uint32_t flags,
42435933ddSDimitry Andric                                      const char *new_process_action)
43435933ddSDimitry Andric       : CommandObjectParsed(interpreter, name, help, syntax, flags),
44ac7ddfbfSEd Maste         m_new_process_action(new_process_action) {}
45ac7ddfbfSEd Maste 
464bb0738eSEd Maste   ~CommandObjectProcessLaunchOrAttach() override = default;
474bb0738eSEd Maste 
48ac7ddfbfSEd Maste protected:
49435933ddSDimitry Andric   bool StopProcessIfNecessary(Process *process, StateType &state,
50435933ddSDimitry Andric                               CommandReturnObject &result) {
51ac7ddfbfSEd Maste     state = eStateInvalid;
52435933ddSDimitry Andric     if (process) {
53ac7ddfbfSEd Maste       state = process->GetState();
54ac7ddfbfSEd Maste 
55435933ddSDimitry Andric       if (process->IsAlive() && state != eStateConnected) {
56ac7ddfbfSEd Maste         char message[1024];
57ac7ddfbfSEd Maste         if (process->GetState() == eStateAttaching)
58435933ddSDimitry Andric           ::snprintf(message, sizeof(message),
59435933ddSDimitry Andric                      "There is a pending attach, abort it and %s?",
60435933ddSDimitry Andric                      m_new_process_action.c_str());
61ac7ddfbfSEd Maste         else if (process->GetShouldDetach())
62435933ddSDimitry Andric           ::snprintf(message, sizeof(message),
63435933ddSDimitry Andric                      "There is a running process, detach from it and %s?",
64435933ddSDimitry Andric                      m_new_process_action.c_str());
65ac7ddfbfSEd Maste         else
66435933ddSDimitry Andric           ::snprintf(message, sizeof(message),
67435933ddSDimitry Andric                      "There is a running process, kill it and %s?",
68435933ddSDimitry Andric                      m_new_process_action.c_str());
69ac7ddfbfSEd Maste 
70435933ddSDimitry Andric         if (!m_interpreter.Confirm(message, true)) {
71ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusFailed);
72ac7ddfbfSEd Maste           return false;
73435933ddSDimitry Andric         } else {
74435933ddSDimitry Andric           if (process->GetShouldDetach()) {
75ac7ddfbfSEd Maste             bool keep_stopped = false;
76ac7ddfbfSEd Maste             Error detach_error(process->Detach(keep_stopped));
77435933ddSDimitry Andric             if (detach_error.Success()) {
78ac7ddfbfSEd Maste               result.SetStatus(eReturnStatusSuccessFinishResult);
794bb0738eSEd Maste               process = nullptr;
80435933ddSDimitry Andric             } else {
81435933ddSDimitry Andric               result.AppendErrorWithFormat(
82435933ddSDimitry Andric                   "Failed to detach from process: %s\n",
83435933ddSDimitry Andric                   detach_error.AsCString());
84ac7ddfbfSEd Maste               result.SetStatus(eReturnStatusFailed);
85ac7ddfbfSEd Maste             }
86435933ddSDimitry Andric           } else {
871c3bbb01SEd Maste             Error destroy_error(process->Destroy(false));
88435933ddSDimitry Andric             if (destroy_error.Success()) {
89ac7ddfbfSEd Maste               result.SetStatus(eReturnStatusSuccessFinishResult);
904bb0738eSEd Maste               process = nullptr;
91435933ddSDimitry Andric             } else {
92435933ddSDimitry Andric               result.AppendErrorWithFormat("Failed to kill process: %s\n",
93435933ddSDimitry Andric                                            destroy_error.AsCString());
94ac7ddfbfSEd Maste               result.SetStatus(eReturnStatusFailed);
95ac7ddfbfSEd Maste             }
96ac7ddfbfSEd Maste           }
97ac7ddfbfSEd Maste         }
98ac7ddfbfSEd Maste       }
99ac7ddfbfSEd Maste     }
100ac7ddfbfSEd Maste     return result.Succeeded();
101ac7ddfbfSEd Maste   }
1024bb0738eSEd Maste 
103ac7ddfbfSEd Maste   std::string m_new_process_action;
104ac7ddfbfSEd Maste };
1054bb0738eSEd Maste 
106ac7ddfbfSEd Maste //-------------------------------------------------------------------------
107ac7ddfbfSEd Maste // CommandObjectProcessLaunch
108ac7ddfbfSEd Maste //-------------------------------------------------------------------------
109ac7ddfbfSEd Maste #pragma mark CommandObjectProcessLaunch
110435933ddSDimitry Andric class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach {
111ac7ddfbfSEd Maste public:
112435933ddSDimitry Andric   CommandObjectProcessLaunch(CommandInterpreter &interpreter)
113435933ddSDimitry Andric       : CommandObjectProcessLaunchOrAttach(
114435933ddSDimitry Andric             interpreter, "process launch",
115435933ddSDimitry Andric             "Launch the executable in the debugger.", nullptr,
116435933ddSDimitry Andric             eCommandRequiresTarget, "restart"),
117435933ddSDimitry Andric         m_options() {
118ac7ddfbfSEd Maste     CommandArgumentEntry arg;
119ac7ddfbfSEd Maste     CommandArgumentData run_args_arg;
120ac7ddfbfSEd Maste 
121ac7ddfbfSEd Maste     // Define the first (and only) variant of this arg.
122ac7ddfbfSEd Maste     run_args_arg.arg_type = eArgTypeRunArgs;
123ac7ddfbfSEd Maste     run_args_arg.arg_repetition = eArgRepeatOptional;
124ac7ddfbfSEd Maste 
125435933ddSDimitry Andric     // There is only one variant this argument could be; put it into the
126435933ddSDimitry Andric     // argument entry.
127ac7ddfbfSEd Maste     arg.push_back(run_args_arg);
128ac7ddfbfSEd Maste 
129ac7ddfbfSEd Maste     // Push the data for the first argument into the m_arguments vector.
130ac7ddfbfSEd Maste     m_arguments.push_back(arg);
131ac7ddfbfSEd Maste   }
132ac7ddfbfSEd Maste 
1334bb0738eSEd Maste   ~CommandObjectProcessLaunch() override = default;
134ac7ddfbfSEd Maste 
135435933ddSDimitry Andric   int HandleArgumentCompletion(Args &input, int &cursor_index,
136ac7ddfbfSEd Maste                                int &cursor_char_position,
137ac7ddfbfSEd Maste                                OptionElementVector &opt_element_vector,
138435933ddSDimitry Andric                                int match_start_point, int max_return_elements,
139ac7ddfbfSEd Maste                                bool &word_complete,
140435933ddSDimitry Andric                                StringList &matches) override {
141ac7ddfbfSEd Maste     std::string completion_str(input.GetArgumentAtIndex(cursor_index));
142ac7ddfbfSEd Maste     completion_str.erase(cursor_char_position);
143ac7ddfbfSEd Maste 
144435933ddSDimitry Andric     CommandCompletions::InvokeCommonCompletionCallbacks(
145435933ddSDimitry Andric         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
146435933ddSDimitry Andric         completion_str.c_str(), match_start_point, max_return_elements, nullptr,
147435933ddSDimitry Andric         word_complete, matches);
148ac7ddfbfSEd Maste     return matches.GetSize();
149ac7ddfbfSEd Maste   }
150ac7ddfbfSEd Maste 
151435933ddSDimitry Andric   Options *GetOptions() override { return &m_options; }
152ac7ddfbfSEd Maste 
153435933ddSDimitry Andric   const char *GetRepeatCommand(Args &current_command_args,
154435933ddSDimitry Andric                                uint32_t index) override {
155ac7ddfbfSEd Maste     // No repeat for "process launch"...
156ac7ddfbfSEd Maste     return "";
157ac7ddfbfSEd Maste   }
158ac7ddfbfSEd Maste 
159ac7ddfbfSEd Maste protected:
160435933ddSDimitry Andric   bool DoExecute(Args &launch_args, CommandReturnObject &result) override {
161ac7ddfbfSEd Maste     Debugger &debugger = m_interpreter.GetDebugger();
162ac7ddfbfSEd Maste     Target *target = debugger.GetSelectedTarget().get();
1634bb0738eSEd Maste     // If our listener is nullptr, users aren't allows to launch
16412b93ac6SEd Maste     ModuleSP exe_module_sp = target->GetExecutableModule();
165ac7ddfbfSEd Maste 
166435933ddSDimitry Andric     if (exe_module_sp == nullptr) {
167435933ddSDimitry Andric       result.AppendError("no file in target, create a debug target using the "
168435933ddSDimitry Andric                          "'target create' command");
169ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
170ac7ddfbfSEd Maste       return false;
171ac7ddfbfSEd Maste     }
172ac7ddfbfSEd Maste 
173ac7ddfbfSEd Maste     StateType state = eStateInvalid;
174ac7ddfbfSEd Maste 
17512b93ac6SEd Maste     if (!StopProcessIfNecessary(m_exe_ctx.GetProcessPtr(), state, result))
176ac7ddfbfSEd Maste       return false;
177ac7ddfbfSEd Maste 
178435933ddSDimitry Andric     llvm::StringRef target_settings_argv0 = target->GetArg0();
179ac7ddfbfSEd Maste 
180435933ddSDimitry Andric     // Determine whether we will disable ASLR or leave it in the default state
181435933ddSDimitry Andric     // (i.e. enabled if the platform supports it).
182435933ddSDimitry Andric     // First check if the process launch options explicitly turn on/off
183435933ddSDimitry Andric     // disabling ASLR.  If so, use that setting;
1840127ef0fSEd Maste     // otherwise, use the 'settings target.disable-aslr' setting.
1850127ef0fSEd Maste     bool disable_aslr = false;
186435933ddSDimitry Andric     if (m_options.disable_aslr != eLazyBoolCalculate) {
187435933ddSDimitry Andric       // The user specified an explicit setting on the process launch line.  Use
188435933ddSDimitry Andric       // it.
1890127ef0fSEd Maste       disable_aslr = (m_options.disable_aslr == eLazyBoolYes);
190435933ddSDimitry Andric     } else {
191435933ddSDimitry Andric       // The user did not explicitly specify whether to disable ASLR.  Fall back
192435933ddSDimitry Andric       // to the target.disable-aslr setting.
1930127ef0fSEd Maste       disable_aslr = target->GetDisableASLR();
1940127ef0fSEd Maste     }
1950127ef0fSEd Maste 
1960127ef0fSEd Maste     if (disable_aslr)
19712b93ac6SEd Maste       m_options.launch_info.GetFlags().Set(eLaunchFlagDisableASLR);
1980127ef0fSEd Maste     else
1990127ef0fSEd Maste       m_options.launch_info.GetFlags().Clear(eLaunchFlagDisableASLR);
2000127ef0fSEd Maste 
2010127ef0fSEd Maste     if (target->GetDetachOnError())
2020127ef0fSEd Maste       m_options.launch_info.GetFlags().Set(eLaunchFlagDetachOnError);
20312b93ac6SEd Maste 
20412b93ac6SEd Maste     if (target->GetDisableSTDIO())
20512b93ac6SEd Maste       m_options.launch_info.GetFlags().Set(eLaunchFlagDisableSTDIO);
20612b93ac6SEd Maste 
20712b93ac6SEd Maste     Args environment;
20812b93ac6SEd Maste     target->GetEnvironmentAsArgs(environment);
20912b93ac6SEd Maste     if (environment.GetArgumentCount() > 0)
210435933ddSDimitry Andric       m_options.launch_info.GetEnvironmentEntries().AppendArguments(
211435933ddSDimitry Andric           environment);
212ac7ddfbfSEd Maste 
213435933ddSDimitry Andric     if (!target_settings_argv0.empty()) {
214435933ddSDimitry Andric       m_options.launch_info.GetArguments().AppendArgument(
215435933ddSDimitry Andric           target_settings_argv0);
216435933ddSDimitry Andric       m_options.launch_info.SetExecutableFile(
217435933ddSDimitry Andric           exe_module_sp->GetPlatformFileSpec(), false);
218435933ddSDimitry Andric     } else {
219435933ddSDimitry Andric       m_options.launch_info.SetExecutableFile(
220435933ddSDimitry Andric           exe_module_sp->GetPlatformFileSpec(), true);
221ac7ddfbfSEd Maste     }
222ac7ddfbfSEd Maste 
223435933ddSDimitry Andric     if (launch_args.GetArgumentCount() == 0) {
224435933ddSDimitry Andric       m_options.launch_info.GetArguments().AppendArguments(
225435933ddSDimitry Andric           target->GetProcessLaunchInfo().GetArguments());
226435933ddSDimitry Andric     } else {
227ac7ddfbfSEd Maste       m_options.launch_info.GetArguments().AppendArguments(launch_args);
228ac7ddfbfSEd Maste       // Save the arguments for subsequent runs in the current target.
229ac7ddfbfSEd Maste       target->SetRunArguments(launch_args);
230ac7ddfbfSEd Maste     }
231ac7ddfbfSEd Maste 
2327aa51b79SEd Maste     StreamString stream;
2337aa51b79SEd Maste     Error error = target->Launch(m_options.launch_info, &stream);
234ac7ddfbfSEd Maste 
235435933ddSDimitry Andric     if (error.Success()) {
23612b93ac6SEd Maste       ProcessSP process_sp(target->GetProcessSP());
237435933ddSDimitry Andric       if (process_sp) {
238435933ddSDimitry Andric         // There is a race condition where this thread will return up the call
239435933ddSDimitry Andric         // stack to the main command
240435933ddSDimitry Andric         // handler and show an (lldb) prompt before HandlePrivateEvent (from
241435933ddSDimitry Andric         // PrivateStateThread) has
2421c3bbb01SEd Maste         // a chance to call PushProcessIOHandler().
2431c3bbb01SEd Maste         process_sp->SyncIOHandler(0, 2000);
2441c3bbb01SEd Maste 
245435933ddSDimitry Andric         llvm::StringRef data = stream.GetString();
246435933ddSDimitry Andric         if (!data.empty())
247435933ddSDimitry Andric           result.AppendMessage(data);
248435933ddSDimitry Andric         const char *archname =
249435933ddSDimitry Andric             exe_module_sp->GetArchitecture().GetArchitectureName();
250435933ddSDimitry Andric         result.AppendMessageWithFormat(
251435933ddSDimitry Andric             "Process %" PRIu64 " launched: '%s' (%s)\n", process_sp->GetID(),
252435933ddSDimitry Andric             exe_module_sp->GetFileSpec().GetPath().c_str(), archname);
253ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusSuccessFinishResult);
25412b93ac6SEd Maste         result.SetDidChangeProcessState(true);
255435933ddSDimitry Andric       } else {
256435933ddSDimitry Andric         result.AppendError(
257435933ddSDimitry Andric             "no error returned from Target::Launch, and target has no process");
258ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
259ac7ddfbfSEd Maste       }
260435933ddSDimitry Andric     } else {
26112b93ac6SEd Maste       result.AppendError(error.AsCString());
262ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
263ac7ddfbfSEd Maste     }
264ac7ddfbfSEd Maste     return result.Succeeded();
265ac7ddfbfSEd Maste   }
266ac7ddfbfSEd Maste 
267ac7ddfbfSEd Maste protected:
268ac7ddfbfSEd Maste   ProcessLaunchCommandOptions m_options;
269ac7ddfbfSEd Maste };
270ac7ddfbfSEd Maste 
271ac7ddfbfSEd Maste //#define SET1 LLDB_OPT_SET_1
272ac7ddfbfSEd Maste //#define SET2 LLDB_OPT_SET_2
273ac7ddfbfSEd Maste //#define SET3 LLDB_OPT_SET_3
274ac7ddfbfSEd Maste //
275ac7ddfbfSEd Maste // OptionDefinition
276ac7ddfbfSEd Maste // CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
277ac7ddfbfSEd Maste //{
278435933ddSDimitry Andric //  // clang-format off
279435933ddSDimitry Andric //  {SET1 | SET2 | SET3, false, "stop-at-entry", 's', OptionParser::eNoArgument,
280435933ddSDimitry Andric //  nullptr, 0, eArgTypeNone,          "Stop at the entry point of the program
281435933ddSDimitry Andric //  when launching a process."},
282435933ddSDimitry Andric //  {SET1,               false, "stdin",         'i',
283435933ddSDimitry Andric //  OptionParser::eRequiredArgument, nullptr, 0, eArgTypeDirectoryName,
284435933ddSDimitry Andric //  "Redirect stdin for the process to <path>."},
285435933ddSDimitry Andric //  {SET1,               false, "stdout",        'o',
286435933ddSDimitry Andric //  OptionParser::eRequiredArgument, nullptr, 0, eArgTypeDirectoryName,
287435933ddSDimitry Andric //  "Redirect stdout for the process to <path>."},
288435933ddSDimitry Andric //  {SET1,               false, "stderr",        'e',
289435933ddSDimitry Andric //  OptionParser::eRequiredArgument, nullptr, 0, eArgTypeDirectoryName,
290435933ddSDimitry Andric //  "Redirect stderr for the process to <path>."},
291435933ddSDimitry Andric //  {SET1 | SET2 | SET3, false, "plugin",        'p',
292435933ddSDimitry Andric //  OptionParser::eRequiredArgument, nullptr, 0, eArgTypePlugin,        "Name of
293435933ddSDimitry Andric //  the process plugin you want to use."},
294435933ddSDimitry Andric //  {       SET2,        false, "tty",           't',
295435933ddSDimitry Andric //  OptionParser::eOptionalArgument, nullptr, 0, eArgTypeDirectoryName, "Start
296435933ddSDimitry Andric //  the process in a terminal. If <path> is specified, look for a terminal whose
297435933ddSDimitry Andric //  name contains <path>, else start the process in a new terminal."},
298435933ddSDimitry Andric //  {              SET3, false, "no-stdio",      'n', OptionParser::eNoArgument,
299435933ddSDimitry Andric //  nullptr, 0, eArgTypeNone,          "Do not set up for terminal I/O to go to
300435933ddSDimitry Andric //  running process."},
301435933ddSDimitry Andric //  {SET1 | SET2 | SET3, false, "working-dir",   'w',
302435933ddSDimitry Andric //  OptionParser::eRequiredArgument, nullptr, 0, eArgTypeDirectoryName, "Set the
303435933ddSDimitry Andric //  current working directory to <path> when running the inferior."},
3044bb0738eSEd Maste //  {0, false, nullptr, 0, 0, nullptr, 0, eArgTypeNone, nullptr}
305435933ddSDimitry Andric //  // clang-format on
306ac7ddfbfSEd Maste //};
307ac7ddfbfSEd Maste //
308ac7ddfbfSEd Maste //#undef SET1
309ac7ddfbfSEd Maste //#undef SET2
310ac7ddfbfSEd Maste //#undef SET3
311ac7ddfbfSEd Maste 
312ac7ddfbfSEd Maste //-------------------------------------------------------------------------
313ac7ddfbfSEd Maste // CommandObjectProcessAttach
314ac7ddfbfSEd Maste //-------------------------------------------------------------------------
315435933ddSDimitry Andric 
316435933ddSDimitry Andric static OptionDefinition g_process_attach_options[] = {
317435933ddSDimitry Andric     // clang-format off
318435933ddSDimitry Andric   { LLDB_OPT_SET_ALL, false, "continue",         'c', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,         "Immediately continue the process once attached." },
319435933ddSDimitry Andric   { LLDB_OPT_SET_ALL, false, "plugin",           'P', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePlugin,       "Name of the process plugin you want to use." },
320435933ddSDimitry Andric   { LLDB_OPT_SET_1,   false, "pid",              'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePid,          "The process ID of an existing process to attach to." },
321435933ddSDimitry Andric   { LLDB_OPT_SET_2,   false, "name",             'n', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeProcessName,  "The name of the process to attach to." },
322435933ddSDimitry Andric   { LLDB_OPT_SET_2,   false, "include-existing", 'i', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,         "Include existing processes when doing attach -w." },
323435933ddSDimitry Andric   { LLDB_OPT_SET_2,   false, "waitfor",          'w', OptionParser::eNoArgument,       nullptr, nullptr, 0, eArgTypeNone,         "Wait for the process with <process-name> to launch." },
324435933ddSDimitry Andric     // clang-format on
325435933ddSDimitry Andric };
326435933ddSDimitry Andric 
327ac7ddfbfSEd Maste #pragma mark CommandObjectProcessAttach
328435933ddSDimitry Andric class CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach {
329ac7ddfbfSEd Maste public:
330435933ddSDimitry Andric   class CommandOptions : public Options {
331ac7ddfbfSEd Maste   public:
332435933ddSDimitry Andric     CommandOptions() : Options() {
333435933ddSDimitry Andric       // Keep default values of all options in one place: OptionParsingStarting
334435933ddSDimitry Andric       // ()
335435933ddSDimitry Andric       OptionParsingStarting(nullptr);
336ac7ddfbfSEd Maste     }
337ac7ddfbfSEd Maste 
3384bb0738eSEd Maste     ~CommandOptions() override = default;
339ac7ddfbfSEd Maste 
340435933ddSDimitry Andric     Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
341435933ddSDimitry Andric                          ExecutionContext *execution_context) override {
342ac7ddfbfSEd Maste       Error error;
343ac7ddfbfSEd Maste       const int short_option = m_getopt_table[option_idx].val;
344435933ddSDimitry Andric       switch (short_option) {
345ac7ddfbfSEd Maste       case 'c':
346ac7ddfbfSEd Maste         attach_info.SetContinueOnceAttached(true);
347ac7ddfbfSEd Maste         break;
348ac7ddfbfSEd Maste 
349435933ddSDimitry Andric       case 'p': {
350435933ddSDimitry Andric         lldb::pid_t pid;
351435933ddSDimitry Andric         if (option_arg.getAsInteger(0, pid)) {
352435933ddSDimitry Andric           error.SetErrorStringWithFormat("invalid process ID '%s'",
353435933ddSDimitry Andric                                          option_arg.str().c_str());
354435933ddSDimitry Andric         } else {
355ac7ddfbfSEd Maste           attach_info.SetProcessID(pid);
356ac7ddfbfSEd Maste         }
357435933ddSDimitry Andric       } break;
358ac7ddfbfSEd Maste 
359ac7ddfbfSEd Maste       case 'P':
360ac7ddfbfSEd Maste         attach_info.SetProcessPluginName(option_arg);
361ac7ddfbfSEd Maste         break;
362ac7ddfbfSEd Maste 
363ac7ddfbfSEd Maste       case 'n':
364ac7ddfbfSEd Maste         attach_info.GetExecutableFile().SetFile(option_arg, false);
365ac7ddfbfSEd Maste         break;
366ac7ddfbfSEd Maste 
367ac7ddfbfSEd Maste       case 'w':
368ac7ddfbfSEd Maste         attach_info.SetWaitForLaunch(true);
369ac7ddfbfSEd Maste         break;
370ac7ddfbfSEd Maste 
371ac7ddfbfSEd Maste       case 'i':
372ac7ddfbfSEd Maste         attach_info.SetIgnoreExisting(false);
373ac7ddfbfSEd Maste         break;
374ac7ddfbfSEd Maste 
375ac7ddfbfSEd Maste       default:
376435933ddSDimitry Andric         error.SetErrorStringWithFormat("invalid short option character '%c'",
377435933ddSDimitry Andric                                        short_option);
378ac7ddfbfSEd Maste         break;
379ac7ddfbfSEd Maste       }
380ac7ddfbfSEd Maste       return error;
381ac7ddfbfSEd Maste     }
382ac7ddfbfSEd Maste 
383435933ddSDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
384ac7ddfbfSEd Maste       attach_info.Clear();
385ac7ddfbfSEd Maste     }
386ac7ddfbfSEd Maste 
387435933ddSDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
388435933ddSDimitry Andric       return llvm::makeArrayRef(g_process_attach_options);
389ac7ddfbfSEd Maste     }
390ac7ddfbfSEd Maste 
391435933ddSDimitry Andric     bool HandleOptionArgumentCompletion(
392435933ddSDimitry Andric         Args &input, int cursor_index, int char_pos,
393435933ddSDimitry Andric         OptionElementVector &opt_element_vector, int opt_element_index,
394435933ddSDimitry Andric         int match_start_point, int max_return_elements,
395435933ddSDimitry Andric         CommandInterpreter &interpreter, bool &word_complete,
396435933ddSDimitry Andric         StringList &matches) override {
397ac7ddfbfSEd Maste       int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
398ac7ddfbfSEd Maste       int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
399ac7ddfbfSEd Maste 
400ac7ddfbfSEd Maste       // We are only completing the name option for now...
401ac7ddfbfSEd Maste 
402435933ddSDimitry Andric       if (GetDefinitions()[opt_defs_index].short_option == 'n') {
403ac7ddfbfSEd Maste         // Are we in the name?
404ac7ddfbfSEd Maste 
405435933ddSDimitry Andric         // Look to see if there is a -P argument provided, and if so use that
406435933ddSDimitry Andric         // plugin, otherwise
407ac7ddfbfSEd Maste         // use the default plugin.
408ac7ddfbfSEd Maste 
4094bb0738eSEd Maste         const char *partial_name = nullptr;
410ac7ddfbfSEd Maste         partial_name = input.GetArgumentAtIndex(opt_arg_pos);
411ac7ddfbfSEd Maste 
412435933ddSDimitry Andric         PlatformSP platform_sp(interpreter.GetPlatform(true));
413435933ddSDimitry Andric         if (platform_sp) {
414ac7ddfbfSEd Maste           ProcessInstanceInfoList process_infos;
415ac7ddfbfSEd Maste           ProcessInstanceInfoMatch match_info;
416435933ddSDimitry Andric           if (partial_name) {
417435933ddSDimitry Andric             match_info.GetProcessInfo().GetExecutableFile().SetFile(
418435933ddSDimitry Andric                 partial_name, false);
419ac7ddfbfSEd Maste             match_info.SetNameMatchType(eNameMatchStartsWith);
420ac7ddfbfSEd Maste           }
421ac7ddfbfSEd Maste           platform_sp->FindProcesses(match_info, process_infos);
422ac7ddfbfSEd Maste           const size_t num_matches = process_infos.GetSize();
423435933ddSDimitry Andric           if (num_matches > 0) {
424435933ddSDimitry Andric             for (size_t i = 0; i < num_matches; ++i) {
425435933ddSDimitry Andric               matches.AppendString(
426435933ddSDimitry Andric                   process_infos.GetProcessNameAtIndex(i),
427ac7ddfbfSEd Maste                   process_infos.GetProcessNameLengthAtIndex(i));
428ac7ddfbfSEd Maste             }
429ac7ddfbfSEd Maste           }
430ac7ddfbfSEd Maste         }
431ac7ddfbfSEd Maste       }
432ac7ddfbfSEd Maste 
433ac7ddfbfSEd Maste       return false;
434ac7ddfbfSEd Maste     }
435ac7ddfbfSEd Maste 
436ac7ddfbfSEd Maste     // Instance variables to hold the values for command options.
437ac7ddfbfSEd Maste 
438ac7ddfbfSEd Maste     ProcessAttachInfo attach_info;
439ac7ddfbfSEd Maste   };
440ac7ddfbfSEd Maste 
441435933ddSDimitry Andric   CommandObjectProcessAttach(CommandInterpreter &interpreter)
442435933ddSDimitry Andric       : CommandObjectProcessLaunchOrAttach(
443435933ddSDimitry Andric             interpreter, "process attach", "Attach to a process.",
444435933ddSDimitry Andric             "process attach <cmd-options>", 0, "attach"),
445435933ddSDimitry Andric         m_options() {}
446ac7ddfbfSEd Maste 
4474bb0738eSEd Maste   ~CommandObjectProcessAttach() override = default;
448ac7ddfbfSEd Maste 
449435933ddSDimitry Andric   Options *GetOptions() override { return &m_options; }
450ac7ddfbfSEd Maste 
451ac7ddfbfSEd Maste protected:
452435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
453435933ddSDimitry Andric     PlatformSP platform_sp(
454435933ddSDimitry Andric         m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform());
4551c3bbb01SEd Maste 
456ac7ddfbfSEd Maste     Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
457435933ddSDimitry Andric     // N.B. The attach should be synchronous.  It doesn't help much to get the
458435933ddSDimitry Andric     // prompt back between initiating the attach
459435933ddSDimitry Andric     // and the target actually stopping.  So even if the interpreter is set to
460435933ddSDimitry Andric     // be asynchronous, we wait for the stop
461ac7ddfbfSEd Maste     // ourselves here.
462ac7ddfbfSEd Maste 
463ac7ddfbfSEd Maste     StateType state = eStateInvalid;
464ac7ddfbfSEd Maste     Process *process = m_exe_ctx.GetProcessPtr();
465ac7ddfbfSEd Maste 
466ac7ddfbfSEd Maste     if (!StopProcessIfNecessary(process, state, result))
467ac7ddfbfSEd Maste       return false;
468ac7ddfbfSEd Maste 
469435933ddSDimitry Andric     if (target == nullptr) {
470ac7ddfbfSEd Maste       // If there isn't a current target create one.
471ac7ddfbfSEd Maste       TargetSP new_target_sp;
472ac7ddfbfSEd Maste       Error error;
473ac7ddfbfSEd Maste 
474435933ddSDimitry Andric       error = m_interpreter.GetDebugger().GetTargetList().CreateTarget(
475435933ddSDimitry Andric           m_interpreter.GetDebugger(), "", "", false,
4764bb0738eSEd Maste           nullptr, // No platform options
477ac7ddfbfSEd Maste           new_target_sp);
478ac7ddfbfSEd Maste       target = new_target_sp.get();
479435933ddSDimitry Andric       if (target == nullptr || error.Fail()) {
480ac7ddfbfSEd Maste         result.AppendError(error.AsCString("Error creating target"));
481ac7ddfbfSEd Maste         return false;
482ac7ddfbfSEd Maste       }
483ac7ddfbfSEd Maste       m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target);
484ac7ddfbfSEd Maste     }
485ac7ddfbfSEd Maste 
486435933ddSDimitry Andric     // Record the old executable module, we want to issue a warning if the
487435933ddSDimitry Andric     // process of attaching changed the
488435933ddSDimitry Andric     // current executable (like somebody said "file foo" then attached to a PID
489435933ddSDimitry Andric     // whose executable was bar.)
490ac7ddfbfSEd Maste 
491ac7ddfbfSEd Maste     ModuleSP old_exec_module_sp = target->GetExecutableModule();
492ac7ddfbfSEd Maste     ArchSpec old_arch_spec = target->GetArchitecture();
493ac7ddfbfSEd Maste 
494435933ddSDimitry Andric     if (command.GetArgumentCount()) {
495435933ddSDimitry Andric       result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: %s\n",
496435933ddSDimitry Andric                                    m_cmd_name.c_str(), m_cmd_syntax.c_str());
497ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
4981c3bbb01SEd Maste       return false;
499ac7ddfbfSEd Maste     }
500ac7ddfbfSEd Maste 
5011c3bbb01SEd Maste     m_interpreter.UpdateExecutionContext(nullptr);
5027aa51b79SEd Maste     StreamString stream;
5031c3bbb01SEd Maste     const auto error = target->Attach(m_options.attach_info, &stream);
504435933ddSDimitry Andric     if (error.Success()) {
5051c3bbb01SEd Maste       ProcessSP process_sp(target->GetProcessSP());
506435933ddSDimitry Andric       if (process_sp) {
507435933ddSDimitry Andric         result.AppendMessage(stream.GetString());
508ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusSuccessFinishNoResult);
5091c3bbb01SEd Maste         result.SetDidChangeProcessState(true);
510444ed5c5SDimitry Andric         result.SetAbnormalStopWasExpected(true);
511435933ddSDimitry Andric       } else {
512435933ddSDimitry Andric         result.AppendError(
513435933ddSDimitry Andric             "no error returned from Target::Attach, and target has no process");
514ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
51512b93ac6SEd Maste       }
516435933ddSDimitry Andric     } else {
51712b93ac6SEd Maste       result.AppendErrorWithFormat("attach failed: %s\n", error.AsCString());
51812b93ac6SEd Maste       result.SetStatus(eReturnStatusFailed);
519ac7ddfbfSEd Maste     }
520ac7ddfbfSEd Maste 
5211c3bbb01SEd Maste     if (!result.Succeeded())
5221c3bbb01SEd Maste       return false;
5231c3bbb01SEd Maste 
524435933ddSDimitry Andric     // Okay, we're done.  Last step is to warn if the executable module has
525435933ddSDimitry Andric     // changed:
526ac7ddfbfSEd Maste     char new_path[PATH_MAX];
527ac7ddfbfSEd Maste     ModuleSP new_exec_module_sp(target->GetExecutableModule());
528435933ddSDimitry Andric     if (!old_exec_module_sp) {
529ac7ddfbfSEd Maste       // We might not have a module if we attached to a raw pid...
530435933ddSDimitry Andric       if (new_exec_module_sp) {
531ac7ddfbfSEd Maste         new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX);
532435933ddSDimitry Andric         result.AppendMessageWithFormat("Executable module set to \"%s\".\n",
533435933ddSDimitry Andric                                        new_path);
534ac7ddfbfSEd Maste       }
535435933ddSDimitry Andric     } else if (old_exec_module_sp->GetFileSpec() !=
536435933ddSDimitry Andric                new_exec_module_sp->GetFileSpec()) {
537ac7ddfbfSEd Maste       char old_path[PATH_MAX];
538ac7ddfbfSEd Maste 
539ac7ddfbfSEd Maste       old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX);
540ac7ddfbfSEd Maste       new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX);
541ac7ddfbfSEd Maste 
542435933ddSDimitry Andric       result.AppendWarningWithFormat(
543435933ddSDimitry Andric           "Executable module changed from \"%s\" to \"%s\".\n", old_path,
544435933ddSDimitry Andric           new_path);
545ac7ddfbfSEd Maste     }
546ac7ddfbfSEd Maste 
547435933ddSDimitry Andric     if (!old_arch_spec.IsValid()) {
548435933ddSDimitry Andric       result.AppendMessageWithFormat(
549435933ddSDimitry Andric           "Architecture set to: %s.\n",
550435933ddSDimitry Andric           target->GetArchitecture().GetTriple().getTriple().c_str());
551435933ddSDimitry Andric     } else if (!old_arch_spec.IsExactMatch(target->GetArchitecture())) {
552435933ddSDimitry Andric       result.AppendWarningWithFormat(
553435933ddSDimitry Andric           "Architecture changed from %s to %s.\n",
554ac7ddfbfSEd Maste           old_arch_spec.GetTriple().getTriple().c_str(),
555ac7ddfbfSEd Maste           target->GetArchitecture().GetTriple().getTriple().c_str());
556ac7ddfbfSEd Maste     }
557ac7ddfbfSEd Maste 
558435933ddSDimitry Andric     // This supports the use-case scenario of immediately continuing the process
559435933ddSDimitry Andric     // once attached.
560ac7ddfbfSEd Maste     if (m_options.attach_info.GetContinueOnceAttached())
561ac7ddfbfSEd Maste       m_interpreter.HandleCommand("process continue", eLazyBoolNo, result);
5621c3bbb01SEd Maste 
563ac7ddfbfSEd Maste     return result.Succeeded();
564ac7ddfbfSEd Maste   }
565ac7ddfbfSEd Maste 
566ac7ddfbfSEd Maste   CommandOptions m_options;
567ac7ddfbfSEd Maste };
568ac7ddfbfSEd Maste 
569ac7ddfbfSEd Maste //-------------------------------------------------------------------------
570ac7ddfbfSEd Maste // CommandObjectProcessContinue
571ac7ddfbfSEd Maste //-------------------------------------------------------------------------
572435933ddSDimitry Andric 
573435933ddSDimitry Andric static OptionDefinition g_process_continue_options[] = {
574435933ddSDimitry Andric     // clang-format off
575435933ddSDimitry 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." }
576435933ddSDimitry Andric     // clang-format on
577435933ddSDimitry Andric };
578435933ddSDimitry Andric 
579ac7ddfbfSEd Maste #pragma mark CommandObjectProcessContinue
580ac7ddfbfSEd Maste 
581435933ddSDimitry Andric class CommandObjectProcessContinue : public CommandObjectParsed {
582ac7ddfbfSEd Maste public:
583435933ddSDimitry Andric   CommandObjectProcessContinue(CommandInterpreter &interpreter)
584435933ddSDimitry Andric       : CommandObjectParsed(
585435933ddSDimitry Andric             interpreter, "process continue",
586ac7ddfbfSEd Maste             "Continue execution of all threads in the current process.",
587ac7ddfbfSEd Maste             "process continue",
588435933ddSDimitry Andric             eCommandRequiresProcess | eCommandTryTargetAPILock |
589435933ddSDimitry Andric                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused),
590435933ddSDimitry Andric         m_options() {}
591ac7ddfbfSEd Maste 
5924bb0738eSEd Maste   ~CommandObjectProcessContinue() override = default;
593ac7ddfbfSEd Maste 
594ac7ddfbfSEd Maste protected:
595435933ddSDimitry Andric   class CommandOptions : public Options {
596ac7ddfbfSEd Maste   public:
597435933ddSDimitry Andric     CommandOptions() : Options() {
598435933ddSDimitry Andric       // Keep default values of all options in one place: OptionParsingStarting
599435933ddSDimitry Andric       // ()
600435933ddSDimitry Andric       OptionParsingStarting(nullptr);
601ac7ddfbfSEd Maste     }
602ac7ddfbfSEd Maste 
6034bb0738eSEd Maste     ~CommandOptions() override = default;
604ac7ddfbfSEd Maste 
605435933ddSDimitry Andric     Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
606435933ddSDimitry Andric                          ExecutionContext *execution_context) override {
607ac7ddfbfSEd Maste       Error error;
608ac7ddfbfSEd Maste       const int short_option = m_getopt_table[option_idx].val;
609435933ddSDimitry Andric       switch (short_option) {
610ac7ddfbfSEd Maste       case 'i':
611435933ddSDimitry Andric         if (option_arg.getAsInteger(0, m_ignore))
612435933ddSDimitry Andric           error.SetErrorStringWithFormat(
613435933ddSDimitry Andric               "invalid value for ignore option: \"%s\", should be a number.",
614435933ddSDimitry Andric               option_arg.str().c_str());
615ac7ddfbfSEd Maste         break;
616ac7ddfbfSEd Maste 
617ac7ddfbfSEd Maste       default:
618435933ddSDimitry Andric         error.SetErrorStringWithFormat("invalid short option character '%c'",
619435933ddSDimitry Andric                                        short_option);
620ac7ddfbfSEd Maste         break;
621ac7ddfbfSEd Maste       }
622ac7ddfbfSEd Maste       return error;
623ac7ddfbfSEd Maste     }
624ac7ddfbfSEd Maste 
625435933ddSDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
626ac7ddfbfSEd Maste       m_ignore = 0;
627ac7ddfbfSEd Maste     }
628ac7ddfbfSEd Maste 
629435933ddSDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
630435933ddSDimitry Andric       return llvm::makeArrayRef(g_process_continue_options);
631ac7ddfbfSEd Maste     }
632ac7ddfbfSEd Maste 
633ac7ddfbfSEd Maste     uint32_t m_ignore;
634ac7ddfbfSEd Maste   };
635ac7ddfbfSEd Maste 
636435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
637ac7ddfbfSEd Maste     Process *process = m_exe_ctx.GetProcessPtr();
638ac7ddfbfSEd Maste     bool synchronous_execution = m_interpreter.GetSynchronous();
639ac7ddfbfSEd Maste     StateType state = process->GetState();
640435933ddSDimitry Andric     if (state == eStateStopped) {
641435933ddSDimitry Andric       if (command.GetArgumentCount() != 0) {
642435933ddSDimitry Andric         result.AppendErrorWithFormat(
643435933ddSDimitry Andric             "The '%s' command does not take any arguments.\n",
644435933ddSDimitry Andric             m_cmd_name.c_str());
645ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
646ac7ddfbfSEd Maste         return false;
647ac7ddfbfSEd Maste       }
648ac7ddfbfSEd Maste 
649435933ddSDimitry Andric       if (m_options.m_ignore > 0) {
6504bb0738eSEd Maste         ThreadSP sel_thread_sp(GetDefaultThread()->shared_from_this());
651435933ddSDimitry Andric         if (sel_thread_sp) {
652ac7ddfbfSEd Maste           StopInfoSP stop_info_sp = sel_thread_sp->GetStopInfo();
653435933ddSDimitry Andric           if (stop_info_sp &&
654435933ddSDimitry Andric               stop_info_sp->GetStopReason() == eStopReasonBreakpoint) {
655435933ddSDimitry Andric             lldb::break_id_t bp_site_id =
656435933ddSDimitry Andric                 (lldb::break_id_t)stop_info_sp->GetValue();
657435933ddSDimitry Andric             BreakpointSiteSP bp_site_sp(
658435933ddSDimitry Andric                 process->GetBreakpointSiteList().FindByID(bp_site_id));
659435933ddSDimitry Andric             if (bp_site_sp) {
660ac7ddfbfSEd Maste               const size_t num_owners = bp_site_sp->GetNumberOfOwners();
661435933ddSDimitry Andric               for (size_t i = 0; i < num_owners; i++) {
662435933ddSDimitry Andric                 Breakpoint &bp_ref =
663435933ddSDimitry Andric                     bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint();
664435933ddSDimitry Andric                 if (!bp_ref.IsInternal()) {
665ac7ddfbfSEd Maste                   bp_ref.SetIgnoreCount(m_options.m_ignore);
666ac7ddfbfSEd Maste                 }
667ac7ddfbfSEd Maste               }
668ac7ddfbfSEd Maste             }
669ac7ddfbfSEd Maste           }
670ac7ddfbfSEd Maste         }
671ac7ddfbfSEd Maste       }
672ac7ddfbfSEd Maste 
673ac7ddfbfSEd Maste       { // Scope for thread list mutex:
674435933ddSDimitry Andric         std::lock_guard<std::recursive_mutex> guard(
675435933ddSDimitry Andric             process->GetThreadList().GetMutex());
676ac7ddfbfSEd Maste         const uint32_t num_threads = process->GetThreadList().GetSize();
677ac7ddfbfSEd Maste 
678ac7ddfbfSEd Maste         // Set the actions that the threads should each take when resuming
679435933ddSDimitry Andric         for (uint32_t idx = 0; idx < num_threads; ++idx) {
6800127ef0fSEd Maste           const bool override_suspend = false;
681435933ddSDimitry Andric           process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState(
682435933ddSDimitry Andric               eStateRunning, override_suspend);
683ac7ddfbfSEd Maste         }
684ac7ddfbfSEd Maste       }
685ac7ddfbfSEd Maste 
6861c3bbb01SEd Maste       const uint32_t iohandler_id = process->GetIOHandlerID();
6871c3bbb01SEd Maste 
6887aa51b79SEd Maste       StreamString stream;
6897aa51b79SEd Maste       Error error;
6907aa51b79SEd Maste       if (synchronous_execution)
6917aa51b79SEd Maste         error = process->ResumeSynchronous(&stream);
6927aa51b79SEd Maste       else
6937aa51b79SEd Maste         error = process->Resume();
6940127ef0fSEd Maste 
695435933ddSDimitry Andric       if (error.Success()) {
696435933ddSDimitry Andric         // There is a race condition where this thread will return up the call
697435933ddSDimitry Andric         // stack to the main command
698435933ddSDimitry Andric         // handler and show an (lldb) prompt before HandlePrivateEvent (from
699435933ddSDimitry Andric         // PrivateStateThread) has
7000127ef0fSEd Maste         // a chance to call PushProcessIOHandler().
7011c3bbb01SEd Maste         process->SyncIOHandler(iohandler_id, 2000);
7020127ef0fSEd Maste 
703435933ddSDimitry Andric         result.AppendMessageWithFormat("Process %" PRIu64 " resuming\n",
704435933ddSDimitry Andric                                        process->GetID());
705435933ddSDimitry Andric         if (synchronous_execution) {
706435933ddSDimitry Andric           // If any state changed events had anything to say, add that to the
707435933ddSDimitry Andric           // result
708435933ddSDimitry Andric           result.AppendMessage(stream.GetString());
709ac7ddfbfSEd Maste 
710ac7ddfbfSEd Maste           result.SetDidChangeProcessState(true);
711ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusSuccessFinishNoResult);
712435933ddSDimitry Andric         } else {
713ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusSuccessContinuingNoResult);
714ac7ddfbfSEd Maste         }
715435933ddSDimitry Andric       } else {
716435933ddSDimitry Andric         result.AppendErrorWithFormat("Failed to resume process: %s.\n",
717435933ddSDimitry Andric                                      error.AsCString());
718ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
719ac7ddfbfSEd Maste       }
720435933ddSDimitry Andric     } else {
721435933ddSDimitry Andric       result.AppendErrorWithFormat(
722435933ddSDimitry Andric           "Process cannot be continued from its current state (%s).\n",
723ac7ddfbfSEd Maste           StateAsCString(state));
724ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
725ac7ddfbfSEd Maste     }
726ac7ddfbfSEd Maste     return result.Succeeded();
727ac7ddfbfSEd Maste   }
728ac7ddfbfSEd Maste 
729435933ddSDimitry Andric   Options *GetOptions() override { return &m_options; }
730ac7ddfbfSEd Maste 
731ac7ddfbfSEd Maste   CommandOptions m_options;
732ac7ddfbfSEd Maste };
733ac7ddfbfSEd Maste 
734ac7ddfbfSEd Maste //-------------------------------------------------------------------------
735ac7ddfbfSEd Maste // CommandObjectProcessDetach
736ac7ddfbfSEd Maste //-------------------------------------------------------------------------
737435933ddSDimitry Andric static OptionDefinition g_process_detach_options[] = {
738435933ddSDimitry Andric     // clang-format off
739435933ddSDimitry 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)." },
740435933ddSDimitry Andric     // clang-format on
741435933ddSDimitry Andric };
742435933ddSDimitry Andric 
743ac7ddfbfSEd Maste #pragma mark CommandObjectProcessDetach
744ac7ddfbfSEd Maste 
745435933ddSDimitry Andric class CommandObjectProcessDetach : public CommandObjectParsed {
746ac7ddfbfSEd Maste public:
747435933ddSDimitry Andric   class CommandOptions : public Options {
748ac7ddfbfSEd Maste   public:
749435933ddSDimitry Andric     CommandOptions() : Options() { OptionParsingStarting(nullptr); }
750ac7ddfbfSEd Maste 
7514bb0738eSEd Maste     ~CommandOptions() override = default;
752ac7ddfbfSEd Maste 
753435933ddSDimitry Andric     Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
754435933ddSDimitry Andric                          ExecutionContext *execution_context) override {
755ac7ddfbfSEd Maste       Error error;
756ac7ddfbfSEd Maste       const int short_option = m_getopt_table[option_idx].val;
757ac7ddfbfSEd Maste 
758435933ddSDimitry Andric       switch (short_option) {
759ac7ddfbfSEd Maste       case 's':
760ac7ddfbfSEd Maste         bool tmp_result;
761ac7ddfbfSEd Maste         bool success;
762ac7ddfbfSEd Maste         tmp_result = Args::StringToBoolean(option_arg, false, &success);
763ac7ddfbfSEd Maste         if (!success)
764435933ddSDimitry Andric           error.SetErrorStringWithFormat("invalid boolean option: \"%s\"",
765435933ddSDimitry Andric                                          option_arg.str().c_str());
766435933ddSDimitry Andric         else {
767ac7ddfbfSEd Maste           if (tmp_result)
768ac7ddfbfSEd Maste             m_keep_stopped = eLazyBoolYes;
769ac7ddfbfSEd Maste           else
770ac7ddfbfSEd Maste             m_keep_stopped = eLazyBoolNo;
771ac7ddfbfSEd Maste         }
772ac7ddfbfSEd Maste         break;
773ac7ddfbfSEd Maste       default:
774435933ddSDimitry Andric         error.SetErrorStringWithFormat("invalid short option character '%c'",
775435933ddSDimitry Andric                                        short_option);
776ac7ddfbfSEd Maste         break;
777ac7ddfbfSEd Maste       }
778ac7ddfbfSEd Maste       return error;
779ac7ddfbfSEd Maste     }
780ac7ddfbfSEd Maste 
781435933ddSDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
782ac7ddfbfSEd Maste       m_keep_stopped = eLazyBoolCalculate;
783ac7ddfbfSEd Maste     }
784ac7ddfbfSEd Maste 
785435933ddSDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
786435933ddSDimitry Andric       return llvm::makeArrayRef(g_process_detach_options);
787ac7ddfbfSEd Maste     }
788ac7ddfbfSEd Maste 
789ac7ddfbfSEd Maste     // Instance variables to hold the values for command options.
790ac7ddfbfSEd Maste     LazyBool m_keep_stopped;
791ac7ddfbfSEd Maste   };
792ac7ddfbfSEd Maste 
7934bb0738eSEd Maste   CommandObjectProcessDetach(CommandInterpreter &interpreter)
794435933ddSDimitry Andric       : CommandObjectParsed(interpreter, "process detach",
795435933ddSDimitry Andric                             "Detach from the current target process.",
796ac7ddfbfSEd Maste                             "process detach",
797435933ddSDimitry Andric                             eCommandRequiresProcess | eCommandTryTargetAPILock |
798435933ddSDimitry Andric                                 eCommandProcessMustBeLaunched),
799435933ddSDimitry Andric         m_options() {}
800ac7ddfbfSEd Maste 
8014bb0738eSEd Maste   ~CommandObjectProcessDetach() override = default;
802ac7ddfbfSEd Maste 
803435933ddSDimitry Andric   Options *GetOptions() override { return &m_options; }
804ac7ddfbfSEd Maste 
805ac7ddfbfSEd Maste protected:
806435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
807ac7ddfbfSEd Maste     Process *process = m_exe_ctx.GetProcessPtr();
808ac7ddfbfSEd Maste     // FIXME: This will be a Command Option:
809ac7ddfbfSEd Maste     bool keep_stopped;
810435933ddSDimitry Andric     if (m_options.m_keep_stopped == eLazyBoolCalculate) {
811ac7ddfbfSEd Maste       // Check the process default:
8124bb0738eSEd Maste       keep_stopped = process->GetDetachKeepsStopped();
813435933ddSDimitry Andric     } else if (m_options.m_keep_stopped == eLazyBoolYes)
814ac7ddfbfSEd Maste       keep_stopped = true;
815ac7ddfbfSEd Maste     else
816ac7ddfbfSEd Maste       keep_stopped = false;
817ac7ddfbfSEd Maste 
818ac7ddfbfSEd Maste     Error error(process->Detach(keep_stopped));
819435933ddSDimitry Andric     if (error.Success()) {
820ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusSuccessFinishResult);
821435933ddSDimitry Andric     } else {
822ac7ddfbfSEd Maste       result.AppendErrorWithFormat("Detach failed: %s\n", error.AsCString());
823ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
824ac7ddfbfSEd Maste       return false;
825ac7ddfbfSEd Maste     }
826ac7ddfbfSEd Maste     return result.Succeeded();
827ac7ddfbfSEd Maste   }
828ac7ddfbfSEd Maste 
829ac7ddfbfSEd Maste   CommandOptions m_options;
830ac7ddfbfSEd Maste };
831ac7ddfbfSEd Maste 
832ac7ddfbfSEd Maste //-------------------------------------------------------------------------
833ac7ddfbfSEd Maste // CommandObjectProcessConnect
834ac7ddfbfSEd Maste //-------------------------------------------------------------------------
835435933ddSDimitry Andric 
836435933ddSDimitry Andric static OptionDefinition g_process_connect_options[] = {
837435933ddSDimitry Andric     // clang-format off
838435933ddSDimitry Andric   { LLDB_OPT_SET_ALL, false, "plugin", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypePlugin, "Name of the process plugin you want to use." },
839435933ddSDimitry Andric     // clang-format on
840435933ddSDimitry Andric };
841435933ddSDimitry Andric 
842ac7ddfbfSEd Maste #pragma mark CommandObjectProcessConnect
843ac7ddfbfSEd Maste 
844435933ddSDimitry Andric class CommandObjectProcessConnect : public CommandObjectParsed {
845ac7ddfbfSEd Maste public:
846435933ddSDimitry Andric   class CommandOptions : public Options {
847ac7ddfbfSEd Maste   public:
848435933ddSDimitry Andric     CommandOptions() : Options() {
849435933ddSDimitry Andric       // Keep default values of all options in one place: OptionParsingStarting
850435933ddSDimitry Andric       // ()
851435933ddSDimitry Andric       OptionParsingStarting(nullptr);
852ac7ddfbfSEd Maste     }
853ac7ddfbfSEd Maste 
8544bb0738eSEd Maste     ~CommandOptions() override = default;
855ac7ddfbfSEd Maste 
856435933ddSDimitry Andric     Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
857435933ddSDimitry Andric                          ExecutionContext *execution_context) override {
858ac7ddfbfSEd Maste       Error error;
859ac7ddfbfSEd Maste       const int short_option = m_getopt_table[option_idx].val;
860ac7ddfbfSEd Maste 
861435933ddSDimitry Andric       switch (short_option) {
862ac7ddfbfSEd Maste       case 'p':
863ac7ddfbfSEd Maste         plugin_name.assign(option_arg);
864ac7ddfbfSEd Maste         break;
865ac7ddfbfSEd Maste 
866ac7ddfbfSEd Maste       default:
867435933ddSDimitry Andric         error.SetErrorStringWithFormat("invalid short option character '%c'",
868435933ddSDimitry Andric                                        short_option);
869ac7ddfbfSEd Maste         break;
870ac7ddfbfSEd Maste       }
871ac7ddfbfSEd Maste       return error;
872ac7ddfbfSEd Maste     }
873ac7ddfbfSEd Maste 
874435933ddSDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
875ac7ddfbfSEd Maste       plugin_name.clear();
876ac7ddfbfSEd Maste     }
877ac7ddfbfSEd Maste 
878435933ddSDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
879435933ddSDimitry Andric       return llvm::makeArrayRef(g_process_connect_options);
880ac7ddfbfSEd Maste     }
881ac7ddfbfSEd Maste 
882ac7ddfbfSEd Maste     // Instance variables to hold the values for command options.
883ac7ddfbfSEd Maste 
884ac7ddfbfSEd Maste     std::string plugin_name;
885ac7ddfbfSEd Maste   };
886ac7ddfbfSEd Maste 
887435933ddSDimitry Andric   CommandObjectProcessConnect(CommandInterpreter &interpreter)
888435933ddSDimitry Andric       : CommandObjectParsed(interpreter, "process connect",
889ac7ddfbfSEd Maste                             "Connect to a remote debug service.",
890435933ddSDimitry Andric                             "process connect <remote-url>", 0),
891435933ddSDimitry Andric         m_options() {}
892ac7ddfbfSEd Maste 
8934bb0738eSEd Maste   ~CommandObjectProcessConnect() override = default;
894ac7ddfbfSEd Maste 
895435933ddSDimitry Andric   Options *GetOptions() override { return &m_options; }
896ac7ddfbfSEd Maste 
897ac7ddfbfSEd Maste protected:
898435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
899435933ddSDimitry Andric     if (command.GetArgumentCount() != 1) {
900435933ddSDimitry Andric       result.AppendErrorWithFormat(
901435933ddSDimitry Andric           "'%s' takes exactly one argument:\nUsage: %s\n", m_cmd_name.c_str(),
9029f2f44ceSEd Maste           m_cmd_syntax.c_str());
9039f2f44ceSEd Maste       result.SetStatus(eReturnStatusFailed);
9049f2f44ceSEd Maste       return false;
9059f2f44ceSEd Maste     }
906ac7ddfbfSEd Maste 
907ac7ddfbfSEd Maste     Process *process = m_exe_ctx.GetProcessPtr();
908435933ddSDimitry Andric     if (process && process->IsAlive()) {
909435933ddSDimitry Andric       result.AppendErrorWithFormat(
910435933ddSDimitry Andric           "Process %" PRIu64
911435933ddSDimitry Andric           " is currently being debugged, kill the process before connecting.\n",
912ac7ddfbfSEd Maste           process->GetID());
913ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
914ac7ddfbfSEd Maste       return false;
915ac7ddfbfSEd Maste     }
916ac7ddfbfSEd Maste 
9179f2f44ceSEd Maste     const char *plugin_name = nullptr;
918ac7ddfbfSEd Maste     if (!m_options.plugin_name.empty())
919ac7ddfbfSEd Maste       plugin_name = m_options.plugin_name.c_str();
920ac7ddfbfSEd Maste 
9219f2f44ceSEd Maste     Error error;
9229f2f44ceSEd Maste     Debugger &debugger = m_interpreter.GetDebugger();
9239f2f44ceSEd Maste     PlatformSP platform_sp = m_interpreter.GetPlatform(true);
924435933ddSDimitry Andric     ProcessSP process_sp = platform_sp->ConnectProcess(
925435933ddSDimitry Andric         command.GetArgumentAtIndex(0), plugin_name, debugger,
926435933ddSDimitry Andric         debugger.GetSelectedTarget().get(), error);
927435933ddSDimitry Andric     if (error.Fail() || process_sp == nullptr) {
9289f2f44ceSEd Maste       result.AppendError(error.AsCString("Error connecting to the process"));
929ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
930ac7ddfbfSEd Maste       return false;
931ac7ddfbfSEd Maste     }
9329f2f44ceSEd Maste     return true;
933ac7ddfbfSEd Maste   }
934ac7ddfbfSEd Maste 
935ac7ddfbfSEd Maste   CommandOptions m_options;
936ac7ddfbfSEd Maste };
937ac7ddfbfSEd Maste 
938ac7ddfbfSEd Maste //-------------------------------------------------------------------------
939ac7ddfbfSEd Maste // CommandObjectProcessPlugin
940ac7ddfbfSEd Maste //-------------------------------------------------------------------------
941ac7ddfbfSEd Maste #pragma mark CommandObjectProcessPlugin
942ac7ddfbfSEd Maste 
943435933ddSDimitry Andric class CommandObjectProcessPlugin : public CommandObjectProxy {
944ac7ddfbfSEd Maste public:
9454bb0738eSEd Maste   CommandObjectProcessPlugin(CommandInterpreter &interpreter)
946435933ddSDimitry Andric       : CommandObjectProxy(
947435933ddSDimitry Andric             interpreter, "process plugin",
948435933ddSDimitry Andric             "Send a custom command to the current target process plug-in.",
949435933ddSDimitry Andric             "process plugin <args>", 0) {}
950ac7ddfbfSEd Maste 
9514bb0738eSEd Maste   ~CommandObjectProcessPlugin() override = default;
952ac7ddfbfSEd Maste 
953435933ddSDimitry Andric   CommandObject *GetProxyCommandObject() override {
954ac7ddfbfSEd Maste     Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
955ac7ddfbfSEd Maste     if (process)
956ac7ddfbfSEd Maste       return process->GetPluginCommandObject();
9574bb0738eSEd Maste     return nullptr;
958ac7ddfbfSEd Maste   }
959ac7ddfbfSEd Maste };
960ac7ddfbfSEd Maste 
961ac7ddfbfSEd Maste //-------------------------------------------------------------------------
962ac7ddfbfSEd Maste // CommandObjectProcessLoad
963ac7ddfbfSEd Maste //-------------------------------------------------------------------------
964435933ddSDimitry Andric 
965435933ddSDimitry Andric static OptionDefinition g_process_load_options[] = {
966435933ddSDimitry Andric     // clang-format off
967435933ddSDimitry 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." },
968435933ddSDimitry Andric     // clang-format on
969435933ddSDimitry Andric };
970435933ddSDimitry Andric 
971ac7ddfbfSEd Maste #pragma mark CommandObjectProcessLoad
972ac7ddfbfSEd Maste 
973435933ddSDimitry Andric class CommandObjectProcessLoad : public CommandObjectParsed {
974ac7ddfbfSEd Maste public:
975435933ddSDimitry Andric   class CommandOptions : public Options {
9769f2f44ceSEd Maste   public:
977435933ddSDimitry Andric     CommandOptions() : Options() {
978435933ddSDimitry Andric       // Keep default values of all options in one place: OptionParsingStarting
979435933ddSDimitry Andric       // ()
980435933ddSDimitry Andric       OptionParsingStarting(nullptr);
9819f2f44ceSEd Maste     }
9829f2f44ceSEd Maste 
9839f2f44ceSEd Maste     ~CommandOptions() override = default;
9849f2f44ceSEd Maste 
985435933ddSDimitry Andric     Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
986435933ddSDimitry Andric                          ExecutionContext *execution_context) override {
9879f2f44ceSEd Maste       Error error;
9889f2f44ceSEd Maste       const int short_option = m_getopt_table[option_idx].val;
989435933ddSDimitry Andric       switch (short_option) {
9909f2f44ceSEd Maste       case 'i':
9919f2f44ceSEd Maste         do_install = true;
992435933ddSDimitry Andric         if (!option_arg.empty())
9939f2f44ceSEd Maste           install_path.SetFile(option_arg, false);
9949f2f44ceSEd Maste         break;
9959f2f44ceSEd Maste       default:
996435933ddSDimitry Andric         error.SetErrorStringWithFormat("invalid short option character '%c'",
997435933ddSDimitry Andric                                        short_option);
9989f2f44ceSEd Maste         break;
9999f2f44ceSEd Maste       }
10009f2f44ceSEd Maste       return error;
10019f2f44ceSEd Maste     }
10029f2f44ceSEd Maste 
1003435933ddSDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
10049f2f44ceSEd Maste       do_install = false;
10059f2f44ceSEd Maste       install_path.Clear();
10069f2f44ceSEd Maste     }
10079f2f44ceSEd Maste 
1008435933ddSDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1009435933ddSDimitry Andric       return llvm::makeArrayRef(g_process_load_options);
10109f2f44ceSEd Maste     }
10119f2f44ceSEd Maste 
10129f2f44ceSEd Maste     // Instance variables to hold the values for command options.
10139f2f44ceSEd Maste     bool do_install;
10149f2f44ceSEd Maste     FileSpec install_path;
10159f2f44ceSEd Maste   };
1016ac7ddfbfSEd Maste 
1017435933ddSDimitry Andric   CommandObjectProcessLoad(CommandInterpreter &interpreter)
1018435933ddSDimitry Andric       : CommandObjectParsed(interpreter, "process load",
1019ac7ddfbfSEd Maste                             "Load a shared library into the current process.",
1020ac7ddfbfSEd Maste                             "process load <filename> [<filename> ...]",
1021435933ddSDimitry Andric                             eCommandRequiresProcess | eCommandTryTargetAPILock |
10221c3bbb01SEd Maste                                 eCommandProcessMustBeLaunched |
10239f2f44ceSEd Maste                                 eCommandProcessMustBePaused),
1024435933ddSDimitry Andric         m_options() {}
1025ac7ddfbfSEd Maste 
10269f2f44ceSEd Maste   ~CommandObjectProcessLoad() override = default;
10279f2f44ceSEd Maste 
1028435933ddSDimitry Andric   Options *GetOptions() override { return &m_options; }
1029ac7ddfbfSEd Maste 
1030ac7ddfbfSEd Maste protected:
1031435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
1032ac7ddfbfSEd Maste     Process *process = m_exe_ctx.GetProcessPtr();
1033ac7ddfbfSEd Maste 
1034435933ddSDimitry Andric     for (auto &entry : command.entries()) {
1035ac7ddfbfSEd Maste       Error error;
10369f2f44ceSEd Maste       PlatformSP platform = process->GetTarget().GetPlatform();
1037435933ddSDimitry Andric       llvm::StringRef image_path = entry.ref;
10389f2f44ceSEd Maste       uint32_t image_token = LLDB_INVALID_IMAGE_TOKEN;
10399f2f44ceSEd Maste 
1040435933ddSDimitry Andric       if (!m_options.do_install) {
1041ac7ddfbfSEd Maste         FileSpec image_spec(image_path, false);
10429f2f44ceSEd Maste         platform->ResolveRemotePath(image_spec, image_spec);
1043435933ddSDimitry Andric         image_token =
1044435933ddSDimitry Andric             platform->LoadImage(process, FileSpec(), image_spec, error);
1045435933ddSDimitry Andric       } else if (m_options.install_path) {
10469f2f44ceSEd Maste         FileSpec image_spec(image_path, true);
1047435933ddSDimitry Andric         platform->ResolveRemotePath(m_options.install_path,
1048435933ddSDimitry Andric                                     m_options.install_path);
1049435933ddSDimitry Andric         image_token = platform->LoadImage(process, image_spec,
1050435933ddSDimitry Andric                                           m_options.install_path, error);
1051435933ddSDimitry Andric       } else {
10529f2f44ceSEd Maste         FileSpec image_spec(image_path, true);
1053435933ddSDimitry Andric         image_token =
1054435933ddSDimitry Andric             platform->LoadImage(process, image_spec, FileSpec(), error);
10559f2f44ceSEd Maste       }
10569f2f44ceSEd Maste 
1057435933ddSDimitry Andric       if (image_token != LLDB_INVALID_IMAGE_TOKEN) {
1058435933ddSDimitry Andric         result.AppendMessageWithFormat(
1059435933ddSDimitry Andric             "Loading \"%s\"...ok\nImage %u loaded.\n", image_path.str().c_str(),
1060435933ddSDimitry Andric             image_token);
1061ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusSuccessFinishResult);
1062435933ddSDimitry Andric       } else {
1063435933ddSDimitry Andric         result.AppendErrorWithFormat("failed to load '%s': %s",
1064435933ddSDimitry Andric                                      image_path.str().c_str(),
1065435933ddSDimitry Andric                                      error.AsCString());
1066ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
1067ac7ddfbfSEd Maste       }
1068ac7ddfbfSEd Maste     }
1069ac7ddfbfSEd Maste     return result.Succeeded();
1070ac7ddfbfSEd Maste   }
10719f2f44ceSEd Maste 
10729f2f44ceSEd Maste   CommandOptions m_options;
1073ac7ddfbfSEd Maste };
1074ac7ddfbfSEd Maste 
1075ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1076ac7ddfbfSEd Maste // CommandObjectProcessUnload
1077ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1078ac7ddfbfSEd Maste #pragma mark CommandObjectProcessUnload
1079ac7ddfbfSEd Maste 
1080435933ddSDimitry Andric class CommandObjectProcessUnload : public CommandObjectParsed {
1081ac7ddfbfSEd Maste public:
1082435933ddSDimitry Andric   CommandObjectProcessUnload(CommandInterpreter &interpreter)
1083435933ddSDimitry Andric       : CommandObjectParsed(
1084435933ddSDimitry Andric             interpreter, "process unload",
1085435933ddSDimitry Andric             "Unload a shared library from the current process using the index "
1086435933ddSDimitry Andric             "returned by a previous call to \"process load\".",
1087ac7ddfbfSEd Maste             "process unload <index>",
1088435933ddSDimitry Andric             eCommandRequiresProcess | eCommandTryTargetAPILock |
1089435933ddSDimitry Andric                 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) {}
1090ac7ddfbfSEd Maste 
10914bb0738eSEd Maste   ~CommandObjectProcessUnload() override = default;
1092ac7ddfbfSEd Maste 
1093ac7ddfbfSEd Maste protected:
1094435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
1095ac7ddfbfSEd Maste     Process *process = m_exe_ctx.GetProcessPtr();
1096ac7ddfbfSEd Maste 
1097435933ddSDimitry Andric     for (auto &entry : command.entries()) {
1098435933ddSDimitry Andric       uint32_t image_token;
1099435933ddSDimitry Andric       if (entry.ref.getAsInteger(0, image_token)) {
1100435933ddSDimitry Andric         result.AppendErrorWithFormat("invalid image index argument '%s'",
1101435933ddSDimitry Andric                                      entry.ref.str().c_str());
1102ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
1103ac7ddfbfSEd Maste         break;
1104435933ddSDimitry Andric       } else {
1105435933ddSDimitry Andric         Error error(process->GetTarget().GetPlatform()->UnloadImage(
1106435933ddSDimitry Andric             process, image_token));
1107435933ddSDimitry Andric         if (error.Success()) {
1108435933ddSDimitry Andric           result.AppendMessageWithFormat(
1109435933ddSDimitry Andric               "Unloading shared library with index %u...ok\n", image_token);
1110ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusSuccessFinishResult);
1111435933ddSDimitry Andric         } else {
1112435933ddSDimitry Andric           result.AppendErrorWithFormat("failed to unload image: %s",
1113435933ddSDimitry Andric                                        error.AsCString());
1114ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusFailed);
1115ac7ddfbfSEd Maste           break;
1116ac7ddfbfSEd Maste         }
1117ac7ddfbfSEd Maste       }
1118ac7ddfbfSEd Maste     }
1119ac7ddfbfSEd Maste     return result.Succeeded();
1120ac7ddfbfSEd Maste   }
1121ac7ddfbfSEd Maste };
1122ac7ddfbfSEd Maste 
1123ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1124ac7ddfbfSEd Maste // CommandObjectProcessSignal
1125ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1126ac7ddfbfSEd Maste #pragma mark CommandObjectProcessSignal
1127ac7ddfbfSEd Maste 
1128435933ddSDimitry Andric class CommandObjectProcessSignal : public CommandObjectParsed {
1129ac7ddfbfSEd Maste public:
11304bb0738eSEd Maste   CommandObjectProcessSignal(CommandInterpreter &interpreter)
1131435933ddSDimitry Andric       : CommandObjectParsed(interpreter, "process signal",
1132435933ddSDimitry Andric                             "Send a UNIX signal to the current target process.",
1133435933ddSDimitry Andric                             nullptr, eCommandRequiresProcess |
1134435933ddSDimitry Andric                                          eCommandTryTargetAPILock) {
1135ac7ddfbfSEd Maste     CommandArgumentEntry arg;
1136ac7ddfbfSEd Maste     CommandArgumentData signal_arg;
1137ac7ddfbfSEd Maste 
1138ac7ddfbfSEd Maste     // Define the first (and only) variant of this arg.
1139ac7ddfbfSEd Maste     signal_arg.arg_type = eArgTypeUnixSignal;
1140ac7ddfbfSEd Maste     signal_arg.arg_repetition = eArgRepeatPlain;
1141ac7ddfbfSEd Maste 
1142435933ddSDimitry Andric     // There is only one variant this argument could be; put it into the
1143435933ddSDimitry Andric     // argument entry.
1144ac7ddfbfSEd Maste     arg.push_back(signal_arg);
1145ac7ddfbfSEd Maste 
1146ac7ddfbfSEd Maste     // Push the data for the first argument into the m_arguments vector.
1147ac7ddfbfSEd Maste     m_arguments.push_back(arg);
1148ac7ddfbfSEd Maste   }
1149ac7ddfbfSEd Maste 
11504bb0738eSEd Maste   ~CommandObjectProcessSignal() override = default;
1151ac7ddfbfSEd Maste 
1152ac7ddfbfSEd Maste protected:
1153435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
1154ac7ddfbfSEd Maste     Process *process = m_exe_ctx.GetProcessPtr();
1155ac7ddfbfSEd Maste 
1156435933ddSDimitry Andric     if (command.GetArgumentCount() == 1) {
1157ac7ddfbfSEd Maste       int signo = LLDB_INVALID_SIGNAL_NUMBER;
1158ac7ddfbfSEd Maste 
1159ac7ddfbfSEd Maste       const char *signal_name = command.GetArgumentAtIndex(0);
1160ac7ddfbfSEd Maste       if (::isxdigit(signal_name[0]))
1161435933ddSDimitry Andric         signo =
1162435933ddSDimitry Andric             StringConvert::ToSInt32(signal_name, LLDB_INVALID_SIGNAL_NUMBER, 0);
1163ac7ddfbfSEd Maste       else
1164b91a7dfcSDimitry Andric         signo = process->GetUnixSignals()->GetSignalNumberFromName(signal_name);
1165ac7ddfbfSEd Maste 
1166435933ddSDimitry Andric       if (signo == LLDB_INVALID_SIGNAL_NUMBER) {
1167435933ddSDimitry Andric         result.AppendErrorWithFormat("Invalid signal argument '%s'.\n",
1168435933ddSDimitry Andric                                      command.GetArgumentAtIndex(0));
1169ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
1170435933ddSDimitry Andric       } else {
1171ac7ddfbfSEd Maste         Error error(process->Signal(signo));
1172435933ddSDimitry Andric         if (error.Success()) {
1173ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusSuccessFinishResult);
1174435933ddSDimitry Andric         } else {
1175435933ddSDimitry Andric           result.AppendErrorWithFormat("Failed to send signal %i: %s\n", signo,
1176435933ddSDimitry Andric                                        error.AsCString());
1177ac7ddfbfSEd Maste           result.SetStatus(eReturnStatusFailed);
1178ac7ddfbfSEd Maste         }
1179ac7ddfbfSEd Maste       }
1180435933ddSDimitry Andric     } else {
1181435933ddSDimitry Andric       result.AppendErrorWithFormat(
1182435933ddSDimitry Andric           "'%s' takes exactly one signal number argument:\nUsage: %s\n",
1183435933ddSDimitry Andric           m_cmd_name.c_str(), m_cmd_syntax.c_str());
1184ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1185ac7ddfbfSEd Maste     }
1186ac7ddfbfSEd Maste     return result.Succeeded();
1187ac7ddfbfSEd Maste   }
1188ac7ddfbfSEd Maste };
1189ac7ddfbfSEd Maste 
1190ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1191ac7ddfbfSEd Maste // CommandObjectProcessInterrupt
1192ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1193ac7ddfbfSEd Maste #pragma mark CommandObjectProcessInterrupt
1194ac7ddfbfSEd Maste 
1195435933ddSDimitry Andric class CommandObjectProcessInterrupt : public CommandObjectParsed {
1196ac7ddfbfSEd Maste public:
11974bb0738eSEd Maste   CommandObjectProcessInterrupt(CommandInterpreter &interpreter)
1198435933ddSDimitry Andric       : CommandObjectParsed(interpreter, "process interrupt",
1199435933ddSDimitry Andric                             "Interrupt the current target process.",
1200ac7ddfbfSEd Maste                             "process interrupt",
1201435933ddSDimitry Andric                             eCommandRequiresProcess | eCommandTryTargetAPILock |
1202435933ddSDimitry Andric                                 eCommandProcessMustBeLaunched) {}
1203ac7ddfbfSEd Maste 
12044bb0738eSEd Maste   ~CommandObjectProcessInterrupt() override = default;
1205ac7ddfbfSEd Maste 
1206ac7ddfbfSEd Maste protected:
1207435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
1208ac7ddfbfSEd Maste     Process *process = m_exe_ctx.GetProcessPtr();
1209435933ddSDimitry Andric     if (process == nullptr) {
1210ac7ddfbfSEd Maste       result.AppendError("no process to halt");
1211ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1212ac7ddfbfSEd Maste       return false;
1213ac7ddfbfSEd Maste     }
1214ac7ddfbfSEd Maste 
1215435933ddSDimitry Andric     if (command.GetArgumentCount() == 0) {
1216ac7ddfbfSEd Maste       bool clear_thread_plans = true;
1217ac7ddfbfSEd Maste       Error error(process->Halt(clear_thread_plans));
1218435933ddSDimitry Andric       if (error.Success()) {
1219ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusSuccessFinishResult);
1220435933ddSDimitry Andric       } else {
1221435933ddSDimitry Andric         result.AppendErrorWithFormat("Failed to halt process: %s\n",
1222435933ddSDimitry Andric                                      error.AsCString());
1223ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
1224ac7ddfbfSEd Maste       }
1225435933ddSDimitry Andric     } else {
1226ac7ddfbfSEd Maste       result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n",
1227435933ddSDimitry Andric                                    m_cmd_name.c_str(), m_cmd_syntax.c_str());
1228ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1229ac7ddfbfSEd Maste     }
1230ac7ddfbfSEd Maste     return result.Succeeded();
1231ac7ddfbfSEd Maste   }
1232ac7ddfbfSEd Maste };
1233ac7ddfbfSEd Maste 
1234ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1235ac7ddfbfSEd Maste // CommandObjectProcessKill
1236ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1237ac7ddfbfSEd Maste #pragma mark CommandObjectProcessKill
1238ac7ddfbfSEd Maste 
1239435933ddSDimitry Andric class CommandObjectProcessKill : public CommandObjectParsed {
1240ac7ddfbfSEd Maste public:
12414bb0738eSEd Maste   CommandObjectProcessKill(CommandInterpreter &interpreter)
1242435933ddSDimitry Andric       : CommandObjectParsed(interpreter, "process kill",
1243435933ddSDimitry Andric                             "Terminate the current target process.",
1244435933ddSDimitry Andric                             "process kill",
1245435933ddSDimitry Andric                             eCommandRequiresProcess | eCommandTryTargetAPILock |
1246435933ddSDimitry Andric                                 eCommandProcessMustBeLaunched) {}
1247ac7ddfbfSEd Maste 
12484bb0738eSEd Maste   ~CommandObjectProcessKill() override = default;
1249ac7ddfbfSEd Maste 
1250ac7ddfbfSEd Maste protected:
1251435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
1252ac7ddfbfSEd Maste     Process *process = m_exe_ctx.GetProcessPtr();
1253435933ddSDimitry Andric     if (process == nullptr) {
1254ac7ddfbfSEd Maste       result.AppendError("no process to kill");
1255ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1256ac7ddfbfSEd Maste       return false;
1257ac7ddfbfSEd Maste     }
1258ac7ddfbfSEd Maste 
1259435933ddSDimitry Andric     if (command.GetArgumentCount() == 0) {
12601c3bbb01SEd Maste       Error error(process->Destroy(true));
1261435933ddSDimitry Andric       if (error.Success()) {
1262ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusSuccessFinishResult);
1263435933ddSDimitry Andric       } else {
1264435933ddSDimitry Andric         result.AppendErrorWithFormat("Failed to kill process: %s\n",
1265435933ddSDimitry Andric                                      error.AsCString());
1266ac7ddfbfSEd Maste         result.SetStatus(eReturnStatusFailed);
1267ac7ddfbfSEd Maste       }
1268435933ddSDimitry Andric     } else {
1269ac7ddfbfSEd Maste       result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n",
1270435933ddSDimitry Andric                                    m_cmd_name.c_str(), m_cmd_syntax.c_str());
1271ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1272ac7ddfbfSEd Maste     }
1273ac7ddfbfSEd Maste     return result.Succeeded();
1274ac7ddfbfSEd Maste   }
1275ac7ddfbfSEd Maste };
1276ac7ddfbfSEd Maste 
1277ac7ddfbfSEd Maste //-------------------------------------------------------------------------
12780127ef0fSEd Maste // CommandObjectProcessSaveCore
12790127ef0fSEd Maste //-------------------------------------------------------------------------
12800127ef0fSEd Maste #pragma mark CommandObjectProcessSaveCore
12810127ef0fSEd Maste 
1282435933ddSDimitry Andric class CommandObjectProcessSaveCore : public CommandObjectParsed {
12830127ef0fSEd Maste public:
1284435933ddSDimitry Andric   CommandObjectProcessSaveCore(CommandInterpreter &interpreter)
1285435933ddSDimitry Andric       : CommandObjectParsed(interpreter, "process save-core",
1286435933ddSDimitry Andric                             "Save the current process as a core file using an "
1287435933ddSDimitry Andric                             "appropriate file type.",
12880127ef0fSEd Maste                             "process save-core FILE",
1289435933ddSDimitry Andric                             eCommandRequiresProcess | eCommandTryTargetAPILock |
1290435933ddSDimitry Andric                                 eCommandProcessMustBeLaunched) {}
12910127ef0fSEd Maste 
12924bb0738eSEd Maste   ~CommandObjectProcessSaveCore() override = default;
12930127ef0fSEd Maste 
12940127ef0fSEd Maste protected:
1295435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
12960127ef0fSEd Maste     ProcessSP process_sp = m_exe_ctx.GetProcessSP();
1297435933ddSDimitry Andric     if (process_sp) {
1298435933ddSDimitry Andric       if (command.GetArgumentCount() == 1) {
12990127ef0fSEd Maste         FileSpec output_file(command.GetArgumentAtIndex(0), false);
13000127ef0fSEd Maste         Error error = PluginManager::SaveCore(process_sp, output_file);
1301435933ddSDimitry Andric         if (error.Success()) {
13020127ef0fSEd Maste           result.SetStatus(eReturnStatusSuccessFinishResult);
1303435933ddSDimitry Andric         } else {
1304435933ddSDimitry Andric           result.AppendErrorWithFormat(
1305435933ddSDimitry Andric               "Failed to save core file for process: %s\n", error.AsCString());
13060127ef0fSEd Maste           result.SetStatus(eReturnStatusFailed);
13070127ef0fSEd Maste         }
1308435933ddSDimitry Andric       } else {
13090127ef0fSEd Maste         result.AppendErrorWithFormat("'%s' takes one arguments:\nUsage: %s\n",
1310435933ddSDimitry Andric                                      m_cmd_name.c_str(), m_cmd_syntax.c_str());
13110127ef0fSEd Maste         result.SetStatus(eReturnStatusFailed);
13120127ef0fSEd Maste       }
1313435933ddSDimitry Andric     } else {
13140127ef0fSEd Maste       result.AppendError("invalid process");
13150127ef0fSEd Maste       result.SetStatus(eReturnStatusFailed);
13160127ef0fSEd Maste       return false;
13170127ef0fSEd Maste     }
13180127ef0fSEd Maste 
13190127ef0fSEd Maste     return result.Succeeded();
13200127ef0fSEd Maste   }
13210127ef0fSEd Maste };
13220127ef0fSEd Maste 
13230127ef0fSEd Maste //-------------------------------------------------------------------------
1324ac7ddfbfSEd Maste // CommandObjectProcessStatus
1325ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1326ac7ddfbfSEd Maste #pragma mark CommandObjectProcessStatus
1327ac7ddfbfSEd Maste 
1328435933ddSDimitry Andric class CommandObjectProcessStatus : public CommandObjectParsed {
1329ac7ddfbfSEd Maste public:
13304bb0738eSEd Maste   CommandObjectProcessStatus(CommandInterpreter &interpreter)
1331435933ddSDimitry Andric       : CommandObjectParsed(
1332435933ddSDimitry Andric             interpreter, "process status",
1333435933ddSDimitry Andric             "Show status and stop location for the current target process.",
1334435933ddSDimitry Andric             "process status",
1335435933ddSDimitry Andric             eCommandRequiresProcess | eCommandTryTargetAPILock) {}
1336ac7ddfbfSEd Maste 
13374bb0738eSEd Maste   ~CommandObjectProcessStatus() override = default;
1338ac7ddfbfSEd Maste 
1339435933ddSDimitry Andric   bool DoExecute(Args &command, CommandReturnObject &result) override {
1340ac7ddfbfSEd Maste     Stream &strm = result.GetOutputStream();
1341ac7ddfbfSEd Maste     result.SetStatus(eReturnStatusSuccessFinishNoResult);
1342435933ddSDimitry Andric     // No need to check "process" for validity as eCommandRequiresProcess
1343435933ddSDimitry Andric     // ensures it is valid
1344ac7ddfbfSEd Maste     Process *process = m_exe_ctx.GetProcessPtr();
1345ac7ddfbfSEd Maste     const bool only_threads_with_stop_reason = true;
1346ac7ddfbfSEd Maste     const uint32_t start_frame = 0;
1347ac7ddfbfSEd Maste     const uint32_t num_frames = 1;
1348ac7ddfbfSEd Maste     const uint32_t num_frames_with_source = 1;
1349435933ddSDimitry Andric     const bool     stop_format = true;
1350ac7ddfbfSEd Maste     process->GetStatus(strm);
1351435933ddSDimitry Andric     process->GetThreadStatus(strm, only_threads_with_stop_reason, start_frame,
1352435933ddSDimitry Andric                              num_frames, num_frames_with_source, stop_format);
1353ac7ddfbfSEd Maste     return result.Succeeded();
1354ac7ddfbfSEd Maste   }
1355ac7ddfbfSEd Maste };
1356ac7ddfbfSEd Maste 
1357ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1358ac7ddfbfSEd Maste // CommandObjectProcessHandle
1359ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1360435933ddSDimitry Andric 
1361435933ddSDimitry Andric static OptionDefinition g_process_handle_options[] = {
1362435933ddSDimitry Andric     // clang-format off
1363435933ddSDimitry 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." },
1364435933ddSDimitry 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." },
1365435933ddSDimitry 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." }
1366435933ddSDimitry Andric     // clang-format on
1367435933ddSDimitry Andric };
1368435933ddSDimitry Andric 
1369ac7ddfbfSEd Maste #pragma mark CommandObjectProcessHandle
1370ac7ddfbfSEd Maste 
1371435933ddSDimitry Andric class CommandObjectProcessHandle : public CommandObjectParsed {
1372ac7ddfbfSEd Maste public:
1373435933ddSDimitry Andric   class CommandOptions : public Options {
1374ac7ddfbfSEd Maste   public:
1375435933ddSDimitry Andric     CommandOptions() : Options() { OptionParsingStarting(nullptr); }
1376ac7ddfbfSEd Maste 
13774bb0738eSEd Maste     ~CommandOptions() override = default;
1378ac7ddfbfSEd Maste 
1379435933ddSDimitry Andric     Error SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
1380435933ddSDimitry Andric                          ExecutionContext *execution_context) override {
1381ac7ddfbfSEd Maste       Error error;
1382ac7ddfbfSEd Maste       const int short_option = m_getopt_table[option_idx].val;
1383ac7ddfbfSEd Maste 
1384435933ddSDimitry Andric       switch (short_option) {
1385ac7ddfbfSEd Maste       case 's':
1386ac7ddfbfSEd Maste         stop = option_arg;
1387ac7ddfbfSEd Maste         break;
1388ac7ddfbfSEd Maste       case 'n':
1389ac7ddfbfSEd Maste         notify = option_arg;
1390ac7ddfbfSEd Maste         break;
1391ac7ddfbfSEd Maste       case 'p':
1392ac7ddfbfSEd Maste         pass = option_arg;
1393ac7ddfbfSEd Maste         break;
1394ac7ddfbfSEd Maste       default:
1395435933ddSDimitry Andric         error.SetErrorStringWithFormat("invalid short option character '%c'",
1396435933ddSDimitry Andric                                        short_option);
1397ac7ddfbfSEd Maste         break;
1398ac7ddfbfSEd Maste       }
1399ac7ddfbfSEd Maste       return error;
1400ac7ddfbfSEd Maste     }
1401ac7ddfbfSEd Maste 
1402435933ddSDimitry Andric     void OptionParsingStarting(ExecutionContext *execution_context) override {
1403ac7ddfbfSEd Maste       stop.clear();
1404ac7ddfbfSEd Maste       notify.clear();
1405ac7ddfbfSEd Maste       pass.clear();
1406ac7ddfbfSEd Maste     }
1407ac7ddfbfSEd Maste 
1408435933ddSDimitry Andric     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
1409435933ddSDimitry Andric       return llvm::makeArrayRef(g_process_handle_options);
1410ac7ddfbfSEd Maste     }
1411ac7ddfbfSEd Maste 
1412ac7ddfbfSEd Maste     // Instance variables to hold the values for command options.
1413ac7ddfbfSEd Maste 
1414ac7ddfbfSEd Maste     std::string stop;
1415ac7ddfbfSEd Maste     std::string notify;
1416ac7ddfbfSEd Maste     std::string pass;
1417ac7ddfbfSEd Maste   };
1418ac7ddfbfSEd Maste 
14194bb0738eSEd Maste   CommandObjectProcessHandle(CommandInterpreter &interpreter)
1420435933ddSDimitry Andric       : CommandObjectParsed(interpreter, "process handle",
1421435933ddSDimitry Andric                             "Manage LLDB handling of OS signals for the "
1422435933ddSDimitry Andric                             "current target process.  Defaults to showing "
1423435933ddSDimitry Andric                             "current policy.",
14244bb0738eSEd Maste                             nullptr),
1425435933ddSDimitry Andric         m_options() {
1426b91a7dfcSDimitry Andric     SetHelpLong("\nIf no signals are specified, update them all.  If no update "
1427b91a7dfcSDimitry Andric                 "option is specified, list the current values.");
1428ac7ddfbfSEd Maste     CommandArgumentEntry arg;
1429ac7ddfbfSEd Maste     CommandArgumentData signal_arg;
1430ac7ddfbfSEd Maste 
1431ac7ddfbfSEd Maste     signal_arg.arg_type = eArgTypeUnixSignal;
1432ac7ddfbfSEd Maste     signal_arg.arg_repetition = eArgRepeatStar;
1433ac7ddfbfSEd Maste 
1434ac7ddfbfSEd Maste     arg.push_back(signal_arg);
1435ac7ddfbfSEd Maste 
1436ac7ddfbfSEd Maste     m_arguments.push_back(arg);
1437ac7ddfbfSEd Maste   }
1438ac7ddfbfSEd Maste 
14394bb0738eSEd Maste   ~CommandObjectProcessHandle() override = default;
1440ac7ddfbfSEd Maste 
1441435933ddSDimitry Andric   Options *GetOptions() override { return &m_options; }
1442ac7ddfbfSEd Maste 
1443435933ddSDimitry Andric   bool VerifyCommandOptionValue(const std::string &option, int &real_value) {
1444ac7ddfbfSEd Maste     bool okay = true;
1445ac7ddfbfSEd Maste     bool success = false;
1446435933ddSDimitry Andric     bool tmp_value = Args::StringToBoolean(option, false, &success);
1447ac7ddfbfSEd Maste 
1448ac7ddfbfSEd Maste     if (success && tmp_value)
1449ac7ddfbfSEd Maste       real_value = 1;
1450ac7ddfbfSEd Maste     else if (success && !tmp_value)
1451ac7ddfbfSEd Maste       real_value = 0;
1452435933ddSDimitry Andric     else {
1453ac7ddfbfSEd Maste       // If the value isn't 'true' or 'false', it had better be 0 or 1.
14541c3bbb01SEd Maste       real_value = StringConvert::ToUInt32(option.c_str(), 3);
1455ac7ddfbfSEd Maste       if (real_value != 0 && real_value != 1)
1456ac7ddfbfSEd Maste         okay = false;
1457ac7ddfbfSEd Maste     }
1458ac7ddfbfSEd Maste 
1459ac7ddfbfSEd Maste     return okay;
1460ac7ddfbfSEd Maste   }
1461ac7ddfbfSEd Maste 
1462435933ddSDimitry Andric   void PrintSignalHeader(Stream &str) {
1463ac7ddfbfSEd Maste     str.Printf("NAME         PASS   STOP   NOTIFY\n");
14641c3bbb01SEd Maste     str.Printf("===========  =====  =====  ======\n");
1465ac7ddfbfSEd Maste   }
1466ac7ddfbfSEd Maste 
1467435933ddSDimitry Andric   void PrintSignal(Stream &str, int32_t signo, const char *sig_name,
1468435933ddSDimitry Andric                    const UnixSignalsSP &signals_sp) {
1469ac7ddfbfSEd Maste     bool stop;
1470ac7ddfbfSEd Maste     bool suppress;
1471ac7ddfbfSEd Maste     bool notify;
1472ac7ddfbfSEd Maste 
14731c3bbb01SEd Maste     str.Printf("%-11s  ", sig_name);
1474435933ddSDimitry Andric     if (signals_sp->GetSignalInfo(signo, suppress, stop, notify)) {
1475ac7ddfbfSEd Maste       bool pass = !suppress;
1476435933ddSDimitry Andric       str.Printf("%s  %s  %s", (pass ? "true " : "false"),
1477435933ddSDimitry Andric                  (stop ? "true " : "false"), (notify ? "true " : "false"));
1478ac7ddfbfSEd Maste     }
1479ac7ddfbfSEd Maste     str.Printf("\n");
1480ac7ddfbfSEd Maste   }
1481ac7ddfbfSEd Maste 
1482435933ddSDimitry Andric   void PrintSignalInformation(Stream &str, Args &signal_args,
1483435933ddSDimitry Andric                               int num_valid_signals,
1484435933ddSDimitry Andric                               const UnixSignalsSP &signals_sp) {
1485ac7ddfbfSEd Maste     PrintSignalHeader(str);
1486ac7ddfbfSEd Maste 
1487435933ddSDimitry Andric     if (num_valid_signals > 0) {
1488ac7ddfbfSEd Maste       size_t num_args = signal_args.GetArgumentCount();
1489435933ddSDimitry Andric       for (size_t i = 0; i < num_args; ++i) {
1490435933ddSDimitry Andric         int32_t signo = signals_sp->GetSignalNumberFromName(
1491435933ddSDimitry Andric             signal_args.GetArgumentAtIndex(i));
1492ac7ddfbfSEd Maste         if (signo != LLDB_INVALID_SIGNAL_NUMBER)
1493435933ddSDimitry Andric           PrintSignal(str, signo, signal_args.GetArgumentAtIndex(i),
1494435933ddSDimitry Andric                       signals_sp);
1495ac7ddfbfSEd Maste       }
1496435933ddSDimitry Andric     } else // Print info for ALL signals
1497ac7ddfbfSEd Maste     {
1498b91a7dfcSDimitry Andric       int32_t signo = signals_sp->GetFirstSignalNumber();
1499435933ddSDimitry Andric       while (signo != LLDB_INVALID_SIGNAL_NUMBER) {
1500435933ddSDimitry Andric         PrintSignal(str, signo, signals_sp->GetSignalAsCString(signo),
1501435933ddSDimitry Andric                     signals_sp);
1502b91a7dfcSDimitry Andric         signo = signals_sp->GetNextSignalNumber(signo);
1503ac7ddfbfSEd Maste       }
1504ac7ddfbfSEd Maste     }
1505ac7ddfbfSEd Maste   }
1506ac7ddfbfSEd Maste 
1507ac7ddfbfSEd Maste protected:
1508435933ddSDimitry Andric   bool DoExecute(Args &signal_args, CommandReturnObject &result) override {
1509ac7ddfbfSEd Maste     TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
1510ac7ddfbfSEd Maste 
1511435933ddSDimitry Andric     if (!target_sp) {
1512ac7ddfbfSEd Maste       result.AppendError("No current target;"
1513435933ddSDimitry Andric                          " cannot handle signals until you have a valid target "
1514435933ddSDimitry Andric                          "and process.\n");
1515ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1516ac7ddfbfSEd Maste       return false;
1517ac7ddfbfSEd Maste     }
1518ac7ddfbfSEd Maste 
1519ac7ddfbfSEd Maste     ProcessSP process_sp = target_sp->GetProcessSP();
1520ac7ddfbfSEd Maste 
1521435933ddSDimitry Andric     if (!process_sp) {
1522435933ddSDimitry Andric       result.AppendError("No current process; cannot handle signals until you "
1523435933ddSDimitry Andric                          "have a valid process.\n");
1524ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1525ac7ddfbfSEd Maste       return false;
1526ac7ddfbfSEd Maste     }
1527ac7ddfbfSEd Maste 
1528ac7ddfbfSEd Maste     int stop_action = -1;   // -1 means leave the current setting alone
1529ac7ddfbfSEd Maste     int pass_action = -1;   // -1 means leave the current setting alone
1530ac7ddfbfSEd Maste     int notify_action = -1; // -1 means leave the current setting alone
1531ac7ddfbfSEd Maste 
1532435933ddSDimitry Andric     if (!m_options.stop.empty() &&
1533435933ddSDimitry Andric         !VerifyCommandOptionValue(m_options.stop, stop_action)) {
1534435933ddSDimitry Andric       result.AppendError("Invalid argument for command option --stop; must be "
1535435933ddSDimitry Andric                          "true or false.\n");
1536ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1537ac7ddfbfSEd Maste       return false;
1538ac7ddfbfSEd Maste     }
1539ac7ddfbfSEd Maste 
1540435933ddSDimitry Andric     if (!m_options.notify.empty() &&
1541435933ddSDimitry Andric         !VerifyCommandOptionValue(m_options.notify, notify_action)) {
1542435933ddSDimitry Andric       result.AppendError("Invalid argument for command option --notify; must "
1543435933ddSDimitry Andric                          "be true or false.\n");
1544ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1545ac7ddfbfSEd Maste       return false;
1546ac7ddfbfSEd Maste     }
1547ac7ddfbfSEd Maste 
1548435933ddSDimitry Andric     if (!m_options.pass.empty() &&
1549435933ddSDimitry Andric         !VerifyCommandOptionValue(m_options.pass, pass_action)) {
1550435933ddSDimitry Andric       result.AppendError("Invalid argument for command option --pass; must be "
1551435933ddSDimitry Andric                          "true or false.\n");
1552ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1553ac7ddfbfSEd Maste       return false;
1554ac7ddfbfSEd Maste     }
1555ac7ddfbfSEd Maste 
1556ac7ddfbfSEd Maste     size_t num_args = signal_args.GetArgumentCount();
1557b91a7dfcSDimitry Andric     UnixSignalsSP signals_sp = process_sp->GetUnixSignals();
1558ac7ddfbfSEd Maste     int num_signals_set = 0;
1559ac7ddfbfSEd Maste 
1560435933ddSDimitry Andric     if (num_args > 0) {
1561435933ddSDimitry Andric       for (const auto &arg : signal_args) {
1562435933ddSDimitry Andric         int32_t signo = signals_sp->GetSignalNumberFromName(arg.c_str());
1563435933ddSDimitry Andric         if (signo != LLDB_INVALID_SIGNAL_NUMBER) {
1564435933ddSDimitry Andric           // Casting the actions as bools here should be okay, because
1565435933ddSDimitry Andric           // VerifyCommandOptionValue guarantees
1566ac7ddfbfSEd Maste           // the value is either 0 or 1.
1567ac7ddfbfSEd Maste           if (stop_action != -1)
1568b91a7dfcSDimitry Andric             signals_sp->SetShouldStop(signo, stop_action);
1569435933ddSDimitry Andric           if (pass_action != -1) {
1570b91a7dfcSDimitry Andric             bool suppress = !pass_action;
1571b91a7dfcSDimitry Andric             signals_sp->SetShouldSuppress(signo, suppress);
1572ac7ddfbfSEd Maste           }
1573ac7ddfbfSEd Maste           if (notify_action != -1)
1574b91a7dfcSDimitry Andric             signals_sp->SetShouldNotify(signo, notify_action);
1575ac7ddfbfSEd Maste           ++num_signals_set;
1576435933ddSDimitry Andric         } else {
1577435933ddSDimitry Andric           result.AppendErrorWithFormat("Invalid signal name '%s'\n",
1578435933ddSDimitry Andric                                        arg.c_str());
1579ac7ddfbfSEd Maste         }
1580ac7ddfbfSEd Maste       }
1581435933ddSDimitry Andric     } else {
1582435933ddSDimitry Andric       // No signal specified, if any command options were specified, update ALL
1583435933ddSDimitry Andric       // signals.
1584435933ddSDimitry Andric       if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1)) {
1585435933ddSDimitry Andric         if (m_interpreter.Confirm(
1586435933ddSDimitry Andric                 "Do you really want to update all the signals?", false)) {
1587b91a7dfcSDimitry Andric           int32_t signo = signals_sp->GetFirstSignalNumber();
1588435933ddSDimitry Andric           while (signo != LLDB_INVALID_SIGNAL_NUMBER) {
1589ac7ddfbfSEd Maste             if (notify_action != -1)
1590b91a7dfcSDimitry Andric               signals_sp->SetShouldNotify(signo, notify_action);
1591ac7ddfbfSEd Maste             if (stop_action != -1)
1592b91a7dfcSDimitry Andric               signals_sp->SetShouldStop(signo, stop_action);
1593435933ddSDimitry Andric             if (pass_action != -1) {
1594b91a7dfcSDimitry Andric               bool suppress = !pass_action;
1595b91a7dfcSDimitry Andric               signals_sp->SetShouldSuppress(signo, suppress);
1596ac7ddfbfSEd Maste             }
1597b91a7dfcSDimitry Andric             signo = signals_sp->GetNextSignalNumber(signo);
1598ac7ddfbfSEd Maste           }
1599ac7ddfbfSEd Maste         }
1600ac7ddfbfSEd Maste       }
1601ac7ddfbfSEd Maste     }
1602ac7ddfbfSEd Maste 
1603435933ddSDimitry Andric     PrintSignalInformation(result.GetOutputStream(), signal_args,
1604435933ddSDimitry Andric                            num_signals_set, signals_sp);
1605ac7ddfbfSEd Maste 
1606ac7ddfbfSEd Maste     if (num_signals_set > 0)
1607ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusSuccessFinishNoResult);
1608ac7ddfbfSEd Maste     else
1609ac7ddfbfSEd Maste       result.SetStatus(eReturnStatusFailed);
1610ac7ddfbfSEd Maste 
1611ac7ddfbfSEd Maste     return result.Succeeded();
1612ac7ddfbfSEd Maste   }
1613ac7ddfbfSEd Maste 
1614ac7ddfbfSEd Maste   CommandOptions m_options;
1615ac7ddfbfSEd Maste };
1616ac7ddfbfSEd Maste 
1617ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1618ac7ddfbfSEd Maste // CommandObjectMultiwordProcess
1619ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1620ac7ddfbfSEd Maste 
1621435933ddSDimitry Andric CommandObjectMultiwordProcess::CommandObjectMultiwordProcess(
1622435933ddSDimitry Andric     CommandInterpreter &interpreter)
1623435933ddSDimitry Andric     : CommandObjectMultiword(
1624435933ddSDimitry Andric           interpreter, "process",
1625435933ddSDimitry Andric           "Commands for interacting with processes on the current platform.",
1626435933ddSDimitry Andric           "process <subcommand> [<subcommand-options>]") {
1627435933ddSDimitry Andric   LoadSubCommand("attach",
1628435933ddSDimitry Andric                  CommandObjectSP(new CommandObjectProcessAttach(interpreter)));
1629435933ddSDimitry Andric   LoadSubCommand("launch",
1630435933ddSDimitry Andric                  CommandObjectSP(new CommandObjectProcessLaunch(interpreter)));
1631435933ddSDimitry Andric   LoadSubCommand("continue", CommandObjectSP(new CommandObjectProcessContinue(
1632435933ddSDimitry Andric                                  interpreter)));
1633435933ddSDimitry Andric   LoadSubCommand("connect",
1634435933ddSDimitry Andric                  CommandObjectSP(new CommandObjectProcessConnect(interpreter)));
1635435933ddSDimitry Andric   LoadSubCommand("detach",
1636435933ddSDimitry Andric                  CommandObjectSP(new CommandObjectProcessDetach(interpreter)));
1637435933ddSDimitry Andric   LoadSubCommand("load",
1638435933ddSDimitry Andric                  CommandObjectSP(new CommandObjectProcessLoad(interpreter)));
1639435933ddSDimitry Andric   LoadSubCommand("unload",
1640435933ddSDimitry Andric                  CommandObjectSP(new CommandObjectProcessUnload(interpreter)));
1641435933ddSDimitry Andric   LoadSubCommand("signal",
1642435933ddSDimitry Andric                  CommandObjectSP(new CommandObjectProcessSignal(interpreter)));
1643435933ddSDimitry Andric   LoadSubCommand("handle",
1644435933ddSDimitry Andric                  CommandObjectSP(new CommandObjectProcessHandle(interpreter)));
1645435933ddSDimitry Andric   LoadSubCommand("status",
1646435933ddSDimitry Andric                  CommandObjectSP(new CommandObjectProcessStatus(interpreter)));
1647435933ddSDimitry Andric   LoadSubCommand("interrupt", CommandObjectSP(new CommandObjectProcessInterrupt(
1648435933ddSDimitry Andric                                   interpreter)));
1649435933ddSDimitry Andric   LoadSubCommand("kill",
1650435933ddSDimitry Andric                  CommandObjectSP(new CommandObjectProcessKill(interpreter)));
1651435933ddSDimitry Andric   LoadSubCommand("plugin",
1652435933ddSDimitry Andric                  CommandObjectSP(new CommandObjectProcessPlugin(interpreter)));
1653435933ddSDimitry Andric   LoadSubCommand("save-core", CommandObjectSP(new CommandObjectProcessSaveCore(
1654435933ddSDimitry Andric                                   interpreter)));
1655ac7ddfbfSEd Maste }
1656ac7ddfbfSEd Maste 
16574bb0738eSEd Maste CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess() = default;
1658