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;
65913c4fa1SGreg Clayton                 case 't':
66913c4fa1SGreg Clayton                     if (option_arg && option_arg[0])
67913c4fa1SGreg Clayton                         tty_name.assign (option_arg);
68913c4fa1SGreg Clayton                     in_new_tty = true;
69913c4fa1SGreg Clayton                     break;
7030fdc8d8SChris Lattner                 default:
7130fdc8d8SChris Lattner                     error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
7230fdc8d8SChris Lattner                     break;
7330fdc8d8SChris Lattner 
7430fdc8d8SChris Lattner             }
7530fdc8d8SChris Lattner             return error;
7630fdc8d8SChris Lattner         }
7730fdc8d8SChris Lattner 
7830fdc8d8SChris Lattner         void
7930fdc8d8SChris Lattner         ResetOptionValues ()
8030fdc8d8SChris Lattner         {
8130fdc8d8SChris Lattner             Options::ResetOptionValues();
8230fdc8d8SChris Lattner             stop_at_entry = false;
8319388cfcSGreg Clayton             in_new_tty = false;
84913c4fa1SGreg Clayton             tty_name.clear();
8530fdc8d8SChris Lattner             stdin_path.clear();
8630fdc8d8SChris Lattner             stdout_path.clear();
8730fdc8d8SChris Lattner             stderr_path.clear();
8830fdc8d8SChris Lattner             plugin_name.clear();
8930fdc8d8SChris Lattner         }
9030fdc8d8SChris Lattner 
9130fdc8d8SChris Lattner         const lldb::OptionDefinition*
9230fdc8d8SChris Lattner         GetDefinitions ()
9330fdc8d8SChris Lattner         {
9430fdc8d8SChris Lattner             return g_option_table;
9530fdc8d8SChris Lattner         }
9630fdc8d8SChris Lattner 
9730fdc8d8SChris Lattner         // Options table: Required for subclasses of Options.
9830fdc8d8SChris Lattner 
9930fdc8d8SChris Lattner         static lldb::OptionDefinition g_option_table[];
10030fdc8d8SChris Lattner 
10130fdc8d8SChris Lattner         // Instance variables to hold the values for command options.
10230fdc8d8SChris Lattner 
10330fdc8d8SChris Lattner         bool stop_at_entry;
10419388cfcSGreg Clayton         bool in_new_tty;
105913c4fa1SGreg Clayton         std::string tty_name;
10630fdc8d8SChris Lattner         std::string stderr_path;
10730fdc8d8SChris Lattner         std::string stdin_path;
10830fdc8d8SChris Lattner         std::string stdout_path;
10930fdc8d8SChris Lattner         std::string plugin_name;
11030fdc8d8SChris Lattner 
11130fdc8d8SChris Lattner     };
11230fdc8d8SChris Lattner 
113a7015092SGreg Clayton     CommandObjectProcessLaunch (CommandInterpreter &interpreter) :
114a7015092SGreg Clayton         CommandObject (interpreter,
115a7015092SGreg Clayton                        "process launch",
116e3d26315SCaroline Tice                        "Launch the executable in the debugger.",
117405fe67fSCaroline Tice                        NULL)
11830fdc8d8SChris Lattner     {
119405fe67fSCaroline Tice         CommandArgumentEntry arg;
120405fe67fSCaroline Tice         CommandArgumentData run_args_arg;
121405fe67fSCaroline Tice 
122405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
123405fe67fSCaroline Tice         run_args_arg.arg_type = eArgTypeRunArgs;
124405fe67fSCaroline Tice         run_args_arg.arg_repetition = eArgRepeatOptional;
125405fe67fSCaroline Tice 
126405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
127405fe67fSCaroline Tice         arg.push_back (run_args_arg);
128405fe67fSCaroline Tice 
129405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
130405fe67fSCaroline Tice         m_arguments.push_back (arg);
13130fdc8d8SChris Lattner     }
13230fdc8d8SChris Lattner 
13330fdc8d8SChris Lattner 
13430fdc8d8SChris Lattner     ~CommandObjectProcessLaunch ()
13530fdc8d8SChris Lattner     {
13630fdc8d8SChris Lattner     }
13730fdc8d8SChris Lattner 
13830fdc8d8SChris Lattner     Options *
13930fdc8d8SChris Lattner     GetOptions ()
14030fdc8d8SChris Lattner     {
14130fdc8d8SChris Lattner         return &m_options;
14230fdc8d8SChris Lattner     }
14330fdc8d8SChris Lattner 
14430fdc8d8SChris Lattner     bool
14505faeb71SGreg Clayton     Execute (Args& launch_args, CommandReturnObject &result)
14630fdc8d8SChris Lattner     {
147a7015092SGreg Clayton         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
14830fdc8d8SChris Lattner 
14930fdc8d8SChris Lattner         if (target == NULL)
15030fdc8d8SChris Lattner         {
15130fdc8d8SChris Lattner             result.AppendError ("invalid target, set executable file using 'file' command");
15230fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
15330fdc8d8SChris Lattner             return false;
15430fdc8d8SChris Lattner         }
15530fdc8d8SChris Lattner 
15630fdc8d8SChris Lattner         // If our listener is NULL, users aren't allows to launch
15730fdc8d8SChris Lattner         char filename[PATH_MAX];
15819388cfcSGreg Clayton         const Module *exe_module = target->GetExecutableModule().get();
15930fdc8d8SChris Lattner         exe_module->GetFileSpec().GetPath(filename, sizeof(filename));
16030fdc8d8SChris Lattner 
161a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
162a7015092SGreg Clayton         if (process && process->IsAlive())
16330fdc8d8SChris Lattner         {
16430fdc8d8SChris Lattner             result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before running again.\n",
16530fdc8d8SChris Lattner                                           process->GetID());
16630fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
16730fdc8d8SChris Lattner             return false;
16830fdc8d8SChris Lattner         }
16930fdc8d8SChris Lattner 
17030fdc8d8SChris Lattner         const char *plugin_name;
17130fdc8d8SChris Lattner         if (!m_options.plugin_name.empty())
17230fdc8d8SChris Lattner             plugin_name = m_options.plugin_name.c_str();
17330fdc8d8SChris Lattner         else
17430fdc8d8SChris Lattner             plugin_name = NULL;
17530fdc8d8SChris Lattner 
176a7015092SGreg Clayton         process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
17730fdc8d8SChris Lattner 
178a7015092SGreg Clayton         if (process == NULL)
1793df9a8dfSCaroline Tice         {
18043a8c39bSCaroline Tice             result.AppendErrorWithFormat ("Failed to find a process plugin for executable.\n");
181a7015092SGreg Clayton             result.SetStatus (eReturnStatusFailed);
182a7015092SGreg Clayton             return false;
1833df9a8dfSCaroline Tice         }
1843df9a8dfSCaroline Tice 
185a7015092SGreg Clayton         // If no launch args were given on the command line, then use any that
186a7015092SGreg Clayton         // might have been set using the "run-args" set variable.
18730fdc8d8SChris Lattner         if (launch_args.GetArgumentCount() == 0)
18830fdc8d8SChris Lattner         {
189a7015092SGreg Clayton             if (process->GetRunArguments().GetArgumentCount() > 0)
190a7015092SGreg Clayton                 launch_args = process->GetRunArguments();
19130fdc8d8SChris Lattner         }
19230fdc8d8SChris Lattner 
19319388cfcSGreg Clayton         if (m_options.in_new_tty)
19419388cfcSGreg Clayton         {
19519388cfcSGreg Clayton             char exec_file_path[PATH_MAX];
19619388cfcSGreg Clayton             if (exe_module->GetFileSpec().GetPath(exec_file_path, sizeof(exec_file_path)))
19719388cfcSGreg Clayton             {
19819388cfcSGreg Clayton                 launch_args.InsertArgumentAtIndex(0, exec_file_path);
19919388cfcSGreg Clayton             }
20019388cfcSGreg Clayton             else
20119388cfcSGreg Clayton             {
20219388cfcSGreg Clayton                 result.AppendError("invalid executable");
20319388cfcSGreg Clayton                 result.SetStatus (eReturnStatusFailed);
20419388cfcSGreg Clayton                 return false;
20519388cfcSGreg Clayton             }
20619388cfcSGreg Clayton         }
20719388cfcSGreg Clayton 
208a7015092SGreg Clayton         Args environment;
20930fdc8d8SChris Lattner 
210a7015092SGreg Clayton         process->GetEnvironmentAsArgs (environment);
211a7015092SGreg Clayton 
212a7015092SGreg Clayton         uint32_t launch_flags = eLaunchFlagNone;
213a7015092SGreg Clayton 
214a7015092SGreg Clayton         if (process->GetDisableASLR())
215a7015092SGreg Clayton             launch_flags |= eLaunchFlagDisableASLR;
216a7015092SGreg Clayton 
21719388cfcSGreg Clayton         const char **inferior_argv = launch_args.GetArgumentCount() ? launch_args.GetConstArgumentVector() : NULL;
21819388cfcSGreg Clayton         const char **inferior_envp = environment.GetArgumentCount() ? environment.GetConstArgumentVector() : NULL;
21930fdc8d8SChris Lattner 
22019388cfcSGreg Clayton         Error error;
22119388cfcSGreg Clayton 
22219388cfcSGreg Clayton         if (m_options.in_new_tty)
22319388cfcSGreg Clayton         {
22419388cfcSGreg Clayton 
225913c4fa1SGreg Clayton             lldb::pid_t pid = Host::LaunchInNewTerminal (m_options.tty_name.c_str(),
226913c4fa1SGreg Clayton                                                          inferior_argv,
22719388cfcSGreg Clayton                                                          inferior_envp,
22819388cfcSGreg Clayton                                                          &exe_module->GetArchitecture(),
22919388cfcSGreg Clayton                                                          true,
23019388cfcSGreg Clayton                                                          process->GetDisableASLR());
23119388cfcSGreg Clayton 
2323fcbed6bSGreg Clayton             if (pid != LLDB_INVALID_PROCESS_ID)
2333fcbed6bSGreg Clayton                 error = process->Attach (pid);
23419388cfcSGreg Clayton         }
23519388cfcSGreg Clayton         else
23619388cfcSGreg Clayton         {
23730fdc8d8SChris Lattner             const char * stdin_path = NULL;
23830fdc8d8SChris Lattner             const char * stdout_path = NULL;
23930fdc8d8SChris Lattner             const char * stderr_path = NULL;
24030fdc8d8SChris Lattner 
241a7015092SGreg Clayton             // Were any standard input/output/error paths given on the command line?
242a7015092SGreg Clayton             if (m_options.stdin_path.empty() &&
24330fdc8d8SChris Lattner                 m_options.stdout_path.empty() &&
244a7015092SGreg Clayton                 m_options.stderr_path.empty())
24530fdc8d8SChris Lattner             {
246a7015092SGreg Clayton                 // No standard file handles were given on the command line, check
247a7015092SGreg Clayton                 // with the process object in case they were give using "set settings"
248a7015092SGreg Clayton                 stdin_path = process->GetStandardInputPath();
249a7015092SGreg Clayton                 stdout_path = process->GetStandardOutputPath();
250a7015092SGreg Clayton                 stderr_path = process->GetStandardErrorPath();
251a7015092SGreg Clayton             }
252a7015092SGreg Clayton             else
253a7015092SGreg Clayton             {
254a7015092SGreg Clayton                 stdin_path = m_options.stdin_path.empty()  ? NULL : m_options.stdin_path.c_str();
255a7015092SGreg Clayton                 stdout_path = m_options.stdout_path.empty() ? NULL : m_options.stdout_path.c_str();
256a7015092SGreg Clayton                 stderr_path = m_options.stderr_path.empty() ? NULL : m_options.stderr_path.c_str();
25730fdc8d8SChris Lattner             }
25830fdc8d8SChris Lattner 
259a7015092SGreg Clayton             if (stdin_path == NULL)
260a7015092SGreg Clayton                 stdin_path = "/dev/null";
261a7015092SGreg Clayton             if (stdout_path == NULL)
262a7015092SGreg Clayton                 stdout_path = "/dev/null";
263a7015092SGreg Clayton             if (stderr_path == NULL)
264a7015092SGreg Clayton                 stderr_path = "/dev/null";
265a7015092SGreg Clayton 
26619388cfcSGreg Clayton             error = process->Launch (inferior_argv,
26719388cfcSGreg Clayton                                      inferior_envp,
268f681b94fSGreg Clayton                                      launch_flags,
26930fdc8d8SChris Lattner                                      stdin_path,
27030fdc8d8SChris Lattner                                      stdout_path,
27119388cfcSGreg Clayton                                      stderr_path);
27219388cfcSGreg Clayton         }
27330fdc8d8SChris Lattner 
27430fdc8d8SChris Lattner         if (error.Success())
27530fdc8d8SChris Lattner         {
27619388cfcSGreg Clayton             const char *archname = exe_module->GetArchitecture().AsCString();
27719388cfcSGreg Clayton 
27819388cfcSGreg Clayton             result.AppendMessageWithFormat ("Process %i launched: '%s' (%s)\n", process->GetID(), filename, archname);
27905faeb71SGreg Clayton             result.SetDidChangeProcessState (true);
28030fdc8d8SChris Lattner             if (m_options.stop_at_entry == false)
28130fdc8d8SChris Lattner             {
28205faeb71SGreg Clayton                 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
28330fdc8d8SChris Lattner                 StateType state = process->WaitForProcessToStop (NULL);
28430fdc8d8SChris Lattner 
28530fdc8d8SChris Lattner                 if (state == eStateStopped)
28630fdc8d8SChris Lattner                 {
28705faeb71SGreg Clayton                     error = process->Resume();
28805faeb71SGreg Clayton                     if (error.Success())
28905faeb71SGreg Clayton                     {
29005faeb71SGreg Clayton                         bool synchronous_execution = m_interpreter.GetSynchronous ();
29130fdc8d8SChris Lattner                         if (synchronous_execution)
29230fdc8d8SChris Lattner                         {
29305faeb71SGreg Clayton                             state = process->WaitForProcessToStop (NULL);
29430fdc8d8SChris Lattner                             result.SetDidChangeProcessState (true);
29505faeb71SGreg Clayton                             result.SetStatus (eReturnStatusSuccessFinishResult);
29605faeb71SGreg Clayton                         }
29705faeb71SGreg Clayton                         else
29805faeb71SGreg Clayton                         {
29905faeb71SGreg Clayton                             result.SetStatus (eReturnStatusSuccessContinuingNoResult);
30005faeb71SGreg Clayton                         }
30105faeb71SGreg Clayton                     }
30230fdc8d8SChris Lattner                 }
30330fdc8d8SChris Lattner             }
30430fdc8d8SChris Lattner         }
30530fdc8d8SChris Lattner 
30630fdc8d8SChris Lattner         return result.Succeeded();
30730fdc8d8SChris Lattner     }
30830fdc8d8SChris Lattner 
309ebc09c36SJim Ingham     virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
310ebc09c36SJim Ingham     {
311ebc09c36SJim Ingham         // No repeat for "process launch"...
312ebc09c36SJim Ingham         return "";
313ebc09c36SJim Ingham     }
314ebc09c36SJim Ingham 
31530fdc8d8SChris Lattner protected:
31630fdc8d8SChris Lattner 
31730fdc8d8SChris Lattner     CommandOptions m_options;
31830fdc8d8SChris Lattner };
31930fdc8d8SChris Lattner 
32030fdc8d8SChris Lattner 
32119388cfcSGreg Clayton #define SET1 LLDB_OPT_SET_1
32219388cfcSGreg Clayton #define SET2 LLDB_OPT_SET_2
32319388cfcSGreg Clayton 
32430fdc8d8SChris Lattner lldb::OptionDefinition
32530fdc8d8SChris Lattner CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
32630fdc8d8SChris Lattner {
32719388cfcSGreg 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."},
32819388cfcSGreg Clayton { SET1       , false, "stdin",         'i', required_argument, NULL, 0, eArgTypePath,    "Redirect stdin for the process to <path>."},
32919388cfcSGreg Clayton { SET1       , false, "stdout",        'o', required_argument, NULL, 0, eArgTypePath,    "Redirect stdout for the process to <path>."},
33019388cfcSGreg Clayton { SET1       , false, "stderr",        'e', required_argument, NULL, 0, eArgTypePath,    "Redirect stderr for the process to <path>."},
33119388cfcSGreg Clayton { SET1 | SET2, false, "plugin",        'p', required_argument, NULL, 0, eArgTypePlugin,  "Name of the process plugin you want to use."},
332913c4fa1SGreg Clayton {        SET2, false, "tty",           't', optional_argument, NULL, 0, eArgTypePath,    "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."},
333deaab222SCaroline Tice { 0,           false, NULL,             0,  0,                 NULL, 0, eArgTypeNone,    NULL }
33430fdc8d8SChris Lattner };
33530fdc8d8SChris Lattner 
33619388cfcSGreg Clayton #undef SET1
33719388cfcSGreg Clayton #undef SET2
33830fdc8d8SChris Lattner 
33930fdc8d8SChris Lattner //-------------------------------------------------------------------------
34030fdc8d8SChris Lattner // CommandObjectProcessAttach
34130fdc8d8SChris Lattner //-------------------------------------------------------------------------
34230fdc8d8SChris Lattner 
34330fdc8d8SChris Lattner class CommandObjectProcessAttach : public CommandObject
34430fdc8d8SChris Lattner {
34530fdc8d8SChris Lattner public:
34630fdc8d8SChris Lattner 
34730fdc8d8SChris Lattner     class CommandOptions : public Options
34830fdc8d8SChris Lattner     {
34930fdc8d8SChris Lattner     public:
35030fdc8d8SChris Lattner 
35130fdc8d8SChris Lattner         CommandOptions () :
35230fdc8d8SChris Lattner             Options()
35330fdc8d8SChris Lattner         {
35430fdc8d8SChris Lattner             // Keep default values of all options in one place: ResetOptionValues ()
35530fdc8d8SChris Lattner             ResetOptionValues ();
35630fdc8d8SChris Lattner         }
35730fdc8d8SChris Lattner 
35830fdc8d8SChris Lattner         ~CommandOptions ()
35930fdc8d8SChris Lattner         {
36030fdc8d8SChris Lattner         }
36130fdc8d8SChris Lattner 
36230fdc8d8SChris Lattner         Error
36330fdc8d8SChris Lattner         SetOptionValue (int option_idx, const char *option_arg)
36430fdc8d8SChris Lattner         {
36530fdc8d8SChris Lattner             Error error;
36630fdc8d8SChris Lattner             char short_option = (char) m_getopt_table[option_idx].val;
36730fdc8d8SChris Lattner             bool success = false;
36830fdc8d8SChris Lattner             switch (short_option)
36930fdc8d8SChris Lattner             {
37030fdc8d8SChris Lattner                 case 'p':
37130fdc8d8SChris Lattner                     pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success);
37230fdc8d8SChris Lattner                     if (!success || pid == LLDB_INVALID_PROCESS_ID)
37330fdc8d8SChris Lattner                     {
37430fdc8d8SChris Lattner                         error.SetErrorStringWithFormat("Invalid process ID '%s'.\n", option_arg);
37530fdc8d8SChris Lattner                     }
37630fdc8d8SChris Lattner                     break;
37730fdc8d8SChris Lattner 
37830fdc8d8SChris Lattner                 case 'P':
37930fdc8d8SChris Lattner                     plugin_name = option_arg;
38030fdc8d8SChris Lattner                     break;
38130fdc8d8SChris Lattner 
38230fdc8d8SChris Lattner                 case 'n':
38330fdc8d8SChris Lattner                     name.assign(option_arg);
38430fdc8d8SChris Lattner                     break;
38530fdc8d8SChris Lattner 
38630fdc8d8SChris Lattner                 case 'w':
38730fdc8d8SChris Lattner                     waitfor = true;
38830fdc8d8SChris Lattner                     break;
38930fdc8d8SChris Lattner 
39030fdc8d8SChris Lattner                 default:
39130fdc8d8SChris Lattner                     error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
39230fdc8d8SChris Lattner                     break;
39330fdc8d8SChris Lattner             }
39430fdc8d8SChris Lattner             return error;
39530fdc8d8SChris Lattner         }
39630fdc8d8SChris Lattner 
39730fdc8d8SChris Lattner         void
39830fdc8d8SChris Lattner         ResetOptionValues ()
39930fdc8d8SChris Lattner         {
40030fdc8d8SChris Lattner             Options::ResetOptionValues();
40130fdc8d8SChris Lattner             pid = LLDB_INVALID_PROCESS_ID;
40230fdc8d8SChris Lattner             name.clear();
40330fdc8d8SChris Lattner             waitfor = false;
40430fdc8d8SChris Lattner         }
40530fdc8d8SChris Lattner 
40630fdc8d8SChris Lattner         const lldb::OptionDefinition*
40730fdc8d8SChris Lattner         GetDefinitions ()
40830fdc8d8SChris Lattner         {
40930fdc8d8SChris Lattner             return g_option_table;
41030fdc8d8SChris Lattner         }
41130fdc8d8SChris Lattner 
4125aee162fSJim Ingham         virtual bool
413a7015092SGreg Clayton         HandleOptionArgumentCompletion (CommandInterpreter &interpeter,
4145aee162fSJim Ingham                                         Args &input,
4155aee162fSJim Ingham                                         int cursor_index,
4165aee162fSJim Ingham                                         int char_pos,
4175aee162fSJim Ingham                                         OptionElementVector &opt_element_vector,
4185aee162fSJim Ingham                                         int opt_element_index,
4195aee162fSJim Ingham                                         int match_start_point,
4205aee162fSJim Ingham                                         int max_return_elements,
4215aee162fSJim Ingham                                         bool &word_complete,
4225aee162fSJim Ingham                                         StringList &matches)
4235aee162fSJim Ingham         {
4245aee162fSJim Ingham             int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
4255aee162fSJim Ingham             int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
4265aee162fSJim Ingham 
4275aee162fSJim Ingham             // We are only completing the name option for now...
4285aee162fSJim Ingham 
4295aee162fSJim Ingham             const lldb::OptionDefinition *opt_defs = GetDefinitions();
4305aee162fSJim Ingham             if (opt_defs[opt_defs_index].short_option == 'n')
4315aee162fSJim Ingham             {
4325aee162fSJim Ingham                 // Are we in the name?
4335aee162fSJim Ingham 
4345aee162fSJim Ingham                 // Look to see if there is a -P argument provided, and if so use that plugin, otherwise
4355aee162fSJim Ingham                 // use the default plugin.
436a7015092SGreg Clayton                 Process *process = interpeter.GetDebugger().GetExecutionContext().process;
4375aee162fSJim Ingham                 bool need_to_delete_process = false;
4385aee162fSJim Ingham 
4395aee162fSJim Ingham                 const char *partial_name = NULL;
4405aee162fSJim Ingham                 partial_name = input.GetArgumentAtIndex(opt_arg_pos);
4415aee162fSJim Ingham 
4425aee162fSJim Ingham                 if (process && process->IsAlive())
4435aee162fSJim Ingham                     return true;
4445aee162fSJim Ingham 
445a7015092SGreg Clayton                 Target *target = interpeter.GetDebugger().GetSelectedTarget().get();
4465aee162fSJim Ingham                 if (target == NULL)
4475aee162fSJim Ingham                 {
4485aee162fSJim Ingham                     // No target has been set yet, for now do host completion.  Otherwise I don't know how we would
4495aee162fSJim Ingham                     // figure out what the right target to use is...
4505aee162fSJim Ingham                     std::vector<lldb::pid_t> pids;
4515aee162fSJim Ingham                     Host::ListProcessesMatchingName (partial_name, matches, pids);
4525aee162fSJim Ingham                     return true;
4535aee162fSJim Ingham                 }
4545aee162fSJim Ingham                 if (!process)
4555aee162fSJim Ingham                 {
456a7015092SGreg Clayton                     process = target->CreateProcess (interpeter.GetDebugger().GetListener(), partial_name).get();
4575aee162fSJim Ingham                     need_to_delete_process = true;
4585aee162fSJim Ingham                 }
4595aee162fSJim Ingham 
4605aee162fSJim Ingham                 if (process)
4615aee162fSJim Ingham                 {
4625aee162fSJim Ingham                     matches.Clear();
4635aee162fSJim Ingham                     std::vector<lldb::pid_t> pids;
4645aee162fSJim Ingham                     process->ListProcessesMatchingName (NULL, matches, pids);
4655aee162fSJim Ingham                     if (need_to_delete_process)
4665aee162fSJim Ingham                         target->DeleteCurrentProcess();
4675aee162fSJim Ingham                     return true;
4685aee162fSJim Ingham                 }
4695aee162fSJim Ingham             }
4705aee162fSJim Ingham 
4715aee162fSJim Ingham             return false;
4725aee162fSJim Ingham         }
4735aee162fSJim Ingham 
47430fdc8d8SChris Lattner         // Options table: Required for subclasses of Options.
47530fdc8d8SChris Lattner 
47630fdc8d8SChris Lattner         static lldb::OptionDefinition g_option_table[];
47730fdc8d8SChris Lattner 
47830fdc8d8SChris Lattner         // Instance variables to hold the values for command options.
47930fdc8d8SChris Lattner 
48030fdc8d8SChris Lattner         lldb::pid_t pid;
48130fdc8d8SChris Lattner         std::string plugin_name;
48230fdc8d8SChris Lattner         std::string name;
48330fdc8d8SChris Lattner         bool waitfor;
48430fdc8d8SChris Lattner     };
48530fdc8d8SChris Lattner 
486a7015092SGreg Clayton     CommandObjectProcessAttach (CommandInterpreter &interpreter) :
487a7015092SGreg Clayton         CommandObject (interpreter,
488a7015092SGreg Clayton                        "process attach",
489e3d26315SCaroline Tice                        "Attach to a process.",
4905aee162fSJim Ingham                        "process attach <cmd-options>")
4915aee162fSJim Ingham     {
4925aee162fSJim Ingham     }
4935aee162fSJim Ingham 
4945aee162fSJim Ingham     ~CommandObjectProcessAttach ()
4955aee162fSJim Ingham     {
4965aee162fSJim Ingham     }
4975aee162fSJim Ingham 
4985aee162fSJim Ingham     bool
499a7015092SGreg Clayton     Execute (Args& command,
5005aee162fSJim Ingham              CommandReturnObject &result)
5015aee162fSJim Ingham     {
502a7015092SGreg Clayton         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
5035aee162fSJim Ingham 
504a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
5055aee162fSJim Ingham         if (process)
5065aee162fSJim Ingham         {
5075aee162fSJim Ingham             if (process->IsAlive())
5085aee162fSJim Ingham             {
5095aee162fSJim Ingham                 result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before attaching.\n",
5105aee162fSJim Ingham                                               process->GetID());
5115aee162fSJim Ingham                 result.SetStatus (eReturnStatusFailed);
5125aee162fSJim Ingham                 return false;
5135aee162fSJim Ingham             }
5145aee162fSJim Ingham         }
5155aee162fSJim Ingham 
5165aee162fSJim Ingham         if (target == NULL)
5175aee162fSJim Ingham         {
5185aee162fSJim Ingham             // If there isn't a current target create one.
5195aee162fSJim Ingham             TargetSP new_target_sp;
5205aee162fSJim Ingham             FileSpec emptyFileSpec;
5215aee162fSJim Ingham             ArchSpec emptyArchSpec;
5225aee162fSJim Ingham             Error error;
5235aee162fSJim Ingham 
524a7015092SGreg Clayton             error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(),
5255aee162fSJim Ingham                                                                               emptyFileSpec,
5265aee162fSJim Ingham                                                                               emptyArchSpec,
5275aee162fSJim Ingham                                                                               NULL,
5285aee162fSJim Ingham                                                                               false,
5295aee162fSJim Ingham                                                                               new_target_sp);
5305aee162fSJim Ingham             target = new_target_sp.get();
5315aee162fSJim Ingham             if (target == NULL || error.Fail())
5325aee162fSJim Ingham             {
5335aee162fSJim Ingham                 result.AppendError(error.AsCString("Error creating empty target"));
5345aee162fSJim Ingham                 return false;
5355aee162fSJim Ingham             }
536a7015092SGreg Clayton             m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target);
5375aee162fSJim Ingham         }
5385aee162fSJim Ingham 
5395aee162fSJim Ingham         // Record the old executable module, we want to issue a warning if the process of attaching changed the
5405aee162fSJim Ingham         // current executable (like somebody said "file foo" then attached to a PID whose executable was bar.)
5415aee162fSJim Ingham 
5425aee162fSJim Ingham         ModuleSP old_exec_module_sp = target->GetExecutableModule();
5435aee162fSJim Ingham         ArchSpec old_arch_spec = target->GetArchitecture();
5445aee162fSJim Ingham 
5455aee162fSJim Ingham         if (command.GetArgumentCount())
5465aee162fSJim Ingham         {
5475aee162fSJim Ingham             result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
5485aee162fSJim Ingham             result.SetStatus (eReturnStatusFailed);
5495aee162fSJim Ingham         }
5505aee162fSJim Ingham         else
5515aee162fSJim Ingham         {
5525aee162fSJim Ingham             const char *plugin_name = NULL;
5535aee162fSJim Ingham 
5545aee162fSJim Ingham             if (!m_options.plugin_name.empty())
5555aee162fSJim Ingham                 plugin_name = m_options.plugin_name.c_str();
5565aee162fSJim Ingham 
557a7015092SGreg Clayton             process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
5585aee162fSJim Ingham 
5595aee162fSJim Ingham             if (process)
5605aee162fSJim Ingham             {
5615aee162fSJim Ingham                 Error error;
5625aee162fSJim Ingham                 int attach_pid = m_options.pid;
5635aee162fSJim Ingham 
5643a0b9cdfSJim Ingham                 const char *wait_name = NULL;
5653a0b9cdfSJim Ingham 
5665aee162fSJim Ingham                 if (m_options.name.empty())
5675aee162fSJim Ingham                 {
5683a0b9cdfSJim Ingham                     if (old_exec_module_sp)
5693a0b9cdfSJim Ingham                     {
5703a0b9cdfSJim Ingham                         wait_name = old_exec_module_sp->GetFileSpec().GetFilename().AsCString();
5713a0b9cdfSJim Ingham                     }
5725aee162fSJim Ingham                 }
5735aee162fSJim Ingham                 else
5745aee162fSJim Ingham                 {
5753a0b9cdfSJim Ingham                     wait_name = m_options.name.c_str();
5763a0b9cdfSJim Ingham                 }
5773a0b9cdfSJim Ingham 
5783a0b9cdfSJim Ingham                 // If we are waiting for a process with this name to show up, do that first.
5793a0b9cdfSJim Ingham                 if (m_options.waitfor)
5803a0b9cdfSJim Ingham                 {
5813a0b9cdfSJim Ingham 
5823a0b9cdfSJim Ingham                     if (wait_name == NULL)
5833a0b9cdfSJim Ingham                     {
5843a0b9cdfSJim Ingham                         result.AppendError("Invalid arguments: must have a file loaded or supply a process name with the waitfor option.\n");
5853a0b9cdfSJim Ingham                         result.SetStatus (eReturnStatusFailed);
5863a0b9cdfSJim Ingham                         return false;
5873a0b9cdfSJim Ingham                     }
5883a0b9cdfSJim Ingham 
589a7015092SGreg Clayton                     m_interpreter.GetDebugger().GetOutputStream().Printf("Waiting to attach to a process named \"%s\".\n", wait_name);
5903a0b9cdfSJim Ingham                     error = process->Attach (wait_name, m_options.waitfor);
5915aee162fSJim Ingham                     if (error.Success())
5925aee162fSJim Ingham                     {
5935aee162fSJim Ingham                         result.SetStatus (eReturnStatusSuccessContinuingNoResult);
5945aee162fSJim Ingham                     }
5955aee162fSJim Ingham                     else
5965aee162fSJim Ingham                     {
5975aee162fSJim Ingham                         result.AppendErrorWithFormat ("Waiting for a process to launch named '%s': %s\n",
5983a0b9cdfSJim Ingham                                                          wait_name,
5995aee162fSJim Ingham                                                          error.AsCString());
6005aee162fSJim Ingham                         result.SetStatus (eReturnStatusFailed);
6015aee162fSJim Ingham                         return false;
6025aee162fSJim Ingham                     }
6035aee162fSJim Ingham                 }
6045aee162fSJim Ingham                 else
6055aee162fSJim Ingham                 {
6065aee162fSJim Ingham                     // If the process was specified by name look it up, so we can warn if there are multiple
6075aee162fSJim Ingham                     // processes with this pid.
6085aee162fSJim Ingham 
6093a0b9cdfSJim Ingham                     if (attach_pid == LLDB_INVALID_PROCESS_ID && wait_name != NULL)
6105aee162fSJim Ingham                     {
6115aee162fSJim Ingham                         std::vector<lldb::pid_t> pids;
6125aee162fSJim Ingham                         StringList matches;
6135aee162fSJim Ingham 
6143a0b9cdfSJim Ingham                         process->ListProcessesMatchingName(wait_name, matches, pids);
6155aee162fSJim Ingham                         if (matches.GetSize() > 1)
6165aee162fSJim Ingham                         {
6173a0b9cdfSJim Ingham                             result.AppendErrorWithFormat("More than one process named %s\n", wait_name);
6185aee162fSJim Ingham                             result.SetStatus (eReturnStatusFailed);
6195aee162fSJim Ingham                             return false;
6205aee162fSJim Ingham                         }
6215aee162fSJim Ingham                         else if (matches.GetSize() == 0)
6225aee162fSJim Ingham                         {
6233a0b9cdfSJim Ingham                             result.AppendErrorWithFormat("Could not find a process named %s\n", wait_name);
6245aee162fSJim Ingham                             result.SetStatus (eReturnStatusFailed);
6255aee162fSJim Ingham                             return false;
6265aee162fSJim Ingham                         }
6275aee162fSJim Ingham                         else
6285aee162fSJim Ingham                         {
6295aee162fSJim Ingham                             attach_pid = pids[0];
6305aee162fSJim Ingham                         }
6315aee162fSJim Ingham 
6325aee162fSJim Ingham                     }
6335aee162fSJim Ingham 
6345aee162fSJim Ingham                     if (attach_pid != LLDB_INVALID_PROCESS_ID)
6355aee162fSJim Ingham                     {
6365aee162fSJim Ingham                         error = process->Attach (attach_pid);
6375aee162fSJim Ingham                         if (error.Success())
6385aee162fSJim Ingham                         {
6395aee162fSJim Ingham                             result.SetStatus (eReturnStatusSuccessContinuingNoResult);
6405aee162fSJim Ingham                         }
6415aee162fSJim Ingham                         else
6425aee162fSJim Ingham                         {
6435aee162fSJim Ingham                             result.AppendErrorWithFormat ("Attaching to process %i failed: %s.\n",
6445aee162fSJim Ingham                                                          attach_pid,
6455aee162fSJim Ingham                                                          error.AsCString());
6465aee162fSJim Ingham                             result.SetStatus (eReturnStatusFailed);
6475aee162fSJim Ingham                         }
6485aee162fSJim Ingham                     }
6495aee162fSJim Ingham                     else
6505aee162fSJim Ingham                     {
6515aee162fSJim Ingham                         result.AppendErrorWithFormat ("No PID specified for attach\n",
6525aee162fSJim Ingham                                                          attach_pid,
6535aee162fSJim Ingham                                                          error.AsCString());
6545aee162fSJim Ingham                         result.SetStatus (eReturnStatusFailed);
6555aee162fSJim Ingham 
6565aee162fSJim Ingham                     }
6575aee162fSJim Ingham                 }
6585aee162fSJim Ingham             }
6595aee162fSJim Ingham         }
6605aee162fSJim Ingham 
6615aee162fSJim Ingham         if (result.Succeeded())
6625aee162fSJim Ingham         {
6635aee162fSJim Ingham             // Okay, we're done.  Last step is to warn if the executable module has changed:
6645aee162fSJim Ingham             if (!old_exec_module_sp)
6655aee162fSJim Ingham             {
6665aee162fSJim Ingham                 char new_path[PATH_MAX + 1];
6675aee162fSJim Ingham                 target->GetExecutableModule()->GetFileSpec().GetPath(new_path, PATH_MAX);
6685aee162fSJim Ingham 
6695aee162fSJim Ingham                 result.AppendMessageWithFormat("Executable module set to \"%s\".\n",
6705aee162fSJim Ingham                     new_path);
6715aee162fSJim Ingham             }
6725aee162fSJim Ingham             else if (old_exec_module_sp->GetFileSpec() != target->GetExecutableModule()->GetFileSpec())
6735aee162fSJim Ingham             {
6745aee162fSJim Ingham                 char old_path[PATH_MAX + 1];
6755aee162fSJim Ingham                 char new_path[PATH_MAX + 1];
6765aee162fSJim Ingham 
6775aee162fSJim Ingham                 old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX);
6785aee162fSJim Ingham                 target->GetExecutableModule()->GetFileSpec().GetPath (new_path, PATH_MAX);
6795aee162fSJim Ingham 
6805aee162fSJim Ingham                 result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n",
6815aee162fSJim Ingham                                                     old_path, new_path);
6825aee162fSJim Ingham             }
6835aee162fSJim Ingham 
6845aee162fSJim Ingham             if (!old_arch_spec.IsValid())
6855aee162fSJim Ingham             {
6865aee162fSJim Ingham                 result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().AsCString());
6875aee162fSJim Ingham             }
6885aee162fSJim Ingham             else if (old_arch_spec != target->GetArchitecture())
6895aee162fSJim Ingham             {
6905aee162fSJim Ingham                 result.AppendWarningWithFormat("Architecture changed from %s to %s.\n",
6915aee162fSJim Ingham                                                 old_arch_spec.AsCString(), target->GetArchitecture().AsCString());
6925aee162fSJim Ingham             }
6935aee162fSJim Ingham         }
6945aee162fSJim Ingham         return result.Succeeded();
6955aee162fSJim Ingham     }
6965aee162fSJim Ingham 
6975aee162fSJim Ingham     Options *
6985aee162fSJim Ingham     GetOptions ()
6995aee162fSJim Ingham     {
7005aee162fSJim Ingham         return &m_options;
7015aee162fSJim Ingham     }
7025aee162fSJim Ingham 
70330fdc8d8SChris Lattner protected:
70430fdc8d8SChris Lattner 
70530fdc8d8SChris Lattner     CommandOptions m_options;
70630fdc8d8SChris Lattner };
70730fdc8d8SChris Lattner 
70830fdc8d8SChris Lattner 
70930fdc8d8SChris Lattner lldb::OptionDefinition
71030fdc8d8SChris Lattner CommandObjectProcessAttach::CommandOptions::g_option_table[] =
71130fdc8d8SChris Lattner {
712deaab222SCaroline Tice { LLDB_OPT_SET_ALL, false, "plugin", 'P', required_argument, NULL, 0, eArgTypePlugin,        "Name of the process plugin you want to use."},
713deaab222SCaroline Tice { LLDB_OPT_SET_1,   false, "pid",    'p', required_argument, NULL, 0, eArgTypePid,           "The process ID of an existing process to attach to."},
714deaab222SCaroline Tice { LLDB_OPT_SET_2,   false, "name",   'n', required_argument, NULL, 0, eArgTypeProcessName,  "The name of the process to attach to."},
715deaab222SCaroline Tice { LLDB_OPT_SET_2,   false, "waitfor",'w', no_argument,       NULL, 0, eArgTypeNone,              "Wait for the the process with <process-name> to launch."},
716deaab222SCaroline Tice { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
71730fdc8d8SChris Lattner };
71830fdc8d8SChris Lattner 
71930fdc8d8SChris Lattner //-------------------------------------------------------------------------
72030fdc8d8SChris Lattner // CommandObjectProcessContinue
72130fdc8d8SChris Lattner //-------------------------------------------------------------------------
72230fdc8d8SChris Lattner 
72330fdc8d8SChris Lattner class CommandObjectProcessContinue : public CommandObject
72430fdc8d8SChris Lattner {
72530fdc8d8SChris Lattner public:
72630fdc8d8SChris Lattner 
727a7015092SGreg Clayton     CommandObjectProcessContinue (CommandInterpreter &interpreter) :
728a7015092SGreg Clayton         CommandObject (interpreter,
729a7015092SGreg Clayton                        "process continue",
730e3d26315SCaroline Tice                        "Continue execution of all threads in the current process.",
73130fdc8d8SChris Lattner                        "process continue",
73230fdc8d8SChris Lattner                        eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
73330fdc8d8SChris Lattner     {
73430fdc8d8SChris Lattner     }
73530fdc8d8SChris Lattner 
73630fdc8d8SChris Lattner 
73730fdc8d8SChris Lattner     ~CommandObjectProcessContinue ()
73830fdc8d8SChris Lattner     {
73930fdc8d8SChris Lattner     }
74030fdc8d8SChris Lattner 
74130fdc8d8SChris Lattner     bool
742a7015092SGreg Clayton     Execute (Args& command,
74330fdc8d8SChris Lattner              CommandReturnObject &result)
74430fdc8d8SChris Lattner     {
745a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
746a7015092SGreg Clayton         bool synchronous_execution = m_interpreter.GetSynchronous ();
74730fdc8d8SChris Lattner 
74830fdc8d8SChris Lattner         if (process == NULL)
74930fdc8d8SChris Lattner         {
75030fdc8d8SChris Lattner             result.AppendError ("no process to continue");
75130fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
75230fdc8d8SChris Lattner             return false;
75330fdc8d8SChris Lattner          }
75430fdc8d8SChris Lattner 
75530fdc8d8SChris Lattner         StateType state = process->GetState();
75630fdc8d8SChris Lattner         if (state == eStateStopped)
75730fdc8d8SChris Lattner         {
75830fdc8d8SChris Lattner             if (command.GetArgumentCount() != 0)
75930fdc8d8SChris Lattner             {
76030fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str());
76130fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
76230fdc8d8SChris Lattner                 return false;
76330fdc8d8SChris Lattner             }
76430fdc8d8SChris Lattner 
76530fdc8d8SChris Lattner             const uint32_t num_threads = process->GetThreadList().GetSize();
76630fdc8d8SChris Lattner 
76730fdc8d8SChris Lattner             // Set the actions that the threads should each take when resuming
76830fdc8d8SChris Lattner             for (uint32_t idx=0; idx<num_threads; ++idx)
76930fdc8d8SChris Lattner             {
77030fdc8d8SChris Lattner                 process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning);
77130fdc8d8SChris Lattner             }
77230fdc8d8SChris Lattner 
77330fdc8d8SChris Lattner             Error error(process->Resume());
77430fdc8d8SChris Lattner             if (error.Success())
77530fdc8d8SChris Lattner             {
77619388cfcSGreg Clayton                 result.AppendMessageWithFormat ("Process %i resuming\n", process->GetID());
77730fdc8d8SChris Lattner                 if (synchronous_execution)
77830fdc8d8SChris Lattner                 {
779b132097bSGreg Clayton                     state = process->WaitForProcessToStop (NULL);
78030fdc8d8SChris Lattner 
78130fdc8d8SChris Lattner                     result.SetDidChangeProcessState (true);
78230fdc8d8SChris Lattner                     result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
78330fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
78430fdc8d8SChris Lattner                 }
78530fdc8d8SChris Lattner                 else
78630fdc8d8SChris Lattner                 {
78730fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusSuccessContinuingNoResult);
78830fdc8d8SChris Lattner                 }
78930fdc8d8SChris Lattner             }
79030fdc8d8SChris Lattner             else
79130fdc8d8SChris Lattner             {
79230fdc8d8SChris Lattner                 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
79330fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
79430fdc8d8SChris Lattner             }
79530fdc8d8SChris Lattner         }
79630fdc8d8SChris Lattner         else
79730fdc8d8SChris Lattner         {
79830fdc8d8SChris Lattner             result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
79930fdc8d8SChris Lattner                                          StateAsCString(state));
80030fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
80130fdc8d8SChris Lattner         }
80230fdc8d8SChris Lattner         return result.Succeeded();
80330fdc8d8SChris Lattner     }
80430fdc8d8SChris Lattner };
80530fdc8d8SChris Lattner 
80630fdc8d8SChris Lattner //-------------------------------------------------------------------------
80730fdc8d8SChris Lattner // CommandObjectProcessDetach
80830fdc8d8SChris Lattner //-------------------------------------------------------------------------
80930fdc8d8SChris Lattner 
81030fdc8d8SChris Lattner class CommandObjectProcessDetach : public CommandObject
81130fdc8d8SChris Lattner {
81230fdc8d8SChris Lattner public:
81330fdc8d8SChris Lattner 
814a7015092SGreg Clayton     CommandObjectProcessDetach (CommandInterpreter &interpreter) :
815a7015092SGreg Clayton         CommandObject (interpreter,
816a7015092SGreg Clayton                        "process detach",
817e3d26315SCaroline Tice                        "Detach from the current process being debugged.",
81830fdc8d8SChris Lattner                        "process detach",
81930fdc8d8SChris Lattner                        eFlagProcessMustBeLaunched)
82030fdc8d8SChris Lattner     {
82130fdc8d8SChris Lattner     }
82230fdc8d8SChris Lattner 
82330fdc8d8SChris Lattner     ~CommandObjectProcessDetach ()
82430fdc8d8SChris Lattner     {
82530fdc8d8SChris Lattner     }
82630fdc8d8SChris Lattner 
82730fdc8d8SChris Lattner     bool
828a7015092SGreg Clayton     Execute (Args& command,
82930fdc8d8SChris Lattner              CommandReturnObject &result)
83030fdc8d8SChris Lattner     {
831a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
83230fdc8d8SChris Lattner         if (process == NULL)
83330fdc8d8SChris Lattner         {
83430fdc8d8SChris Lattner             result.AppendError ("must have a valid process in order to detach");
83530fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
83630fdc8d8SChris Lattner             return false;
83730fdc8d8SChris Lattner         }
83830fdc8d8SChris Lattner 
839*5d7be2e6SCaroline Tice         result.AppendMessageWithFormat ("Detaching from process %i\n", process->GetID());
84030fdc8d8SChris Lattner         Error error (process->Detach());
84130fdc8d8SChris Lattner         if (error.Success())
84230fdc8d8SChris Lattner         {
84330fdc8d8SChris Lattner             result.SetStatus (eReturnStatusSuccessFinishResult);
84430fdc8d8SChris Lattner         }
84530fdc8d8SChris Lattner         else
84630fdc8d8SChris Lattner         {
84730fdc8d8SChris Lattner             result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString());
84830fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
84930fdc8d8SChris Lattner             return false;
85030fdc8d8SChris Lattner         }
85130fdc8d8SChris Lattner         return result.Succeeded();
85230fdc8d8SChris Lattner     }
85330fdc8d8SChris Lattner };
85430fdc8d8SChris Lattner 
85530fdc8d8SChris Lattner //-------------------------------------------------------------------------
85630fdc8d8SChris Lattner // CommandObjectProcessSignal
85730fdc8d8SChris Lattner //-------------------------------------------------------------------------
85830fdc8d8SChris Lattner 
85930fdc8d8SChris Lattner class CommandObjectProcessSignal : public CommandObject
86030fdc8d8SChris Lattner {
86130fdc8d8SChris Lattner public:
86230fdc8d8SChris Lattner 
863a7015092SGreg Clayton     CommandObjectProcessSignal (CommandInterpreter &interpreter) :
864a7015092SGreg Clayton         CommandObject (interpreter,
865a7015092SGreg Clayton                        "process signal",
866e3d26315SCaroline Tice                        "Send a UNIX signal to the current process being debugged.",
867405fe67fSCaroline Tice                        NULL)
86830fdc8d8SChris Lattner     {
869405fe67fSCaroline Tice         CommandArgumentEntry arg;
870405fe67fSCaroline Tice         CommandArgumentData signal_arg;
871405fe67fSCaroline Tice 
872405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
873c0dbdfb6SCaroline Tice         signal_arg.arg_type = eArgTypeUnixSignal;
874405fe67fSCaroline Tice         signal_arg.arg_repetition = eArgRepeatPlain;
875405fe67fSCaroline Tice 
876405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
877405fe67fSCaroline Tice         arg.push_back (signal_arg);
878405fe67fSCaroline Tice 
879405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
880405fe67fSCaroline Tice         m_arguments.push_back (arg);
88130fdc8d8SChris Lattner     }
88230fdc8d8SChris Lattner 
88330fdc8d8SChris Lattner     ~CommandObjectProcessSignal ()
88430fdc8d8SChris Lattner     {
88530fdc8d8SChris Lattner     }
88630fdc8d8SChris Lattner 
88730fdc8d8SChris Lattner     bool
888a7015092SGreg Clayton     Execute (Args& command,
88930fdc8d8SChris Lattner              CommandReturnObject &result)
89030fdc8d8SChris Lattner     {
891a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
89230fdc8d8SChris Lattner         if (process == NULL)
89330fdc8d8SChris Lattner         {
89430fdc8d8SChris Lattner             result.AppendError ("no process to signal");
89530fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
89630fdc8d8SChris Lattner             return false;
89730fdc8d8SChris Lattner         }
89830fdc8d8SChris Lattner 
89930fdc8d8SChris Lattner         if (command.GetArgumentCount() == 1)
90030fdc8d8SChris Lattner         {
901237cd906SGreg Clayton             int signo = LLDB_INVALID_SIGNAL_NUMBER;
902237cd906SGreg Clayton 
903237cd906SGreg Clayton             const char *signal_name = command.GetArgumentAtIndex(0);
904237cd906SGreg Clayton             if (::isxdigit (signal_name[0]))
905237cd906SGreg Clayton                 signo = Args::StringToSInt32(signal_name, LLDB_INVALID_SIGNAL_NUMBER, 0);
906237cd906SGreg Clayton             else
907237cd906SGreg Clayton                 signo = process->GetUnixSignals().GetSignalNumberFromName (signal_name);
908237cd906SGreg Clayton 
909237cd906SGreg Clayton             if (signo == LLDB_INVALID_SIGNAL_NUMBER)
91030fdc8d8SChris Lattner             {
91130fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0));
91230fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
91330fdc8d8SChris Lattner             }
91430fdc8d8SChris Lattner             else
91530fdc8d8SChris Lattner             {
91630fdc8d8SChris Lattner                 Error error (process->Signal (signo));
91730fdc8d8SChris Lattner                 if (error.Success())
91830fdc8d8SChris Lattner                 {
91930fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusSuccessFinishResult);
92030fdc8d8SChris Lattner                 }
92130fdc8d8SChris Lattner                 else
92230fdc8d8SChris Lattner                 {
92330fdc8d8SChris Lattner                     result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString());
92430fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusFailed);
92530fdc8d8SChris Lattner                 }
92630fdc8d8SChris Lattner             }
92730fdc8d8SChris Lattner         }
92830fdc8d8SChris Lattner         else
92930fdc8d8SChris Lattner         {
93030fdc8d8SChris Lattner             result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: \n", m_cmd_name.c_str(),
93130fdc8d8SChris Lattner                                         m_cmd_syntax.c_str());
93230fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
93330fdc8d8SChris Lattner         }
93430fdc8d8SChris Lattner         return result.Succeeded();
93530fdc8d8SChris Lattner     }
93630fdc8d8SChris Lattner };
93730fdc8d8SChris Lattner 
93830fdc8d8SChris Lattner 
93930fdc8d8SChris Lattner //-------------------------------------------------------------------------
94030fdc8d8SChris Lattner // CommandObjectProcessInterrupt
94130fdc8d8SChris Lattner //-------------------------------------------------------------------------
94230fdc8d8SChris Lattner 
94330fdc8d8SChris Lattner class CommandObjectProcessInterrupt : public CommandObject
94430fdc8d8SChris Lattner {
94530fdc8d8SChris Lattner public:
94630fdc8d8SChris Lattner 
94730fdc8d8SChris Lattner 
948a7015092SGreg Clayton     CommandObjectProcessInterrupt (CommandInterpreter &interpreter) :
949a7015092SGreg Clayton     CommandObject (interpreter,
950a7015092SGreg Clayton                    "process interrupt",
951e3d26315SCaroline Tice                    "Interrupt the current process being debugged.",
95230fdc8d8SChris Lattner                    "process interrupt",
95330fdc8d8SChris Lattner                    eFlagProcessMustBeLaunched)
95430fdc8d8SChris Lattner     {
95530fdc8d8SChris Lattner     }
95630fdc8d8SChris Lattner 
95730fdc8d8SChris Lattner     ~CommandObjectProcessInterrupt ()
95830fdc8d8SChris Lattner     {
95930fdc8d8SChris Lattner     }
96030fdc8d8SChris Lattner 
96130fdc8d8SChris Lattner     bool
962a7015092SGreg Clayton     Execute (Args& command,
96330fdc8d8SChris Lattner              CommandReturnObject &result)
96430fdc8d8SChris Lattner     {
965a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
96630fdc8d8SChris Lattner         if (process == NULL)
96730fdc8d8SChris Lattner         {
96830fdc8d8SChris Lattner             result.AppendError ("no process to halt");
96930fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
97030fdc8d8SChris Lattner             return false;
97130fdc8d8SChris Lattner         }
97230fdc8d8SChris Lattner 
97330fdc8d8SChris Lattner         if (command.GetArgumentCount() == 0)
97430fdc8d8SChris Lattner         {
97530fdc8d8SChris Lattner             Error error(process->Halt ());
97630fdc8d8SChris Lattner             if (error.Success())
97730fdc8d8SChris Lattner             {
97830fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusSuccessFinishResult);
97930fdc8d8SChris Lattner 
98030fdc8d8SChris Lattner                 // Maybe we should add a "SuspendThreadPlans so we
98130fdc8d8SChris Lattner                 // can halt, and keep in place all the current thread plans.
98230fdc8d8SChris Lattner                 process->GetThreadList().DiscardThreadPlans();
98330fdc8d8SChris Lattner             }
98430fdc8d8SChris Lattner             else
98530fdc8d8SChris Lattner             {
98630fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString());
98730fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
98830fdc8d8SChris Lattner             }
98930fdc8d8SChris Lattner         }
99030fdc8d8SChris Lattner         else
99130fdc8d8SChris Lattner         {
99230fdc8d8SChris Lattner             result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
99330fdc8d8SChris Lattner                                         m_cmd_name.c_str(),
99430fdc8d8SChris Lattner                                         m_cmd_syntax.c_str());
99530fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
99630fdc8d8SChris Lattner         }
99730fdc8d8SChris Lattner         return result.Succeeded();
99830fdc8d8SChris Lattner     }
99930fdc8d8SChris Lattner };
100030fdc8d8SChris Lattner 
100130fdc8d8SChris Lattner //-------------------------------------------------------------------------
100230fdc8d8SChris Lattner // CommandObjectProcessKill
100330fdc8d8SChris Lattner //-------------------------------------------------------------------------
100430fdc8d8SChris Lattner 
100530fdc8d8SChris Lattner class CommandObjectProcessKill : public CommandObject
100630fdc8d8SChris Lattner {
100730fdc8d8SChris Lattner public:
100830fdc8d8SChris Lattner 
1009a7015092SGreg Clayton     CommandObjectProcessKill (CommandInterpreter &interpreter) :
1010a7015092SGreg Clayton     CommandObject (interpreter,
1011a7015092SGreg Clayton                    "process kill",
1012e3d26315SCaroline Tice                    "Terminate the current process being debugged.",
101330fdc8d8SChris Lattner                    "process kill",
101430fdc8d8SChris Lattner                    eFlagProcessMustBeLaunched)
101530fdc8d8SChris Lattner     {
101630fdc8d8SChris Lattner     }
101730fdc8d8SChris Lattner 
101830fdc8d8SChris Lattner     ~CommandObjectProcessKill ()
101930fdc8d8SChris Lattner     {
102030fdc8d8SChris Lattner     }
102130fdc8d8SChris Lattner 
102230fdc8d8SChris Lattner     bool
1023a7015092SGreg Clayton     Execute (Args& command,
102430fdc8d8SChris Lattner              CommandReturnObject &result)
102530fdc8d8SChris Lattner     {
1026a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
102730fdc8d8SChris Lattner         if (process == NULL)
102830fdc8d8SChris Lattner         {
102930fdc8d8SChris Lattner             result.AppendError ("no process to kill");
103030fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
103130fdc8d8SChris Lattner             return false;
103230fdc8d8SChris Lattner         }
103330fdc8d8SChris Lattner 
103430fdc8d8SChris Lattner         if (command.GetArgumentCount() == 0)
103530fdc8d8SChris Lattner         {
103630fdc8d8SChris Lattner             Error error (process->Destroy());
103730fdc8d8SChris Lattner             if (error.Success())
103830fdc8d8SChris Lattner             {
103930fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusSuccessFinishResult);
104030fdc8d8SChris Lattner             }
104130fdc8d8SChris Lattner             else
104230fdc8d8SChris Lattner             {
104330fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString());
104430fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
104530fdc8d8SChris Lattner             }
104630fdc8d8SChris Lattner         }
104730fdc8d8SChris Lattner         else
104830fdc8d8SChris Lattner         {
104930fdc8d8SChris Lattner             result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
105030fdc8d8SChris Lattner                                         m_cmd_name.c_str(),
105130fdc8d8SChris Lattner                                         m_cmd_syntax.c_str());
105230fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
105330fdc8d8SChris Lattner         }
105430fdc8d8SChris Lattner         return result.Succeeded();
105530fdc8d8SChris Lattner     }
105630fdc8d8SChris Lattner };
105730fdc8d8SChris Lattner 
105830fdc8d8SChris Lattner //-------------------------------------------------------------------------
10594b9bea87SJim Ingham // CommandObjectProcessStatus
10604b9bea87SJim Ingham //-------------------------------------------------------------------------
10614b9bea87SJim Ingham class CommandObjectProcessStatus : public CommandObject
10624b9bea87SJim Ingham {
10634b9bea87SJim Ingham public:
1064a7015092SGreg Clayton     CommandObjectProcessStatus (CommandInterpreter &interpreter) :
1065a7015092SGreg Clayton     CommandObject (interpreter,
1066a7015092SGreg Clayton                    "process status",
1067e3d26315SCaroline Tice                    "Show the current status and location of executing process.",
1068e3d26315SCaroline Tice                    "process status",
10694b9bea87SJim Ingham                    0)
10704b9bea87SJim Ingham     {
10714b9bea87SJim Ingham     }
10724b9bea87SJim Ingham 
10734b9bea87SJim Ingham     ~CommandObjectProcessStatus()
10744b9bea87SJim Ingham     {
10754b9bea87SJim Ingham     }
10764b9bea87SJim Ingham 
10774b9bea87SJim Ingham 
10784b9bea87SJim Ingham     bool
10794b9bea87SJim Ingham     Execute
10804b9bea87SJim Ingham     (
10814b9bea87SJim Ingham         Args& command,
10824b9bea87SJim Ingham         CommandReturnObject &result
10834b9bea87SJim Ingham     )
10844b9bea87SJim Ingham     {
10854b9bea87SJim Ingham         StreamString &output_stream = result.GetOutputStream();
10864b9bea87SJim Ingham         result.SetStatus (eReturnStatusSuccessFinishNoResult);
1087a7015092SGreg Clayton         ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
10884b9bea87SJim Ingham         if (exe_ctx.process)
10894b9bea87SJim Ingham         {
10904b9bea87SJim Ingham             const StateType state = exe_ctx.process->GetState();
10914b9bea87SJim Ingham             if (StateIsStoppedState(state))
10924b9bea87SJim Ingham             {
10934b9bea87SJim Ingham                 if (state == eStateExited)
10944b9bea87SJim Ingham                 {
10954b9bea87SJim Ingham                     int exit_status = exe_ctx.process->GetExitStatus();
10964b9bea87SJim Ingham                     const char *exit_description = exe_ctx.process->GetExitDescription();
10974b9bea87SJim Ingham                     output_stream.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n",
10984b9bea87SJim Ingham                                           exe_ctx.process->GetID(),
10994b9bea87SJim Ingham                                           exit_status,
11004b9bea87SJim Ingham                                           exit_status,
11014b9bea87SJim Ingham                                           exit_description ? exit_description : "");
11024b9bea87SJim Ingham                 }
11034b9bea87SJim Ingham                 else
11044b9bea87SJim Ingham                 {
11054b9bea87SJim Ingham                     output_stream.Printf ("Process %d %s\n", exe_ctx.process->GetID(), StateAsCString (state));
11064b9bea87SJim Ingham                     if (exe_ctx.thread == NULL)
11074b9bea87SJim Ingham                         exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
11084b9bea87SJim Ingham                     if (exe_ctx.thread != NULL)
11094b9bea87SJim Ingham                     {
1110a7015092SGreg Clayton                         DisplayThreadsInfo (m_interpreter, &exe_ctx, result, true, true);
11114b9bea87SJim Ingham                     }
11124b9bea87SJim Ingham                     else
11134b9bea87SJim Ingham                     {
11144b9bea87SJim Ingham                         result.AppendError ("No valid thread found in current process.");
11154b9bea87SJim Ingham                         result.SetStatus (eReturnStatusFailed);
11164b9bea87SJim Ingham                     }
11174b9bea87SJim Ingham                 }
11184b9bea87SJim Ingham             }
11194b9bea87SJim Ingham             else
11204b9bea87SJim Ingham             {
11214b9bea87SJim Ingham                 output_stream.Printf ("Process %d is running.\n",
11224b9bea87SJim Ingham                                           exe_ctx.process->GetID());
11234b9bea87SJim Ingham             }
11244b9bea87SJim Ingham         }
11254b9bea87SJim Ingham         else
11264b9bea87SJim Ingham         {
11274b9bea87SJim Ingham             result.AppendError ("No current location or status available.");
11284b9bea87SJim Ingham             result.SetStatus (eReturnStatusFailed);
11294b9bea87SJim Ingham         }
11304b9bea87SJim Ingham         return result.Succeeded();
11314b9bea87SJim Ingham     }
11324b9bea87SJim Ingham };
11334b9bea87SJim Ingham 
11344b9bea87SJim Ingham //-------------------------------------------------------------------------
113535731357SCaroline Tice // CommandObjectProcessHandle
113635731357SCaroline Tice //-------------------------------------------------------------------------
113735731357SCaroline Tice 
113835731357SCaroline Tice class CommandObjectProcessHandle : public CommandObject
113935731357SCaroline Tice {
114035731357SCaroline Tice public:
114135731357SCaroline Tice 
114235731357SCaroline Tice     class CommandOptions : public Options
114335731357SCaroline Tice     {
114435731357SCaroline Tice     public:
114535731357SCaroline Tice 
114635731357SCaroline Tice         CommandOptions () :
114735731357SCaroline Tice             Options ()
114835731357SCaroline Tice         {
114935731357SCaroline Tice             ResetOptionValues ();
115035731357SCaroline Tice         }
115135731357SCaroline Tice 
115235731357SCaroline Tice         ~CommandOptions ()
115335731357SCaroline Tice         {
115435731357SCaroline Tice         }
115535731357SCaroline Tice 
115635731357SCaroline Tice         Error
115735731357SCaroline Tice         SetOptionValue (int option_idx, const char *option_arg)
115835731357SCaroline Tice         {
115935731357SCaroline Tice             Error error;
116035731357SCaroline Tice             char short_option = (char) m_getopt_table[option_idx].val;
116135731357SCaroline Tice 
116235731357SCaroline Tice             switch (short_option)
116335731357SCaroline Tice             {
116435731357SCaroline Tice                 case 's':
116535731357SCaroline Tice                     stop = option_arg;
116635731357SCaroline Tice                     break;
116735731357SCaroline Tice                 case 'n':
116835731357SCaroline Tice                     notify = option_arg;
116935731357SCaroline Tice                     break;
117035731357SCaroline Tice                 case 'p':
117135731357SCaroline Tice                     pass = option_arg;
117235731357SCaroline Tice                     break;
117335731357SCaroline Tice                 default:
117435731357SCaroline Tice                     error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
117535731357SCaroline Tice                     break;
117635731357SCaroline Tice             }
117735731357SCaroline Tice             return error;
117835731357SCaroline Tice         }
117935731357SCaroline Tice 
118035731357SCaroline Tice         void
118135731357SCaroline Tice         ResetOptionValues ()
118235731357SCaroline Tice         {
118335731357SCaroline Tice             Options::ResetOptionValues();
118435731357SCaroline Tice             stop.clear();
118535731357SCaroline Tice             notify.clear();
118635731357SCaroline Tice             pass.clear();
118735731357SCaroline Tice         }
118835731357SCaroline Tice 
118935731357SCaroline Tice         const lldb::OptionDefinition*
119035731357SCaroline Tice         GetDefinitions ()
119135731357SCaroline Tice         {
119235731357SCaroline Tice             return g_option_table;
119335731357SCaroline Tice         }
119435731357SCaroline Tice 
119535731357SCaroline Tice         // Options table: Required for subclasses of Options.
119635731357SCaroline Tice 
119735731357SCaroline Tice         static lldb::OptionDefinition g_option_table[];
119835731357SCaroline Tice 
119935731357SCaroline Tice         // Instance variables to hold the values for command options.
120035731357SCaroline Tice 
120135731357SCaroline Tice         std::string stop;
120235731357SCaroline Tice         std::string notify;
120335731357SCaroline Tice         std::string pass;
120435731357SCaroline Tice     };
120535731357SCaroline Tice 
120635731357SCaroline Tice 
120735731357SCaroline Tice     CommandObjectProcessHandle (CommandInterpreter &interpreter) :
120835731357SCaroline Tice         CommandObject (interpreter,
120935731357SCaroline Tice                        "process handle",
121010ad7993SCaroline Tice                        "Show or update what the process and debugger should do with various signals received from the OS.",
121135731357SCaroline Tice                        NULL)
121235731357SCaroline Tice     {
121310ad7993SCaroline Tice         SetHelpLong ("If no signals are specified, update them all.  If no update option is specified, list the current values.\n");
121435731357SCaroline Tice         CommandArgumentEntry arg;
1215c0dbdfb6SCaroline Tice         CommandArgumentData signal_arg;
121635731357SCaroline Tice 
1217c0dbdfb6SCaroline Tice         signal_arg.arg_type = eArgTypeUnixSignal;
1218c0dbdfb6SCaroline Tice         signal_arg.arg_repetition = eArgRepeatStar;
121935731357SCaroline Tice 
1220c0dbdfb6SCaroline Tice         arg.push_back (signal_arg);
122135731357SCaroline Tice 
122235731357SCaroline Tice         m_arguments.push_back (arg);
122335731357SCaroline Tice     }
122435731357SCaroline Tice 
122535731357SCaroline Tice     ~CommandObjectProcessHandle ()
122635731357SCaroline Tice     {
122735731357SCaroline Tice     }
122835731357SCaroline Tice 
122935731357SCaroline Tice     Options *
123035731357SCaroline Tice     GetOptions ()
123135731357SCaroline Tice     {
123235731357SCaroline Tice         return &m_options;
123335731357SCaroline Tice     }
123435731357SCaroline Tice 
123535731357SCaroline Tice     bool
123610ad7993SCaroline Tice     VerifyCommandOptionValue (const std::string &option, int &real_value)
123735731357SCaroline Tice     {
123835731357SCaroline Tice         bool okay = true;
123935731357SCaroline Tice 
124010ad7993SCaroline Tice         bool success = false;
124110ad7993SCaroline Tice         bool tmp_value = Args::StringToBoolean (option.c_str(), false, &success);
124210ad7993SCaroline Tice 
124310ad7993SCaroline Tice         if (success && tmp_value)
124410ad7993SCaroline Tice             real_value = 1;
124510ad7993SCaroline Tice         else if (success && !tmp_value)
124610ad7993SCaroline Tice             real_value = 0;
124735731357SCaroline Tice         else
124835731357SCaroline Tice         {
124935731357SCaroline Tice             // If the value isn't 'true' or 'false', it had better be 0 or 1.
125010ad7993SCaroline Tice             real_value = Args::StringToUInt32 (option.c_str(), 3);
125110ad7993SCaroline Tice             if (real_value != 0 && real_value != 1)
125235731357SCaroline Tice                 okay = false;
125335731357SCaroline Tice         }
125435731357SCaroline Tice 
125535731357SCaroline Tice         return okay;
125635731357SCaroline Tice     }
125735731357SCaroline Tice 
125810ad7993SCaroline Tice     void
125910ad7993SCaroline Tice     PrintSignalHeader (Stream &str)
126010ad7993SCaroline Tice     {
126110ad7993SCaroline Tice         str.Printf ("NAME        PASS   STOP   NOTIFY\n");
126210ad7993SCaroline Tice         str.Printf ("==========  =====  =====  ======\n");
126310ad7993SCaroline Tice     }
126410ad7993SCaroline Tice 
126510ad7993SCaroline Tice     void
126610ad7993SCaroline Tice     PrintSignal (Stream &str, int32_t signo, const char *sig_name, UnixSignals &signals)
126710ad7993SCaroline Tice     {
126810ad7993SCaroline Tice         bool stop;
126910ad7993SCaroline Tice         bool suppress;
127010ad7993SCaroline Tice         bool notify;
127110ad7993SCaroline Tice 
127210ad7993SCaroline Tice         str.Printf ("%-10s  ", sig_name);
127310ad7993SCaroline Tice         if (signals.GetSignalInfo (signo, suppress, stop, notify))
127410ad7993SCaroline Tice         {
127510ad7993SCaroline Tice             bool pass = !suppress;
127610ad7993SCaroline Tice             str.Printf ("%s  %s  %s",
127710ad7993SCaroline Tice                         (pass ? "true " : "false"),
127810ad7993SCaroline Tice                         (stop ? "true " : "false"),
127910ad7993SCaroline Tice                         (notify ? "true " : "false"));
128010ad7993SCaroline Tice         }
128110ad7993SCaroline Tice         str.Printf ("\n");
128210ad7993SCaroline Tice     }
128310ad7993SCaroline Tice 
128410ad7993SCaroline Tice     void
128510ad7993SCaroline Tice     PrintSignalInformation (Stream &str, Args &signal_args, int num_valid_signals, UnixSignals &signals)
128610ad7993SCaroline Tice     {
128710ad7993SCaroline Tice         PrintSignalHeader (str);
128810ad7993SCaroline Tice 
128910ad7993SCaroline Tice         if (num_valid_signals > 0)
129010ad7993SCaroline Tice         {
129110ad7993SCaroline Tice             size_t num_args = signal_args.GetArgumentCount();
129210ad7993SCaroline Tice             for (size_t i = 0; i < num_args; ++i)
129310ad7993SCaroline Tice             {
129410ad7993SCaroline Tice                 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
129510ad7993SCaroline Tice                 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
129610ad7993SCaroline Tice                     PrintSignal (str, signo, signal_args.GetArgumentAtIndex (i), signals);
129710ad7993SCaroline Tice             }
129810ad7993SCaroline Tice         }
129910ad7993SCaroline Tice         else // Print info for ALL signals
130010ad7993SCaroline Tice         {
130110ad7993SCaroline Tice             int32_t signo = signals.GetFirstSignalNumber();
130210ad7993SCaroline Tice             while (signo != LLDB_INVALID_SIGNAL_NUMBER)
130310ad7993SCaroline Tice             {
130410ad7993SCaroline Tice                 PrintSignal (str, signo, signals.GetSignalAsCString (signo), signals);
130510ad7993SCaroline Tice                 signo = signals.GetNextSignalNumber (signo);
130610ad7993SCaroline Tice             }
130710ad7993SCaroline Tice         }
130810ad7993SCaroline Tice     }
130910ad7993SCaroline Tice 
131035731357SCaroline Tice     bool
131135731357SCaroline Tice     Execute (Args &signal_args, CommandReturnObject &result)
131235731357SCaroline Tice     {
131335731357SCaroline Tice         TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
131435731357SCaroline Tice 
131535731357SCaroline Tice         if (!target_sp)
131635731357SCaroline Tice         {
131735731357SCaroline Tice             result.AppendError ("No current target;"
131835731357SCaroline Tice                                 " cannot handle signals until you have a valid target and process.\n");
131935731357SCaroline Tice             result.SetStatus (eReturnStatusFailed);
132035731357SCaroline Tice             return false;
132135731357SCaroline Tice         }
132235731357SCaroline Tice 
132335731357SCaroline Tice         ProcessSP process_sp = target_sp->GetProcessSP();
132435731357SCaroline Tice 
132535731357SCaroline Tice         if (!process_sp)
132635731357SCaroline Tice         {
132735731357SCaroline Tice             result.AppendError ("No current process; cannot handle signals until you have a valid process.\n");
132835731357SCaroline Tice             result.SetStatus (eReturnStatusFailed);
132935731357SCaroline Tice             return false;
133035731357SCaroline Tice         }
133135731357SCaroline Tice 
133235731357SCaroline Tice         int stop_action = -1;   // -1 means leave the current setting alone
133335731357SCaroline Tice         int pass_action = -1;   // -1 means leave the current setting alone
133435731357SCaroline Tice         int notify_action = -1; // -1 means leave the current setting alone
133535731357SCaroline Tice 
133635731357SCaroline Tice         if (! m_options.stop.empty()
133710ad7993SCaroline Tice             && ! VerifyCommandOptionValue (m_options.stop, stop_action))
133835731357SCaroline Tice         {
133935731357SCaroline Tice             result.AppendError ("Invalid argument for command option --stop; must be true or false.\n");
134035731357SCaroline Tice             result.SetStatus (eReturnStatusFailed);
134135731357SCaroline Tice             return false;
134235731357SCaroline Tice         }
134335731357SCaroline Tice 
134435731357SCaroline Tice         if (! m_options.notify.empty()
134510ad7993SCaroline Tice             && ! VerifyCommandOptionValue (m_options.notify, notify_action))
134635731357SCaroline Tice         {
134735731357SCaroline Tice             result.AppendError ("Invalid argument for command option --notify; must be true or false.\n");
134835731357SCaroline Tice             result.SetStatus (eReturnStatusFailed);
134935731357SCaroline Tice             return false;
135035731357SCaroline Tice         }
135135731357SCaroline Tice 
135235731357SCaroline Tice         if (! m_options.pass.empty()
135310ad7993SCaroline Tice             && ! VerifyCommandOptionValue (m_options.pass, pass_action))
135435731357SCaroline Tice         {
135535731357SCaroline Tice             result.AppendError ("Invalid argument for command option --pass; must be true or false.\n");
135635731357SCaroline Tice             result.SetStatus (eReturnStatusFailed);
135735731357SCaroline Tice             return false;
135835731357SCaroline Tice         }
135935731357SCaroline Tice 
136035731357SCaroline Tice         size_t num_args = signal_args.GetArgumentCount();
136135731357SCaroline Tice         UnixSignals &signals = process_sp->GetUnixSignals();
136235731357SCaroline Tice         int num_signals_set = 0;
136335731357SCaroline Tice 
136410ad7993SCaroline Tice         if (num_args > 0)
136510ad7993SCaroline Tice         {
136635731357SCaroline Tice             for (size_t i = 0; i < num_args; ++i)
136735731357SCaroline Tice             {
136835731357SCaroline Tice                 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
136935731357SCaroline Tice                 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
137035731357SCaroline Tice                 {
137110ad7993SCaroline Tice                     // Casting the actions as bools here should be okay, because VerifyCommandOptionValue guarantees
137235731357SCaroline Tice                     // the value is either 0 or 1.
137335731357SCaroline Tice                     if (stop_action != -1)
137435731357SCaroline Tice                         signals.SetShouldStop (signo, (bool) stop_action);
137535731357SCaroline Tice                     if (pass_action != -1)
137635731357SCaroline Tice                     {
137710ad7993SCaroline Tice                         bool suppress = ! ((bool) pass_action);
137810ad7993SCaroline Tice                         signals.SetShouldSuppress (signo, suppress);
137935731357SCaroline Tice                     }
138035731357SCaroline Tice                     if (notify_action != -1)
138135731357SCaroline Tice                         signals.SetShouldNotify (signo, (bool) notify_action);
138235731357SCaroline Tice                     ++num_signals_set;
138335731357SCaroline Tice                 }
138435731357SCaroline Tice                 else
138535731357SCaroline Tice                 {
138635731357SCaroline Tice                     result.AppendErrorWithFormat ("Invalid signal name '%s'\n", signal_args.GetArgumentAtIndex (i));
138735731357SCaroline Tice                 }
138835731357SCaroline Tice             }
138910ad7993SCaroline Tice         }
139010ad7993SCaroline Tice         else
139110ad7993SCaroline Tice         {
139210ad7993SCaroline Tice             // No signal specified, if any command options were specified, update ALL signals.
139310ad7993SCaroline Tice             if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1))
139410ad7993SCaroline Tice             {
139510ad7993SCaroline Tice                 if (m_interpreter.Confirm ("Do you really want to update all the signals?", false))
139610ad7993SCaroline Tice                 {
139710ad7993SCaroline Tice                     int32_t signo = signals.GetFirstSignalNumber();
139810ad7993SCaroline Tice                     while (signo != LLDB_INVALID_SIGNAL_NUMBER)
139910ad7993SCaroline Tice                     {
140010ad7993SCaroline Tice                         if (notify_action != -1)
140110ad7993SCaroline Tice                             signals.SetShouldNotify (signo, (bool) notify_action);
140210ad7993SCaroline Tice                         if (stop_action != -1)
140310ad7993SCaroline Tice                             signals.SetShouldStop (signo, (bool) stop_action);
140410ad7993SCaroline Tice                         if (pass_action != -1)
140510ad7993SCaroline Tice                         {
140610ad7993SCaroline Tice                             bool suppress = ! ((bool) pass_action);
140710ad7993SCaroline Tice                             signals.SetShouldSuppress (signo, suppress);
140810ad7993SCaroline Tice                         }
140910ad7993SCaroline Tice                         signo = signals.GetNextSignalNumber (signo);
141010ad7993SCaroline Tice                     }
141110ad7993SCaroline Tice                 }
141210ad7993SCaroline Tice             }
141310ad7993SCaroline Tice         }
141410ad7993SCaroline Tice 
141510ad7993SCaroline Tice         PrintSignalInformation (result.GetOutputStream(), signal_args, num_signals_set, signals);
141635731357SCaroline Tice 
141735731357SCaroline Tice         if (num_signals_set > 0)
141835731357SCaroline Tice             result.SetStatus (eReturnStatusSuccessFinishNoResult);
141935731357SCaroline Tice         else
142035731357SCaroline Tice             result.SetStatus (eReturnStatusFailed);
142135731357SCaroline Tice 
142235731357SCaroline Tice         return result.Succeeded();
142335731357SCaroline Tice     }
142435731357SCaroline Tice 
142535731357SCaroline Tice protected:
142635731357SCaroline Tice 
142735731357SCaroline Tice     CommandOptions m_options;
142835731357SCaroline Tice };
142935731357SCaroline Tice 
143035731357SCaroline Tice lldb::OptionDefinition
143135731357SCaroline Tice CommandObjectProcessHandle::CommandOptions::g_option_table[] =
143235731357SCaroline Tice {
143335731357SCaroline 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." },
143435731357SCaroline 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." },
143535731357SCaroline Tice { LLDB_OPT_SET_1, false, "pass",  'p', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." },
143635731357SCaroline Tice { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
143735731357SCaroline Tice };
143835731357SCaroline Tice 
143935731357SCaroline Tice //-------------------------------------------------------------------------
144030fdc8d8SChris Lattner // CommandObjectMultiwordProcess
144130fdc8d8SChris Lattner //-------------------------------------------------------------------------
144230fdc8d8SChris Lattner 
14436611103cSGreg Clayton CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter &interpreter) :
1444a7015092SGreg Clayton     CommandObjectMultiword (interpreter,
1445a7015092SGreg Clayton                             "process",
144630fdc8d8SChris Lattner                             "A set of commands for operating on a process.",
144730fdc8d8SChris Lattner                             "process <subcommand> [<subcommand-options>]")
144830fdc8d8SChris Lattner {
1449a7015092SGreg Clayton     LoadSubCommand ("attach",      CommandObjectSP (new CommandObjectProcessAttach (interpreter)));
1450a7015092SGreg Clayton     LoadSubCommand ("launch",      CommandObjectSP (new CommandObjectProcessLaunch (interpreter)));
1451a7015092SGreg Clayton     LoadSubCommand ("continue",    CommandObjectSP (new CommandObjectProcessContinue (interpreter)));
1452a7015092SGreg Clayton     LoadSubCommand ("detach",      CommandObjectSP (new CommandObjectProcessDetach (interpreter)));
1453a7015092SGreg Clayton     LoadSubCommand ("signal",      CommandObjectSP (new CommandObjectProcessSignal (interpreter)));
145435731357SCaroline Tice     LoadSubCommand ("handle",      CommandObjectSP (new CommandObjectProcessHandle (interpreter)));
1455a7015092SGreg Clayton     LoadSubCommand ("status",      CommandObjectSP (new CommandObjectProcessStatus (interpreter)));
1456a7015092SGreg Clayton     LoadSubCommand ("interrupt",   CommandObjectSP (new CommandObjectProcessInterrupt (interpreter)));
1457a7015092SGreg Clayton     LoadSubCommand ("kill",        CommandObjectSP (new CommandObjectProcessKill (interpreter)));
145830fdc8d8SChris Lattner }
145930fdc8d8SChris Lattner 
146030fdc8d8SChris Lattner CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess ()
146130fdc8d8SChris Lattner {
146230fdc8d8SChris Lattner }
146330fdc8d8SChris Lattner 
1464