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 
10430fdc8d8SChris Lattner     CommandObjectProcessLaunch () :
10530fdc8d8SChris Lattner         CommandObject ("process launch",
106e3d26315SCaroline Tice                        "Launch 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
1236611103cSGreg Clayton     Execute (CommandInterpreter &interpreter,
1246611103cSGreg Clayton              Args& launch_args,
12530fdc8d8SChris Lattner              CommandReturnObject &result)
12630fdc8d8SChris Lattner     {
1272976d00aSJim Ingham         Target *target = interpreter.GetDebugger().GetSelectedTarget().get();
1286611103cSGreg Clayton         bool synchronous_execution = interpreter.GetSynchronous ();
12930fdc8d8SChris Lattner     //    bool launched = false;
13030fdc8d8SChris Lattner     //    bool stopped_after_launch = false;
13130fdc8d8SChris Lattner 
13230fdc8d8SChris Lattner         if (target == NULL)
13330fdc8d8SChris Lattner         {
13430fdc8d8SChris Lattner             result.AppendError ("invalid target, set executable file using 'file' command");
13530fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
13630fdc8d8SChris Lattner             return false;
13730fdc8d8SChris Lattner         }
13830fdc8d8SChris Lattner 
13930fdc8d8SChris Lattner         // If our listener is NULL, users aren't allows to launch
14030fdc8d8SChris Lattner         char filename[PATH_MAX];
14130fdc8d8SChris Lattner         Module *exe_module = target->GetExecutableModule().get();
14230fdc8d8SChris Lattner         exe_module->GetFileSpec().GetPath(filename, sizeof(filename));
14330fdc8d8SChris Lattner 
1446611103cSGreg Clayton         Process *process = interpreter.GetDebugger().GetExecutionContext().process;
14530fdc8d8SChris Lattner         if (process)
14630fdc8d8SChris Lattner         {
14730fdc8d8SChris Lattner             if (process->IsAlive())
14830fdc8d8SChris Lattner             {
14930fdc8d8SChris Lattner                result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before running again.\n",
15030fdc8d8SChris Lattner                                             process->GetID());
15130fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
15230fdc8d8SChris Lattner                 return false;
15330fdc8d8SChris Lattner             }
15430fdc8d8SChris Lattner         }
15530fdc8d8SChris Lattner 
15630fdc8d8SChris Lattner         const char *plugin_name;
15730fdc8d8SChris Lattner         if (!m_options.plugin_name.empty())
15830fdc8d8SChris Lattner             plugin_name = m_options.plugin_name.c_str();
15930fdc8d8SChris Lattner         else
16030fdc8d8SChris Lattner             plugin_name = NULL;
16130fdc8d8SChris Lattner 
1626611103cSGreg Clayton         process = target->CreateProcess (interpreter.GetDebugger().GetListener(), plugin_name).get();
16330fdc8d8SChris Lattner 
1643df9a8dfSCaroline Tice         const char *process_name = process->GetInstanceName().AsCString();
165101c7c20SCaroline Tice         const char *debugger_instance_name = interpreter.GetDebugger().GetInstanceName().AsCString();
1663df9a8dfSCaroline Tice         StreamString run_args_var_name;
1673df9a8dfSCaroline Tice         StreamString env_vars_var_name;
1683df9a8dfSCaroline Tice         StreamString disable_aslr_var_name;
1693df9a8dfSCaroline Tice         lldb::SettableVariableType var_type;
1703df9a8dfSCaroline Tice 
1713df9a8dfSCaroline Tice         Args *run_args = NULL;
1723df9a8dfSCaroline Tice         run_args_var_name.Printf ("process.[%s].run-args", process_name);
1733df9a8dfSCaroline Tice         StringList run_args_value = Debugger::GetSettingsController()->GetVariable (run_args_var_name.GetData(),
174101c7c20SCaroline Tice                                                                                     var_type, debugger_instance_name);
175101c7c20SCaroline Tice 
1763df9a8dfSCaroline Tice         if (run_args_value.GetSize() > 0)
1773df9a8dfSCaroline Tice         {
1783df9a8dfSCaroline Tice             run_args = new Args;
17937c1b431SChris Lattner             for (unsigned i = 0, e = run_args_value.GetSize(); i != e; ++i)
1803df9a8dfSCaroline Tice                 run_args->AppendArgument(run_args_value.GetStringAtIndex(i));
1813df9a8dfSCaroline Tice         }
1823df9a8dfSCaroline Tice 
1833df9a8dfSCaroline Tice         Args *environment = NULL;
1843df9a8dfSCaroline Tice         env_vars_var_name.Printf ("process.[%s].env-vars", process_name);
1853df9a8dfSCaroline Tice         StringList env_vars_value = Debugger::GetSettingsController()->GetVariable (env_vars_var_name.GetData(),
186101c7c20SCaroline Tice                                                                                     var_type, debugger_instance_name);
187101c7c20SCaroline Tice 
1883df9a8dfSCaroline Tice         if (env_vars_value.GetSize() > 0)
1893df9a8dfSCaroline Tice         {
1903df9a8dfSCaroline Tice             environment = new Args;
19137c1b431SChris Lattner             for (unsigned i = 0, e = env_vars_value.GetSize(); i != e; ++i)
1923df9a8dfSCaroline Tice                 environment->AppendArgument (env_vars_value.GetStringAtIndex (i));
1933df9a8dfSCaroline Tice         }
1943df9a8dfSCaroline Tice 
195f681b94fSGreg Clayton         uint32_t launch_flags = eLaunchFlagNone;
1963df9a8dfSCaroline Tice         disable_aslr_var_name.Printf ("process.[%s].disable-aslr", process_name);
1973df9a8dfSCaroline Tice         StringList disable_aslr_value = Debugger::GetSettingsController()->GetVariable(disable_aslr_var_name.GetData(),
198101c7c20SCaroline Tice                                                                                        var_type,
199101c7c20SCaroline Tice                                                                                        debugger_instance_name);
200101c7c20SCaroline Tice 
2013df9a8dfSCaroline Tice         if (disable_aslr_value.GetSize() > 0)
2023df9a8dfSCaroline Tice         {
2033df9a8dfSCaroline Tice             if (strcmp (disable_aslr_value.GetStringAtIndex(0), "true") == 0)
204f681b94fSGreg Clayton                 launch_flags |= eLaunchFlagDisableASLR;
20530fdc8d8SChris Lattner 
2063df9a8dfSCaroline Tice         }
2073df9a8dfSCaroline Tice 
20830fdc8d8SChris Lattner         // There are two possible sources of args to be passed to the process upon launching:  Those the user
20930fdc8d8SChris Lattner         // typed at the run command (launch_args); or those the user pre-set in the run-args variable (run_args).
21030fdc8d8SChris Lattner 
21130fdc8d8SChris Lattner         // If launch_args is empty, use run_args.
21230fdc8d8SChris Lattner         if (launch_args.GetArgumentCount() == 0)
21330fdc8d8SChris Lattner         {
21430fdc8d8SChris Lattner             if (run_args != NULL)
21530fdc8d8SChris Lattner                 launch_args.AppendArguments (*run_args);
21630fdc8d8SChris Lattner         }
21730fdc8d8SChris Lattner         else
21830fdc8d8SChris Lattner         {
21930fdc8d8SChris Lattner             // launch-args was not empty; use that, AND re-set run-args to contains launch-args values.
2203df9a8dfSCaroline Tice             std::string new_run_args;
2213df9a8dfSCaroline Tice             launch_args.GetCommandString (new_run_args);
222101c7c20SCaroline Tice             Debugger::GetSettingsController()->SetVariable (run_args_var_name.GetData(), new_run_args.c_str(),
223101c7c20SCaroline Tice                                                             lldb::eVarSetOperationAssign, false,
224101c7c20SCaroline Tice                                                             interpreter.GetDebugger().GetInstanceName().AsCString());
22530fdc8d8SChris Lattner         }
22630fdc8d8SChris Lattner 
22730fdc8d8SChris Lattner 
22830fdc8d8SChris Lattner         if (process)
22930fdc8d8SChris Lattner         {
23030fdc8d8SChris Lattner             const char *archname = exe_module->GetArchitecture().AsCString();
23130fdc8d8SChris Lattner 
23230fdc8d8SChris Lattner             const char * stdin_path = NULL;
23330fdc8d8SChris Lattner             const char * stdout_path = NULL;
23430fdc8d8SChris Lattner             const char * stderr_path = NULL;
23530fdc8d8SChris Lattner 
23630fdc8d8SChris Lattner             if (!(m_options.stdin_path.empty() &&
23730fdc8d8SChris Lattner                 m_options.stdout_path.empty() &&
23830fdc8d8SChris Lattner                 m_options.stderr_path.empty()))
23930fdc8d8SChris Lattner             {
24030fdc8d8SChris Lattner                 stdin_path =    m_options.stdin_path.empty()  ? "/dev/null" : m_options.stdin_path.c_str();
24130fdc8d8SChris Lattner                 stdout_path =   m_options.stdout_path.empty() ? "/dev/null" : m_options.stdout_path.c_str();
24230fdc8d8SChris Lattner                 stderr_path =   m_options.stderr_path.empty() ? "/dev/null" : m_options.stderr_path.c_str();
24330fdc8d8SChris Lattner             }
24430fdc8d8SChris Lattner 
24530fdc8d8SChris Lattner             Error error (process->Launch (launch_args.GetConstArgumentVector(),
24630fdc8d8SChris Lattner                                           environment ? environment->GetConstArgumentVector() : NULL,
247f681b94fSGreg Clayton                                           launch_flags,
24830fdc8d8SChris Lattner                                           stdin_path,
24930fdc8d8SChris Lattner                                           stdout_path,
25030fdc8d8SChris Lattner                                           stderr_path));
25130fdc8d8SChris Lattner 
25230fdc8d8SChris Lattner             if (error.Success())
25330fdc8d8SChris Lattner             {
25430fdc8d8SChris Lattner                 result.AppendMessageWithFormat ("Launching '%s'  (%s)\n", filename, archname);
25530fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
25630fdc8d8SChris Lattner                 if (m_options.stop_at_entry == false)
25730fdc8d8SChris Lattner                 {
25830fdc8d8SChris Lattner                     StateType state = process->WaitForProcessToStop (NULL);
25930fdc8d8SChris Lattner 
26030fdc8d8SChris Lattner                     if (state == eStateStopped)
26130fdc8d8SChris Lattner                     {
26230fdc8d8SChris Lattner                         // Call continue_command.
26330fdc8d8SChris Lattner                         CommandReturnObject continue_result;
2646611103cSGreg Clayton                         interpreter.HandleCommand("process continue", false, continue_result);
26530fdc8d8SChris Lattner                     }
26630fdc8d8SChris Lattner 
26730fdc8d8SChris Lattner                     if (synchronous_execution)
26830fdc8d8SChris Lattner                     {
26930fdc8d8SChris Lattner                         result.SetDidChangeProcessState (true);
27030fdc8d8SChris Lattner                         result.SetStatus (eReturnStatusSuccessFinishNoResult);
27130fdc8d8SChris Lattner                     }
27230fdc8d8SChris Lattner                 }
27330fdc8d8SChris Lattner             }
27430fdc8d8SChris Lattner             else
27530fdc8d8SChris Lattner             {
27630fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("Process launch failed: %s",
27730fdc8d8SChris Lattner                                               error.AsCString());
27830fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
27930fdc8d8SChris Lattner             }
28030fdc8d8SChris Lattner         }
28130fdc8d8SChris Lattner         else
28230fdc8d8SChris Lattner         {
28330fdc8d8SChris Lattner             result.AppendErrorWithFormat ("Process launch failed: unable to create a process object.\n");
28430fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
28530fdc8d8SChris Lattner             return false;
28630fdc8d8SChris Lattner         }
28730fdc8d8SChris Lattner 
28830fdc8d8SChris Lattner         return result.Succeeded();
28930fdc8d8SChris Lattner     }
29030fdc8d8SChris Lattner 
291ebc09c36SJim Ingham     virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
292ebc09c36SJim Ingham     {
293ebc09c36SJim Ingham         // No repeat for "process launch"...
294ebc09c36SJim Ingham         return "";
295ebc09c36SJim Ingham     }
296ebc09c36SJim Ingham 
29730fdc8d8SChris Lattner protected:
29830fdc8d8SChris Lattner 
29930fdc8d8SChris Lattner     CommandOptions m_options;
30030fdc8d8SChris Lattner };
30130fdc8d8SChris Lattner 
30230fdc8d8SChris Lattner 
30330fdc8d8SChris Lattner lldb::OptionDefinition
30430fdc8d8SChris Lattner CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
30530fdc8d8SChris Lattner {
3068651121cSJim 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."},
3078651121cSJim Ingham { LLDB_OPT_SET_1, false, "stdin",         'i', required_argument, NULL, 0, "<path>",    "Redirect stdin for the process to <path>."},
3088651121cSJim Ingham { LLDB_OPT_SET_1, false, "stdout",        'o', required_argument, NULL, 0, "<path>",    "Redirect stdout for the process to <path>."},
3098651121cSJim Ingham { LLDB_OPT_SET_1, false, "stderr",        'e', required_argument, NULL, 0, "<path>",    "Redirect stderr for the process to <path>."},
3108651121cSJim Ingham { LLDB_OPT_SET_1, false, "plugin",        'p', required_argument, NULL, 0, "<plugin>",  "Name of the process plugin you want to use."},
31130fdc8d8SChris Lattner { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
31230fdc8d8SChris Lattner };
31330fdc8d8SChris Lattner 
31430fdc8d8SChris Lattner 
31530fdc8d8SChris Lattner //-------------------------------------------------------------------------
31630fdc8d8SChris Lattner // CommandObjectProcessAttach
31730fdc8d8SChris Lattner //-------------------------------------------------------------------------
31830fdc8d8SChris Lattner 
31930fdc8d8SChris Lattner class CommandObjectProcessAttach : public CommandObject
32030fdc8d8SChris Lattner {
32130fdc8d8SChris Lattner public:
32230fdc8d8SChris Lattner 
32330fdc8d8SChris Lattner     class CommandOptions : public Options
32430fdc8d8SChris Lattner     {
32530fdc8d8SChris Lattner     public:
32630fdc8d8SChris Lattner 
32730fdc8d8SChris Lattner         CommandOptions () :
32830fdc8d8SChris Lattner             Options()
32930fdc8d8SChris Lattner         {
33030fdc8d8SChris Lattner             // Keep default values of all options in one place: ResetOptionValues ()
33130fdc8d8SChris Lattner             ResetOptionValues ();
33230fdc8d8SChris Lattner         }
33330fdc8d8SChris Lattner 
33430fdc8d8SChris Lattner         ~CommandOptions ()
33530fdc8d8SChris Lattner         {
33630fdc8d8SChris Lattner         }
33730fdc8d8SChris Lattner 
33830fdc8d8SChris Lattner         Error
33930fdc8d8SChris Lattner         SetOptionValue (int option_idx, const char *option_arg)
34030fdc8d8SChris Lattner         {
34130fdc8d8SChris Lattner             Error error;
34230fdc8d8SChris Lattner             char short_option = (char) m_getopt_table[option_idx].val;
34330fdc8d8SChris Lattner             bool success = false;
34430fdc8d8SChris Lattner             switch (short_option)
34530fdc8d8SChris Lattner             {
34630fdc8d8SChris Lattner                 case 'p':
34730fdc8d8SChris Lattner                     pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success);
34830fdc8d8SChris Lattner                     if (!success || pid == LLDB_INVALID_PROCESS_ID)
34930fdc8d8SChris Lattner                     {
35030fdc8d8SChris Lattner                         error.SetErrorStringWithFormat("Invalid process ID '%s'.\n", option_arg);
35130fdc8d8SChris Lattner                     }
35230fdc8d8SChris Lattner                     break;
35330fdc8d8SChris Lattner 
35430fdc8d8SChris Lattner                 case 'P':
35530fdc8d8SChris Lattner                     plugin_name = option_arg;
35630fdc8d8SChris Lattner                     break;
35730fdc8d8SChris Lattner 
35830fdc8d8SChris Lattner                 case 'n':
35930fdc8d8SChris Lattner                     name.assign(option_arg);
36030fdc8d8SChris Lattner                     break;
36130fdc8d8SChris Lattner 
36230fdc8d8SChris Lattner                 case 'w':
36330fdc8d8SChris Lattner                     waitfor = true;
36430fdc8d8SChris Lattner                     break;
36530fdc8d8SChris Lattner 
36630fdc8d8SChris Lattner                 default:
36730fdc8d8SChris Lattner                     error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
36830fdc8d8SChris Lattner                     break;
36930fdc8d8SChris Lattner             }
37030fdc8d8SChris Lattner             return error;
37130fdc8d8SChris Lattner         }
37230fdc8d8SChris Lattner 
37330fdc8d8SChris Lattner         void
37430fdc8d8SChris Lattner         ResetOptionValues ()
37530fdc8d8SChris Lattner         {
37630fdc8d8SChris Lattner             Options::ResetOptionValues();
37730fdc8d8SChris Lattner             pid = LLDB_INVALID_PROCESS_ID;
37830fdc8d8SChris Lattner             name.clear();
37930fdc8d8SChris Lattner             waitfor = false;
38030fdc8d8SChris Lattner         }
38130fdc8d8SChris Lattner 
38230fdc8d8SChris Lattner         const lldb::OptionDefinition*
38330fdc8d8SChris Lattner         GetDefinitions ()
38430fdc8d8SChris Lattner         {
38530fdc8d8SChris Lattner             return g_option_table;
38630fdc8d8SChris Lattner         }
38730fdc8d8SChris Lattner 
3885aee162fSJim Ingham         virtual bool
3895aee162fSJim Ingham         HandleOptionArgumentCompletion (CommandInterpreter &interpreter,
3905aee162fSJim Ingham                                         Args &input,
3915aee162fSJim Ingham                                         int cursor_index,
3925aee162fSJim Ingham                                         int char_pos,
3935aee162fSJim Ingham                                         OptionElementVector &opt_element_vector,
3945aee162fSJim Ingham                                         int opt_element_index,
3955aee162fSJim Ingham                                         int match_start_point,
3965aee162fSJim Ingham                                         int max_return_elements,
3975aee162fSJim Ingham                                         bool &word_complete,
3985aee162fSJim Ingham                                         StringList &matches)
3995aee162fSJim Ingham         {
4005aee162fSJim Ingham             int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
4015aee162fSJim Ingham             int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
4025aee162fSJim Ingham 
4035aee162fSJim Ingham             // We are only completing the name option for now...
4045aee162fSJim Ingham 
4055aee162fSJim Ingham             const lldb::OptionDefinition *opt_defs = GetDefinitions();
4065aee162fSJim Ingham             if (opt_defs[opt_defs_index].short_option == 'n')
4075aee162fSJim Ingham             {
4085aee162fSJim Ingham                 // Are we in the name?
4095aee162fSJim Ingham 
4105aee162fSJim Ingham                 // Look to see if there is a -P argument provided, and if so use that plugin, otherwise
4115aee162fSJim Ingham                 // use the default plugin.
4125aee162fSJim Ingham                 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
4135aee162fSJim Ingham                 bool need_to_delete_process = false;
4145aee162fSJim Ingham 
4155aee162fSJim Ingham                 const char *partial_name = NULL;
4165aee162fSJim Ingham                 partial_name = input.GetArgumentAtIndex(opt_arg_pos);
4175aee162fSJim Ingham 
4185aee162fSJim Ingham                 if (process && process->IsAlive())
4195aee162fSJim Ingham                     return true;
4205aee162fSJim Ingham 
4212976d00aSJim Ingham                 Target *target = interpreter.GetDebugger().GetSelectedTarget().get();
4225aee162fSJim Ingham                 if (target == NULL)
4235aee162fSJim Ingham                 {
4245aee162fSJim Ingham                     // No target has been set yet, for now do host completion.  Otherwise I don't know how we would
4255aee162fSJim Ingham                     // figure out what the right target to use is...
4265aee162fSJim Ingham                     std::vector<lldb::pid_t> pids;
4275aee162fSJim Ingham                     Host::ListProcessesMatchingName (partial_name, matches, pids);
4285aee162fSJim Ingham                     return true;
4295aee162fSJim Ingham                 }
4305aee162fSJim Ingham                 if (!process)
4315aee162fSJim Ingham                 {
4325aee162fSJim Ingham                     process = target->CreateProcess (interpreter.GetDebugger().GetListener(), partial_name).get();
4335aee162fSJim Ingham                     need_to_delete_process = true;
4345aee162fSJim Ingham                 }
4355aee162fSJim Ingham 
4365aee162fSJim Ingham                 if (process)
4375aee162fSJim Ingham                 {
4385aee162fSJim Ingham                     matches.Clear();
4395aee162fSJim Ingham                     std::vector<lldb::pid_t> pids;
4405aee162fSJim Ingham                     process->ListProcessesMatchingName (NULL, matches, pids);
4415aee162fSJim Ingham                     if (need_to_delete_process)
4425aee162fSJim Ingham                         target->DeleteCurrentProcess();
4435aee162fSJim Ingham                     return true;
4445aee162fSJim Ingham                 }
4455aee162fSJim Ingham             }
4465aee162fSJim Ingham 
4475aee162fSJim Ingham             return false;
4485aee162fSJim Ingham         }
4495aee162fSJim Ingham 
45030fdc8d8SChris Lattner         // Options table: Required for subclasses of Options.
45130fdc8d8SChris Lattner 
45230fdc8d8SChris Lattner         static lldb::OptionDefinition g_option_table[];
45330fdc8d8SChris Lattner 
45430fdc8d8SChris Lattner         // Instance variables to hold the values for command options.
45530fdc8d8SChris Lattner 
45630fdc8d8SChris Lattner         lldb::pid_t pid;
45730fdc8d8SChris Lattner         std::string plugin_name;
45830fdc8d8SChris Lattner         std::string name;
45930fdc8d8SChris Lattner         bool waitfor;
46030fdc8d8SChris Lattner     };
46130fdc8d8SChris Lattner 
4625aee162fSJim Ingham     CommandObjectProcessAttach () :
4635aee162fSJim Ingham         CommandObject ("process attach",
464e3d26315SCaroline Tice                        "Attach to a process.",
4655aee162fSJim Ingham                        "process attach <cmd-options>")
4665aee162fSJim Ingham     {
4675aee162fSJim Ingham     }
4685aee162fSJim Ingham 
4695aee162fSJim Ingham     ~CommandObjectProcessAttach ()
4705aee162fSJim Ingham     {
4715aee162fSJim Ingham     }
4725aee162fSJim Ingham 
4735aee162fSJim Ingham     bool
4745aee162fSJim Ingham     Execute (CommandInterpreter &interpreter,
4755aee162fSJim Ingham              Args& command,
4765aee162fSJim Ingham              CommandReturnObject &result)
4775aee162fSJim Ingham     {
4782976d00aSJim Ingham         Target *target = interpreter.GetDebugger().GetSelectedTarget().get();
4795aee162fSJim Ingham 
4805aee162fSJim Ingham         Process *process = interpreter.GetDebugger().GetExecutionContext().process;
4815aee162fSJim Ingham         if (process)
4825aee162fSJim Ingham         {
4835aee162fSJim Ingham             if (process->IsAlive())
4845aee162fSJim Ingham             {
4855aee162fSJim Ingham                 result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before attaching.\n",
4865aee162fSJim Ingham                                               process->GetID());
4875aee162fSJim Ingham                 result.SetStatus (eReturnStatusFailed);
4885aee162fSJim Ingham                 return false;
4895aee162fSJim Ingham             }
4905aee162fSJim Ingham         }
4915aee162fSJim Ingham 
4925aee162fSJim Ingham         if (target == NULL)
4935aee162fSJim Ingham         {
4945aee162fSJim Ingham             // If there isn't a current target create one.
4955aee162fSJim Ingham             TargetSP new_target_sp;
4965aee162fSJim Ingham             FileSpec emptyFileSpec;
4975aee162fSJim Ingham             ArchSpec emptyArchSpec;
4985aee162fSJim Ingham             Error error;
4995aee162fSJim Ingham 
5005aee162fSJim Ingham             error = interpreter.GetDebugger().GetTargetList().CreateTarget(interpreter.GetDebugger(),
5015aee162fSJim Ingham                                                                            emptyFileSpec,
5025aee162fSJim Ingham                                                                            emptyArchSpec,
5035aee162fSJim Ingham                                                                            NULL,
5045aee162fSJim Ingham                                                                            false,
5055aee162fSJim Ingham                                                                            new_target_sp);
5065aee162fSJim Ingham             target = new_target_sp.get();
5075aee162fSJim Ingham             if (target == NULL || error.Fail())
5085aee162fSJim Ingham             {
5095aee162fSJim Ingham                 result.AppendError(error.AsCString("Error creating empty target"));
5105aee162fSJim Ingham                 return false;
5115aee162fSJim Ingham             }
5122976d00aSJim Ingham             interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target);
5135aee162fSJim Ingham         }
5145aee162fSJim Ingham 
5155aee162fSJim Ingham         // Record the old executable module, we want to issue a warning if the process of attaching changed the
5165aee162fSJim Ingham         // current executable (like somebody said "file foo" then attached to a PID whose executable was bar.)
5175aee162fSJim Ingham 
5185aee162fSJim Ingham         ModuleSP old_exec_module_sp = target->GetExecutableModule();
5195aee162fSJim Ingham         ArchSpec old_arch_spec = target->GetArchitecture();
5205aee162fSJim Ingham 
5215aee162fSJim Ingham         if (command.GetArgumentCount())
5225aee162fSJim Ingham         {
5235aee162fSJim Ingham             result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
5245aee162fSJim Ingham             result.SetStatus (eReturnStatusFailed);
5255aee162fSJim Ingham         }
5265aee162fSJim Ingham         else
5275aee162fSJim Ingham         {
5285aee162fSJim Ingham             const char *plugin_name = NULL;
5295aee162fSJim Ingham 
5305aee162fSJim Ingham             if (!m_options.plugin_name.empty())
5315aee162fSJim Ingham                 plugin_name = m_options.plugin_name.c_str();
5325aee162fSJim Ingham 
5335aee162fSJim Ingham             process = target->CreateProcess (interpreter.GetDebugger().GetListener(), plugin_name).get();
5345aee162fSJim Ingham 
5355aee162fSJim Ingham             if (process)
5365aee162fSJim Ingham             {
5375aee162fSJim Ingham                 Error error;
5385aee162fSJim Ingham                 int attach_pid = m_options.pid;
5395aee162fSJim Ingham 
540*3a0b9cdfSJim Ingham                 const char *wait_name = NULL;
541*3a0b9cdfSJim Ingham 
5425aee162fSJim Ingham                 if (m_options.name.empty())
5435aee162fSJim Ingham                 {
544*3a0b9cdfSJim Ingham                     if (old_exec_module_sp)
545*3a0b9cdfSJim Ingham                     {
546*3a0b9cdfSJim Ingham                         wait_name = old_exec_module_sp->GetFileSpec().GetFilename().AsCString();
547*3a0b9cdfSJim Ingham                     }
5485aee162fSJim Ingham                 }
5495aee162fSJim Ingham                 else
5505aee162fSJim Ingham                 {
551*3a0b9cdfSJim Ingham                     wait_name = m_options.name.c_str();
552*3a0b9cdfSJim Ingham                 }
553*3a0b9cdfSJim Ingham 
554*3a0b9cdfSJim Ingham                 // If we are waiting for a process with this name to show up, do that first.
555*3a0b9cdfSJim Ingham                 if (m_options.waitfor)
556*3a0b9cdfSJim Ingham                 {
557*3a0b9cdfSJim Ingham 
558*3a0b9cdfSJim Ingham                     if (wait_name == NULL)
559*3a0b9cdfSJim Ingham                     {
560*3a0b9cdfSJim Ingham                         result.AppendError("Invalid arguments: must have a file loaded or supply a process name with the waitfor option.\n");
561*3a0b9cdfSJim Ingham                         result.SetStatus (eReturnStatusFailed);
562*3a0b9cdfSJim Ingham                         return false;
563*3a0b9cdfSJim Ingham                     }
564*3a0b9cdfSJim Ingham 
565*3a0b9cdfSJim Ingham                     interpreter.GetDebugger().GetOutputStream().Printf("Waiting to attach to a process named \"%s\".\n", wait_name);
566*3a0b9cdfSJim Ingham                     error = process->Attach (wait_name, m_options.waitfor);
5675aee162fSJim Ingham                     if (error.Success())
5685aee162fSJim Ingham                     {
5695aee162fSJim Ingham                         result.SetStatus (eReturnStatusSuccessContinuingNoResult);
5705aee162fSJim Ingham                     }
5715aee162fSJim Ingham                     else
5725aee162fSJim Ingham                     {
5735aee162fSJim Ingham                         result.AppendErrorWithFormat ("Waiting for a process to launch named '%s': %s\n",
574*3a0b9cdfSJim Ingham                                                          wait_name,
5755aee162fSJim Ingham                                                          error.AsCString());
5765aee162fSJim Ingham                         result.SetStatus (eReturnStatusFailed);
5775aee162fSJim Ingham                         return false;
5785aee162fSJim Ingham                     }
5795aee162fSJim Ingham                 }
5805aee162fSJim Ingham                 else
5815aee162fSJim Ingham                 {
5825aee162fSJim Ingham                     // If the process was specified by name look it up, so we can warn if there are multiple
5835aee162fSJim Ingham                     // processes with this pid.
5845aee162fSJim Ingham 
585*3a0b9cdfSJim Ingham                     if (attach_pid == LLDB_INVALID_PROCESS_ID && wait_name != NULL)
5865aee162fSJim Ingham                     {
5875aee162fSJim Ingham                         std::vector<lldb::pid_t> pids;
5885aee162fSJim Ingham                         StringList matches;
5895aee162fSJim Ingham 
590*3a0b9cdfSJim Ingham                         process->ListProcessesMatchingName(wait_name, matches, pids);
5915aee162fSJim Ingham                         if (matches.GetSize() > 1)
5925aee162fSJim Ingham                         {
593*3a0b9cdfSJim Ingham                             result.AppendErrorWithFormat("More than one process named %s\n", wait_name);
5945aee162fSJim Ingham                             result.SetStatus (eReturnStatusFailed);
5955aee162fSJim Ingham                             return false;
5965aee162fSJim Ingham                         }
5975aee162fSJim Ingham                         else if (matches.GetSize() == 0)
5985aee162fSJim Ingham                         {
599*3a0b9cdfSJim Ingham                             result.AppendErrorWithFormat("Could not find a process named %s\n", wait_name);
6005aee162fSJim Ingham                             result.SetStatus (eReturnStatusFailed);
6015aee162fSJim Ingham                             return false;
6025aee162fSJim Ingham                         }
6035aee162fSJim Ingham                         else
6045aee162fSJim Ingham                         {
6055aee162fSJim Ingham                             attach_pid = pids[0];
6065aee162fSJim Ingham                         }
6075aee162fSJim Ingham 
6085aee162fSJim Ingham                     }
6095aee162fSJim Ingham 
6105aee162fSJim Ingham                     if (attach_pid != LLDB_INVALID_PROCESS_ID)
6115aee162fSJim Ingham                     {
6125aee162fSJim Ingham                         error = process->Attach (attach_pid);
6135aee162fSJim Ingham                         if (error.Success())
6145aee162fSJim Ingham                         {
6155aee162fSJim Ingham                             result.SetStatus (eReturnStatusSuccessContinuingNoResult);
6165aee162fSJim Ingham                         }
6175aee162fSJim Ingham                         else
6185aee162fSJim Ingham                         {
6195aee162fSJim Ingham                             result.AppendErrorWithFormat ("Attaching to process %i failed: %s.\n",
6205aee162fSJim Ingham                                                          attach_pid,
6215aee162fSJim Ingham                                                          error.AsCString());
6225aee162fSJim Ingham                             result.SetStatus (eReturnStatusFailed);
6235aee162fSJim Ingham                         }
6245aee162fSJim Ingham                     }
6255aee162fSJim Ingham                     else
6265aee162fSJim Ingham                     {
6275aee162fSJim Ingham                         result.AppendErrorWithFormat ("No PID specified for attach\n",
6285aee162fSJim Ingham                                                          attach_pid,
6295aee162fSJim Ingham                                                          error.AsCString());
6305aee162fSJim Ingham                         result.SetStatus (eReturnStatusFailed);
6315aee162fSJim Ingham 
6325aee162fSJim Ingham                     }
6335aee162fSJim Ingham                 }
6345aee162fSJim Ingham             }
6355aee162fSJim Ingham         }
6365aee162fSJim Ingham 
6375aee162fSJim Ingham         if (result.Succeeded())
6385aee162fSJim Ingham         {
6395aee162fSJim Ingham             // Okay, we're done.  Last step is to warn if the executable module has changed:
6405aee162fSJim Ingham             if (!old_exec_module_sp)
6415aee162fSJim Ingham             {
6425aee162fSJim Ingham                 char new_path[PATH_MAX + 1];
6435aee162fSJim Ingham                 target->GetExecutableModule()->GetFileSpec().GetPath(new_path, PATH_MAX);
6445aee162fSJim Ingham 
6455aee162fSJim Ingham                 result.AppendMessageWithFormat("Executable module set to \"%s\".\n",
6465aee162fSJim Ingham                     new_path);
6475aee162fSJim Ingham             }
6485aee162fSJim Ingham             else if (old_exec_module_sp->GetFileSpec() != target->GetExecutableModule()->GetFileSpec())
6495aee162fSJim Ingham             {
6505aee162fSJim Ingham                 char old_path[PATH_MAX + 1];
6515aee162fSJim Ingham                 char new_path[PATH_MAX + 1];
6525aee162fSJim Ingham 
6535aee162fSJim Ingham                 old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX);
6545aee162fSJim Ingham                 target->GetExecutableModule()->GetFileSpec().GetPath (new_path, PATH_MAX);
6555aee162fSJim Ingham 
6565aee162fSJim Ingham                 result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n",
6575aee162fSJim Ingham                                                     old_path, new_path);
6585aee162fSJim Ingham             }
6595aee162fSJim Ingham 
6605aee162fSJim Ingham             if (!old_arch_spec.IsValid())
6615aee162fSJim Ingham             {
6625aee162fSJim Ingham                 result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().AsCString());
6635aee162fSJim Ingham             }
6645aee162fSJim Ingham             else if (old_arch_spec != target->GetArchitecture())
6655aee162fSJim Ingham             {
6665aee162fSJim Ingham                 result.AppendWarningWithFormat("Architecture changed from %s to %s.\n",
6675aee162fSJim Ingham                                                 old_arch_spec.AsCString(), target->GetArchitecture().AsCString());
6685aee162fSJim Ingham             }
6695aee162fSJim Ingham         }
6705aee162fSJim Ingham         return result.Succeeded();
6715aee162fSJim Ingham     }
6725aee162fSJim Ingham 
6735aee162fSJim Ingham     Options *
6745aee162fSJim Ingham     GetOptions ()
6755aee162fSJim Ingham     {
6765aee162fSJim Ingham         return &m_options;
6775aee162fSJim Ingham     }
6785aee162fSJim Ingham 
67930fdc8d8SChris Lattner protected:
68030fdc8d8SChris Lattner 
68130fdc8d8SChris Lattner     CommandOptions m_options;
68230fdc8d8SChris Lattner };
68330fdc8d8SChris Lattner 
68430fdc8d8SChris Lattner 
68530fdc8d8SChris Lattner lldb::OptionDefinition
68630fdc8d8SChris Lattner CommandObjectProcessAttach::CommandOptions::g_option_table[] =
68730fdc8d8SChris Lattner {
6888651121cSJim Ingham { LLDB_OPT_SET_ALL, false, "plugin",       'P', required_argument, NULL, 0, "<plugin>",        "Name of the process plugin you want to use."},
6898651121cSJim Ingham { LLDB_OPT_SET_1, false, "pid",          'p', required_argument, NULL, 0, "<pid>",           "The process ID of an existing process to attach to."},
690*3a0b9cdfSJim Ingham { LLDB_OPT_SET_2, false,  "name",         'n', required_argument, NULL, 0, "<process-name>",  "The name of the process to attach to."},
6918651121cSJim Ingham { LLDB_OPT_SET_2, false, "waitfor",      'w', no_argument,       NULL, 0, NULL,              "Wait for the the process with <process-name> to launch."},
69230fdc8d8SChris Lattner { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
69330fdc8d8SChris Lattner };
69430fdc8d8SChris Lattner 
69530fdc8d8SChris Lattner //-------------------------------------------------------------------------
69630fdc8d8SChris Lattner // CommandObjectProcessContinue
69730fdc8d8SChris Lattner //-------------------------------------------------------------------------
69830fdc8d8SChris Lattner 
69930fdc8d8SChris Lattner class CommandObjectProcessContinue : public CommandObject
70030fdc8d8SChris Lattner {
70130fdc8d8SChris Lattner public:
70230fdc8d8SChris Lattner 
70330fdc8d8SChris Lattner     CommandObjectProcessContinue () :
70430fdc8d8SChris Lattner         CommandObject ("process continue",
705e3d26315SCaroline Tice                        "Continue execution of all threads in the current process.",
70630fdc8d8SChris Lattner                        "process continue",
70730fdc8d8SChris Lattner                        eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
70830fdc8d8SChris Lattner     {
70930fdc8d8SChris Lattner     }
71030fdc8d8SChris Lattner 
71130fdc8d8SChris Lattner 
71230fdc8d8SChris Lattner     ~CommandObjectProcessContinue ()
71330fdc8d8SChris Lattner     {
71430fdc8d8SChris Lattner     }
71530fdc8d8SChris Lattner 
71630fdc8d8SChris Lattner     bool
7176611103cSGreg Clayton     Execute (CommandInterpreter &interpreter,
7186611103cSGreg Clayton              Args& command,
71930fdc8d8SChris Lattner              CommandReturnObject &result)
72030fdc8d8SChris Lattner     {
7216611103cSGreg Clayton         Process *process = interpreter.GetDebugger().GetExecutionContext().process;
7226611103cSGreg Clayton         bool synchronous_execution = interpreter.GetSynchronous ();
72330fdc8d8SChris Lattner 
72430fdc8d8SChris Lattner         if (process == NULL)
72530fdc8d8SChris Lattner         {
72630fdc8d8SChris Lattner             result.AppendError ("no process to continue");
72730fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
72830fdc8d8SChris Lattner             return false;
72930fdc8d8SChris Lattner          }
73030fdc8d8SChris Lattner 
73130fdc8d8SChris Lattner         StateType state = process->GetState();
73230fdc8d8SChris Lattner         if (state == eStateStopped)
73330fdc8d8SChris Lattner         {
73430fdc8d8SChris Lattner             if (command.GetArgumentCount() != 0)
73530fdc8d8SChris Lattner             {
73630fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str());
73730fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
73830fdc8d8SChris Lattner                 return false;
73930fdc8d8SChris Lattner             }
74030fdc8d8SChris Lattner 
74130fdc8d8SChris Lattner             const uint32_t num_threads = process->GetThreadList().GetSize();
74230fdc8d8SChris Lattner 
74330fdc8d8SChris Lattner             // Set the actions that the threads should each take when resuming
74430fdc8d8SChris Lattner             for (uint32_t idx=0; idx<num_threads; ++idx)
74530fdc8d8SChris Lattner             {
74630fdc8d8SChris Lattner                 process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning);
74730fdc8d8SChris Lattner             }
74830fdc8d8SChris Lattner 
74930fdc8d8SChris Lattner             Error error(process->Resume());
75030fdc8d8SChris Lattner             if (error.Success())
75130fdc8d8SChris Lattner             {
75230fdc8d8SChris Lattner                 result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID());
75330fdc8d8SChris Lattner                 if (synchronous_execution)
75430fdc8d8SChris Lattner                 {
755b132097bSGreg Clayton                     state = process->WaitForProcessToStop (NULL);
75630fdc8d8SChris Lattner 
75730fdc8d8SChris Lattner                     result.SetDidChangeProcessState (true);
75830fdc8d8SChris Lattner                     result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
75930fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
76030fdc8d8SChris Lattner                 }
76130fdc8d8SChris Lattner                 else
76230fdc8d8SChris Lattner                 {
76330fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusSuccessContinuingNoResult);
76430fdc8d8SChris Lattner                 }
76530fdc8d8SChris Lattner             }
76630fdc8d8SChris Lattner             else
76730fdc8d8SChris Lattner             {
76830fdc8d8SChris Lattner                 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
76930fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
77030fdc8d8SChris Lattner             }
77130fdc8d8SChris Lattner         }
77230fdc8d8SChris Lattner         else
77330fdc8d8SChris Lattner         {
77430fdc8d8SChris Lattner             result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
77530fdc8d8SChris Lattner                                          StateAsCString(state));
77630fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
77730fdc8d8SChris Lattner         }
77830fdc8d8SChris Lattner         return result.Succeeded();
77930fdc8d8SChris Lattner     }
78030fdc8d8SChris Lattner };
78130fdc8d8SChris Lattner 
78230fdc8d8SChris Lattner //-------------------------------------------------------------------------
78330fdc8d8SChris Lattner // CommandObjectProcessDetach
78430fdc8d8SChris Lattner //-------------------------------------------------------------------------
78530fdc8d8SChris Lattner 
78630fdc8d8SChris Lattner class CommandObjectProcessDetach : public CommandObject
78730fdc8d8SChris Lattner {
78830fdc8d8SChris Lattner public:
78930fdc8d8SChris Lattner 
79030fdc8d8SChris Lattner     CommandObjectProcessDetach () :
79130fdc8d8SChris Lattner         CommandObject ("process detach",
792e3d26315SCaroline Tice                        "Detach from the current process being debugged.",
79330fdc8d8SChris Lattner                        "process detach",
79430fdc8d8SChris Lattner                        eFlagProcessMustBeLaunched)
79530fdc8d8SChris Lattner     {
79630fdc8d8SChris Lattner     }
79730fdc8d8SChris Lattner 
79830fdc8d8SChris Lattner     ~CommandObjectProcessDetach ()
79930fdc8d8SChris Lattner     {
80030fdc8d8SChris Lattner     }
80130fdc8d8SChris Lattner 
80230fdc8d8SChris Lattner     bool
8036611103cSGreg Clayton     Execute (CommandInterpreter &interpreter,
8046611103cSGreg Clayton              Args& command,
80530fdc8d8SChris Lattner              CommandReturnObject &result)
80630fdc8d8SChris Lattner     {
8076611103cSGreg Clayton         Process *process = interpreter.GetDebugger().GetExecutionContext().process;
80830fdc8d8SChris Lattner         if (process == NULL)
80930fdc8d8SChris Lattner         {
81030fdc8d8SChris Lattner             result.AppendError ("must have a valid process in order to detach");
81130fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
81230fdc8d8SChris Lattner             return false;
81330fdc8d8SChris Lattner         }
81430fdc8d8SChris Lattner 
81530fdc8d8SChris Lattner         Error error (process->Detach());
81630fdc8d8SChris Lattner         if (error.Success())
81730fdc8d8SChris Lattner         {
81830fdc8d8SChris Lattner             result.SetStatus (eReturnStatusSuccessFinishResult);
81930fdc8d8SChris Lattner         }
82030fdc8d8SChris Lattner         else
82130fdc8d8SChris Lattner         {
82230fdc8d8SChris Lattner             result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString());
82330fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
82430fdc8d8SChris Lattner             return false;
82530fdc8d8SChris Lattner         }
82630fdc8d8SChris Lattner         return result.Succeeded();
82730fdc8d8SChris Lattner     }
82830fdc8d8SChris Lattner };
82930fdc8d8SChris Lattner 
83030fdc8d8SChris Lattner //-------------------------------------------------------------------------
83130fdc8d8SChris Lattner // CommandObjectProcessSignal
83230fdc8d8SChris Lattner //-------------------------------------------------------------------------
83330fdc8d8SChris Lattner 
83430fdc8d8SChris Lattner class CommandObjectProcessSignal : public CommandObject
83530fdc8d8SChris Lattner {
83630fdc8d8SChris Lattner public:
83730fdc8d8SChris Lattner 
83830fdc8d8SChris Lattner     CommandObjectProcessSignal () :
83930fdc8d8SChris Lattner         CommandObject ("process signal",
840e3d26315SCaroline Tice                        "Send a UNIX signal to the current process being debugged.",
84130fdc8d8SChris Lattner                        "process signal <unix-signal-number>")
84230fdc8d8SChris Lattner     {
84330fdc8d8SChris Lattner     }
84430fdc8d8SChris Lattner 
84530fdc8d8SChris Lattner     ~CommandObjectProcessSignal ()
84630fdc8d8SChris Lattner     {
84730fdc8d8SChris Lattner     }
84830fdc8d8SChris Lattner 
84930fdc8d8SChris Lattner     bool
8506611103cSGreg Clayton     Execute (CommandInterpreter &interpreter,
8516611103cSGreg Clayton              Args& command,
85230fdc8d8SChris Lattner              CommandReturnObject &result)
85330fdc8d8SChris Lattner     {
8546611103cSGreg Clayton         Process *process = interpreter.GetDebugger().GetExecutionContext().process;
85530fdc8d8SChris Lattner         if (process == NULL)
85630fdc8d8SChris Lattner         {
85730fdc8d8SChris Lattner             result.AppendError ("no process to signal");
85830fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
85930fdc8d8SChris Lattner             return false;
86030fdc8d8SChris Lattner         }
86130fdc8d8SChris Lattner 
86230fdc8d8SChris Lattner         if (command.GetArgumentCount() == 1)
86330fdc8d8SChris Lattner         {
86430fdc8d8SChris Lattner             int signo = Args::StringToSInt32(command.GetArgumentAtIndex(0), -1, 0);
86530fdc8d8SChris Lattner             if (signo == -1)
86630fdc8d8SChris Lattner             {
86730fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0));
86830fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
86930fdc8d8SChris Lattner             }
87030fdc8d8SChris Lattner             else
87130fdc8d8SChris Lattner             {
87230fdc8d8SChris Lattner                 Error error (process->Signal (signo));
87330fdc8d8SChris Lattner                 if (error.Success())
87430fdc8d8SChris Lattner                 {
87530fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusSuccessFinishResult);
87630fdc8d8SChris Lattner                 }
87730fdc8d8SChris Lattner                 else
87830fdc8d8SChris Lattner                 {
87930fdc8d8SChris Lattner                     result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString());
88030fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusFailed);
88130fdc8d8SChris Lattner                 }
88230fdc8d8SChris Lattner             }
88330fdc8d8SChris Lattner         }
88430fdc8d8SChris Lattner         else
88530fdc8d8SChris Lattner         {
88630fdc8d8SChris Lattner             result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: \n", m_cmd_name.c_str(),
88730fdc8d8SChris Lattner                                         m_cmd_syntax.c_str());
88830fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
88930fdc8d8SChris Lattner         }
89030fdc8d8SChris Lattner         return result.Succeeded();
89130fdc8d8SChris Lattner     }
89230fdc8d8SChris Lattner };
89330fdc8d8SChris Lattner 
89430fdc8d8SChris Lattner 
89530fdc8d8SChris Lattner //-------------------------------------------------------------------------
89630fdc8d8SChris Lattner // CommandObjectProcessInterrupt
89730fdc8d8SChris Lattner //-------------------------------------------------------------------------
89830fdc8d8SChris Lattner 
89930fdc8d8SChris Lattner class CommandObjectProcessInterrupt : public CommandObject
90030fdc8d8SChris Lattner {
90130fdc8d8SChris Lattner public:
90230fdc8d8SChris Lattner 
90330fdc8d8SChris Lattner 
90430fdc8d8SChris Lattner     CommandObjectProcessInterrupt () :
90530fdc8d8SChris Lattner     CommandObject ("process interrupt",
906e3d26315SCaroline Tice                    "Interrupt the current process being debugged.",
90730fdc8d8SChris Lattner                    "process interrupt",
90830fdc8d8SChris Lattner                    eFlagProcessMustBeLaunched)
90930fdc8d8SChris Lattner     {
91030fdc8d8SChris Lattner     }
91130fdc8d8SChris Lattner 
91230fdc8d8SChris Lattner     ~CommandObjectProcessInterrupt ()
91330fdc8d8SChris Lattner     {
91430fdc8d8SChris Lattner     }
91530fdc8d8SChris Lattner 
91630fdc8d8SChris Lattner     bool
9176611103cSGreg Clayton     Execute (CommandInterpreter &interpreter,
9186611103cSGreg Clayton              Args& command,
91930fdc8d8SChris Lattner              CommandReturnObject &result)
92030fdc8d8SChris Lattner     {
9216611103cSGreg Clayton         Process *process = interpreter.GetDebugger().GetExecutionContext().process;
92230fdc8d8SChris Lattner         if (process == NULL)
92330fdc8d8SChris Lattner         {
92430fdc8d8SChris Lattner             result.AppendError ("no process to halt");
92530fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
92630fdc8d8SChris Lattner             return false;
92730fdc8d8SChris Lattner         }
92830fdc8d8SChris Lattner 
92930fdc8d8SChris Lattner         if (command.GetArgumentCount() == 0)
93030fdc8d8SChris Lattner         {
93130fdc8d8SChris Lattner             Error error(process->Halt ());
93230fdc8d8SChris Lattner             if (error.Success())
93330fdc8d8SChris Lattner             {
93430fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusSuccessFinishResult);
93530fdc8d8SChris Lattner 
93630fdc8d8SChris Lattner                 // Maybe we should add a "SuspendThreadPlans so we
93730fdc8d8SChris Lattner                 // can halt, and keep in place all the current thread plans.
93830fdc8d8SChris Lattner                 process->GetThreadList().DiscardThreadPlans();
93930fdc8d8SChris Lattner             }
94030fdc8d8SChris Lattner             else
94130fdc8d8SChris Lattner             {
94230fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString());
94330fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
94430fdc8d8SChris Lattner             }
94530fdc8d8SChris Lattner         }
94630fdc8d8SChris Lattner         else
94730fdc8d8SChris Lattner         {
94830fdc8d8SChris Lattner             result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
94930fdc8d8SChris Lattner                                         m_cmd_name.c_str(),
95030fdc8d8SChris Lattner                                         m_cmd_syntax.c_str());
95130fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
95230fdc8d8SChris Lattner         }
95330fdc8d8SChris Lattner         return result.Succeeded();
95430fdc8d8SChris Lattner     }
95530fdc8d8SChris Lattner };
95630fdc8d8SChris Lattner 
95730fdc8d8SChris Lattner //-------------------------------------------------------------------------
95830fdc8d8SChris Lattner // CommandObjectProcessKill
95930fdc8d8SChris Lattner //-------------------------------------------------------------------------
96030fdc8d8SChris Lattner 
96130fdc8d8SChris Lattner class CommandObjectProcessKill : public CommandObject
96230fdc8d8SChris Lattner {
96330fdc8d8SChris Lattner public:
96430fdc8d8SChris Lattner 
96530fdc8d8SChris Lattner     CommandObjectProcessKill () :
96630fdc8d8SChris Lattner     CommandObject ("process kill",
967e3d26315SCaroline Tice                    "Terminate the current process being debugged.",
96830fdc8d8SChris Lattner                    "process kill",
96930fdc8d8SChris Lattner                    eFlagProcessMustBeLaunched)
97030fdc8d8SChris Lattner     {
97130fdc8d8SChris Lattner     }
97230fdc8d8SChris Lattner 
97330fdc8d8SChris Lattner     ~CommandObjectProcessKill ()
97430fdc8d8SChris Lattner     {
97530fdc8d8SChris Lattner     }
97630fdc8d8SChris Lattner 
97730fdc8d8SChris Lattner     bool
9786611103cSGreg Clayton     Execute (CommandInterpreter &interpreter,
9796611103cSGreg Clayton              Args& command,
98030fdc8d8SChris Lattner              CommandReturnObject &result)
98130fdc8d8SChris Lattner     {
9826611103cSGreg Clayton         Process *process = interpreter.GetDebugger().GetExecutionContext().process;
98330fdc8d8SChris Lattner         if (process == NULL)
98430fdc8d8SChris Lattner         {
98530fdc8d8SChris Lattner             result.AppendError ("no process to kill");
98630fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
98730fdc8d8SChris Lattner             return false;
98830fdc8d8SChris Lattner         }
98930fdc8d8SChris Lattner 
99030fdc8d8SChris Lattner         if (command.GetArgumentCount() == 0)
99130fdc8d8SChris Lattner         {
99230fdc8d8SChris Lattner             Error error (process->Destroy());
99330fdc8d8SChris Lattner             if (error.Success())
99430fdc8d8SChris Lattner             {
99530fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusSuccessFinishResult);
99630fdc8d8SChris Lattner             }
99730fdc8d8SChris Lattner             else
99830fdc8d8SChris Lattner             {
99930fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString());
100030fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
100130fdc8d8SChris Lattner             }
100230fdc8d8SChris Lattner         }
100330fdc8d8SChris Lattner         else
100430fdc8d8SChris Lattner         {
100530fdc8d8SChris Lattner             result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
100630fdc8d8SChris Lattner                                         m_cmd_name.c_str(),
100730fdc8d8SChris Lattner                                         m_cmd_syntax.c_str());
100830fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
100930fdc8d8SChris Lattner         }
101030fdc8d8SChris Lattner         return result.Succeeded();
101130fdc8d8SChris Lattner     }
101230fdc8d8SChris Lattner };
101330fdc8d8SChris Lattner 
101430fdc8d8SChris Lattner //-------------------------------------------------------------------------
10154b9bea87SJim Ingham // CommandObjectProcessStatus
10164b9bea87SJim Ingham //-------------------------------------------------------------------------
10174b9bea87SJim Ingham class CommandObjectProcessStatus : public CommandObject
10184b9bea87SJim Ingham {
10194b9bea87SJim Ingham public:
10204b9bea87SJim Ingham     CommandObjectProcessStatus () :
1021e3d26315SCaroline Tice     CommandObject ("process status",
1022e3d26315SCaroline Tice                    "Show the current status and location of executing process.",
1023e3d26315SCaroline Tice                    "process status",
10244b9bea87SJim Ingham                    0)
10254b9bea87SJim Ingham     {
10264b9bea87SJim Ingham     }
10274b9bea87SJim Ingham 
10284b9bea87SJim Ingham     ~CommandObjectProcessStatus()
10294b9bea87SJim Ingham     {
10304b9bea87SJim Ingham     }
10314b9bea87SJim Ingham 
10324b9bea87SJim Ingham 
10334b9bea87SJim Ingham     bool
10344b9bea87SJim Ingham     Execute
10354b9bea87SJim Ingham     (
10366611103cSGreg Clayton         CommandInterpreter &interpreter,
10374b9bea87SJim Ingham         Args& command,
10384b9bea87SJim Ingham         CommandReturnObject &result
10394b9bea87SJim Ingham     )
10404b9bea87SJim Ingham     {
10414b9bea87SJim Ingham         StreamString &output_stream = result.GetOutputStream();
10424b9bea87SJim Ingham         result.SetStatus (eReturnStatusSuccessFinishNoResult);
10436611103cSGreg Clayton         ExecutionContext exe_ctx(interpreter.GetDebugger().GetExecutionContext());
10444b9bea87SJim Ingham         if (exe_ctx.process)
10454b9bea87SJim Ingham         {
10464b9bea87SJim Ingham             const StateType state = exe_ctx.process->GetState();
10474b9bea87SJim Ingham             if (StateIsStoppedState(state))
10484b9bea87SJim Ingham             {
10494b9bea87SJim Ingham                 if (state == eStateExited)
10504b9bea87SJim Ingham                 {
10514b9bea87SJim Ingham                     int exit_status = exe_ctx.process->GetExitStatus();
10524b9bea87SJim Ingham                     const char *exit_description = exe_ctx.process->GetExitDescription();
10534b9bea87SJim Ingham                     output_stream.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n",
10544b9bea87SJim Ingham                                           exe_ctx.process->GetID(),
10554b9bea87SJim Ingham                                           exit_status,
10564b9bea87SJim Ingham                                           exit_status,
10574b9bea87SJim Ingham                                           exit_description ? exit_description : "");
10584b9bea87SJim Ingham                 }
10594b9bea87SJim Ingham                 else
10604b9bea87SJim Ingham                 {
10614b9bea87SJim Ingham                     output_stream.Printf ("Process %d %s\n", exe_ctx.process->GetID(), StateAsCString (state));
10624b9bea87SJim Ingham                     if (exe_ctx.thread == NULL)
10634b9bea87SJim Ingham                         exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
10644b9bea87SJim Ingham                     if (exe_ctx.thread != NULL)
10654b9bea87SJim Ingham                     {
10664b9bea87SJim Ingham                         DisplayThreadsInfo (interpreter, &exe_ctx, result, true, true);
10674b9bea87SJim Ingham                     }
10684b9bea87SJim Ingham                     else
10694b9bea87SJim Ingham                     {
10704b9bea87SJim Ingham                         result.AppendError ("No valid thread found in current process.");
10714b9bea87SJim Ingham                         result.SetStatus (eReturnStatusFailed);
10724b9bea87SJim Ingham                     }
10734b9bea87SJim Ingham                 }
10744b9bea87SJim Ingham             }
10754b9bea87SJim Ingham             else
10764b9bea87SJim Ingham             {
10774b9bea87SJim Ingham                 output_stream.Printf ("Process %d is running.\n",
10784b9bea87SJim Ingham                                           exe_ctx.process->GetID());
10794b9bea87SJim Ingham             }
10804b9bea87SJim Ingham         }
10814b9bea87SJim Ingham         else
10824b9bea87SJim Ingham         {
10834b9bea87SJim Ingham             result.AppendError ("No current location or status available.");
10844b9bea87SJim Ingham             result.SetStatus (eReturnStatusFailed);
10854b9bea87SJim Ingham         }
10864b9bea87SJim Ingham         return result.Succeeded();
10874b9bea87SJim Ingham     }
10884b9bea87SJim Ingham };
10894b9bea87SJim Ingham 
10904b9bea87SJim Ingham //-------------------------------------------------------------------------
109130fdc8d8SChris Lattner // CommandObjectMultiwordProcess
109230fdc8d8SChris Lattner //-------------------------------------------------------------------------
109330fdc8d8SChris Lattner 
10946611103cSGreg Clayton CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter &interpreter) :
109530fdc8d8SChris Lattner     CommandObjectMultiword ("process",
109630fdc8d8SChris Lattner                               "A set of commands for operating on a process.",
109730fdc8d8SChris Lattner                               "process <subcommand> [<subcommand-options>]")
109830fdc8d8SChris Lattner {
10996611103cSGreg Clayton     LoadSubCommand (interpreter, "attach",      CommandObjectSP (new CommandObjectProcessAttach ()));
11006611103cSGreg Clayton     LoadSubCommand (interpreter, "launch",      CommandObjectSP (new CommandObjectProcessLaunch ()));
11016611103cSGreg Clayton     LoadSubCommand (interpreter, "continue",    CommandObjectSP (new CommandObjectProcessContinue ()));
11026611103cSGreg Clayton     LoadSubCommand (interpreter, "detach",      CommandObjectSP (new CommandObjectProcessDetach ()));
11036611103cSGreg Clayton     LoadSubCommand (interpreter, "signal",      CommandObjectSP (new CommandObjectProcessSignal ()));
11046611103cSGreg Clayton     LoadSubCommand (interpreter, "status",      CommandObjectSP (new CommandObjectProcessStatus ()));
11056611103cSGreg Clayton     LoadSubCommand (interpreter, "interrupt",   CommandObjectSP (new CommandObjectProcessInterrupt ()));
11066611103cSGreg Clayton     LoadSubCommand (interpreter, "kill",        CommandObjectSP (new CommandObjectProcessKill ()));
110730fdc8d8SChris Lattner }
110830fdc8d8SChris Lattner 
110930fdc8d8SChris Lattner CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess ()
111030fdc8d8SChris Lattner {
111130fdc8d8SChris Lattner }
111230fdc8d8SChris Lattner 
1113