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;
6519388cfcSGreg Clayton                 case 't':   in_new_tty = true; break;
6630fdc8d8SChris Lattner                 default:
6730fdc8d8SChris Lattner                     error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
6830fdc8d8SChris Lattner                     break;
6930fdc8d8SChris Lattner 
7030fdc8d8SChris Lattner             }
7130fdc8d8SChris Lattner             return error;
7230fdc8d8SChris Lattner         }
7330fdc8d8SChris Lattner 
7430fdc8d8SChris Lattner         void
7530fdc8d8SChris Lattner         ResetOptionValues ()
7630fdc8d8SChris Lattner         {
7730fdc8d8SChris Lattner             Options::ResetOptionValues();
7830fdc8d8SChris Lattner             stop_at_entry = false;
7919388cfcSGreg Clayton             in_new_tty = false;
8030fdc8d8SChris Lattner             stdin_path.clear();
8130fdc8d8SChris Lattner             stdout_path.clear();
8230fdc8d8SChris Lattner             stderr_path.clear();
8330fdc8d8SChris Lattner             plugin_name.clear();
8430fdc8d8SChris Lattner         }
8530fdc8d8SChris Lattner 
8630fdc8d8SChris Lattner         const lldb::OptionDefinition*
8730fdc8d8SChris Lattner         GetDefinitions ()
8830fdc8d8SChris Lattner         {
8930fdc8d8SChris Lattner             return g_option_table;
9030fdc8d8SChris Lattner         }
9130fdc8d8SChris Lattner 
9230fdc8d8SChris Lattner         // Options table: Required for subclasses of Options.
9330fdc8d8SChris Lattner 
9430fdc8d8SChris Lattner         static lldb::OptionDefinition g_option_table[];
9530fdc8d8SChris Lattner 
9630fdc8d8SChris Lattner         // Instance variables to hold the values for command options.
9730fdc8d8SChris Lattner 
9830fdc8d8SChris Lattner         bool stop_at_entry;
9919388cfcSGreg Clayton         bool in_new_tty;
10030fdc8d8SChris Lattner         std::string stderr_path;
10130fdc8d8SChris Lattner         std::string stdin_path;
10230fdc8d8SChris Lattner         std::string stdout_path;
10330fdc8d8SChris Lattner         std::string plugin_name;
10430fdc8d8SChris Lattner 
10530fdc8d8SChris Lattner     };
10630fdc8d8SChris Lattner 
107a7015092SGreg Clayton     CommandObjectProcessLaunch (CommandInterpreter &interpreter) :
108a7015092SGreg Clayton         CommandObject (interpreter,
109a7015092SGreg Clayton                        "process launch",
110e3d26315SCaroline Tice                        "Launch the executable in the debugger.",
111405fe67fSCaroline Tice                        NULL)
11230fdc8d8SChris Lattner     {
113405fe67fSCaroline Tice         CommandArgumentEntry arg;
114405fe67fSCaroline Tice         CommandArgumentData run_args_arg;
115405fe67fSCaroline Tice 
116405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
117405fe67fSCaroline Tice         run_args_arg.arg_type = eArgTypeRunArgs;
118405fe67fSCaroline Tice         run_args_arg.arg_repetition = eArgRepeatOptional;
119405fe67fSCaroline Tice 
120405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
121405fe67fSCaroline Tice         arg.push_back (run_args_arg);
122405fe67fSCaroline Tice 
123405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
124405fe67fSCaroline Tice         m_arguments.push_back (arg);
12530fdc8d8SChris Lattner     }
12630fdc8d8SChris Lattner 
12730fdc8d8SChris Lattner 
12830fdc8d8SChris Lattner     ~CommandObjectProcessLaunch ()
12930fdc8d8SChris Lattner     {
13030fdc8d8SChris Lattner     }
13130fdc8d8SChris Lattner 
13230fdc8d8SChris Lattner     Options *
13330fdc8d8SChris Lattner     GetOptions ()
13430fdc8d8SChris Lattner     {
13530fdc8d8SChris Lattner         return &m_options;
13630fdc8d8SChris Lattner     }
13730fdc8d8SChris Lattner 
13830fdc8d8SChris Lattner     bool
13905faeb71SGreg Clayton     Execute (Args& launch_args, CommandReturnObject &result)
14030fdc8d8SChris Lattner     {
141a7015092SGreg Clayton         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
14230fdc8d8SChris Lattner 
14330fdc8d8SChris Lattner         if (target == NULL)
14430fdc8d8SChris Lattner         {
14530fdc8d8SChris Lattner             result.AppendError ("invalid target, set executable file using 'file' command");
14630fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
14730fdc8d8SChris Lattner             return false;
14830fdc8d8SChris Lattner         }
14930fdc8d8SChris Lattner 
15030fdc8d8SChris Lattner         // If our listener is NULL, users aren't allows to launch
15130fdc8d8SChris Lattner         char filename[PATH_MAX];
15219388cfcSGreg Clayton         const Module *exe_module = target->GetExecutableModule().get();
15330fdc8d8SChris Lattner         exe_module->GetFileSpec().GetPath(filename, sizeof(filename));
15430fdc8d8SChris Lattner 
155a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
156a7015092SGreg Clayton         if (process && process->IsAlive())
15730fdc8d8SChris Lattner         {
15830fdc8d8SChris Lattner             result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before running again.\n",
15930fdc8d8SChris Lattner                                           process->GetID());
16030fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
16130fdc8d8SChris Lattner             return false;
16230fdc8d8SChris Lattner         }
16330fdc8d8SChris Lattner 
16430fdc8d8SChris Lattner         const char *plugin_name;
16530fdc8d8SChris Lattner         if (!m_options.plugin_name.empty())
16630fdc8d8SChris Lattner             plugin_name = m_options.plugin_name.c_str();
16730fdc8d8SChris Lattner         else
16830fdc8d8SChris Lattner             plugin_name = NULL;
16930fdc8d8SChris Lattner 
170a7015092SGreg Clayton         process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
17130fdc8d8SChris Lattner 
172a7015092SGreg Clayton         if (process == NULL)
1733df9a8dfSCaroline Tice         {
17443a8c39bSCaroline Tice             result.AppendErrorWithFormat ("Failed to find a process plugin for executable.\n");
175a7015092SGreg Clayton             result.SetStatus (eReturnStatusFailed);
176a7015092SGreg Clayton             return false;
1773df9a8dfSCaroline Tice         }
1783df9a8dfSCaroline Tice 
179a7015092SGreg Clayton         // If no launch args were given on the command line, then use any that
180a7015092SGreg Clayton         // might have been set using the "run-args" set variable.
18130fdc8d8SChris Lattner         if (launch_args.GetArgumentCount() == 0)
18230fdc8d8SChris Lattner         {
183a7015092SGreg Clayton             if (process->GetRunArguments().GetArgumentCount() > 0)
184a7015092SGreg Clayton                 launch_args = process->GetRunArguments();
18530fdc8d8SChris Lattner         }
18630fdc8d8SChris Lattner 
18719388cfcSGreg Clayton         if (m_options.in_new_tty)
18819388cfcSGreg Clayton         {
18919388cfcSGreg Clayton             char exec_file_path[PATH_MAX];
19019388cfcSGreg Clayton             if (exe_module->GetFileSpec().GetPath(exec_file_path, sizeof(exec_file_path)))
19119388cfcSGreg Clayton             {
19219388cfcSGreg Clayton                 launch_args.InsertArgumentAtIndex(0, exec_file_path);
19319388cfcSGreg Clayton             }
19419388cfcSGreg Clayton             else
19519388cfcSGreg Clayton             {
19619388cfcSGreg Clayton                 result.AppendError("invalid executable");
19719388cfcSGreg Clayton                 result.SetStatus (eReturnStatusFailed);
19819388cfcSGreg Clayton                 return false;
19919388cfcSGreg Clayton             }
20019388cfcSGreg Clayton         }
20119388cfcSGreg Clayton 
202a7015092SGreg Clayton         Args environment;
20330fdc8d8SChris Lattner 
204a7015092SGreg Clayton         process->GetEnvironmentAsArgs (environment);
205a7015092SGreg Clayton 
206a7015092SGreg Clayton         uint32_t launch_flags = eLaunchFlagNone;
207a7015092SGreg Clayton 
208a7015092SGreg Clayton         if (process->GetDisableASLR())
209a7015092SGreg Clayton             launch_flags |= eLaunchFlagDisableASLR;
210a7015092SGreg Clayton 
21119388cfcSGreg Clayton         const char **inferior_argv = launch_args.GetArgumentCount() ? launch_args.GetConstArgumentVector() : NULL;
21219388cfcSGreg Clayton         const char **inferior_envp = environment.GetArgumentCount() ? environment.GetConstArgumentVector() : NULL;
21330fdc8d8SChris Lattner 
21419388cfcSGreg Clayton         Error error;
21519388cfcSGreg Clayton 
21619388cfcSGreg Clayton         if (m_options.in_new_tty)
21719388cfcSGreg Clayton         {
21819388cfcSGreg Clayton 
219*3fcbed6bSGreg Clayton             lldb::pid_t pid = Host::LaunchInNewTerminal (inferior_argv,
22019388cfcSGreg Clayton                                                          inferior_envp,
22119388cfcSGreg Clayton                                                          &exe_module->GetArchitecture(),
22219388cfcSGreg Clayton                                                          true,
22319388cfcSGreg Clayton                                                          process->GetDisableASLR());
22419388cfcSGreg Clayton 
225*3fcbed6bSGreg Clayton             if (pid != LLDB_INVALID_PROCESS_ID)
226*3fcbed6bSGreg Clayton                 error = process->Attach (pid);
22719388cfcSGreg Clayton         }
22819388cfcSGreg Clayton         else
22919388cfcSGreg Clayton         {
23030fdc8d8SChris Lattner             const char * stdin_path = NULL;
23130fdc8d8SChris Lattner             const char * stdout_path = NULL;
23230fdc8d8SChris Lattner             const char * stderr_path = NULL;
23330fdc8d8SChris Lattner 
234a7015092SGreg Clayton             // Were any standard input/output/error paths given on the command line?
235a7015092SGreg Clayton             if (m_options.stdin_path.empty() &&
23630fdc8d8SChris Lattner                 m_options.stdout_path.empty() &&
237a7015092SGreg Clayton                 m_options.stderr_path.empty())
23830fdc8d8SChris Lattner             {
239a7015092SGreg Clayton                 // No standard file handles were given on the command line, check
240a7015092SGreg Clayton                 // with the process object in case they were give using "set settings"
241a7015092SGreg Clayton                 stdin_path = process->GetStandardInputPath();
242a7015092SGreg Clayton                 stdout_path = process->GetStandardOutputPath();
243a7015092SGreg Clayton                 stderr_path = process->GetStandardErrorPath();
244a7015092SGreg Clayton             }
245a7015092SGreg Clayton             else
246a7015092SGreg Clayton             {
247a7015092SGreg Clayton                 stdin_path = m_options.stdin_path.empty()  ? NULL : m_options.stdin_path.c_str();
248a7015092SGreg Clayton                 stdout_path = m_options.stdout_path.empty() ? NULL : m_options.stdout_path.c_str();
249a7015092SGreg Clayton                 stderr_path = m_options.stderr_path.empty() ? NULL : m_options.stderr_path.c_str();
25030fdc8d8SChris Lattner             }
25130fdc8d8SChris Lattner 
252a7015092SGreg Clayton             if (stdin_path == NULL)
253a7015092SGreg Clayton                 stdin_path = "/dev/null";
254a7015092SGreg Clayton             if (stdout_path == NULL)
255a7015092SGreg Clayton                 stdout_path = "/dev/null";
256a7015092SGreg Clayton             if (stderr_path == NULL)
257a7015092SGreg Clayton                 stderr_path = "/dev/null";
258a7015092SGreg Clayton 
25919388cfcSGreg Clayton             error = process->Launch (inferior_argv,
26019388cfcSGreg Clayton                                      inferior_envp,
261f681b94fSGreg Clayton                                      launch_flags,
26230fdc8d8SChris Lattner                                      stdin_path,
26330fdc8d8SChris Lattner                                      stdout_path,
26419388cfcSGreg Clayton                                      stderr_path);
26519388cfcSGreg Clayton         }
26630fdc8d8SChris Lattner 
26730fdc8d8SChris Lattner         if (error.Success())
26830fdc8d8SChris Lattner         {
26919388cfcSGreg Clayton             const char *archname = exe_module->GetArchitecture().AsCString();
27019388cfcSGreg Clayton 
27119388cfcSGreg Clayton             result.AppendMessageWithFormat ("Process %i launched: '%s' (%s)\n", process->GetID(), filename, archname);
27205faeb71SGreg Clayton             result.SetDidChangeProcessState (true);
27330fdc8d8SChris Lattner             if (m_options.stop_at_entry == false)
27430fdc8d8SChris Lattner             {
27505faeb71SGreg Clayton                 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
27630fdc8d8SChris Lattner                 StateType state = process->WaitForProcessToStop (NULL);
27730fdc8d8SChris Lattner 
27830fdc8d8SChris Lattner                 if (state == eStateStopped)
27930fdc8d8SChris Lattner                 {
28005faeb71SGreg Clayton                     error = process->Resume();
28105faeb71SGreg Clayton                     if (error.Success())
28205faeb71SGreg Clayton                     {
28305faeb71SGreg Clayton                         bool synchronous_execution = m_interpreter.GetSynchronous ();
28430fdc8d8SChris Lattner                         if (synchronous_execution)
28530fdc8d8SChris Lattner                         {
28605faeb71SGreg Clayton                             state = process->WaitForProcessToStop (NULL);
28730fdc8d8SChris Lattner                             result.SetDidChangeProcessState (true);
28805faeb71SGreg Clayton                             result.SetStatus (eReturnStatusSuccessFinishResult);
28905faeb71SGreg Clayton                         }
29005faeb71SGreg Clayton                         else
29105faeb71SGreg Clayton                         {
29205faeb71SGreg Clayton                             result.SetStatus (eReturnStatusSuccessContinuingNoResult);
29305faeb71SGreg Clayton                         }
29405faeb71SGreg Clayton                     }
29530fdc8d8SChris Lattner                 }
29630fdc8d8SChris Lattner             }
29730fdc8d8SChris Lattner         }
29830fdc8d8SChris Lattner 
29930fdc8d8SChris Lattner         return result.Succeeded();
30030fdc8d8SChris Lattner     }
30130fdc8d8SChris Lattner 
302ebc09c36SJim Ingham     virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
303ebc09c36SJim Ingham     {
304ebc09c36SJim Ingham         // No repeat for "process launch"...
305ebc09c36SJim Ingham         return "";
306ebc09c36SJim Ingham     }
307ebc09c36SJim Ingham 
30830fdc8d8SChris Lattner protected:
30930fdc8d8SChris Lattner 
31030fdc8d8SChris Lattner     CommandOptions m_options;
31130fdc8d8SChris Lattner };
31230fdc8d8SChris Lattner 
31330fdc8d8SChris Lattner 
31419388cfcSGreg Clayton #define SET1 LLDB_OPT_SET_1
31519388cfcSGreg Clayton #define SET2 LLDB_OPT_SET_2
31619388cfcSGreg Clayton 
31730fdc8d8SChris Lattner lldb::OptionDefinition
31830fdc8d8SChris Lattner CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
31930fdc8d8SChris Lattner {
32019388cfcSGreg Clayton { SET1 | SET2, false, "stop-at-entry", 's', no_argument,       NULL, 0, eArgTypeNone,    "Stop at the entry point of the program when launching a process."},
32119388cfcSGreg Clayton { SET1       , false, "stdin",         'i', required_argument, NULL, 0, eArgTypePath,    "Redirect stdin for the process to <path>."},
32219388cfcSGreg Clayton { SET1       , false, "stdout",        'o', required_argument, NULL, 0, eArgTypePath,    "Redirect stdout for the process to <path>."},
32319388cfcSGreg Clayton { SET1       , false, "stderr",        'e', required_argument, NULL, 0, eArgTypePath,    "Redirect stderr for the process to <path>."},
32419388cfcSGreg Clayton { SET1 | SET2, false, "plugin",        'p', required_argument, NULL, 0, eArgTypePlugin,  "Name of the process plugin you want to use."},
32519388cfcSGreg Clayton {        SET2, false, "tty",           't', no_argument,       NULL, 0, eArgTypeNone,    "Start the process in a new terminal (tty)."},
326deaab222SCaroline Tice { 0,           false, NULL,             0,  0,                 NULL, 0, eArgTypeNone,    NULL }
32730fdc8d8SChris Lattner };
32830fdc8d8SChris Lattner 
32919388cfcSGreg Clayton #undef SET1
33019388cfcSGreg Clayton #undef SET2
33130fdc8d8SChris Lattner 
33230fdc8d8SChris Lattner //-------------------------------------------------------------------------
33330fdc8d8SChris Lattner // CommandObjectProcessAttach
33430fdc8d8SChris Lattner //-------------------------------------------------------------------------
33530fdc8d8SChris Lattner 
33630fdc8d8SChris Lattner class CommandObjectProcessAttach : public CommandObject
33730fdc8d8SChris Lattner {
33830fdc8d8SChris Lattner public:
33930fdc8d8SChris Lattner 
34030fdc8d8SChris Lattner     class CommandOptions : public Options
34130fdc8d8SChris Lattner     {
34230fdc8d8SChris Lattner     public:
34330fdc8d8SChris Lattner 
34430fdc8d8SChris Lattner         CommandOptions () :
34530fdc8d8SChris Lattner             Options()
34630fdc8d8SChris Lattner         {
34730fdc8d8SChris Lattner             // Keep default values of all options in one place: ResetOptionValues ()
34830fdc8d8SChris Lattner             ResetOptionValues ();
34930fdc8d8SChris Lattner         }
35030fdc8d8SChris Lattner 
35130fdc8d8SChris Lattner         ~CommandOptions ()
35230fdc8d8SChris Lattner         {
35330fdc8d8SChris Lattner         }
35430fdc8d8SChris Lattner 
35530fdc8d8SChris Lattner         Error
35630fdc8d8SChris Lattner         SetOptionValue (int option_idx, const char *option_arg)
35730fdc8d8SChris Lattner         {
35830fdc8d8SChris Lattner             Error error;
35930fdc8d8SChris Lattner             char short_option = (char) m_getopt_table[option_idx].val;
36030fdc8d8SChris Lattner             bool success = false;
36130fdc8d8SChris Lattner             switch (short_option)
36230fdc8d8SChris Lattner             {
36330fdc8d8SChris Lattner                 case 'p':
36430fdc8d8SChris Lattner                     pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success);
36530fdc8d8SChris Lattner                     if (!success || pid == LLDB_INVALID_PROCESS_ID)
36630fdc8d8SChris Lattner                     {
36730fdc8d8SChris Lattner                         error.SetErrorStringWithFormat("Invalid process ID '%s'.\n", option_arg);
36830fdc8d8SChris Lattner                     }
36930fdc8d8SChris Lattner                     break;
37030fdc8d8SChris Lattner 
37130fdc8d8SChris Lattner                 case 'P':
37230fdc8d8SChris Lattner                     plugin_name = option_arg;
37330fdc8d8SChris Lattner                     break;
37430fdc8d8SChris Lattner 
37530fdc8d8SChris Lattner                 case 'n':
37630fdc8d8SChris Lattner                     name.assign(option_arg);
37730fdc8d8SChris Lattner                     break;
37830fdc8d8SChris Lattner 
37930fdc8d8SChris Lattner                 case 'w':
38030fdc8d8SChris Lattner                     waitfor = true;
38130fdc8d8SChris Lattner                     break;
38230fdc8d8SChris Lattner 
38330fdc8d8SChris Lattner                 default:
38430fdc8d8SChris Lattner                     error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
38530fdc8d8SChris Lattner                     break;
38630fdc8d8SChris Lattner             }
38730fdc8d8SChris Lattner             return error;
38830fdc8d8SChris Lattner         }
38930fdc8d8SChris Lattner 
39030fdc8d8SChris Lattner         void
39130fdc8d8SChris Lattner         ResetOptionValues ()
39230fdc8d8SChris Lattner         {
39330fdc8d8SChris Lattner             Options::ResetOptionValues();
39430fdc8d8SChris Lattner             pid = LLDB_INVALID_PROCESS_ID;
39530fdc8d8SChris Lattner             name.clear();
39630fdc8d8SChris Lattner             waitfor = false;
39730fdc8d8SChris Lattner         }
39830fdc8d8SChris Lattner 
39930fdc8d8SChris Lattner         const lldb::OptionDefinition*
40030fdc8d8SChris Lattner         GetDefinitions ()
40130fdc8d8SChris Lattner         {
40230fdc8d8SChris Lattner             return g_option_table;
40330fdc8d8SChris Lattner         }
40430fdc8d8SChris Lattner 
4055aee162fSJim Ingham         virtual bool
406a7015092SGreg Clayton         HandleOptionArgumentCompletion (CommandInterpreter &interpeter,
4075aee162fSJim Ingham                                         Args &input,
4085aee162fSJim Ingham                                         int cursor_index,
4095aee162fSJim Ingham                                         int char_pos,
4105aee162fSJim Ingham                                         OptionElementVector &opt_element_vector,
4115aee162fSJim Ingham                                         int opt_element_index,
4125aee162fSJim Ingham                                         int match_start_point,
4135aee162fSJim Ingham                                         int max_return_elements,
4145aee162fSJim Ingham                                         bool &word_complete,
4155aee162fSJim Ingham                                         StringList &matches)
4165aee162fSJim Ingham         {
4175aee162fSJim Ingham             int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
4185aee162fSJim Ingham             int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
4195aee162fSJim Ingham 
4205aee162fSJim Ingham             // We are only completing the name option for now...
4215aee162fSJim Ingham 
4225aee162fSJim Ingham             const lldb::OptionDefinition *opt_defs = GetDefinitions();
4235aee162fSJim Ingham             if (opt_defs[opt_defs_index].short_option == 'n')
4245aee162fSJim Ingham             {
4255aee162fSJim Ingham                 // Are we in the name?
4265aee162fSJim Ingham 
4275aee162fSJim Ingham                 // Look to see if there is a -P argument provided, and if so use that plugin, otherwise
4285aee162fSJim Ingham                 // use the default plugin.
429a7015092SGreg Clayton                 Process *process = interpeter.GetDebugger().GetExecutionContext().process;
4305aee162fSJim Ingham                 bool need_to_delete_process = false;
4315aee162fSJim Ingham 
4325aee162fSJim Ingham                 const char *partial_name = NULL;
4335aee162fSJim Ingham                 partial_name = input.GetArgumentAtIndex(opt_arg_pos);
4345aee162fSJim Ingham 
4355aee162fSJim Ingham                 if (process && process->IsAlive())
4365aee162fSJim Ingham                     return true;
4375aee162fSJim Ingham 
438a7015092SGreg Clayton                 Target *target = interpeter.GetDebugger().GetSelectedTarget().get();
4395aee162fSJim Ingham                 if (target == NULL)
4405aee162fSJim Ingham                 {
4415aee162fSJim Ingham                     // No target has been set yet, for now do host completion.  Otherwise I don't know how we would
4425aee162fSJim Ingham                     // figure out what the right target to use is...
4435aee162fSJim Ingham                     std::vector<lldb::pid_t> pids;
4445aee162fSJim Ingham                     Host::ListProcessesMatchingName (partial_name, matches, pids);
4455aee162fSJim Ingham                     return true;
4465aee162fSJim Ingham                 }
4475aee162fSJim Ingham                 if (!process)
4485aee162fSJim Ingham                 {
449a7015092SGreg Clayton                     process = target->CreateProcess (interpeter.GetDebugger().GetListener(), partial_name).get();
4505aee162fSJim Ingham                     need_to_delete_process = true;
4515aee162fSJim Ingham                 }
4525aee162fSJim Ingham 
4535aee162fSJim Ingham                 if (process)
4545aee162fSJim Ingham                 {
4555aee162fSJim Ingham                     matches.Clear();
4565aee162fSJim Ingham                     std::vector<lldb::pid_t> pids;
4575aee162fSJim Ingham                     process->ListProcessesMatchingName (NULL, matches, pids);
4585aee162fSJim Ingham                     if (need_to_delete_process)
4595aee162fSJim Ingham                         target->DeleteCurrentProcess();
4605aee162fSJim Ingham                     return true;
4615aee162fSJim Ingham                 }
4625aee162fSJim Ingham             }
4635aee162fSJim Ingham 
4645aee162fSJim Ingham             return false;
4655aee162fSJim Ingham         }
4665aee162fSJim Ingham 
46730fdc8d8SChris Lattner         // Options table: Required for subclasses of Options.
46830fdc8d8SChris Lattner 
46930fdc8d8SChris Lattner         static lldb::OptionDefinition g_option_table[];
47030fdc8d8SChris Lattner 
47130fdc8d8SChris Lattner         // Instance variables to hold the values for command options.
47230fdc8d8SChris Lattner 
47330fdc8d8SChris Lattner         lldb::pid_t pid;
47430fdc8d8SChris Lattner         std::string plugin_name;
47530fdc8d8SChris Lattner         std::string name;
47630fdc8d8SChris Lattner         bool waitfor;
47730fdc8d8SChris Lattner     };
47830fdc8d8SChris Lattner 
479a7015092SGreg Clayton     CommandObjectProcessAttach (CommandInterpreter &interpreter) :
480a7015092SGreg Clayton         CommandObject (interpreter,
481a7015092SGreg Clayton                        "process attach",
482e3d26315SCaroline Tice                        "Attach to a process.",
4835aee162fSJim Ingham                        "process attach <cmd-options>")
4845aee162fSJim Ingham     {
4855aee162fSJim Ingham     }
4865aee162fSJim Ingham 
4875aee162fSJim Ingham     ~CommandObjectProcessAttach ()
4885aee162fSJim Ingham     {
4895aee162fSJim Ingham     }
4905aee162fSJim Ingham 
4915aee162fSJim Ingham     bool
492a7015092SGreg Clayton     Execute (Args& command,
4935aee162fSJim Ingham              CommandReturnObject &result)
4945aee162fSJim Ingham     {
495a7015092SGreg Clayton         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
4965aee162fSJim Ingham 
497a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
4985aee162fSJim Ingham         if (process)
4995aee162fSJim Ingham         {
5005aee162fSJim Ingham             if (process->IsAlive())
5015aee162fSJim Ingham             {
5025aee162fSJim Ingham                 result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before attaching.\n",
5035aee162fSJim Ingham                                               process->GetID());
5045aee162fSJim Ingham                 result.SetStatus (eReturnStatusFailed);
5055aee162fSJim Ingham                 return false;
5065aee162fSJim Ingham             }
5075aee162fSJim Ingham         }
5085aee162fSJim Ingham 
5095aee162fSJim Ingham         if (target == NULL)
5105aee162fSJim Ingham         {
5115aee162fSJim Ingham             // If there isn't a current target create one.
5125aee162fSJim Ingham             TargetSP new_target_sp;
5135aee162fSJim Ingham             FileSpec emptyFileSpec;
5145aee162fSJim Ingham             ArchSpec emptyArchSpec;
5155aee162fSJim Ingham             Error error;
5165aee162fSJim Ingham 
517a7015092SGreg Clayton             error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(),
5185aee162fSJim Ingham                                                                               emptyFileSpec,
5195aee162fSJim Ingham                                                                               emptyArchSpec,
5205aee162fSJim Ingham                                                                               NULL,
5215aee162fSJim Ingham                                                                               false,
5225aee162fSJim Ingham                                                                               new_target_sp);
5235aee162fSJim Ingham             target = new_target_sp.get();
5245aee162fSJim Ingham             if (target == NULL || error.Fail())
5255aee162fSJim Ingham             {
5265aee162fSJim Ingham                 result.AppendError(error.AsCString("Error creating empty target"));
5275aee162fSJim Ingham                 return false;
5285aee162fSJim Ingham             }
529a7015092SGreg Clayton             m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target);
5305aee162fSJim Ingham         }
5315aee162fSJim Ingham 
5325aee162fSJim Ingham         // Record the old executable module, we want to issue a warning if the process of attaching changed the
5335aee162fSJim Ingham         // current executable (like somebody said "file foo" then attached to a PID whose executable was bar.)
5345aee162fSJim Ingham 
5355aee162fSJim Ingham         ModuleSP old_exec_module_sp = target->GetExecutableModule();
5365aee162fSJim Ingham         ArchSpec old_arch_spec = target->GetArchitecture();
5375aee162fSJim Ingham 
5385aee162fSJim Ingham         if (command.GetArgumentCount())
5395aee162fSJim Ingham         {
5405aee162fSJim Ingham             result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
5415aee162fSJim Ingham             result.SetStatus (eReturnStatusFailed);
5425aee162fSJim Ingham         }
5435aee162fSJim Ingham         else
5445aee162fSJim Ingham         {
5455aee162fSJim Ingham             const char *plugin_name = NULL;
5465aee162fSJim Ingham 
5475aee162fSJim Ingham             if (!m_options.plugin_name.empty())
5485aee162fSJim Ingham                 plugin_name = m_options.plugin_name.c_str();
5495aee162fSJim Ingham 
550a7015092SGreg Clayton             process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
5515aee162fSJim Ingham 
5525aee162fSJim Ingham             if (process)
5535aee162fSJim Ingham             {
5545aee162fSJim Ingham                 Error error;
5555aee162fSJim Ingham                 int attach_pid = m_options.pid;
5565aee162fSJim Ingham 
5573a0b9cdfSJim Ingham                 const char *wait_name = NULL;
5583a0b9cdfSJim Ingham 
5595aee162fSJim Ingham                 if (m_options.name.empty())
5605aee162fSJim Ingham                 {
5613a0b9cdfSJim Ingham                     if (old_exec_module_sp)
5623a0b9cdfSJim Ingham                     {
5633a0b9cdfSJim Ingham                         wait_name = old_exec_module_sp->GetFileSpec().GetFilename().AsCString();
5643a0b9cdfSJim Ingham                     }
5655aee162fSJim Ingham                 }
5665aee162fSJim Ingham                 else
5675aee162fSJim Ingham                 {
5683a0b9cdfSJim Ingham                     wait_name = m_options.name.c_str();
5693a0b9cdfSJim Ingham                 }
5703a0b9cdfSJim Ingham 
5713a0b9cdfSJim Ingham                 // If we are waiting for a process with this name to show up, do that first.
5723a0b9cdfSJim Ingham                 if (m_options.waitfor)
5733a0b9cdfSJim Ingham                 {
5743a0b9cdfSJim Ingham 
5753a0b9cdfSJim Ingham                     if (wait_name == NULL)
5763a0b9cdfSJim Ingham                     {
5773a0b9cdfSJim Ingham                         result.AppendError("Invalid arguments: must have a file loaded or supply a process name with the waitfor option.\n");
5783a0b9cdfSJim Ingham                         result.SetStatus (eReturnStatusFailed);
5793a0b9cdfSJim Ingham                         return false;
5803a0b9cdfSJim Ingham                     }
5813a0b9cdfSJim Ingham 
582a7015092SGreg Clayton                     m_interpreter.GetDebugger().GetOutputStream().Printf("Waiting to attach to a process named \"%s\".\n", wait_name);
5833a0b9cdfSJim Ingham                     error = process->Attach (wait_name, m_options.waitfor);
5845aee162fSJim Ingham                     if (error.Success())
5855aee162fSJim Ingham                     {
5865aee162fSJim Ingham                         result.SetStatus (eReturnStatusSuccessContinuingNoResult);
5875aee162fSJim Ingham                     }
5885aee162fSJim Ingham                     else
5895aee162fSJim Ingham                     {
5905aee162fSJim Ingham                         result.AppendErrorWithFormat ("Waiting for a process to launch named '%s': %s\n",
5913a0b9cdfSJim Ingham                                                          wait_name,
5925aee162fSJim Ingham                                                          error.AsCString());
5935aee162fSJim Ingham                         result.SetStatus (eReturnStatusFailed);
5945aee162fSJim Ingham                         return false;
5955aee162fSJim Ingham                     }
5965aee162fSJim Ingham                 }
5975aee162fSJim Ingham                 else
5985aee162fSJim Ingham                 {
5995aee162fSJim Ingham                     // If the process was specified by name look it up, so we can warn if there are multiple
6005aee162fSJim Ingham                     // processes with this pid.
6015aee162fSJim Ingham 
6023a0b9cdfSJim Ingham                     if (attach_pid == LLDB_INVALID_PROCESS_ID && wait_name != NULL)
6035aee162fSJim Ingham                     {
6045aee162fSJim Ingham                         std::vector<lldb::pid_t> pids;
6055aee162fSJim Ingham                         StringList matches;
6065aee162fSJim Ingham 
6073a0b9cdfSJim Ingham                         process->ListProcessesMatchingName(wait_name, matches, pids);
6085aee162fSJim Ingham                         if (matches.GetSize() > 1)
6095aee162fSJim Ingham                         {
6103a0b9cdfSJim Ingham                             result.AppendErrorWithFormat("More than one process named %s\n", wait_name);
6115aee162fSJim Ingham                             result.SetStatus (eReturnStatusFailed);
6125aee162fSJim Ingham                             return false;
6135aee162fSJim Ingham                         }
6145aee162fSJim Ingham                         else if (matches.GetSize() == 0)
6155aee162fSJim Ingham                         {
6163a0b9cdfSJim Ingham                             result.AppendErrorWithFormat("Could not find a process named %s\n", wait_name);
6175aee162fSJim Ingham                             result.SetStatus (eReturnStatusFailed);
6185aee162fSJim Ingham                             return false;
6195aee162fSJim Ingham                         }
6205aee162fSJim Ingham                         else
6215aee162fSJim Ingham                         {
6225aee162fSJim Ingham                             attach_pid = pids[0];
6235aee162fSJim Ingham                         }
6245aee162fSJim Ingham 
6255aee162fSJim Ingham                     }
6265aee162fSJim Ingham 
6275aee162fSJim Ingham                     if (attach_pid != LLDB_INVALID_PROCESS_ID)
6285aee162fSJim Ingham                     {
6295aee162fSJim Ingham                         error = process->Attach (attach_pid);
6305aee162fSJim Ingham                         if (error.Success())
6315aee162fSJim Ingham                         {
6325aee162fSJim Ingham                             result.SetStatus (eReturnStatusSuccessContinuingNoResult);
6335aee162fSJim Ingham                         }
6345aee162fSJim Ingham                         else
6355aee162fSJim Ingham                         {
6365aee162fSJim Ingham                             result.AppendErrorWithFormat ("Attaching to process %i failed: %s.\n",
6375aee162fSJim Ingham                                                          attach_pid,
6385aee162fSJim Ingham                                                          error.AsCString());
6395aee162fSJim Ingham                             result.SetStatus (eReturnStatusFailed);
6405aee162fSJim Ingham                         }
6415aee162fSJim Ingham                     }
6425aee162fSJim Ingham                     else
6435aee162fSJim Ingham                     {
6445aee162fSJim Ingham                         result.AppendErrorWithFormat ("No PID specified for attach\n",
6455aee162fSJim Ingham                                                          attach_pid,
6465aee162fSJim Ingham                                                          error.AsCString());
6475aee162fSJim Ingham                         result.SetStatus (eReturnStatusFailed);
6485aee162fSJim Ingham 
6495aee162fSJim Ingham                     }
6505aee162fSJim Ingham                 }
6515aee162fSJim Ingham             }
6525aee162fSJim Ingham         }
6535aee162fSJim Ingham 
6545aee162fSJim Ingham         if (result.Succeeded())
6555aee162fSJim Ingham         {
6565aee162fSJim Ingham             // Okay, we're done.  Last step is to warn if the executable module has changed:
6575aee162fSJim Ingham             if (!old_exec_module_sp)
6585aee162fSJim Ingham             {
6595aee162fSJim Ingham                 char new_path[PATH_MAX + 1];
6605aee162fSJim Ingham                 target->GetExecutableModule()->GetFileSpec().GetPath(new_path, PATH_MAX);
6615aee162fSJim Ingham 
6625aee162fSJim Ingham                 result.AppendMessageWithFormat("Executable module set to \"%s\".\n",
6635aee162fSJim Ingham                     new_path);
6645aee162fSJim Ingham             }
6655aee162fSJim Ingham             else if (old_exec_module_sp->GetFileSpec() != target->GetExecutableModule()->GetFileSpec())
6665aee162fSJim Ingham             {
6675aee162fSJim Ingham                 char old_path[PATH_MAX + 1];
6685aee162fSJim Ingham                 char new_path[PATH_MAX + 1];
6695aee162fSJim Ingham 
6705aee162fSJim Ingham                 old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX);
6715aee162fSJim Ingham                 target->GetExecutableModule()->GetFileSpec().GetPath (new_path, PATH_MAX);
6725aee162fSJim Ingham 
6735aee162fSJim Ingham                 result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n",
6745aee162fSJim Ingham                                                     old_path, new_path);
6755aee162fSJim Ingham             }
6765aee162fSJim Ingham 
6775aee162fSJim Ingham             if (!old_arch_spec.IsValid())
6785aee162fSJim Ingham             {
6795aee162fSJim Ingham                 result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().AsCString());
6805aee162fSJim Ingham             }
6815aee162fSJim Ingham             else if (old_arch_spec != target->GetArchitecture())
6825aee162fSJim Ingham             {
6835aee162fSJim Ingham                 result.AppendWarningWithFormat("Architecture changed from %s to %s.\n",
6845aee162fSJim Ingham                                                 old_arch_spec.AsCString(), target->GetArchitecture().AsCString());
6855aee162fSJim Ingham             }
6865aee162fSJim Ingham         }
6875aee162fSJim Ingham         return result.Succeeded();
6885aee162fSJim Ingham     }
6895aee162fSJim Ingham 
6905aee162fSJim Ingham     Options *
6915aee162fSJim Ingham     GetOptions ()
6925aee162fSJim Ingham     {
6935aee162fSJim Ingham         return &m_options;
6945aee162fSJim Ingham     }
6955aee162fSJim Ingham 
69630fdc8d8SChris Lattner protected:
69730fdc8d8SChris Lattner 
69830fdc8d8SChris Lattner     CommandOptions m_options;
69930fdc8d8SChris Lattner };
70030fdc8d8SChris Lattner 
70130fdc8d8SChris Lattner 
70230fdc8d8SChris Lattner lldb::OptionDefinition
70330fdc8d8SChris Lattner CommandObjectProcessAttach::CommandOptions::g_option_table[] =
70430fdc8d8SChris Lattner {
705deaab222SCaroline Tice { LLDB_OPT_SET_ALL, false, "plugin", 'P', required_argument, NULL, 0, eArgTypePlugin,        "Name of the process plugin you want to use."},
706deaab222SCaroline Tice { LLDB_OPT_SET_1,   false, "pid",    'p', required_argument, NULL, 0, eArgTypePid,           "The process ID of an existing process to attach to."},
707deaab222SCaroline Tice { LLDB_OPT_SET_2,   false, "name",   'n', required_argument, NULL, 0, eArgTypeProcessName,  "The name of the process to attach to."},
708deaab222SCaroline Tice { LLDB_OPT_SET_2,   false, "waitfor",'w', no_argument,       NULL, 0, eArgTypeNone,              "Wait for the the process with <process-name> to launch."},
709deaab222SCaroline Tice { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
71030fdc8d8SChris Lattner };
71130fdc8d8SChris Lattner 
71230fdc8d8SChris Lattner //-------------------------------------------------------------------------
71330fdc8d8SChris Lattner // CommandObjectProcessContinue
71430fdc8d8SChris Lattner //-------------------------------------------------------------------------
71530fdc8d8SChris Lattner 
71630fdc8d8SChris Lattner class CommandObjectProcessContinue : public CommandObject
71730fdc8d8SChris Lattner {
71830fdc8d8SChris Lattner public:
71930fdc8d8SChris Lattner 
720a7015092SGreg Clayton     CommandObjectProcessContinue (CommandInterpreter &interpreter) :
721a7015092SGreg Clayton         CommandObject (interpreter,
722a7015092SGreg Clayton                        "process continue",
723e3d26315SCaroline Tice                        "Continue execution of all threads in the current process.",
72430fdc8d8SChris Lattner                        "process continue",
72530fdc8d8SChris Lattner                        eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
72630fdc8d8SChris Lattner     {
72730fdc8d8SChris Lattner     }
72830fdc8d8SChris Lattner 
72930fdc8d8SChris Lattner 
73030fdc8d8SChris Lattner     ~CommandObjectProcessContinue ()
73130fdc8d8SChris Lattner     {
73230fdc8d8SChris Lattner     }
73330fdc8d8SChris Lattner 
73430fdc8d8SChris Lattner     bool
735a7015092SGreg Clayton     Execute (Args& command,
73630fdc8d8SChris Lattner              CommandReturnObject &result)
73730fdc8d8SChris Lattner     {
738a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
739a7015092SGreg Clayton         bool synchronous_execution = m_interpreter.GetSynchronous ();
74030fdc8d8SChris Lattner 
74130fdc8d8SChris Lattner         if (process == NULL)
74230fdc8d8SChris Lattner         {
74330fdc8d8SChris Lattner             result.AppendError ("no process to continue");
74430fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
74530fdc8d8SChris Lattner             return false;
74630fdc8d8SChris Lattner          }
74730fdc8d8SChris Lattner 
74830fdc8d8SChris Lattner         StateType state = process->GetState();
74930fdc8d8SChris Lattner         if (state == eStateStopped)
75030fdc8d8SChris Lattner         {
75130fdc8d8SChris Lattner             if (command.GetArgumentCount() != 0)
75230fdc8d8SChris Lattner             {
75330fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str());
75430fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
75530fdc8d8SChris Lattner                 return false;
75630fdc8d8SChris Lattner             }
75730fdc8d8SChris Lattner 
75830fdc8d8SChris Lattner             const uint32_t num_threads = process->GetThreadList().GetSize();
75930fdc8d8SChris Lattner 
76030fdc8d8SChris Lattner             // Set the actions that the threads should each take when resuming
76130fdc8d8SChris Lattner             for (uint32_t idx=0; idx<num_threads; ++idx)
76230fdc8d8SChris Lattner             {
76330fdc8d8SChris Lattner                 process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning);
76430fdc8d8SChris Lattner             }
76530fdc8d8SChris Lattner 
76630fdc8d8SChris Lattner             Error error(process->Resume());
76730fdc8d8SChris Lattner             if (error.Success())
76830fdc8d8SChris Lattner             {
76919388cfcSGreg Clayton                 result.AppendMessageWithFormat ("Process %i resuming\n", process->GetID());
77030fdc8d8SChris Lattner                 if (synchronous_execution)
77130fdc8d8SChris Lattner                 {
772b132097bSGreg Clayton                     state = process->WaitForProcessToStop (NULL);
77330fdc8d8SChris Lattner 
77430fdc8d8SChris Lattner                     result.SetDidChangeProcessState (true);
77530fdc8d8SChris Lattner                     result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
77630fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
77730fdc8d8SChris Lattner                 }
77830fdc8d8SChris Lattner                 else
77930fdc8d8SChris Lattner                 {
78030fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusSuccessContinuingNoResult);
78130fdc8d8SChris Lattner                 }
78230fdc8d8SChris Lattner             }
78330fdc8d8SChris Lattner             else
78430fdc8d8SChris Lattner             {
78530fdc8d8SChris Lattner                 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
78630fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
78730fdc8d8SChris Lattner             }
78830fdc8d8SChris Lattner         }
78930fdc8d8SChris Lattner         else
79030fdc8d8SChris Lattner         {
79130fdc8d8SChris Lattner             result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
79230fdc8d8SChris Lattner                                          StateAsCString(state));
79330fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
79430fdc8d8SChris Lattner         }
79530fdc8d8SChris Lattner         return result.Succeeded();
79630fdc8d8SChris Lattner     }
79730fdc8d8SChris Lattner };
79830fdc8d8SChris Lattner 
79930fdc8d8SChris Lattner //-------------------------------------------------------------------------
80030fdc8d8SChris Lattner // CommandObjectProcessDetach
80130fdc8d8SChris Lattner //-------------------------------------------------------------------------
80230fdc8d8SChris Lattner 
80330fdc8d8SChris Lattner class CommandObjectProcessDetach : public CommandObject
80430fdc8d8SChris Lattner {
80530fdc8d8SChris Lattner public:
80630fdc8d8SChris Lattner 
807a7015092SGreg Clayton     CommandObjectProcessDetach (CommandInterpreter &interpreter) :
808a7015092SGreg Clayton         CommandObject (interpreter,
809a7015092SGreg Clayton                        "process detach",
810e3d26315SCaroline Tice                        "Detach from the current process being debugged.",
81130fdc8d8SChris Lattner                        "process detach",
81230fdc8d8SChris Lattner                        eFlagProcessMustBeLaunched)
81330fdc8d8SChris Lattner     {
81430fdc8d8SChris Lattner     }
81530fdc8d8SChris Lattner 
81630fdc8d8SChris Lattner     ~CommandObjectProcessDetach ()
81730fdc8d8SChris Lattner     {
81830fdc8d8SChris Lattner     }
81930fdc8d8SChris Lattner 
82030fdc8d8SChris Lattner     bool
821a7015092SGreg Clayton     Execute (Args& command,
82230fdc8d8SChris Lattner              CommandReturnObject &result)
82330fdc8d8SChris Lattner     {
824a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
82530fdc8d8SChris Lattner         if (process == NULL)
82630fdc8d8SChris Lattner         {
82730fdc8d8SChris Lattner             result.AppendError ("must have a valid process in order to detach");
82830fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
82930fdc8d8SChris Lattner             return false;
83030fdc8d8SChris Lattner         }
83130fdc8d8SChris Lattner 
83230fdc8d8SChris Lattner         Error error (process->Detach());
83330fdc8d8SChris Lattner         if (error.Success())
83430fdc8d8SChris Lattner         {
83530fdc8d8SChris Lattner             result.SetStatus (eReturnStatusSuccessFinishResult);
83630fdc8d8SChris Lattner         }
83730fdc8d8SChris Lattner         else
83830fdc8d8SChris Lattner         {
83930fdc8d8SChris Lattner             result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString());
84030fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
84130fdc8d8SChris Lattner             return false;
84230fdc8d8SChris Lattner         }
84330fdc8d8SChris Lattner         return result.Succeeded();
84430fdc8d8SChris Lattner     }
84530fdc8d8SChris Lattner };
84630fdc8d8SChris Lattner 
84730fdc8d8SChris Lattner //-------------------------------------------------------------------------
84830fdc8d8SChris Lattner // CommandObjectProcessSignal
84930fdc8d8SChris Lattner //-------------------------------------------------------------------------
85030fdc8d8SChris Lattner 
85130fdc8d8SChris Lattner class CommandObjectProcessSignal : public CommandObject
85230fdc8d8SChris Lattner {
85330fdc8d8SChris Lattner public:
85430fdc8d8SChris Lattner 
855a7015092SGreg Clayton     CommandObjectProcessSignal (CommandInterpreter &interpreter) :
856a7015092SGreg Clayton         CommandObject (interpreter,
857a7015092SGreg Clayton                        "process signal",
858e3d26315SCaroline Tice                        "Send a UNIX signal to the current process being debugged.",
859405fe67fSCaroline Tice                        NULL)
86030fdc8d8SChris Lattner     {
861405fe67fSCaroline Tice         CommandArgumentEntry arg;
862405fe67fSCaroline Tice         CommandArgumentData signal_arg;
863405fe67fSCaroline Tice 
864405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
865c0dbdfb6SCaroline Tice         signal_arg.arg_type = eArgTypeUnixSignal;
866405fe67fSCaroline Tice         signal_arg.arg_repetition = eArgRepeatPlain;
867405fe67fSCaroline Tice 
868405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
869405fe67fSCaroline Tice         arg.push_back (signal_arg);
870405fe67fSCaroline Tice 
871405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
872405fe67fSCaroline Tice         m_arguments.push_back (arg);
87330fdc8d8SChris Lattner     }
87430fdc8d8SChris Lattner 
87530fdc8d8SChris Lattner     ~CommandObjectProcessSignal ()
87630fdc8d8SChris Lattner     {
87730fdc8d8SChris Lattner     }
87830fdc8d8SChris Lattner 
87930fdc8d8SChris Lattner     bool
880a7015092SGreg Clayton     Execute (Args& command,
88130fdc8d8SChris Lattner              CommandReturnObject &result)
88230fdc8d8SChris Lattner     {
883a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
88430fdc8d8SChris Lattner         if (process == NULL)
88530fdc8d8SChris Lattner         {
88630fdc8d8SChris Lattner             result.AppendError ("no process to signal");
88730fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
88830fdc8d8SChris Lattner             return false;
88930fdc8d8SChris Lattner         }
89030fdc8d8SChris Lattner 
89130fdc8d8SChris Lattner         if (command.GetArgumentCount() == 1)
89230fdc8d8SChris Lattner         {
893237cd906SGreg Clayton             int signo = LLDB_INVALID_SIGNAL_NUMBER;
894237cd906SGreg Clayton 
895237cd906SGreg Clayton             const char *signal_name = command.GetArgumentAtIndex(0);
896237cd906SGreg Clayton             if (::isxdigit (signal_name[0]))
897237cd906SGreg Clayton                 signo = Args::StringToSInt32(signal_name, LLDB_INVALID_SIGNAL_NUMBER, 0);
898237cd906SGreg Clayton             else
899237cd906SGreg Clayton                 signo = process->GetUnixSignals().GetSignalNumberFromName (signal_name);
900237cd906SGreg Clayton 
901237cd906SGreg Clayton             if (signo == LLDB_INVALID_SIGNAL_NUMBER)
90230fdc8d8SChris Lattner             {
90330fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0));
90430fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
90530fdc8d8SChris Lattner             }
90630fdc8d8SChris Lattner             else
90730fdc8d8SChris Lattner             {
90830fdc8d8SChris Lattner                 Error error (process->Signal (signo));
90930fdc8d8SChris Lattner                 if (error.Success())
91030fdc8d8SChris Lattner                 {
91130fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusSuccessFinishResult);
91230fdc8d8SChris Lattner                 }
91330fdc8d8SChris Lattner                 else
91430fdc8d8SChris Lattner                 {
91530fdc8d8SChris Lattner                     result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString());
91630fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusFailed);
91730fdc8d8SChris Lattner                 }
91830fdc8d8SChris Lattner             }
91930fdc8d8SChris Lattner         }
92030fdc8d8SChris Lattner         else
92130fdc8d8SChris Lattner         {
92230fdc8d8SChris Lattner             result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: \n", m_cmd_name.c_str(),
92330fdc8d8SChris Lattner                                         m_cmd_syntax.c_str());
92430fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
92530fdc8d8SChris Lattner         }
92630fdc8d8SChris Lattner         return result.Succeeded();
92730fdc8d8SChris Lattner     }
92830fdc8d8SChris Lattner };
92930fdc8d8SChris Lattner 
93030fdc8d8SChris Lattner 
93130fdc8d8SChris Lattner //-------------------------------------------------------------------------
93230fdc8d8SChris Lattner // CommandObjectProcessInterrupt
93330fdc8d8SChris Lattner //-------------------------------------------------------------------------
93430fdc8d8SChris Lattner 
93530fdc8d8SChris Lattner class CommandObjectProcessInterrupt : public CommandObject
93630fdc8d8SChris Lattner {
93730fdc8d8SChris Lattner public:
93830fdc8d8SChris Lattner 
93930fdc8d8SChris Lattner 
940a7015092SGreg Clayton     CommandObjectProcessInterrupt (CommandInterpreter &interpreter) :
941a7015092SGreg Clayton     CommandObject (interpreter,
942a7015092SGreg Clayton                    "process interrupt",
943e3d26315SCaroline Tice                    "Interrupt the current process being debugged.",
94430fdc8d8SChris Lattner                    "process interrupt",
94530fdc8d8SChris Lattner                    eFlagProcessMustBeLaunched)
94630fdc8d8SChris Lattner     {
94730fdc8d8SChris Lattner     }
94830fdc8d8SChris Lattner 
94930fdc8d8SChris Lattner     ~CommandObjectProcessInterrupt ()
95030fdc8d8SChris Lattner     {
95130fdc8d8SChris Lattner     }
95230fdc8d8SChris Lattner 
95330fdc8d8SChris Lattner     bool
954a7015092SGreg Clayton     Execute (Args& command,
95530fdc8d8SChris Lattner              CommandReturnObject &result)
95630fdc8d8SChris Lattner     {
957a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
95830fdc8d8SChris Lattner         if (process == NULL)
95930fdc8d8SChris Lattner         {
96030fdc8d8SChris Lattner             result.AppendError ("no process to halt");
96130fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
96230fdc8d8SChris Lattner             return false;
96330fdc8d8SChris Lattner         }
96430fdc8d8SChris Lattner 
96530fdc8d8SChris Lattner         if (command.GetArgumentCount() == 0)
96630fdc8d8SChris Lattner         {
96730fdc8d8SChris Lattner             Error error(process->Halt ());
96830fdc8d8SChris Lattner             if (error.Success())
96930fdc8d8SChris Lattner             {
97030fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusSuccessFinishResult);
97130fdc8d8SChris Lattner 
97230fdc8d8SChris Lattner                 // Maybe we should add a "SuspendThreadPlans so we
97330fdc8d8SChris Lattner                 // can halt, and keep in place all the current thread plans.
97430fdc8d8SChris Lattner                 process->GetThreadList().DiscardThreadPlans();
97530fdc8d8SChris Lattner             }
97630fdc8d8SChris Lattner             else
97730fdc8d8SChris Lattner             {
97830fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString());
97930fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
98030fdc8d8SChris Lattner             }
98130fdc8d8SChris Lattner         }
98230fdc8d8SChris Lattner         else
98330fdc8d8SChris Lattner         {
98430fdc8d8SChris Lattner             result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
98530fdc8d8SChris Lattner                                         m_cmd_name.c_str(),
98630fdc8d8SChris Lattner                                         m_cmd_syntax.c_str());
98730fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
98830fdc8d8SChris Lattner         }
98930fdc8d8SChris Lattner         return result.Succeeded();
99030fdc8d8SChris Lattner     }
99130fdc8d8SChris Lattner };
99230fdc8d8SChris Lattner 
99330fdc8d8SChris Lattner //-------------------------------------------------------------------------
99430fdc8d8SChris Lattner // CommandObjectProcessKill
99530fdc8d8SChris Lattner //-------------------------------------------------------------------------
99630fdc8d8SChris Lattner 
99730fdc8d8SChris Lattner class CommandObjectProcessKill : public CommandObject
99830fdc8d8SChris Lattner {
99930fdc8d8SChris Lattner public:
100030fdc8d8SChris Lattner 
1001a7015092SGreg Clayton     CommandObjectProcessKill (CommandInterpreter &interpreter) :
1002a7015092SGreg Clayton     CommandObject (interpreter,
1003a7015092SGreg Clayton                    "process kill",
1004e3d26315SCaroline Tice                    "Terminate the current process being debugged.",
100530fdc8d8SChris Lattner                    "process kill",
100630fdc8d8SChris Lattner                    eFlagProcessMustBeLaunched)
100730fdc8d8SChris Lattner     {
100830fdc8d8SChris Lattner     }
100930fdc8d8SChris Lattner 
101030fdc8d8SChris Lattner     ~CommandObjectProcessKill ()
101130fdc8d8SChris Lattner     {
101230fdc8d8SChris Lattner     }
101330fdc8d8SChris Lattner 
101430fdc8d8SChris Lattner     bool
1015a7015092SGreg Clayton     Execute (Args& command,
101630fdc8d8SChris Lattner              CommandReturnObject &result)
101730fdc8d8SChris Lattner     {
1018a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
101930fdc8d8SChris Lattner         if (process == NULL)
102030fdc8d8SChris Lattner         {
102130fdc8d8SChris Lattner             result.AppendError ("no process to kill");
102230fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
102330fdc8d8SChris Lattner             return false;
102430fdc8d8SChris Lattner         }
102530fdc8d8SChris Lattner 
102630fdc8d8SChris Lattner         if (command.GetArgumentCount() == 0)
102730fdc8d8SChris Lattner         {
102830fdc8d8SChris Lattner             Error error (process->Destroy());
102930fdc8d8SChris Lattner             if (error.Success())
103030fdc8d8SChris Lattner             {
103130fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusSuccessFinishResult);
103230fdc8d8SChris Lattner             }
103330fdc8d8SChris Lattner             else
103430fdc8d8SChris Lattner             {
103530fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString());
103630fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
103730fdc8d8SChris Lattner             }
103830fdc8d8SChris Lattner         }
103930fdc8d8SChris Lattner         else
104030fdc8d8SChris Lattner         {
104130fdc8d8SChris Lattner             result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
104230fdc8d8SChris Lattner                                         m_cmd_name.c_str(),
104330fdc8d8SChris Lattner                                         m_cmd_syntax.c_str());
104430fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
104530fdc8d8SChris Lattner         }
104630fdc8d8SChris Lattner         return result.Succeeded();
104730fdc8d8SChris Lattner     }
104830fdc8d8SChris Lattner };
104930fdc8d8SChris Lattner 
105030fdc8d8SChris Lattner //-------------------------------------------------------------------------
10514b9bea87SJim Ingham // CommandObjectProcessStatus
10524b9bea87SJim Ingham //-------------------------------------------------------------------------
10534b9bea87SJim Ingham class CommandObjectProcessStatus : public CommandObject
10544b9bea87SJim Ingham {
10554b9bea87SJim Ingham public:
1056a7015092SGreg Clayton     CommandObjectProcessStatus (CommandInterpreter &interpreter) :
1057a7015092SGreg Clayton     CommandObject (interpreter,
1058a7015092SGreg Clayton                    "process status",
1059e3d26315SCaroline Tice                    "Show the current status and location of executing process.",
1060e3d26315SCaroline Tice                    "process status",
10614b9bea87SJim Ingham                    0)
10624b9bea87SJim Ingham     {
10634b9bea87SJim Ingham     }
10644b9bea87SJim Ingham 
10654b9bea87SJim Ingham     ~CommandObjectProcessStatus()
10664b9bea87SJim Ingham     {
10674b9bea87SJim Ingham     }
10684b9bea87SJim Ingham 
10694b9bea87SJim Ingham 
10704b9bea87SJim Ingham     bool
10714b9bea87SJim Ingham     Execute
10724b9bea87SJim Ingham     (
10734b9bea87SJim Ingham         Args& command,
10744b9bea87SJim Ingham         CommandReturnObject &result
10754b9bea87SJim Ingham     )
10764b9bea87SJim Ingham     {
10774b9bea87SJim Ingham         StreamString &output_stream = result.GetOutputStream();
10784b9bea87SJim Ingham         result.SetStatus (eReturnStatusSuccessFinishNoResult);
1079a7015092SGreg Clayton         ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
10804b9bea87SJim Ingham         if (exe_ctx.process)
10814b9bea87SJim Ingham         {
10824b9bea87SJim Ingham             const StateType state = exe_ctx.process->GetState();
10834b9bea87SJim Ingham             if (StateIsStoppedState(state))
10844b9bea87SJim Ingham             {
10854b9bea87SJim Ingham                 if (state == eStateExited)
10864b9bea87SJim Ingham                 {
10874b9bea87SJim Ingham                     int exit_status = exe_ctx.process->GetExitStatus();
10884b9bea87SJim Ingham                     const char *exit_description = exe_ctx.process->GetExitDescription();
10894b9bea87SJim Ingham                     output_stream.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n",
10904b9bea87SJim Ingham                                           exe_ctx.process->GetID(),
10914b9bea87SJim Ingham                                           exit_status,
10924b9bea87SJim Ingham                                           exit_status,
10934b9bea87SJim Ingham                                           exit_description ? exit_description : "");
10944b9bea87SJim Ingham                 }
10954b9bea87SJim Ingham                 else
10964b9bea87SJim Ingham                 {
10974b9bea87SJim Ingham                     output_stream.Printf ("Process %d %s\n", exe_ctx.process->GetID(), StateAsCString (state));
10984b9bea87SJim Ingham                     if (exe_ctx.thread == NULL)
10994b9bea87SJim Ingham                         exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
11004b9bea87SJim Ingham                     if (exe_ctx.thread != NULL)
11014b9bea87SJim Ingham                     {
1102a7015092SGreg Clayton                         DisplayThreadsInfo (m_interpreter, &exe_ctx, result, true, true);
11034b9bea87SJim Ingham                     }
11044b9bea87SJim Ingham                     else
11054b9bea87SJim Ingham                     {
11064b9bea87SJim Ingham                         result.AppendError ("No valid thread found in current process.");
11074b9bea87SJim Ingham                         result.SetStatus (eReturnStatusFailed);
11084b9bea87SJim Ingham                     }
11094b9bea87SJim Ingham                 }
11104b9bea87SJim Ingham             }
11114b9bea87SJim Ingham             else
11124b9bea87SJim Ingham             {
11134b9bea87SJim Ingham                 output_stream.Printf ("Process %d is running.\n",
11144b9bea87SJim Ingham                                           exe_ctx.process->GetID());
11154b9bea87SJim Ingham             }
11164b9bea87SJim Ingham         }
11174b9bea87SJim Ingham         else
11184b9bea87SJim Ingham         {
11194b9bea87SJim Ingham             result.AppendError ("No current location or status available.");
11204b9bea87SJim Ingham             result.SetStatus (eReturnStatusFailed);
11214b9bea87SJim Ingham         }
11224b9bea87SJim Ingham         return result.Succeeded();
11234b9bea87SJim Ingham     }
11244b9bea87SJim Ingham };
11254b9bea87SJim Ingham 
11264b9bea87SJim Ingham //-------------------------------------------------------------------------
112735731357SCaroline Tice // CommandObjectProcessHandle
112835731357SCaroline Tice //-------------------------------------------------------------------------
112935731357SCaroline Tice 
113035731357SCaroline Tice class CommandObjectProcessHandle : public CommandObject
113135731357SCaroline Tice {
113235731357SCaroline Tice public:
113335731357SCaroline Tice 
113435731357SCaroline Tice     class CommandOptions : public Options
113535731357SCaroline Tice     {
113635731357SCaroline Tice     public:
113735731357SCaroline Tice 
113835731357SCaroline Tice         CommandOptions () :
113935731357SCaroline Tice             Options ()
114035731357SCaroline Tice         {
114135731357SCaroline Tice             ResetOptionValues ();
114235731357SCaroline Tice         }
114335731357SCaroline Tice 
114435731357SCaroline Tice         ~CommandOptions ()
114535731357SCaroline Tice         {
114635731357SCaroline Tice         }
114735731357SCaroline Tice 
114835731357SCaroline Tice         Error
114935731357SCaroline Tice         SetOptionValue (int option_idx, const char *option_arg)
115035731357SCaroline Tice         {
115135731357SCaroline Tice             Error error;
115235731357SCaroline Tice             char short_option = (char) m_getopt_table[option_idx].val;
115335731357SCaroline Tice 
115435731357SCaroline Tice             switch (short_option)
115535731357SCaroline Tice             {
115635731357SCaroline Tice                 case 's':
115735731357SCaroline Tice                     stop = option_arg;
115835731357SCaroline Tice                     break;
115935731357SCaroline Tice                 case 'n':
116035731357SCaroline Tice                     notify = option_arg;
116135731357SCaroline Tice                     break;
116235731357SCaroline Tice                 case 'p':
116335731357SCaroline Tice                     pass = option_arg;
116435731357SCaroline Tice                     break;
116535731357SCaroline Tice                 default:
116635731357SCaroline Tice                     error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
116735731357SCaroline Tice                     break;
116835731357SCaroline Tice             }
116935731357SCaroline Tice             return error;
117035731357SCaroline Tice         }
117135731357SCaroline Tice 
117235731357SCaroline Tice         void
117335731357SCaroline Tice         ResetOptionValues ()
117435731357SCaroline Tice         {
117535731357SCaroline Tice             Options::ResetOptionValues();
117635731357SCaroline Tice             stop.clear();
117735731357SCaroline Tice             notify.clear();
117835731357SCaroline Tice             pass.clear();
117935731357SCaroline Tice         }
118035731357SCaroline Tice 
118135731357SCaroline Tice         const lldb::OptionDefinition*
118235731357SCaroline Tice         GetDefinitions ()
118335731357SCaroline Tice         {
118435731357SCaroline Tice             return g_option_table;
118535731357SCaroline Tice         }
118635731357SCaroline Tice 
118735731357SCaroline Tice         // Options table: Required for subclasses of Options.
118835731357SCaroline Tice 
118935731357SCaroline Tice         static lldb::OptionDefinition g_option_table[];
119035731357SCaroline Tice 
119135731357SCaroline Tice         // Instance variables to hold the values for command options.
119235731357SCaroline Tice 
119335731357SCaroline Tice         std::string stop;
119435731357SCaroline Tice         std::string notify;
119535731357SCaroline Tice         std::string pass;
119635731357SCaroline Tice     };
119735731357SCaroline Tice 
119835731357SCaroline Tice 
119935731357SCaroline Tice     CommandObjectProcessHandle (CommandInterpreter &interpreter) :
120035731357SCaroline Tice         CommandObject (interpreter,
120135731357SCaroline Tice                        "process handle",
120210ad7993SCaroline Tice                        "Show or update what the process and debugger should do with various signals received from the OS.",
120335731357SCaroline Tice                        NULL)
120435731357SCaroline Tice     {
120510ad7993SCaroline Tice         SetHelpLong ("If no signals are specified, update them all.  If no update option is specified, list the current values.\n");
120635731357SCaroline Tice         CommandArgumentEntry arg;
1207c0dbdfb6SCaroline Tice         CommandArgumentData signal_arg;
120835731357SCaroline Tice 
1209c0dbdfb6SCaroline Tice         signal_arg.arg_type = eArgTypeUnixSignal;
1210c0dbdfb6SCaroline Tice         signal_arg.arg_repetition = eArgRepeatStar;
121135731357SCaroline Tice 
1212c0dbdfb6SCaroline Tice         arg.push_back (signal_arg);
121335731357SCaroline Tice 
121435731357SCaroline Tice         m_arguments.push_back (arg);
121535731357SCaroline Tice     }
121635731357SCaroline Tice 
121735731357SCaroline Tice     ~CommandObjectProcessHandle ()
121835731357SCaroline Tice     {
121935731357SCaroline Tice     }
122035731357SCaroline Tice 
122135731357SCaroline Tice     Options *
122235731357SCaroline Tice     GetOptions ()
122335731357SCaroline Tice     {
122435731357SCaroline Tice         return &m_options;
122535731357SCaroline Tice     }
122635731357SCaroline Tice 
122735731357SCaroline Tice     bool
122810ad7993SCaroline Tice     VerifyCommandOptionValue (const std::string &option, int &real_value)
122935731357SCaroline Tice     {
123035731357SCaroline Tice         bool okay = true;
123135731357SCaroline Tice 
123210ad7993SCaroline Tice         bool success = false;
123310ad7993SCaroline Tice         bool tmp_value = Args::StringToBoolean (option.c_str(), false, &success);
123410ad7993SCaroline Tice 
123510ad7993SCaroline Tice         if (success && tmp_value)
123610ad7993SCaroline Tice             real_value = 1;
123710ad7993SCaroline Tice         else if (success && !tmp_value)
123810ad7993SCaroline Tice             real_value = 0;
123935731357SCaroline Tice         else
124035731357SCaroline Tice         {
124135731357SCaroline Tice             // If the value isn't 'true' or 'false', it had better be 0 or 1.
124210ad7993SCaroline Tice             real_value = Args::StringToUInt32 (option.c_str(), 3);
124310ad7993SCaroline Tice             if (real_value != 0 && real_value != 1)
124435731357SCaroline Tice                 okay = false;
124535731357SCaroline Tice         }
124635731357SCaroline Tice 
124735731357SCaroline Tice         return okay;
124835731357SCaroline Tice     }
124935731357SCaroline Tice 
125010ad7993SCaroline Tice     void
125110ad7993SCaroline Tice     PrintSignalHeader (Stream &str)
125210ad7993SCaroline Tice     {
125310ad7993SCaroline Tice         str.Printf ("NAME        PASS   STOP   NOTIFY\n");
125410ad7993SCaroline Tice         str.Printf ("==========  =====  =====  ======\n");
125510ad7993SCaroline Tice     }
125610ad7993SCaroline Tice 
125710ad7993SCaroline Tice     void
125810ad7993SCaroline Tice     PrintSignal (Stream &str, int32_t signo, const char *sig_name, UnixSignals &signals)
125910ad7993SCaroline Tice     {
126010ad7993SCaroline Tice         bool stop;
126110ad7993SCaroline Tice         bool suppress;
126210ad7993SCaroline Tice         bool notify;
126310ad7993SCaroline Tice 
126410ad7993SCaroline Tice         str.Printf ("%-10s  ", sig_name);
126510ad7993SCaroline Tice         if (signals.GetSignalInfo (signo, suppress, stop, notify))
126610ad7993SCaroline Tice         {
126710ad7993SCaroline Tice             bool pass = !suppress;
126810ad7993SCaroline Tice             str.Printf ("%s  %s  %s",
126910ad7993SCaroline Tice                         (pass ? "true " : "false"),
127010ad7993SCaroline Tice                         (stop ? "true " : "false"),
127110ad7993SCaroline Tice                         (notify ? "true " : "false"));
127210ad7993SCaroline Tice         }
127310ad7993SCaroline Tice         str.Printf ("\n");
127410ad7993SCaroline Tice     }
127510ad7993SCaroline Tice 
127610ad7993SCaroline Tice     void
127710ad7993SCaroline Tice     PrintSignalInformation (Stream &str, Args &signal_args, int num_valid_signals, UnixSignals &signals)
127810ad7993SCaroline Tice     {
127910ad7993SCaroline Tice         PrintSignalHeader (str);
128010ad7993SCaroline Tice 
128110ad7993SCaroline Tice         if (num_valid_signals > 0)
128210ad7993SCaroline Tice         {
128310ad7993SCaroline Tice             size_t num_args = signal_args.GetArgumentCount();
128410ad7993SCaroline Tice             for (size_t i = 0; i < num_args; ++i)
128510ad7993SCaroline Tice             {
128610ad7993SCaroline Tice                 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
128710ad7993SCaroline Tice                 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
128810ad7993SCaroline Tice                     PrintSignal (str, signo, signal_args.GetArgumentAtIndex (i), signals);
128910ad7993SCaroline Tice             }
129010ad7993SCaroline Tice         }
129110ad7993SCaroline Tice         else // Print info for ALL signals
129210ad7993SCaroline Tice         {
129310ad7993SCaroline Tice             int32_t signo = signals.GetFirstSignalNumber();
129410ad7993SCaroline Tice             while (signo != LLDB_INVALID_SIGNAL_NUMBER)
129510ad7993SCaroline Tice             {
129610ad7993SCaroline Tice                 PrintSignal (str, signo, signals.GetSignalAsCString (signo), signals);
129710ad7993SCaroline Tice                 signo = signals.GetNextSignalNumber (signo);
129810ad7993SCaroline Tice             }
129910ad7993SCaroline Tice         }
130010ad7993SCaroline Tice     }
130110ad7993SCaroline Tice 
130235731357SCaroline Tice     bool
130335731357SCaroline Tice     Execute (Args &signal_args, CommandReturnObject &result)
130435731357SCaroline Tice     {
130535731357SCaroline Tice         TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
130635731357SCaroline Tice 
130735731357SCaroline Tice         if (!target_sp)
130835731357SCaroline Tice         {
130935731357SCaroline Tice             result.AppendError ("No current target;"
131035731357SCaroline Tice                                 " cannot handle signals until you have a valid target and process.\n");
131135731357SCaroline Tice             result.SetStatus (eReturnStatusFailed);
131235731357SCaroline Tice             return false;
131335731357SCaroline Tice         }
131435731357SCaroline Tice 
131535731357SCaroline Tice         ProcessSP process_sp = target_sp->GetProcessSP();
131635731357SCaroline Tice 
131735731357SCaroline Tice         if (!process_sp)
131835731357SCaroline Tice         {
131935731357SCaroline Tice             result.AppendError ("No current process; cannot handle signals until you have a valid process.\n");
132035731357SCaroline Tice             result.SetStatus (eReturnStatusFailed);
132135731357SCaroline Tice             return false;
132235731357SCaroline Tice         }
132335731357SCaroline Tice 
132435731357SCaroline Tice         int stop_action = -1;   // -1 means leave the current setting alone
132535731357SCaroline Tice         int pass_action = -1;   // -1 means leave the current setting alone
132635731357SCaroline Tice         int notify_action = -1; // -1 means leave the current setting alone
132735731357SCaroline Tice 
132835731357SCaroline Tice         if (! m_options.stop.empty()
132910ad7993SCaroline Tice             && ! VerifyCommandOptionValue (m_options.stop, stop_action))
133035731357SCaroline Tice         {
133135731357SCaroline Tice             result.AppendError ("Invalid argument for command option --stop; must be true or false.\n");
133235731357SCaroline Tice             result.SetStatus (eReturnStatusFailed);
133335731357SCaroline Tice             return false;
133435731357SCaroline Tice         }
133535731357SCaroline Tice 
133635731357SCaroline Tice         if (! m_options.notify.empty()
133710ad7993SCaroline Tice             && ! VerifyCommandOptionValue (m_options.notify, notify_action))
133835731357SCaroline Tice         {
133935731357SCaroline Tice             result.AppendError ("Invalid argument for command option --notify; must be true or false.\n");
134035731357SCaroline Tice             result.SetStatus (eReturnStatusFailed);
134135731357SCaroline Tice             return false;
134235731357SCaroline Tice         }
134335731357SCaroline Tice 
134435731357SCaroline Tice         if (! m_options.pass.empty()
134510ad7993SCaroline Tice             && ! VerifyCommandOptionValue (m_options.pass, pass_action))
134635731357SCaroline Tice         {
134735731357SCaroline Tice             result.AppendError ("Invalid argument for command option --pass; must be true or false.\n");
134835731357SCaroline Tice             result.SetStatus (eReturnStatusFailed);
134935731357SCaroline Tice             return false;
135035731357SCaroline Tice         }
135135731357SCaroline Tice 
135235731357SCaroline Tice         size_t num_args = signal_args.GetArgumentCount();
135335731357SCaroline Tice         UnixSignals &signals = process_sp->GetUnixSignals();
135435731357SCaroline Tice         int num_signals_set = 0;
135535731357SCaroline Tice 
135610ad7993SCaroline Tice         if (num_args > 0)
135710ad7993SCaroline Tice         {
135835731357SCaroline Tice             for (size_t i = 0; i < num_args; ++i)
135935731357SCaroline Tice             {
136035731357SCaroline Tice                 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
136135731357SCaroline Tice                 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
136235731357SCaroline Tice                 {
136310ad7993SCaroline Tice                     // Casting the actions as bools here should be okay, because VerifyCommandOptionValue guarantees
136435731357SCaroline Tice                     // the value is either 0 or 1.
136535731357SCaroline Tice                     if (stop_action != -1)
136635731357SCaroline Tice                         signals.SetShouldStop (signo, (bool) stop_action);
136735731357SCaroline Tice                     if (pass_action != -1)
136835731357SCaroline Tice                     {
136910ad7993SCaroline Tice                         bool suppress = ! ((bool) pass_action);
137010ad7993SCaroline Tice                         signals.SetShouldSuppress (signo, suppress);
137135731357SCaroline Tice                     }
137235731357SCaroline Tice                     if (notify_action != -1)
137335731357SCaroline Tice                         signals.SetShouldNotify (signo, (bool) notify_action);
137435731357SCaroline Tice                     ++num_signals_set;
137535731357SCaroline Tice                 }
137635731357SCaroline Tice                 else
137735731357SCaroline Tice                 {
137835731357SCaroline Tice                     result.AppendErrorWithFormat ("Invalid signal name '%s'\n", signal_args.GetArgumentAtIndex (i));
137935731357SCaroline Tice                 }
138035731357SCaroline Tice             }
138110ad7993SCaroline Tice         }
138210ad7993SCaroline Tice         else
138310ad7993SCaroline Tice         {
138410ad7993SCaroline Tice             // No signal specified, if any command options were specified, update ALL signals.
138510ad7993SCaroline Tice             if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1))
138610ad7993SCaroline Tice             {
138710ad7993SCaroline Tice                 if (m_interpreter.Confirm ("Do you really want to update all the signals?", false))
138810ad7993SCaroline Tice                 {
138910ad7993SCaroline Tice                     int32_t signo = signals.GetFirstSignalNumber();
139010ad7993SCaroline Tice                     while (signo != LLDB_INVALID_SIGNAL_NUMBER)
139110ad7993SCaroline Tice                     {
139210ad7993SCaroline Tice                         if (notify_action != -1)
139310ad7993SCaroline Tice                             signals.SetShouldNotify (signo, (bool) notify_action);
139410ad7993SCaroline Tice                         if (stop_action != -1)
139510ad7993SCaroline Tice                             signals.SetShouldStop (signo, (bool) stop_action);
139610ad7993SCaroline Tice                         if (pass_action != -1)
139710ad7993SCaroline Tice                         {
139810ad7993SCaroline Tice                             bool suppress = ! ((bool) pass_action);
139910ad7993SCaroline Tice                             signals.SetShouldSuppress (signo, suppress);
140010ad7993SCaroline Tice                         }
140110ad7993SCaroline Tice                         signo = signals.GetNextSignalNumber (signo);
140210ad7993SCaroline Tice                     }
140310ad7993SCaroline Tice                 }
140410ad7993SCaroline Tice             }
140510ad7993SCaroline Tice         }
140610ad7993SCaroline Tice 
140710ad7993SCaroline Tice         PrintSignalInformation (result.GetOutputStream(), signal_args, num_signals_set, signals);
140835731357SCaroline Tice 
140935731357SCaroline Tice         if (num_signals_set > 0)
141035731357SCaroline Tice             result.SetStatus (eReturnStatusSuccessFinishNoResult);
141135731357SCaroline Tice         else
141235731357SCaroline Tice             result.SetStatus (eReturnStatusFailed);
141335731357SCaroline Tice 
141435731357SCaroline Tice         return result.Succeeded();
141535731357SCaroline Tice     }
141635731357SCaroline Tice 
141735731357SCaroline Tice protected:
141835731357SCaroline Tice 
141935731357SCaroline Tice     CommandOptions m_options;
142035731357SCaroline Tice };
142135731357SCaroline Tice 
142235731357SCaroline Tice lldb::OptionDefinition
142335731357SCaroline Tice CommandObjectProcessHandle::CommandOptions::g_option_table[] =
142435731357SCaroline Tice {
142535731357SCaroline Tice { LLDB_OPT_SET_1, false, "stop",   's', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the process should be stopped if the signal is received." },
142635731357SCaroline Tice { LLDB_OPT_SET_1, false, "notify", 'n', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the debugger should notify the user if the signal is received." },
142735731357SCaroline Tice { LLDB_OPT_SET_1, false, "pass",  'p', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." },
142835731357SCaroline Tice { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
142935731357SCaroline Tice };
143035731357SCaroline Tice 
143135731357SCaroline Tice //-------------------------------------------------------------------------
143230fdc8d8SChris Lattner // CommandObjectMultiwordProcess
143330fdc8d8SChris Lattner //-------------------------------------------------------------------------
143430fdc8d8SChris Lattner 
14356611103cSGreg Clayton CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter &interpreter) :
1436a7015092SGreg Clayton     CommandObjectMultiword (interpreter,
1437a7015092SGreg Clayton                             "process",
143830fdc8d8SChris Lattner                             "A set of commands for operating on a process.",
143930fdc8d8SChris Lattner                             "process <subcommand> [<subcommand-options>]")
144030fdc8d8SChris Lattner {
1441a7015092SGreg Clayton     LoadSubCommand ("attach",      CommandObjectSP (new CommandObjectProcessAttach (interpreter)));
1442a7015092SGreg Clayton     LoadSubCommand ("launch",      CommandObjectSP (new CommandObjectProcessLaunch (interpreter)));
1443a7015092SGreg Clayton     LoadSubCommand ("continue",    CommandObjectSP (new CommandObjectProcessContinue (interpreter)));
1444a7015092SGreg Clayton     LoadSubCommand ("detach",      CommandObjectSP (new CommandObjectProcessDetach (interpreter)));
1445a7015092SGreg Clayton     LoadSubCommand ("signal",      CommandObjectSP (new CommandObjectProcessSignal (interpreter)));
144635731357SCaroline Tice     LoadSubCommand ("handle",      CommandObjectSP (new CommandObjectProcessHandle (interpreter)));
1447a7015092SGreg Clayton     LoadSubCommand ("status",      CommandObjectSP (new CommandObjectProcessStatus (interpreter)));
1448a7015092SGreg Clayton     LoadSubCommand ("interrupt",   CommandObjectSP (new CommandObjectProcessInterrupt (interpreter)));
1449a7015092SGreg Clayton     LoadSubCommand ("kill",        CommandObjectSP (new CommandObjectProcessKill (interpreter)));
145030fdc8d8SChris Lattner }
145130fdc8d8SChris Lattner 
145230fdc8d8SChris Lattner CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess ()
145330fdc8d8SChris Lattner {
145430fdc8d8SChris Lattner }
145530fdc8d8SChris Lattner 
1456