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"
21*4b9bea87SJim 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 
10430fdc8d8SChris Lattner     CommandObjectProcessLaunch () :
10530fdc8d8SChris Lattner         CommandObject ("process launch",
10630fdc8d8SChris Lattner                        "Launches the executable in the debugger.",
10730fdc8d8SChris Lattner                        "process launch [<cmd-options>] [<arguments-for-running-the-program>]")
10830fdc8d8SChris Lattner     {
10930fdc8d8SChris Lattner     }
11030fdc8d8SChris Lattner 
11130fdc8d8SChris Lattner 
11230fdc8d8SChris Lattner     ~CommandObjectProcessLaunch ()
11330fdc8d8SChris Lattner     {
11430fdc8d8SChris Lattner     }
11530fdc8d8SChris Lattner 
11630fdc8d8SChris Lattner     Options *
11730fdc8d8SChris Lattner     GetOptions ()
11830fdc8d8SChris Lattner     {
11930fdc8d8SChris Lattner         return &m_options;
12030fdc8d8SChris Lattner     }
12130fdc8d8SChris Lattner 
12230fdc8d8SChris Lattner     bool
12330fdc8d8SChris Lattner     Execute (Args& launch_args,
12430fdc8d8SChris Lattner              CommandContext *context,
12530fdc8d8SChris Lattner              CommandInterpreter *interpreter,
12630fdc8d8SChris Lattner              CommandReturnObject &result)
12730fdc8d8SChris Lattner     {
12830fdc8d8SChris Lattner         Target *target = context->GetTarget();
12930fdc8d8SChris Lattner         bool synchronous_execution = interpreter->GetSynchronous ();
13030fdc8d8SChris Lattner     //    bool launched = false;
13130fdc8d8SChris Lattner     //    bool stopped_after_launch = false;
13230fdc8d8SChris Lattner 
13330fdc8d8SChris Lattner         if (target == NULL)
13430fdc8d8SChris Lattner         {
13530fdc8d8SChris Lattner             result.AppendError ("invalid target, set executable file using 'file' command");
13630fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
13730fdc8d8SChris Lattner             return false;
13830fdc8d8SChris Lattner         }
13930fdc8d8SChris Lattner 
14030fdc8d8SChris Lattner         // If our listener is NULL, users aren't allows to launch
14130fdc8d8SChris Lattner         Listener *listener = interpreter->GetListener();
14230fdc8d8SChris Lattner         if (listener == NULL)
14330fdc8d8SChris Lattner         {
14430fdc8d8SChris Lattner             result.AppendError ("operation not allowed through the command interpreter");
14530fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
14630fdc8d8SChris Lattner             return false;
14730fdc8d8SChris Lattner         }
14830fdc8d8SChris Lattner 
14930fdc8d8SChris Lattner         char filename[PATH_MAX];
15030fdc8d8SChris Lattner         Module *exe_module = target->GetExecutableModule().get();
15130fdc8d8SChris Lattner         exe_module->GetFileSpec().GetPath(filename, sizeof(filename));
15230fdc8d8SChris Lattner 
15330fdc8d8SChris Lattner         Process *process = context->GetExecutionContext().process;
15430fdc8d8SChris Lattner         if (process)
15530fdc8d8SChris Lattner         {
15630fdc8d8SChris Lattner             if (process->IsAlive())
15730fdc8d8SChris Lattner             {
15830fdc8d8SChris Lattner                result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before running again.\n",
15930fdc8d8SChris Lattner                                             process->GetID());
16030fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
16130fdc8d8SChris Lattner                 return false;
16230fdc8d8SChris Lattner             }
16330fdc8d8SChris Lattner         }
16430fdc8d8SChris Lattner 
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 
17130fdc8d8SChris Lattner         process = target->CreateProcess (*listener, plugin_name).get();
17230fdc8d8SChris Lattner 
17330fdc8d8SChris Lattner         const Args *environment = interpreter->GetEnvironmentVariables();
17430fdc8d8SChris Lattner         const Args *run_args = interpreter->GetProgramArguments();
17530fdc8d8SChris Lattner 
17630fdc8d8SChris Lattner         // There are two possible sources of args to be passed to the process upon launching:  Those the user
17730fdc8d8SChris Lattner         // typed at the run command (launch_args); or those the user pre-set in the run-args variable (run_args).
17830fdc8d8SChris Lattner 
17930fdc8d8SChris Lattner         // If launch_args is empty, use run_args.
18030fdc8d8SChris Lattner         if (launch_args.GetArgumentCount() == 0)
18130fdc8d8SChris Lattner         {
18230fdc8d8SChris Lattner             if (run_args != NULL)
18330fdc8d8SChris Lattner                 launch_args.AppendArguments (*run_args);
18430fdc8d8SChris Lattner         }
18530fdc8d8SChris Lattner         else
18630fdc8d8SChris Lattner         {
18730fdc8d8SChris Lattner             // launch-args was not empty; use that, AND re-set run-args to contains launch-args values.
18830fdc8d8SChris Lattner             StateVariable *run_args_var = interpreter->GetStateVariable ("run-args");
18930fdc8d8SChris Lattner             if (run_args_var != NULL)
19030fdc8d8SChris Lattner             {
19130fdc8d8SChris Lattner                 run_args_var->ArrayClearValues();
19230fdc8d8SChris Lattner                 run_args_var->GetArgs().AppendArguments (launch_args);
19330fdc8d8SChris Lattner             }
19430fdc8d8SChris Lattner         }
19530fdc8d8SChris Lattner 
19630fdc8d8SChris Lattner 
19730fdc8d8SChris Lattner         if (process)
19830fdc8d8SChris Lattner         {
19930fdc8d8SChris Lattner             const char *archname = exe_module->GetArchitecture().AsCString();
20030fdc8d8SChris Lattner 
20130fdc8d8SChris Lattner             const char * stdin_path = NULL;
20230fdc8d8SChris Lattner             const char * stdout_path = NULL;
20330fdc8d8SChris Lattner             const char * stderr_path = NULL;
20430fdc8d8SChris Lattner 
20530fdc8d8SChris Lattner             if (!(m_options.stdin_path.empty() &&
20630fdc8d8SChris Lattner                 m_options.stdout_path.empty() &&
20730fdc8d8SChris Lattner                 m_options.stderr_path.empty()))
20830fdc8d8SChris Lattner             {
20930fdc8d8SChris Lattner                 stdin_path =    m_options.stdin_path.empty()  ? "/dev/null" : m_options.stdin_path.c_str();
21030fdc8d8SChris Lattner                 stdout_path =   m_options.stdout_path.empty() ? "/dev/null" : m_options.stdout_path.c_str();
21130fdc8d8SChris Lattner                 stderr_path =   m_options.stderr_path.empty() ? "/dev/null" : m_options.stderr_path.c_str();
21230fdc8d8SChris Lattner             }
21330fdc8d8SChris Lattner 
21430fdc8d8SChris Lattner             Error error (process->Launch (launch_args.GetConstArgumentVector(),
21530fdc8d8SChris Lattner                                           environment ? environment->GetConstArgumentVector() : NULL,
21630fdc8d8SChris Lattner                                           stdin_path,
21730fdc8d8SChris Lattner                                           stdout_path,
21830fdc8d8SChris Lattner                                           stderr_path));
21930fdc8d8SChris Lattner 
22030fdc8d8SChris Lattner             if (error.Success())
22130fdc8d8SChris Lattner             {
22230fdc8d8SChris Lattner                 result.AppendMessageWithFormat ("Launching '%s'  (%s)\n", filename, archname);
22330fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
22430fdc8d8SChris Lattner                 if (m_options.stop_at_entry == false)
22530fdc8d8SChris Lattner                 {
22630fdc8d8SChris Lattner                     StateType state = process->WaitForProcessToStop (NULL);
22730fdc8d8SChris Lattner 
22830fdc8d8SChris Lattner                     if (state == eStateStopped)
22930fdc8d8SChris Lattner                     {
23030fdc8d8SChris Lattner                         // Call continue_command.
23130fdc8d8SChris Lattner                         CommandReturnObject continue_result;
23230fdc8d8SChris Lattner                         interpreter->HandleCommand("process continue", false, continue_result);
23330fdc8d8SChris Lattner                     }
23430fdc8d8SChris Lattner 
23530fdc8d8SChris Lattner                     if (synchronous_execution)
23630fdc8d8SChris Lattner                     {
23730fdc8d8SChris Lattner                         result.SetDidChangeProcessState (true);
23830fdc8d8SChris Lattner                         result.SetStatus (eReturnStatusSuccessFinishNoResult);
23930fdc8d8SChris Lattner                     }
24030fdc8d8SChris Lattner                 }
24130fdc8d8SChris Lattner             }
24230fdc8d8SChris Lattner             else
24330fdc8d8SChris Lattner             {
24430fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("Process launch failed: %s",
24530fdc8d8SChris Lattner                                               error.AsCString());
24630fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
24730fdc8d8SChris Lattner             }
24830fdc8d8SChris Lattner         }
24930fdc8d8SChris Lattner         else
25030fdc8d8SChris Lattner         {
25130fdc8d8SChris Lattner             result.AppendErrorWithFormat ("Process launch failed: unable to create a process object.\n");
25230fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
25330fdc8d8SChris Lattner             return false;
25430fdc8d8SChris Lattner         }
25530fdc8d8SChris Lattner 
25630fdc8d8SChris Lattner         return result.Succeeded();
25730fdc8d8SChris Lattner     }
25830fdc8d8SChris Lattner 
25930fdc8d8SChris Lattner protected:
26030fdc8d8SChris Lattner 
26130fdc8d8SChris Lattner     CommandOptions m_options;
26230fdc8d8SChris Lattner };
26330fdc8d8SChris Lattner 
26430fdc8d8SChris Lattner 
26530fdc8d8SChris Lattner lldb::OptionDefinition
26630fdc8d8SChris Lattner CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
26730fdc8d8SChris Lattner {
2688651121cSJim Ingham { LLDB_OPT_SET_1, false, "stop-at-entry", 's', no_argument,       NULL, 0, NULL,        "Stop at the entry point of the program when launching a process."},
2698651121cSJim Ingham { LLDB_OPT_SET_1, false, "stdin",         'i', required_argument, NULL, 0, "<path>",    "Redirect stdin for the process to <path>."},
2708651121cSJim Ingham { LLDB_OPT_SET_1, false, "stdout",        'o', required_argument, NULL, 0, "<path>",    "Redirect stdout for the process to <path>."},
2718651121cSJim Ingham { LLDB_OPT_SET_1, false, "stderr",        'e', required_argument, NULL, 0, "<path>",    "Redirect stderr for the process to <path>."},
2728651121cSJim Ingham { LLDB_OPT_SET_1, false, "plugin",        'p', required_argument, NULL, 0, "<plugin>",  "Name of the process plugin you want to use."},
27330fdc8d8SChris Lattner { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
27430fdc8d8SChris Lattner };
27530fdc8d8SChris Lattner 
27630fdc8d8SChris Lattner 
27730fdc8d8SChris Lattner //-------------------------------------------------------------------------
27830fdc8d8SChris Lattner // CommandObjectProcessAttach
27930fdc8d8SChris Lattner //-------------------------------------------------------------------------
28030fdc8d8SChris Lattner 
28130fdc8d8SChris Lattner class CommandObjectProcessAttach : public CommandObject
28230fdc8d8SChris Lattner {
28330fdc8d8SChris Lattner public:
28430fdc8d8SChris Lattner 
28530fdc8d8SChris Lattner     CommandObjectProcessAttach () :
28630fdc8d8SChris Lattner         CommandObject ("process attach",
28730fdc8d8SChris Lattner                        "Attaches to a process.",
28830fdc8d8SChris Lattner                        "process attach <cmd-options>")
28930fdc8d8SChris Lattner     {
29030fdc8d8SChris Lattner         SetHelpLong("Currently, you must set the executable file before you can attach "
29130fdc8d8SChris Lattner                     "to a process.\n");
29230fdc8d8SChris Lattner     }
29330fdc8d8SChris Lattner 
29430fdc8d8SChris Lattner     ~CommandObjectProcessAttach ()
29530fdc8d8SChris Lattner     {
29630fdc8d8SChris Lattner     }
29730fdc8d8SChris Lattner 
29830fdc8d8SChris Lattner     bool
29930fdc8d8SChris Lattner     Execute (Args& command,
30030fdc8d8SChris Lattner              CommandContext *context,
30130fdc8d8SChris Lattner              CommandInterpreter *interpreter,
30230fdc8d8SChris Lattner              CommandReturnObject &result)
30330fdc8d8SChris Lattner     {
30430fdc8d8SChris Lattner         Target *target = context->GetTarget();
30530fdc8d8SChris Lattner         if (target == NULL)
30630fdc8d8SChris Lattner         {
30730fdc8d8SChris Lattner             result.AppendError ("invalid target, set executable file using 'file' command");
30830fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
30930fdc8d8SChris Lattner             return false;
31030fdc8d8SChris Lattner         }
31130fdc8d8SChris Lattner 
31230fdc8d8SChris Lattner         // If our listener is NULL, users aren't allows to launch
31330fdc8d8SChris Lattner         Listener *listener = interpreter->GetListener();
31430fdc8d8SChris Lattner         if (listener == NULL)
31530fdc8d8SChris Lattner         {
31630fdc8d8SChris Lattner             result.AppendError ("operation not allowed through the command interpreter");
31730fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
31830fdc8d8SChris Lattner             return false;
31930fdc8d8SChris Lattner         }
32030fdc8d8SChris Lattner         Process *process = context->GetExecutionContext().process;
32130fdc8d8SChris Lattner         if (process)
32230fdc8d8SChris Lattner         {
32330fdc8d8SChris Lattner             if (process->IsAlive())
32430fdc8d8SChris Lattner             {
32530fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before attaching.\n", process->GetID());
32630fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
32730fdc8d8SChris Lattner                 return false;
32830fdc8d8SChris Lattner             }
32930fdc8d8SChris Lattner         }
33030fdc8d8SChris Lattner 
33130fdc8d8SChris Lattner         if (command.GetArgumentCount())
33230fdc8d8SChris Lattner         {
33330fdc8d8SChris Lattner             result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
33430fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
33530fdc8d8SChris Lattner         }
33630fdc8d8SChris Lattner         else
33730fdc8d8SChris Lattner         {
33830fdc8d8SChris Lattner             const char *plugin_name = NULL;
33930fdc8d8SChris Lattner 
34030fdc8d8SChris Lattner             if (!m_options.plugin_name.empty())
34130fdc8d8SChris Lattner                 plugin_name = m_options.plugin_name.c_str();
34230fdc8d8SChris Lattner 
34330fdc8d8SChris Lattner             process = target->CreateProcess (*listener, plugin_name).get();
34430fdc8d8SChris Lattner 
34530fdc8d8SChris Lattner             if (process)
34630fdc8d8SChris Lattner             {
34730fdc8d8SChris Lattner                 Error error;
34830fdc8d8SChris Lattner                 int attach_pid = m_options.pid;
34930fdc8d8SChris Lattner 
35030fdc8d8SChris Lattner                 if (attach_pid != LLDB_INVALID_PROCESS_ID)
35130fdc8d8SChris Lattner                 {
35230fdc8d8SChris Lattner                     error = process->Attach (attach_pid);
35330fdc8d8SChris Lattner                     if (error.Success())
35430fdc8d8SChris Lattner                     {
35530fdc8d8SChris Lattner                         result.SetStatus (eReturnStatusSuccessContinuingNoResult);
35630fdc8d8SChris Lattner                     }
35730fdc8d8SChris Lattner                     else
35830fdc8d8SChris Lattner                     {
35930fdc8d8SChris Lattner                         result.AppendErrorWithFormat ("Attaching to process %i failed: %s.\n",
36030fdc8d8SChris Lattner                                                      attach_pid,
36130fdc8d8SChris Lattner                                                      error.AsCString());
36230fdc8d8SChris Lattner                         result.SetStatus (eReturnStatusFailed);
36330fdc8d8SChris Lattner                     }
36430fdc8d8SChris Lattner                 }
36530fdc8d8SChris Lattner                 else if (!m_options.name.empty())
36630fdc8d8SChris Lattner                 {
36730fdc8d8SChris Lattner                     error = process->Attach (m_options.name.c_str(), m_options.waitfor);
36830fdc8d8SChris Lattner                     if (error.Success())
36930fdc8d8SChris Lattner                     {
37030fdc8d8SChris Lattner                         result.SetStatus (eReturnStatusSuccessContinuingNoResult);
37130fdc8d8SChris Lattner                     }
37230fdc8d8SChris Lattner                     else
37330fdc8d8SChris Lattner                     {
37430fdc8d8SChris Lattner                         if (m_options.waitfor)
37530fdc8d8SChris Lattner                             result.AppendErrorWithFormat ("Waiting for a process to launch named '%s': %s\n",
37630fdc8d8SChris Lattner                                                          m_options.name.c_str(),
37730fdc8d8SChris Lattner                                                          error.AsCString());
37830fdc8d8SChris Lattner                         else
37930fdc8d8SChris Lattner                             result.AppendErrorWithFormat ("Failed to a process named '%s': %s\n",
38030fdc8d8SChris Lattner                                                          m_options.name.c_str(),
38130fdc8d8SChris Lattner                                                          error.AsCString());
38230fdc8d8SChris Lattner                         result.SetStatus (eReturnStatusFailed);
38330fdc8d8SChris Lattner                     }
38430fdc8d8SChris Lattner                 }
38530fdc8d8SChris Lattner             }
38630fdc8d8SChris Lattner         }
38730fdc8d8SChris Lattner         return result.Succeeded();
38830fdc8d8SChris Lattner     }
38930fdc8d8SChris Lattner 
39030fdc8d8SChris Lattner     Options *
39130fdc8d8SChris Lattner     GetOptions ()
39230fdc8d8SChris Lattner     {
39330fdc8d8SChris Lattner         return &m_options;
39430fdc8d8SChris Lattner     }
39530fdc8d8SChris Lattner 
39630fdc8d8SChris Lattner     class CommandOptions : public Options
39730fdc8d8SChris Lattner     {
39830fdc8d8SChris Lattner     public:
39930fdc8d8SChris Lattner 
40030fdc8d8SChris Lattner         CommandOptions () :
40130fdc8d8SChris Lattner             Options()
40230fdc8d8SChris Lattner         {
40330fdc8d8SChris Lattner             // Keep default values of all options in one place: ResetOptionValues ()
40430fdc8d8SChris Lattner             ResetOptionValues ();
40530fdc8d8SChris Lattner         }
40630fdc8d8SChris Lattner 
40730fdc8d8SChris Lattner         ~CommandOptions ()
40830fdc8d8SChris Lattner         {
40930fdc8d8SChris Lattner         }
41030fdc8d8SChris Lattner 
41130fdc8d8SChris Lattner         Error
41230fdc8d8SChris Lattner         SetOptionValue (int option_idx, const char *option_arg)
41330fdc8d8SChris Lattner         {
41430fdc8d8SChris Lattner             Error error;
41530fdc8d8SChris Lattner             char short_option = (char) m_getopt_table[option_idx].val;
41630fdc8d8SChris Lattner             bool success = false;
41730fdc8d8SChris Lattner             switch (short_option)
41830fdc8d8SChris Lattner             {
41930fdc8d8SChris Lattner                 case 'p':
42030fdc8d8SChris Lattner                     pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success);
42130fdc8d8SChris Lattner                     if (!success || pid == LLDB_INVALID_PROCESS_ID)
42230fdc8d8SChris Lattner                     {
42330fdc8d8SChris Lattner                         error.SetErrorStringWithFormat("Invalid process ID '%s'.\n", option_arg);
42430fdc8d8SChris Lattner                     }
42530fdc8d8SChris Lattner                     break;
42630fdc8d8SChris Lattner 
42730fdc8d8SChris Lattner                 case 'P':
42830fdc8d8SChris Lattner                     plugin_name = option_arg;
42930fdc8d8SChris Lattner                     break;
43030fdc8d8SChris Lattner 
43130fdc8d8SChris Lattner                 case 'n':
43230fdc8d8SChris Lattner                     name.assign(option_arg);
43330fdc8d8SChris Lattner                     break;
43430fdc8d8SChris Lattner 
43530fdc8d8SChris Lattner                 case 'w':
43630fdc8d8SChris Lattner                     waitfor = true;
43730fdc8d8SChris Lattner                     break;
43830fdc8d8SChris Lattner 
43930fdc8d8SChris Lattner                 default:
44030fdc8d8SChris Lattner                     error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
44130fdc8d8SChris Lattner                     break;
44230fdc8d8SChris Lattner             }
44330fdc8d8SChris Lattner             return error;
44430fdc8d8SChris Lattner         }
44530fdc8d8SChris Lattner 
44630fdc8d8SChris Lattner         void
44730fdc8d8SChris Lattner         ResetOptionValues ()
44830fdc8d8SChris Lattner         {
44930fdc8d8SChris Lattner             Options::ResetOptionValues();
45030fdc8d8SChris Lattner             pid = LLDB_INVALID_PROCESS_ID;
45130fdc8d8SChris Lattner             name.clear();
45230fdc8d8SChris Lattner             waitfor = false;
45330fdc8d8SChris Lattner         }
45430fdc8d8SChris Lattner 
45530fdc8d8SChris Lattner         const lldb::OptionDefinition*
45630fdc8d8SChris Lattner         GetDefinitions ()
45730fdc8d8SChris Lattner         {
45830fdc8d8SChris Lattner             return g_option_table;
45930fdc8d8SChris Lattner         }
46030fdc8d8SChris Lattner 
46130fdc8d8SChris Lattner         // Options table: Required for subclasses of Options.
46230fdc8d8SChris Lattner 
46330fdc8d8SChris Lattner         static lldb::OptionDefinition g_option_table[];
46430fdc8d8SChris Lattner 
46530fdc8d8SChris Lattner         // Instance variables to hold the values for command options.
46630fdc8d8SChris Lattner 
46730fdc8d8SChris Lattner         lldb::pid_t pid;
46830fdc8d8SChris Lattner         std::string plugin_name;
46930fdc8d8SChris Lattner         std::string name;
47030fdc8d8SChris Lattner         bool waitfor;
47130fdc8d8SChris Lattner     };
47230fdc8d8SChris Lattner 
47330fdc8d8SChris Lattner protected:
47430fdc8d8SChris Lattner 
47530fdc8d8SChris Lattner     CommandOptions m_options;
47630fdc8d8SChris Lattner };
47730fdc8d8SChris Lattner 
47830fdc8d8SChris Lattner 
47930fdc8d8SChris Lattner lldb::OptionDefinition
48030fdc8d8SChris Lattner CommandObjectProcessAttach::CommandOptions::g_option_table[] =
48130fdc8d8SChris Lattner {
4828651121cSJim Ingham { LLDB_OPT_SET_ALL, false, "plugin",       'P', required_argument, NULL, 0, "<plugin>",        "Name of the process plugin you want to use."},
4838651121cSJim Ingham { LLDB_OPT_SET_1, false, "pid",          'p', required_argument, NULL, 0, "<pid>",           "The process ID of an existing process to attach to."},
4848651121cSJim Ingham { LLDB_OPT_SET_2, true,  "name",         'n', required_argument, NULL, 0, "<process-name>",  "The name of the process to attach to."},
4858651121cSJim Ingham { LLDB_OPT_SET_2, false, "waitfor",      'w', no_argument,       NULL, 0, NULL,              "Wait for the the process with <process-name> to launch."},
48630fdc8d8SChris Lattner { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
48730fdc8d8SChris Lattner };
48830fdc8d8SChris Lattner 
48930fdc8d8SChris Lattner //-------------------------------------------------------------------------
49030fdc8d8SChris Lattner // CommandObjectProcessContinue
49130fdc8d8SChris Lattner //-------------------------------------------------------------------------
49230fdc8d8SChris Lattner 
49330fdc8d8SChris Lattner class CommandObjectProcessContinue : public CommandObject
49430fdc8d8SChris Lattner {
49530fdc8d8SChris Lattner public:
49630fdc8d8SChris Lattner 
49730fdc8d8SChris Lattner     CommandObjectProcessContinue () :
49830fdc8d8SChris Lattner         CommandObject ("process continue",
49930fdc8d8SChris Lattner                        "Continues execution all threads in the current process.",
50030fdc8d8SChris Lattner                        "process continue",
50130fdc8d8SChris Lattner                        eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
50230fdc8d8SChris Lattner     {
50330fdc8d8SChris Lattner     }
50430fdc8d8SChris Lattner 
50530fdc8d8SChris Lattner 
50630fdc8d8SChris Lattner     ~CommandObjectProcessContinue ()
50730fdc8d8SChris Lattner     {
50830fdc8d8SChris Lattner     }
50930fdc8d8SChris Lattner 
51030fdc8d8SChris Lattner     bool
51130fdc8d8SChris Lattner     Execute (Args& command,
51230fdc8d8SChris Lattner              CommandContext *context,
51330fdc8d8SChris Lattner              CommandInterpreter *interpreter,
51430fdc8d8SChris Lattner              CommandReturnObject &result)
51530fdc8d8SChris Lattner     {
51630fdc8d8SChris Lattner         Process *process = context->GetExecutionContext().process;
51730fdc8d8SChris Lattner         bool synchronous_execution = interpreter->GetSynchronous ();
51830fdc8d8SChris Lattner 
51930fdc8d8SChris Lattner         if (process == NULL)
52030fdc8d8SChris Lattner         {
52130fdc8d8SChris Lattner             result.AppendError ("no process to continue");
52230fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
52330fdc8d8SChris Lattner             return false;
52430fdc8d8SChris Lattner          }
52530fdc8d8SChris Lattner 
52630fdc8d8SChris Lattner         StateType state = process->GetState();
52730fdc8d8SChris Lattner         if (state == eStateStopped)
52830fdc8d8SChris Lattner         {
52930fdc8d8SChris Lattner             if (command.GetArgumentCount() != 0)
53030fdc8d8SChris Lattner             {
53130fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str());
53230fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
53330fdc8d8SChris Lattner                 return false;
53430fdc8d8SChris Lattner             }
53530fdc8d8SChris Lattner 
53630fdc8d8SChris Lattner             const uint32_t num_threads = process->GetThreadList().GetSize();
53730fdc8d8SChris Lattner 
53830fdc8d8SChris Lattner             // Set the actions that the threads should each take when resuming
53930fdc8d8SChris Lattner             for (uint32_t idx=0; idx<num_threads; ++idx)
54030fdc8d8SChris Lattner             {
54130fdc8d8SChris Lattner                 process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning);
54230fdc8d8SChris Lattner             }
54330fdc8d8SChris Lattner 
54430fdc8d8SChris Lattner             Error error(process->Resume());
54530fdc8d8SChris Lattner             if (error.Success())
54630fdc8d8SChris Lattner             {
54730fdc8d8SChris Lattner                 result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID());
54830fdc8d8SChris Lattner                 if (synchronous_execution)
54930fdc8d8SChris Lattner                 {
55030fdc8d8SChris Lattner                     StateType state = process->WaitForProcessToStop (NULL);
55130fdc8d8SChris Lattner 
55230fdc8d8SChris Lattner                     result.SetDidChangeProcessState (true);
55330fdc8d8SChris Lattner                     result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
55430fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
55530fdc8d8SChris Lattner                 }
55630fdc8d8SChris Lattner                 else
55730fdc8d8SChris Lattner                 {
55830fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusSuccessContinuingNoResult);
55930fdc8d8SChris Lattner                 }
56030fdc8d8SChris Lattner             }
56130fdc8d8SChris Lattner             else
56230fdc8d8SChris Lattner             {
56330fdc8d8SChris Lattner                 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
56430fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
56530fdc8d8SChris Lattner             }
56630fdc8d8SChris Lattner         }
56730fdc8d8SChris Lattner         else
56830fdc8d8SChris Lattner         {
56930fdc8d8SChris Lattner             result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
57030fdc8d8SChris Lattner                                          StateAsCString(state));
57130fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
57230fdc8d8SChris Lattner         }
57330fdc8d8SChris Lattner         return result.Succeeded();
57430fdc8d8SChris Lattner     }
57530fdc8d8SChris Lattner };
57630fdc8d8SChris Lattner 
57730fdc8d8SChris Lattner //-------------------------------------------------------------------------
57830fdc8d8SChris Lattner // CommandObjectProcessDetach
57930fdc8d8SChris Lattner //-------------------------------------------------------------------------
58030fdc8d8SChris Lattner 
58130fdc8d8SChris Lattner class CommandObjectProcessDetach : public CommandObject
58230fdc8d8SChris Lattner {
58330fdc8d8SChris Lattner public:
58430fdc8d8SChris Lattner 
58530fdc8d8SChris Lattner     CommandObjectProcessDetach () :
58630fdc8d8SChris Lattner         CommandObject ("process detach",
58730fdc8d8SChris Lattner                        "Detaches from the current process being debugged.",
58830fdc8d8SChris Lattner                        "process detach",
58930fdc8d8SChris Lattner                        eFlagProcessMustBeLaunched)
59030fdc8d8SChris Lattner     {
59130fdc8d8SChris Lattner     }
59230fdc8d8SChris Lattner 
59330fdc8d8SChris Lattner     ~CommandObjectProcessDetach ()
59430fdc8d8SChris Lattner     {
59530fdc8d8SChris Lattner     }
59630fdc8d8SChris Lattner 
59730fdc8d8SChris Lattner     bool
59830fdc8d8SChris Lattner     Execute (Args& command,
59930fdc8d8SChris Lattner              CommandContext *context,
60030fdc8d8SChris Lattner              CommandInterpreter *interpreter,
60130fdc8d8SChris Lattner              CommandReturnObject &result)
60230fdc8d8SChris Lattner     {
60330fdc8d8SChris Lattner         Process *process = context->GetExecutionContext().process;
60430fdc8d8SChris Lattner         if (process == NULL)
60530fdc8d8SChris Lattner         {
60630fdc8d8SChris Lattner             result.AppendError ("must have a valid process in order to detach");
60730fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
60830fdc8d8SChris Lattner             return false;
60930fdc8d8SChris Lattner         }
61030fdc8d8SChris Lattner 
61130fdc8d8SChris Lattner         Error error (process->Detach());
61230fdc8d8SChris Lattner         if (error.Success())
61330fdc8d8SChris Lattner         {
61430fdc8d8SChris Lattner             result.SetStatus (eReturnStatusSuccessFinishResult);
61530fdc8d8SChris Lattner         }
61630fdc8d8SChris Lattner         else
61730fdc8d8SChris Lattner         {
61830fdc8d8SChris Lattner             result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString());
61930fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
62030fdc8d8SChris Lattner             return false;
62130fdc8d8SChris Lattner         }
62230fdc8d8SChris Lattner         return result.Succeeded();
62330fdc8d8SChris Lattner     }
62430fdc8d8SChris Lattner };
62530fdc8d8SChris Lattner 
62630fdc8d8SChris Lattner //-------------------------------------------------------------------------
62730fdc8d8SChris Lattner // CommandObjectProcessSignal
62830fdc8d8SChris Lattner //-------------------------------------------------------------------------
62930fdc8d8SChris Lattner 
63030fdc8d8SChris Lattner class CommandObjectProcessSignal : public CommandObject
63130fdc8d8SChris Lattner {
63230fdc8d8SChris Lattner public:
63330fdc8d8SChris Lattner 
63430fdc8d8SChris Lattner     CommandObjectProcessSignal () :
63530fdc8d8SChris Lattner         CommandObject ("process signal",
63630fdc8d8SChris Lattner                        "Sends a UNIX signal to the current process being debugged.",
63730fdc8d8SChris Lattner                        "process signal <unix-signal-number>")
63830fdc8d8SChris Lattner     {
63930fdc8d8SChris Lattner     }
64030fdc8d8SChris Lattner 
64130fdc8d8SChris Lattner     ~CommandObjectProcessSignal ()
64230fdc8d8SChris Lattner     {
64330fdc8d8SChris Lattner     }
64430fdc8d8SChris Lattner 
64530fdc8d8SChris Lattner     bool
64630fdc8d8SChris Lattner     Execute (Args& command,
64730fdc8d8SChris Lattner              CommandContext *context,
64830fdc8d8SChris Lattner              CommandInterpreter *interpreter,
64930fdc8d8SChris Lattner              CommandReturnObject &result)
65030fdc8d8SChris Lattner     {
65130fdc8d8SChris Lattner         Process *process = context->GetExecutionContext().process;
65230fdc8d8SChris Lattner         if (process == NULL)
65330fdc8d8SChris Lattner         {
65430fdc8d8SChris Lattner             result.AppendError ("no process to signal");
65530fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
65630fdc8d8SChris Lattner             return false;
65730fdc8d8SChris Lattner         }
65830fdc8d8SChris Lattner 
65930fdc8d8SChris Lattner         if (command.GetArgumentCount() == 1)
66030fdc8d8SChris Lattner         {
66130fdc8d8SChris Lattner             int signo = Args::StringToSInt32(command.GetArgumentAtIndex(0), -1, 0);
66230fdc8d8SChris Lattner             if (signo == -1)
66330fdc8d8SChris Lattner             {
66430fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0));
66530fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
66630fdc8d8SChris Lattner             }
66730fdc8d8SChris Lattner             else
66830fdc8d8SChris Lattner             {
66930fdc8d8SChris Lattner                 Error error (process->Signal (signo));
67030fdc8d8SChris Lattner                 if (error.Success())
67130fdc8d8SChris Lattner                 {
67230fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusSuccessFinishResult);
67330fdc8d8SChris Lattner                 }
67430fdc8d8SChris Lattner                 else
67530fdc8d8SChris Lattner                 {
67630fdc8d8SChris Lattner                     result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString());
67730fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusFailed);
67830fdc8d8SChris Lattner                 }
67930fdc8d8SChris Lattner             }
68030fdc8d8SChris Lattner         }
68130fdc8d8SChris Lattner         else
68230fdc8d8SChris Lattner         {
68330fdc8d8SChris Lattner             result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: \n", m_cmd_name.c_str(),
68430fdc8d8SChris Lattner                                         m_cmd_syntax.c_str());
68530fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
68630fdc8d8SChris Lattner         }
68730fdc8d8SChris Lattner         return result.Succeeded();
68830fdc8d8SChris Lattner     }
68930fdc8d8SChris Lattner };
69030fdc8d8SChris Lattner 
69130fdc8d8SChris Lattner 
69230fdc8d8SChris Lattner //-------------------------------------------------------------------------
69330fdc8d8SChris Lattner // CommandObjectProcessInterrupt
69430fdc8d8SChris Lattner //-------------------------------------------------------------------------
69530fdc8d8SChris Lattner 
69630fdc8d8SChris Lattner class CommandObjectProcessInterrupt : public CommandObject
69730fdc8d8SChris Lattner {
69830fdc8d8SChris Lattner public:
69930fdc8d8SChris Lattner 
70030fdc8d8SChris Lattner 
70130fdc8d8SChris Lattner     CommandObjectProcessInterrupt () :
70230fdc8d8SChris Lattner     CommandObject ("process interrupt",
70330fdc8d8SChris Lattner                    "Interrupts the current process being debugged.",
70430fdc8d8SChris Lattner                    "process interrupt",
70530fdc8d8SChris Lattner                    eFlagProcessMustBeLaunched)
70630fdc8d8SChris Lattner     {
70730fdc8d8SChris Lattner     }
70830fdc8d8SChris Lattner 
70930fdc8d8SChris Lattner     ~CommandObjectProcessInterrupt ()
71030fdc8d8SChris Lattner     {
71130fdc8d8SChris Lattner     }
71230fdc8d8SChris Lattner 
71330fdc8d8SChris Lattner     bool
71430fdc8d8SChris Lattner     Execute (Args& command,
71530fdc8d8SChris Lattner              CommandContext *context,
71630fdc8d8SChris Lattner              CommandInterpreter *interpreter,
71730fdc8d8SChris Lattner              CommandReturnObject &result)
71830fdc8d8SChris Lattner     {
71930fdc8d8SChris Lattner         Process *process = context->GetExecutionContext().process;
72030fdc8d8SChris Lattner         if (process == NULL)
72130fdc8d8SChris Lattner         {
72230fdc8d8SChris Lattner             result.AppendError ("no process to halt");
72330fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
72430fdc8d8SChris Lattner             return false;
72530fdc8d8SChris Lattner         }
72630fdc8d8SChris Lattner 
72730fdc8d8SChris Lattner         if (command.GetArgumentCount() == 0)
72830fdc8d8SChris Lattner         {
72930fdc8d8SChris Lattner             Error error(process->Halt ());
73030fdc8d8SChris Lattner             if (error.Success())
73130fdc8d8SChris Lattner             {
73230fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusSuccessFinishResult);
73330fdc8d8SChris Lattner 
73430fdc8d8SChris Lattner                 // Maybe we should add a "SuspendThreadPlans so we
73530fdc8d8SChris Lattner                 // can halt, and keep in place all the current thread plans.
73630fdc8d8SChris Lattner                 process->GetThreadList().DiscardThreadPlans();
73730fdc8d8SChris Lattner             }
73830fdc8d8SChris Lattner             else
73930fdc8d8SChris Lattner             {
74030fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString());
74130fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
74230fdc8d8SChris Lattner             }
74330fdc8d8SChris Lattner         }
74430fdc8d8SChris Lattner         else
74530fdc8d8SChris Lattner         {
74630fdc8d8SChris Lattner             result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
74730fdc8d8SChris Lattner                                         m_cmd_name.c_str(),
74830fdc8d8SChris Lattner                                         m_cmd_syntax.c_str());
74930fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
75030fdc8d8SChris Lattner         }
75130fdc8d8SChris Lattner         return result.Succeeded();
75230fdc8d8SChris Lattner     }
75330fdc8d8SChris Lattner };
75430fdc8d8SChris Lattner 
75530fdc8d8SChris Lattner //-------------------------------------------------------------------------
75630fdc8d8SChris Lattner // CommandObjectProcessKill
75730fdc8d8SChris Lattner //-------------------------------------------------------------------------
75830fdc8d8SChris Lattner 
75930fdc8d8SChris Lattner class CommandObjectProcessKill : public CommandObject
76030fdc8d8SChris Lattner {
76130fdc8d8SChris Lattner public:
76230fdc8d8SChris Lattner 
76330fdc8d8SChris Lattner     CommandObjectProcessKill () :
76430fdc8d8SChris Lattner     CommandObject ("process kill",
76530fdc8d8SChris Lattner                    "Terminates the current process being debugged.",
76630fdc8d8SChris Lattner                    "process kill",
76730fdc8d8SChris Lattner                    eFlagProcessMustBeLaunched)
76830fdc8d8SChris Lattner     {
76930fdc8d8SChris Lattner     }
77030fdc8d8SChris Lattner 
77130fdc8d8SChris Lattner     ~CommandObjectProcessKill ()
77230fdc8d8SChris Lattner     {
77330fdc8d8SChris Lattner     }
77430fdc8d8SChris Lattner 
77530fdc8d8SChris Lattner     bool
77630fdc8d8SChris Lattner     Execute (Args& command,
77730fdc8d8SChris Lattner              CommandContext *context,
77830fdc8d8SChris Lattner              CommandInterpreter *interpreter,
77930fdc8d8SChris Lattner              CommandReturnObject &result)
78030fdc8d8SChris Lattner     {
78130fdc8d8SChris Lattner         Process *process = context->GetExecutionContext().process;
78230fdc8d8SChris Lattner         if (process == NULL)
78330fdc8d8SChris Lattner         {
78430fdc8d8SChris Lattner             result.AppendError ("no process to kill");
78530fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
78630fdc8d8SChris Lattner             return false;
78730fdc8d8SChris Lattner         }
78830fdc8d8SChris Lattner 
78930fdc8d8SChris Lattner         if (command.GetArgumentCount() == 0)
79030fdc8d8SChris Lattner         {
79130fdc8d8SChris Lattner             Error error (process->Destroy());
79230fdc8d8SChris Lattner             if (error.Success())
79330fdc8d8SChris Lattner             {
79430fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusSuccessFinishResult);
79530fdc8d8SChris Lattner             }
79630fdc8d8SChris Lattner             else
79730fdc8d8SChris Lattner             {
79830fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString());
79930fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
80030fdc8d8SChris Lattner             }
80130fdc8d8SChris Lattner         }
80230fdc8d8SChris Lattner         else
80330fdc8d8SChris Lattner         {
80430fdc8d8SChris Lattner             result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
80530fdc8d8SChris Lattner                                         m_cmd_name.c_str(),
80630fdc8d8SChris Lattner                                         m_cmd_syntax.c_str());
80730fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
80830fdc8d8SChris Lattner         }
80930fdc8d8SChris Lattner         return result.Succeeded();
81030fdc8d8SChris Lattner     }
81130fdc8d8SChris Lattner };
81230fdc8d8SChris Lattner 
81330fdc8d8SChris Lattner //-------------------------------------------------------------------------
814*4b9bea87SJim Ingham // CommandObjectProcessStatus
815*4b9bea87SJim Ingham //-------------------------------------------------------------------------
816*4b9bea87SJim Ingham class CommandObjectProcessStatus : public CommandObject
817*4b9bea87SJim Ingham {
818*4b9bea87SJim Ingham public:
819*4b9bea87SJim Ingham     CommandObjectProcessStatus () :
820*4b9bea87SJim Ingham     CommandObject ("status",
821*4b9bea87SJim Ingham                    "Shows the current status and location of executing process.",
822*4b9bea87SJim Ingham                    "status",
823*4b9bea87SJim Ingham                    0)
824*4b9bea87SJim Ingham     {
825*4b9bea87SJim Ingham     }
826*4b9bea87SJim Ingham 
827*4b9bea87SJim Ingham     ~CommandObjectProcessStatus()
828*4b9bea87SJim Ingham     {
829*4b9bea87SJim Ingham     }
830*4b9bea87SJim Ingham 
831*4b9bea87SJim Ingham 
832*4b9bea87SJim Ingham     bool
833*4b9bea87SJim Ingham     Execute
834*4b9bea87SJim Ingham     (
835*4b9bea87SJim Ingham         Args& command,
836*4b9bea87SJim Ingham         CommandContext *context,
837*4b9bea87SJim Ingham         CommandInterpreter *interpreter,
838*4b9bea87SJim Ingham         CommandReturnObject &result
839*4b9bea87SJim Ingham     )
840*4b9bea87SJim Ingham     {
841*4b9bea87SJim Ingham         StreamString &output_stream = result.GetOutputStream();
842*4b9bea87SJim Ingham         result.SetStatus (eReturnStatusSuccessFinishNoResult);
843*4b9bea87SJim Ingham         ExecutionContext exe_ctx(context->GetExecutionContext());
844*4b9bea87SJim Ingham         if (exe_ctx.process)
845*4b9bea87SJim Ingham         {
846*4b9bea87SJim Ingham             const StateType state = exe_ctx.process->GetState();
847*4b9bea87SJim Ingham             if (StateIsStoppedState(state))
848*4b9bea87SJim Ingham             {
849*4b9bea87SJim Ingham                 if (state == eStateExited)
850*4b9bea87SJim Ingham                 {
851*4b9bea87SJim Ingham                     int exit_status = exe_ctx.process->GetExitStatus();
852*4b9bea87SJim Ingham                     const char *exit_description = exe_ctx.process->GetExitDescription();
853*4b9bea87SJim Ingham                     output_stream.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n",
854*4b9bea87SJim Ingham                                           exe_ctx.process->GetID(),
855*4b9bea87SJim Ingham                                           exit_status,
856*4b9bea87SJim Ingham                                           exit_status,
857*4b9bea87SJim Ingham                                           exit_description ? exit_description : "");
858*4b9bea87SJim Ingham                 }
859*4b9bea87SJim Ingham                 else
860*4b9bea87SJim Ingham                 {
861*4b9bea87SJim Ingham                     output_stream.Printf ("Process %d %s\n", exe_ctx.process->GetID(), StateAsCString (state));
862*4b9bea87SJim Ingham                     if (exe_ctx.thread == NULL)
863*4b9bea87SJim Ingham                         exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
864*4b9bea87SJim Ingham                     if (exe_ctx.thread != NULL)
865*4b9bea87SJim Ingham                     {
866*4b9bea87SJim Ingham                         DisplayThreadsInfo (interpreter, &exe_ctx, result, true, true);
867*4b9bea87SJim Ingham                     }
868*4b9bea87SJim Ingham                     else
869*4b9bea87SJim Ingham                     {
870*4b9bea87SJim Ingham                         result.AppendError ("No valid thread found in current process.");
871*4b9bea87SJim Ingham                         result.SetStatus (eReturnStatusFailed);
872*4b9bea87SJim Ingham                     }
873*4b9bea87SJim Ingham                 }
874*4b9bea87SJim Ingham             }
875*4b9bea87SJim Ingham             else
876*4b9bea87SJim Ingham             {
877*4b9bea87SJim Ingham                 output_stream.Printf ("Process %d is running.\n",
878*4b9bea87SJim Ingham                                           exe_ctx.process->GetID());
879*4b9bea87SJim Ingham             }
880*4b9bea87SJim Ingham         }
881*4b9bea87SJim Ingham         else
882*4b9bea87SJim Ingham         {
883*4b9bea87SJim Ingham             result.AppendError ("No current location or status available.");
884*4b9bea87SJim Ingham             result.SetStatus (eReturnStatusFailed);
885*4b9bea87SJim Ingham         }
886*4b9bea87SJim Ingham         return result.Succeeded();
887*4b9bea87SJim Ingham     }
888*4b9bea87SJim Ingham };
889*4b9bea87SJim Ingham 
890*4b9bea87SJim Ingham //-------------------------------------------------------------------------
89130fdc8d8SChris Lattner // CommandObjectMultiwordProcess
89230fdc8d8SChris Lattner //-------------------------------------------------------------------------
89330fdc8d8SChris Lattner 
89430fdc8d8SChris Lattner CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter *interpreter) :
89530fdc8d8SChris Lattner     CommandObjectMultiword ("process",
89630fdc8d8SChris Lattner                               "A set of commands for operating on a process.",
89730fdc8d8SChris Lattner                               "process <subcommand> [<subcommand-options>]")
89830fdc8d8SChris Lattner {
89930fdc8d8SChris Lattner     LoadSubCommand (CommandObjectSP (new CommandObjectProcessAttach ()), "attach", interpreter);
90030fdc8d8SChris Lattner     LoadSubCommand (CommandObjectSP (new CommandObjectProcessLaunch ()), "launch", interpreter);
90130fdc8d8SChris Lattner     LoadSubCommand (CommandObjectSP (new CommandObjectProcessContinue ()), "continue", interpreter);
90230fdc8d8SChris Lattner     LoadSubCommand (CommandObjectSP (new CommandObjectProcessDetach ()), "detach", interpreter);
90330fdc8d8SChris Lattner     LoadSubCommand (CommandObjectSP (new CommandObjectProcessSignal ()), "signal", interpreter);
904*4b9bea87SJim Ingham     LoadSubCommand (CommandObjectSP (new CommandObjectProcessStatus ()), "status", interpreter);
90530fdc8d8SChris Lattner     LoadSubCommand (CommandObjectSP (new CommandObjectProcessInterrupt ()), "interrupt", interpreter);
90630fdc8d8SChris Lattner     LoadSubCommand (CommandObjectSP (new CommandObjectProcessKill ()), "kill", interpreter);
90730fdc8d8SChris Lattner }
90830fdc8d8SChris Lattner 
90930fdc8d8SChris Lattner CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess ()
91030fdc8d8SChris Lattner {
91130fdc8d8SChris Lattner }
91230fdc8d8SChris Lattner 
913