130fdc8d8SChris Lattner //===-- CommandObjectProcess.cpp --------------------------------*- C++ -*-===//
230fdc8d8SChris Lattner //
330fdc8d8SChris Lattner //                     The LLVM Compiler Infrastructure
430fdc8d8SChris Lattner //
530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source
630fdc8d8SChris Lattner // License. See LICENSE.TXT for details.
730fdc8d8SChris Lattner //
830fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
930fdc8d8SChris Lattner 
1030fdc8d8SChris Lattner #include "CommandObjectProcess.h"
1130fdc8d8SChris Lattner 
1230fdc8d8SChris Lattner // C Includes
1330fdc8d8SChris Lattner // C++ Includes
1430fdc8d8SChris Lattner // Other libraries and framework includes
1530fdc8d8SChris Lattner // Project includes
1640af72e1SJim Ingham #include "lldb/Interpreter/Args.h"
1740af72e1SJim Ingham #include "lldb/Interpreter/Options.h"
1830fdc8d8SChris Lattner #include "lldb/Core/State.h"
1930fdc8d8SChris Lattner #include "lldb/Interpreter/CommandInterpreter.h"
2030fdc8d8SChris Lattner #include "lldb/Interpreter/CommandReturnObject.h"
214b9bea87SJim Ingham #include "./CommandObjectThread.h"
2230fdc8d8SChris Lattner #include "lldb/Target/Process.h"
2330fdc8d8SChris Lattner #include "lldb/Target/Target.h"
2430fdc8d8SChris Lattner #include "lldb/Target/Thread.h"
2530fdc8d8SChris Lattner 
2630fdc8d8SChris Lattner using namespace lldb;
2730fdc8d8SChris Lattner using namespace lldb_private;
2830fdc8d8SChris Lattner 
2930fdc8d8SChris Lattner //-------------------------------------------------------------------------
3030fdc8d8SChris Lattner // CommandObjectProcessLaunch
3130fdc8d8SChris Lattner //-------------------------------------------------------------------------
3230fdc8d8SChris Lattner 
3330fdc8d8SChris Lattner class CommandObjectProcessLaunch : public CommandObject
3430fdc8d8SChris Lattner {
3530fdc8d8SChris Lattner public:
3630fdc8d8SChris Lattner 
3730fdc8d8SChris Lattner     class CommandOptions : public Options
3830fdc8d8SChris Lattner     {
3930fdc8d8SChris Lattner     public:
4030fdc8d8SChris Lattner 
4130fdc8d8SChris Lattner         CommandOptions () :
4230fdc8d8SChris Lattner             Options()
4330fdc8d8SChris Lattner         {
4430fdc8d8SChris Lattner             // Keep default values of all options in one place: ResetOptionValues ()
4530fdc8d8SChris Lattner             ResetOptionValues ();
4630fdc8d8SChris Lattner         }
4730fdc8d8SChris Lattner 
4830fdc8d8SChris Lattner         ~CommandOptions ()
4930fdc8d8SChris Lattner         {
5030fdc8d8SChris Lattner         }
5130fdc8d8SChris Lattner 
5230fdc8d8SChris Lattner         Error
5330fdc8d8SChris Lattner         SetOptionValue (int option_idx, const char *option_arg)
5430fdc8d8SChris Lattner         {
5530fdc8d8SChris Lattner             Error error;
5630fdc8d8SChris Lattner             char short_option = (char) m_getopt_table[option_idx].val;
5730fdc8d8SChris Lattner 
5830fdc8d8SChris Lattner             switch (short_option)
5930fdc8d8SChris Lattner             {
6030fdc8d8SChris Lattner                 case 's':   stop_at_entry = true;       break;
6130fdc8d8SChris Lattner                 case 'e':   stderr_path = option_arg;   break;
6230fdc8d8SChris Lattner                 case 'i':   stdin_path  = option_arg;   break;
6330fdc8d8SChris Lattner                 case 'o':   stdout_path = option_arg;   break;
6430fdc8d8SChris Lattner                 case 'p':   plugin_name = option_arg;   break;
65*19388cfcSGreg Clayton                 case 't':   in_new_tty = true; break;
6630fdc8d8SChris Lattner                 default:
6730fdc8d8SChris Lattner                     error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
6830fdc8d8SChris Lattner                     break;
6930fdc8d8SChris Lattner 
7030fdc8d8SChris Lattner             }
7130fdc8d8SChris Lattner             return error;
7230fdc8d8SChris Lattner         }
7330fdc8d8SChris Lattner 
7430fdc8d8SChris Lattner         void
7530fdc8d8SChris Lattner         ResetOptionValues ()
7630fdc8d8SChris Lattner         {
7730fdc8d8SChris Lattner             Options::ResetOptionValues();
7830fdc8d8SChris Lattner             stop_at_entry = false;
79*19388cfcSGreg Clayton             in_new_tty = false;
8030fdc8d8SChris Lattner             stdin_path.clear();
8130fdc8d8SChris Lattner             stdout_path.clear();
8230fdc8d8SChris Lattner             stderr_path.clear();
8330fdc8d8SChris Lattner             plugin_name.clear();
8430fdc8d8SChris Lattner         }
8530fdc8d8SChris Lattner 
8630fdc8d8SChris Lattner         const lldb::OptionDefinition*
8730fdc8d8SChris Lattner         GetDefinitions ()
8830fdc8d8SChris Lattner         {
8930fdc8d8SChris Lattner             return g_option_table;
9030fdc8d8SChris Lattner         }
9130fdc8d8SChris Lattner 
9230fdc8d8SChris Lattner         // Options table: Required for subclasses of Options.
9330fdc8d8SChris Lattner 
9430fdc8d8SChris Lattner         static lldb::OptionDefinition g_option_table[];
9530fdc8d8SChris Lattner 
9630fdc8d8SChris Lattner         // Instance variables to hold the values for command options.
9730fdc8d8SChris Lattner 
9830fdc8d8SChris Lattner         bool stop_at_entry;
99*19388cfcSGreg Clayton         bool in_new_tty;
10030fdc8d8SChris Lattner         std::string stderr_path;
10130fdc8d8SChris Lattner         std::string stdin_path;
10230fdc8d8SChris Lattner         std::string stdout_path;
10330fdc8d8SChris Lattner         std::string plugin_name;
10430fdc8d8SChris Lattner 
10530fdc8d8SChris Lattner     };
10630fdc8d8SChris Lattner 
107a7015092SGreg Clayton     CommandObjectProcessLaunch (CommandInterpreter &interpreter) :
108a7015092SGreg Clayton         CommandObject (interpreter,
109a7015092SGreg Clayton                        "process launch",
110e3d26315SCaroline Tice                        "Launch the executable in the debugger.",
111405fe67fSCaroline Tice                        NULL)
11230fdc8d8SChris Lattner     {
113405fe67fSCaroline Tice         CommandArgumentEntry arg;
114405fe67fSCaroline Tice         CommandArgumentData run_args_arg;
115405fe67fSCaroline Tice 
116405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
117405fe67fSCaroline Tice         run_args_arg.arg_type = eArgTypeRunArgs;
118405fe67fSCaroline Tice         run_args_arg.arg_repetition = eArgRepeatOptional;
119405fe67fSCaroline Tice 
120405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
121405fe67fSCaroline Tice         arg.push_back (run_args_arg);
122405fe67fSCaroline Tice 
123405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
124405fe67fSCaroline Tice         m_arguments.push_back (arg);
12530fdc8d8SChris Lattner     }
12630fdc8d8SChris Lattner 
12730fdc8d8SChris Lattner 
12830fdc8d8SChris Lattner     ~CommandObjectProcessLaunch ()
12930fdc8d8SChris Lattner     {
13030fdc8d8SChris Lattner     }
13130fdc8d8SChris Lattner 
13230fdc8d8SChris Lattner     Options *
13330fdc8d8SChris Lattner     GetOptions ()
13430fdc8d8SChris Lattner     {
13530fdc8d8SChris Lattner         return &m_options;
13630fdc8d8SChris Lattner     }
13730fdc8d8SChris Lattner 
13830fdc8d8SChris Lattner     bool
13905faeb71SGreg Clayton     Execute (Args& launch_args, CommandReturnObject &result)
14030fdc8d8SChris Lattner     {
141a7015092SGreg Clayton         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
14230fdc8d8SChris Lattner 
14330fdc8d8SChris Lattner         if (target == NULL)
14430fdc8d8SChris Lattner         {
14530fdc8d8SChris Lattner             result.AppendError ("invalid target, set executable file using 'file' command");
14630fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
14730fdc8d8SChris Lattner             return false;
14830fdc8d8SChris Lattner         }
14930fdc8d8SChris Lattner 
15030fdc8d8SChris Lattner         // If our listener is NULL, users aren't allows to launch
15130fdc8d8SChris Lattner         char filename[PATH_MAX];
152*19388cfcSGreg Clayton         const Module *exe_module = target->GetExecutableModule().get();
15330fdc8d8SChris Lattner         exe_module->GetFileSpec().GetPath(filename, sizeof(filename));
15430fdc8d8SChris Lattner 
155a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
156a7015092SGreg Clayton         if (process && process->IsAlive())
15730fdc8d8SChris Lattner         {
15830fdc8d8SChris Lattner             result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before running again.\n",
15930fdc8d8SChris Lattner                                           process->GetID());
16030fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
16130fdc8d8SChris Lattner             return false;
16230fdc8d8SChris Lattner         }
16330fdc8d8SChris Lattner 
16430fdc8d8SChris Lattner         const char *plugin_name;
16530fdc8d8SChris Lattner         if (!m_options.plugin_name.empty())
16630fdc8d8SChris Lattner             plugin_name = m_options.plugin_name.c_str();
16730fdc8d8SChris Lattner         else
16830fdc8d8SChris Lattner             plugin_name = NULL;
16930fdc8d8SChris Lattner 
170a7015092SGreg Clayton         process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
17130fdc8d8SChris Lattner 
172a7015092SGreg Clayton         if (process == NULL)
1733df9a8dfSCaroline Tice         {
17443a8c39bSCaroline Tice             result.AppendErrorWithFormat ("Failed to find a process plugin for executable.\n");
175a7015092SGreg Clayton             result.SetStatus (eReturnStatusFailed);
176a7015092SGreg Clayton             return false;
1773df9a8dfSCaroline Tice         }
1783df9a8dfSCaroline Tice 
179a7015092SGreg Clayton         // If no launch args were given on the command line, then use any that
180a7015092SGreg Clayton         // might have been set using the "run-args" set variable.
18130fdc8d8SChris Lattner         if (launch_args.GetArgumentCount() == 0)
18230fdc8d8SChris Lattner         {
183a7015092SGreg Clayton             if (process->GetRunArguments().GetArgumentCount() > 0)
184a7015092SGreg Clayton                 launch_args = process->GetRunArguments();
18530fdc8d8SChris Lattner         }
18630fdc8d8SChris Lattner 
187*19388cfcSGreg Clayton         if (m_options.in_new_tty)
188*19388cfcSGreg Clayton         {
189*19388cfcSGreg Clayton             char exec_file_path[PATH_MAX];
190*19388cfcSGreg Clayton             if (exe_module->GetFileSpec().GetPath(exec_file_path, sizeof(exec_file_path)))
191*19388cfcSGreg Clayton             {
192*19388cfcSGreg Clayton                 launch_args.InsertArgumentAtIndex(0, exec_file_path);
193*19388cfcSGreg Clayton             }
194*19388cfcSGreg Clayton             else
195*19388cfcSGreg Clayton             {
196*19388cfcSGreg Clayton                 result.AppendError("invalid executable");
197*19388cfcSGreg Clayton                 result.SetStatus (eReturnStatusFailed);
198*19388cfcSGreg Clayton                 return false;
199*19388cfcSGreg Clayton             }
200*19388cfcSGreg Clayton         }
201*19388cfcSGreg Clayton 
202a7015092SGreg Clayton         Args environment;
20330fdc8d8SChris Lattner 
204a7015092SGreg Clayton         process->GetEnvironmentAsArgs (environment);
205a7015092SGreg Clayton 
206a7015092SGreg Clayton         uint32_t launch_flags = eLaunchFlagNone;
207a7015092SGreg Clayton 
208a7015092SGreg Clayton         if (process->GetDisableASLR())
209a7015092SGreg Clayton             launch_flags |= eLaunchFlagDisableASLR;
210a7015092SGreg Clayton 
211*19388cfcSGreg Clayton         const char **inferior_argv = launch_args.GetArgumentCount() ? launch_args.GetConstArgumentVector() : NULL;
212*19388cfcSGreg Clayton         const char **inferior_envp = environment.GetArgumentCount() ? environment.GetConstArgumentVector() : NULL;
21330fdc8d8SChris Lattner 
214*19388cfcSGreg Clayton         Error error;
215*19388cfcSGreg Clayton 
216*19388cfcSGreg Clayton         if (m_options.in_new_tty)
217*19388cfcSGreg Clayton         {
218*19388cfcSGreg Clayton 
219*19388cfcSGreg Clayton             lldb::pid_t terminal_pid = Host::LaunchInNewTerminal (inferior_argv,
220*19388cfcSGreg Clayton                                                                   inferior_envp,
221*19388cfcSGreg Clayton                                                                   &exe_module->GetArchitecture(),
222*19388cfcSGreg Clayton                                                                   true,
223*19388cfcSGreg Clayton                                                                   process->GetDisableASLR());
224*19388cfcSGreg Clayton 
225*19388cfcSGreg Clayton             // Let the app get launched and stopped...
226*19388cfcSGreg Clayton             const char *process_name = exe_module->GetFileSpec().GetFilename().AsCString("<invalid>");
227*19388cfcSGreg Clayton 
228*19388cfcSGreg Clayton             if (terminal_pid == LLDB_INVALID_PROCESS_ID)
229*19388cfcSGreg Clayton             {
230*19388cfcSGreg Clayton                 error.SetErrorStringWithFormat ("failed to launch '%s' in new terminal", process_name);
231*19388cfcSGreg Clayton             }
232*19388cfcSGreg Clayton             else
233*19388cfcSGreg Clayton             {
234*19388cfcSGreg Clayton                 for (int i=0; i<20; i++)
235*19388cfcSGreg Clayton                 {
236*19388cfcSGreg Clayton                     usleep (250000);
237*19388cfcSGreg Clayton                     error = process->Attach (process_name, false);
238*19388cfcSGreg Clayton                     if (error.Success())
239*19388cfcSGreg Clayton                         break;
240*19388cfcSGreg Clayton                 }
241*19388cfcSGreg Clayton             }
242*19388cfcSGreg Clayton         }
243*19388cfcSGreg Clayton         else
244*19388cfcSGreg Clayton         {
24530fdc8d8SChris Lattner             const char * stdin_path = NULL;
24630fdc8d8SChris Lattner             const char * stdout_path = NULL;
24730fdc8d8SChris Lattner             const char * stderr_path = NULL;
24830fdc8d8SChris Lattner 
249a7015092SGreg Clayton             // Were any standard input/output/error paths given on the command line?
250a7015092SGreg Clayton             if (m_options.stdin_path.empty() &&
25130fdc8d8SChris Lattner                 m_options.stdout_path.empty() &&
252a7015092SGreg Clayton                 m_options.stderr_path.empty())
25330fdc8d8SChris Lattner             {
254a7015092SGreg Clayton                 // No standard file handles were given on the command line, check
255a7015092SGreg Clayton                 // with the process object in case they were give using "set settings"
256a7015092SGreg Clayton                 stdin_path = process->GetStandardInputPath();
257a7015092SGreg Clayton                 stdout_path = process->GetStandardOutputPath();
258a7015092SGreg Clayton                 stderr_path = process->GetStandardErrorPath();
259a7015092SGreg Clayton             }
260a7015092SGreg Clayton             else
261a7015092SGreg Clayton             {
262a7015092SGreg Clayton                 stdin_path = m_options.stdin_path.empty()  ? NULL : m_options.stdin_path.c_str();
263a7015092SGreg Clayton                 stdout_path = m_options.stdout_path.empty() ? NULL : m_options.stdout_path.c_str();
264a7015092SGreg Clayton                 stderr_path = m_options.stderr_path.empty() ? NULL : m_options.stderr_path.c_str();
26530fdc8d8SChris Lattner             }
26630fdc8d8SChris Lattner 
267a7015092SGreg Clayton             if (stdin_path == NULL)
268a7015092SGreg Clayton                 stdin_path = "/dev/null";
269a7015092SGreg Clayton             if (stdout_path == NULL)
270a7015092SGreg Clayton                 stdout_path = "/dev/null";
271a7015092SGreg Clayton             if (stderr_path == NULL)
272a7015092SGreg Clayton                 stderr_path = "/dev/null";
273a7015092SGreg Clayton 
274*19388cfcSGreg Clayton             error = process->Launch (inferior_argv,
275*19388cfcSGreg Clayton                                      inferior_envp,
276f681b94fSGreg Clayton                                      launch_flags,
27730fdc8d8SChris Lattner                                      stdin_path,
27830fdc8d8SChris Lattner                                      stdout_path,
279*19388cfcSGreg Clayton                                      stderr_path);
280*19388cfcSGreg Clayton         }
28130fdc8d8SChris Lattner 
28230fdc8d8SChris Lattner         if (error.Success())
28330fdc8d8SChris Lattner         {
284*19388cfcSGreg Clayton             const char *archname = exe_module->GetArchitecture().AsCString();
285*19388cfcSGreg Clayton 
286*19388cfcSGreg Clayton             result.AppendMessageWithFormat ("Process %i launched: '%s' (%s)\n", process->GetID(), filename, archname);
28705faeb71SGreg Clayton             result.SetDidChangeProcessState (true);
28830fdc8d8SChris Lattner             if (m_options.stop_at_entry == false)
28930fdc8d8SChris Lattner             {
29005faeb71SGreg Clayton                 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
29130fdc8d8SChris Lattner                 StateType state = process->WaitForProcessToStop (NULL);
29230fdc8d8SChris Lattner 
29330fdc8d8SChris Lattner                 if (state == eStateStopped)
29430fdc8d8SChris Lattner                 {
29505faeb71SGreg Clayton                     error = process->Resume();
29605faeb71SGreg Clayton                     if (error.Success())
29705faeb71SGreg Clayton                     {
29805faeb71SGreg Clayton                         bool synchronous_execution = m_interpreter.GetSynchronous ();
29930fdc8d8SChris Lattner                         if (synchronous_execution)
30030fdc8d8SChris Lattner                         {
30105faeb71SGreg Clayton                             state = process->WaitForProcessToStop (NULL);
30230fdc8d8SChris Lattner                             result.SetDidChangeProcessState (true);
30305faeb71SGreg Clayton                             result.SetStatus (eReturnStatusSuccessFinishResult);
30405faeb71SGreg Clayton                         }
30505faeb71SGreg Clayton                         else
30605faeb71SGreg Clayton                         {
30705faeb71SGreg Clayton                             result.SetStatus (eReturnStatusSuccessContinuingNoResult);
30805faeb71SGreg Clayton                         }
30905faeb71SGreg Clayton                     }
31030fdc8d8SChris Lattner                 }
31130fdc8d8SChris Lattner             }
31230fdc8d8SChris Lattner         }
31330fdc8d8SChris Lattner 
31430fdc8d8SChris Lattner         return result.Succeeded();
31530fdc8d8SChris Lattner     }
31630fdc8d8SChris Lattner 
317ebc09c36SJim Ingham     virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
318ebc09c36SJim Ingham     {
319ebc09c36SJim Ingham         // No repeat for "process launch"...
320ebc09c36SJim Ingham         return "";
321ebc09c36SJim Ingham     }
322ebc09c36SJim Ingham 
32330fdc8d8SChris Lattner protected:
32430fdc8d8SChris Lattner 
32530fdc8d8SChris Lattner     CommandOptions m_options;
32630fdc8d8SChris Lattner };
32730fdc8d8SChris Lattner 
32830fdc8d8SChris Lattner 
329*19388cfcSGreg Clayton #define SET1 LLDB_OPT_SET_1
330*19388cfcSGreg Clayton #define SET2 LLDB_OPT_SET_2
331*19388cfcSGreg Clayton 
33230fdc8d8SChris Lattner lldb::OptionDefinition
33330fdc8d8SChris Lattner CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
33430fdc8d8SChris Lattner {
335*19388cfcSGreg Clayton { SET1 | SET2, false, "stop-at-entry", 's', no_argument,       NULL, 0, eArgTypeNone,    "Stop at the entry point of the program when launching a process."},
336*19388cfcSGreg Clayton { SET1       , false, "stdin",         'i', required_argument, NULL, 0, eArgTypePath,    "Redirect stdin for the process to <path>."},
337*19388cfcSGreg Clayton { SET1       , false, "stdout",        'o', required_argument, NULL, 0, eArgTypePath,    "Redirect stdout for the process to <path>."},
338*19388cfcSGreg Clayton { SET1       , false, "stderr",        'e', required_argument, NULL, 0, eArgTypePath,    "Redirect stderr for the process to <path>."},
339*19388cfcSGreg Clayton { SET1 | SET2, false, "plugin",        'p', required_argument, NULL, 0, eArgTypePlugin,  "Name of the process plugin you want to use."},
340*19388cfcSGreg Clayton {        SET2, false, "tty",           't', no_argument,       NULL, 0, eArgTypeNone,    "Start the process in a new terminal (tty)."},
341deaab222SCaroline Tice { 0,           false, NULL,             0,  0,                 NULL, 0, eArgTypeNone,    NULL }
34230fdc8d8SChris Lattner };
34330fdc8d8SChris Lattner 
344*19388cfcSGreg Clayton #undef SET1
345*19388cfcSGreg Clayton #undef SET2
34630fdc8d8SChris Lattner 
34730fdc8d8SChris Lattner //-------------------------------------------------------------------------
34830fdc8d8SChris Lattner // CommandObjectProcessAttach
34930fdc8d8SChris Lattner //-------------------------------------------------------------------------
35030fdc8d8SChris Lattner 
35130fdc8d8SChris Lattner class CommandObjectProcessAttach : public CommandObject
35230fdc8d8SChris Lattner {
35330fdc8d8SChris Lattner public:
35430fdc8d8SChris Lattner 
35530fdc8d8SChris Lattner     class CommandOptions : public Options
35630fdc8d8SChris Lattner     {
35730fdc8d8SChris Lattner     public:
35830fdc8d8SChris Lattner 
35930fdc8d8SChris Lattner         CommandOptions () :
36030fdc8d8SChris Lattner             Options()
36130fdc8d8SChris Lattner         {
36230fdc8d8SChris Lattner             // Keep default values of all options in one place: ResetOptionValues ()
36330fdc8d8SChris Lattner             ResetOptionValues ();
36430fdc8d8SChris Lattner         }
36530fdc8d8SChris Lattner 
36630fdc8d8SChris Lattner         ~CommandOptions ()
36730fdc8d8SChris Lattner         {
36830fdc8d8SChris Lattner         }
36930fdc8d8SChris Lattner 
37030fdc8d8SChris Lattner         Error
37130fdc8d8SChris Lattner         SetOptionValue (int option_idx, const char *option_arg)
37230fdc8d8SChris Lattner         {
37330fdc8d8SChris Lattner             Error error;
37430fdc8d8SChris Lattner             char short_option = (char) m_getopt_table[option_idx].val;
37530fdc8d8SChris Lattner             bool success = false;
37630fdc8d8SChris Lattner             switch (short_option)
37730fdc8d8SChris Lattner             {
37830fdc8d8SChris Lattner                 case 'p':
37930fdc8d8SChris Lattner                     pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success);
38030fdc8d8SChris Lattner                     if (!success || pid == LLDB_INVALID_PROCESS_ID)
38130fdc8d8SChris Lattner                     {
38230fdc8d8SChris Lattner                         error.SetErrorStringWithFormat("Invalid process ID '%s'.\n", option_arg);
38330fdc8d8SChris Lattner                     }
38430fdc8d8SChris Lattner                     break;
38530fdc8d8SChris Lattner 
38630fdc8d8SChris Lattner                 case 'P':
38730fdc8d8SChris Lattner                     plugin_name = option_arg;
38830fdc8d8SChris Lattner                     break;
38930fdc8d8SChris Lattner 
39030fdc8d8SChris Lattner                 case 'n':
39130fdc8d8SChris Lattner                     name.assign(option_arg);
39230fdc8d8SChris Lattner                     break;
39330fdc8d8SChris Lattner 
39430fdc8d8SChris Lattner                 case 'w':
39530fdc8d8SChris Lattner                     waitfor = true;
39630fdc8d8SChris Lattner                     break;
39730fdc8d8SChris Lattner 
39830fdc8d8SChris Lattner                 default:
39930fdc8d8SChris Lattner                     error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
40030fdc8d8SChris Lattner                     break;
40130fdc8d8SChris Lattner             }
40230fdc8d8SChris Lattner             return error;
40330fdc8d8SChris Lattner         }
40430fdc8d8SChris Lattner 
40530fdc8d8SChris Lattner         void
40630fdc8d8SChris Lattner         ResetOptionValues ()
40730fdc8d8SChris Lattner         {
40830fdc8d8SChris Lattner             Options::ResetOptionValues();
40930fdc8d8SChris Lattner             pid = LLDB_INVALID_PROCESS_ID;
41030fdc8d8SChris Lattner             name.clear();
41130fdc8d8SChris Lattner             waitfor = false;
41230fdc8d8SChris Lattner         }
41330fdc8d8SChris Lattner 
41430fdc8d8SChris Lattner         const lldb::OptionDefinition*
41530fdc8d8SChris Lattner         GetDefinitions ()
41630fdc8d8SChris Lattner         {
41730fdc8d8SChris Lattner             return g_option_table;
41830fdc8d8SChris Lattner         }
41930fdc8d8SChris Lattner 
4205aee162fSJim Ingham         virtual bool
421a7015092SGreg Clayton         HandleOptionArgumentCompletion (CommandInterpreter &interpeter,
4225aee162fSJim Ingham                                         Args &input,
4235aee162fSJim Ingham                                         int cursor_index,
4245aee162fSJim Ingham                                         int char_pos,
4255aee162fSJim Ingham                                         OptionElementVector &opt_element_vector,
4265aee162fSJim Ingham                                         int opt_element_index,
4275aee162fSJim Ingham                                         int match_start_point,
4285aee162fSJim Ingham                                         int max_return_elements,
4295aee162fSJim Ingham                                         bool &word_complete,
4305aee162fSJim Ingham                                         StringList &matches)
4315aee162fSJim Ingham         {
4325aee162fSJim Ingham             int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
4335aee162fSJim Ingham             int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
4345aee162fSJim Ingham 
4355aee162fSJim Ingham             // We are only completing the name option for now...
4365aee162fSJim Ingham 
4375aee162fSJim Ingham             const lldb::OptionDefinition *opt_defs = GetDefinitions();
4385aee162fSJim Ingham             if (opt_defs[opt_defs_index].short_option == 'n')
4395aee162fSJim Ingham             {
4405aee162fSJim Ingham                 // Are we in the name?
4415aee162fSJim Ingham 
4425aee162fSJim Ingham                 // Look to see if there is a -P argument provided, and if so use that plugin, otherwise
4435aee162fSJim Ingham                 // use the default plugin.
444a7015092SGreg Clayton                 Process *process = interpeter.GetDebugger().GetExecutionContext().process;
4455aee162fSJim Ingham                 bool need_to_delete_process = false;
4465aee162fSJim Ingham 
4475aee162fSJim Ingham                 const char *partial_name = NULL;
4485aee162fSJim Ingham                 partial_name = input.GetArgumentAtIndex(opt_arg_pos);
4495aee162fSJim Ingham 
4505aee162fSJim Ingham                 if (process && process->IsAlive())
4515aee162fSJim Ingham                     return true;
4525aee162fSJim Ingham 
453a7015092SGreg Clayton                 Target *target = interpeter.GetDebugger().GetSelectedTarget().get();
4545aee162fSJim Ingham                 if (target == NULL)
4555aee162fSJim Ingham                 {
4565aee162fSJim Ingham                     // No target has been set yet, for now do host completion.  Otherwise I don't know how we would
4575aee162fSJim Ingham                     // figure out what the right target to use is...
4585aee162fSJim Ingham                     std::vector<lldb::pid_t> pids;
4595aee162fSJim Ingham                     Host::ListProcessesMatchingName (partial_name, matches, pids);
4605aee162fSJim Ingham                     return true;
4615aee162fSJim Ingham                 }
4625aee162fSJim Ingham                 if (!process)
4635aee162fSJim Ingham                 {
464a7015092SGreg Clayton                     process = target->CreateProcess (interpeter.GetDebugger().GetListener(), partial_name).get();
4655aee162fSJim Ingham                     need_to_delete_process = true;
4665aee162fSJim Ingham                 }
4675aee162fSJim Ingham 
4685aee162fSJim Ingham                 if (process)
4695aee162fSJim Ingham                 {
4705aee162fSJim Ingham                     matches.Clear();
4715aee162fSJim Ingham                     std::vector<lldb::pid_t> pids;
4725aee162fSJim Ingham                     process->ListProcessesMatchingName (NULL, matches, pids);
4735aee162fSJim Ingham                     if (need_to_delete_process)
4745aee162fSJim Ingham                         target->DeleteCurrentProcess();
4755aee162fSJim Ingham                     return true;
4765aee162fSJim Ingham                 }
4775aee162fSJim Ingham             }
4785aee162fSJim Ingham 
4795aee162fSJim Ingham             return false;
4805aee162fSJim Ingham         }
4815aee162fSJim Ingham 
48230fdc8d8SChris Lattner         // Options table: Required for subclasses of Options.
48330fdc8d8SChris Lattner 
48430fdc8d8SChris Lattner         static lldb::OptionDefinition g_option_table[];
48530fdc8d8SChris Lattner 
48630fdc8d8SChris Lattner         // Instance variables to hold the values for command options.
48730fdc8d8SChris Lattner 
48830fdc8d8SChris Lattner         lldb::pid_t pid;
48930fdc8d8SChris Lattner         std::string plugin_name;
49030fdc8d8SChris Lattner         std::string name;
49130fdc8d8SChris Lattner         bool waitfor;
49230fdc8d8SChris Lattner     };
49330fdc8d8SChris Lattner 
494a7015092SGreg Clayton     CommandObjectProcessAttach (CommandInterpreter &interpreter) :
495a7015092SGreg Clayton         CommandObject (interpreter,
496a7015092SGreg Clayton                        "process attach",
497e3d26315SCaroline Tice                        "Attach to a process.",
4985aee162fSJim Ingham                        "process attach <cmd-options>")
4995aee162fSJim Ingham     {
5005aee162fSJim Ingham     }
5015aee162fSJim Ingham 
5025aee162fSJim Ingham     ~CommandObjectProcessAttach ()
5035aee162fSJim Ingham     {
5045aee162fSJim Ingham     }
5055aee162fSJim Ingham 
5065aee162fSJim Ingham     bool
507a7015092SGreg Clayton     Execute (Args& command,
5085aee162fSJim Ingham              CommandReturnObject &result)
5095aee162fSJim Ingham     {
510a7015092SGreg Clayton         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
5115aee162fSJim Ingham 
512a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
5135aee162fSJim Ingham         if (process)
5145aee162fSJim Ingham         {
5155aee162fSJim Ingham             if (process->IsAlive())
5165aee162fSJim Ingham             {
5175aee162fSJim Ingham                 result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before attaching.\n",
5185aee162fSJim Ingham                                               process->GetID());
5195aee162fSJim Ingham                 result.SetStatus (eReturnStatusFailed);
5205aee162fSJim Ingham                 return false;
5215aee162fSJim Ingham             }
5225aee162fSJim Ingham         }
5235aee162fSJim Ingham 
5245aee162fSJim Ingham         if (target == NULL)
5255aee162fSJim Ingham         {
5265aee162fSJim Ingham             // If there isn't a current target create one.
5275aee162fSJim Ingham             TargetSP new_target_sp;
5285aee162fSJim Ingham             FileSpec emptyFileSpec;
5295aee162fSJim Ingham             ArchSpec emptyArchSpec;
5305aee162fSJim Ingham             Error error;
5315aee162fSJim Ingham 
532a7015092SGreg Clayton             error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(),
5335aee162fSJim Ingham                                                                               emptyFileSpec,
5345aee162fSJim Ingham                                                                               emptyArchSpec,
5355aee162fSJim Ingham                                                                               NULL,
5365aee162fSJim Ingham                                                                               false,
5375aee162fSJim Ingham                                                                               new_target_sp);
5385aee162fSJim Ingham             target = new_target_sp.get();
5395aee162fSJim Ingham             if (target == NULL || error.Fail())
5405aee162fSJim Ingham             {
5415aee162fSJim Ingham                 result.AppendError(error.AsCString("Error creating empty target"));
5425aee162fSJim Ingham                 return false;
5435aee162fSJim Ingham             }
544a7015092SGreg Clayton             m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target);
5455aee162fSJim Ingham         }
5465aee162fSJim Ingham 
5475aee162fSJim Ingham         // Record the old executable module, we want to issue a warning if the process of attaching changed the
5485aee162fSJim Ingham         // current executable (like somebody said "file foo" then attached to a PID whose executable was bar.)
5495aee162fSJim Ingham 
5505aee162fSJim Ingham         ModuleSP old_exec_module_sp = target->GetExecutableModule();
5515aee162fSJim Ingham         ArchSpec old_arch_spec = target->GetArchitecture();
5525aee162fSJim Ingham 
5535aee162fSJim Ingham         if (command.GetArgumentCount())
5545aee162fSJim Ingham         {
5555aee162fSJim Ingham             result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
5565aee162fSJim Ingham             result.SetStatus (eReturnStatusFailed);
5575aee162fSJim Ingham         }
5585aee162fSJim Ingham         else
5595aee162fSJim Ingham         {
5605aee162fSJim Ingham             const char *plugin_name = NULL;
5615aee162fSJim Ingham 
5625aee162fSJim Ingham             if (!m_options.plugin_name.empty())
5635aee162fSJim Ingham                 plugin_name = m_options.plugin_name.c_str();
5645aee162fSJim Ingham 
565a7015092SGreg Clayton             process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
5665aee162fSJim Ingham 
5675aee162fSJim Ingham             if (process)
5685aee162fSJim Ingham             {
5695aee162fSJim Ingham                 Error error;
5705aee162fSJim Ingham                 int attach_pid = m_options.pid;
5715aee162fSJim Ingham 
5723a0b9cdfSJim Ingham                 const char *wait_name = NULL;
5733a0b9cdfSJim Ingham 
5745aee162fSJim Ingham                 if (m_options.name.empty())
5755aee162fSJim Ingham                 {
5763a0b9cdfSJim Ingham                     if (old_exec_module_sp)
5773a0b9cdfSJim Ingham                     {
5783a0b9cdfSJim Ingham                         wait_name = old_exec_module_sp->GetFileSpec().GetFilename().AsCString();
5793a0b9cdfSJim Ingham                     }
5805aee162fSJim Ingham                 }
5815aee162fSJim Ingham                 else
5825aee162fSJim Ingham                 {
5833a0b9cdfSJim Ingham                     wait_name = m_options.name.c_str();
5843a0b9cdfSJim Ingham                 }
5853a0b9cdfSJim Ingham 
5863a0b9cdfSJim Ingham                 // If we are waiting for a process with this name to show up, do that first.
5873a0b9cdfSJim Ingham                 if (m_options.waitfor)
5883a0b9cdfSJim Ingham                 {
5893a0b9cdfSJim Ingham 
5903a0b9cdfSJim Ingham                     if (wait_name == NULL)
5913a0b9cdfSJim Ingham                     {
5923a0b9cdfSJim Ingham                         result.AppendError("Invalid arguments: must have a file loaded or supply a process name with the waitfor option.\n");
5933a0b9cdfSJim Ingham                         result.SetStatus (eReturnStatusFailed);
5943a0b9cdfSJim Ingham                         return false;
5953a0b9cdfSJim Ingham                     }
5963a0b9cdfSJim Ingham 
597a7015092SGreg Clayton                     m_interpreter.GetDebugger().GetOutputStream().Printf("Waiting to attach to a process named \"%s\".\n", wait_name);
5983a0b9cdfSJim Ingham                     error = process->Attach (wait_name, m_options.waitfor);
5995aee162fSJim Ingham                     if (error.Success())
6005aee162fSJim Ingham                     {
6015aee162fSJim Ingham                         result.SetStatus (eReturnStatusSuccessContinuingNoResult);
6025aee162fSJim Ingham                     }
6035aee162fSJim Ingham                     else
6045aee162fSJim Ingham                     {
6055aee162fSJim Ingham                         result.AppendErrorWithFormat ("Waiting for a process to launch named '%s': %s\n",
6063a0b9cdfSJim Ingham                                                          wait_name,
6075aee162fSJim Ingham                                                          error.AsCString());
6085aee162fSJim Ingham                         result.SetStatus (eReturnStatusFailed);
6095aee162fSJim Ingham                         return false;
6105aee162fSJim Ingham                     }
6115aee162fSJim Ingham                 }
6125aee162fSJim Ingham                 else
6135aee162fSJim Ingham                 {
6145aee162fSJim Ingham                     // If the process was specified by name look it up, so we can warn if there are multiple
6155aee162fSJim Ingham                     // processes with this pid.
6165aee162fSJim Ingham 
6173a0b9cdfSJim Ingham                     if (attach_pid == LLDB_INVALID_PROCESS_ID && wait_name != NULL)
6185aee162fSJim Ingham                     {
6195aee162fSJim Ingham                         std::vector<lldb::pid_t> pids;
6205aee162fSJim Ingham                         StringList matches;
6215aee162fSJim Ingham 
6223a0b9cdfSJim Ingham                         process->ListProcessesMatchingName(wait_name, matches, pids);
6235aee162fSJim Ingham                         if (matches.GetSize() > 1)
6245aee162fSJim Ingham                         {
6253a0b9cdfSJim Ingham                             result.AppendErrorWithFormat("More than one process named %s\n", wait_name);
6265aee162fSJim Ingham                             result.SetStatus (eReturnStatusFailed);
6275aee162fSJim Ingham                             return false;
6285aee162fSJim Ingham                         }
6295aee162fSJim Ingham                         else if (matches.GetSize() == 0)
6305aee162fSJim Ingham                         {
6313a0b9cdfSJim Ingham                             result.AppendErrorWithFormat("Could not find a process named %s\n", wait_name);
6325aee162fSJim Ingham                             result.SetStatus (eReturnStatusFailed);
6335aee162fSJim Ingham                             return false;
6345aee162fSJim Ingham                         }
6355aee162fSJim Ingham                         else
6365aee162fSJim Ingham                         {
6375aee162fSJim Ingham                             attach_pid = pids[0];
6385aee162fSJim Ingham                         }
6395aee162fSJim Ingham 
6405aee162fSJim Ingham                     }
6415aee162fSJim Ingham 
6425aee162fSJim Ingham                     if (attach_pid != LLDB_INVALID_PROCESS_ID)
6435aee162fSJim Ingham                     {
6445aee162fSJim Ingham                         error = process->Attach (attach_pid);
6455aee162fSJim Ingham                         if (error.Success())
6465aee162fSJim Ingham                         {
6475aee162fSJim Ingham                             result.SetStatus (eReturnStatusSuccessContinuingNoResult);
6485aee162fSJim Ingham                         }
6495aee162fSJim Ingham                         else
6505aee162fSJim Ingham                         {
6515aee162fSJim Ingham                             result.AppendErrorWithFormat ("Attaching to process %i failed: %s.\n",
6525aee162fSJim Ingham                                                          attach_pid,
6535aee162fSJim Ingham                                                          error.AsCString());
6545aee162fSJim Ingham                             result.SetStatus (eReturnStatusFailed);
6555aee162fSJim Ingham                         }
6565aee162fSJim Ingham                     }
6575aee162fSJim Ingham                     else
6585aee162fSJim Ingham                     {
6595aee162fSJim Ingham                         result.AppendErrorWithFormat ("No PID specified for attach\n",
6605aee162fSJim Ingham                                                          attach_pid,
6615aee162fSJim Ingham                                                          error.AsCString());
6625aee162fSJim Ingham                         result.SetStatus (eReturnStatusFailed);
6635aee162fSJim Ingham 
6645aee162fSJim Ingham                     }
6655aee162fSJim Ingham                 }
6665aee162fSJim Ingham             }
6675aee162fSJim Ingham         }
6685aee162fSJim Ingham 
6695aee162fSJim Ingham         if (result.Succeeded())
6705aee162fSJim Ingham         {
6715aee162fSJim Ingham             // Okay, we're done.  Last step is to warn if the executable module has changed:
6725aee162fSJim Ingham             if (!old_exec_module_sp)
6735aee162fSJim Ingham             {
6745aee162fSJim Ingham                 char new_path[PATH_MAX + 1];
6755aee162fSJim Ingham                 target->GetExecutableModule()->GetFileSpec().GetPath(new_path, PATH_MAX);
6765aee162fSJim Ingham 
6775aee162fSJim Ingham                 result.AppendMessageWithFormat("Executable module set to \"%s\".\n",
6785aee162fSJim Ingham                     new_path);
6795aee162fSJim Ingham             }
6805aee162fSJim Ingham             else if (old_exec_module_sp->GetFileSpec() != target->GetExecutableModule()->GetFileSpec())
6815aee162fSJim Ingham             {
6825aee162fSJim Ingham                 char old_path[PATH_MAX + 1];
6835aee162fSJim Ingham                 char new_path[PATH_MAX + 1];
6845aee162fSJim Ingham 
6855aee162fSJim Ingham                 old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX);
6865aee162fSJim Ingham                 target->GetExecutableModule()->GetFileSpec().GetPath (new_path, PATH_MAX);
6875aee162fSJim Ingham 
6885aee162fSJim Ingham                 result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n",
6895aee162fSJim Ingham                                                     old_path, new_path);
6905aee162fSJim Ingham             }
6915aee162fSJim Ingham 
6925aee162fSJim Ingham             if (!old_arch_spec.IsValid())
6935aee162fSJim Ingham             {
6945aee162fSJim Ingham                 result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().AsCString());
6955aee162fSJim Ingham             }
6965aee162fSJim Ingham             else if (old_arch_spec != target->GetArchitecture())
6975aee162fSJim Ingham             {
6985aee162fSJim Ingham                 result.AppendWarningWithFormat("Architecture changed from %s to %s.\n",
6995aee162fSJim Ingham                                                 old_arch_spec.AsCString(), target->GetArchitecture().AsCString());
7005aee162fSJim Ingham             }
7015aee162fSJim Ingham         }
7025aee162fSJim Ingham         return result.Succeeded();
7035aee162fSJim Ingham     }
7045aee162fSJim Ingham 
7055aee162fSJim Ingham     Options *
7065aee162fSJim Ingham     GetOptions ()
7075aee162fSJim Ingham     {
7085aee162fSJim Ingham         return &m_options;
7095aee162fSJim Ingham     }
7105aee162fSJim Ingham 
71130fdc8d8SChris Lattner protected:
71230fdc8d8SChris Lattner 
71330fdc8d8SChris Lattner     CommandOptions m_options;
71430fdc8d8SChris Lattner };
71530fdc8d8SChris Lattner 
71630fdc8d8SChris Lattner 
71730fdc8d8SChris Lattner lldb::OptionDefinition
71830fdc8d8SChris Lattner CommandObjectProcessAttach::CommandOptions::g_option_table[] =
71930fdc8d8SChris Lattner {
720deaab222SCaroline Tice { LLDB_OPT_SET_ALL, false, "plugin", 'P', required_argument, NULL, 0, eArgTypePlugin,        "Name of the process plugin you want to use."},
721deaab222SCaroline Tice { LLDB_OPT_SET_1,   false, "pid",    'p', required_argument, NULL, 0, eArgTypePid,           "The process ID of an existing process to attach to."},
722deaab222SCaroline Tice { LLDB_OPT_SET_2,   false, "name",   'n', required_argument, NULL, 0, eArgTypeProcessName,  "The name of the process to attach to."},
723deaab222SCaroline Tice { LLDB_OPT_SET_2,   false, "waitfor",'w', no_argument,       NULL, 0, eArgTypeNone,              "Wait for the the process with <process-name> to launch."},
724deaab222SCaroline Tice { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
72530fdc8d8SChris Lattner };
72630fdc8d8SChris Lattner 
72730fdc8d8SChris Lattner //-------------------------------------------------------------------------
72830fdc8d8SChris Lattner // CommandObjectProcessContinue
72930fdc8d8SChris Lattner //-------------------------------------------------------------------------
73030fdc8d8SChris Lattner 
73130fdc8d8SChris Lattner class CommandObjectProcessContinue : public CommandObject
73230fdc8d8SChris Lattner {
73330fdc8d8SChris Lattner public:
73430fdc8d8SChris Lattner 
735a7015092SGreg Clayton     CommandObjectProcessContinue (CommandInterpreter &interpreter) :
736a7015092SGreg Clayton         CommandObject (interpreter,
737a7015092SGreg Clayton                        "process continue",
738e3d26315SCaroline Tice                        "Continue execution of all threads in the current process.",
73930fdc8d8SChris Lattner                        "process continue",
74030fdc8d8SChris Lattner                        eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
74130fdc8d8SChris Lattner     {
74230fdc8d8SChris Lattner     }
74330fdc8d8SChris Lattner 
74430fdc8d8SChris Lattner 
74530fdc8d8SChris Lattner     ~CommandObjectProcessContinue ()
74630fdc8d8SChris Lattner     {
74730fdc8d8SChris Lattner     }
74830fdc8d8SChris Lattner 
74930fdc8d8SChris Lattner     bool
750a7015092SGreg Clayton     Execute (Args& command,
75130fdc8d8SChris Lattner              CommandReturnObject &result)
75230fdc8d8SChris Lattner     {
753a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
754a7015092SGreg Clayton         bool synchronous_execution = m_interpreter.GetSynchronous ();
75530fdc8d8SChris Lattner 
75630fdc8d8SChris Lattner         if (process == NULL)
75730fdc8d8SChris Lattner         {
75830fdc8d8SChris Lattner             result.AppendError ("no process to continue");
75930fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
76030fdc8d8SChris Lattner             return false;
76130fdc8d8SChris Lattner          }
76230fdc8d8SChris Lattner 
76330fdc8d8SChris Lattner         StateType state = process->GetState();
76430fdc8d8SChris Lattner         if (state == eStateStopped)
76530fdc8d8SChris Lattner         {
76630fdc8d8SChris Lattner             if (command.GetArgumentCount() != 0)
76730fdc8d8SChris Lattner             {
76830fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str());
76930fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
77030fdc8d8SChris Lattner                 return false;
77130fdc8d8SChris Lattner             }
77230fdc8d8SChris Lattner 
77330fdc8d8SChris Lattner             const uint32_t num_threads = process->GetThreadList().GetSize();
77430fdc8d8SChris Lattner 
77530fdc8d8SChris Lattner             // Set the actions that the threads should each take when resuming
77630fdc8d8SChris Lattner             for (uint32_t idx=0; idx<num_threads; ++idx)
77730fdc8d8SChris Lattner             {
77830fdc8d8SChris Lattner                 process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning);
77930fdc8d8SChris Lattner             }
78030fdc8d8SChris Lattner 
78130fdc8d8SChris Lattner             Error error(process->Resume());
78230fdc8d8SChris Lattner             if (error.Success())
78330fdc8d8SChris Lattner             {
784*19388cfcSGreg Clayton                 result.AppendMessageWithFormat ("Process %i resuming\n", process->GetID());
78530fdc8d8SChris Lattner                 if (synchronous_execution)
78630fdc8d8SChris Lattner                 {
787b132097bSGreg Clayton                     state = process->WaitForProcessToStop (NULL);
78830fdc8d8SChris Lattner 
78930fdc8d8SChris Lattner                     result.SetDidChangeProcessState (true);
79030fdc8d8SChris Lattner                     result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
79130fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
79230fdc8d8SChris Lattner                 }
79330fdc8d8SChris Lattner                 else
79430fdc8d8SChris Lattner                 {
79530fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusSuccessContinuingNoResult);
79630fdc8d8SChris Lattner                 }
79730fdc8d8SChris Lattner             }
79830fdc8d8SChris Lattner             else
79930fdc8d8SChris Lattner             {
80030fdc8d8SChris Lattner                 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
80130fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
80230fdc8d8SChris Lattner             }
80330fdc8d8SChris Lattner         }
80430fdc8d8SChris Lattner         else
80530fdc8d8SChris Lattner         {
80630fdc8d8SChris Lattner             result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
80730fdc8d8SChris Lattner                                          StateAsCString(state));
80830fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
80930fdc8d8SChris Lattner         }
81030fdc8d8SChris Lattner         return result.Succeeded();
81130fdc8d8SChris Lattner     }
81230fdc8d8SChris Lattner };
81330fdc8d8SChris Lattner 
81430fdc8d8SChris Lattner //-------------------------------------------------------------------------
81530fdc8d8SChris Lattner // CommandObjectProcessDetach
81630fdc8d8SChris Lattner //-------------------------------------------------------------------------
81730fdc8d8SChris Lattner 
81830fdc8d8SChris Lattner class CommandObjectProcessDetach : public CommandObject
81930fdc8d8SChris Lattner {
82030fdc8d8SChris Lattner public:
82130fdc8d8SChris Lattner 
822a7015092SGreg Clayton     CommandObjectProcessDetach (CommandInterpreter &interpreter) :
823a7015092SGreg Clayton         CommandObject (interpreter,
824a7015092SGreg Clayton                        "process detach",
825e3d26315SCaroline Tice                        "Detach from the current process being debugged.",
82630fdc8d8SChris Lattner                        "process detach",
82730fdc8d8SChris Lattner                        eFlagProcessMustBeLaunched)
82830fdc8d8SChris Lattner     {
82930fdc8d8SChris Lattner     }
83030fdc8d8SChris Lattner 
83130fdc8d8SChris Lattner     ~CommandObjectProcessDetach ()
83230fdc8d8SChris Lattner     {
83330fdc8d8SChris Lattner     }
83430fdc8d8SChris Lattner 
83530fdc8d8SChris Lattner     bool
836a7015092SGreg Clayton     Execute (Args& command,
83730fdc8d8SChris Lattner              CommandReturnObject &result)
83830fdc8d8SChris Lattner     {
839a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
84030fdc8d8SChris Lattner         if (process == NULL)
84130fdc8d8SChris Lattner         {
84230fdc8d8SChris Lattner             result.AppendError ("must have a valid process in order to detach");
84330fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
84430fdc8d8SChris Lattner             return false;
84530fdc8d8SChris Lattner         }
84630fdc8d8SChris Lattner 
84730fdc8d8SChris Lattner         Error error (process->Detach());
84830fdc8d8SChris Lattner         if (error.Success())
84930fdc8d8SChris Lattner         {
85030fdc8d8SChris Lattner             result.SetStatus (eReturnStatusSuccessFinishResult);
85130fdc8d8SChris Lattner         }
85230fdc8d8SChris Lattner         else
85330fdc8d8SChris Lattner         {
85430fdc8d8SChris Lattner             result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString());
85530fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
85630fdc8d8SChris Lattner             return false;
85730fdc8d8SChris Lattner         }
85830fdc8d8SChris Lattner         return result.Succeeded();
85930fdc8d8SChris Lattner     }
86030fdc8d8SChris Lattner };
86130fdc8d8SChris Lattner 
86230fdc8d8SChris Lattner //-------------------------------------------------------------------------
86330fdc8d8SChris Lattner // CommandObjectProcessSignal
86430fdc8d8SChris Lattner //-------------------------------------------------------------------------
86530fdc8d8SChris Lattner 
86630fdc8d8SChris Lattner class CommandObjectProcessSignal : public CommandObject
86730fdc8d8SChris Lattner {
86830fdc8d8SChris Lattner public:
86930fdc8d8SChris Lattner 
870a7015092SGreg Clayton     CommandObjectProcessSignal (CommandInterpreter &interpreter) :
871a7015092SGreg Clayton         CommandObject (interpreter,
872a7015092SGreg Clayton                        "process signal",
873e3d26315SCaroline Tice                        "Send a UNIX signal to the current process being debugged.",
874405fe67fSCaroline Tice                        NULL)
87530fdc8d8SChris Lattner     {
876405fe67fSCaroline Tice         CommandArgumentEntry arg;
877405fe67fSCaroline Tice         CommandArgumentData signal_arg;
878405fe67fSCaroline Tice 
879405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
880405fe67fSCaroline Tice         signal_arg.arg_type = eArgTypeUnixSignalNumber;
881405fe67fSCaroline Tice         signal_arg.arg_repetition = eArgRepeatPlain;
882405fe67fSCaroline Tice 
883405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
884405fe67fSCaroline Tice         arg.push_back (signal_arg);
885405fe67fSCaroline Tice 
886405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
887405fe67fSCaroline Tice         m_arguments.push_back (arg);
88830fdc8d8SChris Lattner     }
88930fdc8d8SChris Lattner 
89030fdc8d8SChris Lattner     ~CommandObjectProcessSignal ()
89130fdc8d8SChris Lattner     {
89230fdc8d8SChris Lattner     }
89330fdc8d8SChris Lattner 
89430fdc8d8SChris Lattner     bool
895a7015092SGreg Clayton     Execute (Args& command,
89630fdc8d8SChris Lattner              CommandReturnObject &result)
89730fdc8d8SChris Lattner     {
898a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
89930fdc8d8SChris Lattner         if (process == NULL)
90030fdc8d8SChris Lattner         {
90130fdc8d8SChris Lattner             result.AppendError ("no process to signal");
90230fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
90330fdc8d8SChris Lattner             return false;
90430fdc8d8SChris Lattner         }
90530fdc8d8SChris Lattner 
90630fdc8d8SChris Lattner         if (command.GetArgumentCount() == 1)
90730fdc8d8SChris Lattner         {
908237cd906SGreg Clayton             int signo = LLDB_INVALID_SIGNAL_NUMBER;
909237cd906SGreg Clayton 
910237cd906SGreg Clayton             const char *signal_name = command.GetArgumentAtIndex(0);
911237cd906SGreg Clayton             if (::isxdigit (signal_name[0]))
912237cd906SGreg Clayton                 signo = Args::StringToSInt32(signal_name, LLDB_INVALID_SIGNAL_NUMBER, 0);
913237cd906SGreg Clayton             else
914237cd906SGreg Clayton                 signo = process->GetUnixSignals().GetSignalNumberFromName (signal_name);
915237cd906SGreg Clayton 
916237cd906SGreg Clayton             if (signo == LLDB_INVALID_SIGNAL_NUMBER)
91730fdc8d8SChris Lattner             {
91830fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0));
91930fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
92030fdc8d8SChris Lattner             }
92130fdc8d8SChris Lattner             else
92230fdc8d8SChris Lattner             {
92330fdc8d8SChris Lattner                 Error error (process->Signal (signo));
92430fdc8d8SChris Lattner                 if (error.Success())
92530fdc8d8SChris Lattner                 {
92630fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusSuccessFinishResult);
92730fdc8d8SChris Lattner                 }
92830fdc8d8SChris Lattner                 else
92930fdc8d8SChris Lattner                 {
93030fdc8d8SChris Lattner                     result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString());
93130fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusFailed);
93230fdc8d8SChris Lattner                 }
93330fdc8d8SChris Lattner             }
93430fdc8d8SChris Lattner         }
93530fdc8d8SChris Lattner         else
93630fdc8d8SChris Lattner         {
93730fdc8d8SChris Lattner             result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: \n", m_cmd_name.c_str(),
93830fdc8d8SChris Lattner                                         m_cmd_syntax.c_str());
93930fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
94030fdc8d8SChris Lattner         }
94130fdc8d8SChris Lattner         return result.Succeeded();
94230fdc8d8SChris Lattner     }
94330fdc8d8SChris Lattner };
94430fdc8d8SChris Lattner 
94530fdc8d8SChris Lattner 
94630fdc8d8SChris Lattner //-------------------------------------------------------------------------
94730fdc8d8SChris Lattner // CommandObjectProcessInterrupt
94830fdc8d8SChris Lattner //-------------------------------------------------------------------------
94930fdc8d8SChris Lattner 
95030fdc8d8SChris Lattner class CommandObjectProcessInterrupt : public CommandObject
95130fdc8d8SChris Lattner {
95230fdc8d8SChris Lattner public:
95330fdc8d8SChris Lattner 
95430fdc8d8SChris Lattner 
955a7015092SGreg Clayton     CommandObjectProcessInterrupt (CommandInterpreter &interpreter) :
956a7015092SGreg Clayton     CommandObject (interpreter,
957a7015092SGreg Clayton                    "process interrupt",
958e3d26315SCaroline Tice                    "Interrupt the current process being debugged.",
95930fdc8d8SChris Lattner                    "process interrupt",
96030fdc8d8SChris Lattner                    eFlagProcessMustBeLaunched)
96130fdc8d8SChris Lattner     {
96230fdc8d8SChris Lattner     }
96330fdc8d8SChris Lattner 
96430fdc8d8SChris Lattner     ~CommandObjectProcessInterrupt ()
96530fdc8d8SChris Lattner     {
96630fdc8d8SChris Lattner     }
96730fdc8d8SChris Lattner 
96830fdc8d8SChris Lattner     bool
969a7015092SGreg Clayton     Execute (Args& command,
97030fdc8d8SChris Lattner              CommandReturnObject &result)
97130fdc8d8SChris Lattner     {
972a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
97330fdc8d8SChris Lattner         if (process == NULL)
97430fdc8d8SChris Lattner         {
97530fdc8d8SChris Lattner             result.AppendError ("no process to halt");
97630fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
97730fdc8d8SChris Lattner             return false;
97830fdc8d8SChris Lattner         }
97930fdc8d8SChris Lattner 
98030fdc8d8SChris Lattner         if (command.GetArgumentCount() == 0)
98130fdc8d8SChris Lattner         {
98230fdc8d8SChris Lattner             Error error(process->Halt ());
98330fdc8d8SChris Lattner             if (error.Success())
98430fdc8d8SChris Lattner             {
98530fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusSuccessFinishResult);
98630fdc8d8SChris Lattner 
98730fdc8d8SChris Lattner                 // Maybe we should add a "SuspendThreadPlans so we
98830fdc8d8SChris Lattner                 // can halt, and keep in place all the current thread plans.
98930fdc8d8SChris Lattner                 process->GetThreadList().DiscardThreadPlans();
99030fdc8d8SChris Lattner             }
99130fdc8d8SChris Lattner             else
99230fdc8d8SChris Lattner             {
99330fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString());
99430fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
99530fdc8d8SChris Lattner             }
99630fdc8d8SChris Lattner         }
99730fdc8d8SChris Lattner         else
99830fdc8d8SChris Lattner         {
99930fdc8d8SChris Lattner             result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
100030fdc8d8SChris Lattner                                         m_cmd_name.c_str(),
100130fdc8d8SChris Lattner                                         m_cmd_syntax.c_str());
100230fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
100330fdc8d8SChris Lattner         }
100430fdc8d8SChris Lattner         return result.Succeeded();
100530fdc8d8SChris Lattner     }
100630fdc8d8SChris Lattner };
100730fdc8d8SChris Lattner 
100830fdc8d8SChris Lattner //-------------------------------------------------------------------------
100930fdc8d8SChris Lattner // CommandObjectProcessKill
101030fdc8d8SChris Lattner //-------------------------------------------------------------------------
101130fdc8d8SChris Lattner 
101230fdc8d8SChris Lattner class CommandObjectProcessKill : public CommandObject
101330fdc8d8SChris Lattner {
101430fdc8d8SChris Lattner public:
101530fdc8d8SChris Lattner 
1016a7015092SGreg Clayton     CommandObjectProcessKill (CommandInterpreter &interpreter) :
1017a7015092SGreg Clayton     CommandObject (interpreter,
1018a7015092SGreg Clayton                    "process kill",
1019e3d26315SCaroline Tice                    "Terminate the current process being debugged.",
102030fdc8d8SChris Lattner                    "process kill",
102130fdc8d8SChris Lattner                    eFlagProcessMustBeLaunched)
102230fdc8d8SChris Lattner     {
102330fdc8d8SChris Lattner     }
102430fdc8d8SChris Lattner 
102530fdc8d8SChris Lattner     ~CommandObjectProcessKill ()
102630fdc8d8SChris Lattner     {
102730fdc8d8SChris Lattner     }
102830fdc8d8SChris Lattner 
102930fdc8d8SChris Lattner     bool
1030a7015092SGreg Clayton     Execute (Args& command,
103130fdc8d8SChris Lattner              CommandReturnObject &result)
103230fdc8d8SChris Lattner     {
1033a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
103430fdc8d8SChris Lattner         if (process == NULL)
103530fdc8d8SChris Lattner         {
103630fdc8d8SChris Lattner             result.AppendError ("no process to kill");
103730fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
103830fdc8d8SChris Lattner             return false;
103930fdc8d8SChris Lattner         }
104030fdc8d8SChris Lattner 
104130fdc8d8SChris Lattner         if (command.GetArgumentCount() == 0)
104230fdc8d8SChris Lattner         {
104330fdc8d8SChris Lattner             Error error (process->Destroy());
104430fdc8d8SChris Lattner             if (error.Success())
104530fdc8d8SChris Lattner             {
104630fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusSuccessFinishResult);
104730fdc8d8SChris Lattner             }
104830fdc8d8SChris Lattner             else
104930fdc8d8SChris Lattner             {
105030fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString());
105130fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
105230fdc8d8SChris Lattner             }
105330fdc8d8SChris Lattner         }
105430fdc8d8SChris Lattner         else
105530fdc8d8SChris Lattner         {
105630fdc8d8SChris Lattner             result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
105730fdc8d8SChris Lattner                                         m_cmd_name.c_str(),
105830fdc8d8SChris Lattner                                         m_cmd_syntax.c_str());
105930fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
106030fdc8d8SChris Lattner         }
106130fdc8d8SChris Lattner         return result.Succeeded();
106230fdc8d8SChris Lattner     }
106330fdc8d8SChris Lattner };
106430fdc8d8SChris Lattner 
106530fdc8d8SChris Lattner //-------------------------------------------------------------------------
10664b9bea87SJim Ingham // CommandObjectProcessStatus
10674b9bea87SJim Ingham //-------------------------------------------------------------------------
10684b9bea87SJim Ingham class CommandObjectProcessStatus : public CommandObject
10694b9bea87SJim Ingham {
10704b9bea87SJim Ingham public:
1071a7015092SGreg Clayton     CommandObjectProcessStatus (CommandInterpreter &interpreter) :
1072a7015092SGreg Clayton     CommandObject (interpreter,
1073a7015092SGreg Clayton                    "process status",
1074e3d26315SCaroline Tice                    "Show the current status and location of executing process.",
1075e3d26315SCaroline Tice                    "process status",
10764b9bea87SJim Ingham                    0)
10774b9bea87SJim Ingham     {
10784b9bea87SJim Ingham     }
10794b9bea87SJim Ingham 
10804b9bea87SJim Ingham     ~CommandObjectProcessStatus()
10814b9bea87SJim Ingham     {
10824b9bea87SJim Ingham     }
10834b9bea87SJim Ingham 
10844b9bea87SJim Ingham 
10854b9bea87SJim Ingham     bool
10864b9bea87SJim Ingham     Execute
10874b9bea87SJim Ingham     (
10884b9bea87SJim Ingham         Args& command,
10894b9bea87SJim Ingham         CommandReturnObject &result
10904b9bea87SJim Ingham     )
10914b9bea87SJim Ingham     {
10924b9bea87SJim Ingham         StreamString &output_stream = result.GetOutputStream();
10934b9bea87SJim Ingham         result.SetStatus (eReturnStatusSuccessFinishNoResult);
1094a7015092SGreg Clayton         ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
10954b9bea87SJim Ingham         if (exe_ctx.process)
10964b9bea87SJim Ingham         {
10974b9bea87SJim Ingham             const StateType state = exe_ctx.process->GetState();
10984b9bea87SJim Ingham             if (StateIsStoppedState(state))
10994b9bea87SJim Ingham             {
11004b9bea87SJim Ingham                 if (state == eStateExited)
11014b9bea87SJim Ingham                 {
11024b9bea87SJim Ingham                     int exit_status = exe_ctx.process->GetExitStatus();
11034b9bea87SJim Ingham                     const char *exit_description = exe_ctx.process->GetExitDescription();
11044b9bea87SJim Ingham                     output_stream.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n",
11054b9bea87SJim Ingham                                           exe_ctx.process->GetID(),
11064b9bea87SJim Ingham                                           exit_status,
11074b9bea87SJim Ingham                                           exit_status,
11084b9bea87SJim Ingham                                           exit_description ? exit_description : "");
11094b9bea87SJim Ingham                 }
11104b9bea87SJim Ingham                 else
11114b9bea87SJim Ingham                 {
11124b9bea87SJim Ingham                     output_stream.Printf ("Process %d %s\n", exe_ctx.process->GetID(), StateAsCString (state));
11134b9bea87SJim Ingham                     if (exe_ctx.thread == NULL)
11144b9bea87SJim Ingham                         exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
11154b9bea87SJim Ingham                     if (exe_ctx.thread != NULL)
11164b9bea87SJim Ingham                     {
1117a7015092SGreg Clayton                         DisplayThreadsInfo (m_interpreter, &exe_ctx, result, true, true);
11184b9bea87SJim Ingham                     }
11194b9bea87SJim Ingham                     else
11204b9bea87SJim Ingham                     {
11214b9bea87SJim Ingham                         result.AppendError ("No valid thread found in current process.");
11224b9bea87SJim Ingham                         result.SetStatus (eReturnStatusFailed);
11234b9bea87SJim Ingham                     }
11244b9bea87SJim Ingham                 }
11254b9bea87SJim Ingham             }
11264b9bea87SJim Ingham             else
11274b9bea87SJim Ingham             {
11284b9bea87SJim Ingham                 output_stream.Printf ("Process %d is running.\n",
11294b9bea87SJim Ingham                                           exe_ctx.process->GetID());
11304b9bea87SJim Ingham             }
11314b9bea87SJim Ingham         }
11324b9bea87SJim Ingham         else
11334b9bea87SJim Ingham         {
11344b9bea87SJim Ingham             result.AppendError ("No current location or status available.");
11354b9bea87SJim Ingham             result.SetStatus (eReturnStatusFailed);
11364b9bea87SJim Ingham         }
11374b9bea87SJim Ingham         return result.Succeeded();
11384b9bea87SJim Ingham     }
11394b9bea87SJim Ingham };
11404b9bea87SJim Ingham 
11414b9bea87SJim Ingham //-------------------------------------------------------------------------
114235731357SCaroline Tice // CommandObjectProcessHandle
114335731357SCaroline Tice //-------------------------------------------------------------------------
114435731357SCaroline Tice 
114535731357SCaroline Tice class CommandObjectProcessHandle : public CommandObject
114635731357SCaroline Tice {
114735731357SCaroline Tice public:
114835731357SCaroline Tice 
114935731357SCaroline Tice     class CommandOptions : public Options
115035731357SCaroline Tice     {
115135731357SCaroline Tice     public:
115235731357SCaroline Tice 
115335731357SCaroline Tice         CommandOptions () :
115435731357SCaroline Tice             Options ()
115535731357SCaroline Tice         {
115635731357SCaroline Tice             ResetOptionValues ();
115735731357SCaroline Tice         }
115835731357SCaroline Tice 
115935731357SCaroline Tice         ~CommandOptions ()
116035731357SCaroline Tice         {
116135731357SCaroline Tice         }
116235731357SCaroline Tice 
116335731357SCaroline Tice         Error
116435731357SCaroline Tice         SetOptionValue (int option_idx, const char *option_arg)
116535731357SCaroline Tice         {
116635731357SCaroline Tice             Error error;
116735731357SCaroline Tice             char short_option = (char) m_getopt_table[option_idx].val;
116835731357SCaroline Tice 
116935731357SCaroline Tice             switch (short_option)
117035731357SCaroline Tice             {
117135731357SCaroline Tice                 case 's':
117235731357SCaroline Tice                     stop = option_arg;
117335731357SCaroline Tice                     break;
117435731357SCaroline Tice                 case 'n':
117535731357SCaroline Tice                     notify = option_arg;
117635731357SCaroline Tice                     break;
117735731357SCaroline Tice                 case 'p':
117835731357SCaroline Tice                     pass = option_arg;
117935731357SCaroline Tice                     break;
118035731357SCaroline Tice                 default:
118135731357SCaroline Tice                     error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
118235731357SCaroline Tice                     break;
118335731357SCaroline Tice             }
118435731357SCaroline Tice             return error;
118535731357SCaroline Tice         }
118635731357SCaroline Tice 
118735731357SCaroline Tice         void
118835731357SCaroline Tice         ResetOptionValues ()
118935731357SCaroline Tice         {
119035731357SCaroline Tice             Options::ResetOptionValues();
119135731357SCaroline Tice             stop.clear();
119235731357SCaroline Tice             notify.clear();
119335731357SCaroline Tice             pass.clear();
119435731357SCaroline Tice         }
119535731357SCaroline Tice 
119635731357SCaroline Tice         const lldb::OptionDefinition*
119735731357SCaroline Tice         GetDefinitions ()
119835731357SCaroline Tice         {
119935731357SCaroline Tice             return g_option_table;
120035731357SCaroline Tice         }
120135731357SCaroline Tice 
120235731357SCaroline Tice         // Options table: Required for subclasses of Options.
120335731357SCaroline Tice 
120435731357SCaroline Tice         static lldb::OptionDefinition g_option_table[];
120535731357SCaroline Tice 
120635731357SCaroline Tice         // Instance variables to hold the values for command options.
120735731357SCaroline Tice 
120835731357SCaroline Tice         std::string stop;
120935731357SCaroline Tice         std::string notify;
121035731357SCaroline Tice         std::string pass;
121135731357SCaroline Tice     };
121235731357SCaroline Tice 
121335731357SCaroline Tice 
121435731357SCaroline Tice     CommandObjectProcessHandle (CommandInterpreter &interpreter) :
121535731357SCaroline Tice         CommandObject (interpreter,
121635731357SCaroline Tice                        "process handle",
121710ad7993SCaroline Tice                        "Show or update what the process and debugger should do with various signals received from the OS.",
121835731357SCaroline Tice                        NULL)
121935731357SCaroline Tice     {
122010ad7993SCaroline Tice         SetHelpLong ("If no signals are specified, update them all.  If no update option is specified, list the current values.\n");
122135731357SCaroline Tice         CommandArgumentEntry arg;
122235731357SCaroline Tice         CommandArgumentData signal_name_arg;
122335731357SCaroline Tice 
122435731357SCaroline Tice         signal_name_arg.arg_type = eArgTypeSignalName;
122510ad7993SCaroline Tice         signal_name_arg.arg_repetition = eArgRepeatStar;
122635731357SCaroline Tice 
122735731357SCaroline Tice         arg.push_back (signal_name_arg);
122835731357SCaroline Tice 
122935731357SCaroline Tice         m_arguments.push_back (arg);
123035731357SCaroline Tice     }
123135731357SCaroline Tice 
123235731357SCaroline Tice     ~CommandObjectProcessHandle ()
123335731357SCaroline Tice     {
123435731357SCaroline Tice     }
123535731357SCaroline Tice 
123635731357SCaroline Tice     Options *
123735731357SCaroline Tice     GetOptions ()
123835731357SCaroline Tice     {
123935731357SCaroline Tice         return &m_options;
124035731357SCaroline Tice     }
124135731357SCaroline Tice 
124235731357SCaroline Tice     bool
124310ad7993SCaroline Tice     VerifyCommandOptionValue (const std::string &option, int &real_value)
124435731357SCaroline Tice     {
124535731357SCaroline Tice         bool okay = true;
124635731357SCaroline Tice 
124710ad7993SCaroline Tice         bool success = false;
124810ad7993SCaroline Tice         bool tmp_value = Args::StringToBoolean (option.c_str(), false, &success);
124910ad7993SCaroline Tice 
125010ad7993SCaroline Tice         if (success && tmp_value)
125110ad7993SCaroline Tice             real_value = 1;
125210ad7993SCaroline Tice         else if (success && !tmp_value)
125310ad7993SCaroline Tice             real_value = 0;
125435731357SCaroline Tice         else
125535731357SCaroline Tice         {
125635731357SCaroline Tice             // If the value isn't 'true' or 'false', it had better be 0 or 1.
125710ad7993SCaroline Tice             real_value = Args::StringToUInt32 (option.c_str(), 3);
125810ad7993SCaroline Tice             if (real_value != 0 && real_value != 1)
125935731357SCaroline Tice                 okay = false;
126035731357SCaroline Tice         }
126135731357SCaroline Tice 
126235731357SCaroline Tice         return okay;
126335731357SCaroline Tice     }
126435731357SCaroline Tice 
126510ad7993SCaroline Tice     void
126610ad7993SCaroline Tice     PrintSignalHeader (Stream &str)
126710ad7993SCaroline Tice     {
126810ad7993SCaroline Tice         str.Printf ("NAME        PASS   STOP   NOTIFY\n");
126910ad7993SCaroline Tice         str.Printf ("==========  =====  =====  ======\n");
127010ad7993SCaroline Tice     }
127110ad7993SCaroline Tice 
127210ad7993SCaroline Tice     void
127310ad7993SCaroline Tice     PrintSignal (Stream &str, int32_t signo, const char *sig_name, UnixSignals &signals)
127410ad7993SCaroline Tice     {
127510ad7993SCaroline Tice         bool stop;
127610ad7993SCaroline Tice         bool suppress;
127710ad7993SCaroline Tice         bool notify;
127810ad7993SCaroline Tice 
127910ad7993SCaroline Tice         str.Printf ("%-10s  ", sig_name);
128010ad7993SCaroline Tice         if (signals.GetSignalInfo (signo, suppress, stop, notify))
128110ad7993SCaroline Tice         {
128210ad7993SCaroline Tice             bool pass = !suppress;
128310ad7993SCaroline Tice             str.Printf ("%s  %s  %s",
128410ad7993SCaroline Tice                         (pass ? "true " : "false"),
128510ad7993SCaroline Tice                         (stop ? "true " : "false"),
128610ad7993SCaroline Tice                         (notify ? "true " : "false"));
128710ad7993SCaroline Tice         }
128810ad7993SCaroline Tice         str.Printf ("\n");
128910ad7993SCaroline Tice     }
129010ad7993SCaroline Tice 
129110ad7993SCaroline Tice     void
129210ad7993SCaroline Tice     PrintSignalInformation (Stream &str, Args &signal_args, int num_valid_signals, UnixSignals &signals)
129310ad7993SCaroline Tice     {
129410ad7993SCaroline Tice         PrintSignalHeader (str);
129510ad7993SCaroline Tice 
129610ad7993SCaroline Tice         if (num_valid_signals > 0)
129710ad7993SCaroline Tice         {
129810ad7993SCaroline Tice             size_t num_args = signal_args.GetArgumentCount();
129910ad7993SCaroline Tice             for (size_t i = 0; i < num_args; ++i)
130010ad7993SCaroline Tice             {
130110ad7993SCaroline Tice                 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
130210ad7993SCaroline Tice                 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
130310ad7993SCaroline Tice                     PrintSignal (str, signo, signal_args.GetArgumentAtIndex (i), signals);
130410ad7993SCaroline Tice             }
130510ad7993SCaroline Tice         }
130610ad7993SCaroline Tice         else // Print info for ALL signals
130710ad7993SCaroline Tice         {
130810ad7993SCaroline Tice             int32_t signo = signals.GetFirstSignalNumber();
130910ad7993SCaroline Tice             while (signo != LLDB_INVALID_SIGNAL_NUMBER)
131010ad7993SCaroline Tice             {
131110ad7993SCaroline Tice                 PrintSignal (str, signo, signals.GetSignalAsCString (signo), signals);
131210ad7993SCaroline Tice                 signo = signals.GetNextSignalNumber (signo);
131310ad7993SCaroline Tice             }
131410ad7993SCaroline Tice         }
131510ad7993SCaroline Tice     }
131610ad7993SCaroline Tice 
131735731357SCaroline Tice     bool
131835731357SCaroline Tice     Execute (Args &signal_args, CommandReturnObject &result)
131935731357SCaroline Tice     {
132035731357SCaroline Tice         TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
132135731357SCaroline Tice 
132235731357SCaroline Tice         if (!target_sp)
132335731357SCaroline Tice         {
132435731357SCaroline Tice             result.AppendError ("No current target;"
132535731357SCaroline Tice                                 " cannot handle signals until you have a valid target and process.\n");
132635731357SCaroline Tice             result.SetStatus (eReturnStatusFailed);
132735731357SCaroline Tice             return false;
132835731357SCaroline Tice         }
132935731357SCaroline Tice 
133035731357SCaroline Tice         ProcessSP process_sp = target_sp->GetProcessSP();
133135731357SCaroline Tice 
133235731357SCaroline Tice         if (!process_sp)
133335731357SCaroline Tice         {
133435731357SCaroline Tice             result.AppendError ("No current process; cannot handle signals until you have a valid process.\n");
133535731357SCaroline Tice             result.SetStatus (eReturnStatusFailed);
133635731357SCaroline Tice             return false;
133735731357SCaroline Tice         }
133835731357SCaroline Tice 
133935731357SCaroline Tice         int stop_action = -1;   // -1 means leave the current setting alone
134035731357SCaroline Tice         int pass_action = -1;   // -1 means leave the current setting alone
134135731357SCaroline Tice         int notify_action = -1; // -1 means leave the current setting alone
134235731357SCaroline Tice 
134335731357SCaroline Tice         if (! m_options.stop.empty()
134410ad7993SCaroline Tice             && ! VerifyCommandOptionValue (m_options.stop, stop_action))
134535731357SCaroline Tice         {
134635731357SCaroline Tice             result.AppendError ("Invalid argument for command option --stop; must be true or false.\n");
134735731357SCaroline Tice             result.SetStatus (eReturnStatusFailed);
134835731357SCaroline Tice             return false;
134935731357SCaroline Tice         }
135035731357SCaroline Tice 
135135731357SCaroline Tice         if (! m_options.notify.empty()
135210ad7993SCaroline Tice             && ! VerifyCommandOptionValue (m_options.notify, notify_action))
135335731357SCaroline Tice         {
135435731357SCaroline Tice             result.AppendError ("Invalid argument for command option --notify; must be true or false.\n");
135535731357SCaroline Tice             result.SetStatus (eReturnStatusFailed);
135635731357SCaroline Tice             return false;
135735731357SCaroline Tice         }
135835731357SCaroline Tice 
135935731357SCaroline Tice         if (! m_options.pass.empty()
136010ad7993SCaroline Tice             && ! VerifyCommandOptionValue (m_options.pass, pass_action))
136135731357SCaroline Tice         {
136235731357SCaroline Tice             result.AppendError ("Invalid argument for command option --pass; must be true or false.\n");
136335731357SCaroline Tice             result.SetStatus (eReturnStatusFailed);
136435731357SCaroline Tice             return false;
136535731357SCaroline Tice         }
136635731357SCaroline Tice 
136735731357SCaroline Tice         size_t num_args = signal_args.GetArgumentCount();
136835731357SCaroline Tice         UnixSignals &signals = process_sp->GetUnixSignals();
136935731357SCaroline Tice         int num_signals_set = 0;
137035731357SCaroline Tice 
137110ad7993SCaroline Tice         if (num_args > 0)
137210ad7993SCaroline Tice         {
137335731357SCaroline Tice             for (size_t i = 0; i < num_args; ++i)
137435731357SCaroline Tice             {
137535731357SCaroline Tice                 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
137635731357SCaroline Tice                 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
137735731357SCaroline Tice                 {
137810ad7993SCaroline Tice                     // Casting the actions as bools here should be okay, because VerifyCommandOptionValue guarantees
137935731357SCaroline Tice                     // the value is either 0 or 1.
138035731357SCaroline Tice                     if (stop_action != -1)
138135731357SCaroline Tice                         signals.SetShouldStop (signo, (bool) stop_action);
138235731357SCaroline Tice                     if (pass_action != -1)
138335731357SCaroline Tice                     {
138410ad7993SCaroline Tice                         bool suppress = ! ((bool) pass_action);
138510ad7993SCaroline Tice                         signals.SetShouldSuppress (signo, suppress);
138635731357SCaroline Tice                     }
138735731357SCaroline Tice                     if (notify_action != -1)
138835731357SCaroline Tice                         signals.SetShouldNotify (signo, (bool) notify_action);
138935731357SCaroline Tice                     ++num_signals_set;
139035731357SCaroline Tice                 }
139135731357SCaroline Tice                 else
139235731357SCaroline Tice                 {
139335731357SCaroline Tice                     result.AppendErrorWithFormat ("Invalid signal name '%s'\n", signal_args.GetArgumentAtIndex (i));
139435731357SCaroline Tice                 }
139535731357SCaroline Tice             }
139610ad7993SCaroline Tice         }
139710ad7993SCaroline Tice         else
139810ad7993SCaroline Tice         {
139910ad7993SCaroline Tice             // No signal specified, if any command options were specified, update ALL signals.
140010ad7993SCaroline Tice             if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1))
140110ad7993SCaroline Tice             {
140210ad7993SCaroline Tice                 if (m_interpreter.Confirm ("Do you really want to update all the signals?", false))
140310ad7993SCaroline Tice                 {
140410ad7993SCaroline Tice                     int32_t signo = signals.GetFirstSignalNumber();
140510ad7993SCaroline Tice                     while (signo != LLDB_INVALID_SIGNAL_NUMBER)
140610ad7993SCaroline Tice                     {
140710ad7993SCaroline Tice                         if (notify_action != -1)
140810ad7993SCaroline Tice                             signals.SetShouldNotify (signo, (bool) notify_action);
140910ad7993SCaroline Tice                         if (stop_action != -1)
141010ad7993SCaroline Tice                             signals.SetShouldStop (signo, (bool) stop_action);
141110ad7993SCaroline Tice                         if (pass_action != -1)
141210ad7993SCaroline Tice                         {
141310ad7993SCaroline Tice                             bool suppress = ! ((bool) pass_action);
141410ad7993SCaroline Tice                             signals.SetShouldSuppress (signo, suppress);
141510ad7993SCaroline Tice                         }
141610ad7993SCaroline Tice                         signo = signals.GetNextSignalNumber (signo);
141710ad7993SCaroline Tice                     }
141810ad7993SCaroline Tice                 }
141910ad7993SCaroline Tice             }
142010ad7993SCaroline Tice         }
142110ad7993SCaroline Tice 
142210ad7993SCaroline Tice         PrintSignalInformation (result.GetOutputStream(), signal_args, num_signals_set, signals);
142335731357SCaroline Tice 
142435731357SCaroline Tice         if (num_signals_set > 0)
142535731357SCaroline Tice             result.SetStatus (eReturnStatusSuccessFinishNoResult);
142635731357SCaroline Tice         else
142735731357SCaroline Tice             result.SetStatus (eReturnStatusFailed);
142835731357SCaroline Tice 
142935731357SCaroline Tice         return result.Succeeded();
143035731357SCaroline Tice     }
143135731357SCaroline Tice 
143235731357SCaroline Tice protected:
143335731357SCaroline Tice 
143435731357SCaroline Tice     CommandOptions m_options;
143535731357SCaroline Tice };
143635731357SCaroline Tice 
143735731357SCaroline Tice lldb::OptionDefinition
143835731357SCaroline Tice CommandObjectProcessHandle::CommandOptions::g_option_table[] =
143935731357SCaroline Tice {
144035731357SCaroline Tice { 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." },
144135731357SCaroline Tice { 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." },
144235731357SCaroline Tice { LLDB_OPT_SET_1, false, "pass",  'p', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." },
144335731357SCaroline Tice { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
144435731357SCaroline Tice };
144535731357SCaroline Tice 
144635731357SCaroline Tice //-------------------------------------------------------------------------
144730fdc8d8SChris Lattner // CommandObjectMultiwordProcess
144830fdc8d8SChris Lattner //-------------------------------------------------------------------------
144930fdc8d8SChris Lattner 
14506611103cSGreg Clayton CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter &interpreter) :
1451a7015092SGreg Clayton     CommandObjectMultiword (interpreter,
1452a7015092SGreg Clayton                             "process",
145330fdc8d8SChris Lattner                             "A set of commands for operating on a process.",
145430fdc8d8SChris Lattner                             "process <subcommand> [<subcommand-options>]")
145530fdc8d8SChris Lattner {
1456a7015092SGreg Clayton     LoadSubCommand ("attach",      CommandObjectSP (new CommandObjectProcessAttach (interpreter)));
1457a7015092SGreg Clayton     LoadSubCommand ("launch",      CommandObjectSP (new CommandObjectProcessLaunch (interpreter)));
1458a7015092SGreg Clayton     LoadSubCommand ("continue",    CommandObjectSP (new CommandObjectProcessContinue (interpreter)));
1459a7015092SGreg Clayton     LoadSubCommand ("detach",      CommandObjectSP (new CommandObjectProcessDetach (interpreter)));
1460a7015092SGreg Clayton     LoadSubCommand ("signal",      CommandObjectSP (new CommandObjectProcessSignal (interpreter)));
146135731357SCaroline Tice     LoadSubCommand ("handle",      CommandObjectSP (new CommandObjectProcessHandle (interpreter)));
1462a7015092SGreg Clayton     LoadSubCommand ("status",      CommandObjectSP (new CommandObjectProcessStatus (interpreter)));
1463a7015092SGreg Clayton     LoadSubCommand ("interrupt",   CommandObjectSP (new CommandObjectProcessInterrupt (interpreter)));
1464a7015092SGreg Clayton     LoadSubCommand ("kill",        CommandObjectSP (new CommandObjectProcessKill (interpreter)));
146530fdc8d8SChris Lattner }
146630fdc8d8SChris Lattner 
146730fdc8d8SChris Lattner CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess ()
146830fdc8d8SChris Lattner {
146930fdc8d8SChris Lattner }
147030fdc8d8SChris Lattner 
1471