1254721Semaste//===-- CommandObjectProcess.cpp --------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste#include "lldb/lldb-python.h"
11254721Semaste
12254721Semaste#include "CommandObjectProcess.h"
13254721Semaste
14254721Semaste// C Includes
15254721Semaste// C++ Includes
16254721Semaste// Other libraries and framework includes
17254721Semaste// Project includes
18254721Semaste#include "lldb/Breakpoint/Breakpoint.h"
19254721Semaste#include "lldb/Breakpoint/BreakpointLocation.h"
20254721Semaste#include "lldb/Breakpoint/BreakpointSite.h"
21254721Semaste#include "lldb/Core/State.h"
22254721Semaste#include "lldb/Core/Module.h"
23254721Semaste#include "lldb/Host/Host.h"
24254721Semaste#include "lldb/Interpreter/Args.h"
25254721Semaste#include "lldb/Interpreter/Options.h"
26254721Semaste#include "lldb/Interpreter/CommandInterpreter.h"
27254721Semaste#include "lldb/Interpreter/CommandReturnObject.h"
28254721Semaste#include "lldb/Target/Platform.h"
29254721Semaste#include "lldb/Target/Process.h"
30254721Semaste#include "lldb/Target/StopInfo.h"
31254721Semaste#include "lldb/Target/Target.h"
32254721Semaste#include "lldb/Target/Thread.h"
33254721Semaste
34254721Semasteusing namespace lldb;
35254721Semasteusing namespace lldb_private;
36254721Semaste
37254721Semasteclass CommandObjectProcessLaunchOrAttach : public CommandObjectParsed
38254721Semaste{
39254721Semastepublic:
40254721Semaste    CommandObjectProcessLaunchOrAttach (CommandInterpreter &interpreter,
41254721Semaste                                       const char *name,
42254721Semaste                                       const char *help,
43254721Semaste                                       const char *syntax,
44254721Semaste                                       uint32_t flags,
45254721Semaste                                       const char *new_process_action) :
46254721Semaste        CommandObjectParsed (interpreter, name, help, syntax, flags),
47254721Semaste        m_new_process_action (new_process_action) {}
48254721Semaste
49254721Semaste    virtual ~CommandObjectProcessLaunchOrAttach () {}
50254721Semasteprotected:
51254721Semaste    bool
52269024Semaste    StopProcessIfNecessary (Process *process, StateType &state, CommandReturnObject &result)
53254721Semaste    {
54254721Semaste        state = eStateInvalid;
55254721Semaste        if (process)
56254721Semaste        {
57254721Semaste            state = process->GetState();
58254721Semaste
59254721Semaste            if (process->IsAlive() && state != eStateConnected)
60254721Semaste            {
61254721Semaste                char message[1024];
62254721Semaste                if (process->GetState() == eStateAttaching)
63254721Semaste                    ::snprintf (message, sizeof(message), "There is a pending attach, abort it and %s?", m_new_process_action.c_str());
64254721Semaste                else if (process->GetShouldDetach())
65254721Semaste                    ::snprintf (message, sizeof(message), "There is a running process, detach from it and %s?", m_new_process_action.c_str());
66254721Semaste                else
67254721Semaste                    ::snprintf (message, sizeof(message), "There is a running process, kill it and %s?", m_new_process_action.c_str());
68254721Semaste
69254721Semaste                if (!m_interpreter.Confirm (message, true))
70254721Semaste                {
71254721Semaste                    result.SetStatus (eReturnStatusFailed);
72254721Semaste                    return false;
73254721Semaste                }
74254721Semaste                else
75254721Semaste                {
76254721Semaste                    if (process->GetShouldDetach())
77254721Semaste                    {
78254721Semaste                        bool keep_stopped = false;
79254721Semaste                        Error detach_error (process->Detach(keep_stopped));
80254721Semaste                        if (detach_error.Success())
81254721Semaste                        {
82254721Semaste                            result.SetStatus (eReturnStatusSuccessFinishResult);
83254721Semaste                            process = NULL;
84254721Semaste                        }
85254721Semaste                        else
86254721Semaste                        {
87254721Semaste                            result.AppendErrorWithFormat ("Failed to detach from process: %s\n", detach_error.AsCString());
88254721Semaste                            result.SetStatus (eReturnStatusFailed);
89254721Semaste                        }
90254721Semaste                    }
91254721Semaste                    else
92254721Semaste                    {
93254721Semaste                        Error destroy_error (process->Destroy());
94254721Semaste                        if (destroy_error.Success())
95254721Semaste                        {
96254721Semaste                            result.SetStatus (eReturnStatusSuccessFinishResult);
97254721Semaste                            process = NULL;
98254721Semaste                        }
99254721Semaste                        else
100254721Semaste                        {
101254721Semaste                            result.AppendErrorWithFormat ("Failed to kill process: %s\n", destroy_error.AsCString());
102254721Semaste                            result.SetStatus (eReturnStatusFailed);
103254721Semaste                        }
104254721Semaste                    }
105254721Semaste                }
106254721Semaste            }
107254721Semaste        }
108254721Semaste        return result.Succeeded();
109254721Semaste    }
110254721Semaste    std::string m_new_process_action;
111254721Semaste};
112254721Semaste//-------------------------------------------------------------------------
113254721Semaste// CommandObjectProcessLaunch
114254721Semaste//-------------------------------------------------------------------------
115254721Semaste#pragma mark CommandObjectProcessLaunch
116254721Semasteclass CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach
117254721Semaste{
118254721Semastepublic:
119254721Semaste
120254721Semaste    CommandObjectProcessLaunch (CommandInterpreter &interpreter) :
121254721Semaste        CommandObjectProcessLaunchOrAttach (interpreter,
122254721Semaste                                            "process launch",
123254721Semaste                                            "Launch the executable in the debugger.",
124254721Semaste                                            NULL,
125254721Semaste                                            eFlagRequiresTarget,
126254721Semaste                                            "restart"),
127254721Semaste        m_options (interpreter)
128254721Semaste    {
129254721Semaste        CommandArgumentEntry arg;
130254721Semaste        CommandArgumentData run_args_arg;
131254721Semaste
132254721Semaste        // Define the first (and only) variant of this arg.
133254721Semaste        run_args_arg.arg_type = eArgTypeRunArgs;
134254721Semaste        run_args_arg.arg_repetition = eArgRepeatOptional;
135254721Semaste
136254721Semaste        // There is only one variant this argument could be; put it into the argument entry.
137254721Semaste        arg.push_back (run_args_arg);
138254721Semaste
139254721Semaste        // Push the data for the first argument into the m_arguments vector.
140254721Semaste        m_arguments.push_back (arg);
141254721Semaste    }
142254721Semaste
143254721Semaste
144254721Semaste    ~CommandObjectProcessLaunch ()
145254721Semaste    {
146254721Semaste    }
147254721Semaste
148254721Semaste    virtual int
149254721Semaste    HandleArgumentCompletion (Args &input,
150254721Semaste                              int &cursor_index,
151254721Semaste                              int &cursor_char_position,
152254721Semaste                              OptionElementVector &opt_element_vector,
153254721Semaste                              int match_start_point,
154254721Semaste                              int max_return_elements,
155254721Semaste                              bool &word_complete,
156254721Semaste                              StringList &matches)
157254721Semaste    {
158254721Semaste        std::string completion_str (input.GetArgumentAtIndex(cursor_index));
159254721Semaste        completion_str.erase (cursor_char_position);
160254721Semaste
161254721Semaste        CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter,
162254721Semaste                                                             CommandCompletions::eDiskFileCompletion,
163254721Semaste                                                             completion_str.c_str(),
164254721Semaste                                                             match_start_point,
165254721Semaste                                                             max_return_elements,
166254721Semaste                                                             NULL,
167254721Semaste                                                             word_complete,
168254721Semaste                                                             matches);
169254721Semaste        return matches.GetSize();
170254721Semaste    }
171254721Semaste
172254721Semaste    Options *
173254721Semaste    GetOptions ()
174254721Semaste    {
175254721Semaste        return &m_options;
176254721Semaste    }
177254721Semaste
178254721Semaste    virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
179254721Semaste    {
180254721Semaste        // No repeat for "process launch"...
181254721Semaste        return "";
182254721Semaste    }
183254721Semaste
184254721Semasteprotected:
185254721Semaste    bool
186254721Semaste    DoExecute (Args& launch_args, CommandReturnObject &result)
187254721Semaste    {
188254721Semaste        Debugger &debugger = m_interpreter.GetDebugger();
189254721Semaste        Target *target = debugger.GetSelectedTarget().get();
190254721Semaste        // If our listener is NULL, users aren't allows to launch
191269024Semaste        ModuleSP exe_module_sp = target->GetExecutableModule();
192254721Semaste
193269024Semaste        if (exe_module_sp == NULL)
194254721Semaste        {
195254721Semaste            result.AppendError ("no file in target, create a debug target using the 'target create' command");
196254721Semaste            result.SetStatus (eReturnStatusFailed);
197254721Semaste            return false;
198254721Semaste        }
199254721Semaste
200254721Semaste        StateType state = eStateInvalid;
201254721Semaste
202269024Semaste        if (!StopProcessIfNecessary(m_exe_ctx.GetProcessPtr(), state, result))
203254721Semaste            return false;
204254721Semaste
205254721Semaste        const char *target_settings_argv0 = target->GetArg0();
206254721Semaste
207269024Semaste        if (target->GetDisableASLR())
208269024Semaste            m_options.launch_info.GetFlags().Set (eLaunchFlagDisableASLR);
209254721Semaste
210269024Semaste        if (target->GetDisableSTDIO())
211269024Semaste            m_options.launch_info.GetFlags().Set (eLaunchFlagDisableSTDIO);
212269024Semaste
213269024Semaste        Args environment;
214269024Semaste        target->GetEnvironmentAsArgs (environment);
215269024Semaste        if (environment.GetArgumentCount() > 0)
216269024Semaste            m_options.launch_info.GetEnvironmentEntries ().AppendArguments (environment);
217269024Semaste
218254721Semaste        if (target_settings_argv0)
219254721Semaste        {
220254721Semaste            m_options.launch_info.GetArguments().AppendArgument (target_settings_argv0);
221269024Semaste            m_options.launch_info.SetExecutableFile(exe_module_sp->GetPlatformFileSpec(), false);
222254721Semaste        }
223254721Semaste        else
224254721Semaste        {
225269024Semaste            m_options.launch_info.SetExecutableFile(exe_module_sp->GetPlatformFileSpec(), true);
226254721Semaste        }
227254721Semaste
228254721Semaste        if (launch_args.GetArgumentCount() == 0)
229254721Semaste        {
230254721Semaste            Args target_setting_args;
231254721Semaste            if (target->GetRunArguments(target_setting_args))
232254721Semaste                m_options.launch_info.GetArguments().AppendArguments (target_setting_args);
233254721Semaste        }
234254721Semaste        else
235254721Semaste        {
236254721Semaste            m_options.launch_info.GetArguments().AppendArguments (launch_args);
237254721Semaste            // Save the arguments for subsequent runs in the current target.
238254721Semaste            target->SetRunArguments (launch_args);
239254721Semaste        }
240254721Semaste
241269024Semaste        Error error = target->Launch(debugger.GetListener(), m_options.launch_info);
242254721Semaste
243254721Semaste        if (error.Success())
244254721Semaste        {
245269024Semaste            const char *archname = exe_module_sp->GetArchitecture().GetArchitectureName();
246269024Semaste            ProcessSP process_sp (target->GetProcessSP());
247269024Semaste            if (process_sp)
248254721Semaste            {
249269024Semaste                result.AppendMessageWithFormat ("Process %" PRIu64 " launched: '%s' (%s)\n", process_sp->GetID(), exe_module_sp->GetFileSpec().GetPath().c_str(), archname);
250269024Semaste                result.SetStatus (eReturnStatusSuccessFinishResult);
251269024Semaste                result.SetDidChangeProcessState (true);
252254721Semaste            }
253269024Semaste            else
254269024Semaste            {
255269024Semaste                result.AppendError("no error returned from Target::Launch, and target has no process");
256269024Semaste                result.SetStatus (eReturnStatusFailed);
257269024Semaste            }
258254721Semaste        }
259254721Semaste        else
260254721Semaste        {
261269024Semaste            result.AppendError(error.AsCString());
262254721Semaste            result.SetStatus (eReturnStatusFailed);
263254721Semaste        }
264254721Semaste        return result.Succeeded();
265254721Semaste    }
266254721Semaste
267254721Semasteprotected:
268254721Semaste    ProcessLaunchCommandOptions m_options;
269254721Semaste};
270254721Semaste
271254721Semaste
272254721Semaste//#define SET1 LLDB_OPT_SET_1
273254721Semaste//#define SET2 LLDB_OPT_SET_2
274254721Semaste//#define SET3 LLDB_OPT_SET_3
275254721Semaste//
276254721Semaste//OptionDefinition
277254721Semaste//CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
278254721Semaste//{
279263363Semaste//{ SET1 | SET2 | SET3, false, "stop-at-entry", 's', OptionParser::eNoArgument,       NULL, 0, eArgTypeNone,    "Stop at the entry point of the program when launching a process."},
280263363Semaste//{ SET1              , false, "stdin",         'i', OptionParser::eRequiredArgument, NULL, 0, eArgTypeDirectoryName,    "Redirect stdin for the process to <path>."},
281263363Semaste//{ SET1              , false, "stdout",        'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypeDirectoryName,    "Redirect stdout for the process to <path>."},
282263363Semaste//{ SET1              , false, "stderr",        'e', OptionParser::eRequiredArgument, NULL, 0, eArgTypeDirectoryName,    "Redirect stderr for the process to <path>."},
283263363Semaste//{ SET1 | SET2 | SET3, false, "plugin",        'p', OptionParser::eRequiredArgument, NULL, 0, eArgTypePlugin,  "Name of the process plugin you want to use."},
284263363Semaste//{        SET2       , false, "tty",           't', OptionParser::eOptionalArgument, NULL, 0, eArgTypeDirectoryName,    "Start the process in a terminal. If <path> is specified, look for a terminal whose name contains <path>, else start the process in a new terminal."},
285263363Semaste//{               SET3, false, "no-stdio",      'n', OptionParser::eNoArgument,       NULL, 0, eArgTypeNone,    "Do not set up for terminal I/O to go to running process."},
286263363Semaste//{ SET1 | SET2 | SET3, false, "working-dir",   'w', OptionParser::eRequiredArgument, NULL, 0, eArgTypeDirectoryName,    "Set the current working directory to <path> when running the inferior."},
287254721Semaste//{ 0,                  false, NULL,             0,  0,                 NULL, 0, eArgTypeNone,    NULL }
288254721Semaste//};
289254721Semaste//
290254721Semaste//#undef SET1
291254721Semaste//#undef SET2
292254721Semaste//#undef SET3
293254721Semaste
294254721Semaste//-------------------------------------------------------------------------
295254721Semaste// CommandObjectProcessAttach
296254721Semaste//-------------------------------------------------------------------------
297254721Semaste#pragma mark CommandObjectProcessAttach
298254721Semasteclass CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach
299254721Semaste{
300254721Semastepublic:
301254721Semaste
302254721Semaste    class CommandOptions : public Options
303254721Semaste    {
304254721Semaste    public:
305254721Semaste
306254721Semaste        CommandOptions (CommandInterpreter &interpreter) :
307254721Semaste            Options(interpreter)
308254721Semaste        {
309254721Semaste            // Keep default values of all options in one place: OptionParsingStarting ()
310254721Semaste            OptionParsingStarting ();
311254721Semaste        }
312254721Semaste
313254721Semaste        ~CommandOptions ()
314254721Semaste        {
315254721Semaste        }
316254721Semaste
317254721Semaste        Error
318254721Semaste        SetOptionValue (uint32_t option_idx, const char *option_arg)
319254721Semaste        {
320254721Semaste            Error error;
321254721Semaste            const int short_option = m_getopt_table[option_idx].val;
322254721Semaste            bool success = false;
323254721Semaste            switch (short_option)
324254721Semaste            {
325254721Semaste                case 'c':
326254721Semaste                    attach_info.SetContinueOnceAttached(true);
327254721Semaste                    break;
328254721Semaste
329254721Semaste                case 'p':
330254721Semaste                    {
331254721Semaste                        lldb::pid_t pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success);
332254721Semaste                        if (!success || pid == LLDB_INVALID_PROCESS_ID)
333254721Semaste                        {
334254721Semaste                            error.SetErrorStringWithFormat("invalid process ID '%s'", option_arg);
335254721Semaste                        }
336254721Semaste                        else
337254721Semaste                        {
338254721Semaste                            attach_info.SetProcessID (pid);
339254721Semaste                        }
340254721Semaste                    }
341254721Semaste                    break;
342254721Semaste
343254721Semaste                case 'P':
344254721Semaste                    attach_info.SetProcessPluginName (option_arg);
345254721Semaste                    break;
346254721Semaste
347254721Semaste                case 'n':
348254721Semaste                    attach_info.GetExecutableFile().SetFile(option_arg, false);
349254721Semaste                    break;
350254721Semaste
351254721Semaste                case 'w':
352254721Semaste                    attach_info.SetWaitForLaunch(true);
353254721Semaste                    break;
354254721Semaste
355254721Semaste                case 'i':
356254721Semaste                    attach_info.SetIgnoreExisting(false);
357254721Semaste                    break;
358254721Semaste
359254721Semaste                default:
360254721Semaste                    error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
361254721Semaste                    break;
362254721Semaste            }
363254721Semaste            return error;
364254721Semaste        }
365254721Semaste
366254721Semaste        void
367254721Semaste        OptionParsingStarting ()
368254721Semaste        {
369254721Semaste            attach_info.Clear();
370254721Semaste        }
371254721Semaste
372254721Semaste        const OptionDefinition*
373254721Semaste        GetDefinitions ()
374254721Semaste        {
375254721Semaste            return g_option_table;
376254721Semaste        }
377254721Semaste
378254721Semaste        virtual bool
379254721Semaste        HandleOptionArgumentCompletion (Args &input,
380254721Semaste                                        int cursor_index,
381254721Semaste                                        int char_pos,
382254721Semaste                                        OptionElementVector &opt_element_vector,
383254721Semaste                                        int opt_element_index,
384254721Semaste                                        int match_start_point,
385254721Semaste                                        int max_return_elements,
386254721Semaste                                        bool &word_complete,
387254721Semaste                                        StringList &matches)
388254721Semaste        {
389254721Semaste            int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
390254721Semaste            int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
391254721Semaste
392254721Semaste            // We are only completing the name option for now...
393254721Semaste
394254721Semaste            const OptionDefinition *opt_defs = GetDefinitions();
395254721Semaste            if (opt_defs[opt_defs_index].short_option == 'n')
396254721Semaste            {
397254721Semaste                // Are we in the name?
398254721Semaste
399254721Semaste                // Look to see if there is a -P argument provided, and if so use that plugin, otherwise
400254721Semaste                // use the default plugin.
401254721Semaste
402254721Semaste                const char *partial_name = NULL;
403254721Semaste                partial_name = input.GetArgumentAtIndex(opt_arg_pos);
404254721Semaste
405254721Semaste                PlatformSP platform_sp (m_interpreter.GetPlatform (true));
406254721Semaste                if (platform_sp)
407254721Semaste                {
408254721Semaste                    ProcessInstanceInfoList process_infos;
409254721Semaste                    ProcessInstanceInfoMatch match_info;
410254721Semaste                    if (partial_name)
411254721Semaste                    {
412254721Semaste                        match_info.GetProcessInfo().GetExecutableFile().SetFile(partial_name, false);
413254721Semaste                        match_info.SetNameMatchType(eNameMatchStartsWith);
414254721Semaste                    }
415254721Semaste                    platform_sp->FindProcesses (match_info, process_infos);
416254721Semaste                    const size_t num_matches = process_infos.GetSize();
417254721Semaste                    if (num_matches > 0)
418254721Semaste                    {
419254721Semaste                        for (size_t i=0; i<num_matches; ++i)
420254721Semaste                        {
421254721Semaste                            matches.AppendString (process_infos.GetProcessNameAtIndex(i),
422254721Semaste                                                  process_infos.GetProcessNameLengthAtIndex(i));
423254721Semaste                        }
424254721Semaste                    }
425254721Semaste                }
426254721Semaste            }
427254721Semaste
428254721Semaste            return false;
429254721Semaste        }
430254721Semaste
431254721Semaste        // Options table: Required for subclasses of Options.
432254721Semaste
433254721Semaste        static OptionDefinition g_option_table[];
434254721Semaste
435254721Semaste        // Instance variables to hold the values for command options.
436254721Semaste
437254721Semaste        ProcessAttachInfo attach_info;
438254721Semaste    };
439254721Semaste
440254721Semaste    CommandObjectProcessAttach (CommandInterpreter &interpreter) :
441254721Semaste        CommandObjectProcessLaunchOrAttach (interpreter,
442254721Semaste                                            "process attach",
443254721Semaste                                            "Attach to a process.",
444254721Semaste                                            "process attach <cmd-options>",
445254721Semaste                                            0,
446254721Semaste                                            "attach"),
447254721Semaste        m_options (interpreter)
448254721Semaste    {
449254721Semaste    }
450254721Semaste
451254721Semaste    ~CommandObjectProcessAttach ()
452254721Semaste    {
453254721Semaste    }
454254721Semaste
455254721Semaste    Options *
456254721Semaste    GetOptions ()
457254721Semaste    {
458254721Semaste        return &m_options;
459254721Semaste    }
460254721Semaste
461254721Semasteprotected:
462254721Semaste    bool
463254721Semaste    DoExecute (Args& command,
464254721Semaste             CommandReturnObject &result)
465254721Semaste    {
466254721Semaste        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
467254721Semaste        // N.B. The attach should be synchronous.  It doesn't help much to get the prompt back between initiating the attach
468254721Semaste        // and the target actually stopping.  So even if the interpreter is set to be asynchronous, we wait for the stop
469254721Semaste        // ourselves here.
470254721Semaste
471254721Semaste        StateType state = eStateInvalid;
472254721Semaste        Process *process = m_exe_ctx.GetProcessPtr();
473254721Semaste
474254721Semaste        if (!StopProcessIfNecessary (process, state, result))
475254721Semaste            return false;
476254721Semaste
477254721Semaste        if (target == NULL)
478254721Semaste        {
479254721Semaste            // If there isn't a current target create one.
480254721Semaste            TargetSP new_target_sp;
481254721Semaste            Error error;
482254721Semaste
483254721Semaste            error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(),
484254721Semaste                                                                              NULL,
485254721Semaste                                                                              NULL,
486254721Semaste                                                                              false,
487254721Semaste                                                                              NULL, // No platform options
488254721Semaste                                                                              new_target_sp);
489254721Semaste            target = new_target_sp.get();
490254721Semaste            if (target == NULL || error.Fail())
491254721Semaste            {
492254721Semaste                result.AppendError(error.AsCString("Error creating target"));
493254721Semaste                return false;
494254721Semaste            }
495254721Semaste            m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target);
496254721Semaste        }
497254721Semaste
498254721Semaste        // Record the old executable module, we want to issue a warning if the process of attaching changed the
499254721Semaste        // current executable (like somebody said "file foo" then attached to a PID whose executable was bar.)
500254721Semaste
501254721Semaste        ModuleSP old_exec_module_sp = target->GetExecutableModule();
502254721Semaste        ArchSpec old_arch_spec = target->GetArchitecture();
503254721Semaste
504254721Semaste        if (command.GetArgumentCount())
505254721Semaste        {
506254721Semaste            result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: %s\n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
507254721Semaste            result.SetStatus (eReturnStatusFailed);
508254721Semaste        }
509254721Semaste        else
510254721Semaste        {
511254721Semaste            if (state != eStateConnected)
512254721Semaste            {
513254721Semaste                const char *plugin_name = m_options.attach_info.GetProcessPluginName();
514254721Semaste                process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name, NULL).get();
515254721Semaste            }
516254721Semaste
517254721Semaste            if (process)
518254721Semaste            {
519254721Semaste                Error error;
520254721Semaste                // If no process info was specified, then use the target executable
521254721Semaste                // name as the process to attach to by default
522254721Semaste                if (!m_options.attach_info.ProcessInfoSpecified ())
523254721Semaste                {
524254721Semaste                    if (old_exec_module_sp)
525254721Semaste                        m_options.attach_info.GetExecutableFile().GetFilename() = old_exec_module_sp->GetPlatformFileSpec().GetFilename();
526254721Semaste
527254721Semaste                    if (!m_options.attach_info.ProcessInfoSpecified ())
528254721Semaste                    {
529254721Semaste                        error.SetErrorString ("no process specified, create a target with a file, or specify the --pid or --name command option");
530254721Semaste                    }
531254721Semaste                }
532254721Semaste
533254721Semaste                if (error.Success())
534254721Semaste                {
535269024Semaste                    ListenerSP listener_sp (new Listener("lldb.CommandObjectProcessAttach.DoExecute.attach.hijack"));
536269024Semaste                    m_options.attach_info.SetHijackListener(listener_sp);
537269024Semaste                    process->HijackProcessEvents(listener_sp.get());
538254721Semaste                    error = process->Attach (m_options.attach_info);
539254721Semaste
540254721Semaste                    if (error.Success())
541254721Semaste                    {
542254721Semaste                        result.SetStatus (eReturnStatusSuccessContinuingNoResult);
543269024Semaste                        StateType state = process->WaitForProcessToStop (NULL, NULL, false, listener_sp.get());
544269024Semaste
545269024Semaste                        process->RestoreProcessEvents();
546269024Semaste
547269024Semaste                        result.SetDidChangeProcessState (true);
548269024Semaste
549269024Semaste                        if (state == eStateStopped)
550269024Semaste                        {
551269024Semaste                            result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state));
552269024Semaste                            result.SetStatus (eReturnStatusSuccessFinishNoResult);
553269024Semaste                        }
554269024Semaste                        else
555269024Semaste                        {
556269024Semaste                            result.AppendError ("attach failed: process did not stop (no such process or permission problem?)");
557269024Semaste                            process->Destroy();
558269024Semaste                            result.SetStatus (eReturnStatusFailed);
559269024Semaste                        }
560254721Semaste                    }
561254721Semaste                    else
562254721Semaste                    {
563254721Semaste                        result.AppendErrorWithFormat ("attach failed: %s\n", error.AsCString());
564254721Semaste                        result.SetStatus (eReturnStatusFailed);
565254721Semaste                    }
566254721Semaste                }
567254721Semaste            }
568254721Semaste        }
569254721Semaste
570254721Semaste        if (result.Succeeded())
571254721Semaste        {
572254721Semaste            // Okay, we're done.  Last step is to warn if the executable module has changed:
573254721Semaste            char new_path[PATH_MAX];
574254721Semaste            ModuleSP new_exec_module_sp (target->GetExecutableModule());
575254721Semaste            if (!old_exec_module_sp)
576254721Semaste            {
577254721Semaste                // We might not have a module if we attached to a raw pid...
578254721Semaste                if (new_exec_module_sp)
579254721Semaste                {
580254721Semaste                    new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX);
581254721Semaste                    result.AppendMessageWithFormat("Executable module set to \"%s\".\n", new_path);
582254721Semaste                }
583254721Semaste            }
584254721Semaste            else if (old_exec_module_sp->GetFileSpec() != new_exec_module_sp->GetFileSpec())
585254721Semaste            {
586254721Semaste                char old_path[PATH_MAX];
587254721Semaste
588254721Semaste                old_exec_module_sp->GetFileSpec().GetPath (old_path, PATH_MAX);
589254721Semaste                new_exec_module_sp->GetFileSpec().GetPath (new_path, PATH_MAX);
590254721Semaste
591254721Semaste                result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n",
592254721Semaste                                                    old_path, new_path);
593254721Semaste            }
594254721Semaste
595254721Semaste            if (!old_arch_spec.IsValid())
596254721Semaste            {
597254721Semaste                result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().GetTriple().getTriple().c_str());
598254721Semaste            }
599254721Semaste            else if (!old_arch_spec.IsExactMatch(target->GetArchitecture()))
600254721Semaste            {
601254721Semaste                result.AppendWarningWithFormat("Architecture changed from %s to %s.\n",
602254721Semaste                                               old_arch_spec.GetTriple().getTriple().c_str(),
603254721Semaste                                               target->GetArchitecture().GetTriple().getTriple().c_str());
604254721Semaste            }
605254721Semaste
606254721Semaste            // This supports the use-case scenario of immediately continuing the process once attached.
607254721Semaste            if (m_options.attach_info.GetContinueOnceAttached())
608254721Semaste                m_interpreter.HandleCommand("process continue", eLazyBoolNo, result);
609254721Semaste        }
610254721Semaste        return result.Succeeded();
611254721Semaste    }
612254721Semaste
613254721Semaste    CommandOptions m_options;
614254721Semaste};
615254721Semaste
616254721Semaste
617254721SemasteOptionDefinition
618254721SemasteCommandObjectProcessAttach::CommandOptions::g_option_table[] =
619254721Semaste{
620263363Semaste{ LLDB_OPT_SET_ALL, false, "continue",'c', OptionParser::eNoArgument,         NULL, 0, eArgTypeNone,         "Immediately continue the process once attached."},
621263363Semaste{ LLDB_OPT_SET_ALL, false, "plugin",  'P', OptionParser::eRequiredArgument,   NULL, 0, eArgTypePlugin,       "Name of the process plugin you want to use."},
622263363Semaste{ LLDB_OPT_SET_1,   false, "pid",     'p', OptionParser::eRequiredArgument,   NULL, 0, eArgTypePid,          "The process ID of an existing process to attach to."},
623263363Semaste{ LLDB_OPT_SET_2,   false, "name",    'n', OptionParser::eRequiredArgument,   NULL, 0, eArgTypeProcessName,  "The name of the process to attach to."},
624263363Semaste{ LLDB_OPT_SET_2,   false, "include-existing", 'i', OptionParser::eNoArgument, NULL, 0, eArgTypeNone,         "Include existing processes when doing attach -w."},
625263363Semaste{ LLDB_OPT_SET_2,   false, "waitfor", 'w', OptionParser::eNoArgument,         NULL, 0, eArgTypeNone,         "Wait for the process with <process-name> to launch."},
626254721Semaste{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
627254721Semaste};
628254721Semaste
629254721Semaste//-------------------------------------------------------------------------
630254721Semaste// CommandObjectProcessContinue
631254721Semaste//-------------------------------------------------------------------------
632254721Semaste#pragma mark CommandObjectProcessContinue
633254721Semaste
634254721Semasteclass CommandObjectProcessContinue : public CommandObjectParsed
635254721Semaste{
636254721Semastepublic:
637254721Semaste
638254721Semaste    CommandObjectProcessContinue (CommandInterpreter &interpreter) :
639254721Semaste        CommandObjectParsed (interpreter,
640254721Semaste                             "process continue",
641254721Semaste                             "Continue execution of all threads in the current process.",
642254721Semaste                             "process continue",
643254721Semaste                             eFlagRequiresProcess       |
644254721Semaste                             eFlagTryTargetAPILock      |
645254721Semaste                             eFlagProcessMustBeLaunched |
646254721Semaste                             eFlagProcessMustBePaused   ),
647254721Semaste        m_options(interpreter)
648254721Semaste    {
649254721Semaste    }
650254721Semaste
651254721Semaste
652254721Semaste    ~CommandObjectProcessContinue ()
653254721Semaste    {
654254721Semaste    }
655254721Semaste
656254721Semasteprotected:
657254721Semaste
658254721Semaste    class CommandOptions : public Options
659254721Semaste    {
660254721Semaste    public:
661254721Semaste
662254721Semaste        CommandOptions (CommandInterpreter &interpreter) :
663254721Semaste            Options(interpreter)
664254721Semaste        {
665254721Semaste            // Keep default values of all options in one place: OptionParsingStarting ()
666254721Semaste            OptionParsingStarting ();
667254721Semaste        }
668254721Semaste
669254721Semaste        ~CommandOptions ()
670254721Semaste        {
671254721Semaste        }
672254721Semaste
673254721Semaste        Error
674254721Semaste        SetOptionValue (uint32_t option_idx, const char *option_arg)
675254721Semaste        {
676254721Semaste            Error error;
677254721Semaste            const int short_option = m_getopt_table[option_idx].val;
678254721Semaste            bool success = false;
679254721Semaste            switch (short_option)
680254721Semaste            {
681254721Semaste                case 'i':
682254721Semaste                    m_ignore = Args::StringToUInt32 (option_arg, 0, 0, &success);
683254721Semaste                    if (!success)
684254721Semaste                        error.SetErrorStringWithFormat ("invalid value for ignore option: \"%s\", should be a number.", option_arg);
685254721Semaste                    break;
686254721Semaste
687254721Semaste                default:
688254721Semaste                    error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
689254721Semaste                    break;
690254721Semaste            }
691254721Semaste            return error;
692254721Semaste        }
693254721Semaste
694254721Semaste        void
695254721Semaste        OptionParsingStarting ()
696254721Semaste        {
697254721Semaste            m_ignore = 0;
698254721Semaste        }
699254721Semaste
700254721Semaste        const OptionDefinition*
701254721Semaste        GetDefinitions ()
702254721Semaste        {
703254721Semaste            return g_option_table;
704254721Semaste        }
705254721Semaste
706254721Semaste        // Options table: Required for subclasses of Options.
707254721Semaste
708254721Semaste        static OptionDefinition g_option_table[];
709254721Semaste
710254721Semaste        uint32_t m_ignore;
711254721Semaste    };
712254721Semaste
713254721Semaste    bool
714254721Semaste    DoExecute (Args& command, CommandReturnObject &result)
715254721Semaste    {
716254721Semaste        Process *process = m_exe_ctx.GetProcessPtr();
717254721Semaste        bool synchronous_execution = m_interpreter.GetSynchronous ();
718254721Semaste        StateType state = process->GetState();
719254721Semaste        if (state == eStateStopped)
720254721Semaste        {
721254721Semaste            if (command.GetArgumentCount() != 0)
722254721Semaste            {
723254721Semaste                result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str());
724254721Semaste                result.SetStatus (eReturnStatusFailed);
725254721Semaste                return false;
726254721Semaste            }
727254721Semaste
728254721Semaste            if (m_options.m_ignore > 0)
729254721Semaste            {
730254721Semaste                ThreadSP sel_thread_sp(process->GetThreadList().GetSelectedThread());
731254721Semaste                if (sel_thread_sp)
732254721Semaste                {
733254721Semaste                    StopInfoSP stop_info_sp = sel_thread_sp->GetStopInfo();
734254721Semaste                    if (stop_info_sp && stop_info_sp->GetStopReason() == eStopReasonBreakpoint)
735254721Semaste                    {
736254721Semaste                        lldb::break_id_t bp_site_id = (lldb::break_id_t)stop_info_sp->GetValue();
737254721Semaste                        BreakpointSiteSP bp_site_sp(process->GetBreakpointSiteList().FindByID(bp_site_id));
738254721Semaste                        if (bp_site_sp)
739254721Semaste                        {
740254721Semaste                            const size_t num_owners = bp_site_sp->GetNumberOfOwners();
741254721Semaste                            for (size_t i = 0; i < num_owners; i++)
742254721Semaste                            {
743254721Semaste                                Breakpoint &bp_ref = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint();
744254721Semaste                                if (!bp_ref.IsInternal())
745254721Semaste                                {
746254721Semaste                                    bp_ref.SetIgnoreCount(m_options.m_ignore);
747254721Semaste                                }
748254721Semaste                            }
749254721Semaste                        }
750254721Semaste                    }
751254721Semaste                }
752254721Semaste            }
753254721Semaste
754254721Semaste            {  // Scope for thread list mutex:
755254721Semaste                Mutex::Locker locker (process->GetThreadList().GetMutex());
756254721Semaste                const uint32_t num_threads = process->GetThreadList().GetSize();
757254721Semaste
758254721Semaste                // Set the actions that the threads should each take when resuming
759254721Semaste                for (uint32_t idx=0; idx<num_threads; ++idx)
760254721Semaste                {
761254721Semaste                    process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning);
762254721Semaste                }
763254721Semaste            }
764254721Semaste
765254721Semaste            Error error(process->Resume());
766254721Semaste            if (error.Success())
767254721Semaste            {
768254721Semaste                result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID());
769254721Semaste                if (synchronous_execution)
770254721Semaste                {
771254721Semaste                    state = process->WaitForProcessToStop (NULL);
772254721Semaste
773254721Semaste                    result.SetDidChangeProcessState (true);
774254721Semaste                    result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state));
775254721Semaste                    result.SetStatus (eReturnStatusSuccessFinishNoResult);
776254721Semaste                }
777254721Semaste                else
778254721Semaste                {
779254721Semaste                    result.SetStatus (eReturnStatusSuccessContinuingNoResult);
780254721Semaste                }
781254721Semaste            }
782254721Semaste            else
783254721Semaste            {
784254721Semaste                result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
785254721Semaste                result.SetStatus (eReturnStatusFailed);
786254721Semaste            }
787254721Semaste        }
788254721Semaste        else
789254721Semaste        {
790254721Semaste            result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
791254721Semaste                                         StateAsCString(state));
792254721Semaste            result.SetStatus (eReturnStatusFailed);
793254721Semaste        }
794254721Semaste        return result.Succeeded();
795254721Semaste    }
796254721Semaste
797254721Semaste    Options *
798254721Semaste    GetOptions ()
799254721Semaste    {
800254721Semaste        return &m_options;
801254721Semaste    }
802254721Semaste
803254721Semaste    CommandOptions m_options;
804254721Semaste
805254721Semaste};
806254721Semaste
807254721SemasteOptionDefinition
808254721SemasteCommandObjectProcessContinue::CommandOptions::g_option_table[] =
809254721Semaste{
810263363Semaste{ LLDB_OPT_SET_ALL, false, "ignore-count",'i', OptionParser::eRequiredArgument,         NULL, 0, eArgTypeUnsignedInteger,
811254721Semaste                           "Ignore <N> crossings of the breakpoint (if it exists) for the currently selected thread."},
812254721Semaste{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
813254721Semaste};
814254721Semaste
815254721Semaste//-------------------------------------------------------------------------
816254721Semaste// CommandObjectProcessDetach
817254721Semaste//-------------------------------------------------------------------------
818254721Semaste#pragma mark CommandObjectProcessDetach
819254721Semaste
820254721Semasteclass CommandObjectProcessDetach : public CommandObjectParsed
821254721Semaste{
822254721Semastepublic:
823254721Semaste    class CommandOptions : public Options
824254721Semaste    {
825254721Semaste    public:
826254721Semaste
827254721Semaste        CommandOptions (CommandInterpreter &interpreter) :
828254721Semaste            Options (interpreter)
829254721Semaste        {
830254721Semaste            OptionParsingStarting ();
831254721Semaste        }
832254721Semaste
833254721Semaste        ~CommandOptions ()
834254721Semaste        {
835254721Semaste        }
836254721Semaste
837254721Semaste        Error
838254721Semaste        SetOptionValue (uint32_t option_idx, const char *option_arg)
839254721Semaste        {
840254721Semaste            Error error;
841254721Semaste            const int short_option = m_getopt_table[option_idx].val;
842254721Semaste
843254721Semaste            switch (short_option)
844254721Semaste            {
845254721Semaste                case 's':
846254721Semaste                    bool tmp_result;
847254721Semaste                    bool success;
848254721Semaste                    tmp_result = Args::StringToBoolean(option_arg, false, &success);
849254721Semaste                    if (!success)
850254721Semaste                        error.SetErrorStringWithFormat("invalid boolean option: \"%s\"", option_arg);
851254721Semaste                    else
852254721Semaste                    {
853254721Semaste                        if (tmp_result)
854254721Semaste                            m_keep_stopped = eLazyBoolYes;
855254721Semaste                        else
856254721Semaste                            m_keep_stopped = eLazyBoolNo;
857254721Semaste                    }
858254721Semaste                    break;
859254721Semaste                default:
860254721Semaste                    error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
861254721Semaste                    break;
862254721Semaste            }
863254721Semaste            return error;
864254721Semaste        }
865254721Semaste
866254721Semaste        void
867254721Semaste        OptionParsingStarting ()
868254721Semaste        {
869254721Semaste            m_keep_stopped = eLazyBoolCalculate;
870254721Semaste        }
871254721Semaste
872254721Semaste        const OptionDefinition*
873254721Semaste        GetDefinitions ()
874254721Semaste        {
875254721Semaste            return g_option_table;
876254721Semaste        }
877254721Semaste
878254721Semaste        // Options table: Required for subclasses of Options.
879254721Semaste
880254721Semaste        static OptionDefinition g_option_table[];
881254721Semaste
882254721Semaste        // Instance variables to hold the values for command options.
883254721Semaste        LazyBool m_keep_stopped;
884254721Semaste    };
885254721Semaste
886254721Semaste    CommandObjectProcessDetach (CommandInterpreter &interpreter) :
887254721Semaste        CommandObjectParsed (interpreter,
888254721Semaste                             "process detach",
889254721Semaste                             "Detach from the current process being debugged.",
890254721Semaste                             "process detach",
891254721Semaste                             eFlagRequiresProcess      |
892254721Semaste                             eFlagTryTargetAPILock     |
893254721Semaste                             eFlagProcessMustBeLaunched),
894254721Semaste        m_options(interpreter)
895254721Semaste    {
896254721Semaste    }
897254721Semaste
898254721Semaste    ~CommandObjectProcessDetach ()
899254721Semaste    {
900254721Semaste    }
901254721Semaste
902254721Semaste    Options *
903254721Semaste    GetOptions ()
904254721Semaste    {
905254721Semaste        return &m_options;
906254721Semaste    }
907254721Semaste
908254721Semaste
909254721Semasteprotected:
910254721Semaste    bool
911254721Semaste    DoExecute (Args& command, CommandReturnObject &result)
912254721Semaste    {
913254721Semaste        Process *process = m_exe_ctx.GetProcessPtr();
914254721Semaste        result.AppendMessageWithFormat ("Detaching from process %" PRIu64 "\n", process->GetID());
915254721Semaste        // FIXME: This will be a Command Option:
916254721Semaste        bool keep_stopped;
917254721Semaste        if (m_options.m_keep_stopped == eLazyBoolCalculate)
918254721Semaste        {
919254721Semaste            // Check the process default:
920254721Semaste            if (process->GetDetachKeepsStopped())
921254721Semaste                keep_stopped = true;
922254721Semaste            else
923254721Semaste                keep_stopped = false;
924254721Semaste        }
925254721Semaste        else if (m_options.m_keep_stopped == eLazyBoolYes)
926254721Semaste            keep_stopped = true;
927254721Semaste        else
928254721Semaste            keep_stopped = false;
929254721Semaste
930254721Semaste        Error error (process->Detach(keep_stopped));
931254721Semaste        if (error.Success())
932254721Semaste        {
933254721Semaste            result.SetStatus (eReturnStatusSuccessFinishResult);
934254721Semaste        }
935254721Semaste        else
936254721Semaste        {
937254721Semaste            result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString());
938254721Semaste            result.SetStatus (eReturnStatusFailed);
939254721Semaste            return false;
940254721Semaste        }
941254721Semaste        return result.Succeeded();
942254721Semaste    }
943254721Semaste
944254721Semaste    CommandOptions m_options;
945254721Semaste};
946254721Semaste
947254721SemasteOptionDefinition
948254721SemasteCommandObjectProcessDetach::CommandOptions::g_option_table[] =
949254721Semaste{
950263363Semaste{ LLDB_OPT_SET_1, false, "keep-stopped",   's', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "Whether or not the process should be kept stopped on detach (if possible)." },
951254721Semaste{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
952254721Semaste};
953254721Semaste
954254721Semaste//-------------------------------------------------------------------------
955254721Semaste// CommandObjectProcessConnect
956254721Semaste//-------------------------------------------------------------------------
957254721Semaste#pragma mark CommandObjectProcessConnect
958254721Semaste
959254721Semasteclass CommandObjectProcessConnect : public CommandObjectParsed
960254721Semaste{
961254721Semastepublic:
962254721Semaste
963254721Semaste    class CommandOptions : public Options
964254721Semaste    {
965254721Semaste    public:
966254721Semaste
967254721Semaste        CommandOptions (CommandInterpreter &interpreter) :
968254721Semaste            Options(interpreter)
969254721Semaste        {
970254721Semaste            // Keep default values of all options in one place: OptionParsingStarting ()
971254721Semaste            OptionParsingStarting ();
972254721Semaste        }
973254721Semaste
974254721Semaste        ~CommandOptions ()
975254721Semaste        {
976254721Semaste        }
977254721Semaste
978254721Semaste        Error
979254721Semaste        SetOptionValue (uint32_t option_idx, const char *option_arg)
980254721Semaste        {
981254721Semaste            Error error;
982254721Semaste            const int short_option = m_getopt_table[option_idx].val;
983254721Semaste
984254721Semaste            switch (short_option)
985254721Semaste            {
986254721Semaste            case 'p':
987254721Semaste                plugin_name.assign (option_arg);
988254721Semaste                break;
989254721Semaste
990254721Semaste            default:
991254721Semaste                error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
992254721Semaste                break;
993254721Semaste            }
994254721Semaste            return error;
995254721Semaste        }
996254721Semaste
997254721Semaste        void
998254721Semaste        OptionParsingStarting ()
999254721Semaste        {
1000254721Semaste            plugin_name.clear();
1001254721Semaste        }
1002254721Semaste
1003254721Semaste        const OptionDefinition*
1004254721Semaste        GetDefinitions ()
1005254721Semaste        {
1006254721Semaste            return g_option_table;
1007254721Semaste        }
1008254721Semaste
1009254721Semaste        // Options table: Required for subclasses of Options.
1010254721Semaste
1011254721Semaste        static OptionDefinition g_option_table[];
1012254721Semaste
1013254721Semaste        // Instance variables to hold the values for command options.
1014254721Semaste
1015254721Semaste        std::string plugin_name;
1016254721Semaste    };
1017254721Semaste
1018254721Semaste    CommandObjectProcessConnect (CommandInterpreter &interpreter) :
1019254721Semaste        CommandObjectParsed (interpreter,
1020254721Semaste                             "process connect",
1021254721Semaste                             "Connect to a remote debug service.",
1022254721Semaste                             "process connect <remote-url>",
1023254721Semaste                             0),
1024254721Semaste        m_options (interpreter)
1025254721Semaste    {
1026254721Semaste    }
1027254721Semaste
1028254721Semaste    ~CommandObjectProcessConnect ()
1029254721Semaste    {
1030254721Semaste    }
1031254721Semaste
1032254721Semaste
1033254721Semaste    Options *
1034254721Semaste    GetOptions ()
1035254721Semaste    {
1036254721Semaste        return &m_options;
1037254721Semaste    }
1038254721Semaste
1039254721Semasteprotected:
1040254721Semaste    bool
1041254721Semaste    DoExecute (Args& command,
1042254721Semaste             CommandReturnObject &result)
1043254721Semaste    {
1044254721Semaste
1045254721Semaste        TargetSP target_sp (m_interpreter.GetDebugger().GetSelectedTarget());
1046254721Semaste        Error error;
1047254721Semaste        Process *process = m_exe_ctx.GetProcessPtr();
1048254721Semaste        if (process)
1049254721Semaste        {
1050254721Semaste            if (process->IsAlive())
1051254721Semaste            {
1052254721Semaste                result.AppendErrorWithFormat ("Process %" PRIu64 " is currently being debugged, kill the process before connecting.\n",
1053254721Semaste                                              process->GetID());
1054254721Semaste                result.SetStatus (eReturnStatusFailed);
1055254721Semaste                return false;
1056254721Semaste            }
1057254721Semaste        }
1058254721Semaste
1059254721Semaste        if (!target_sp)
1060254721Semaste        {
1061254721Semaste            // If there isn't a current target create one.
1062254721Semaste
1063254721Semaste            error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(),
1064254721Semaste                                                                              NULL,
1065254721Semaste                                                                              NULL,
1066254721Semaste                                                                              false,
1067254721Semaste                                                                              NULL, // No platform options
1068254721Semaste                                                                              target_sp);
1069254721Semaste            if (!target_sp || error.Fail())
1070254721Semaste            {
1071254721Semaste                result.AppendError(error.AsCString("Error creating target"));
1072254721Semaste                result.SetStatus (eReturnStatusFailed);
1073254721Semaste                return false;
1074254721Semaste            }
1075254721Semaste            m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target_sp.get());
1076254721Semaste        }
1077254721Semaste
1078254721Semaste        if (command.GetArgumentCount() == 1)
1079254721Semaste        {
1080254721Semaste            const char *plugin_name = NULL;
1081254721Semaste            if (!m_options.plugin_name.empty())
1082254721Semaste                plugin_name = m_options.plugin_name.c_str();
1083254721Semaste
1084254721Semaste            const char *remote_url = command.GetArgumentAtIndex(0);
1085254721Semaste            process = target_sp->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name, NULL).get();
1086254721Semaste
1087254721Semaste            if (process)
1088254721Semaste            {
1089269024Semaste                error = process->ConnectRemote (process->GetTarget().GetDebugger().GetOutputFile().get(), remote_url);
1090254721Semaste
1091254721Semaste                if (error.Fail())
1092254721Semaste                {
1093254721Semaste                    result.AppendError(error.AsCString("Remote connect failed"));
1094254721Semaste                    result.SetStatus (eReturnStatusFailed);
1095254721Semaste                    target_sp->DeleteCurrentProcess();
1096254721Semaste                    return false;
1097254721Semaste                }
1098254721Semaste            }
1099254721Semaste            else
1100254721Semaste            {
1101254721Semaste                result.AppendErrorWithFormat ("Unable to find process plug-in for remote URL '%s'.\nPlease specify a process plug-in name with the --plugin option, or specify an object file using the \"file\" command.\n",
1102254721Semaste                                              remote_url);
1103254721Semaste                result.SetStatus (eReturnStatusFailed);
1104254721Semaste            }
1105254721Semaste        }
1106254721Semaste        else
1107254721Semaste        {
1108254721Semaste            result.AppendErrorWithFormat ("'%s' takes exactly one argument:\nUsage: %s\n",
1109254721Semaste                                          m_cmd_name.c_str(),
1110254721Semaste                                          m_cmd_syntax.c_str());
1111254721Semaste            result.SetStatus (eReturnStatusFailed);
1112254721Semaste        }
1113254721Semaste        return result.Succeeded();
1114254721Semaste    }
1115254721Semaste
1116254721Semaste    CommandOptions m_options;
1117254721Semaste};
1118254721Semaste
1119254721SemasteOptionDefinition
1120254721SemasteCommandObjectProcessConnect::CommandOptions::g_option_table[] =
1121254721Semaste{
1122263363Semaste    { LLDB_OPT_SET_ALL, false, "plugin", 'p', OptionParser::eRequiredArgument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
1123254721Semaste    { 0,                false, NULL,      0 , 0,                 NULL, 0, eArgTypeNone,   NULL }
1124254721Semaste};
1125254721Semaste
1126254721Semaste//-------------------------------------------------------------------------
1127254721Semaste// CommandObjectProcessPlugin
1128254721Semaste//-------------------------------------------------------------------------
1129254721Semaste#pragma mark CommandObjectProcessPlugin
1130254721Semaste
1131254721Semasteclass CommandObjectProcessPlugin : public CommandObjectProxy
1132254721Semaste{
1133254721Semastepublic:
1134254721Semaste
1135254721Semaste    CommandObjectProcessPlugin (CommandInterpreter &interpreter) :
1136254721Semaste        CommandObjectProxy (interpreter,
1137254721Semaste                            "process plugin",
1138254721Semaste                            "Send a custom command to the current process plug-in.",
1139254721Semaste                            "process plugin <args>",
1140254721Semaste                            0)
1141254721Semaste    {
1142254721Semaste    }
1143254721Semaste
1144254721Semaste    ~CommandObjectProcessPlugin ()
1145254721Semaste    {
1146254721Semaste    }
1147254721Semaste
1148254721Semaste    virtual CommandObject *
1149254721Semaste    GetProxyCommandObject()
1150254721Semaste    {
1151254721Semaste        Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
1152254721Semaste        if (process)
1153254721Semaste            return process->GetPluginCommandObject();
1154254721Semaste        return NULL;
1155254721Semaste    }
1156254721Semaste};
1157254721Semaste
1158254721Semaste
1159254721Semaste//-------------------------------------------------------------------------
1160254721Semaste// CommandObjectProcessLoad
1161254721Semaste//-------------------------------------------------------------------------
1162254721Semaste#pragma mark CommandObjectProcessLoad
1163254721Semaste
1164254721Semasteclass CommandObjectProcessLoad : public CommandObjectParsed
1165254721Semaste{
1166254721Semastepublic:
1167254721Semaste
1168254721Semaste    CommandObjectProcessLoad (CommandInterpreter &interpreter) :
1169254721Semaste        CommandObjectParsed (interpreter,
1170254721Semaste                             "process load",
1171254721Semaste                             "Load a shared library into the current process.",
1172254721Semaste                             "process load <filename> [<filename> ...]",
1173254721Semaste                             eFlagRequiresProcess       |
1174254721Semaste                             eFlagTryTargetAPILock      |
1175254721Semaste                             eFlagProcessMustBeLaunched |
1176254721Semaste                             eFlagProcessMustBePaused   )
1177254721Semaste    {
1178254721Semaste    }
1179254721Semaste
1180254721Semaste    ~CommandObjectProcessLoad ()
1181254721Semaste    {
1182254721Semaste    }
1183254721Semaste
1184254721Semasteprotected:
1185254721Semaste    bool
1186254721Semaste    DoExecute (Args& command,
1187254721Semaste             CommandReturnObject &result)
1188254721Semaste    {
1189254721Semaste        Process *process = m_exe_ctx.GetProcessPtr();
1190254721Semaste
1191254721Semaste        const size_t argc = command.GetArgumentCount();
1192254721Semaste
1193254721Semaste        for (uint32_t i=0; i<argc; ++i)
1194254721Semaste        {
1195254721Semaste            Error error;
1196254721Semaste            const char *image_path = command.GetArgumentAtIndex(i);
1197254721Semaste            FileSpec image_spec (image_path, false);
1198254721Semaste            process->GetTarget().GetPlatform()->ResolveRemotePath(image_spec, image_spec);
1199254721Semaste            uint32_t image_token = process->LoadImage(image_spec, error);
1200254721Semaste            if (image_token != LLDB_INVALID_IMAGE_TOKEN)
1201254721Semaste            {
1202254721Semaste                result.AppendMessageWithFormat ("Loading \"%s\"...ok\nImage %u loaded.\n", image_path, image_token);
1203254721Semaste                result.SetStatus (eReturnStatusSuccessFinishResult);
1204254721Semaste            }
1205254721Semaste            else
1206254721Semaste            {
1207254721Semaste                result.AppendErrorWithFormat ("failed to load '%s': %s", image_path, error.AsCString());
1208254721Semaste                result.SetStatus (eReturnStatusFailed);
1209254721Semaste            }
1210254721Semaste        }
1211254721Semaste        return result.Succeeded();
1212254721Semaste    }
1213254721Semaste};
1214254721Semaste
1215254721Semaste
1216254721Semaste//-------------------------------------------------------------------------
1217254721Semaste// CommandObjectProcessUnload
1218254721Semaste//-------------------------------------------------------------------------
1219254721Semaste#pragma mark CommandObjectProcessUnload
1220254721Semaste
1221254721Semasteclass CommandObjectProcessUnload : public CommandObjectParsed
1222254721Semaste{
1223254721Semastepublic:
1224254721Semaste
1225254721Semaste    CommandObjectProcessUnload (CommandInterpreter &interpreter) :
1226254721Semaste        CommandObjectParsed (interpreter,
1227254721Semaste                             "process unload",
1228254721Semaste                             "Unload a shared library from the current process using the index returned by a previous call to \"process load\".",
1229254721Semaste                             "process unload <index>",
1230254721Semaste                             eFlagRequiresProcess       |
1231254721Semaste                             eFlagTryTargetAPILock      |
1232254721Semaste                             eFlagProcessMustBeLaunched |
1233254721Semaste                             eFlagProcessMustBePaused   )
1234254721Semaste    {
1235254721Semaste    }
1236254721Semaste
1237254721Semaste    ~CommandObjectProcessUnload ()
1238254721Semaste    {
1239254721Semaste    }
1240254721Semaste
1241254721Semasteprotected:
1242254721Semaste    bool
1243254721Semaste    DoExecute (Args& command,
1244254721Semaste             CommandReturnObject &result)
1245254721Semaste    {
1246254721Semaste        Process *process = m_exe_ctx.GetProcessPtr();
1247254721Semaste
1248254721Semaste        const size_t argc = command.GetArgumentCount();
1249254721Semaste
1250254721Semaste        for (uint32_t i=0; i<argc; ++i)
1251254721Semaste        {
1252254721Semaste            const char *image_token_cstr = command.GetArgumentAtIndex(i);
1253254721Semaste            uint32_t image_token = Args::StringToUInt32(image_token_cstr, LLDB_INVALID_IMAGE_TOKEN, 0);
1254254721Semaste            if (image_token == LLDB_INVALID_IMAGE_TOKEN)
1255254721Semaste            {
1256254721Semaste                result.AppendErrorWithFormat ("invalid image index argument '%s'", image_token_cstr);
1257254721Semaste                result.SetStatus (eReturnStatusFailed);
1258254721Semaste                break;
1259254721Semaste            }
1260254721Semaste            else
1261254721Semaste            {
1262254721Semaste                Error error (process->UnloadImage(image_token));
1263254721Semaste                if (error.Success())
1264254721Semaste                {
1265254721Semaste                    result.AppendMessageWithFormat ("Unloading shared library with index %u...ok\n", image_token);
1266254721Semaste                    result.SetStatus (eReturnStatusSuccessFinishResult);
1267254721Semaste                }
1268254721Semaste                else
1269254721Semaste                {
1270254721Semaste                    result.AppendErrorWithFormat ("failed to unload image: %s", error.AsCString());
1271254721Semaste                    result.SetStatus (eReturnStatusFailed);
1272254721Semaste                    break;
1273254721Semaste                }
1274254721Semaste            }
1275254721Semaste        }
1276254721Semaste        return result.Succeeded();
1277254721Semaste    }
1278254721Semaste};
1279254721Semaste
1280254721Semaste//-------------------------------------------------------------------------
1281254721Semaste// CommandObjectProcessSignal
1282254721Semaste//-------------------------------------------------------------------------
1283254721Semaste#pragma mark CommandObjectProcessSignal
1284254721Semaste
1285254721Semasteclass CommandObjectProcessSignal : public CommandObjectParsed
1286254721Semaste{
1287254721Semastepublic:
1288254721Semaste
1289254721Semaste    CommandObjectProcessSignal (CommandInterpreter &interpreter) :
1290254721Semaste        CommandObjectParsed (interpreter,
1291254721Semaste                             "process signal",
1292254721Semaste                             "Send a UNIX signal to the current process being debugged.",
1293254721Semaste                             NULL,
1294254721Semaste                             eFlagRequiresProcess | eFlagTryTargetAPILock)
1295254721Semaste    {
1296254721Semaste        CommandArgumentEntry arg;
1297254721Semaste        CommandArgumentData signal_arg;
1298254721Semaste
1299254721Semaste        // Define the first (and only) variant of this arg.
1300254721Semaste        signal_arg.arg_type = eArgTypeUnixSignal;
1301254721Semaste        signal_arg.arg_repetition = eArgRepeatPlain;
1302254721Semaste
1303254721Semaste        // There is only one variant this argument could be; put it into the argument entry.
1304254721Semaste        arg.push_back (signal_arg);
1305254721Semaste
1306254721Semaste        // Push the data for the first argument into the m_arguments vector.
1307254721Semaste        m_arguments.push_back (arg);
1308254721Semaste    }
1309254721Semaste
1310254721Semaste    ~CommandObjectProcessSignal ()
1311254721Semaste    {
1312254721Semaste    }
1313254721Semaste
1314254721Semasteprotected:
1315254721Semaste    bool
1316254721Semaste    DoExecute (Args& command,
1317254721Semaste             CommandReturnObject &result)
1318254721Semaste    {
1319254721Semaste        Process *process = m_exe_ctx.GetProcessPtr();
1320254721Semaste
1321254721Semaste        if (command.GetArgumentCount() == 1)
1322254721Semaste        {
1323254721Semaste            int signo = LLDB_INVALID_SIGNAL_NUMBER;
1324254721Semaste
1325254721Semaste            const char *signal_name = command.GetArgumentAtIndex(0);
1326254721Semaste            if (::isxdigit (signal_name[0]))
1327254721Semaste                signo = Args::StringToSInt32(signal_name, LLDB_INVALID_SIGNAL_NUMBER, 0);
1328254721Semaste            else
1329254721Semaste                signo = process->GetUnixSignals().GetSignalNumberFromName (signal_name);
1330254721Semaste
1331254721Semaste            if (signo == LLDB_INVALID_SIGNAL_NUMBER)
1332254721Semaste            {
1333254721Semaste                result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0));
1334254721Semaste                result.SetStatus (eReturnStatusFailed);
1335254721Semaste            }
1336254721Semaste            else
1337254721Semaste            {
1338254721Semaste                Error error (process->Signal (signo));
1339254721Semaste                if (error.Success())
1340254721Semaste                {
1341254721Semaste                    result.SetStatus (eReturnStatusSuccessFinishResult);
1342254721Semaste                }
1343254721Semaste                else
1344254721Semaste                {
1345254721Semaste                    result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString());
1346254721Semaste                    result.SetStatus (eReturnStatusFailed);
1347254721Semaste                }
1348254721Semaste            }
1349254721Semaste        }
1350254721Semaste        else
1351254721Semaste        {
1352254721Semaste            result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: %s\n", m_cmd_name.c_str(),
1353254721Semaste                                        m_cmd_syntax.c_str());
1354254721Semaste            result.SetStatus (eReturnStatusFailed);
1355254721Semaste        }
1356254721Semaste        return result.Succeeded();
1357254721Semaste    }
1358254721Semaste};
1359254721Semaste
1360254721Semaste
1361254721Semaste//-------------------------------------------------------------------------
1362254721Semaste// CommandObjectProcessInterrupt
1363254721Semaste//-------------------------------------------------------------------------
1364254721Semaste#pragma mark CommandObjectProcessInterrupt
1365254721Semaste
1366254721Semasteclass CommandObjectProcessInterrupt : public CommandObjectParsed
1367254721Semaste{
1368254721Semastepublic:
1369254721Semaste
1370254721Semaste
1371254721Semaste    CommandObjectProcessInterrupt (CommandInterpreter &interpreter) :
1372254721Semaste        CommandObjectParsed (interpreter,
1373254721Semaste                             "process interrupt",
1374254721Semaste                             "Interrupt the current process being debugged.",
1375254721Semaste                             "process interrupt",
1376254721Semaste                             eFlagRequiresProcess      |
1377254721Semaste                             eFlagTryTargetAPILock     |
1378254721Semaste                             eFlagProcessMustBeLaunched)
1379254721Semaste    {
1380254721Semaste    }
1381254721Semaste
1382254721Semaste    ~CommandObjectProcessInterrupt ()
1383254721Semaste    {
1384254721Semaste    }
1385254721Semaste
1386254721Semasteprotected:
1387254721Semaste    bool
1388254721Semaste    DoExecute (Args& command,
1389254721Semaste               CommandReturnObject &result)
1390254721Semaste    {
1391254721Semaste        Process *process = m_exe_ctx.GetProcessPtr();
1392254721Semaste        if (process == NULL)
1393254721Semaste        {
1394254721Semaste            result.AppendError ("no process to halt");
1395254721Semaste            result.SetStatus (eReturnStatusFailed);
1396254721Semaste            return false;
1397254721Semaste        }
1398254721Semaste
1399254721Semaste        if (command.GetArgumentCount() == 0)
1400254721Semaste        {
1401254721Semaste            bool clear_thread_plans = true;
1402254721Semaste            Error error(process->Halt (clear_thread_plans));
1403254721Semaste            if (error.Success())
1404254721Semaste            {
1405254721Semaste                result.SetStatus (eReturnStatusSuccessFinishResult);
1406254721Semaste            }
1407254721Semaste            else
1408254721Semaste            {
1409254721Semaste                result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString());
1410254721Semaste                result.SetStatus (eReturnStatusFailed);
1411254721Semaste            }
1412254721Semaste        }
1413254721Semaste        else
1414254721Semaste        {
1415254721Semaste            result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n",
1416254721Semaste                                        m_cmd_name.c_str(),
1417254721Semaste                                        m_cmd_syntax.c_str());
1418254721Semaste            result.SetStatus (eReturnStatusFailed);
1419254721Semaste        }
1420254721Semaste        return result.Succeeded();
1421254721Semaste    }
1422254721Semaste};
1423254721Semaste
1424254721Semaste//-------------------------------------------------------------------------
1425254721Semaste// CommandObjectProcessKill
1426254721Semaste//-------------------------------------------------------------------------
1427254721Semaste#pragma mark CommandObjectProcessKill
1428254721Semaste
1429254721Semasteclass CommandObjectProcessKill : public CommandObjectParsed
1430254721Semaste{
1431254721Semastepublic:
1432254721Semaste
1433254721Semaste    CommandObjectProcessKill (CommandInterpreter &interpreter) :
1434254721Semaste        CommandObjectParsed (interpreter,
1435254721Semaste                             "process kill",
1436254721Semaste                             "Terminate the current process being debugged.",
1437254721Semaste                             "process kill",
1438254721Semaste                             eFlagRequiresProcess      |
1439254721Semaste                             eFlagTryTargetAPILock     |
1440254721Semaste                             eFlagProcessMustBeLaunched)
1441254721Semaste    {
1442254721Semaste    }
1443254721Semaste
1444254721Semaste    ~CommandObjectProcessKill ()
1445254721Semaste    {
1446254721Semaste    }
1447254721Semaste
1448254721Semasteprotected:
1449254721Semaste    bool
1450254721Semaste    DoExecute (Args& command,
1451254721Semaste             CommandReturnObject &result)
1452254721Semaste    {
1453254721Semaste        Process *process = m_exe_ctx.GetProcessPtr();
1454254721Semaste        if (process == NULL)
1455254721Semaste        {
1456254721Semaste            result.AppendError ("no process to kill");
1457254721Semaste            result.SetStatus (eReturnStatusFailed);
1458254721Semaste            return false;
1459254721Semaste        }
1460254721Semaste
1461254721Semaste        if (command.GetArgumentCount() == 0)
1462254721Semaste        {
1463254721Semaste            Error error (process->Destroy());
1464254721Semaste            if (error.Success())
1465254721Semaste            {
1466254721Semaste                result.SetStatus (eReturnStatusSuccessFinishResult);
1467254721Semaste            }
1468254721Semaste            else
1469254721Semaste            {
1470254721Semaste                result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString());
1471254721Semaste                result.SetStatus (eReturnStatusFailed);
1472254721Semaste            }
1473254721Semaste        }
1474254721Semaste        else
1475254721Semaste        {
1476254721Semaste            result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n",
1477254721Semaste                                        m_cmd_name.c_str(),
1478254721Semaste                                        m_cmd_syntax.c_str());
1479254721Semaste            result.SetStatus (eReturnStatusFailed);
1480254721Semaste        }
1481254721Semaste        return result.Succeeded();
1482254721Semaste    }
1483254721Semaste};
1484254721Semaste
1485254721Semaste//-------------------------------------------------------------------------
1486254721Semaste// CommandObjectProcessStatus
1487254721Semaste//-------------------------------------------------------------------------
1488254721Semaste#pragma mark CommandObjectProcessStatus
1489254721Semaste
1490254721Semasteclass CommandObjectProcessStatus : public CommandObjectParsed
1491254721Semaste{
1492254721Semastepublic:
1493254721Semaste    CommandObjectProcessStatus (CommandInterpreter &interpreter) :
1494254721Semaste        CommandObjectParsed (interpreter,
1495254721Semaste                             "process status",
1496254721Semaste                             "Show the current status and location of executing process.",
1497254721Semaste                             "process status",
1498254721Semaste                             eFlagRequiresProcess | eFlagTryTargetAPILock)
1499254721Semaste    {
1500254721Semaste    }
1501254721Semaste
1502254721Semaste    ~CommandObjectProcessStatus()
1503254721Semaste    {
1504254721Semaste    }
1505254721Semaste
1506254721Semaste
1507254721Semaste    bool
1508254721Semaste    DoExecute (Args& command, CommandReturnObject &result)
1509254721Semaste    {
1510254721Semaste        Stream &strm = result.GetOutputStream();
1511254721Semaste        result.SetStatus (eReturnStatusSuccessFinishNoResult);
1512254721Semaste        // No need to check "process" for validity as eFlagRequiresProcess ensures it is valid
1513254721Semaste        Process *process = m_exe_ctx.GetProcessPtr();
1514254721Semaste        const bool only_threads_with_stop_reason = true;
1515254721Semaste        const uint32_t start_frame = 0;
1516254721Semaste        const uint32_t num_frames = 1;
1517254721Semaste        const uint32_t num_frames_with_source = 1;
1518254721Semaste        process->GetStatus(strm);
1519254721Semaste        process->GetThreadStatus (strm,
1520254721Semaste                                  only_threads_with_stop_reason,
1521254721Semaste                                  start_frame,
1522254721Semaste                                  num_frames,
1523254721Semaste                                  num_frames_with_source);
1524254721Semaste        return result.Succeeded();
1525254721Semaste    }
1526254721Semaste};
1527254721Semaste
1528254721Semaste//-------------------------------------------------------------------------
1529254721Semaste// CommandObjectProcessHandle
1530254721Semaste//-------------------------------------------------------------------------
1531254721Semaste#pragma mark CommandObjectProcessHandle
1532254721Semaste
1533254721Semasteclass CommandObjectProcessHandle : public CommandObjectParsed
1534254721Semaste{
1535254721Semastepublic:
1536254721Semaste
1537254721Semaste    class CommandOptions : public Options
1538254721Semaste    {
1539254721Semaste    public:
1540254721Semaste
1541254721Semaste        CommandOptions (CommandInterpreter &interpreter) :
1542254721Semaste            Options (interpreter)
1543254721Semaste        {
1544254721Semaste            OptionParsingStarting ();
1545254721Semaste        }
1546254721Semaste
1547254721Semaste        ~CommandOptions ()
1548254721Semaste        {
1549254721Semaste        }
1550254721Semaste
1551254721Semaste        Error
1552254721Semaste        SetOptionValue (uint32_t option_idx, const char *option_arg)
1553254721Semaste        {
1554254721Semaste            Error error;
1555254721Semaste            const int short_option = m_getopt_table[option_idx].val;
1556254721Semaste
1557254721Semaste            switch (short_option)
1558254721Semaste            {
1559254721Semaste                case 's':
1560254721Semaste                    stop = option_arg;
1561254721Semaste                    break;
1562254721Semaste                case 'n':
1563254721Semaste                    notify = option_arg;
1564254721Semaste                    break;
1565254721Semaste                case 'p':
1566254721Semaste                    pass = option_arg;
1567254721Semaste                    break;
1568254721Semaste                default:
1569254721Semaste                    error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
1570254721Semaste                    break;
1571254721Semaste            }
1572254721Semaste            return error;
1573254721Semaste        }
1574254721Semaste
1575254721Semaste        void
1576254721Semaste        OptionParsingStarting ()
1577254721Semaste        {
1578254721Semaste            stop.clear();
1579254721Semaste            notify.clear();
1580254721Semaste            pass.clear();
1581254721Semaste        }
1582254721Semaste
1583254721Semaste        const OptionDefinition*
1584254721Semaste        GetDefinitions ()
1585254721Semaste        {
1586254721Semaste            return g_option_table;
1587254721Semaste        }
1588254721Semaste
1589254721Semaste        // Options table: Required for subclasses of Options.
1590254721Semaste
1591254721Semaste        static OptionDefinition g_option_table[];
1592254721Semaste
1593254721Semaste        // Instance variables to hold the values for command options.
1594254721Semaste
1595254721Semaste        std::string stop;
1596254721Semaste        std::string notify;
1597254721Semaste        std::string pass;
1598254721Semaste    };
1599254721Semaste
1600254721Semaste
1601254721Semaste    CommandObjectProcessHandle (CommandInterpreter &interpreter) :
1602254721Semaste        CommandObjectParsed (interpreter,
1603254721Semaste                             "process handle",
1604254721Semaste                             "Show or update what the process and debugger should do with various signals received from the OS.",
1605254721Semaste                             NULL),
1606254721Semaste        m_options (interpreter)
1607254721Semaste    {
1608254721Semaste        SetHelpLong ("If no signals are specified, update them all.  If no update option is specified, list the current values.\n");
1609254721Semaste        CommandArgumentEntry arg;
1610254721Semaste        CommandArgumentData signal_arg;
1611254721Semaste
1612254721Semaste        signal_arg.arg_type = eArgTypeUnixSignal;
1613254721Semaste        signal_arg.arg_repetition = eArgRepeatStar;
1614254721Semaste
1615254721Semaste        arg.push_back (signal_arg);
1616254721Semaste
1617254721Semaste        m_arguments.push_back (arg);
1618254721Semaste    }
1619254721Semaste
1620254721Semaste    ~CommandObjectProcessHandle ()
1621254721Semaste    {
1622254721Semaste    }
1623254721Semaste
1624254721Semaste    Options *
1625254721Semaste    GetOptions ()
1626254721Semaste    {
1627254721Semaste        return &m_options;
1628254721Semaste    }
1629254721Semaste
1630254721Semaste    bool
1631254721Semaste    VerifyCommandOptionValue (const std::string &option, int &real_value)
1632254721Semaste    {
1633254721Semaste        bool okay = true;
1634254721Semaste
1635254721Semaste        bool success = false;
1636254721Semaste        bool tmp_value = Args::StringToBoolean (option.c_str(), false, &success);
1637254721Semaste
1638254721Semaste        if (success && tmp_value)
1639254721Semaste            real_value = 1;
1640254721Semaste        else if (success && !tmp_value)
1641254721Semaste            real_value = 0;
1642254721Semaste        else
1643254721Semaste        {
1644254721Semaste            // If the value isn't 'true' or 'false', it had better be 0 or 1.
1645254721Semaste            real_value = Args::StringToUInt32 (option.c_str(), 3);
1646254721Semaste            if (real_value != 0 && real_value != 1)
1647254721Semaste                okay = false;
1648254721Semaste        }
1649254721Semaste
1650254721Semaste        return okay;
1651254721Semaste    }
1652254721Semaste
1653254721Semaste    void
1654254721Semaste    PrintSignalHeader (Stream &str)
1655254721Semaste    {
1656254721Semaste        str.Printf ("NAME        PASS   STOP   NOTIFY\n");
1657254721Semaste        str.Printf ("==========  =====  =====  ======\n");
1658254721Semaste    }
1659254721Semaste
1660254721Semaste    void
1661254721Semaste    PrintSignal (Stream &str, int32_t signo, const char *sig_name, UnixSignals &signals)
1662254721Semaste    {
1663254721Semaste        bool stop;
1664254721Semaste        bool suppress;
1665254721Semaste        bool notify;
1666254721Semaste
1667254721Semaste        str.Printf ("%-10s  ", sig_name);
1668254721Semaste        if (signals.GetSignalInfo (signo, suppress, stop, notify))
1669254721Semaste        {
1670254721Semaste            bool pass = !suppress;
1671254721Semaste            str.Printf ("%s  %s  %s",
1672254721Semaste                        (pass ? "true " : "false"),
1673254721Semaste                        (stop ? "true " : "false"),
1674254721Semaste                        (notify ? "true " : "false"));
1675254721Semaste        }
1676254721Semaste        str.Printf ("\n");
1677254721Semaste    }
1678254721Semaste
1679254721Semaste    void
1680254721Semaste    PrintSignalInformation (Stream &str, Args &signal_args, int num_valid_signals, UnixSignals &signals)
1681254721Semaste    {
1682254721Semaste        PrintSignalHeader (str);
1683254721Semaste
1684254721Semaste        if (num_valid_signals > 0)
1685254721Semaste        {
1686254721Semaste            size_t num_args = signal_args.GetArgumentCount();
1687254721Semaste            for (size_t i = 0; i < num_args; ++i)
1688254721Semaste            {
1689254721Semaste                int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
1690254721Semaste                if (signo != LLDB_INVALID_SIGNAL_NUMBER)
1691254721Semaste                    PrintSignal (str, signo, signal_args.GetArgumentAtIndex (i), signals);
1692254721Semaste            }
1693254721Semaste        }
1694254721Semaste        else // Print info for ALL signals
1695254721Semaste        {
1696254721Semaste            int32_t signo = signals.GetFirstSignalNumber();
1697254721Semaste            while (signo != LLDB_INVALID_SIGNAL_NUMBER)
1698254721Semaste            {
1699254721Semaste                PrintSignal (str, signo, signals.GetSignalAsCString (signo), signals);
1700254721Semaste                signo = signals.GetNextSignalNumber (signo);
1701254721Semaste            }
1702254721Semaste        }
1703254721Semaste    }
1704254721Semaste
1705254721Semasteprotected:
1706254721Semaste    bool
1707254721Semaste    DoExecute (Args &signal_args, CommandReturnObject &result)
1708254721Semaste    {
1709254721Semaste        TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
1710254721Semaste
1711254721Semaste        if (!target_sp)
1712254721Semaste        {
1713254721Semaste            result.AppendError ("No current target;"
1714254721Semaste                                " cannot handle signals until you have a valid target and process.\n");
1715254721Semaste            result.SetStatus (eReturnStatusFailed);
1716254721Semaste            return false;
1717254721Semaste        }
1718254721Semaste
1719254721Semaste        ProcessSP process_sp = target_sp->GetProcessSP();
1720254721Semaste
1721254721Semaste        if (!process_sp)
1722254721Semaste        {
1723254721Semaste            result.AppendError ("No current process; cannot handle signals until you have a valid process.\n");
1724254721Semaste            result.SetStatus (eReturnStatusFailed);
1725254721Semaste            return false;
1726254721Semaste        }
1727254721Semaste
1728254721Semaste        int stop_action = -1;   // -1 means leave the current setting alone
1729254721Semaste        int pass_action = -1;   // -1 means leave the current setting alone
1730254721Semaste        int notify_action = -1; // -1 means leave the current setting alone
1731254721Semaste
1732254721Semaste        if (! m_options.stop.empty()
1733254721Semaste            && ! VerifyCommandOptionValue (m_options.stop, stop_action))
1734254721Semaste        {
1735254721Semaste            result.AppendError ("Invalid argument for command option --stop; must be true or false.\n");
1736254721Semaste            result.SetStatus (eReturnStatusFailed);
1737254721Semaste            return false;
1738254721Semaste        }
1739254721Semaste
1740254721Semaste        if (! m_options.notify.empty()
1741254721Semaste            && ! VerifyCommandOptionValue (m_options.notify, notify_action))
1742254721Semaste        {
1743254721Semaste            result.AppendError ("Invalid argument for command option --notify; must be true or false.\n");
1744254721Semaste            result.SetStatus (eReturnStatusFailed);
1745254721Semaste            return false;
1746254721Semaste        }
1747254721Semaste
1748254721Semaste        if (! m_options.pass.empty()
1749254721Semaste            && ! VerifyCommandOptionValue (m_options.pass, pass_action))
1750254721Semaste        {
1751254721Semaste            result.AppendError ("Invalid argument for command option --pass; must be true or false.\n");
1752254721Semaste            result.SetStatus (eReturnStatusFailed);
1753254721Semaste            return false;
1754254721Semaste        }
1755254721Semaste
1756254721Semaste        size_t num_args = signal_args.GetArgumentCount();
1757254721Semaste        UnixSignals &signals = process_sp->GetUnixSignals();
1758254721Semaste        int num_signals_set = 0;
1759254721Semaste
1760254721Semaste        if (num_args > 0)
1761254721Semaste        {
1762254721Semaste            for (size_t i = 0; i < num_args; ++i)
1763254721Semaste            {
1764254721Semaste                int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
1765254721Semaste                if (signo != LLDB_INVALID_SIGNAL_NUMBER)
1766254721Semaste                {
1767254721Semaste                    // Casting the actions as bools here should be okay, because VerifyCommandOptionValue guarantees
1768254721Semaste                    // the value is either 0 or 1.
1769254721Semaste                    if (stop_action != -1)
1770254721Semaste                        signals.SetShouldStop (signo, (bool) stop_action);
1771254721Semaste                    if (pass_action != -1)
1772254721Semaste                    {
1773254721Semaste                        bool suppress = ! ((bool) pass_action);
1774254721Semaste                        signals.SetShouldSuppress (signo, suppress);
1775254721Semaste                    }
1776254721Semaste                    if (notify_action != -1)
1777254721Semaste                        signals.SetShouldNotify (signo, (bool) notify_action);
1778254721Semaste                    ++num_signals_set;
1779254721Semaste                }
1780254721Semaste                else
1781254721Semaste                {
1782254721Semaste                    result.AppendErrorWithFormat ("Invalid signal name '%s'\n", signal_args.GetArgumentAtIndex (i));
1783254721Semaste                }
1784254721Semaste            }
1785254721Semaste        }
1786254721Semaste        else
1787254721Semaste        {
1788254721Semaste            // No signal specified, if any command options were specified, update ALL signals.
1789254721Semaste            if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1))
1790254721Semaste            {
1791254721Semaste                if (m_interpreter.Confirm ("Do you really want to update all the signals?", false))
1792254721Semaste                {
1793254721Semaste                    int32_t signo = signals.GetFirstSignalNumber();
1794254721Semaste                    while (signo != LLDB_INVALID_SIGNAL_NUMBER)
1795254721Semaste                    {
1796254721Semaste                        if (notify_action != -1)
1797254721Semaste                            signals.SetShouldNotify (signo, (bool) notify_action);
1798254721Semaste                        if (stop_action != -1)
1799254721Semaste                            signals.SetShouldStop (signo, (bool) stop_action);
1800254721Semaste                        if (pass_action != -1)
1801254721Semaste                        {
1802254721Semaste                            bool suppress = ! ((bool) pass_action);
1803254721Semaste                            signals.SetShouldSuppress (signo, suppress);
1804254721Semaste                        }
1805254721Semaste                        signo = signals.GetNextSignalNumber (signo);
1806254721Semaste                    }
1807254721Semaste                }
1808254721Semaste            }
1809254721Semaste        }
1810254721Semaste
1811254721Semaste        PrintSignalInformation (result.GetOutputStream(), signal_args, num_signals_set, signals);
1812254721Semaste
1813254721Semaste        if (num_signals_set > 0)
1814254721Semaste            result.SetStatus (eReturnStatusSuccessFinishNoResult);
1815254721Semaste        else
1816254721Semaste            result.SetStatus (eReturnStatusFailed);
1817254721Semaste
1818254721Semaste        return result.Succeeded();
1819254721Semaste    }
1820254721Semaste
1821254721Semaste    CommandOptions m_options;
1822254721Semaste};
1823254721Semaste
1824254721SemasteOptionDefinition
1825254721SemasteCommandObjectProcessHandle::CommandOptions::g_option_table[] =
1826254721Semaste{
1827263363Semaste{ LLDB_OPT_SET_1, false, "stop",   's', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "Whether or not the process should be stopped if the signal is received." },
1828263363Semaste{ LLDB_OPT_SET_1, false, "notify", 'n', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "Whether or not the debugger should notify the user if the signal is received." },
1829263363Semaste{ LLDB_OPT_SET_1, false, "pass",  'p', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." },
1830254721Semaste{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1831254721Semaste};
1832254721Semaste
1833254721Semaste//-------------------------------------------------------------------------
1834254721Semaste// CommandObjectMultiwordProcess
1835254721Semaste//-------------------------------------------------------------------------
1836254721Semaste
1837254721SemasteCommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter &interpreter) :
1838254721Semaste    CommandObjectMultiword (interpreter,
1839254721Semaste                            "process",
1840254721Semaste                            "A set of commands for operating on a process.",
1841254721Semaste                            "process <subcommand> [<subcommand-options>]")
1842254721Semaste{
1843254721Semaste    LoadSubCommand ("attach",      CommandObjectSP (new CommandObjectProcessAttach    (interpreter)));
1844254721Semaste    LoadSubCommand ("launch",      CommandObjectSP (new CommandObjectProcessLaunch    (interpreter)));
1845254721Semaste    LoadSubCommand ("continue",    CommandObjectSP (new CommandObjectProcessContinue  (interpreter)));
1846254721Semaste    LoadSubCommand ("connect",     CommandObjectSP (new CommandObjectProcessConnect   (interpreter)));
1847254721Semaste    LoadSubCommand ("detach",      CommandObjectSP (new CommandObjectProcessDetach    (interpreter)));
1848254721Semaste    LoadSubCommand ("load",        CommandObjectSP (new CommandObjectProcessLoad      (interpreter)));
1849254721Semaste    LoadSubCommand ("unload",      CommandObjectSP (new CommandObjectProcessUnload    (interpreter)));
1850254721Semaste    LoadSubCommand ("signal",      CommandObjectSP (new CommandObjectProcessSignal    (interpreter)));
1851254721Semaste    LoadSubCommand ("handle",      CommandObjectSP (new CommandObjectProcessHandle    (interpreter)));
1852254721Semaste    LoadSubCommand ("status",      CommandObjectSP (new CommandObjectProcessStatus    (interpreter)));
1853254721Semaste    LoadSubCommand ("interrupt",   CommandObjectSP (new CommandObjectProcessInterrupt (interpreter)));
1854254721Semaste    LoadSubCommand ("kill",        CommandObjectSP (new CommandObjectProcessKill      (interpreter)));
1855254721Semaste    LoadSubCommand ("plugin",      CommandObjectSP (new CommandObjectProcessPlugin    (interpreter)));
1856254721Semaste}
1857254721Semaste
1858254721SemasteCommandObjectMultiwordProcess::~CommandObjectMultiwordProcess ()
1859254721Semaste{
1860254721Semaste}
1861254721Semaste
1862