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;
6530fdc8d8SChris Lattner                 default:
6630fdc8d8SChris Lattner                     error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
6730fdc8d8SChris Lattner                     break;
6830fdc8d8SChris Lattner 
6930fdc8d8SChris Lattner             }
7030fdc8d8SChris Lattner             return error;
7130fdc8d8SChris Lattner         }
7230fdc8d8SChris Lattner 
7330fdc8d8SChris Lattner         void
7430fdc8d8SChris Lattner         ResetOptionValues ()
7530fdc8d8SChris Lattner         {
7630fdc8d8SChris Lattner             Options::ResetOptionValues();
7730fdc8d8SChris Lattner             stop_at_entry = false;
7830fdc8d8SChris Lattner             stdin_path.clear();
7930fdc8d8SChris Lattner             stdout_path.clear();
8030fdc8d8SChris Lattner             stderr_path.clear();
8130fdc8d8SChris Lattner             plugin_name.clear();
8230fdc8d8SChris Lattner         }
8330fdc8d8SChris Lattner 
8430fdc8d8SChris Lattner         const lldb::OptionDefinition*
8530fdc8d8SChris Lattner         GetDefinitions ()
8630fdc8d8SChris Lattner         {
8730fdc8d8SChris Lattner             return g_option_table;
8830fdc8d8SChris Lattner         }
8930fdc8d8SChris Lattner 
9030fdc8d8SChris Lattner         // Options table: Required for subclasses of Options.
9130fdc8d8SChris Lattner 
9230fdc8d8SChris Lattner         static lldb::OptionDefinition g_option_table[];
9330fdc8d8SChris Lattner 
9430fdc8d8SChris Lattner         // Instance variables to hold the values for command options.
9530fdc8d8SChris Lattner 
9630fdc8d8SChris Lattner         bool stop_at_entry;
9730fdc8d8SChris Lattner         std::string stderr_path;
9830fdc8d8SChris Lattner         std::string stdin_path;
9930fdc8d8SChris Lattner         std::string stdout_path;
10030fdc8d8SChris Lattner         std::string plugin_name;
10130fdc8d8SChris Lattner 
10230fdc8d8SChris Lattner     };
10330fdc8d8SChris Lattner 
104a7015092SGreg Clayton     CommandObjectProcessLaunch (CommandInterpreter &interpreter) :
105a7015092SGreg Clayton         CommandObject (interpreter,
106a7015092SGreg Clayton                        "process launch",
107e3d26315SCaroline Tice                        "Launch the executable in the debugger.",
108*405fe67fSCaroline Tice                        NULL)
10930fdc8d8SChris Lattner     {
110*405fe67fSCaroline Tice         CommandArgumentEntry arg;
111*405fe67fSCaroline Tice         CommandArgumentData run_args_arg;
112*405fe67fSCaroline Tice 
113*405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
114*405fe67fSCaroline Tice         run_args_arg.arg_type = eArgTypeRunArgs;
115*405fe67fSCaroline Tice         run_args_arg.arg_repetition = eArgRepeatOptional;
116*405fe67fSCaroline Tice 
117*405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
118*405fe67fSCaroline Tice         arg.push_back (run_args_arg);
119*405fe67fSCaroline Tice 
120*405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
121*405fe67fSCaroline Tice         m_arguments.push_back (arg);
12230fdc8d8SChris Lattner     }
12330fdc8d8SChris Lattner 
12430fdc8d8SChris Lattner 
12530fdc8d8SChris Lattner     ~CommandObjectProcessLaunch ()
12630fdc8d8SChris Lattner     {
12730fdc8d8SChris Lattner     }
12830fdc8d8SChris Lattner 
12930fdc8d8SChris Lattner     Options *
13030fdc8d8SChris Lattner     GetOptions ()
13130fdc8d8SChris Lattner     {
13230fdc8d8SChris Lattner         return &m_options;
13330fdc8d8SChris Lattner     }
13430fdc8d8SChris Lattner 
13530fdc8d8SChris Lattner     bool
136a7015092SGreg Clayton     Execute (Args& launch_args,
13730fdc8d8SChris Lattner              CommandReturnObject &result)
13830fdc8d8SChris Lattner     {
139a7015092SGreg Clayton         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
140a7015092SGreg Clayton         bool synchronous_execution = m_interpreter.GetSynchronous ();
14130fdc8d8SChris Lattner     //    bool launched = false;
14230fdc8d8SChris Lattner     //    bool stopped_after_launch = false;
14330fdc8d8SChris Lattner 
14430fdc8d8SChris Lattner         if (target == NULL)
14530fdc8d8SChris Lattner         {
14630fdc8d8SChris Lattner             result.AppendError ("invalid target, set executable file using 'file' command");
14730fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
14830fdc8d8SChris Lattner             return false;
14930fdc8d8SChris Lattner         }
15030fdc8d8SChris Lattner 
15130fdc8d8SChris Lattner         // If our listener is NULL, users aren't allows to launch
15230fdc8d8SChris Lattner         char filename[PATH_MAX];
15330fdc8d8SChris Lattner         Module *exe_module = target->GetExecutableModule().get();
15430fdc8d8SChris Lattner         exe_module->GetFileSpec().GetPath(filename, sizeof(filename));
15530fdc8d8SChris Lattner 
156a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
157a7015092SGreg Clayton         if (process && process->IsAlive())
15830fdc8d8SChris Lattner         {
15930fdc8d8SChris Lattner             result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before running again.\n",
16030fdc8d8SChris Lattner                                           process->GetID());
16130fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
16230fdc8d8SChris Lattner             return false;
16330fdc8d8SChris Lattner         }
16430fdc8d8SChris Lattner 
16530fdc8d8SChris Lattner         const char *plugin_name;
16630fdc8d8SChris Lattner         if (!m_options.plugin_name.empty())
16730fdc8d8SChris Lattner             plugin_name = m_options.plugin_name.c_str();
16830fdc8d8SChris Lattner         else
16930fdc8d8SChris Lattner             plugin_name = NULL;
17030fdc8d8SChris Lattner 
171a7015092SGreg Clayton         process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
17230fdc8d8SChris Lattner 
173a7015092SGreg Clayton         if (process == NULL)
1743df9a8dfSCaroline Tice         {
175a7015092SGreg Clayton             result.AppendErrorWithFormat ("Failed to find a process plugin for executable");
176a7015092SGreg Clayton             result.SetStatus (eReturnStatusFailed);
177a7015092SGreg Clayton             return false;
1783df9a8dfSCaroline Tice         }
1793df9a8dfSCaroline Tice 
180a7015092SGreg Clayton         // If no launch args were given on the command line, then use any that
181a7015092SGreg Clayton         // might have been set using the "run-args" set variable.
18230fdc8d8SChris Lattner         if (launch_args.GetArgumentCount() == 0)
18330fdc8d8SChris Lattner         {
184a7015092SGreg Clayton             if (process->GetRunArguments().GetArgumentCount() > 0)
185a7015092SGreg Clayton                 launch_args = process->GetRunArguments();
18630fdc8d8SChris Lattner         }
18730fdc8d8SChris Lattner 
188a7015092SGreg Clayton         Args environment;
18930fdc8d8SChris Lattner 
190a7015092SGreg Clayton         process->GetEnvironmentAsArgs (environment);
191a7015092SGreg Clayton 
192a7015092SGreg Clayton         uint32_t launch_flags = eLaunchFlagNone;
193a7015092SGreg Clayton 
194a7015092SGreg Clayton         if (process->GetDisableASLR())
195a7015092SGreg Clayton             launch_flags |= eLaunchFlagDisableASLR;
196a7015092SGreg Clayton 
19730fdc8d8SChris Lattner         const char *archname = exe_module->GetArchitecture().AsCString();
19830fdc8d8SChris Lattner 
19930fdc8d8SChris Lattner         const char * stdin_path = NULL;
20030fdc8d8SChris Lattner         const char * stdout_path = NULL;
20130fdc8d8SChris Lattner         const char * stderr_path = NULL;
20230fdc8d8SChris Lattner 
203a7015092SGreg Clayton         // Were any standard input/output/error paths given on the command line?
204a7015092SGreg Clayton         if (m_options.stdin_path.empty() &&
20530fdc8d8SChris Lattner             m_options.stdout_path.empty() &&
206a7015092SGreg Clayton             m_options.stderr_path.empty())
20730fdc8d8SChris Lattner         {
208a7015092SGreg Clayton             // No standard file handles were given on the command line, check
209a7015092SGreg Clayton             // with the process object in case they were give using "set settings"
210a7015092SGreg Clayton             stdin_path = process->GetStandardInputPath();
211a7015092SGreg Clayton             stdout_path = process->GetStandardOutputPath();
212a7015092SGreg Clayton             stderr_path = process->GetStandardErrorPath();
213a7015092SGreg Clayton         }
214a7015092SGreg Clayton         else
215a7015092SGreg Clayton         {
216a7015092SGreg Clayton             stdin_path = m_options.stdin_path.empty()  ? NULL : m_options.stdin_path.c_str();
217a7015092SGreg Clayton             stdout_path = m_options.stdout_path.empty() ? NULL : m_options.stdout_path.c_str();
218a7015092SGreg Clayton             stderr_path = m_options.stderr_path.empty() ? NULL : m_options.stderr_path.c_str();
21930fdc8d8SChris Lattner         }
22030fdc8d8SChris Lattner 
221a7015092SGreg Clayton         if (stdin_path == NULL)
222a7015092SGreg Clayton             stdin_path = "/dev/null";
223a7015092SGreg Clayton         if (stdout_path == NULL)
224a7015092SGreg Clayton             stdout_path = "/dev/null";
225a7015092SGreg Clayton         if (stderr_path == NULL)
226a7015092SGreg Clayton             stderr_path = "/dev/null";
227a7015092SGreg Clayton 
228a7015092SGreg Clayton         Error error (process->Launch (launch_args.GetArgumentCount() ? launch_args.GetConstArgumentVector() : NULL,
229a7015092SGreg Clayton                                       environment.GetArgumentCount() ? environment.GetConstArgumentVector() : NULL,
230f681b94fSGreg Clayton                                       launch_flags,
23130fdc8d8SChris Lattner                                       stdin_path,
23230fdc8d8SChris Lattner                                       stdout_path,
23330fdc8d8SChris Lattner                                       stderr_path));
23430fdc8d8SChris Lattner 
23530fdc8d8SChris Lattner         if (error.Success())
23630fdc8d8SChris Lattner         {
23730fdc8d8SChris Lattner             result.AppendMessageWithFormat ("Launching '%s'  (%s)\n", filename, archname);
23830fdc8d8SChris Lattner             result.SetStatus (eReturnStatusSuccessContinuingNoResult);
23930fdc8d8SChris Lattner             if (m_options.stop_at_entry == false)
24030fdc8d8SChris Lattner             {
24130fdc8d8SChris Lattner                 StateType state = process->WaitForProcessToStop (NULL);
24230fdc8d8SChris Lattner 
24330fdc8d8SChris Lattner                 if (state == eStateStopped)
24430fdc8d8SChris Lattner                 {
24530fdc8d8SChris Lattner                     // Call continue_command.
24630fdc8d8SChris Lattner                     CommandReturnObject continue_result;
247a7015092SGreg Clayton                     m_interpreter.HandleCommand("process continue", false, continue_result);
24830fdc8d8SChris Lattner                 }
24930fdc8d8SChris Lattner 
25030fdc8d8SChris Lattner                 if (synchronous_execution)
25130fdc8d8SChris Lattner                 {
25230fdc8d8SChris Lattner                     result.SetDidChangeProcessState (true);
25330fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
25430fdc8d8SChris Lattner                 }
25530fdc8d8SChris Lattner             }
25630fdc8d8SChris Lattner         }
25730fdc8d8SChris Lattner 
25830fdc8d8SChris Lattner         return result.Succeeded();
25930fdc8d8SChris Lattner     }
26030fdc8d8SChris Lattner 
261ebc09c36SJim Ingham     virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
262ebc09c36SJim Ingham     {
263ebc09c36SJim Ingham         // No repeat for "process launch"...
264ebc09c36SJim Ingham         return "";
265ebc09c36SJim Ingham     }
266ebc09c36SJim Ingham 
26730fdc8d8SChris Lattner protected:
26830fdc8d8SChris Lattner 
26930fdc8d8SChris Lattner     CommandOptions m_options;
27030fdc8d8SChris Lattner };
27130fdc8d8SChris Lattner 
27230fdc8d8SChris Lattner 
27330fdc8d8SChris Lattner lldb::OptionDefinition
27430fdc8d8SChris Lattner CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
27530fdc8d8SChris Lattner {
276deaab222SCaroline Tice { LLDB_OPT_SET_1, false, "stop-at-entry", 's', no_argument,       NULL, 0, eArgTypeNone,        "Stop at the entry point of the program when launching a process."},
277deaab222SCaroline Tice { LLDB_OPT_SET_1, false, "stdin",         'i', required_argument, NULL, 0, eArgTypePath,    "Redirect stdin for the process to <path>."},
278deaab222SCaroline Tice { LLDB_OPT_SET_1, false, "stdout",        'o', required_argument, NULL, 0, eArgTypePath,    "Redirect stdout for the process to <path>."},
279deaab222SCaroline Tice { LLDB_OPT_SET_1, false, "stderr",        'e', required_argument, NULL, 0, eArgTypePath,    "Redirect stderr for the process to <path>."},
280deaab222SCaroline Tice { LLDB_OPT_SET_1, false, "plugin",        'p', required_argument, NULL, 0, eArgTypePlugin,  "Name of the process plugin you want to use."},
281deaab222SCaroline Tice { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
28230fdc8d8SChris Lattner };
28330fdc8d8SChris Lattner 
28430fdc8d8SChris Lattner 
28530fdc8d8SChris Lattner //-------------------------------------------------------------------------
28630fdc8d8SChris Lattner // CommandObjectProcessAttach
28730fdc8d8SChris Lattner //-------------------------------------------------------------------------
28830fdc8d8SChris Lattner 
28930fdc8d8SChris Lattner class CommandObjectProcessAttach : public CommandObject
29030fdc8d8SChris Lattner {
29130fdc8d8SChris Lattner public:
29230fdc8d8SChris Lattner 
29330fdc8d8SChris Lattner     class CommandOptions : public Options
29430fdc8d8SChris Lattner     {
29530fdc8d8SChris Lattner     public:
29630fdc8d8SChris Lattner 
29730fdc8d8SChris Lattner         CommandOptions () :
29830fdc8d8SChris Lattner             Options()
29930fdc8d8SChris Lattner         {
30030fdc8d8SChris Lattner             // Keep default values of all options in one place: ResetOptionValues ()
30130fdc8d8SChris Lattner             ResetOptionValues ();
30230fdc8d8SChris Lattner         }
30330fdc8d8SChris Lattner 
30430fdc8d8SChris Lattner         ~CommandOptions ()
30530fdc8d8SChris Lattner         {
30630fdc8d8SChris Lattner         }
30730fdc8d8SChris Lattner 
30830fdc8d8SChris Lattner         Error
30930fdc8d8SChris Lattner         SetOptionValue (int option_idx, const char *option_arg)
31030fdc8d8SChris Lattner         {
31130fdc8d8SChris Lattner             Error error;
31230fdc8d8SChris Lattner             char short_option = (char) m_getopt_table[option_idx].val;
31330fdc8d8SChris Lattner             bool success = false;
31430fdc8d8SChris Lattner             switch (short_option)
31530fdc8d8SChris Lattner             {
31630fdc8d8SChris Lattner                 case 'p':
31730fdc8d8SChris Lattner                     pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success);
31830fdc8d8SChris Lattner                     if (!success || pid == LLDB_INVALID_PROCESS_ID)
31930fdc8d8SChris Lattner                     {
32030fdc8d8SChris Lattner                         error.SetErrorStringWithFormat("Invalid process ID '%s'.\n", option_arg);
32130fdc8d8SChris Lattner                     }
32230fdc8d8SChris Lattner                     break;
32330fdc8d8SChris Lattner 
32430fdc8d8SChris Lattner                 case 'P':
32530fdc8d8SChris Lattner                     plugin_name = option_arg;
32630fdc8d8SChris Lattner                     break;
32730fdc8d8SChris Lattner 
32830fdc8d8SChris Lattner                 case 'n':
32930fdc8d8SChris Lattner                     name.assign(option_arg);
33030fdc8d8SChris Lattner                     break;
33130fdc8d8SChris Lattner 
33230fdc8d8SChris Lattner                 case 'w':
33330fdc8d8SChris Lattner                     waitfor = true;
33430fdc8d8SChris Lattner                     break;
33530fdc8d8SChris Lattner 
33630fdc8d8SChris Lattner                 default:
33730fdc8d8SChris Lattner                     error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
33830fdc8d8SChris Lattner                     break;
33930fdc8d8SChris Lattner             }
34030fdc8d8SChris Lattner             return error;
34130fdc8d8SChris Lattner         }
34230fdc8d8SChris Lattner 
34330fdc8d8SChris Lattner         void
34430fdc8d8SChris Lattner         ResetOptionValues ()
34530fdc8d8SChris Lattner         {
34630fdc8d8SChris Lattner             Options::ResetOptionValues();
34730fdc8d8SChris Lattner             pid = LLDB_INVALID_PROCESS_ID;
34830fdc8d8SChris Lattner             name.clear();
34930fdc8d8SChris Lattner             waitfor = false;
35030fdc8d8SChris Lattner         }
35130fdc8d8SChris Lattner 
35230fdc8d8SChris Lattner         const lldb::OptionDefinition*
35330fdc8d8SChris Lattner         GetDefinitions ()
35430fdc8d8SChris Lattner         {
35530fdc8d8SChris Lattner             return g_option_table;
35630fdc8d8SChris Lattner         }
35730fdc8d8SChris Lattner 
3585aee162fSJim Ingham         virtual bool
359a7015092SGreg Clayton         HandleOptionArgumentCompletion (CommandInterpreter &interpeter,
3605aee162fSJim Ingham                                         Args &input,
3615aee162fSJim Ingham                                         int cursor_index,
3625aee162fSJim Ingham                                         int char_pos,
3635aee162fSJim Ingham                                         OptionElementVector &opt_element_vector,
3645aee162fSJim Ingham                                         int opt_element_index,
3655aee162fSJim Ingham                                         int match_start_point,
3665aee162fSJim Ingham                                         int max_return_elements,
3675aee162fSJim Ingham                                         bool &word_complete,
3685aee162fSJim Ingham                                         StringList &matches)
3695aee162fSJim Ingham         {
3705aee162fSJim Ingham             int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
3715aee162fSJim Ingham             int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
3725aee162fSJim Ingham 
3735aee162fSJim Ingham             // We are only completing the name option for now...
3745aee162fSJim Ingham 
3755aee162fSJim Ingham             const lldb::OptionDefinition *opt_defs = GetDefinitions();
3765aee162fSJim Ingham             if (opt_defs[opt_defs_index].short_option == 'n')
3775aee162fSJim Ingham             {
3785aee162fSJim Ingham                 // Are we in the name?
3795aee162fSJim Ingham 
3805aee162fSJim Ingham                 // Look to see if there is a -P argument provided, and if so use that plugin, otherwise
3815aee162fSJim Ingham                 // use the default plugin.
382a7015092SGreg Clayton                 Process *process = interpeter.GetDebugger().GetExecutionContext().process;
3835aee162fSJim Ingham                 bool need_to_delete_process = false;
3845aee162fSJim Ingham 
3855aee162fSJim Ingham                 const char *partial_name = NULL;
3865aee162fSJim Ingham                 partial_name = input.GetArgumentAtIndex(opt_arg_pos);
3875aee162fSJim Ingham 
3885aee162fSJim Ingham                 if (process && process->IsAlive())
3895aee162fSJim Ingham                     return true;
3905aee162fSJim Ingham 
391a7015092SGreg Clayton                 Target *target = interpeter.GetDebugger().GetSelectedTarget().get();
3925aee162fSJim Ingham                 if (target == NULL)
3935aee162fSJim Ingham                 {
3945aee162fSJim Ingham                     // No target has been set yet, for now do host completion.  Otherwise I don't know how we would
3955aee162fSJim Ingham                     // figure out what the right target to use is...
3965aee162fSJim Ingham                     std::vector<lldb::pid_t> pids;
3975aee162fSJim Ingham                     Host::ListProcessesMatchingName (partial_name, matches, pids);
3985aee162fSJim Ingham                     return true;
3995aee162fSJim Ingham                 }
4005aee162fSJim Ingham                 if (!process)
4015aee162fSJim Ingham                 {
402a7015092SGreg Clayton                     process = target->CreateProcess (interpeter.GetDebugger().GetListener(), partial_name).get();
4035aee162fSJim Ingham                     need_to_delete_process = true;
4045aee162fSJim Ingham                 }
4055aee162fSJim Ingham 
4065aee162fSJim Ingham                 if (process)
4075aee162fSJim Ingham                 {
4085aee162fSJim Ingham                     matches.Clear();
4095aee162fSJim Ingham                     std::vector<lldb::pid_t> pids;
4105aee162fSJim Ingham                     process->ListProcessesMatchingName (NULL, matches, pids);
4115aee162fSJim Ingham                     if (need_to_delete_process)
4125aee162fSJim Ingham                         target->DeleteCurrentProcess();
4135aee162fSJim Ingham                     return true;
4145aee162fSJim Ingham                 }
4155aee162fSJim Ingham             }
4165aee162fSJim Ingham 
4175aee162fSJim Ingham             return false;
4185aee162fSJim Ingham         }
4195aee162fSJim Ingham 
42030fdc8d8SChris Lattner         // Options table: Required for subclasses of Options.
42130fdc8d8SChris Lattner 
42230fdc8d8SChris Lattner         static lldb::OptionDefinition g_option_table[];
42330fdc8d8SChris Lattner 
42430fdc8d8SChris Lattner         // Instance variables to hold the values for command options.
42530fdc8d8SChris Lattner 
42630fdc8d8SChris Lattner         lldb::pid_t pid;
42730fdc8d8SChris Lattner         std::string plugin_name;
42830fdc8d8SChris Lattner         std::string name;
42930fdc8d8SChris Lattner         bool waitfor;
43030fdc8d8SChris Lattner     };
43130fdc8d8SChris Lattner 
432a7015092SGreg Clayton     CommandObjectProcessAttach (CommandInterpreter &interpreter) :
433a7015092SGreg Clayton         CommandObject (interpreter,
434a7015092SGreg Clayton                        "process attach",
435e3d26315SCaroline Tice                        "Attach to a process.",
4365aee162fSJim Ingham                        "process attach <cmd-options>")
4375aee162fSJim Ingham     {
4385aee162fSJim Ingham     }
4395aee162fSJim Ingham 
4405aee162fSJim Ingham     ~CommandObjectProcessAttach ()
4415aee162fSJim Ingham     {
4425aee162fSJim Ingham     }
4435aee162fSJim Ingham 
4445aee162fSJim Ingham     bool
445a7015092SGreg Clayton     Execute (Args& command,
4465aee162fSJim Ingham              CommandReturnObject &result)
4475aee162fSJim Ingham     {
448a7015092SGreg Clayton         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
4495aee162fSJim Ingham 
450a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
4515aee162fSJim Ingham         if (process)
4525aee162fSJim Ingham         {
4535aee162fSJim Ingham             if (process->IsAlive())
4545aee162fSJim Ingham             {
4555aee162fSJim Ingham                 result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before attaching.\n",
4565aee162fSJim Ingham                                               process->GetID());
4575aee162fSJim Ingham                 result.SetStatus (eReturnStatusFailed);
4585aee162fSJim Ingham                 return false;
4595aee162fSJim Ingham             }
4605aee162fSJim Ingham         }
4615aee162fSJim Ingham 
4625aee162fSJim Ingham         if (target == NULL)
4635aee162fSJim Ingham         {
4645aee162fSJim Ingham             // If there isn't a current target create one.
4655aee162fSJim Ingham             TargetSP new_target_sp;
4665aee162fSJim Ingham             FileSpec emptyFileSpec;
4675aee162fSJim Ingham             ArchSpec emptyArchSpec;
4685aee162fSJim Ingham             Error error;
4695aee162fSJim Ingham 
470a7015092SGreg Clayton             error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(),
4715aee162fSJim Ingham                                                                               emptyFileSpec,
4725aee162fSJim Ingham                                                                               emptyArchSpec,
4735aee162fSJim Ingham                                                                               NULL,
4745aee162fSJim Ingham                                                                               false,
4755aee162fSJim Ingham                                                                               new_target_sp);
4765aee162fSJim Ingham             target = new_target_sp.get();
4775aee162fSJim Ingham             if (target == NULL || error.Fail())
4785aee162fSJim Ingham             {
4795aee162fSJim Ingham                 result.AppendError(error.AsCString("Error creating empty target"));
4805aee162fSJim Ingham                 return false;
4815aee162fSJim Ingham             }
482a7015092SGreg Clayton             m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target);
4835aee162fSJim Ingham         }
4845aee162fSJim Ingham 
4855aee162fSJim Ingham         // Record the old executable module, we want to issue a warning if the process of attaching changed the
4865aee162fSJim Ingham         // current executable (like somebody said "file foo" then attached to a PID whose executable was bar.)
4875aee162fSJim Ingham 
4885aee162fSJim Ingham         ModuleSP old_exec_module_sp = target->GetExecutableModule();
4895aee162fSJim Ingham         ArchSpec old_arch_spec = target->GetArchitecture();
4905aee162fSJim Ingham 
4915aee162fSJim Ingham         if (command.GetArgumentCount())
4925aee162fSJim Ingham         {
4935aee162fSJim Ingham             result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
4945aee162fSJim Ingham             result.SetStatus (eReturnStatusFailed);
4955aee162fSJim Ingham         }
4965aee162fSJim Ingham         else
4975aee162fSJim Ingham         {
4985aee162fSJim Ingham             const char *plugin_name = NULL;
4995aee162fSJim Ingham 
5005aee162fSJim Ingham             if (!m_options.plugin_name.empty())
5015aee162fSJim Ingham                 plugin_name = m_options.plugin_name.c_str();
5025aee162fSJim Ingham 
503a7015092SGreg Clayton             process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
5045aee162fSJim Ingham 
5055aee162fSJim Ingham             if (process)
5065aee162fSJim Ingham             {
5075aee162fSJim Ingham                 Error error;
5085aee162fSJim Ingham                 int attach_pid = m_options.pid;
5095aee162fSJim Ingham 
5103a0b9cdfSJim Ingham                 const char *wait_name = NULL;
5113a0b9cdfSJim Ingham 
5125aee162fSJim Ingham                 if (m_options.name.empty())
5135aee162fSJim Ingham                 {
5143a0b9cdfSJim Ingham                     if (old_exec_module_sp)
5153a0b9cdfSJim Ingham                     {
5163a0b9cdfSJim Ingham                         wait_name = old_exec_module_sp->GetFileSpec().GetFilename().AsCString();
5173a0b9cdfSJim Ingham                     }
5185aee162fSJim Ingham                 }
5195aee162fSJim Ingham                 else
5205aee162fSJim Ingham                 {
5213a0b9cdfSJim Ingham                     wait_name = m_options.name.c_str();
5223a0b9cdfSJim Ingham                 }
5233a0b9cdfSJim Ingham 
5243a0b9cdfSJim Ingham                 // If we are waiting for a process with this name to show up, do that first.
5253a0b9cdfSJim Ingham                 if (m_options.waitfor)
5263a0b9cdfSJim Ingham                 {
5273a0b9cdfSJim Ingham 
5283a0b9cdfSJim Ingham                     if (wait_name == NULL)
5293a0b9cdfSJim Ingham                     {
5303a0b9cdfSJim Ingham                         result.AppendError("Invalid arguments: must have a file loaded or supply a process name with the waitfor option.\n");
5313a0b9cdfSJim Ingham                         result.SetStatus (eReturnStatusFailed);
5323a0b9cdfSJim Ingham                         return false;
5333a0b9cdfSJim Ingham                     }
5343a0b9cdfSJim Ingham 
535a7015092SGreg Clayton                     m_interpreter.GetDebugger().GetOutputStream().Printf("Waiting to attach to a process named \"%s\".\n", wait_name);
5363a0b9cdfSJim Ingham                     error = process->Attach (wait_name, m_options.waitfor);
5375aee162fSJim Ingham                     if (error.Success())
5385aee162fSJim Ingham                     {
5395aee162fSJim Ingham                         result.SetStatus (eReturnStatusSuccessContinuingNoResult);
5405aee162fSJim Ingham                     }
5415aee162fSJim Ingham                     else
5425aee162fSJim Ingham                     {
5435aee162fSJim Ingham                         result.AppendErrorWithFormat ("Waiting for a process to launch named '%s': %s\n",
5443a0b9cdfSJim Ingham                                                          wait_name,
5455aee162fSJim Ingham                                                          error.AsCString());
5465aee162fSJim Ingham                         result.SetStatus (eReturnStatusFailed);
5475aee162fSJim Ingham                         return false;
5485aee162fSJim Ingham                     }
5495aee162fSJim Ingham                 }
5505aee162fSJim Ingham                 else
5515aee162fSJim Ingham                 {
5525aee162fSJim Ingham                     // If the process was specified by name look it up, so we can warn if there are multiple
5535aee162fSJim Ingham                     // processes with this pid.
5545aee162fSJim Ingham 
5553a0b9cdfSJim Ingham                     if (attach_pid == LLDB_INVALID_PROCESS_ID && wait_name != NULL)
5565aee162fSJim Ingham                     {
5575aee162fSJim Ingham                         std::vector<lldb::pid_t> pids;
5585aee162fSJim Ingham                         StringList matches;
5595aee162fSJim Ingham 
5603a0b9cdfSJim Ingham                         process->ListProcessesMatchingName(wait_name, matches, pids);
5615aee162fSJim Ingham                         if (matches.GetSize() > 1)
5625aee162fSJim Ingham                         {
5633a0b9cdfSJim Ingham                             result.AppendErrorWithFormat("More than one process named %s\n", wait_name);
5645aee162fSJim Ingham                             result.SetStatus (eReturnStatusFailed);
5655aee162fSJim Ingham                             return false;
5665aee162fSJim Ingham                         }
5675aee162fSJim Ingham                         else if (matches.GetSize() == 0)
5685aee162fSJim Ingham                         {
5693a0b9cdfSJim Ingham                             result.AppendErrorWithFormat("Could not find a process named %s\n", wait_name);
5705aee162fSJim Ingham                             result.SetStatus (eReturnStatusFailed);
5715aee162fSJim Ingham                             return false;
5725aee162fSJim Ingham                         }
5735aee162fSJim Ingham                         else
5745aee162fSJim Ingham                         {
5755aee162fSJim Ingham                             attach_pid = pids[0];
5765aee162fSJim Ingham                         }
5775aee162fSJim Ingham 
5785aee162fSJim Ingham                     }
5795aee162fSJim Ingham 
5805aee162fSJim Ingham                     if (attach_pid != LLDB_INVALID_PROCESS_ID)
5815aee162fSJim Ingham                     {
5825aee162fSJim Ingham                         error = process->Attach (attach_pid);
5835aee162fSJim Ingham                         if (error.Success())
5845aee162fSJim Ingham                         {
5855aee162fSJim Ingham                             result.SetStatus (eReturnStatusSuccessContinuingNoResult);
5865aee162fSJim Ingham                         }
5875aee162fSJim Ingham                         else
5885aee162fSJim Ingham                         {
5895aee162fSJim Ingham                             result.AppendErrorWithFormat ("Attaching to process %i failed: %s.\n",
5905aee162fSJim Ingham                                                          attach_pid,
5915aee162fSJim Ingham                                                          error.AsCString());
5925aee162fSJim Ingham                             result.SetStatus (eReturnStatusFailed);
5935aee162fSJim Ingham                         }
5945aee162fSJim Ingham                     }
5955aee162fSJim Ingham                     else
5965aee162fSJim Ingham                     {
5975aee162fSJim Ingham                         result.AppendErrorWithFormat ("No PID specified for attach\n",
5985aee162fSJim Ingham                                                          attach_pid,
5995aee162fSJim Ingham                                                          error.AsCString());
6005aee162fSJim Ingham                         result.SetStatus (eReturnStatusFailed);
6015aee162fSJim Ingham 
6025aee162fSJim Ingham                     }
6035aee162fSJim Ingham                 }
6045aee162fSJim Ingham             }
6055aee162fSJim Ingham         }
6065aee162fSJim Ingham 
6075aee162fSJim Ingham         if (result.Succeeded())
6085aee162fSJim Ingham         {
6095aee162fSJim Ingham             // Okay, we're done.  Last step is to warn if the executable module has changed:
6105aee162fSJim Ingham             if (!old_exec_module_sp)
6115aee162fSJim Ingham             {
6125aee162fSJim Ingham                 char new_path[PATH_MAX + 1];
6135aee162fSJim Ingham                 target->GetExecutableModule()->GetFileSpec().GetPath(new_path, PATH_MAX);
6145aee162fSJim Ingham 
6155aee162fSJim Ingham                 result.AppendMessageWithFormat("Executable module set to \"%s\".\n",
6165aee162fSJim Ingham                     new_path);
6175aee162fSJim Ingham             }
6185aee162fSJim Ingham             else if (old_exec_module_sp->GetFileSpec() != target->GetExecutableModule()->GetFileSpec())
6195aee162fSJim Ingham             {
6205aee162fSJim Ingham                 char old_path[PATH_MAX + 1];
6215aee162fSJim Ingham                 char new_path[PATH_MAX + 1];
6225aee162fSJim Ingham 
6235aee162fSJim Ingham                 old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX);
6245aee162fSJim Ingham                 target->GetExecutableModule()->GetFileSpec().GetPath (new_path, PATH_MAX);
6255aee162fSJim Ingham 
6265aee162fSJim Ingham                 result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n",
6275aee162fSJim Ingham                                                     old_path, new_path);
6285aee162fSJim Ingham             }
6295aee162fSJim Ingham 
6305aee162fSJim Ingham             if (!old_arch_spec.IsValid())
6315aee162fSJim Ingham             {
6325aee162fSJim Ingham                 result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().AsCString());
6335aee162fSJim Ingham             }
6345aee162fSJim Ingham             else if (old_arch_spec != target->GetArchitecture())
6355aee162fSJim Ingham             {
6365aee162fSJim Ingham                 result.AppendWarningWithFormat("Architecture changed from %s to %s.\n",
6375aee162fSJim Ingham                                                 old_arch_spec.AsCString(), target->GetArchitecture().AsCString());
6385aee162fSJim Ingham             }
6395aee162fSJim Ingham         }
6405aee162fSJim Ingham         return result.Succeeded();
6415aee162fSJim Ingham     }
6425aee162fSJim Ingham 
6435aee162fSJim Ingham     Options *
6445aee162fSJim Ingham     GetOptions ()
6455aee162fSJim Ingham     {
6465aee162fSJim Ingham         return &m_options;
6475aee162fSJim Ingham     }
6485aee162fSJim Ingham 
64930fdc8d8SChris Lattner protected:
65030fdc8d8SChris Lattner 
65130fdc8d8SChris Lattner     CommandOptions m_options;
65230fdc8d8SChris Lattner };
65330fdc8d8SChris Lattner 
65430fdc8d8SChris Lattner 
65530fdc8d8SChris Lattner lldb::OptionDefinition
65630fdc8d8SChris Lattner CommandObjectProcessAttach::CommandOptions::g_option_table[] =
65730fdc8d8SChris Lattner {
658deaab222SCaroline Tice { LLDB_OPT_SET_ALL, false, "plugin", 'P', required_argument, NULL, 0, eArgTypePlugin,        "Name of the process plugin you want to use."},
659deaab222SCaroline Tice { LLDB_OPT_SET_1,   false, "pid",    'p', required_argument, NULL, 0, eArgTypePid,           "The process ID of an existing process to attach to."},
660deaab222SCaroline Tice { LLDB_OPT_SET_2,   false, "name",   'n', required_argument, NULL, 0, eArgTypeProcessName,  "The name of the process to attach to."},
661deaab222SCaroline Tice { LLDB_OPT_SET_2,   false, "waitfor",'w', no_argument,       NULL, 0, eArgTypeNone,              "Wait for the the process with <process-name> to launch."},
662deaab222SCaroline Tice { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
66330fdc8d8SChris Lattner };
66430fdc8d8SChris Lattner 
66530fdc8d8SChris Lattner //-------------------------------------------------------------------------
66630fdc8d8SChris Lattner // CommandObjectProcessContinue
66730fdc8d8SChris Lattner //-------------------------------------------------------------------------
66830fdc8d8SChris Lattner 
66930fdc8d8SChris Lattner class CommandObjectProcessContinue : public CommandObject
67030fdc8d8SChris Lattner {
67130fdc8d8SChris Lattner public:
67230fdc8d8SChris Lattner 
673a7015092SGreg Clayton     CommandObjectProcessContinue (CommandInterpreter &interpreter) :
674a7015092SGreg Clayton         CommandObject (interpreter,
675a7015092SGreg Clayton                        "process continue",
676e3d26315SCaroline Tice                        "Continue execution of all threads in the current process.",
67730fdc8d8SChris Lattner                        "process continue",
67830fdc8d8SChris Lattner                        eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
67930fdc8d8SChris Lattner     {
68030fdc8d8SChris Lattner     }
68130fdc8d8SChris Lattner 
68230fdc8d8SChris Lattner 
68330fdc8d8SChris Lattner     ~CommandObjectProcessContinue ()
68430fdc8d8SChris Lattner     {
68530fdc8d8SChris Lattner     }
68630fdc8d8SChris Lattner 
68730fdc8d8SChris Lattner     bool
688a7015092SGreg Clayton     Execute (Args& command,
68930fdc8d8SChris Lattner              CommandReturnObject &result)
69030fdc8d8SChris Lattner     {
691a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
692a7015092SGreg Clayton         bool synchronous_execution = m_interpreter.GetSynchronous ();
69330fdc8d8SChris Lattner 
69430fdc8d8SChris Lattner         if (process == NULL)
69530fdc8d8SChris Lattner         {
69630fdc8d8SChris Lattner             result.AppendError ("no process to continue");
69730fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
69830fdc8d8SChris Lattner             return false;
69930fdc8d8SChris Lattner          }
70030fdc8d8SChris Lattner 
70130fdc8d8SChris Lattner         StateType state = process->GetState();
70230fdc8d8SChris Lattner         if (state == eStateStopped)
70330fdc8d8SChris Lattner         {
70430fdc8d8SChris Lattner             if (command.GetArgumentCount() != 0)
70530fdc8d8SChris Lattner             {
70630fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str());
70730fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
70830fdc8d8SChris Lattner                 return false;
70930fdc8d8SChris Lattner             }
71030fdc8d8SChris Lattner 
71130fdc8d8SChris Lattner             const uint32_t num_threads = process->GetThreadList().GetSize();
71230fdc8d8SChris Lattner 
71330fdc8d8SChris Lattner             // Set the actions that the threads should each take when resuming
71430fdc8d8SChris Lattner             for (uint32_t idx=0; idx<num_threads; ++idx)
71530fdc8d8SChris Lattner             {
71630fdc8d8SChris Lattner                 process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning);
71730fdc8d8SChris Lattner             }
71830fdc8d8SChris Lattner 
71930fdc8d8SChris Lattner             Error error(process->Resume());
72030fdc8d8SChris Lattner             if (error.Success())
72130fdc8d8SChris Lattner             {
72230fdc8d8SChris Lattner                 result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID());
72330fdc8d8SChris Lattner                 if (synchronous_execution)
72430fdc8d8SChris Lattner                 {
725b132097bSGreg Clayton                     state = process->WaitForProcessToStop (NULL);
72630fdc8d8SChris Lattner 
72730fdc8d8SChris Lattner                     result.SetDidChangeProcessState (true);
72830fdc8d8SChris Lattner                     result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
72930fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
73030fdc8d8SChris Lattner                 }
73130fdc8d8SChris Lattner                 else
73230fdc8d8SChris Lattner                 {
73330fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusSuccessContinuingNoResult);
73430fdc8d8SChris Lattner                 }
73530fdc8d8SChris Lattner             }
73630fdc8d8SChris Lattner             else
73730fdc8d8SChris Lattner             {
73830fdc8d8SChris Lattner                 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
73930fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
74030fdc8d8SChris Lattner             }
74130fdc8d8SChris Lattner         }
74230fdc8d8SChris Lattner         else
74330fdc8d8SChris Lattner         {
74430fdc8d8SChris Lattner             result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
74530fdc8d8SChris Lattner                                          StateAsCString(state));
74630fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
74730fdc8d8SChris Lattner         }
74830fdc8d8SChris Lattner         return result.Succeeded();
74930fdc8d8SChris Lattner     }
75030fdc8d8SChris Lattner };
75130fdc8d8SChris Lattner 
75230fdc8d8SChris Lattner //-------------------------------------------------------------------------
75330fdc8d8SChris Lattner // CommandObjectProcessDetach
75430fdc8d8SChris Lattner //-------------------------------------------------------------------------
75530fdc8d8SChris Lattner 
75630fdc8d8SChris Lattner class CommandObjectProcessDetach : public CommandObject
75730fdc8d8SChris Lattner {
75830fdc8d8SChris Lattner public:
75930fdc8d8SChris Lattner 
760a7015092SGreg Clayton     CommandObjectProcessDetach (CommandInterpreter &interpreter) :
761a7015092SGreg Clayton         CommandObject (interpreter,
762a7015092SGreg Clayton                        "process detach",
763e3d26315SCaroline Tice                        "Detach from the current process being debugged.",
76430fdc8d8SChris Lattner                        "process detach",
76530fdc8d8SChris Lattner                        eFlagProcessMustBeLaunched)
76630fdc8d8SChris Lattner     {
76730fdc8d8SChris Lattner     }
76830fdc8d8SChris Lattner 
76930fdc8d8SChris Lattner     ~CommandObjectProcessDetach ()
77030fdc8d8SChris Lattner     {
77130fdc8d8SChris Lattner     }
77230fdc8d8SChris Lattner 
77330fdc8d8SChris Lattner     bool
774a7015092SGreg Clayton     Execute (Args& command,
77530fdc8d8SChris Lattner              CommandReturnObject &result)
77630fdc8d8SChris Lattner     {
777a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
77830fdc8d8SChris Lattner         if (process == NULL)
77930fdc8d8SChris Lattner         {
78030fdc8d8SChris Lattner             result.AppendError ("must have a valid process in order to detach");
78130fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
78230fdc8d8SChris Lattner             return false;
78330fdc8d8SChris Lattner         }
78430fdc8d8SChris Lattner 
78530fdc8d8SChris Lattner         Error error (process->Detach());
78630fdc8d8SChris Lattner         if (error.Success())
78730fdc8d8SChris Lattner         {
78830fdc8d8SChris Lattner             result.SetStatus (eReturnStatusSuccessFinishResult);
78930fdc8d8SChris Lattner         }
79030fdc8d8SChris Lattner         else
79130fdc8d8SChris Lattner         {
79230fdc8d8SChris Lattner             result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString());
79330fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
79430fdc8d8SChris Lattner             return false;
79530fdc8d8SChris Lattner         }
79630fdc8d8SChris Lattner         return result.Succeeded();
79730fdc8d8SChris Lattner     }
79830fdc8d8SChris Lattner };
79930fdc8d8SChris Lattner 
80030fdc8d8SChris Lattner //-------------------------------------------------------------------------
80130fdc8d8SChris Lattner // CommandObjectProcessSignal
80230fdc8d8SChris Lattner //-------------------------------------------------------------------------
80330fdc8d8SChris Lattner 
80430fdc8d8SChris Lattner class CommandObjectProcessSignal : public CommandObject
80530fdc8d8SChris Lattner {
80630fdc8d8SChris Lattner public:
80730fdc8d8SChris Lattner 
808a7015092SGreg Clayton     CommandObjectProcessSignal (CommandInterpreter &interpreter) :
809a7015092SGreg Clayton         CommandObject (interpreter,
810a7015092SGreg Clayton                        "process signal",
811e3d26315SCaroline Tice                        "Send a UNIX signal to the current process being debugged.",
812*405fe67fSCaroline Tice                        NULL)
81330fdc8d8SChris Lattner     {
814*405fe67fSCaroline Tice         CommandArgumentEntry arg;
815*405fe67fSCaroline Tice         CommandArgumentData signal_arg;
816*405fe67fSCaroline Tice 
817*405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
818*405fe67fSCaroline Tice         signal_arg.arg_type = eArgTypeUnixSignalNumber;
819*405fe67fSCaroline Tice         signal_arg.arg_repetition = eArgRepeatPlain;
820*405fe67fSCaroline Tice 
821*405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
822*405fe67fSCaroline Tice         arg.push_back (signal_arg);
823*405fe67fSCaroline Tice 
824*405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
825*405fe67fSCaroline Tice         m_arguments.push_back (arg);
82630fdc8d8SChris Lattner     }
82730fdc8d8SChris Lattner 
82830fdc8d8SChris Lattner     ~CommandObjectProcessSignal ()
82930fdc8d8SChris Lattner     {
83030fdc8d8SChris Lattner     }
83130fdc8d8SChris Lattner 
83230fdc8d8SChris Lattner     bool
833a7015092SGreg Clayton     Execute (Args& command,
83430fdc8d8SChris Lattner              CommandReturnObject &result)
83530fdc8d8SChris Lattner     {
836a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
83730fdc8d8SChris Lattner         if (process == NULL)
83830fdc8d8SChris Lattner         {
83930fdc8d8SChris Lattner             result.AppendError ("no process to signal");
84030fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
84130fdc8d8SChris Lattner             return false;
84230fdc8d8SChris Lattner         }
84330fdc8d8SChris Lattner 
84430fdc8d8SChris Lattner         if (command.GetArgumentCount() == 1)
84530fdc8d8SChris Lattner         {
84630fdc8d8SChris Lattner             int signo = Args::StringToSInt32(command.GetArgumentAtIndex(0), -1, 0);
84730fdc8d8SChris Lattner             if (signo == -1)
84830fdc8d8SChris Lattner             {
84930fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0));
85030fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
85130fdc8d8SChris Lattner             }
85230fdc8d8SChris Lattner             else
85330fdc8d8SChris Lattner             {
85430fdc8d8SChris Lattner                 Error error (process->Signal (signo));
85530fdc8d8SChris Lattner                 if (error.Success())
85630fdc8d8SChris Lattner                 {
85730fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusSuccessFinishResult);
85830fdc8d8SChris Lattner                 }
85930fdc8d8SChris Lattner                 else
86030fdc8d8SChris Lattner                 {
86130fdc8d8SChris Lattner                     result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString());
86230fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusFailed);
86330fdc8d8SChris Lattner                 }
86430fdc8d8SChris Lattner             }
86530fdc8d8SChris Lattner         }
86630fdc8d8SChris Lattner         else
86730fdc8d8SChris Lattner         {
86830fdc8d8SChris Lattner             result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: \n", m_cmd_name.c_str(),
86930fdc8d8SChris Lattner                                         m_cmd_syntax.c_str());
87030fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
87130fdc8d8SChris Lattner         }
87230fdc8d8SChris Lattner         return result.Succeeded();
87330fdc8d8SChris Lattner     }
87430fdc8d8SChris Lattner };
87530fdc8d8SChris Lattner 
87630fdc8d8SChris Lattner 
87730fdc8d8SChris Lattner //-------------------------------------------------------------------------
87830fdc8d8SChris Lattner // CommandObjectProcessInterrupt
87930fdc8d8SChris Lattner //-------------------------------------------------------------------------
88030fdc8d8SChris Lattner 
88130fdc8d8SChris Lattner class CommandObjectProcessInterrupt : public CommandObject
88230fdc8d8SChris Lattner {
88330fdc8d8SChris Lattner public:
88430fdc8d8SChris Lattner 
88530fdc8d8SChris Lattner 
886a7015092SGreg Clayton     CommandObjectProcessInterrupt (CommandInterpreter &interpreter) :
887a7015092SGreg Clayton     CommandObject (interpreter,
888a7015092SGreg Clayton                    "process interrupt",
889e3d26315SCaroline Tice                    "Interrupt the current process being debugged.",
89030fdc8d8SChris Lattner                    "process interrupt",
89130fdc8d8SChris Lattner                    eFlagProcessMustBeLaunched)
89230fdc8d8SChris Lattner     {
89330fdc8d8SChris Lattner     }
89430fdc8d8SChris Lattner 
89530fdc8d8SChris Lattner     ~CommandObjectProcessInterrupt ()
89630fdc8d8SChris Lattner     {
89730fdc8d8SChris Lattner     }
89830fdc8d8SChris Lattner 
89930fdc8d8SChris Lattner     bool
900a7015092SGreg Clayton     Execute (Args& command,
90130fdc8d8SChris Lattner              CommandReturnObject &result)
90230fdc8d8SChris Lattner     {
903a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
90430fdc8d8SChris Lattner         if (process == NULL)
90530fdc8d8SChris Lattner         {
90630fdc8d8SChris Lattner             result.AppendError ("no process to halt");
90730fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
90830fdc8d8SChris Lattner             return false;
90930fdc8d8SChris Lattner         }
91030fdc8d8SChris Lattner 
91130fdc8d8SChris Lattner         if (command.GetArgumentCount() == 0)
91230fdc8d8SChris Lattner         {
91330fdc8d8SChris Lattner             Error error(process->Halt ());
91430fdc8d8SChris Lattner             if (error.Success())
91530fdc8d8SChris Lattner             {
91630fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusSuccessFinishResult);
91730fdc8d8SChris Lattner 
91830fdc8d8SChris Lattner                 // Maybe we should add a "SuspendThreadPlans so we
91930fdc8d8SChris Lattner                 // can halt, and keep in place all the current thread plans.
92030fdc8d8SChris Lattner                 process->GetThreadList().DiscardThreadPlans();
92130fdc8d8SChris Lattner             }
92230fdc8d8SChris Lattner             else
92330fdc8d8SChris Lattner             {
92430fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString());
92530fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
92630fdc8d8SChris Lattner             }
92730fdc8d8SChris Lattner         }
92830fdc8d8SChris Lattner         else
92930fdc8d8SChris Lattner         {
93030fdc8d8SChris Lattner             result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
93130fdc8d8SChris Lattner                                         m_cmd_name.c_str(),
93230fdc8d8SChris Lattner                                         m_cmd_syntax.c_str());
93330fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
93430fdc8d8SChris Lattner         }
93530fdc8d8SChris Lattner         return result.Succeeded();
93630fdc8d8SChris Lattner     }
93730fdc8d8SChris Lattner };
93830fdc8d8SChris Lattner 
93930fdc8d8SChris Lattner //-------------------------------------------------------------------------
94030fdc8d8SChris Lattner // CommandObjectProcessKill
94130fdc8d8SChris Lattner //-------------------------------------------------------------------------
94230fdc8d8SChris Lattner 
94330fdc8d8SChris Lattner class CommandObjectProcessKill : public CommandObject
94430fdc8d8SChris Lattner {
94530fdc8d8SChris Lattner public:
94630fdc8d8SChris Lattner 
947a7015092SGreg Clayton     CommandObjectProcessKill (CommandInterpreter &interpreter) :
948a7015092SGreg Clayton     CommandObject (interpreter,
949a7015092SGreg Clayton                    "process kill",
950e3d26315SCaroline Tice                    "Terminate the current process being debugged.",
95130fdc8d8SChris Lattner                    "process kill",
95230fdc8d8SChris Lattner                    eFlagProcessMustBeLaunched)
95330fdc8d8SChris Lattner     {
95430fdc8d8SChris Lattner     }
95530fdc8d8SChris Lattner 
95630fdc8d8SChris Lattner     ~CommandObjectProcessKill ()
95730fdc8d8SChris Lattner     {
95830fdc8d8SChris Lattner     }
95930fdc8d8SChris Lattner 
96030fdc8d8SChris Lattner     bool
961a7015092SGreg Clayton     Execute (Args& command,
96230fdc8d8SChris Lattner              CommandReturnObject &result)
96330fdc8d8SChris Lattner     {
964a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
96530fdc8d8SChris Lattner         if (process == NULL)
96630fdc8d8SChris Lattner         {
96730fdc8d8SChris Lattner             result.AppendError ("no process to kill");
96830fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
96930fdc8d8SChris Lattner             return false;
97030fdc8d8SChris Lattner         }
97130fdc8d8SChris Lattner 
97230fdc8d8SChris Lattner         if (command.GetArgumentCount() == 0)
97330fdc8d8SChris Lattner         {
97430fdc8d8SChris Lattner             Error error (process->Destroy());
97530fdc8d8SChris Lattner             if (error.Success())
97630fdc8d8SChris Lattner             {
97730fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusSuccessFinishResult);
97830fdc8d8SChris Lattner             }
97930fdc8d8SChris Lattner             else
98030fdc8d8SChris Lattner             {
98130fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString());
98230fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
98330fdc8d8SChris Lattner             }
98430fdc8d8SChris Lattner         }
98530fdc8d8SChris Lattner         else
98630fdc8d8SChris Lattner         {
98730fdc8d8SChris Lattner             result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
98830fdc8d8SChris Lattner                                         m_cmd_name.c_str(),
98930fdc8d8SChris Lattner                                         m_cmd_syntax.c_str());
99030fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
99130fdc8d8SChris Lattner         }
99230fdc8d8SChris Lattner         return result.Succeeded();
99330fdc8d8SChris Lattner     }
99430fdc8d8SChris Lattner };
99530fdc8d8SChris Lattner 
99630fdc8d8SChris Lattner //-------------------------------------------------------------------------
9974b9bea87SJim Ingham // CommandObjectProcessStatus
9984b9bea87SJim Ingham //-------------------------------------------------------------------------
9994b9bea87SJim Ingham class CommandObjectProcessStatus : public CommandObject
10004b9bea87SJim Ingham {
10014b9bea87SJim Ingham public:
1002a7015092SGreg Clayton     CommandObjectProcessStatus (CommandInterpreter &interpreter) :
1003a7015092SGreg Clayton     CommandObject (interpreter,
1004a7015092SGreg Clayton                    "process status",
1005e3d26315SCaroline Tice                    "Show the current status and location of executing process.",
1006e3d26315SCaroline Tice                    "process status",
10074b9bea87SJim Ingham                    0)
10084b9bea87SJim Ingham     {
10094b9bea87SJim Ingham     }
10104b9bea87SJim Ingham 
10114b9bea87SJim Ingham     ~CommandObjectProcessStatus()
10124b9bea87SJim Ingham     {
10134b9bea87SJim Ingham     }
10144b9bea87SJim Ingham 
10154b9bea87SJim Ingham 
10164b9bea87SJim Ingham     bool
10174b9bea87SJim Ingham     Execute
10184b9bea87SJim Ingham     (
10194b9bea87SJim Ingham         Args& command,
10204b9bea87SJim Ingham         CommandReturnObject &result
10214b9bea87SJim Ingham     )
10224b9bea87SJim Ingham     {
10234b9bea87SJim Ingham         StreamString &output_stream = result.GetOutputStream();
10244b9bea87SJim Ingham         result.SetStatus (eReturnStatusSuccessFinishNoResult);
1025a7015092SGreg Clayton         ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
10264b9bea87SJim Ingham         if (exe_ctx.process)
10274b9bea87SJim Ingham         {
10284b9bea87SJim Ingham             const StateType state = exe_ctx.process->GetState();
10294b9bea87SJim Ingham             if (StateIsStoppedState(state))
10304b9bea87SJim Ingham             {
10314b9bea87SJim Ingham                 if (state == eStateExited)
10324b9bea87SJim Ingham                 {
10334b9bea87SJim Ingham                     int exit_status = exe_ctx.process->GetExitStatus();
10344b9bea87SJim Ingham                     const char *exit_description = exe_ctx.process->GetExitDescription();
10354b9bea87SJim Ingham                     output_stream.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n",
10364b9bea87SJim Ingham                                           exe_ctx.process->GetID(),
10374b9bea87SJim Ingham                                           exit_status,
10384b9bea87SJim Ingham                                           exit_status,
10394b9bea87SJim Ingham                                           exit_description ? exit_description : "");
10404b9bea87SJim Ingham                 }
10414b9bea87SJim Ingham                 else
10424b9bea87SJim Ingham                 {
10434b9bea87SJim Ingham                     output_stream.Printf ("Process %d %s\n", exe_ctx.process->GetID(), StateAsCString (state));
10444b9bea87SJim Ingham                     if (exe_ctx.thread == NULL)
10454b9bea87SJim Ingham                         exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
10464b9bea87SJim Ingham                     if (exe_ctx.thread != NULL)
10474b9bea87SJim Ingham                     {
1048a7015092SGreg Clayton                         DisplayThreadsInfo (m_interpreter, &exe_ctx, result, true, true);
10494b9bea87SJim Ingham                     }
10504b9bea87SJim Ingham                     else
10514b9bea87SJim Ingham                     {
10524b9bea87SJim Ingham                         result.AppendError ("No valid thread found in current process.");
10534b9bea87SJim Ingham                         result.SetStatus (eReturnStatusFailed);
10544b9bea87SJim Ingham                     }
10554b9bea87SJim Ingham                 }
10564b9bea87SJim Ingham             }
10574b9bea87SJim Ingham             else
10584b9bea87SJim Ingham             {
10594b9bea87SJim Ingham                 output_stream.Printf ("Process %d is running.\n",
10604b9bea87SJim Ingham                                           exe_ctx.process->GetID());
10614b9bea87SJim Ingham             }
10624b9bea87SJim Ingham         }
10634b9bea87SJim Ingham         else
10644b9bea87SJim Ingham         {
10654b9bea87SJim Ingham             result.AppendError ("No current location or status available.");
10664b9bea87SJim Ingham             result.SetStatus (eReturnStatusFailed);
10674b9bea87SJim Ingham         }
10684b9bea87SJim Ingham         return result.Succeeded();
10694b9bea87SJim Ingham     }
10704b9bea87SJim Ingham };
10714b9bea87SJim Ingham 
10724b9bea87SJim Ingham //-------------------------------------------------------------------------
107330fdc8d8SChris Lattner // CommandObjectMultiwordProcess
107430fdc8d8SChris Lattner //-------------------------------------------------------------------------
107530fdc8d8SChris Lattner 
10766611103cSGreg Clayton CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter &interpreter) :
1077a7015092SGreg Clayton     CommandObjectMultiword (interpreter,
1078a7015092SGreg Clayton                             "process",
107930fdc8d8SChris Lattner                             "A set of commands for operating on a process.",
108030fdc8d8SChris Lattner                             "process <subcommand> [<subcommand-options>]")
108130fdc8d8SChris Lattner {
1082a7015092SGreg Clayton     LoadSubCommand ("attach",      CommandObjectSP (new CommandObjectProcessAttach (interpreter)));
1083a7015092SGreg Clayton     LoadSubCommand ("launch",      CommandObjectSP (new CommandObjectProcessLaunch (interpreter)));
1084a7015092SGreg Clayton     LoadSubCommand ("continue",    CommandObjectSP (new CommandObjectProcessContinue (interpreter)));
1085a7015092SGreg Clayton     LoadSubCommand ("detach",      CommandObjectSP (new CommandObjectProcessDetach (interpreter)));
1086a7015092SGreg Clayton     LoadSubCommand ("signal",      CommandObjectSP (new CommandObjectProcessSignal (interpreter)));
1087a7015092SGreg Clayton     LoadSubCommand ("status",      CommandObjectSP (new CommandObjectProcessStatus (interpreter)));
1088a7015092SGreg Clayton     LoadSubCommand ("interrupt",   CommandObjectSP (new CommandObjectProcessInterrupt (interpreter)));
1089a7015092SGreg Clayton     LoadSubCommand ("kill",        CommandObjectSP (new CommandObjectProcessKill (interpreter)));
109030fdc8d8SChris Lattner }
109130fdc8d8SChris Lattner 
109230fdc8d8SChris Lattner CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess ()
109330fdc8d8SChris Lattner {
109430fdc8d8SChris Lattner }
109530fdc8d8SChris Lattner 
1096