1ac7ddfbfSEd Maste //===-- CommandObjectProcess.cpp --------------------------------*- C++ -*-===//
2ac7ddfbfSEd Maste //
3ac7ddfbfSEd Maste //                     The LLVM Compiler Infrastructure
4ac7ddfbfSEd Maste //
5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source
6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details.
7ac7ddfbfSEd Maste //
8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===//
9ac7ddfbfSEd Maste 
10ac7ddfbfSEd Maste #include "lldb/lldb-python.h"
11ac7ddfbfSEd Maste 
12ac7ddfbfSEd Maste #include "CommandObjectProcess.h"
13ac7ddfbfSEd Maste 
14ac7ddfbfSEd Maste // C Includes
15ac7ddfbfSEd Maste // C++ Includes
16ac7ddfbfSEd Maste // Other libraries and framework includes
17ac7ddfbfSEd Maste // Project includes
18ac7ddfbfSEd Maste #include "lldb/Breakpoint/Breakpoint.h"
19ac7ddfbfSEd Maste #include "lldb/Breakpoint/BreakpointLocation.h"
20ac7ddfbfSEd Maste #include "lldb/Breakpoint/BreakpointSite.h"
21ac7ddfbfSEd Maste #include "lldb/Core/State.h"
22ac7ddfbfSEd Maste #include "lldb/Core/Module.h"
23ac7ddfbfSEd Maste #include "lldb/Host/Host.h"
24ac7ddfbfSEd Maste #include "lldb/Interpreter/Args.h"
25ac7ddfbfSEd Maste #include "lldb/Interpreter/Options.h"
26ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandInterpreter.h"
27ac7ddfbfSEd Maste #include "lldb/Interpreter/CommandReturnObject.h"
28ac7ddfbfSEd Maste #include "lldb/Target/Platform.h"
29ac7ddfbfSEd Maste #include "lldb/Target/Process.h"
30ac7ddfbfSEd Maste #include "lldb/Target/StopInfo.h"
31ac7ddfbfSEd Maste #include "lldb/Target/Target.h"
32ac7ddfbfSEd Maste #include "lldb/Target/Thread.h"
33ac7ddfbfSEd Maste 
34ac7ddfbfSEd Maste using namespace lldb;
35ac7ddfbfSEd Maste using namespace lldb_private;
36ac7ddfbfSEd Maste 
37ac7ddfbfSEd Maste class CommandObjectProcessLaunchOrAttach : public CommandObjectParsed
38ac7ddfbfSEd Maste {
39ac7ddfbfSEd Maste public:
40ac7ddfbfSEd Maste     CommandObjectProcessLaunchOrAttach (CommandInterpreter &interpreter,
41ac7ddfbfSEd Maste                                        const char *name,
42ac7ddfbfSEd Maste                                        const char *help,
43ac7ddfbfSEd Maste                                        const char *syntax,
44ac7ddfbfSEd Maste                                        uint32_t flags,
45ac7ddfbfSEd Maste                                        const char *new_process_action) :
46ac7ddfbfSEd Maste         CommandObjectParsed (interpreter, name, help, syntax, flags),
47ac7ddfbfSEd Maste         m_new_process_action (new_process_action) {}
48ac7ddfbfSEd Maste 
49ac7ddfbfSEd Maste     virtual ~CommandObjectProcessLaunchOrAttach () {}
50ac7ddfbfSEd Maste protected:
51ac7ddfbfSEd Maste     bool
52ac7ddfbfSEd Maste     StopProcessIfNecessary (Process *&process, StateType &state, CommandReturnObject &result)
53ac7ddfbfSEd Maste     {
54ac7ddfbfSEd Maste         state = eStateInvalid;
55ac7ddfbfSEd Maste         if (process)
56ac7ddfbfSEd Maste         {
57ac7ddfbfSEd Maste             state = process->GetState();
58ac7ddfbfSEd Maste 
59ac7ddfbfSEd Maste             if (process->IsAlive() && state != eStateConnected)
60ac7ddfbfSEd Maste             {
61ac7ddfbfSEd Maste                 char message[1024];
62ac7ddfbfSEd Maste                 if (process->GetState() == eStateAttaching)
63ac7ddfbfSEd Maste                     ::snprintf (message, sizeof(message), "There is a pending attach, abort it and %s?", m_new_process_action.c_str());
64ac7ddfbfSEd Maste                 else if (process->GetShouldDetach())
65ac7ddfbfSEd Maste                     ::snprintf (message, sizeof(message), "There is a running process, detach from it and %s?", m_new_process_action.c_str());
66ac7ddfbfSEd Maste                 else
67ac7ddfbfSEd Maste                     ::snprintf (message, sizeof(message), "There is a running process, kill it and %s?", m_new_process_action.c_str());
68ac7ddfbfSEd Maste 
69ac7ddfbfSEd Maste                 if (!m_interpreter.Confirm (message, true))
70ac7ddfbfSEd Maste                 {
71ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
72ac7ddfbfSEd Maste                     return false;
73ac7ddfbfSEd Maste                 }
74ac7ddfbfSEd Maste                 else
75ac7ddfbfSEd Maste                 {
76ac7ddfbfSEd Maste                     if (process->GetShouldDetach())
77ac7ddfbfSEd Maste                     {
78ac7ddfbfSEd Maste                         bool keep_stopped = false;
79ac7ddfbfSEd Maste                         Error detach_error (process->Detach(keep_stopped));
80ac7ddfbfSEd Maste                         if (detach_error.Success())
81ac7ddfbfSEd Maste                         {
82ac7ddfbfSEd Maste                             result.SetStatus (eReturnStatusSuccessFinishResult);
83ac7ddfbfSEd Maste                             process = NULL;
84ac7ddfbfSEd Maste                         }
85ac7ddfbfSEd Maste                         else
86ac7ddfbfSEd Maste                         {
87ac7ddfbfSEd Maste                             result.AppendErrorWithFormat ("Failed to detach from process: %s\n", detach_error.AsCString());
88ac7ddfbfSEd Maste                             result.SetStatus (eReturnStatusFailed);
89ac7ddfbfSEd Maste                         }
90ac7ddfbfSEd Maste                     }
91ac7ddfbfSEd Maste                     else
92ac7ddfbfSEd Maste                     {
93ac7ddfbfSEd Maste                         Error destroy_error (process->Destroy());
94ac7ddfbfSEd Maste                         if (destroy_error.Success())
95ac7ddfbfSEd Maste                         {
96ac7ddfbfSEd Maste                             result.SetStatus (eReturnStatusSuccessFinishResult);
97ac7ddfbfSEd Maste                             process = NULL;
98ac7ddfbfSEd Maste                         }
99ac7ddfbfSEd Maste                         else
100ac7ddfbfSEd Maste                         {
101ac7ddfbfSEd Maste                             result.AppendErrorWithFormat ("Failed to kill process: %s\n", destroy_error.AsCString());
102ac7ddfbfSEd Maste                             result.SetStatus (eReturnStatusFailed);
103ac7ddfbfSEd Maste                         }
104ac7ddfbfSEd Maste                     }
105ac7ddfbfSEd Maste                 }
106ac7ddfbfSEd Maste             }
107ac7ddfbfSEd Maste         }
108ac7ddfbfSEd Maste         return result.Succeeded();
109ac7ddfbfSEd Maste     }
110ac7ddfbfSEd Maste     std::string m_new_process_action;
111ac7ddfbfSEd Maste };
112ac7ddfbfSEd Maste //-------------------------------------------------------------------------
113ac7ddfbfSEd Maste // CommandObjectProcessLaunch
114ac7ddfbfSEd Maste //-------------------------------------------------------------------------
115ac7ddfbfSEd Maste #pragma mark CommandObjectProcessLaunch
116ac7ddfbfSEd Maste class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach
117ac7ddfbfSEd Maste {
118ac7ddfbfSEd Maste public:
119ac7ddfbfSEd Maste 
120ac7ddfbfSEd Maste     CommandObjectProcessLaunch (CommandInterpreter &interpreter) :
121ac7ddfbfSEd Maste         CommandObjectProcessLaunchOrAttach (interpreter,
122ac7ddfbfSEd Maste                                             "process launch",
123ac7ddfbfSEd Maste                                             "Launch the executable in the debugger.",
124ac7ddfbfSEd Maste                                             NULL,
125ac7ddfbfSEd Maste                                             eFlagRequiresTarget,
126ac7ddfbfSEd Maste                                             "restart"),
127ac7ddfbfSEd Maste         m_options (interpreter)
128ac7ddfbfSEd Maste     {
129ac7ddfbfSEd Maste         CommandArgumentEntry arg;
130ac7ddfbfSEd Maste         CommandArgumentData run_args_arg;
131ac7ddfbfSEd Maste 
132ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
133ac7ddfbfSEd Maste         run_args_arg.arg_type = eArgTypeRunArgs;
134ac7ddfbfSEd Maste         run_args_arg.arg_repetition = eArgRepeatOptional;
135ac7ddfbfSEd Maste 
136ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
137ac7ddfbfSEd Maste         arg.push_back (run_args_arg);
138ac7ddfbfSEd Maste 
139ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
140ac7ddfbfSEd Maste         m_arguments.push_back (arg);
141ac7ddfbfSEd Maste     }
142ac7ddfbfSEd Maste 
143ac7ddfbfSEd Maste 
144ac7ddfbfSEd Maste     ~CommandObjectProcessLaunch ()
145ac7ddfbfSEd Maste     {
146ac7ddfbfSEd Maste     }
147ac7ddfbfSEd Maste 
148ac7ddfbfSEd Maste     virtual int
149ac7ddfbfSEd Maste     HandleArgumentCompletion (Args &input,
150ac7ddfbfSEd Maste                               int &cursor_index,
151ac7ddfbfSEd Maste                               int &cursor_char_position,
152ac7ddfbfSEd Maste                               OptionElementVector &opt_element_vector,
153ac7ddfbfSEd Maste                               int match_start_point,
154ac7ddfbfSEd Maste                               int max_return_elements,
155ac7ddfbfSEd Maste                               bool &word_complete,
156ac7ddfbfSEd Maste                               StringList &matches)
157ac7ddfbfSEd Maste     {
158ac7ddfbfSEd Maste         std::string completion_str (input.GetArgumentAtIndex(cursor_index));
159ac7ddfbfSEd Maste         completion_str.erase (cursor_char_position);
160ac7ddfbfSEd Maste 
161ac7ddfbfSEd Maste         CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter,
162ac7ddfbfSEd Maste                                                              CommandCompletions::eDiskFileCompletion,
163ac7ddfbfSEd Maste                                                              completion_str.c_str(),
164ac7ddfbfSEd Maste                                                              match_start_point,
165ac7ddfbfSEd Maste                                                              max_return_elements,
166ac7ddfbfSEd Maste                                                              NULL,
167ac7ddfbfSEd Maste                                                              word_complete,
168ac7ddfbfSEd Maste                                                              matches);
169ac7ddfbfSEd Maste         return matches.GetSize();
170ac7ddfbfSEd Maste     }
171ac7ddfbfSEd Maste 
172ac7ddfbfSEd Maste     Options *
173ac7ddfbfSEd Maste     GetOptions ()
174ac7ddfbfSEd Maste     {
175ac7ddfbfSEd Maste         return &m_options;
176ac7ddfbfSEd Maste     }
177ac7ddfbfSEd Maste 
178ac7ddfbfSEd Maste     virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
179ac7ddfbfSEd Maste     {
180ac7ddfbfSEd Maste         // No repeat for "process launch"...
181ac7ddfbfSEd Maste         return "";
182ac7ddfbfSEd Maste     }
183ac7ddfbfSEd Maste 
184ac7ddfbfSEd Maste protected:
185ac7ddfbfSEd Maste     bool
186ac7ddfbfSEd Maste     DoExecute (Args& launch_args, CommandReturnObject &result)
187ac7ddfbfSEd Maste     {
188ac7ddfbfSEd Maste         Debugger &debugger = m_interpreter.GetDebugger();
189ac7ddfbfSEd Maste         Target *target = debugger.GetSelectedTarget().get();
190ac7ddfbfSEd Maste         Error error;
191ac7ddfbfSEd Maste         // If our listener is NULL, users aren't allows to launch
192ac7ddfbfSEd Maste         char filename[PATH_MAX];
193ac7ddfbfSEd Maste         const Module *exe_module = target->GetExecutableModulePointer();
194ac7ddfbfSEd Maste 
195ac7ddfbfSEd Maste         if (exe_module == NULL)
196ac7ddfbfSEd Maste         {
197ac7ddfbfSEd Maste             result.AppendError ("no file in target, create a debug target using the 'target create' command");
198ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
199ac7ddfbfSEd Maste             return false;
200ac7ddfbfSEd Maste         }
201ac7ddfbfSEd Maste 
202ac7ddfbfSEd Maste         StateType state = eStateInvalid;
203ac7ddfbfSEd Maste         Process *process = m_exe_ctx.GetProcessPtr();
204ac7ddfbfSEd Maste 
205ac7ddfbfSEd Maste         if (!StopProcessIfNecessary(process, state, result))
206ac7ddfbfSEd Maste             return false;
207ac7ddfbfSEd Maste 
208ac7ddfbfSEd Maste         const char *target_settings_argv0 = target->GetArg0();
209ac7ddfbfSEd Maste 
210ac7ddfbfSEd Maste         exe_module->GetFileSpec().GetPath (filename, sizeof(filename));
211ac7ddfbfSEd Maste 
212ac7ddfbfSEd Maste         if (target_settings_argv0)
213ac7ddfbfSEd Maste         {
214ac7ddfbfSEd Maste             m_options.launch_info.GetArguments().AppendArgument (target_settings_argv0);
215ac7ddfbfSEd Maste             m_options.launch_info.SetExecutableFile(exe_module->GetPlatformFileSpec(), false);
216ac7ddfbfSEd Maste         }
217ac7ddfbfSEd Maste         else
218ac7ddfbfSEd Maste         {
219ac7ddfbfSEd Maste             m_options.launch_info.SetExecutableFile(exe_module->GetPlatformFileSpec(), true);
220ac7ddfbfSEd Maste         }
221ac7ddfbfSEd Maste 
222ac7ddfbfSEd Maste         if (launch_args.GetArgumentCount() == 0)
223ac7ddfbfSEd Maste         {
224ac7ddfbfSEd Maste             Args target_setting_args;
225ac7ddfbfSEd Maste             if (target->GetRunArguments(target_setting_args))
226ac7ddfbfSEd Maste                 m_options.launch_info.GetArguments().AppendArguments (target_setting_args);
227ac7ddfbfSEd Maste         }
228ac7ddfbfSEd Maste         else
229ac7ddfbfSEd Maste         {
230ac7ddfbfSEd Maste             m_options.launch_info.GetArguments().AppendArguments (launch_args);
231ac7ddfbfSEd Maste 
232ac7ddfbfSEd Maste             // Save the arguments for subsequent runs in the current target.
233ac7ddfbfSEd Maste             target->SetRunArguments (launch_args);
234ac7ddfbfSEd Maste         }
235ac7ddfbfSEd Maste 
236ac7ddfbfSEd Maste         if (target->GetDisableASLR())
237ac7ddfbfSEd Maste             m_options.launch_info.GetFlags().Set (eLaunchFlagDisableASLR);
238ac7ddfbfSEd Maste 
239ac7ddfbfSEd Maste         if (target->GetDisableSTDIO())
240ac7ddfbfSEd Maste             m_options.launch_info.GetFlags().Set (eLaunchFlagDisableSTDIO);
241ac7ddfbfSEd Maste 
242ac7ddfbfSEd Maste         m_options.launch_info.GetFlags().Set (eLaunchFlagDebug);
243ac7ddfbfSEd Maste 
244ac7ddfbfSEd Maste         Args environment;
245ac7ddfbfSEd Maste         target->GetEnvironmentAsArgs (environment);
246ac7ddfbfSEd Maste         if (environment.GetArgumentCount() > 0)
247ac7ddfbfSEd Maste             m_options.launch_info.GetEnvironmentEntries ().AppendArguments (environment);
248ac7ddfbfSEd Maste 
249ac7ddfbfSEd Maste         // Get the value of synchronous execution here.  If you wait till after you have started to
250ac7ddfbfSEd Maste         // run, then you could have hit a breakpoint, whose command might switch the value, and
251ac7ddfbfSEd Maste         // then you'll pick up that incorrect value.
252ac7ddfbfSEd Maste         bool synchronous_execution = m_interpreter.GetSynchronous ();
253ac7ddfbfSEd Maste 
254ac7ddfbfSEd Maste         // Finalize the file actions, and if none were given, default to opening
255ac7ddfbfSEd Maste         // up a pseudo terminal
256ac7ddfbfSEd Maste         const bool default_to_use_pty = true;
257ac7ddfbfSEd Maste         m_options.launch_info.FinalizeFileActions (target, default_to_use_pty);
258ac7ddfbfSEd Maste 
259ac7ddfbfSEd Maste         if (state == eStateConnected)
260ac7ddfbfSEd Maste         {
261ac7ddfbfSEd Maste             if (m_options.launch_info.GetFlags().Test (eLaunchFlagLaunchInTTY))
262ac7ddfbfSEd Maste             {
263ac7ddfbfSEd Maste                 result.AppendWarning("can't launch in tty when launching through a remote connection");
264ac7ddfbfSEd Maste                 m_options.launch_info.GetFlags().Clear (eLaunchFlagLaunchInTTY);
265ac7ddfbfSEd Maste             }
266ac7ddfbfSEd Maste         }
267ac7ddfbfSEd Maste 
268ac7ddfbfSEd Maste         if (!m_options.launch_info.GetArchitecture().IsValid())
269ac7ddfbfSEd Maste             m_options.launch_info.GetArchitecture() = target->GetArchitecture();
270ac7ddfbfSEd Maste 
271ac7ddfbfSEd Maste         PlatformSP platform_sp (target->GetPlatform());
272ac7ddfbfSEd Maste 
273ac7ddfbfSEd Maste         if (platform_sp && platform_sp->CanDebugProcess ())
274ac7ddfbfSEd Maste         {
275ac7ddfbfSEd Maste             process = target->GetPlatform()->DebugProcess (m_options.launch_info,
276ac7ddfbfSEd Maste                                                            debugger,
277ac7ddfbfSEd Maste                                                            target,
278ac7ddfbfSEd Maste                                                            debugger.GetListener(),
279ac7ddfbfSEd Maste                                                            error).get();
280ac7ddfbfSEd Maste         }
281ac7ddfbfSEd Maste         else
282ac7ddfbfSEd Maste         {
283ac7ddfbfSEd Maste             const char *plugin_name = m_options.launch_info.GetProcessPluginName();
284ac7ddfbfSEd Maste             process = target->CreateProcess (debugger.GetListener(), plugin_name, NULL).get();
285ac7ddfbfSEd Maste             if (process)
286ac7ddfbfSEd Maste                 error = process->Launch (m_options.launch_info);
287ac7ddfbfSEd Maste         }
288ac7ddfbfSEd Maste 
289ac7ddfbfSEd Maste         if (process == NULL)
290ac7ddfbfSEd Maste         {
291ac7ddfbfSEd Maste             result.SetError (error, "failed to launch or debug process");
292ac7ddfbfSEd Maste             return false;
293ac7ddfbfSEd Maste         }
294ac7ddfbfSEd Maste 
295ac7ddfbfSEd Maste 
296ac7ddfbfSEd Maste         if (error.Success())
297ac7ddfbfSEd Maste         {
298ac7ddfbfSEd Maste             const char *archname = exe_module->GetArchitecture().GetArchitectureName();
299ac7ddfbfSEd Maste 
300ac7ddfbfSEd Maste             result.AppendMessageWithFormat ("Process %" PRIu64 " launched: '%s' (%s)\n", process->GetID(), filename, archname);
301ac7ddfbfSEd Maste             result.SetDidChangeProcessState (true);
302ac7ddfbfSEd Maste             if (m_options.launch_info.GetFlags().Test(eLaunchFlagStopAtEntry) == false)
303ac7ddfbfSEd Maste             {
304ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
305ac7ddfbfSEd Maste                 StateType state = process->WaitForProcessToStop (NULL);
306ac7ddfbfSEd Maste 
307ac7ddfbfSEd Maste                 if (state == eStateStopped)
308ac7ddfbfSEd Maste                 {
309ac7ddfbfSEd Maste                     error = process->Resume();
310ac7ddfbfSEd Maste                     if (error.Success())
311ac7ddfbfSEd Maste                     {
312ac7ddfbfSEd Maste                         if (synchronous_execution)
313ac7ddfbfSEd Maste                         {
314ac7ddfbfSEd Maste                             state = process->WaitForProcessToStop (NULL);
315ac7ddfbfSEd Maste                             const bool must_be_alive = true;
316ac7ddfbfSEd Maste                             if (!StateIsStoppedState(state, must_be_alive))
317ac7ddfbfSEd Maste                             {
318ac7ddfbfSEd Maste                                 result.AppendErrorWithFormat ("process isn't stopped: %s", StateAsCString(state));
319ac7ddfbfSEd Maste                             }
320ac7ddfbfSEd Maste                             result.SetDidChangeProcessState (true);
321ac7ddfbfSEd Maste                             result.SetStatus (eReturnStatusSuccessFinishResult);
322ac7ddfbfSEd Maste                         }
323ac7ddfbfSEd Maste                         else
324ac7ddfbfSEd Maste                         {
325ac7ddfbfSEd Maste                             result.SetStatus (eReturnStatusSuccessContinuingNoResult);
326ac7ddfbfSEd Maste                         }
327ac7ddfbfSEd Maste                     }
328ac7ddfbfSEd Maste                     else
329ac7ddfbfSEd Maste                     {
330ac7ddfbfSEd Maste                         result.AppendErrorWithFormat ("process resume at entry point failed: %s", error.AsCString());
331ac7ddfbfSEd Maste                         result.SetStatus (eReturnStatusFailed);
332ac7ddfbfSEd Maste                     }
333ac7ddfbfSEd Maste                 }
334ac7ddfbfSEd Maste                 else
335ac7ddfbfSEd Maste                 {
336ac7ddfbfSEd Maste                     result.AppendErrorWithFormat ("initial process state wasn't stopped: %s", StateAsCString(state));
337ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
338ac7ddfbfSEd Maste                 }
339ac7ddfbfSEd Maste             }
340ac7ddfbfSEd Maste         }
341ac7ddfbfSEd Maste         else
342ac7ddfbfSEd Maste         {
343ac7ddfbfSEd Maste             result.AppendErrorWithFormat ("process launch failed: %s", error.AsCString());
344ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
345ac7ddfbfSEd Maste         }
346ac7ddfbfSEd Maste 
347ac7ddfbfSEd Maste         return result.Succeeded();
348ac7ddfbfSEd Maste     }
349ac7ddfbfSEd Maste 
350ac7ddfbfSEd Maste protected:
351ac7ddfbfSEd Maste     ProcessLaunchCommandOptions m_options;
352ac7ddfbfSEd Maste };
353ac7ddfbfSEd Maste 
354ac7ddfbfSEd Maste 
355ac7ddfbfSEd Maste //#define SET1 LLDB_OPT_SET_1
356ac7ddfbfSEd Maste //#define SET2 LLDB_OPT_SET_2
357ac7ddfbfSEd Maste //#define SET3 LLDB_OPT_SET_3
358ac7ddfbfSEd Maste //
359ac7ddfbfSEd Maste //OptionDefinition
360ac7ddfbfSEd Maste //CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
361ac7ddfbfSEd Maste //{
362ac7ddfbfSEd Maste //{ SET1 | SET2 | SET3, false, "stop-at-entry", 's', no_argument,       NULL, 0, eArgTypeNone,    "Stop at the entry point of the program when launching a process."},
363ac7ddfbfSEd Maste //{ SET1              , false, "stdin",         'i', required_argument, NULL, 0, eArgTypeDirectoryName,    "Redirect stdin for the process to <path>."},
364ac7ddfbfSEd Maste //{ SET1              , false, "stdout",        'o', required_argument, NULL, 0, eArgTypeDirectoryName,    "Redirect stdout for the process to <path>."},
365ac7ddfbfSEd Maste //{ SET1              , false, "stderr",        'e', required_argument, NULL, 0, eArgTypeDirectoryName,    "Redirect stderr for the process to <path>."},
366ac7ddfbfSEd Maste //{ SET1 | SET2 | SET3, false, "plugin",        'p', required_argument, NULL, 0, eArgTypePlugin,  "Name of the process plugin you want to use."},
367ac7ddfbfSEd Maste //{        SET2       , false, "tty",           't', optional_argument, 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."},
368ac7ddfbfSEd Maste //{               SET3, false, "no-stdio",      'n', no_argument,       NULL, 0, eArgTypeNone,    "Do not set up for terminal I/O to go to running process."},
369ac7ddfbfSEd Maste //{ SET1 | SET2 | SET3, false, "working-dir",   'w', required_argument, NULL, 0, eArgTypeDirectoryName,    "Set the current working directory to <path> when running the inferior."},
370ac7ddfbfSEd Maste //{ 0,                  false, NULL,             0,  0,                 NULL, 0, eArgTypeNone,    NULL }
371ac7ddfbfSEd Maste //};
372ac7ddfbfSEd Maste //
373ac7ddfbfSEd Maste //#undef SET1
374ac7ddfbfSEd Maste //#undef SET2
375ac7ddfbfSEd Maste //#undef SET3
376ac7ddfbfSEd Maste 
377ac7ddfbfSEd Maste //-------------------------------------------------------------------------
378ac7ddfbfSEd Maste // CommandObjectProcessAttach
379ac7ddfbfSEd Maste //-------------------------------------------------------------------------
380ac7ddfbfSEd Maste #pragma mark CommandObjectProcessAttach
381ac7ddfbfSEd Maste class CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach
382ac7ddfbfSEd Maste {
383ac7ddfbfSEd Maste public:
384ac7ddfbfSEd Maste 
385ac7ddfbfSEd Maste     class CommandOptions : public Options
386ac7ddfbfSEd Maste     {
387ac7ddfbfSEd Maste     public:
388ac7ddfbfSEd Maste 
389ac7ddfbfSEd Maste         CommandOptions (CommandInterpreter &interpreter) :
390ac7ddfbfSEd Maste             Options(interpreter)
391ac7ddfbfSEd Maste         {
392ac7ddfbfSEd Maste             // Keep default values of all options in one place: OptionParsingStarting ()
393ac7ddfbfSEd Maste             OptionParsingStarting ();
394ac7ddfbfSEd Maste         }
395ac7ddfbfSEd Maste 
396ac7ddfbfSEd Maste         ~CommandOptions ()
397ac7ddfbfSEd Maste         {
398ac7ddfbfSEd Maste         }
399ac7ddfbfSEd Maste 
400ac7ddfbfSEd Maste         Error
401ac7ddfbfSEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg)
402ac7ddfbfSEd Maste         {
403ac7ddfbfSEd Maste             Error error;
404ac7ddfbfSEd Maste             const int short_option = m_getopt_table[option_idx].val;
405ac7ddfbfSEd Maste             bool success = false;
406ac7ddfbfSEd Maste             switch (short_option)
407ac7ddfbfSEd Maste             {
408ac7ddfbfSEd Maste                 case 'c':
409ac7ddfbfSEd Maste                     attach_info.SetContinueOnceAttached(true);
410ac7ddfbfSEd Maste                     break;
411ac7ddfbfSEd Maste 
412ac7ddfbfSEd Maste                 case 'p':
413ac7ddfbfSEd Maste                     {
414ac7ddfbfSEd Maste                         lldb::pid_t pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success);
415ac7ddfbfSEd Maste                         if (!success || pid == LLDB_INVALID_PROCESS_ID)
416ac7ddfbfSEd Maste                         {
417ac7ddfbfSEd Maste                             error.SetErrorStringWithFormat("invalid process ID '%s'", option_arg);
418ac7ddfbfSEd Maste                         }
419ac7ddfbfSEd Maste                         else
420ac7ddfbfSEd Maste                         {
421ac7ddfbfSEd Maste                             attach_info.SetProcessID (pid);
422ac7ddfbfSEd Maste                         }
423ac7ddfbfSEd Maste                     }
424ac7ddfbfSEd Maste                     break;
425ac7ddfbfSEd Maste 
426ac7ddfbfSEd Maste                 case 'P':
427ac7ddfbfSEd Maste                     attach_info.SetProcessPluginName (option_arg);
428ac7ddfbfSEd Maste                     break;
429ac7ddfbfSEd Maste 
430ac7ddfbfSEd Maste                 case 'n':
431ac7ddfbfSEd Maste                     attach_info.GetExecutableFile().SetFile(option_arg, false);
432ac7ddfbfSEd Maste                     break;
433ac7ddfbfSEd Maste 
434ac7ddfbfSEd Maste                 case 'w':
435ac7ddfbfSEd Maste                     attach_info.SetWaitForLaunch(true);
436ac7ddfbfSEd Maste                     break;
437ac7ddfbfSEd Maste 
438ac7ddfbfSEd Maste                 case 'i':
439ac7ddfbfSEd Maste                     attach_info.SetIgnoreExisting(false);
440ac7ddfbfSEd Maste                     break;
441ac7ddfbfSEd Maste 
442ac7ddfbfSEd Maste                 default:
443ac7ddfbfSEd Maste                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
444ac7ddfbfSEd Maste                     break;
445ac7ddfbfSEd Maste             }
446ac7ddfbfSEd Maste             return error;
447ac7ddfbfSEd Maste         }
448ac7ddfbfSEd Maste 
449ac7ddfbfSEd Maste         void
450ac7ddfbfSEd Maste         OptionParsingStarting ()
451ac7ddfbfSEd Maste         {
452ac7ddfbfSEd Maste             attach_info.Clear();
453ac7ddfbfSEd Maste         }
454ac7ddfbfSEd Maste 
455ac7ddfbfSEd Maste         const OptionDefinition*
456ac7ddfbfSEd Maste         GetDefinitions ()
457ac7ddfbfSEd Maste         {
458ac7ddfbfSEd Maste             return g_option_table;
459ac7ddfbfSEd Maste         }
460ac7ddfbfSEd Maste 
461ac7ddfbfSEd Maste         virtual bool
462ac7ddfbfSEd Maste         HandleOptionArgumentCompletion (Args &input,
463ac7ddfbfSEd Maste                                         int cursor_index,
464ac7ddfbfSEd Maste                                         int char_pos,
465ac7ddfbfSEd Maste                                         OptionElementVector &opt_element_vector,
466ac7ddfbfSEd Maste                                         int opt_element_index,
467ac7ddfbfSEd Maste                                         int match_start_point,
468ac7ddfbfSEd Maste                                         int max_return_elements,
469ac7ddfbfSEd Maste                                         bool &word_complete,
470ac7ddfbfSEd Maste                                         StringList &matches)
471ac7ddfbfSEd Maste         {
472ac7ddfbfSEd Maste             int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
473ac7ddfbfSEd Maste             int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
474ac7ddfbfSEd Maste 
475ac7ddfbfSEd Maste             // We are only completing the name option for now...
476ac7ddfbfSEd Maste 
477ac7ddfbfSEd Maste             const OptionDefinition *opt_defs = GetDefinitions();
478ac7ddfbfSEd Maste             if (opt_defs[opt_defs_index].short_option == 'n')
479ac7ddfbfSEd Maste             {
480ac7ddfbfSEd Maste                 // Are we in the name?
481ac7ddfbfSEd Maste 
482ac7ddfbfSEd Maste                 // Look to see if there is a -P argument provided, and if so use that plugin, otherwise
483ac7ddfbfSEd Maste                 // use the default plugin.
484ac7ddfbfSEd Maste 
485ac7ddfbfSEd Maste                 const char *partial_name = NULL;
486ac7ddfbfSEd Maste                 partial_name = input.GetArgumentAtIndex(opt_arg_pos);
487ac7ddfbfSEd Maste 
488ac7ddfbfSEd Maste                 PlatformSP platform_sp (m_interpreter.GetPlatform (true));
489ac7ddfbfSEd Maste                 if (platform_sp)
490ac7ddfbfSEd Maste                 {
491ac7ddfbfSEd Maste                     ProcessInstanceInfoList process_infos;
492ac7ddfbfSEd Maste                     ProcessInstanceInfoMatch match_info;
493ac7ddfbfSEd Maste                     if (partial_name)
494ac7ddfbfSEd Maste                     {
495ac7ddfbfSEd Maste                         match_info.GetProcessInfo().GetExecutableFile().SetFile(partial_name, false);
496ac7ddfbfSEd Maste                         match_info.SetNameMatchType(eNameMatchStartsWith);
497ac7ddfbfSEd Maste                     }
498ac7ddfbfSEd Maste                     platform_sp->FindProcesses (match_info, process_infos);
499ac7ddfbfSEd Maste                     const size_t num_matches = process_infos.GetSize();
500ac7ddfbfSEd Maste                     if (num_matches > 0)
501ac7ddfbfSEd Maste                     {
502ac7ddfbfSEd Maste                         for (size_t i=0; i<num_matches; ++i)
503ac7ddfbfSEd Maste                         {
504ac7ddfbfSEd Maste                             matches.AppendString (process_infos.GetProcessNameAtIndex(i),
505ac7ddfbfSEd Maste                                                   process_infos.GetProcessNameLengthAtIndex(i));
506ac7ddfbfSEd Maste                         }
507ac7ddfbfSEd Maste                     }
508ac7ddfbfSEd Maste                 }
509ac7ddfbfSEd Maste             }
510ac7ddfbfSEd Maste 
511ac7ddfbfSEd Maste             return false;
512ac7ddfbfSEd Maste         }
513ac7ddfbfSEd Maste 
514ac7ddfbfSEd Maste         // Options table: Required for subclasses of Options.
515ac7ddfbfSEd Maste 
516ac7ddfbfSEd Maste         static OptionDefinition g_option_table[];
517ac7ddfbfSEd Maste 
518ac7ddfbfSEd Maste         // Instance variables to hold the values for command options.
519ac7ddfbfSEd Maste 
520ac7ddfbfSEd Maste         ProcessAttachInfo attach_info;
521ac7ddfbfSEd Maste     };
522ac7ddfbfSEd Maste 
523ac7ddfbfSEd Maste     CommandObjectProcessAttach (CommandInterpreter &interpreter) :
524ac7ddfbfSEd Maste         CommandObjectProcessLaunchOrAttach (interpreter,
525ac7ddfbfSEd Maste                                             "process attach",
526ac7ddfbfSEd Maste                                             "Attach to a process.",
527ac7ddfbfSEd Maste                                             "process attach <cmd-options>",
528ac7ddfbfSEd Maste                                             0,
529ac7ddfbfSEd Maste                                             "attach"),
530ac7ddfbfSEd Maste         m_options (interpreter)
531ac7ddfbfSEd Maste     {
532ac7ddfbfSEd Maste     }
533ac7ddfbfSEd Maste 
534ac7ddfbfSEd Maste     ~CommandObjectProcessAttach ()
535ac7ddfbfSEd Maste     {
536ac7ddfbfSEd Maste     }
537ac7ddfbfSEd Maste 
538ac7ddfbfSEd Maste     Options *
539ac7ddfbfSEd Maste     GetOptions ()
540ac7ddfbfSEd Maste     {
541ac7ddfbfSEd Maste         return &m_options;
542ac7ddfbfSEd Maste     }
543ac7ddfbfSEd Maste 
544ac7ddfbfSEd Maste protected:
545ac7ddfbfSEd Maste     bool
546ac7ddfbfSEd Maste     DoExecute (Args& command,
547ac7ddfbfSEd Maste              CommandReturnObject &result)
548ac7ddfbfSEd Maste     {
549ac7ddfbfSEd Maste         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
550ac7ddfbfSEd Maste         // N.B. The attach should be synchronous.  It doesn't help much to get the prompt back between initiating the attach
551ac7ddfbfSEd Maste         // and the target actually stopping.  So even if the interpreter is set to be asynchronous, we wait for the stop
552ac7ddfbfSEd Maste         // ourselves here.
553ac7ddfbfSEd Maste 
554ac7ddfbfSEd Maste         StateType state = eStateInvalid;
555ac7ddfbfSEd Maste         Process *process = m_exe_ctx.GetProcessPtr();
556ac7ddfbfSEd Maste 
557ac7ddfbfSEd Maste         if (!StopProcessIfNecessary (process, state, result))
558ac7ddfbfSEd Maste             return false;
559ac7ddfbfSEd Maste 
560ac7ddfbfSEd Maste         if (target == NULL)
561ac7ddfbfSEd Maste         {
562ac7ddfbfSEd Maste             // If there isn't a current target create one.
563ac7ddfbfSEd Maste             TargetSP new_target_sp;
564ac7ddfbfSEd Maste             Error error;
565ac7ddfbfSEd Maste 
566ac7ddfbfSEd Maste             error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(),
567ac7ddfbfSEd Maste                                                                               NULL,
568ac7ddfbfSEd Maste                                                                               NULL,
569ac7ddfbfSEd Maste                                                                               false,
570ac7ddfbfSEd Maste                                                                               NULL, // No platform options
571ac7ddfbfSEd Maste                                                                               new_target_sp);
572ac7ddfbfSEd Maste             target = new_target_sp.get();
573ac7ddfbfSEd Maste             if (target == NULL || error.Fail())
574ac7ddfbfSEd Maste             {
575ac7ddfbfSEd Maste                 result.AppendError(error.AsCString("Error creating target"));
576ac7ddfbfSEd Maste                 return false;
577ac7ddfbfSEd Maste             }
578ac7ddfbfSEd Maste             m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target);
579ac7ddfbfSEd Maste         }
580ac7ddfbfSEd Maste 
581ac7ddfbfSEd Maste         // Record the old executable module, we want to issue a warning if the process of attaching changed the
582ac7ddfbfSEd Maste         // current executable (like somebody said "file foo" then attached to a PID whose executable was bar.)
583ac7ddfbfSEd Maste 
584ac7ddfbfSEd Maste         ModuleSP old_exec_module_sp = target->GetExecutableModule();
585ac7ddfbfSEd Maste         ArchSpec old_arch_spec = target->GetArchitecture();
586ac7ddfbfSEd Maste 
587ac7ddfbfSEd Maste         if (command.GetArgumentCount())
588ac7ddfbfSEd Maste         {
589ac7ddfbfSEd Maste             result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: %s\n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
590ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
591ac7ddfbfSEd Maste         }
592ac7ddfbfSEd Maste         else
593ac7ddfbfSEd Maste         {
594ac7ddfbfSEd Maste             if (state != eStateConnected)
595ac7ddfbfSEd Maste             {
596ac7ddfbfSEd Maste                 const char *plugin_name = m_options.attach_info.GetProcessPluginName();
597ac7ddfbfSEd Maste                 process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name, NULL).get();
598ac7ddfbfSEd Maste             }
599ac7ddfbfSEd Maste 
600ac7ddfbfSEd Maste             if (process)
601ac7ddfbfSEd Maste             {
602ac7ddfbfSEd Maste                 Error error;
603ac7ddfbfSEd Maste                 // If no process info was specified, then use the target executable
604ac7ddfbfSEd Maste                 // name as the process to attach to by default
605ac7ddfbfSEd Maste                 if (!m_options.attach_info.ProcessInfoSpecified ())
606ac7ddfbfSEd Maste                 {
607ac7ddfbfSEd Maste                     if (old_exec_module_sp)
608ac7ddfbfSEd Maste                         m_options.attach_info.GetExecutableFile().GetFilename() = old_exec_module_sp->GetPlatformFileSpec().GetFilename();
609ac7ddfbfSEd Maste 
610ac7ddfbfSEd Maste                     if (!m_options.attach_info.ProcessInfoSpecified ())
611ac7ddfbfSEd Maste                     {
612ac7ddfbfSEd Maste                         error.SetErrorString ("no process specified, create a target with a file, or specify the --pid or --name command option");
613ac7ddfbfSEd Maste                     }
614ac7ddfbfSEd Maste                 }
615ac7ddfbfSEd Maste 
616ac7ddfbfSEd Maste                 if (error.Success())
617ac7ddfbfSEd Maste                 {
618ac7ddfbfSEd Maste                     error = process->Attach (m_options.attach_info);
619ac7ddfbfSEd Maste 
620ac7ddfbfSEd Maste                     if (error.Success())
621ac7ddfbfSEd Maste                     {
622ac7ddfbfSEd Maste                         result.SetStatus (eReturnStatusSuccessContinuingNoResult);
623ac7ddfbfSEd Maste                     }
624ac7ddfbfSEd Maste                     else
625ac7ddfbfSEd Maste                     {
626ac7ddfbfSEd Maste                         result.AppendErrorWithFormat ("attach failed: %s\n", error.AsCString());
627ac7ddfbfSEd Maste                         result.SetStatus (eReturnStatusFailed);
628ac7ddfbfSEd Maste                         return false;
629ac7ddfbfSEd Maste                     }
630ac7ddfbfSEd Maste                     // If we're synchronous, wait for the stopped event and report that.
631ac7ddfbfSEd Maste                     // Otherwise just return.
632ac7ddfbfSEd Maste                     // FIXME: in the async case it will now be possible to get to the command
633ac7ddfbfSEd Maste                     // interpreter with a state eStateAttaching.  Make sure we handle that correctly.
634ac7ddfbfSEd Maste                     StateType state = process->WaitForProcessToStop (NULL);
635ac7ddfbfSEd Maste 
636ac7ddfbfSEd Maste                     result.SetDidChangeProcessState (true);
637ac7ddfbfSEd Maste 
638ac7ddfbfSEd Maste                     if (state == eStateStopped)
639ac7ddfbfSEd Maste                     {
640ac7ddfbfSEd Maste                         result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state));
641ac7ddfbfSEd Maste                         result.SetStatus (eReturnStatusSuccessFinishNoResult);
642ac7ddfbfSEd Maste                     }
643ac7ddfbfSEd Maste                     else
644ac7ddfbfSEd Maste                     {
645ac7ddfbfSEd Maste                         result.AppendError ("attach failed: process did not stop (no such process or permission problem?)");
646ac7ddfbfSEd Maste                         process->Destroy();
647ac7ddfbfSEd Maste                         result.SetStatus (eReturnStatusFailed);
648ac7ddfbfSEd Maste                         return false;
649ac7ddfbfSEd Maste                     }
650ac7ddfbfSEd Maste                 }
651ac7ddfbfSEd Maste             }
652ac7ddfbfSEd Maste         }
653ac7ddfbfSEd Maste 
654ac7ddfbfSEd Maste         if (result.Succeeded())
655ac7ddfbfSEd Maste         {
656ac7ddfbfSEd Maste             // Okay, we're done.  Last step is to warn if the executable module has changed:
657ac7ddfbfSEd Maste             char new_path[PATH_MAX];
658ac7ddfbfSEd Maste             ModuleSP new_exec_module_sp (target->GetExecutableModule());
659ac7ddfbfSEd Maste             if (!old_exec_module_sp)
660ac7ddfbfSEd Maste             {
661ac7ddfbfSEd Maste                 // We might not have a module if we attached to a raw pid...
662ac7ddfbfSEd Maste                 if (new_exec_module_sp)
663ac7ddfbfSEd Maste                 {
664ac7ddfbfSEd Maste                     new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX);
665ac7ddfbfSEd Maste                     result.AppendMessageWithFormat("Executable module set to \"%s\".\n", new_path);
666ac7ddfbfSEd Maste                 }
667ac7ddfbfSEd Maste             }
668ac7ddfbfSEd Maste             else if (old_exec_module_sp->GetFileSpec() != new_exec_module_sp->GetFileSpec())
669ac7ddfbfSEd Maste             {
670ac7ddfbfSEd Maste                 char old_path[PATH_MAX];
671ac7ddfbfSEd Maste 
672ac7ddfbfSEd Maste                 old_exec_module_sp->GetFileSpec().GetPath (old_path, PATH_MAX);
673ac7ddfbfSEd Maste                 new_exec_module_sp->GetFileSpec().GetPath (new_path, PATH_MAX);
674ac7ddfbfSEd Maste 
675ac7ddfbfSEd Maste                 result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n",
676ac7ddfbfSEd Maste                                                     old_path, new_path);
677ac7ddfbfSEd Maste             }
678ac7ddfbfSEd Maste 
679ac7ddfbfSEd Maste             if (!old_arch_spec.IsValid())
680ac7ddfbfSEd Maste             {
681ac7ddfbfSEd Maste                 result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().GetTriple().getTriple().c_str());
682ac7ddfbfSEd Maste             }
683ac7ddfbfSEd Maste             else if (!old_arch_spec.IsExactMatch(target->GetArchitecture()))
684ac7ddfbfSEd Maste             {
685ac7ddfbfSEd Maste                 result.AppendWarningWithFormat("Architecture changed from %s to %s.\n",
686ac7ddfbfSEd Maste                                                old_arch_spec.GetTriple().getTriple().c_str(),
687ac7ddfbfSEd Maste                                                target->GetArchitecture().GetTriple().getTriple().c_str());
688ac7ddfbfSEd Maste             }
689ac7ddfbfSEd Maste 
690ac7ddfbfSEd Maste             // This supports the use-case scenario of immediately continuing the process once attached.
691ac7ddfbfSEd Maste             if (m_options.attach_info.GetContinueOnceAttached())
692ac7ddfbfSEd Maste                 m_interpreter.HandleCommand("process continue", eLazyBoolNo, result);
693ac7ddfbfSEd Maste         }
694ac7ddfbfSEd Maste         return result.Succeeded();
695ac7ddfbfSEd Maste     }
696ac7ddfbfSEd Maste 
697ac7ddfbfSEd Maste     CommandOptions m_options;
698ac7ddfbfSEd Maste };
699ac7ddfbfSEd Maste 
700ac7ddfbfSEd Maste 
701ac7ddfbfSEd Maste OptionDefinition
702ac7ddfbfSEd Maste CommandObjectProcessAttach::CommandOptions::g_option_table[] =
703ac7ddfbfSEd Maste {
704ac7ddfbfSEd Maste { LLDB_OPT_SET_ALL, false, "continue",'c', no_argument,         NULL, 0, eArgTypeNone,         "Immediately continue the process once attached."},
705ac7ddfbfSEd Maste { LLDB_OPT_SET_ALL, false, "plugin",  'P', required_argument,   NULL, 0, eArgTypePlugin,       "Name of the process plugin you want to use."},
706ac7ddfbfSEd Maste { LLDB_OPT_SET_1,   false, "pid",     'p', required_argument,   NULL, 0, eArgTypePid,          "The process ID of an existing process to attach to."},
707ac7ddfbfSEd Maste { LLDB_OPT_SET_2,   false, "name",    'n', required_argument,   NULL, 0, eArgTypeProcessName,  "The name of the process to attach to."},
708ac7ddfbfSEd Maste { LLDB_OPT_SET_2,   false, "include-existing", 'i', no_argument, NULL, 0, eArgTypeNone,         "Include existing processes when doing attach -w."},
709ac7ddfbfSEd Maste { LLDB_OPT_SET_2,   false, "waitfor", 'w', no_argument,         NULL, 0, eArgTypeNone,         "Wait for the process with <process-name> to launch."},
710ac7ddfbfSEd Maste { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
711ac7ddfbfSEd Maste };
712ac7ddfbfSEd Maste 
713ac7ddfbfSEd Maste //-------------------------------------------------------------------------
714ac7ddfbfSEd Maste // CommandObjectProcessContinue
715ac7ddfbfSEd Maste //-------------------------------------------------------------------------
716ac7ddfbfSEd Maste #pragma mark CommandObjectProcessContinue
717ac7ddfbfSEd Maste 
718ac7ddfbfSEd Maste class CommandObjectProcessContinue : public CommandObjectParsed
719ac7ddfbfSEd Maste {
720ac7ddfbfSEd Maste public:
721ac7ddfbfSEd Maste 
722ac7ddfbfSEd Maste     CommandObjectProcessContinue (CommandInterpreter &interpreter) :
723ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
724ac7ddfbfSEd Maste                              "process continue",
725ac7ddfbfSEd Maste                              "Continue execution of all threads in the current process.",
726ac7ddfbfSEd Maste                              "process continue",
727ac7ddfbfSEd Maste                              eFlagRequiresProcess       |
728ac7ddfbfSEd Maste                              eFlagTryTargetAPILock      |
729ac7ddfbfSEd Maste                              eFlagProcessMustBeLaunched |
730ac7ddfbfSEd Maste                              eFlagProcessMustBePaused   ),
731ac7ddfbfSEd Maste         m_options(interpreter)
732ac7ddfbfSEd Maste     {
733ac7ddfbfSEd Maste     }
734ac7ddfbfSEd Maste 
735ac7ddfbfSEd Maste 
736ac7ddfbfSEd Maste     ~CommandObjectProcessContinue ()
737ac7ddfbfSEd Maste     {
738ac7ddfbfSEd Maste     }
739ac7ddfbfSEd Maste 
740ac7ddfbfSEd Maste protected:
741ac7ddfbfSEd Maste 
742ac7ddfbfSEd Maste     class CommandOptions : public Options
743ac7ddfbfSEd Maste     {
744ac7ddfbfSEd Maste     public:
745ac7ddfbfSEd Maste 
746ac7ddfbfSEd Maste         CommandOptions (CommandInterpreter &interpreter) :
747ac7ddfbfSEd Maste             Options(interpreter)
748ac7ddfbfSEd Maste         {
749ac7ddfbfSEd Maste             // Keep default values of all options in one place: OptionParsingStarting ()
750ac7ddfbfSEd Maste             OptionParsingStarting ();
751ac7ddfbfSEd Maste         }
752ac7ddfbfSEd Maste 
753ac7ddfbfSEd Maste         ~CommandOptions ()
754ac7ddfbfSEd Maste         {
755ac7ddfbfSEd Maste         }
756ac7ddfbfSEd Maste 
757ac7ddfbfSEd Maste         Error
758ac7ddfbfSEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg)
759ac7ddfbfSEd Maste         {
760ac7ddfbfSEd Maste             Error error;
761ac7ddfbfSEd Maste             const int short_option = m_getopt_table[option_idx].val;
762ac7ddfbfSEd Maste             bool success = false;
763ac7ddfbfSEd Maste             switch (short_option)
764ac7ddfbfSEd Maste             {
765ac7ddfbfSEd Maste                 case 'i':
766ac7ddfbfSEd Maste                     m_ignore = Args::StringToUInt32 (option_arg, 0, 0, &success);
767ac7ddfbfSEd Maste                     if (!success)
768ac7ddfbfSEd Maste                         error.SetErrorStringWithFormat ("invalid value for ignore option: \"%s\", should be a number.", option_arg);
769ac7ddfbfSEd Maste                     break;
770ac7ddfbfSEd Maste 
771ac7ddfbfSEd Maste                 default:
772ac7ddfbfSEd Maste                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
773ac7ddfbfSEd Maste                     break;
774ac7ddfbfSEd Maste             }
775ac7ddfbfSEd Maste             return error;
776ac7ddfbfSEd Maste         }
777ac7ddfbfSEd Maste 
778ac7ddfbfSEd Maste         void
779ac7ddfbfSEd Maste         OptionParsingStarting ()
780ac7ddfbfSEd Maste         {
781ac7ddfbfSEd Maste             m_ignore = 0;
782ac7ddfbfSEd Maste         }
783ac7ddfbfSEd Maste 
784ac7ddfbfSEd Maste         const OptionDefinition*
785ac7ddfbfSEd Maste         GetDefinitions ()
786ac7ddfbfSEd Maste         {
787ac7ddfbfSEd Maste             return g_option_table;
788ac7ddfbfSEd Maste         }
789ac7ddfbfSEd Maste 
790ac7ddfbfSEd Maste         // Options table: Required for subclasses of Options.
791ac7ddfbfSEd Maste 
792ac7ddfbfSEd Maste         static OptionDefinition g_option_table[];
793ac7ddfbfSEd Maste 
794ac7ddfbfSEd Maste         uint32_t m_ignore;
795ac7ddfbfSEd Maste     };
796ac7ddfbfSEd Maste 
797ac7ddfbfSEd Maste     bool
798ac7ddfbfSEd Maste     DoExecute (Args& command, CommandReturnObject &result)
799ac7ddfbfSEd Maste     {
800ac7ddfbfSEd Maste         Process *process = m_exe_ctx.GetProcessPtr();
801ac7ddfbfSEd Maste         bool synchronous_execution = m_interpreter.GetSynchronous ();
802ac7ddfbfSEd Maste         StateType state = process->GetState();
803ac7ddfbfSEd Maste         if (state == eStateStopped)
804ac7ddfbfSEd Maste         {
805ac7ddfbfSEd Maste             if (command.GetArgumentCount() != 0)
806ac7ddfbfSEd Maste             {
807ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str());
808ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
809ac7ddfbfSEd Maste                 return false;
810ac7ddfbfSEd Maste             }
811ac7ddfbfSEd Maste 
812ac7ddfbfSEd Maste             if (m_options.m_ignore > 0)
813ac7ddfbfSEd Maste             {
814ac7ddfbfSEd Maste                 ThreadSP sel_thread_sp(process->GetThreadList().GetSelectedThread());
815ac7ddfbfSEd Maste                 if (sel_thread_sp)
816ac7ddfbfSEd Maste                 {
817ac7ddfbfSEd Maste                     StopInfoSP stop_info_sp = sel_thread_sp->GetStopInfo();
818ac7ddfbfSEd Maste                     if (stop_info_sp && stop_info_sp->GetStopReason() == eStopReasonBreakpoint)
819ac7ddfbfSEd Maste                     {
820ac7ddfbfSEd Maste                         lldb::break_id_t bp_site_id = (lldb::break_id_t)stop_info_sp->GetValue();
821ac7ddfbfSEd Maste                         BreakpointSiteSP bp_site_sp(process->GetBreakpointSiteList().FindByID(bp_site_id));
822ac7ddfbfSEd Maste                         if (bp_site_sp)
823ac7ddfbfSEd Maste                         {
824ac7ddfbfSEd Maste                             const size_t num_owners = bp_site_sp->GetNumberOfOwners();
825ac7ddfbfSEd Maste                             for (size_t i = 0; i < num_owners; i++)
826ac7ddfbfSEd Maste                             {
827ac7ddfbfSEd Maste                                 Breakpoint &bp_ref = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint();
828ac7ddfbfSEd Maste                                 if (!bp_ref.IsInternal())
829ac7ddfbfSEd Maste                                 {
830ac7ddfbfSEd Maste                                     bp_ref.SetIgnoreCount(m_options.m_ignore);
831ac7ddfbfSEd Maste                                 }
832ac7ddfbfSEd Maste                             }
833ac7ddfbfSEd Maste                         }
834ac7ddfbfSEd Maste                     }
835ac7ddfbfSEd Maste                 }
836ac7ddfbfSEd Maste             }
837ac7ddfbfSEd Maste 
838ac7ddfbfSEd Maste             {  // Scope for thread list mutex:
839ac7ddfbfSEd Maste                 Mutex::Locker locker (process->GetThreadList().GetMutex());
840ac7ddfbfSEd Maste                 const uint32_t num_threads = process->GetThreadList().GetSize();
841ac7ddfbfSEd Maste 
842ac7ddfbfSEd Maste                 // Set the actions that the threads should each take when resuming
843ac7ddfbfSEd Maste                 for (uint32_t idx=0; idx<num_threads; ++idx)
844ac7ddfbfSEd Maste                 {
845ac7ddfbfSEd Maste                     process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning);
846ac7ddfbfSEd Maste                 }
847ac7ddfbfSEd Maste             }
848ac7ddfbfSEd Maste 
849ac7ddfbfSEd Maste             Error error(process->Resume());
850ac7ddfbfSEd Maste             if (error.Success())
851ac7ddfbfSEd Maste             {
852ac7ddfbfSEd Maste                 result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID());
853ac7ddfbfSEd Maste                 if (synchronous_execution)
854ac7ddfbfSEd Maste                 {
855ac7ddfbfSEd Maste                     state = process->WaitForProcessToStop (NULL);
856ac7ddfbfSEd Maste 
857ac7ddfbfSEd Maste                     result.SetDidChangeProcessState (true);
858ac7ddfbfSEd Maste                     result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state));
859ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
860ac7ddfbfSEd Maste                 }
861ac7ddfbfSEd Maste                 else
862ac7ddfbfSEd Maste                 {
863ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusSuccessContinuingNoResult);
864ac7ddfbfSEd Maste                 }
865ac7ddfbfSEd Maste             }
866ac7ddfbfSEd Maste             else
867ac7ddfbfSEd Maste             {
868ac7ddfbfSEd Maste                 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
869ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
870ac7ddfbfSEd Maste             }
871ac7ddfbfSEd Maste         }
872ac7ddfbfSEd Maste         else
873ac7ddfbfSEd Maste         {
874ac7ddfbfSEd Maste             result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
875ac7ddfbfSEd Maste                                          StateAsCString(state));
876ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
877ac7ddfbfSEd Maste         }
878ac7ddfbfSEd Maste         return result.Succeeded();
879ac7ddfbfSEd Maste     }
880ac7ddfbfSEd Maste 
881ac7ddfbfSEd Maste     Options *
882ac7ddfbfSEd Maste     GetOptions ()
883ac7ddfbfSEd Maste     {
884ac7ddfbfSEd Maste         return &m_options;
885ac7ddfbfSEd Maste     }
886ac7ddfbfSEd Maste 
887ac7ddfbfSEd Maste     CommandOptions m_options;
888ac7ddfbfSEd Maste 
889ac7ddfbfSEd Maste };
890ac7ddfbfSEd Maste 
891ac7ddfbfSEd Maste OptionDefinition
892ac7ddfbfSEd Maste CommandObjectProcessContinue::CommandOptions::g_option_table[] =
893ac7ddfbfSEd Maste {
894ac7ddfbfSEd Maste { LLDB_OPT_SET_ALL, false, "ignore-count",'i', required_argument,         NULL, 0, eArgTypeUnsignedInteger,
895ac7ddfbfSEd Maste                            "Ignore <N> crossings of the breakpoint (if it exists) for the currently selected thread."},
896ac7ddfbfSEd Maste { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
897ac7ddfbfSEd Maste };
898ac7ddfbfSEd Maste 
899ac7ddfbfSEd Maste //-------------------------------------------------------------------------
900ac7ddfbfSEd Maste // CommandObjectProcessDetach
901ac7ddfbfSEd Maste //-------------------------------------------------------------------------
902ac7ddfbfSEd Maste #pragma mark CommandObjectProcessDetach
903ac7ddfbfSEd Maste 
904ac7ddfbfSEd Maste class CommandObjectProcessDetach : public CommandObjectParsed
905ac7ddfbfSEd Maste {
906ac7ddfbfSEd Maste public:
907ac7ddfbfSEd Maste     class CommandOptions : public Options
908ac7ddfbfSEd Maste     {
909ac7ddfbfSEd Maste     public:
910ac7ddfbfSEd Maste 
911ac7ddfbfSEd Maste         CommandOptions (CommandInterpreter &interpreter) :
912ac7ddfbfSEd Maste             Options (interpreter)
913ac7ddfbfSEd Maste         {
914ac7ddfbfSEd Maste             OptionParsingStarting ();
915ac7ddfbfSEd Maste         }
916ac7ddfbfSEd Maste 
917ac7ddfbfSEd Maste         ~CommandOptions ()
918ac7ddfbfSEd Maste         {
919ac7ddfbfSEd Maste         }
920ac7ddfbfSEd Maste 
921ac7ddfbfSEd Maste         Error
922ac7ddfbfSEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg)
923ac7ddfbfSEd Maste         {
924ac7ddfbfSEd Maste             Error error;
925ac7ddfbfSEd Maste             const int short_option = m_getopt_table[option_idx].val;
926ac7ddfbfSEd Maste 
927ac7ddfbfSEd Maste             switch (short_option)
928ac7ddfbfSEd Maste             {
929ac7ddfbfSEd Maste                 case 's':
930ac7ddfbfSEd Maste                     bool tmp_result;
931ac7ddfbfSEd Maste                     bool success;
932ac7ddfbfSEd Maste                     tmp_result = Args::StringToBoolean(option_arg, false, &success);
933ac7ddfbfSEd Maste                     if (!success)
934ac7ddfbfSEd Maste                         error.SetErrorStringWithFormat("invalid boolean option: \"%s\"", option_arg);
935ac7ddfbfSEd Maste                     else
936ac7ddfbfSEd Maste                     {
937ac7ddfbfSEd Maste                         if (tmp_result)
938ac7ddfbfSEd Maste                             m_keep_stopped = eLazyBoolYes;
939ac7ddfbfSEd Maste                         else
940ac7ddfbfSEd Maste                             m_keep_stopped = eLazyBoolNo;
941ac7ddfbfSEd Maste                     }
942ac7ddfbfSEd Maste                     break;
943ac7ddfbfSEd Maste                 default:
944ac7ddfbfSEd Maste                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
945ac7ddfbfSEd Maste                     break;
946ac7ddfbfSEd Maste             }
947ac7ddfbfSEd Maste             return error;
948ac7ddfbfSEd Maste         }
949ac7ddfbfSEd Maste 
950ac7ddfbfSEd Maste         void
951ac7ddfbfSEd Maste         OptionParsingStarting ()
952ac7ddfbfSEd Maste         {
953ac7ddfbfSEd Maste             m_keep_stopped = eLazyBoolCalculate;
954ac7ddfbfSEd Maste         }
955ac7ddfbfSEd Maste 
956ac7ddfbfSEd Maste         const OptionDefinition*
957ac7ddfbfSEd Maste         GetDefinitions ()
958ac7ddfbfSEd Maste         {
959ac7ddfbfSEd Maste             return g_option_table;
960ac7ddfbfSEd Maste         }
961ac7ddfbfSEd Maste 
962ac7ddfbfSEd Maste         // Options table: Required for subclasses of Options.
963ac7ddfbfSEd Maste 
964ac7ddfbfSEd Maste         static OptionDefinition g_option_table[];
965ac7ddfbfSEd Maste 
966ac7ddfbfSEd Maste         // Instance variables to hold the values for command options.
967ac7ddfbfSEd Maste         LazyBool m_keep_stopped;
968ac7ddfbfSEd Maste     };
969ac7ddfbfSEd Maste 
970ac7ddfbfSEd Maste     CommandObjectProcessDetach (CommandInterpreter &interpreter) :
971ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
972ac7ddfbfSEd Maste                              "process detach",
973ac7ddfbfSEd Maste                              "Detach from the current process being debugged.",
974ac7ddfbfSEd Maste                              "process detach",
975ac7ddfbfSEd Maste                              eFlagRequiresProcess      |
976ac7ddfbfSEd Maste                              eFlagTryTargetAPILock     |
977ac7ddfbfSEd Maste                              eFlagProcessMustBeLaunched),
978ac7ddfbfSEd Maste         m_options(interpreter)
979ac7ddfbfSEd Maste     {
980ac7ddfbfSEd Maste     }
981ac7ddfbfSEd Maste 
982ac7ddfbfSEd Maste     ~CommandObjectProcessDetach ()
983ac7ddfbfSEd Maste     {
984ac7ddfbfSEd Maste     }
985ac7ddfbfSEd Maste 
986ac7ddfbfSEd Maste     Options *
987ac7ddfbfSEd Maste     GetOptions ()
988ac7ddfbfSEd Maste     {
989ac7ddfbfSEd Maste         return &m_options;
990ac7ddfbfSEd Maste     }
991ac7ddfbfSEd Maste 
992ac7ddfbfSEd Maste 
993ac7ddfbfSEd Maste protected:
994ac7ddfbfSEd Maste     bool
995ac7ddfbfSEd Maste     DoExecute (Args& command, CommandReturnObject &result)
996ac7ddfbfSEd Maste     {
997ac7ddfbfSEd Maste         Process *process = m_exe_ctx.GetProcessPtr();
998ac7ddfbfSEd Maste         result.AppendMessageWithFormat ("Detaching from process %" PRIu64 "\n", process->GetID());
999ac7ddfbfSEd Maste         // FIXME: This will be a Command Option:
1000ac7ddfbfSEd Maste         bool keep_stopped;
1001ac7ddfbfSEd Maste         if (m_options.m_keep_stopped == eLazyBoolCalculate)
1002ac7ddfbfSEd Maste         {
1003ac7ddfbfSEd Maste             // Check the process default:
1004ac7ddfbfSEd Maste             if (process->GetDetachKeepsStopped())
1005ac7ddfbfSEd Maste                 keep_stopped = true;
1006ac7ddfbfSEd Maste             else
1007ac7ddfbfSEd Maste                 keep_stopped = false;
1008ac7ddfbfSEd Maste         }
1009ac7ddfbfSEd Maste         else if (m_options.m_keep_stopped == eLazyBoolYes)
1010ac7ddfbfSEd Maste             keep_stopped = true;
1011ac7ddfbfSEd Maste         else
1012ac7ddfbfSEd Maste             keep_stopped = false;
1013ac7ddfbfSEd Maste 
1014ac7ddfbfSEd Maste         Error error (process->Detach(keep_stopped));
1015ac7ddfbfSEd Maste         if (error.Success())
1016ac7ddfbfSEd Maste         {
1017ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusSuccessFinishResult);
1018ac7ddfbfSEd Maste         }
1019ac7ddfbfSEd Maste         else
1020ac7ddfbfSEd Maste         {
1021ac7ddfbfSEd Maste             result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString());
1022ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1023ac7ddfbfSEd Maste             return false;
1024ac7ddfbfSEd Maste         }
1025ac7ddfbfSEd Maste         return result.Succeeded();
1026ac7ddfbfSEd Maste     }
1027ac7ddfbfSEd Maste 
1028ac7ddfbfSEd Maste     CommandOptions m_options;
1029ac7ddfbfSEd Maste };
1030ac7ddfbfSEd Maste 
1031ac7ddfbfSEd Maste OptionDefinition
1032ac7ddfbfSEd Maste CommandObjectProcessDetach::CommandOptions::g_option_table[] =
1033ac7ddfbfSEd Maste {
1034ac7ddfbfSEd Maste { LLDB_OPT_SET_1, false, "keep-stopped",   's', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the process should be kept stopped on detach (if possible)." },
1035ac7ddfbfSEd Maste { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1036ac7ddfbfSEd Maste };
1037ac7ddfbfSEd Maste 
1038ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1039ac7ddfbfSEd Maste // CommandObjectProcessConnect
1040ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1041ac7ddfbfSEd Maste #pragma mark CommandObjectProcessConnect
1042ac7ddfbfSEd Maste 
1043ac7ddfbfSEd Maste class CommandObjectProcessConnect : public CommandObjectParsed
1044ac7ddfbfSEd Maste {
1045ac7ddfbfSEd Maste public:
1046ac7ddfbfSEd Maste 
1047ac7ddfbfSEd Maste     class CommandOptions : public Options
1048ac7ddfbfSEd Maste     {
1049ac7ddfbfSEd Maste     public:
1050ac7ddfbfSEd Maste 
1051ac7ddfbfSEd Maste         CommandOptions (CommandInterpreter &interpreter) :
1052ac7ddfbfSEd Maste             Options(interpreter)
1053ac7ddfbfSEd Maste         {
1054ac7ddfbfSEd Maste             // Keep default values of all options in one place: OptionParsingStarting ()
1055ac7ddfbfSEd Maste             OptionParsingStarting ();
1056ac7ddfbfSEd Maste         }
1057ac7ddfbfSEd Maste 
1058ac7ddfbfSEd Maste         ~CommandOptions ()
1059ac7ddfbfSEd Maste         {
1060ac7ddfbfSEd Maste         }
1061ac7ddfbfSEd Maste 
1062ac7ddfbfSEd Maste         Error
1063ac7ddfbfSEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg)
1064ac7ddfbfSEd Maste         {
1065ac7ddfbfSEd Maste             Error error;
1066ac7ddfbfSEd Maste             const int short_option = m_getopt_table[option_idx].val;
1067ac7ddfbfSEd Maste 
1068ac7ddfbfSEd Maste             switch (short_option)
1069ac7ddfbfSEd Maste             {
1070ac7ddfbfSEd Maste             case 'p':
1071ac7ddfbfSEd Maste                 plugin_name.assign (option_arg);
1072ac7ddfbfSEd Maste                 break;
1073ac7ddfbfSEd Maste 
1074ac7ddfbfSEd Maste             default:
1075ac7ddfbfSEd Maste                 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
1076ac7ddfbfSEd Maste                 break;
1077ac7ddfbfSEd Maste             }
1078ac7ddfbfSEd Maste             return error;
1079ac7ddfbfSEd Maste         }
1080ac7ddfbfSEd Maste 
1081ac7ddfbfSEd Maste         void
1082ac7ddfbfSEd Maste         OptionParsingStarting ()
1083ac7ddfbfSEd Maste         {
1084ac7ddfbfSEd Maste             plugin_name.clear();
1085ac7ddfbfSEd Maste         }
1086ac7ddfbfSEd Maste 
1087ac7ddfbfSEd Maste         const OptionDefinition*
1088ac7ddfbfSEd Maste         GetDefinitions ()
1089ac7ddfbfSEd Maste         {
1090ac7ddfbfSEd Maste             return g_option_table;
1091ac7ddfbfSEd Maste         }
1092ac7ddfbfSEd Maste 
1093ac7ddfbfSEd Maste         // Options table: Required for subclasses of Options.
1094ac7ddfbfSEd Maste 
1095ac7ddfbfSEd Maste         static OptionDefinition g_option_table[];
1096ac7ddfbfSEd Maste 
1097ac7ddfbfSEd Maste         // Instance variables to hold the values for command options.
1098ac7ddfbfSEd Maste 
1099ac7ddfbfSEd Maste         std::string plugin_name;
1100ac7ddfbfSEd Maste     };
1101ac7ddfbfSEd Maste 
1102ac7ddfbfSEd Maste     CommandObjectProcessConnect (CommandInterpreter &interpreter) :
1103ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
1104ac7ddfbfSEd Maste                              "process connect",
1105ac7ddfbfSEd Maste                              "Connect to a remote debug service.",
1106ac7ddfbfSEd Maste                              "process connect <remote-url>",
1107ac7ddfbfSEd Maste                              0),
1108ac7ddfbfSEd Maste         m_options (interpreter)
1109ac7ddfbfSEd Maste     {
1110ac7ddfbfSEd Maste     }
1111ac7ddfbfSEd Maste 
1112ac7ddfbfSEd Maste     ~CommandObjectProcessConnect ()
1113ac7ddfbfSEd Maste     {
1114ac7ddfbfSEd Maste     }
1115ac7ddfbfSEd Maste 
1116ac7ddfbfSEd Maste 
1117ac7ddfbfSEd Maste     Options *
1118ac7ddfbfSEd Maste     GetOptions ()
1119ac7ddfbfSEd Maste     {
1120ac7ddfbfSEd Maste         return &m_options;
1121ac7ddfbfSEd Maste     }
1122ac7ddfbfSEd Maste 
1123ac7ddfbfSEd Maste protected:
1124ac7ddfbfSEd Maste     bool
1125ac7ddfbfSEd Maste     DoExecute (Args& command,
1126ac7ddfbfSEd Maste              CommandReturnObject &result)
1127ac7ddfbfSEd Maste     {
1128ac7ddfbfSEd Maste 
1129ac7ddfbfSEd Maste         TargetSP target_sp (m_interpreter.GetDebugger().GetSelectedTarget());
1130ac7ddfbfSEd Maste         Error error;
1131ac7ddfbfSEd Maste         Process *process = m_exe_ctx.GetProcessPtr();
1132ac7ddfbfSEd Maste         if (process)
1133ac7ddfbfSEd Maste         {
1134ac7ddfbfSEd Maste             if (process->IsAlive())
1135ac7ddfbfSEd Maste             {
1136ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("Process %" PRIu64 " is currently being debugged, kill the process before connecting.\n",
1137ac7ddfbfSEd Maste                                               process->GetID());
1138ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1139ac7ddfbfSEd Maste                 return false;
1140ac7ddfbfSEd Maste             }
1141ac7ddfbfSEd Maste         }
1142ac7ddfbfSEd Maste 
1143ac7ddfbfSEd Maste         if (!target_sp)
1144ac7ddfbfSEd Maste         {
1145ac7ddfbfSEd Maste             // If there isn't a current target create one.
1146ac7ddfbfSEd Maste 
1147ac7ddfbfSEd Maste             error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(),
1148ac7ddfbfSEd Maste                                                                               NULL,
1149ac7ddfbfSEd Maste                                                                               NULL,
1150ac7ddfbfSEd Maste                                                                               false,
1151ac7ddfbfSEd Maste                                                                               NULL, // No platform options
1152ac7ddfbfSEd Maste                                                                               target_sp);
1153ac7ddfbfSEd Maste             if (!target_sp || error.Fail())
1154ac7ddfbfSEd Maste             {
1155ac7ddfbfSEd Maste                 result.AppendError(error.AsCString("Error creating target"));
1156ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1157ac7ddfbfSEd Maste                 return false;
1158ac7ddfbfSEd Maste             }
1159ac7ddfbfSEd Maste             m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target_sp.get());
1160ac7ddfbfSEd Maste         }
1161ac7ddfbfSEd Maste 
1162ac7ddfbfSEd Maste         if (command.GetArgumentCount() == 1)
1163ac7ddfbfSEd Maste         {
1164ac7ddfbfSEd Maste             const char *plugin_name = NULL;
1165ac7ddfbfSEd Maste             if (!m_options.plugin_name.empty())
1166ac7ddfbfSEd Maste                 plugin_name = m_options.plugin_name.c_str();
1167ac7ddfbfSEd Maste 
1168ac7ddfbfSEd Maste             const char *remote_url = command.GetArgumentAtIndex(0);
1169ac7ddfbfSEd Maste             process = target_sp->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name, NULL).get();
1170ac7ddfbfSEd Maste 
1171ac7ddfbfSEd Maste             if (process)
1172ac7ddfbfSEd Maste             {
1173ac7ddfbfSEd Maste                 error = process->ConnectRemote (&process->GetTarget().GetDebugger().GetOutputStream(), remote_url);
1174ac7ddfbfSEd Maste 
1175ac7ddfbfSEd Maste                 if (error.Fail())
1176ac7ddfbfSEd Maste                 {
1177ac7ddfbfSEd Maste                     result.AppendError(error.AsCString("Remote connect failed"));
1178ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
1179ac7ddfbfSEd Maste                     target_sp->DeleteCurrentProcess();
1180ac7ddfbfSEd Maste                     return false;
1181ac7ddfbfSEd Maste                 }
1182ac7ddfbfSEd Maste             }
1183ac7ddfbfSEd Maste             else
1184ac7ddfbfSEd Maste             {
1185ac7ddfbfSEd Maste                 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",
1186ac7ddfbfSEd Maste                                               remote_url);
1187ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1188ac7ddfbfSEd Maste             }
1189ac7ddfbfSEd Maste         }
1190ac7ddfbfSEd Maste         else
1191ac7ddfbfSEd Maste         {
1192ac7ddfbfSEd Maste             result.AppendErrorWithFormat ("'%s' takes exactly one argument:\nUsage: %s\n",
1193ac7ddfbfSEd Maste                                           m_cmd_name.c_str(),
1194ac7ddfbfSEd Maste                                           m_cmd_syntax.c_str());
1195ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1196ac7ddfbfSEd Maste         }
1197ac7ddfbfSEd Maste         return result.Succeeded();
1198ac7ddfbfSEd Maste     }
1199ac7ddfbfSEd Maste 
1200ac7ddfbfSEd Maste     CommandOptions m_options;
1201ac7ddfbfSEd Maste };
1202ac7ddfbfSEd Maste 
1203ac7ddfbfSEd Maste OptionDefinition
1204ac7ddfbfSEd Maste CommandObjectProcessConnect::CommandOptions::g_option_table[] =
1205ac7ddfbfSEd Maste {
1206ac7ddfbfSEd Maste     { LLDB_OPT_SET_ALL, false, "plugin", 'p', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
1207ac7ddfbfSEd Maste     { 0,                false, NULL,      0 , 0,                 NULL, 0, eArgTypeNone,   NULL }
1208ac7ddfbfSEd Maste };
1209ac7ddfbfSEd Maste 
1210ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1211ac7ddfbfSEd Maste // CommandObjectProcessPlugin
1212ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1213ac7ddfbfSEd Maste #pragma mark CommandObjectProcessPlugin
1214ac7ddfbfSEd Maste 
1215ac7ddfbfSEd Maste class CommandObjectProcessPlugin : public CommandObjectProxy
1216ac7ddfbfSEd Maste {
1217ac7ddfbfSEd Maste public:
1218ac7ddfbfSEd Maste 
1219ac7ddfbfSEd Maste     CommandObjectProcessPlugin (CommandInterpreter &interpreter) :
1220ac7ddfbfSEd Maste         CommandObjectProxy (interpreter,
1221ac7ddfbfSEd Maste                             "process plugin",
1222ac7ddfbfSEd Maste                             "Send a custom command to the current process plug-in.",
1223ac7ddfbfSEd Maste                             "process plugin <args>",
1224ac7ddfbfSEd Maste                             0)
1225ac7ddfbfSEd Maste     {
1226ac7ddfbfSEd Maste     }
1227ac7ddfbfSEd Maste 
1228ac7ddfbfSEd Maste     ~CommandObjectProcessPlugin ()
1229ac7ddfbfSEd Maste     {
1230ac7ddfbfSEd Maste     }
1231ac7ddfbfSEd Maste 
1232ac7ddfbfSEd Maste     virtual CommandObject *
1233ac7ddfbfSEd Maste     GetProxyCommandObject()
1234ac7ddfbfSEd Maste     {
1235ac7ddfbfSEd Maste         Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
1236ac7ddfbfSEd Maste         if (process)
1237ac7ddfbfSEd Maste             return process->GetPluginCommandObject();
1238ac7ddfbfSEd Maste         return NULL;
1239ac7ddfbfSEd Maste     }
1240ac7ddfbfSEd Maste };
1241ac7ddfbfSEd Maste 
1242ac7ddfbfSEd Maste 
1243ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1244ac7ddfbfSEd Maste // CommandObjectProcessLoad
1245ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1246ac7ddfbfSEd Maste #pragma mark CommandObjectProcessLoad
1247ac7ddfbfSEd Maste 
1248ac7ddfbfSEd Maste class CommandObjectProcessLoad : public CommandObjectParsed
1249ac7ddfbfSEd Maste {
1250ac7ddfbfSEd Maste public:
1251ac7ddfbfSEd Maste 
1252ac7ddfbfSEd Maste     CommandObjectProcessLoad (CommandInterpreter &interpreter) :
1253ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
1254ac7ddfbfSEd Maste                              "process load",
1255ac7ddfbfSEd Maste                              "Load a shared library into the current process.",
1256ac7ddfbfSEd Maste                              "process load <filename> [<filename> ...]",
1257ac7ddfbfSEd Maste                              eFlagRequiresProcess       |
1258ac7ddfbfSEd Maste                              eFlagTryTargetAPILock      |
1259ac7ddfbfSEd Maste                              eFlagProcessMustBeLaunched |
1260ac7ddfbfSEd Maste                              eFlagProcessMustBePaused   )
1261ac7ddfbfSEd Maste     {
1262ac7ddfbfSEd Maste     }
1263ac7ddfbfSEd Maste 
1264ac7ddfbfSEd Maste     ~CommandObjectProcessLoad ()
1265ac7ddfbfSEd Maste     {
1266ac7ddfbfSEd Maste     }
1267ac7ddfbfSEd Maste 
1268ac7ddfbfSEd Maste protected:
1269ac7ddfbfSEd Maste     bool
1270ac7ddfbfSEd Maste     DoExecute (Args& command,
1271ac7ddfbfSEd Maste              CommandReturnObject &result)
1272ac7ddfbfSEd Maste     {
1273ac7ddfbfSEd Maste         Process *process = m_exe_ctx.GetProcessPtr();
1274ac7ddfbfSEd Maste 
1275ac7ddfbfSEd Maste         const size_t argc = command.GetArgumentCount();
1276ac7ddfbfSEd Maste 
1277ac7ddfbfSEd Maste         for (uint32_t i=0; i<argc; ++i)
1278ac7ddfbfSEd Maste         {
1279ac7ddfbfSEd Maste             Error error;
1280ac7ddfbfSEd Maste             const char *image_path = command.GetArgumentAtIndex(i);
1281ac7ddfbfSEd Maste             FileSpec image_spec (image_path, false);
1282ac7ddfbfSEd Maste             process->GetTarget().GetPlatform()->ResolveRemotePath(image_spec, image_spec);
1283ac7ddfbfSEd Maste             uint32_t image_token = process->LoadImage(image_spec, error);
1284ac7ddfbfSEd Maste             if (image_token != LLDB_INVALID_IMAGE_TOKEN)
1285ac7ddfbfSEd Maste             {
1286ac7ddfbfSEd Maste                 result.AppendMessageWithFormat ("Loading \"%s\"...ok\nImage %u loaded.\n", image_path, image_token);
1287ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusSuccessFinishResult);
1288ac7ddfbfSEd Maste             }
1289ac7ddfbfSEd Maste             else
1290ac7ddfbfSEd Maste             {
1291ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("failed to load '%s': %s", image_path, error.AsCString());
1292ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1293ac7ddfbfSEd Maste             }
1294ac7ddfbfSEd Maste         }
1295ac7ddfbfSEd Maste         return result.Succeeded();
1296ac7ddfbfSEd Maste     }
1297ac7ddfbfSEd Maste };
1298ac7ddfbfSEd Maste 
1299ac7ddfbfSEd Maste 
1300ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1301ac7ddfbfSEd Maste // CommandObjectProcessUnload
1302ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1303ac7ddfbfSEd Maste #pragma mark CommandObjectProcessUnload
1304ac7ddfbfSEd Maste 
1305ac7ddfbfSEd Maste class CommandObjectProcessUnload : public CommandObjectParsed
1306ac7ddfbfSEd Maste {
1307ac7ddfbfSEd Maste public:
1308ac7ddfbfSEd Maste 
1309ac7ddfbfSEd Maste     CommandObjectProcessUnload (CommandInterpreter &interpreter) :
1310ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
1311ac7ddfbfSEd Maste                              "process unload",
1312ac7ddfbfSEd Maste                              "Unload a shared library from the current process using the index returned by a previous call to \"process load\".",
1313ac7ddfbfSEd Maste                              "process unload <index>",
1314ac7ddfbfSEd Maste                              eFlagRequiresProcess       |
1315ac7ddfbfSEd Maste                              eFlagTryTargetAPILock      |
1316ac7ddfbfSEd Maste                              eFlagProcessMustBeLaunched |
1317ac7ddfbfSEd Maste                              eFlagProcessMustBePaused   )
1318ac7ddfbfSEd Maste     {
1319ac7ddfbfSEd Maste     }
1320ac7ddfbfSEd Maste 
1321ac7ddfbfSEd Maste     ~CommandObjectProcessUnload ()
1322ac7ddfbfSEd Maste     {
1323ac7ddfbfSEd Maste     }
1324ac7ddfbfSEd Maste 
1325ac7ddfbfSEd Maste protected:
1326ac7ddfbfSEd Maste     bool
1327ac7ddfbfSEd Maste     DoExecute (Args& command,
1328ac7ddfbfSEd Maste              CommandReturnObject &result)
1329ac7ddfbfSEd Maste     {
1330ac7ddfbfSEd Maste         Process *process = m_exe_ctx.GetProcessPtr();
1331ac7ddfbfSEd Maste 
1332ac7ddfbfSEd Maste         const size_t argc = command.GetArgumentCount();
1333ac7ddfbfSEd Maste 
1334ac7ddfbfSEd Maste         for (uint32_t i=0; i<argc; ++i)
1335ac7ddfbfSEd Maste         {
1336ac7ddfbfSEd Maste             const char *image_token_cstr = command.GetArgumentAtIndex(i);
1337ac7ddfbfSEd Maste             uint32_t image_token = Args::StringToUInt32(image_token_cstr, LLDB_INVALID_IMAGE_TOKEN, 0);
1338ac7ddfbfSEd Maste             if (image_token == LLDB_INVALID_IMAGE_TOKEN)
1339ac7ddfbfSEd Maste             {
1340ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("invalid image index argument '%s'", image_token_cstr);
1341ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1342ac7ddfbfSEd Maste                 break;
1343ac7ddfbfSEd Maste             }
1344ac7ddfbfSEd Maste             else
1345ac7ddfbfSEd Maste             {
1346ac7ddfbfSEd Maste                 Error error (process->UnloadImage(image_token));
1347ac7ddfbfSEd Maste                 if (error.Success())
1348ac7ddfbfSEd Maste                 {
1349ac7ddfbfSEd Maste                     result.AppendMessageWithFormat ("Unloading shared library with index %u...ok\n", image_token);
1350ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusSuccessFinishResult);
1351ac7ddfbfSEd Maste                 }
1352ac7ddfbfSEd Maste                 else
1353ac7ddfbfSEd Maste                 {
1354ac7ddfbfSEd Maste                     result.AppendErrorWithFormat ("failed to unload image: %s", error.AsCString());
1355ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
1356ac7ddfbfSEd Maste                     break;
1357ac7ddfbfSEd Maste                 }
1358ac7ddfbfSEd Maste             }
1359ac7ddfbfSEd Maste         }
1360ac7ddfbfSEd Maste         return result.Succeeded();
1361ac7ddfbfSEd Maste     }
1362ac7ddfbfSEd Maste };
1363ac7ddfbfSEd Maste 
1364ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1365ac7ddfbfSEd Maste // CommandObjectProcessSignal
1366ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1367ac7ddfbfSEd Maste #pragma mark CommandObjectProcessSignal
1368ac7ddfbfSEd Maste 
1369ac7ddfbfSEd Maste class CommandObjectProcessSignal : public CommandObjectParsed
1370ac7ddfbfSEd Maste {
1371ac7ddfbfSEd Maste public:
1372ac7ddfbfSEd Maste 
1373ac7ddfbfSEd Maste     CommandObjectProcessSignal (CommandInterpreter &interpreter) :
1374ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
1375ac7ddfbfSEd Maste                              "process signal",
1376ac7ddfbfSEd Maste                              "Send a UNIX signal to the current process being debugged.",
1377ac7ddfbfSEd Maste                              NULL,
1378ac7ddfbfSEd Maste                              eFlagRequiresProcess | eFlagTryTargetAPILock)
1379ac7ddfbfSEd Maste     {
1380ac7ddfbfSEd Maste         CommandArgumentEntry arg;
1381ac7ddfbfSEd Maste         CommandArgumentData signal_arg;
1382ac7ddfbfSEd Maste 
1383ac7ddfbfSEd Maste         // Define the first (and only) variant of this arg.
1384ac7ddfbfSEd Maste         signal_arg.arg_type = eArgTypeUnixSignal;
1385ac7ddfbfSEd Maste         signal_arg.arg_repetition = eArgRepeatPlain;
1386ac7ddfbfSEd Maste 
1387ac7ddfbfSEd Maste         // There is only one variant this argument could be; put it into the argument entry.
1388ac7ddfbfSEd Maste         arg.push_back (signal_arg);
1389ac7ddfbfSEd Maste 
1390ac7ddfbfSEd Maste         // Push the data for the first argument into the m_arguments vector.
1391ac7ddfbfSEd Maste         m_arguments.push_back (arg);
1392ac7ddfbfSEd Maste     }
1393ac7ddfbfSEd Maste 
1394ac7ddfbfSEd Maste     ~CommandObjectProcessSignal ()
1395ac7ddfbfSEd Maste     {
1396ac7ddfbfSEd Maste     }
1397ac7ddfbfSEd Maste 
1398ac7ddfbfSEd Maste protected:
1399ac7ddfbfSEd Maste     bool
1400ac7ddfbfSEd Maste     DoExecute (Args& command,
1401ac7ddfbfSEd Maste              CommandReturnObject &result)
1402ac7ddfbfSEd Maste     {
1403ac7ddfbfSEd Maste         Process *process = m_exe_ctx.GetProcessPtr();
1404ac7ddfbfSEd Maste 
1405ac7ddfbfSEd Maste         if (command.GetArgumentCount() == 1)
1406ac7ddfbfSEd Maste         {
1407ac7ddfbfSEd Maste             int signo = LLDB_INVALID_SIGNAL_NUMBER;
1408ac7ddfbfSEd Maste 
1409ac7ddfbfSEd Maste             const char *signal_name = command.GetArgumentAtIndex(0);
1410ac7ddfbfSEd Maste             if (::isxdigit (signal_name[0]))
1411ac7ddfbfSEd Maste                 signo = Args::StringToSInt32(signal_name, LLDB_INVALID_SIGNAL_NUMBER, 0);
1412ac7ddfbfSEd Maste             else
1413ac7ddfbfSEd Maste                 signo = process->GetUnixSignals().GetSignalNumberFromName (signal_name);
1414ac7ddfbfSEd Maste 
1415ac7ddfbfSEd Maste             if (signo == LLDB_INVALID_SIGNAL_NUMBER)
1416ac7ddfbfSEd Maste             {
1417ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0));
1418ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1419ac7ddfbfSEd Maste             }
1420ac7ddfbfSEd Maste             else
1421ac7ddfbfSEd Maste             {
1422ac7ddfbfSEd Maste                 Error error (process->Signal (signo));
1423ac7ddfbfSEd Maste                 if (error.Success())
1424ac7ddfbfSEd Maste                 {
1425ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusSuccessFinishResult);
1426ac7ddfbfSEd Maste                 }
1427ac7ddfbfSEd Maste                 else
1428ac7ddfbfSEd Maste                 {
1429ac7ddfbfSEd Maste                     result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString());
1430ac7ddfbfSEd Maste                     result.SetStatus (eReturnStatusFailed);
1431ac7ddfbfSEd Maste                 }
1432ac7ddfbfSEd Maste             }
1433ac7ddfbfSEd Maste         }
1434ac7ddfbfSEd Maste         else
1435ac7ddfbfSEd Maste         {
1436ac7ddfbfSEd Maste             result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: %s\n", m_cmd_name.c_str(),
1437ac7ddfbfSEd Maste                                         m_cmd_syntax.c_str());
1438ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1439ac7ddfbfSEd Maste         }
1440ac7ddfbfSEd Maste         return result.Succeeded();
1441ac7ddfbfSEd Maste     }
1442ac7ddfbfSEd Maste };
1443ac7ddfbfSEd Maste 
1444ac7ddfbfSEd Maste 
1445ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1446ac7ddfbfSEd Maste // CommandObjectProcessInterrupt
1447ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1448ac7ddfbfSEd Maste #pragma mark CommandObjectProcessInterrupt
1449ac7ddfbfSEd Maste 
1450ac7ddfbfSEd Maste class CommandObjectProcessInterrupt : public CommandObjectParsed
1451ac7ddfbfSEd Maste {
1452ac7ddfbfSEd Maste public:
1453ac7ddfbfSEd Maste 
1454ac7ddfbfSEd Maste 
1455ac7ddfbfSEd Maste     CommandObjectProcessInterrupt (CommandInterpreter &interpreter) :
1456ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
1457ac7ddfbfSEd Maste                              "process interrupt",
1458ac7ddfbfSEd Maste                              "Interrupt the current process being debugged.",
1459ac7ddfbfSEd Maste                              "process interrupt",
1460ac7ddfbfSEd Maste                              eFlagRequiresProcess      |
1461ac7ddfbfSEd Maste                              eFlagTryTargetAPILock     |
1462ac7ddfbfSEd Maste                              eFlagProcessMustBeLaunched)
1463ac7ddfbfSEd Maste     {
1464ac7ddfbfSEd Maste     }
1465ac7ddfbfSEd Maste 
1466ac7ddfbfSEd Maste     ~CommandObjectProcessInterrupt ()
1467ac7ddfbfSEd Maste     {
1468ac7ddfbfSEd Maste     }
1469ac7ddfbfSEd Maste 
1470ac7ddfbfSEd Maste protected:
1471ac7ddfbfSEd Maste     bool
1472ac7ddfbfSEd Maste     DoExecute (Args& command,
1473ac7ddfbfSEd Maste                CommandReturnObject &result)
1474ac7ddfbfSEd Maste     {
1475ac7ddfbfSEd Maste         Process *process = m_exe_ctx.GetProcessPtr();
1476ac7ddfbfSEd Maste         if (process == NULL)
1477ac7ddfbfSEd Maste         {
1478ac7ddfbfSEd Maste             result.AppendError ("no process to halt");
1479ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1480ac7ddfbfSEd Maste             return false;
1481ac7ddfbfSEd Maste         }
1482ac7ddfbfSEd Maste 
1483ac7ddfbfSEd Maste         if (command.GetArgumentCount() == 0)
1484ac7ddfbfSEd Maste         {
1485ac7ddfbfSEd Maste             bool clear_thread_plans = true;
1486ac7ddfbfSEd Maste             Error error(process->Halt (clear_thread_plans));
1487ac7ddfbfSEd Maste             if (error.Success())
1488ac7ddfbfSEd Maste             {
1489ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusSuccessFinishResult);
1490ac7ddfbfSEd Maste             }
1491ac7ddfbfSEd Maste             else
1492ac7ddfbfSEd Maste             {
1493ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString());
1494ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1495ac7ddfbfSEd Maste             }
1496ac7ddfbfSEd Maste         }
1497ac7ddfbfSEd Maste         else
1498ac7ddfbfSEd Maste         {
1499ac7ddfbfSEd Maste             result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n",
1500ac7ddfbfSEd Maste                                         m_cmd_name.c_str(),
1501ac7ddfbfSEd Maste                                         m_cmd_syntax.c_str());
1502ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1503ac7ddfbfSEd Maste         }
1504ac7ddfbfSEd Maste         return result.Succeeded();
1505ac7ddfbfSEd Maste     }
1506ac7ddfbfSEd Maste };
1507ac7ddfbfSEd Maste 
1508ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1509ac7ddfbfSEd Maste // CommandObjectProcessKill
1510ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1511ac7ddfbfSEd Maste #pragma mark CommandObjectProcessKill
1512ac7ddfbfSEd Maste 
1513ac7ddfbfSEd Maste class CommandObjectProcessKill : public CommandObjectParsed
1514ac7ddfbfSEd Maste {
1515ac7ddfbfSEd Maste public:
1516ac7ddfbfSEd Maste 
1517ac7ddfbfSEd Maste     CommandObjectProcessKill (CommandInterpreter &interpreter) :
1518ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
1519ac7ddfbfSEd Maste                              "process kill",
1520ac7ddfbfSEd Maste                              "Terminate the current process being debugged.",
1521ac7ddfbfSEd Maste                              "process kill",
1522ac7ddfbfSEd Maste                              eFlagRequiresProcess      |
1523ac7ddfbfSEd Maste                              eFlagTryTargetAPILock     |
1524ac7ddfbfSEd Maste                              eFlagProcessMustBeLaunched)
1525ac7ddfbfSEd Maste     {
1526ac7ddfbfSEd Maste     }
1527ac7ddfbfSEd Maste 
1528ac7ddfbfSEd Maste     ~CommandObjectProcessKill ()
1529ac7ddfbfSEd Maste     {
1530ac7ddfbfSEd Maste     }
1531ac7ddfbfSEd Maste 
1532ac7ddfbfSEd Maste protected:
1533ac7ddfbfSEd Maste     bool
1534ac7ddfbfSEd Maste     DoExecute (Args& command,
1535ac7ddfbfSEd Maste              CommandReturnObject &result)
1536ac7ddfbfSEd Maste     {
1537ac7ddfbfSEd Maste         Process *process = m_exe_ctx.GetProcessPtr();
1538ac7ddfbfSEd Maste         if (process == NULL)
1539ac7ddfbfSEd Maste         {
1540ac7ddfbfSEd Maste             result.AppendError ("no process to kill");
1541ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1542ac7ddfbfSEd Maste             return false;
1543ac7ddfbfSEd Maste         }
1544ac7ddfbfSEd Maste 
1545ac7ddfbfSEd Maste         if (command.GetArgumentCount() == 0)
1546ac7ddfbfSEd Maste         {
1547ac7ddfbfSEd Maste             Error error (process->Destroy());
1548ac7ddfbfSEd Maste             if (error.Success())
1549ac7ddfbfSEd Maste             {
1550ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusSuccessFinishResult);
1551ac7ddfbfSEd Maste             }
1552ac7ddfbfSEd Maste             else
1553ac7ddfbfSEd Maste             {
1554ac7ddfbfSEd Maste                 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString());
1555ac7ddfbfSEd Maste                 result.SetStatus (eReturnStatusFailed);
1556ac7ddfbfSEd Maste             }
1557ac7ddfbfSEd Maste         }
1558ac7ddfbfSEd Maste         else
1559ac7ddfbfSEd Maste         {
1560ac7ddfbfSEd Maste             result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n",
1561ac7ddfbfSEd Maste                                         m_cmd_name.c_str(),
1562ac7ddfbfSEd Maste                                         m_cmd_syntax.c_str());
1563ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1564ac7ddfbfSEd Maste         }
1565ac7ddfbfSEd Maste         return result.Succeeded();
1566ac7ddfbfSEd Maste     }
1567ac7ddfbfSEd Maste };
1568ac7ddfbfSEd Maste 
1569ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1570ac7ddfbfSEd Maste // CommandObjectProcessStatus
1571ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1572ac7ddfbfSEd Maste #pragma mark CommandObjectProcessStatus
1573ac7ddfbfSEd Maste 
1574ac7ddfbfSEd Maste class CommandObjectProcessStatus : public CommandObjectParsed
1575ac7ddfbfSEd Maste {
1576ac7ddfbfSEd Maste public:
1577ac7ddfbfSEd Maste     CommandObjectProcessStatus (CommandInterpreter &interpreter) :
1578ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
1579ac7ddfbfSEd Maste                              "process status",
1580ac7ddfbfSEd Maste                              "Show the current status and location of executing process.",
1581ac7ddfbfSEd Maste                              "process status",
1582ac7ddfbfSEd Maste                              eFlagRequiresProcess | eFlagTryTargetAPILock)
1583ac7ddfbfSEd Maste     {
1584ac7ddfbfSEd Maste     }
1585ac7ddfbfSEd Maste 
1586ac7ddfbfSEd Maste     ~CommandObjectProcessStatus()
1587ac7ddfbfSEd Maste     {
1588ac7ddfbfSEd Maste     }
1589ac7ddfbfSEd Maste 
1590ac7ddfbfSEd Maste 
1591ac7ddfbfSEd Maste     bool
1592ac7ddfbfSEd Maste     DoExecute (Args& command, CommandReturnObject &result)
1593ac7ddfbfSEd Maste     {
1594ac7ddfbfSEd Maste         Stream &strm = result.GetOutputStream();
1595ac7ddfbfSEd Maste         result.SetStatus (eReturnStatusSuccessFinishNoResult);
1596ac7ddfbfSEd Maste         // No need to check "process" for validity as eFlagRequiresProcess ensures it is valid
1597ac7ddfbfSEd Maste         Process *process = m_exe_ctx.GetProcessPtr();
1598ac7ddfbfSEd Maste         const bool only_threads_with_stop_reason = true;
1599ac7ddfbfSEd Maste         const uint32_t start_frame = 0;
1600ac7ddfbfSEd Maste         const uint32_t num_frames = 1;
1601ac7ddfbfSEd Maste         const uint32_t num_frames_with_source = 1;
1602ac7ddfbfSEd Maste         process->GetStatus(strm);
1603ac7ddfbfSEd Maste         process->GetThreadStatus (strm,
1604ac7ddfbfSEd Maste                                   only_threads_with_stop_reason,
1605ac7ddfbfSEd Maste                                   start_frame,
1606ac7ddfbfSEd Maste                                   num_frames,
1607ac7ddfbfSEd Maste                                   num_frames_with_source);
1608ac7ddfbfSEd Maste         return result.Succeeded();
1609ac7ddfbfSEd Maste     }
1610ac7ddfbfSEd Maste };
1611ac7ddfbfSEd Maste 
1612ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1613ac7ddfbfSEd Maste // CommandObjectProcessHandle
1614ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1615ac7ddfbfSEd Maste #pragma mark CommandObjectProcessHandle
1616ac7ddfbfSEd Maste 
1617ac7ddfbfSEd Maste class CommandObjectProcessHandle : public CommandObjectParsed
1618ac7ddfbfSEd Maste {
1619ac7ddfbfSEd Maste public:
1620ac7ddfbfSEd Maste 
1621ac7ddfbfSEd Maste     class CommandOptions : public Options
1622ac7ddfbfSEd Maste     {
1623ac7ddfbfSEd Maste     public:
1624ac7ddfbfSEd Maste 
1625ac7ddfbfSEd Maste         CommandOptions (CommandInterpreter &interpreter) :
1626ac7ddfbfSEd Maste             Options (interpreter)
1627ac7ddfbfSEd Maste         {
1628ac7ddfbfSEd Maste             OptionParsingStarting ();
1629ac7ddfbfSEd Maste         }
1630ac7ddfbfSEd Maste 
1631ac7ddfbfSEd Maste         ~CommandOptions ()
1632ac7ddfbfSEd Maste         {
1633ac7ddfbfSEd Maste         }
1634ac7ddfbfSEd Maste 
1635ac7ddfbfSEd Maste         Error
1636ac7ddfbfSEd Maste         SetOptionValue (uint32_t option_idx, const char *option_arg)
1637ac7ddfbfSEd Maste         {
1638ac7ddfbfSEd Maste             Error error;
1639ac7ddfbfSEd Maste             const int short_option = m_getopt_table[option_idx].val;
1640ac7ddfbfSEd Maste 
1641ac7ddfbfSEd Maste             switch (short_option)
1642ac7ddfbfSEd Maste             {
1643ac7ddfbfSEd Maste                 case 's':
1644ac7ddfbfSEd Maste                     stop = option_arg;
1645ac7ddfbfSEd Maste                     break;
1646ac7ddfbfSEd Maste                 case 'n':
1647ac7ddfbfSEd Maste                     notify = option_arg;
1648ac7ddfbfSEd Maste                     break;
1649ac7ddfbfSEd Maste                 case 'p':
1650ac7ddfbfSEd Maste                     pass = option_arg;
1651ac7ddfbfSEd Maste                     break;
1652ac7ddfbfSEd Maste                 default:
1653ac7ddfbfSEd Maste                     error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
1654ac7ddfbfSEd Maste                     break;
1655ac7ddfbfSEd Maste             }
1656ac7ddfbfSEd Maste             return error;
1657ac7ddfbfSEd Maste         }
1658ac7ddfbfSEd Maste 
1659ac7ddfbfSEd Maste         void
1660ac7ddfbfSEd Maste         OptionParsingStarting ()
1661ac7ddfbfSEd Maste         {
1662ac7ddfbfSEd Maste             stop.clear();
1663ac7ddfbfSEd Maste             notify.clear();
1664ac7ddfbfSEd Maste             pass.clear();
1665ac7ddfbfSEd Maste         }
1666ac7ddfbfSEd Maste 
1667ac7ddfbfSEd Maste         const OptionDefinition*
1668ac7ddfbfSEd Maste         GetDefinitions ()
1669ac7ddfbfSEd Maste         {
1670ac7ddfbfSEd Maste             return g_option_table;
1671ac7ddfbfSEd Maste         }
1672ac7ddfbfSEd Maste 
1673ac7ddfbfSEd Maste         // Options table: Required for subclasses of Options.
1674ac7ddfbfSEd Maste 
1675ac7ddfbfSEd Maste         static OptionDefinition g_option_table[];
1676ac7ddfbfSEd Maste 
1677ac7ddfbfSEd Maste         // Instance variables to hold the values for command options.
1678ac7ddfbfSEd Maste 
1679ac7ddfbfSEd Maste         std::string stop;
1680ac7ddfbfSEd Maste         std::string notify;
1681ac7ddfbfSEd Maste         std::string pass;
1682ac7ddfbfSEd Maste     };
1683ac7ddfbfSEd Maste 
1684ac7ddfbfSEd Maste 
1685ac7ddfbfSEd Maste     CommandObjectProcessHandle (CommandInterpreter &interpreter) :
1686ac7ddfbfSEd Maste         CommandObjectParsed (interpreter,
1687ac7ddfbfSEd Maste                              "process handle",
1688ac7ddfbfSEd Maste                              "Show or update what the process and debugger should do with various signals received from the OS.",
1689ac7ddfbfSEd Maste                              NULL),
1690ac7ddfbfSEd Maste         m_options (interpreter)
1691ac7ddfbfSEd Maste     {
1692ac7ddfbfSEd Maste         SetHelpLong ("If no signals are specified, update them all.  If no update option is specified, list the current values.\n");
1693ac7ddfbfSEd Maste         CommandArgumentEntry arg;
1694ac7ddfbfSEd Maste         CommandArgumentData signal_arg;
1695ac7ddfbfSEd Maste 
1696ac7ddfbfSEd Maste         signal_arg.arg_type = eArgTypeUnixSignal;
1697ac7ddfbfSEd Maste         signal_arg.arg_repetition = eArgRepeatStar;
1698ac7ddfbfSEd Maste 
1699ac7ddfbfSEd Maste         arg.push_back (signal_arg);
1700ac7ddfbfSEd Maste 
1701ac7ddfbfSEd Maste         m_arguments.push_back (arg);
1702ac7ddfbfSEd Maste     }
1703ac7ddfbfSEd Maste 
1704ac7ddfbfSEd Maste     ~CommandObjectProcessHandle ()
1705ac7ddfbfSEd Maste     {
1706ac7ddfbfSEd Maste     }
1707ac7ddfbfSEd Maste 
1708ac7ddfbfSEd Maste     Options *
1709ac7ddfbfSEd Maste     GetOptions ()
1710ac7ddfbfSEd Maste     {
1711ac7ddfbfSEd Maste         return &m_options;
1712ac7ddfbfSEd Maste     }
1713ac7ddfbfSEd Maste 
1714ac7ddfbfSEd Maste     bool
1715ac7ddfbfSEd Maste     VerifyCommandOptionValue (const std::string &option, int &real_value)
1716ac7ddfbfSEd Maste     {
1717ac7ddfbfSEd Maste         bool okay = true;
1718ac7ddfbfSEd Maste 
1719ac7ddfbfSEd Maste         bool success = false;
1720ac7ddfbfSEd Maste         bool tmp_value = Args::StringToBoolean (option.c_str(), false, &success);
1721ac7ddfbfSEd Maste 
1722ac7ddfbfSEd Maste         if (success && tmp_value)
1723ac7ddfbfSEd Maste             real_value = 1;
1724ac7ddfbfSEd Maste         else if (success && !tmp_value)
1725ac7ddfbfSEd Maste             real_value = 0;
1726ac7ddfbfSEd Maste         else
1727ac7ddfbfSEd Maste         {
1728ac7ddfbfSEd Maste             // If the value isn't 'true' or 'false', it had better be 0 or 1.
1729ac7ddfbfSEd Maste             real_value = Args::StringToUInt32 (option.c_str(), 3);
1730ac7ddfbfSEd Maste             if (real_value != 0 && real_value != 1)
1731ac7ddfbfSEd Maste                 okay = false;
1732ac7ddfbfSEd Maste         }
1733ac7ddfbfSEd Maste 
1734ac7ddfbfSEd Maste         return okay;
1735ac7ddfbfSEd Maste     }
1736ac7ddfbfSEd Maste 
1737ac7ddfbfSEd Maste     void
1738ac7ddfbfSEd Maste     PrintSignalHeader (Stream &str)
1739ac7ddfbfSEd Maste     {
1740ac7ddfbfSEd Maste         str.Printf ("NAME        PASS   STOP   NOTIFY\n");
1741ac7ddfbfSEd Maste         str.Printf ("==========  =====  =====  ======\n");
1742ac7ddfbfSEd Maste     }
1743ac7ddfbfSEd Maste 
1744ac7ddfbfSEd Maste     void
1745ac7ddfbfSEd Maste     PrintSignal (Stream &str, int32_t signo, const char *sig_name, UnixSignals &signals)
1746ac7ddfbfSEd Maste     {
1747ac7ddfbfSEd Maste         bool stop;
1748ac7ddfbfSEd Maste         bool suppress;
1749ac7ddfbfSEd Maste         bool notify;
1750ac7ddfbfSEd Maste 
1751ac7ddfbfSEd Maste         str.Printf ("%-10s  ", sig_name);
1752ac7ddfbfSEd Maste         if (signals.GetSignalInfo (signo, suppress, stop, notify))
1753ac7ddfbfSEd Maste         {
1754ac7ddfbfSEd Maste             bool pass = !suppress;
1755ac7ddfbfSEd Maste             str.Printf ("%s  %s  %s",
1756ac7ddfbfSEd Maste                         (pass ? "true " : "false"),
1757ac7ddfbfSEd Maste                         (stop ? "true " : "false"),
1758ac7ddfbfSEd Maste                         (notify ? "true " : "false"));
1759ac7ddfbfSEd Maste         }
1760ac7ddfbfSEd Maste         str.Printf ("\n");
1761ac7ddfbfSEd Maste     }
1762ac7ddfbfSEd Maste 
1763ac7ddfbfSEd Maste     void
1764ac7ddfbfSEd Maste     PrintSignalInformation (Stream &str, Args &signal_args, int num_valid_signals, UnixSignals &signals)
1765ac7ddfbfSEd Maste     {
1766ac7ddfbfSEd Maste         PrintSignalHeader (str);
1767ac7ddfbfSEd Maste 
1768ac7ddfbfSEd Maste         if (num_valid_signals > 0)
1769ac7ddfbfSEd Maste         {
1770ac7ddfbfSEd Maste             size_t num_args = signal_args.GetArgumentCount();
1771ac7ddfbfSEd Maste             for (size_t i = 0; i < num_args; ++i)
1772ac7ddfbfSEd Maste             {
1773ac7ddfbfSEd Maste                 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
1774ac7ddfbfSEd Maste                 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
1775ac7ddfbfSEd Maste                     PrintSignal (str, signo, signal_args.GetArgumentAtIndex (i), signals);
1776ac7ddfbfSEd Maste             }
1777ac7ddfbfSEd Maste         }
1778ac7ddfbfSEd Maste         else // Print info for ALL signals
1779ac7ddfbfSEd Maste         {
1780ac7ddfbfSEd Maste             int32_t signo = signals.GetFirstSignalNumber();
1781ac7ddfbfSEd Maste             while (signo != LLDB_INVALID_SIGNAL_NUMBER)
1782ac7ddfbfSEd Maste             {
1783ac7ddfbfSEd Maste                 PrintSignal (str, signo, signals.GetSignalAsCString (signo), signals);
1784ac7ddfbfSEd Maste                 signo = signals.GetNextSignalNumber (signo);
1785ac7ddfbfSEd Maste             }
1786ac7ddfbfSEd Maste         }
1787ac7ddfbfSEd Maste     }
1788ac7ddfbfSEd Maste 
1789ac7ddfbfSEd Maste protected:
1790ac7ddfbfSEd Maste     bool
1791ac7ddfbfSEd Maste     DoExecute (Args &signal_args, CommandReturnObject &result)
1792ac7ddfbfSEd Maste     {
1793ac7ddfbfSEd Maste         TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
1794ac7ddfbfSEd Maste 
1795ac7ddfbfSEd Maste         if (!target_sp)
1796ac7ddfbfSEd Maste         {
1797ac7ddfbfSEd Maste             result.AppendError ("No current target;"
1798ac7ddfbfSEd Maste                                 " cannot handle signals until you have a valid target and process.\n");
1799ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1800ac7ddfbfSEd Maste             return false;
1801ac7ddfbfSEd Maste         }
1802ac7ddfbfSEd Maste 
1803ac7ddfbfSEd Maste         ProcessSP process_sp = target_sp->GetProcessSP();
1804ac7ddfbfSEd Maste 
1805ac7ddfbfSEd Maste         if (!process_sp)
1806ac7ddfbfSEd Maste         {
1807ac7ddfbfSEd Maste             result.AppendError ("No current process; cannot handle signals until you have a valid process.\n");
1808ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1809ac7ddfbfSEd Maste             return false;
1810ac7ddfbfSEd Maste         }
1811ac7ddfbfSEd Maste 
1812ac7ddfbfSEd Maste         int stop_action = -1;   // -1 means leave the current setting alone
1813ac7ddfbfSEd Maste         int pass_action = -1;   // -1 means leave the current setting alone
1814ac7ddfbfSEd Maste         int notify_action = -1; // -1 means leave the current setting alone
1815ac7ddfbfSEd Maste 
1816ac7ddfbfSEd Maste         if (! m_options.stop.empty()
1817ac7ddfbfSEd Maste             && ! VerifyCommandOptionValue (m_options.stop, stop_action))
1818ac7ddfbfSEd Maste         {
1819ac7ddfbfSEd Maste             result.AppendError ("Invalid argument for command option --stop; must be true or false.\n");
1820ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1821ac7ddfbfSEd Maste             return false;
1822ac7ddfbfSEd Maste         }
1823ac7ddfbfSEd Maste 
1824ac7ddfbfSEd Maste         if (! m_options.notify.empty()
1825ac7ddfbfSEd Maste             && ! VerifyCommandOptionValue (m_options.notify, notify_action))
1826ac7ddfbfSEd Maste         {
1827ac7ddfbfSEd Maste             result.AppendError ("Invalid argument for command option --notify; must be true or false.\n");
1828ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1829ac7ddfbfSEd Maste             return false;
1830ac7ddfbfSEd Maste         }
1831ac7ddfbfSEd Maste 
1832ac7ddfbfSEd Maste         if (! m_options.pass.empty()
1833ac7ddfbfSEd Maste             && ! VerifyCommandOptionValue (m_options.pass, pass_action))
1834ac7ddfbfSEd Maste         {
1835ac7ddfbfSEd Maste             result.AppendError ("Invalid argument for command option --pass; must be true or false.\n");
1836ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1837ac7ddfbfSEd Maste             return false;
1838ac7ddfbfSEd Maste         }
1839ac7ddfbfSEd Maste 
1840ac7ddfbfSEd Maste         size_t num_args = signal_args.GetArgumentCount();
1841ac7ddfbfSEd Maste         UnixSignals &signals = process_sp->GetUnixSignals();
1842ac7ddfbfSEd Maste         int num_signals_set = 0;
1843ac7ddfbfSEd Maste 
1844ac7ddfbfSEd Maste         if (num_args > 0)
1845ac7ddfbfSEd Maste         {
1846ac7ddfbfSEd Maste             for (size_t i = 0; i < num_args; ++i)
1847ac7ddfbfSEd Maste             {
1848ac7ddfbfSEd Maste                 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
1849ac7ddfbfSEd Maste                 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
1850ac7ddfbfSEd Maste                 {
1851ac7ddfbfSEd Maste                     // Casting the actions as bools here should be okay, because VerifyCommandOptionValue guarantees
1852ac7ddfbfSEd Maste                     // the value is either 0 or 1.
1853ac7ddfbfSEd Maste                     if (stop_action != -1)
1854ac7ddfbfSEd Maste                         signals.SetShouldStop (signo, (bool) stop_action);
1855ac7ddfbfSEd Maste                     if (pass_action != -1)
1856ac7ddfbfSEd Maste                     {
1857ac7ddfbfSEd Maste                         bool suppress = ! ((bool) pass_action);
1858ac7ddfbfSEd Maste                         signals.SetShouldSuppress (signo, suppress);
1859ac7ddfbfSEd Maste                     }
1860ac7ddfbfSEd Maste                     if (notify_action != -1)
1861ac7ddfbfSEd Maste                         signals.SetShouldNotify (signo, (bool) notify_action);
1862ac7ddfbfSEd Maste                     ++num_signals_set;
1863ac7ddfbfSEd Maste                 }
1864ac7ddfbfSEd Maste                 else
1865ac7ddfbfSEd Maste                 {
1866ac7ddfbfSEd Maste                     result.AppendErrorWithFormat ("Invalid signal name '%s'\n", signal_args.GetArgumentAtIndex (i));
1867ac7ddfbfSEd Maste                 }
1868ac7ddfbfSEd Maste             }
1869ac7ddfbfSEd Maste         }
1870ac7ddfbfSEd Maste         else
1871ac7ddfbfSEd Maste         {
1872ac7ddfbfSEd Maste             // No signal specified, if any command options were specified, update ALL signals.
1873ac7ddfbfSEd Maste             if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1))
1874ac7ddfbfSEd Maste             {
1875ac7ddfbfSEd Maste                 if (m_interpreter.Confirm ("Do you really want to update all the signals?", false))
1876ac7ddfbfSEd Maste                 {
1877ac7ddfbfSEd Maste                     int32_t signo = signals.GetFirstSignalNumber();
1878ac7ddfbfSEd Maste                     while (signo != LLDB_INVALID_SIGNAL_NUMBER)
1879ac7ddfbfSEd Maste                     {
1880ac7ddfbfSEd Maste                         if (notify_action != -1)
1881ac7ddfbfSEd Maste                             signals.SetShouldNotify (signo, (bool) notify_action);
1882ac7ddfbfSEd Maste                         if (stop_action != -1)
1883ac7ddfbfSEd Maste                             signals.SetShouldStop (signo, (bool) stop_action);
1884ac7ddfbfSEd Maste                         if (pass_action != -1)
1885ac7ddfbfSEd Maste                         {
1886ac7ddfbfSEd Maste                             bool suppress = ! ((bool) pass_action);
1887ac7ddfbfSEd Maste                             signals.SetShouldSuppress (signo, suppress);
1888ac7ddfbfSEd Maste                         }
1889ac7ddfbfSEd Maste                         signo = signals.GetNextSignalNumber (signo);
1890ac7ddfbfSEd Maste                     }
1891ac7ddfbfSEd Maste                 }
1892ac7ddfbfSEd Maste             }
1893ac7ddfbfSEd Maste         }
1894ac7ddfbfSEd Maste 
1895ac7ddfbfSEd Maste         PrintSignalInformation (result.GetOutputStream(), signal_args, num_signals_set, signals);
1896ac7ddfbfSEd Maste 
1897ac7ddfbfSEd Maste         if (num_signals_set > 0)
1898ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusSuccessFinishNoResult);
1899ac7ddfbfSEd Maste         else
1900ac7ddfbfSEd Maste             result.SetStatus (eReturnStatusFailed);
1901ac7ddfbfSEd Maste 
1902ac7ddfbfSEd Maste         return result.Succeeded();
1903ac7ddfbfSEd Maste     }
1904ac7ddfbfSEd Maste 
1905ac7ddfbfSEd Maste     CommandOptions m_options;
1906ac7ddfbfSEd Maste };
1907ac7ddfbfSEd Maste 
1908ac7ddfbfSEd Maste OptionDefinition
1909ac7ddfbfSEd Maste CommandObjectProcessHandle::CommandOptions::g_option_table[] =
1910ac7ddfbfSEd Maste {
1911ac7ddfbfSEd Maste { LLDB_OPT_SET_1, false, "stop",   's', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the process should be stopped if the signal is received." },
1912ac7ddfbfSEd Maste { LLDB_OPT_SET_1, false, "notify", 'n', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the debugger should notify the user if the signal is received." },
1913ac7ddfbfSEd Maste { LLDB_OPT_SET_1, false, "pass",  'p', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." },
1914ac7ddfbfSEd Maste { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
1915ac7ddfbfSEd Maste };
1916ac7ddfbfSEd Maste 
1917ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1918ac7ddfbfSEd Maste // CommandObjectMultiwordProcess
1919ac7ddfbfSEd Maste //-------------------------------------------------------------------------
1920ac7ddfbfSEd Maste 
1921ac7ddfbfSEd Maste CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter &interpreter) :
1922ac7ddfbfSEd Maste     CommandObjectMultiword (interpreter,
1923ac7ddfbfSEd Maste                             "process",
1924ac7ddfbfSEd Maste                             "A set of commands for operating on a process.",
1925ac7ddfbfSEd Maste                             "process <subcommand> [<subcommand-options>]")
1926ac7ddfbfSEd Maste {
1927ac7ddfbfSEd Maste     LoadSubCommand ("attach",      CommandObjectSP (new CommandObjectProcessAttach    (interpreter)));
1928ac7ddfbfSEd Maste     LoadSubCommand ("launch",      CommandObjectSP (new CommandObjectProcessLaunch    (interpreter)));
1929ac7ddfbfSEd Maste     LoadSubCommand ("continue",    CommandObjectSP (new CommandObjectProcessContinue  (interpreter)));
1930ac7ddfbfSEd Maste     LoadSubCommand ("connect",     CommandObjectSP (new CommandObjectProcessConnect   (interpreter)));
1931ac7ddfbfSEd Maste     LoadSubCommand ("detach",      CommandObjectSP (new CommandObjectProcessDetach    (interpreter)));
1932ac7ddfbfSEd Maste     LoadSubCommand ("load",        CommandObjectSP (new CommandObjectProcessLoad      (interpreter)));
1933ac7ddfbfSEd Maste     LoadSubCommand ("unload",      CommandObjectSP (new CommandObjectProcessUnload    (interpreter)));
1934ac7ddfbfSEd Maste     LoadSubCommand ("signal",      CommandObjectSP (new CommandObjectProcessSignal    (interpreter)));
1935ac7ddfbfSEd Maste     LoadSubCommand ("handle",      CommandObjectSP (new CommandObjectProcessHandle    (interpreter)));
1936ac7ddfbfSEd Maste     LoadSubCommand ("status",      CommandObjectSP (new CommandObjectProcessStatus    (interpreter)));
1937ac7ddfbfSEd Maste     LoadSubCommand ("interrupt",   CommandObjectSP (new CommandObjectProcessInterrupt (interpreter)));
1938ac7ddfbfSEd Maste     LoadSubCommand ("kill",        CommandObjectSP (new CommandObjectProcessKill      (interpreter)));
1939ac7ddfbfSEd Maste     LoadSubCommand ("plugin",      CommandObjectSP (new CommandObjectProcessPlugin    (interpreter)));
1940ac7ddfbfSEd Maste }
1941ac7ddfbfSEd Maste 
1942ac7ddfbfSEd Maste CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess ()
1943ac7ddfbfSEd Maste {
1944ac7ddfbfSEd Maste }
1945ac7ddfbfSEd Maste 
1946