130fdc8d8SChris Lattner //===-- CommandObjectProcess.cpp --------------------------------*- C++ -*-===//
230fdc8d8SChris Lattner //
330fdc8d8SChris Lattner //                     The LLVM Compiler Infrastructure
430fdc8d8SChris Lattner //
530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source
630fdc8d8SChris Lattner // License. See LICENSE.TXT for details.
730fdc8d8SChris Lattner //
830fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
930fdc8d8SChris Lattner 
1030fdc8d8SChris Lattner #include "CommandObjectProcess.h"
1130fdc8d8SChris Lattner 
1230fdc8d8SChris Lattner // C Includes
1330fdc8d8SChris Lattner // C++ Includes
1430fdc8d8SChris Lattner // Other libraries and framework includes
1530fdc8d8SChris Lattner // Project includes
1640af72e1SJim Ingham #include "lldb/Interpreter/Args.h"
1740af72e1SJim Ingham #include "lldb/Interpreter/Options.h"
1830fdc8d8SChris Lattner #include "lldb/Core/State.h"
1930fdc8d8SChris Lattner #include "lldb/Interpreter/CommandInterpreter.h"
2030fdc8d8SChris Lattner #include "lldb/Interpreter/CommandReturnObject.h"
214b9bea87SJim Ingham #include "./CommandObjectThread.h"
2230fdc8d8SChris Lattner #include "lldb/Target/Process.h"
2330fdc8d8SChris Lattner #include "lldb/Target/Target.h"
2430fdc8d8SChris Lattner #include "lldb/Target/Thread.h"
2530fdc8d8SChris Lattner 
2630fdc8d8SChris Lattner using namespace lldb;
2730fdc8d8SChris Lattner using namespace lldb_private;
2830fdc8d8SChris Lattner 
2930fdc8d8SChris Lattner //-------------------------------------------------------------------------
3030fdc8d8SChris Lattner // CommandObjectProcessLaunch
3130fdc8d8SChris Lattner //-------------------------------------------------------------------------
3230fdc8d8SChris Lattner 
3330fdc8d8SChris Lattner class CommandObjectProcessLaunch : public CommandObject
3430fdc8d8SChris Lattner {
3530fdc8d8SChris Lattner public:
3630fdc8d8SChris Lattner 
3730fdc8d8SChris Lattner     class CommandOptions : public Options
3830fdc8d8SChris Lattner     {
3930fdc8d8SChris Lattner     public:
4030fdc8d8SChris Lattner 
4130fdc8d8SChris Lattner         CommandOptions () :
4230fdc8d8SChris Lattner             Options()
4330fdc8d8SChris Lattner         {
4430fdc8d8SChris Lattner             // Keep default values of all options in one place: ResetOptionValues ()
4530fdc8d8SChris Lattner             ResetOptionValues ();
4630fdc8d8SChris Lattner         }
4730fdc8d8SChris Lattner 
4830fdc8d8SChris Lattner         ~CommandOptions ()
4930fdc8d8SChris Lattner         {
5030fdc8d8SChris Lattner         }
5130fdc8d8SChris Lattner 
5230fdc8d8SChris Lattner         Error
5330fdc8d8SChris Lattner         SetOptionValue (int option_idx, const char *option_arg)
5430fdc8d8SChris Lattner         {
5530fdc8d8SChris Lattner             Error error;
5630fdc8d8SChris Lattner             char short_option = (char) m_getopt_table[option_idx].val;
5730fdc8d8SChris Lattner 
5830fdc8d8SChris Lattner             switch (short_option)
5930fdc8d8SChris Lattner             {
6030fdc8d8SChris Lattner                 case 's':   stop_at_entry = true;       break;
6130fdc8d8SChris Lattner                 case 'e':   stderr_path = option_arg;   break;
6230fdc8d8SChris Lattner                 case 'i':   stdin_path  = option_arg;   break;
6330fdc8d8SChris Lattner                 case 'o':   stdout_path = option_arg;   break;
6430fdc8d8SChris Lattner                 case 'p':   plugin_name = option_arg;   break;
6530fdc8d8SChris Lattner                 default:
6630fdc8d8SChris Lattner                     error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
6730fdc8d8SChris Lattner                     break;
6830fdc8d8SChris Lattner 
6930fdc8d8SChris Lattner             }
7030fdc8d8SChris Lattner             return error;
7130fdc8d8SChris Lattner         }
7230fdc8d8SChris Lattner 
7330fdc8d8SChris Lattner         void
7430fdc8d8SChris Lattner         ResetOptionValues ()
7530fdc8d8SChris Lattner         {
7630fdc8d8SChris Lattner             Options::ResetOptionValues();
7730fdc8d8SChris Lattner             stop_at_entry = false;
7830fdc8d8SChris Lattner             stdin_path.clear();
7930fdc8d8SChris Lattner             stdout_path.clear();
8030fdc8d8SChris Lattner             stderr_path.clear();
8130fdc8d8SChris Lattner             plugin_name.clear();
8230fdc8d8SChris Lattner         }
8330fdc8d8SChris Lattner 
8430fdc8d8SChris Lattner         const lldb::OptionDefinition*
8530fdc8d8SChris Lattner         GetDefinitions ()
8630fdc8d8SChris Lattner         {
8730fdc8d8SChris Lattner             return g_option_table;
8830fdc8d8SChris Lattner         }
8930fdc8d8SChris Lattner 
9030fdc8d8SChris Lattner         // Options table: Required for subclasses of Options.
9130fdc8d8SChris Lattner 
9230fdc8d8SChris Lattner         static lldb::OptionDefinition g_option_table[];
9330fdc8d8SChris Lattner 
9430fdc8d8SChris Lattner         // Instance variables to hold the values for command options.
9530fdc8d8SChris Lattner 
9630fdc8d8SChris Lattner         bool stop_at_entry;
9730fdc8d8SChris Lattner         std::string stderr_path;
9830fdc8d8SChris Lattner         std::string stdin_path;
9930fdc8d8SChris Lattner         std::string stdout_path;
10030fdc8d8SChris Lattner         std::string plugin_name;
10130fdc8d8SChris Lattner 
10230fdc8d8SChris Lattner     };
10330fdc8d8SChris Lattner 
104a7015092SGreg Clayton     CommandObjectProcessLaunch (CommandInterpreter &interpreter) :
105a7015092SGreg Clayton         CommandObject (interpreter,
106a7015092SGreg Clayton                        "process launch",
107e3d26315SCaroline Tice                        "Launch the executable in the debugger.",
108405fe67fSCaroline Tice                        NULL)
10930fdc8d8SChris Lattner     {
110405fe67fSCaroline Tice         CommandArgumentEntry arg;
111405fe67fSCaroline Tice         CommandArgumentData run_args_arg;
112405fe67fSCaroline Tice 
113405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
114405fe67fSCaroline Tice         run_args_arg.arg_type = eArgTypeRunArgs;
115405fe67fSCaroline Tice         run_args_arg.arg_repetition = eArgRepeatOptional;
116405fe67fSCaroline Tice 
117405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
118405fe67fSCaroline Tice         arg.push_back (run_args_arg);
119405fe67fSCaroline Tice 
120405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
121405fe67fSCaroline Tice         m_arguments.push_back (arg);
12230fdc8d8SChris Lattner     }
12330fdc8d8SChris Lattner 
12430fdc8d8SChris Lattner 
12530fdc8d8SChris Lattner     ~CommandObjectProcessLaunch ()
12630fdc8d8SChris Lattner     {
12730fdc8d8SChris Lattner     }
12830fdc8d8SChris Lattner 
12930fdc8d8SChris Lattner     Options *
13030fdc8d8SChris Lattner     GetOptions ()
13130fdc8d8SChris Lattner     {
13230fdc8d8SChris Lattner         return &m_options;
13330fdc8d8SChris Lattner     }
13430fdc8d8SChris Lattner 
13530fdc8d8SChris Lattner     bool
13605faeb71SGreg Clayton     Execute (Args& launch_args, CommandReturnObject &result)
13730fdc8d8SChris Lattner     {
138a7015092SGreg Clayton         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
13930fdc8d8SChris Lattner 
14030fdc8d8SChris Lattner         if (target == NULL)
14130fdc8d8SChris Lattner         {
14230fdc8d8SChris Lattner             result.AppendError ("invalid target, set executable file using 'file' command");
14330fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
14430fdc8d8SChris Lattner             return false;
14530fdc8d8SChris Lattner         }
14630fdc8d8SChris Lattner 
14730fdc8d8SChris Lattner         // If our listener is NULL, users aren't allows to launch
14830fdc8d8SChris Lattner         char filename[PATH_MAX];
14930fdc8d8SChris Lattner         Module *exe_module = target->GetExecutableModule().get();
15030fdc8d8SChris Lattner         exe_module->GetFileSpec().GetPath(filename, sizeof(filename));
15130fdc8d8SChris Lattner 
152a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
153a7015092SGreg Clayton         if (process && process->IsAlive())
15430fdc8d8SChris Lattner         {
15530fdc8d8SChris Lattner             result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before running again.\n",
15630fdc8d8SChris Lattner                                           process->GetID());
15730fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
15830fdc8d8SChris Lattner             return false;
15930fdc8d8SChris Lattner         }
16030fdc8d8SChris Lattner 
16130fdc8d8SChris Lattner         const char *plugin_name;
16230fdc8d8SChris Lattner         if (!m_options.plugin_name.empty())
16330fdc8d8SChris Lattner             plugin_name = m_options.plugin_name.c_str();
16430fdc8d8SChris Lattner         else
16530fdc8d8SChris Lattner             plugin_name = NULL;
16630fdc8d8SChris Lattner 
167a7015092SGreg Clayton         process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
16830fdc8d8SChris Lattner 
169a7015092SGreg Clayton         if (process == NULL)
1703df9a8dfSCaroline Tice         {
171*43a8c39bSCaroline Tice             result.AppendErrorWithFormat ("Failed to find a process plugin for executable.\n");
172a7015092SGreg Clayton             result.SetStatus (eReturnStatusFailed);
173a7015092SGreg Clayton             return false;
1743df9a8dfSCaroline Tice         }
1753df9a8dfSCaroline Tice 
176a7015092SGreg Clayton         // If no launch args were given on the command line, then use any that
177a7015092SGreg Clayton         // might have been set using the "run-args" set variable.
17830fdc8d8SChris Lattner         if (launch_args.GetArgumentCount() == 0)
17930fdc8d8SChris Lattner         {
180a7015092SGreg Clayton             if (process->GetRunArguments().GetArgumentCount() > 0)
181a7015092SGreg Clayton                 launch_args = process->GetRunArguments();
18230fdc8d8SChris Lattner         }
18330fdc8d8SChris Lattner 
184a7015092SGreg Clayton         Args environment;
18530fdc8d8SChris Lattner 
186a7015092SGreg Clayton         process->GetEnvironmentAsArgs (environment);
187a7015092SGreg Clayton 
188a7015092SGreg Clayton         uint32_t launch_flags = eLaunchFlagNone;
189a7015092SGreg Clayton 
190a7015092SGreg Clayton         if (process->GetDisableASLR())
191a7015092SGreg Clayton             launch_flags |= eLaunchFlagDisableASLR;
192a7015092SGreg Clayton 
19330fdc8d8SChris Lattner         const char *archname = exe_module->GetArchitecture().AsCString();
19430fdc8d8SChris Lattner 
19530fdc8d8SChris Lattner         const char * stdin_path = NULL;
19630fdc8d8SChris Lattner         const char * stdout_path = NULL;
19730fdc8d8SChris Lattner         const char * stderr_path = NULL;
19830fdc8d8SChris Lattner 
199a7015092SGreg Clayton         // Were any standard input/output/error paths given on the command line?
200a7015092SGreg Clayton         if (m_options.stdin_path.empty() &&
20130fdc8d8SChris Lattner             m_options.stdout_path.empty() &&
202a7015092SGreg Clayton             m_options.stderr_path.empty())
20330fdc8d8SChris Lattner         {
204a7015092SGreg Clayton             // No standard file handles were given on the command line, check
205a7015092SGreg Clayton             // with the process object in case they were give using "set settings"
206a7015092SGreg Clayton             stdin_path = process->GetStandardInputPath();
207a7015092SGreg Clayton             stdout_path = process->GetStandardOutputPath();
208a7015092SGreg Clayton             stderr_path = process->GetStandardErrorPath();
209a7015092SGreg Clayton         }
210a7015092SGreg Clayton         else
211a7015092SGreg Clayton         {
212a7015092SGreg Clayton             stdin_path = m_options.stdin_path.empty()  ? NULL : m_options.stdin_path.c_str();
213a7015092SGreg Clayton             stdout_path = m_options.stdout_path.empty() ? NULL : m_options.stdout_path.c_str();
214a7015092SGreg Clayton             stderr_path = m_options.stderr_path.empty() ? NULL : m_options.stderr_path.c_str();
21530fdc8d8SChris Lattner         }
21630fdc8d8SChris Lattner 
217a7015092SGreg Clayton         if (stdin_path == NULL)
218a7015092SGreg Clayton             stdin_path = "/dev/null";
219a7015092SGreg Clayton         if (stdout_path == NULL)
220a7015092SGreg Clayton             stdout_path = "/dev/null";
221a7015092SGreg Clayton         if (stderr_path == NULL)
222a7015092SGreg Clayton             stderr_path = "/dev/null";
223a7015092SGreg Clayton 
224a7015092SGreg Clayton         Error error (process->Launch (launch_args.GetArgumentCount() ? launch_args.GetConstArgumentVector() : NULL,
225a7015092SGreg Clayton                                       environment.GetArgumentCount() ? environment.GetConstArgumentVector() : NULL,
226f681b94fSGreg Clayton                                       launch_flags,
22730fdc8d8SChris Lattner                                       stdin_path,
22830fdc8d8SChris Lattner                                       stdout_path,
22930fdc8d8SChris Lattner                                       stderr_path));
23030fdc8d8SChris Lattner 
23130fdc8d8SChris Lattner         if (error.Success())
23230fdc8d8SChris Lattner         {
23330fdc8d8SChris Lattner             result.AppendMessageWithFormat ("Launching '%s'  (%s)\n", filename, archname);
23405faeb71SGreg Clayton             result.SetDidChangeProcessState (true);
23530fdc8d8SChris Lattner             if (m_options.stop_at_entry == false)
23630fdc8d8SChris Lattner             {
23705faeb71SGreg Clayton                 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
23830fdc8d8SChris Lattner                 StateType state = process->WaitForProcessToStop (NULL);
23930fdc8d8SChris Lattner 
24030fdc8d8SChris Lattner                 if (state == eStateStopped)
24130fdc8d8SChris Lattner                 {
24205faeb71SGreg Clayton                     error = process->Resume();
24305faeb71SGreg Clayton                     if (error.Success())
24405faeb71SGreg Clayton                     {
24505faeb71SGreg Clayton                         bool synchronous_execution = m_interpreter.GetSynchronous ();
24630fdc8d8SChris Lattner                         if (synchronous_execution)
24730fdc8d8SChris Lattner                         {
24805faeb71SGreg Clayton                             state = process->WaitForProcessToStop (NULL);
24930fdc8d8SChris Lattner                             result.SetDidChangeProcessState (true);
25005faeb71SGreg Clayton                             result.SetStatus (eReturnStatusSuccessFinishResult);
25105faeb71SGreg Clayton                         }
25205faeb71SGreg Clayton                         else
25305faeb71SGreg Clayton                         {
25405faeb71SGreg Clayton                             result.SetStatus (eReturnStatusSuccessContinuingNoResult);
25505faeb71SGreg Clayton                         }
25605faeb71SGreg Clayton                     }
25730fdc8d8SChris Lattner                 }
25830fdc8d8SChris Lattner             }
25930fdc8d8SChris Lattner         }
26030fdc8d8SChris Lattner 
26130fdc8d8SChris Lattner         return result.Succeeded();
26230fdc8d8SChris Lattner     }
26330fdc8d8SChris Lattner 
264ebc09c36SJim Ingham     virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
265ebc09c36SJim Ingham     {
266ebc09c36SJim Ingham         // No repeat for "process launch"...
267ebc09c36SJim Ingham         return "";
268ebc09c36SJim Ingham     }
269ebc09c36SJim Ingham 
27030fdc8d8SChris Lattner protected:
27130fdc8d8SChris Lattner 
27230fdc8d8SChris Lattner     CommandOptions m_options;
27330fdc8d8SChris Lattner };
27430fdc8d8SChris Lattner 
27530fdc8d8SChris Lattner 
27630fdc8d8SChris Lattner lldb::OptionDefinition
27730fdc8d8SChris Lattner CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
27830fdc8d8SChris Lattner {
279deaab222SCaroline Tice { LLDB_OPT_SET_1, false, "stop-at-entry", 's', no_argument,       NULL, 0, eArgTypeNone,        "Stop at the entry point of the program when launching a process."},
280deaab222SCaroline Tice { LLDB_OPT_SET_1, false, "stdin",         'i', required_argument, NULL, 0, eArgTypePath,    "Redirect stdin for the process to <path>."},
281deaab222SCaroline Tice { LLDB_OPT_SET_1, false, "stdout",        'o', required_argument, NULL, 0, eArgTypePath,    "Redirect stdout for the process to <path>."},
282deaab222SCaroline Tice { LLDB_OPT_SET_1, false, "stderr",        'e', required_argument, NULL, 0, eArgTypePath,    "Redirect stderr for the process to <path>."},
283deaab222SCaroline Tice { LLDB_OPT_SET_1, false, "plugin",        'p', required_argument, NULL, 0, eArgTypePlugin,  "Name of the process plugin you want to use."},
284deaab222SCaroline Tice { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
28530fdc8d8SChris Lattner };
28630fdc8d8SChris Lattner 
28730fdc8d8SChris Lattner 
28830fdc8d8SChris Lattner //-------------------------------------------------------------------------
28930fdc8d8SChris Lattner // CommandObjectProcessAttach
29030fdc8d8SChris Lattner //-------------------------------------------------------------------------
29130fdc8d8SChris Lattner 
29230fdc8d8SChris Lattner class CommandObjectProcessAttach : public CommandObject
29330fdc8d8SChris Lattner {
29430fdc8d8SChris Lattner public:
29530fdc8d8SChris Lattner 
29630fdc8d8SChris Lattner     class CommandOptions : public Options
29730fdc8d8SChris Lattner     {
29830fdc8d8SChris Lattner     public:
29930fdc8d8SChris Lattner 
30030fdc8d8SChris Lattner         CommandOptions () :
30130fdc8d8SChris Lattner             Options()
30230fdc8d8SChris Lattner         {
30330fdc8d8SChris Lattner             // Keep default values of all options in one place: ResetOptionValues ()
30430fdc8d8SChris Lattner             ResetOptionValues ();
30530fdc8d8SChris Lattner         }
30630fdc8d8SChris Lattner 
30730fdc8d8SChris Lattner         ~CommandOptions ()
30830fdc8d8SChris Lattner         {
30930fdc8d8SChris Lattner         }
31030fdc8d8SChris Lattner 
31130fdc8d8SChris Lattner         Error
31230fdc8d8SChris Lattner         SetOptionValue (int option_idx, const char *option_arg)
31330fdc8d8SChris Lattner         {
31430fdc8d8SChris Lattner             Error error;
31530fdc8d8SChris Lattner             char short_option = (char) m_getopt_table[option_idx].val;
31630fdc8d8SChris Lattner             bool success = false;
31730fdc8d8SChris Lattner             switch (short_option)
31830fdc8d8SChris Lattner             {
31930fdc8d8SChris Lattner                 case 'p':
32030fdc8d8SChris Lattner                     pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success);
32130fdc8d8SChris Lattner                     if (!success || pid == LLDB_INVALID_PROCESS_ID)
32230fdc8d8SChris Lattner                     {
32330fdc8d8SChris Lattner                         error.SetErrorStringWithFormat("Invalid process ID '%s'.\n", option_arg);
32430fdc8d8SChris Lattner                     }
32530fdc8d8SChris Lattner                     break;
32630fdc8d8SChris Lattner 
32730fdc8d8SChris Lattner                 case 'P':
32830fdc8d8SChris Lattner                     plugin_name = option_arg;
32930fdc8d8SChris Lattner                     break;
33030fdc8d8SChris Lattner 
33130fdc8d8SChris Lattner                 case 'n':
33230fdc8d8SChris Lattner                     name.assign(option_arg);
33330fdc8d8SChris Lattner                     break;
33430fdc8d8SChris Lattner 
33530fdc8d8SChris Lattner                 case 'w':
33630fdc8d8SChris Lattner                     waitfor = true;
33730fdc8d8SChris Lattner                     break;
33830fdc8d8SChris Lattner 
33930fdc8d8SChris Lattner                 default:
34030fdc8d8SChris Lattner                     error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
34130fdc8d8SChris Lattner                     break;
34230fdc8d8SChris Lattner             }
34330fdc8d8SChris Lattner             return error;
34430fdc8d8SChris Lattner         }
34530fdc8d8SChris Lattner 
34630fdc8d8SChris Lattner         void
34730fdc8d8SChris Lattner         ResetOptionValues ()
34830fdc8d8SChris Lattner         {
34930fdc8d8SChris Lattner             Options::ResetOptionValues();
35030fdc8d8SChris Lattner             pid = LLDB_INVALID_PROCESS_ID;
35130fdc8d8SChris Lattner             name.clear();
35230fdc8d8SChris Lattner             waitfor = false;
35330fdc8d8SChris Lattner         }
35430fdc8d8SChris Lattner 
35530fdc8d8SChris Lattner         const lldb::OptionDefinition*
35630fdc8d8SChris Lattner         GetDefinitions ()
35730fdc8d8SChris Lattner         {
35830fdc8d8SChris Lattner             return g_option_table;
35930fdc8d8SChris Lattner         }
36030fdc8d8SChris Lattner 
3615aee162fSJim Ingham         virtual bool
362a7015092SGreg Clayton         HandleOptionArgumentCompletion (CommandInterpreter &interpeter,
3635aee162fSJim Ingham                                         Args &input,
3645aee162fSJim Ingham                                         int cursor_index,
3655aee162fSJim Ingham                                         int char_pos,
3665aee162fSJim Ingham                                         OptionElementVector &opt_element_vector,
3675aee162fSJim Ingham                                         int opt_element_index,
3685aee162fSJim Ingham                                         int match_start_point,
3695aee162fSJim Ingham                                         int max_return_elements,
3705aee162fSJim Ingham                                         bool &word_complete,
3715aee162fSJim Ingham                                         StringList &matches)
3725aee162fSJim Ingham         {
3735aee162fSJim Ingham             int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
3745aee162fSJim Ingham             int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
3755aee162fSJim Ingham 
3765aee162fSJim Ingham             // We are only completing the name option for now...
3775aee162fSJim Ingham 
3785aee162fSJim Ingham             const lldb::OptionDefinition *opt_defs = GetDefinitions();
3795aee162fSJim Ingham             if (opt_defs[opt_defs_index].short_option == 'n')
3805aee162fSJim Ingham             {
3815aee162fSJim Ingham                 // Are we in the name?
3825aee162fSJim Ingham 
3835aee162fSJim Ingham                 // Look to see if there is a -P argument provided, and if so use that plugin, otherwise
3845aee162fSJim Ingham                 // use the default plugin.
385a7015092SGreg Clayton                 Process *process = interpeter.GetDebugger().GetExecutionContext().process;
3865aee162fSJim Ingham                 bool need_to_delete_process = false;
3875aee162fSJim Ingham 
3885aee162fSJim Ingham                 const char *partial_name = NULL;
3895aee162fSJim Ingham                 partial_name = input.GetArgumentAtIndex(opt_arg_pos);
3905aee162fSJim Ingham 
3915aee162fSJim Ingham                 if (process && process->IsAlive())
3925aee162fSJim Ingham                     return true;
3935aee162fSJim Ingham 
394a7015092SGreg Clayton                 Target *target = interpeter.GetDebugger().GetSelectedTarget().get();
3955aee162fSJim Ingham                 if (target == NULL)
3965aee162fSJim Ingham                 {
3975aee162fSJim Ingham                     // No target has been set yet, for now do host completion.  Otherwise I don't know how we would
3985aee162fSJim Ingham                     // figure out what the right target to use is...
3995aee162fSJim Ingham                     std::vector<lldb::pid_t> pids;
4005aee162fSJim Ingham                     Host::ListProcessesMatchingName (partial_name, matches, pids);
4015aee162fSJim Ingham                     return true;
4025aee162fSJim Ingham                 }
4035aee162fSJim Ingham                 if (!process)
4045aee162fSJim Ingham                 {
405a7015092SGreg Clayton                     process = target->CreateProcess (interpeter.GetDebugger().GetListener(), partial_name).get();
4065aee162fSJim Ingham                     need_to_delete_process = true;
4075aee162fSJim Ingham                 }
4085aee162fSJim Ingham 
4095aee162fSJim Ingham                 if (process)
4105aee162fSJim Ingham                 {
4115aee162fSJim Ingham                     matches.Clear();
4125aee162fSJim Ingham                     std::vector<lldb::pid_t> pids;
4135aee162fSJim Ingham                     process->ListProcessesMatchingName (NULL, matches, pids);
4145aee162fSJim Ingham                     if (need_to_delete_process)
4155aee162fSJim Ingham                         target->DeleteCurrentProcess();
4165aee162fSJim Ingham                     return true;
4175aee162fSJim Ingham                 }
4185aee162fSJim Ingham             }
4195aee162fSJim Ingham 
4205aee162fSJim Ingham             return false;
4215aee162fSJim Ingham         }
4225aee162fSJim Ingham 
42330fdc8d8SChris Lattner         // Options table: Required for subclasses of Options.
42430fdc8d8SChris Lattner 
42530fdc8d8SChris Lattner         static lldb::OptionDefinition g_option_table[];
42630fdc8d8SChris Lattner 
42730fdc8d8SChris Lattner         // Instance variables to hold the values for command options.
42830fdc8d8SChris Lattner 
42930fdc8d8SChris Lattner         lldb::pid_t pid;
43030fdc8d8SChris Lattner         std::string plugin_name;
43130fdc8d8SChris Lattner         std::string name;
43230fdc8d8SChris Lattner         bool waitfor;
43330fdc8d8SChris Lattner     };
43430fdc8d8SChris Lattner 
435a7015092SGreg Clayton     CommandObjectProcessAttach (CommandInterpreter &interpreter) :
436a7015092SGreg Clayton         CommandObject (interpreter,
437a7015092SGreg Clayton                        "process attach",
438e3d26315SCaroline Tice                        "Attach to a process.",
4395aee162fSJim Ingham                        "process attach <cmd-options>")
4405aee162fSJim Ingham     {
4415aee162fSJim Ingham     }
4425aee162fSJim Ingham 
4435aee162fSJim Ingham     ~CommandObjectProcessAttach ()
4445aee162fSJim Ingham     {
4455aee162fSJim Ingham     }
4465aee162fSJim Ingham 
4475aee162fSJim Ingham     bool
448a7015092SGreg Clayton     Execute (Args& command,
4495aee162fSJim Ingham              CommandReturnObject &result)
4505aee162fSJim Ingham     {
451a7015092SGreg Clayton         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
4525aee162fSJim Ingham 
453a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
4545aee162fSJim Ingham         if (process)
4555aee162fSJim Ingham         {
4565aee162fSJim Ingham             if (process->IsAlive())
4575aee162fSJim Ingham             {
4585aee162fSJim Ingham                 result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before attaching.\n",
4595aee162fSJim Ingham                                               process->GetID());
4605aee162fSJim Ingham                 result.SetStatus (eReturnStatusFailed);
4615aee162fSJim Ingham                 return false;
4625aee162fSJim Ingham             }
4635aee162fSJim Ingham         }
4645aee162fSJim Ingham 
4655aee162fSJim Ingham         if (target == NULL)
4665aee162fSJim Ingham         {
4675aee162fSJim Ingham             // If there isn't a current target create one.
4685aee162fSJim Ingham             TargetSP new_target_sp;
4695aee162fSJim Ingham             FileSpec emptyFileSpec;
4705aee162fSJim Ingham             ArchSpec emptyArchSpec;
4715aee162fSJim Ingham             Error error;
4725aee162fSJim Ingham 
473a7015092SGreg Clayton             error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(),
4745aee162fSJim Ingham                                                                               emptyFileSpec,
4755aee162fSJim Ingham                                                                               emptyArchSpec,
4765aee162fSJim Ingham                                                                               NULL,
4775aee162fSJim Ingham                                                                               false,
4785aee162fSJim Ingham                                                                               new_target_sp);
4795aee162fSJim Ingham             target = new_target_sp.get();
4805aee162fSJim Ingham             if (target == NULL || error.Fail())
4815aee162fSJim Ingham             {
4825aee162fSJim Ingham                 result.AppendError(error.AsCString("Error creating empty target"));
4835aee162fSJim Ingham                 return false;
4845aee162fSJim Ingham             }
485a7015092SGreg Clayton             m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target);
4865aee162fSJim Ingham         }
4875aee162fSJim Ingham 
4885aee162fSJim Ingham         // Record the old executable module, we want to issue a warning if the process of attaching changed the
4895aee162fSJim Ingham         // current executable (like somebody said "file foo" then attached to a PID whose executable was bar.)
4905aee162fSJim Ingham 
4915aee162fSJim Ingham         ModuleSP old_exec_module_sp = target->GetExecutableModule();
4925aee162fSJim Ingham         ArchSpec old_arch_spec = target->GetArchitecture();
4935aee162fSJim Ingham 
4945aee162fSJim Ingham         if (command.GetArgumentCount())
4955aee162fSJim Ingham         {
4965aee162fSJim Ingham             result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
4975aee162fSJim Ingham             result.SetStatus (eReturnStatusFailed);
4985aee162fSJim Ingham         }
4995aee162fSJim Ingham         else
5005aee162fSJim Ingham         {
5015aee162fSJim Ingham             const char *plugin_name = NULL;
5025aee162fSJim Ingham 
5035aee162fSJim Ingham             if (!m_options.plugin_name.empty())
5045aee162fSJim Ingham                 plugin_name = m_options.plugin_name.c_str();
5055aee162fSJim Ingham 
506a7015092SGreg Clayton             process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
5075aee162fSJim Ingham 
5085aee162fSJim Ingham             if (process)
5095aee162fSJim Ingham             {
5105aee162fSJim Ingham                 Error error;
5115aee162fSJim Ingham                 int attach_pid = m_options.pid;
5125aee162fSJim Ingham 
5133a0b9cdfSJim Ingham                 const char *wait_name = NULL;
5143a0b9cdfSJim Ingham 
5155aee162fSJim Ingham                 if (m_options.name.empty())
5165aee162fSJim Ingham                 {
5173a0b9cdfSJim Ingham                     if (old_exec_module_sp)
5183a0b9cdfSJim Ingham                     {
5193a0b9cdfSJim Ingham                         wait_name = old_exec_module_sp->GetFileSpec().GetFilename().AsCString();
5203a0b9cdfSJim Ingham                     }
5215aee162fSJim Ingham                 }
5225aee162fSJim Ingham                 else
5235aee162fSJim Ingham                 {
5243a0b9cdfSJim Ingham                     wait_name = m_options.name.c_str();
5253a0b9cdfSJim Ingham                 }
5263a0b9cdfSJim Ingham 
5273a0b9cdfSJim Ingham                 // If we are waiting for a process with this name to show up, do that first.
5283a0b9cdfSJim Ingham                 if (m_options.waitfor)
5293a0b9cdfSJim Ingham                 {
5303a0b9cdfSJim Ingham 
5313a0b9cdfSJim Ingham                     if (wait_name == NULL)
5323a0b9cdfSJim Ingham                     {
5333a0b9cdfSJim Ingham                         result.AppendError("Invalid arguments: must have a file loaded or supply a process name with the waitfor option.\n");
5343a0b9cdfSJim Ingham                         result.SetStatus (eReturnStatusFailed);
5353a0b9cdfSJim Ingham                         return false;
5363a0b9cdfSJim Ingham                     }
5373a0b9cdfSJim Ingham 
538a7015092SGreg Clayton                     m_interpreter.GetDebugger().GetOutputStream().Printf("Waiting to attach to a process named \"%s\".\n", wait_name);
5393a0b9cdfSJim Ingham                     error = process->Attach (wait_name, m_options.waitfor);
5405aee162fSJim Ingham                     if (error.Success())
5415aee162fSJim Ingham                     {
5425aee162fSJim Ingham                         result.SetStatus (eReturnStatusSuccessContinuingNoResult);
5435aee162fSJim Ingham                     }
5445aee162fSJim Ingham                     else
5455aee162fSJim Ingham                     {
5465aee162fSJim Ingham                         result.AppendErrorWithFormat ("Waiting for a process to launch named '%s': %s\n",
5473a0b9cdfSJim Ingham                                                          wait_name,
5485aee162fSJim Ingham                                                          error.AsCString());
5495aee162fSJim Ingham                         result.SetStatus (eReturnStatusFailed);
5505aee162fSJim Ingham                         return false;
5515aee162fSJim Ingham                     }
5525aee162fSJim Ingham                 }
5535aee162fSJim Ingham                 else
5545aee162fSJim Ingham                 {
5555aee162fSJim Ingham                     // If the process was specified by name look it up, so we can warn if there are multiple
5565aee162fSJim Ingham                     // processes with this pid.
5575aee162fSJim Ingham 
5583a0b9cdfSJim Ingham                     if (attach_pid == LLDB_INVALID_PROCESS_ID && wait_name != NULL)
5595aee162fSJim Ingham                     {
5605aee162fSJim Ingham                         std::vector<lldb::pid_t> pids;
5615aee162fSJim Ingham                         StringList matches;
5625aee162fSJim Ingham 
5633a0b9cdfSJim Ingham                         process->ListProcessesMatchingName(wait_name, matches, pids);
5645aee162fSJim Ingham                         if (matches.GetSize() > 1)
5655aee162fSJim Ingham                         {
5663a0b9cdfSJim Ingham                             result.AppendErrorWithFormat("More than one process named %s\n", wait_name);
5675aee162fSJim Ingham                             result.SetStatus (eReturnStatusFailed);
5685aee162fSJim Ingham                             return false;
5695aee162fSJim Ingham                         }
5705aee162fSJim Ingham                         else if (matches.GetSize() == 0)
5715aee162fSJim Ingham                         {
5723a0b9cdfSJim Ingham                             result.AppendErrorWithFormat("Could not find a process named %s\n", wait_name);
5735aee162fSJim Ingham                             result.SetStatus (eReturnStatusFailed);
5745aee162fSJim Ingham                             return false;
5755aee162fSJim Ingham                         }
5765aee162fSJim Ingham                         else
5775aee162fSJim Ingham                         {
5785aee162fSJim Ingham                             attach_pid = pids[0];
5795aee162fSJim Ingham                         }
5805aee162fSJim Ingham 
5815aee162fSJim Ingham                     }
5825aee162fSJim Ingham 
5835aee162fSJim Ingham                     if (attach_pid != LLDB_INVALID_PROCESS_ID)
5845aee162fSJim Ingham                     {
5855aee162fSJim Ingham                         error = process->Attach (attach_pid);
5865aee162fSJim Ingham                         if (error.Success())
5875aee162fSJim Ingham                         {
5885aee162fSJim Ingham                             result.SetStatus (eReturnStatusSuccessContinuingNoResult);
5895aee162fSJim Ingham                         }
5905aee162fSJim Ingham                         else
5915aee162fSJim Ingham                         {
5925aee162fSJim Ingham                             result.AppendErrorWithFormat ("Attaching to process %i failed: %s.\n",
5935aee162fSJim Ingham                                                          attach_pid,
5945aee162fSJim Ingham                                                          error.AsCString());
5955aee162fSJim Ingham                             result.SetStatus (eReturnStatusFailed);
5965aee162fSJim Ingham                         }
5975aee162fSJim Ingham                     }
5985aee162fSJim Ingham                     else
5995aee162fSJim Ingham                     {
6005aee162fSJim Ingham                         result.AppendErrorWithFormat ("No PID specified for attach\n",
6015aee162fSJim Ingham                                                          attach_pid,
6025aee162fSJim Ingham                                                          error.AsCString());
6035aee162fSJim Ingham                         result.SetStatus (eReturnStatusFailed);
6045aee162fSJim Ingham 
6055aee162fSJim Ingham                     }
6065aee162fSJim Ingham                 }
6075aee162fSJim Ingham             }
6085aee162fSJim Ingham         }
6095aee162fSJim Ingham 
6105aee162fSJim Ingham         if (result.Succeeded())
6115aee162fSJim Ingham         {
6125aee162fSJim Ingham             // Okay, we're done.  Last step is to warn if the executable module has changed:
6135aee162fSJim Ingham             if (!old_exec_module_sp)
6145aee162fSJim Ingham             {
6155aee162fSJim Ingham                 char new_path[PATH_MAX + 1];
6165aee162fSJim Ingham                 target->GetExecutableModule()->GetFileSpec().GetPath(new_path, PATH_MAX);
6175aee162fSJim Ingham 
6185aee162fSJim Ingham                 result.AppendMessageWithFormat("Executable module set to \"%s\".\n",
6195aee162fSJim Ingham                     new_path);
6205aee162fSJim Ingham             }
6215aee162fSJim Ingham             else if (old_exec_module_sp->GetFileSpec() != target->GetExecutableModule()->GetFileSpec())
6225aee162fSJim Ingham             {
6235aee162fSJim Ingham                 char old_path[PATH_MAX + 1];
6245aee162fSJim Ingham                 char new_path[PATH_MAX + 1];
6255aee162fSJim Ingham 
6265aee162fSJim Ingham                 old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX);
6275aee162fSJim Ingham                 target->GetExecutableModule()->GetFileSpec().GetPath (new_path, PATH_MAX);
6285aee162fSJim Ingham 
6295aee162fSJim Ingham                 result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n",
6305aee162fSJim Ingham                                                     old_path, new_path);
6315aee162fSJim Ingham             }
6325aee162fSJim Ingham 
6335aee162fSJim Ingham             if (!old_arch_spec.IsValid())
6345aee162fSJim Ingham             {
6355aee162fSJim Ingham                 result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().AsCString());
6365aee162fSJim Ingham             }
6375aee162fSJim Ingham             else if (old_arch_spec != target->GetArchitecture())
6385aee162fSJim Ingham             {
6395aee162fSJim Ingham                 result.AppendWarningWithFormat("Architecture changed from %s to %s.\n",
6405aee162fSJim Ingham                                                 old_arch_spec.AsCString(), target->GetArchitecture().AsCString());
6415aee162fSJim Ingham             }
6425aee162fSJim Ingham         }
6435aee162fSJim Ingham         return result.Succeeded();
6445aee162fSJim Ingham     }
6455aee162fSJim Ingham 
6465aee162fSJim Ingham     Options *
6475aee162fSJim Ingham     GetOptions ()
6485aee162fSJim Ingham     {
6495aee162fSJim Ingham         return &m_options;
6505aee162fSJim Ingham     }
6515aee162fSJim Ingham 
65230fdc8d8SChris Lattner protected:
65330fdc8d8SChris Lattner 
65430fdc8d8SChris Lattner     CommandOptions m_options;
65530fdc8d8SChris Lattner };
65630fdc8d8SChris Lattner 
65730fdc8d8SChris Lattner 
65830fdc8d8SChris Lattner lldb::OptionDefinition
65930fdc8d8SChris Lattner CommandObjectProcessAttach::CommandOptions::g_option_table[] =
66030fdc8d8SChris Lattner {
661deaab222SCaroline Tice { LLDB_OPT_SET_ALL, false, "plugin", 'P', required_argument, NULL, 0, eArgTypePlugin,        "Name of the process plugin you want to use."},
662deaab222SCaroline Tice { LLDB_OPT_SET_1,   false, "pid",    'p', required_argument, NULL, 0, eArgTypePid,           "The process ID of an existing process to attach to."},
663deaab222SCaroline Tice { LLDB_OPT_SET_2,   false, "name",   'n', required_argument, NULL, 0, eArgTypeProcessName,  "The name of the process to attach to."},
664deaab222SCaroline Tice { LLDB_OPT_SET_2,   false, "waitfor",'w', no_argument,       NULL, 0, eArgTypeNone,              "Wait for the the process with <process-name> to launch."},
665deaab222SCaroline Tice { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
66630fdc8d8SChris Lattner };
66730fdc8d8SChris Lattner 
66830fdc8d8SChris Lattner //-------------------------------------------------------------------------
66930fdc8d8SChris Lattner // CommandObjectProcessContinue
67030fdc8d8SChris Lattner //-------------------------------------------------------------------------
67130fdc8d8SChris Lattner 
67230fdc8d8SChris Lattner class CommandObjectProcessContinue : public CommandObject
67330fdc8d8SChris Lattner {
67430fdc8d8SChris Lattner public:
67530fdc8d8SChris Lattner 
676a7015092SGreg Clayton     CommandObjectProcessContinue (CommandInterpreter &interpreter) :
677a7015092SGreg Clayton         CommandObject (interpreter,
678a7015092SGreg Clayton                        "process continue",
679e3d26315SCaroline Tice                        "Continue execution of all threads in the current process.",
68030fdc8d8SChris Lattner                        "process continue",
68130fdc8d8SChris Lattner                        eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
68230fdc8d8SChris Lattner     {
68330fdc8d8SChris Lattner     }
68430fdc8d8SChris Lattner 
68530fdc8d8SChris Lattner 
68630fdc8d8SChris Lattner     ~CommandObjectProcessContinue ()
68730fdc8d8SChris Lattner     {
68830fdc8d8SChris Lattner     }
68930fdc8d8SChris Lattner 
69030fdc8d8SChris Lattner     bool
691a7015092SGreg Clayton     Execute (Args& command,
69230fdc8d8SChris Lattner              CommandReturnObject &result)
69330fdc8d8SChris Lattner     {
694a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
695a7015092SGreg Clayton         bool synchronous_execution = m_interpreter.GetSynchronous ();
69630fdc8d8SChris Lattner 
69730fdc8d8SChris Lattner         if (process == NULL)
69830fdc8d8SChris Lattner         {
69930fdc8d8SChris Lattner             result.AppendError ("no process to continue");
70030fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
70130fdc8d8SChris Lattner             return false;
70230fdc8d8SChris Lattner          }
70330fdc8d8SChris Lattner 
70430fdc8d8SChris Lattner         StateType state = process->GetState();
70530fdc8d8SChris Lattner         if (state == eStateStopped)
70630fdc8d8SChris Lattner         {
70730fdc8d8SChris Lattner             if (command.GetArgumentCount() != 0)
70830fdc8d8SChris Lattner             {
70930fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str());
71030fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
71130fdc8d8SChris Lattner                 return false;
71230fdc8d8SChris Lattner             }
71330fdc8d8SChris Lattner 
71430fdc8d8SChris Lattner             const uint32_t num_threads = process->GetThreadList().GetSize();
71530fdc8d8SChris Lattner 
71630fdc8d8SChris Lattner             // Set the actions that the threads should each take when resuming
71730fdc8d8SChris Lattner             for (uint32_t idx=0; idx<num_threads; ++idx)
71830fdc8d8SChris Lattner             {
71930fdc8d8SChris Lattner                 process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning);
72030fdc8d8SChris Lattner             }
72130fdc8d8SChris Lattner 
72230fdc8d8SChris Lattner             Error error(process->Resume());
72330fdc8d8SChris Lattner             if (error.Success())
72430fdc8d8SChris Lattner             {
72530fdc8d8SChris Lattner                 result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID());
72630fdc8d8SChris Lattner                 if (synchronous_execution)
72730fdc8d8SChris Lattner                 {
728b132097bSGreg Clayton                     state = process->WaitForProcessToStop (NULL);
72930fdc8d8SChris Lattner 
73030fdc8d8SChris Lattner                     result.SetDidChangeProcessState (true);
73130fdc8d8SChris Lattner                     result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
73230fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
73330fdc8d8SChris Lattner                 }
73430fdc8d8SChris Lattner                 else
73530fdc8d8SChris Lattner                 {
73630fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusSuccessContinuingNoResult);
73730fdc8d8SChris Lattner                 }
73830fdc8d8SChris Lattner             }
73930fdc8d8SChris Lattner             else
74030fdc8d8SChris Lattner             {
74130fdc8d8SChris Lattner                 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
74230fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
74330fdc8d8SChris Lattner             }
74430fdc8d8SChris Lattner         }
74530fdc8d8SChris Lattner         else
74630fdc8d8SChris Lattner         {
74730fdc8d8SChris Lattner             result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
74830fdc8d8SChris Lattner                                          StateAsCString(state));
74930fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
75030fdc8d8SChris Lattner         }
75130fdc8d8SChris Lattner         return result.Succeeded();
75230fdc8d8SChris Lattner     }
75330fdc8d8SChris Lattner };
75430fdc8d8SChris Lattner 
75530fdc8d8SChris Lattner //-------------------------------------------------------------------------
75630fdc8d8SChris Lattner // CommandObjectProcessDetach
75730fdc8d8SChris Lattner //-------------------------------------------------------------------------
75830fdc8d8SChris Lattner 
75930fdc8d8SChris Lattner class CommandObjectProcessDetach : public CommandObject
76030fdc8d8SChris Lattner {
76130fdc8d8SChris Lattner public:
76230fdc8d8SChris Lattner 
763a7015092SGreg Clayton     CommandObjectProcessDetach (CommandInterpreter &interpreter) :
764a7015092SGreg Clayton         CommandObject (interpreter,
765a7015092SGreg Clayton                        "process detach",
766e3d26315SCaroline Tice                        "Detach from the current process being debugged.",
76730fdc8d8SChris Lattner                        "process detach",
76830fdc8d8SChris Lattner                        eFlagProcessMustBeLaunched)
76930fdc8d8SChris Lattner     {
77030fdc8d8SChris Lattner     }
77130fdc8d8SChris Lattner 
77230fdc8d8SChris Lattner     ~CommandObjectProcessDetach ()
77330fdc8d8SChris Lattner     {
77430fdc8d8SChris Lattner     }
77530fdc8d8SChris Lattner 
77630fdc8d8SChris Lattner     bool
777a7015092SGreg Clayton     Execute (Args& command,
77830fdc8d8SChris Lattner              CommandReturnObject &result)
77930fdc8d8SChris Lattner     {
780a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
78130fdc8d8SChris Lattner         if (process == NULL)
78230fdc8d8SChris Lattner         {
78330fdc8d8SChris Lattner             result.AppendError ("must have a valid process in order to detach");
78430fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
78530fdc8d8SChris Lattner             return false;
78630fdc8d8SChris Lattner         }
78730fdc8d8SChris Lattner 
78830fdc8d8SChris Lattner         Error error (process->Detach());
78930fdc8d8SChris Lattner         if (error.Success())
79030fdc8d8SChris Lattner         {
79130fdc8d8SChris Lattner             result.SetStatus (eReturnStatusSuccessFinishResult);
79230fdc8d8SChris Lattner         }
79330fdc8d8SChris Lattner         else
79430fdc8d8SChris Lattner         {
79530fdc8d8SChris Lattner             result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString());
79630fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
79730fdc8d8SChris Lattner             return false;
79830fdc8d8SChris Lattner         }
79930fdc8d8SChris Lattner         return result.Succeeded();
80030fdc8d8SChris Lattner     }
80130fdc8d8SChris Lattner };
80230fdc8d8SChris Lattner 
80330fdc8d8SChris Lattner //-------------------------------------------------------------------------
80430fdc8d8SChris Lattner // CommandObjectProcessSignal
80530fdc8d8SChris Lattner //-------------------------------------------------------------------------
80630fdc8d8SChris Lattner 
80730fdc8d8SChris Lattner class CommandObjectProcessSignal : public CommandObject
80830fdc8d8SChris Lattner {
80930fdc8d8SChris Lattner public:
81030fdc8d8SChris Lattner 
811a7015092SGreg Clayton     CommandObjectProcessSignal (CommandInterpreter &interpreter) :
812a7015092SGreg Clayton         CommandObject (interpreter,
813a7015092SGreg Clayton                        "process signal",
814e3d26315SCaroline Tice                        "Send a UNIX signal to the current process being debugged.",
815405fe67fSCaroline Tice                        NULL)
81630fdc8d8SChris Lattner     {
817405fe67fSCaroline Tice         CommandArgumentEntry arg;
818405fe67fSCaroline Tice         CommandArgumentData signal_arg;
819405fe67fSCaroline Tice 
820405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
821405fe67fSCaroline Tice         signal_arg.arg_type = eArgTypeUnixSignalNumber;
822405fe67fSCaroline Tice         signal_arg.arg_repetition = eArgRepeatPlain;
823405fe67fSCaroline Tice 
824405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
825405fe67fSCaroline Tice         arg.push_back (signal_arg);
826405fe67fSCaroline Tice 
827405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
828405fe67fSCaroline Tice         m_arguments.push_back (arg);
82930fdc8d8SChris Lattner     }
83030fdc8d8SChris Lattner 
83130fdc8d8SChris Lattner     ~CommandObjectProcessSignal ()
83230fdc8d8SChris Lattner     {
83330fdc8d8SChris Lattner     }
83430fdc8d8SChris Lattner 
83530fdc8d8SChris Lattner     bool
836a7015092SGreg Clayton     Execute (Args& command,
83730fdc8d8SChris Lattner              CommandReturnObject &result)
83830fdc8d8SChris Lattner     {
839a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
84030fdc8d8SChris Lattner         if (process == NULL)
84130fdc8d8SChris Lattner         {
84230fdc8d8SChris Lattner             result.AppendError ("no process to signal");
84330fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
84430fdc8d8SChris Lattner             return false;
84530fdc8d8SChris Lattner         }
84630fdc8d8SChris Lattner 
84730fdc8d8SChris Lattner         if (command.GetArgumentCount() == 1)
84830fdc8d8SChris Lattner         {
849237cd906SGreg Clayton             int signo = LLDB_INVALID_SIGNAL_NUMBER;
850237cd906SGreg Clayton 
851237cd906SGreg Clayton             const char *signal_name = command.GetArgumentAtIndex(0);
852237cd906SGreg Clayton             if (::isxdigit (signal_name[0]))
853237cd906SGreg Clayton                 signo = Args::StringToSInt32(signal_name, LLDB_INVALID_SIGNAL_NUMBER, 0);
854237cd906SGreg Clayton             else
855237cd906SGreg Clayton                 signo = process->GetUnixSignals().GetSignalNumberFromName (signal_name);
856237cd906SGreg Clayton 
857237cd906SGreg Clayton             if (signo == LLDB_INVALID_SIGNAL_NUMBER)
85830fdc8d8SChris Lattner             {
85930fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0));
86030fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
86130fdc8d8SChris Lattner             }
86230fdc8d8SChris Lattner             else
86330fdc8d8SChris Lattner             {
86430fdc8d8SChris Lattner                 Error error (process->Signal (signo));
86530fdc8d8SChris Lattner                 if (error.Success())
86630fdc8d8SChris Lattner                 {
86730fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusSuccessFinishResult);
86830fdc8d8SChris Lattner                 }
86930fdc8d8SChris Lattner                 else
87030fdc8d8SChris Lattner                 {
87130fdc8d8SChris Lattner                     result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString());
87230fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusFailed);
87330fdc8d8SChris Lattner                 }
87430fdc8d8SChris Lattner             }
87530fdc8d8SChris Lattner         }
87630fdc8d8SChris Lattner         else
87730fdc8d8SChris Lattner         {
87830fdc8d8SChris Lattner             result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: \n", m_cmd_name.c_str(),
87930fdc8d8SChris Lattner                                         m_cmd_syntax.c_str());
88030fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
88130fdc8d8SChris Lattner         }
88230fdc8d8SChris Lattner         return result.Succeeded();
88330fdc8d8SChris Lattner     }
88430fdc8d8SChris Lattner };
88530fdc8d8SChris Lattner 
88630fdc8d8SChris Lattner 
88730fdc8d8SChris Lattner //-------------------------------------------------------------------------
88830fdc8d8SChris Lattner // CommandObjectProcessInterrupt
88930fdc8d8SChris Lattner //-------------------------------------------------------------------------
89030fdc8d8SChris Lattner 
89130fdc8d8SChris Lattner class CommandObjectProcessInterrupt : public CommandObject
89230fdc8d8SChris Lattner {
89330fdc8d8SChris Lattner public:
89430fdc8d8SChris Lattner 
89530fdc8d8SChris Lattner 
896a7015092SGreg Clayton     CommandObjectProcessInterrupt (CommandInterpreter &interpreter) :
897a7015092SGreg Clayton     CommandObject (interpreter,
898a7015092SGreg Clayton                    "process interrupt",
899e3d26315SCaroline Tice                    "Interrupt the current process being debugged.",
90030fdc8d8SChris Lattner                    "process interrupt",
90130fdc8d8SChris Lattner                    eFlagProcessMustBeLaunched)
90230fdc8d8SChris Lattner     {
90330fdc8d8SChris Lattner     }
90430fdc8d8SChris Lattner 
90530fdc8d8SChris Lattner     ~CommandObjectProcessInterrupt ()
90630fdc8d8SChris Lattner     {
90730fdc8d8SChris Lattner     }
90830fdc8d8SChris Lattner 
90930fdc8d8SChris Lattner     bool
910a7015092SGreg Clayton     Execute (Args& command,
91130fdc8d8SChris Lattner              CommandReturnObject &result)
91230fdc8d8SChris Lattner     {
913a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
91430fdc8d8SChris Lattner         if (process == NULL)
91530fdc8d8SChris Lattner         {
91630fdc8d8SChris Lattner             result.AppendError ("no process to halt");
91730fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
91830fdc8d8SChris Lattner             return false;
91930fdc8d8SChris Lattner         }
92030fdc8d8SChris Lattner 
92130fdc8d8SChris Lattner         if (command.GetArgumentCount() == 0)
92230fdc8d8SChris Lattner         {
92330fdc8d8SChris Lattner             Error error(process->Halt ());
92430fdc8d8SChris Lattner             if (error.Success())
92530fdc8d8SChris Lattner             {
92630fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusSuccessFinishResult);
92730fdc8d8SChris Lattner 
92830fdc8d8SChris Lattner                 // Maybe we should add a "SuspendThreadPlans so we
92930fdc8d8SChris Lattner                 // can halt, and keep in place all the current thread plans.
93030fdc8d8SChris Lattner                 process->GetThreadList().DiscardThreadPlans();
93130fdc8d8SChris Lattner             }
93230fdc8d8SChris Lattner             else
93330fdc8d8SChris Lattner             {
93430fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString());
93530fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
93630fdc8d8SChris Lattner             }
93730fdc8d8SChris Lattner         }
93830fdc8d8SChris Lattner         else
93930fdc8d8SChris Lattner         {
94030fdc8d8SChris Lattner             result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
94130fdc8d8SChris Lattner                                         m_cmd_name.c_str(),
94230fdc8d8SChris Lattner                                         m_cmd_syntax.c_str());
94330fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
94430fdc8d8SChris Lattner         }
94530fdc8d8SChris Lattner         return result.Succeeded();
94630fdc8d8SChris Lattner     }
94730fdc8d8SChris Lattner };
94830fdc8d8SChris Lattner 
94930fdc8d8SChris Lattner //-------------------------------------------------------------------------
95030fdc8d8SChris Lattner // CommandObjectProcessKill
95130fdc8d8SChris Lattner //-------------------------------------------------------------------------
95230fdc8d8SChris Lattner 
95330fdc8d8SChris Lattner class CommandObjectProcessKill : public CommandObject
95430fdc8d8SChris Lattner {
95530fdc8d8SChris Lattner public:
95630fdc8d8SChris Lattner 
957a7015092SGreg Clayton     CommandObjectProcessKill (CommandInterpreter &interpreter) :
958a7015092SGreg Clayton     CommandObject (interpreter,
959a7015092SGreg Clayton                    "process kill",
960e3d26315SCaroline Tice                    "Terminate the current process being debugged.",
96130fdc8d8SChris Lattner                    "process kill",
96230fdc8d8SChris Lattner                    eFlagProcessMustBeLaunched)
96330fdc8d8SChris Lattner     {
96430fdc8d8SChris Lattner     }
96530fdc8d8SChris Lattner 
96630fdc8d8SChris Lattner     ~CommandObjectProcessKill ()
96730fdc8d8SChris Lattner     {
96830fdc8d8SChris Lattner     }
96930fdc8d8SChris Lattner 
97030fdc8d8SChris Lattner     bool
971a7015092SGreg Clayton     Execute (Args& command,
97230fdc8d8SChris Lattner              CommandReturnObject &result)
97330fdc8d8SChris Lattner     {
974a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
97530fdc8d8SChris Lattner         if (process == NULL)
97630fdc8d8SChris Lattner         {
97730fdc8d8SChris Lattner             result.AppendError ("no process to kill");
97830fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
97930fdc8d8SChris Lattner             return false;
98030fdc8d8SChris Lattner         }
98130fdc8d8SChris Lattner 
98230fdc8d8SChris Lattner         if (command.GetArgumentCount() == 0)
98330fdc8d8SChris Lattner         {
98430fdc8d8SChris Lattner             Error error (process->Destroy());
98530fdc8d8SChris Lattner             if (error.Success())
98630fdc8d8SChris Lattner             {
98730fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusSuccessFinishResult);
98830fdc8d8SChris Lattner             }
98930fdc8d8SChris Lattner             else
99030fdc8d8SChris Lattner             {
99130fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString());
99230fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
99330fdc8d8SChris Lattner             }
99430fdc8d8SChris Lattner         }
99530fdc8d8SChris Lattner         else
99630fdc8d8SChris Lattner         {
99730fdc8d8SChris Lattner             result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
99830fdc8d8SChris Lattner                                         m_cmd_name.c_str(),
99930fdc8d8SChris Lattner                                         m_cmd_syntax.c_str());
100030fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
100130fdc8d8SChris Lattner         }
100230fdc8d8SChris Lattner         return result.Succeeded();
100330fdc8d8SChris Lattner     }
100430fdc8d8SChris Lattner };
100530fdc8d8SChris Lattner 
100630fdc8d8SChris Lattner //-------------------------------------------------------------------------
10074b9bea87SJim Ingham // CommandObjectProcessStatus
10084b9bea87SJim Ingham //-------------------------------------------------------------------------
10094b9bea87SJim Ingham class CommandObjectProcessStatus : public CommandObject
10104b9bea87SJim Ingham {
10114b9bea87SJim Ingham public:
1012a7015092SGreg Clayton     CommandObjectProcessStatus (CommandInterpreter &interpreter) :
1013a7015092SGreg Clayton     CommandObject (interpreter,
1014a7015092SGreg Clayton                    "process status",
1015e3d26315SCaroline Tice                    "Show the current status and location of executing process.",
1016e3d26315SCaroline Tice                    "process status",
10174b9bea87SJim Ingham                    0)
10184b9bea87SJim Ingham     {
10194b9bea87SJim Ingham     }
10204b9bea87SJim Ingham 
10214b9bea87SJim Ingham     ~CommandObjectProcessStatus()
10224b9bea87SJim Ingham     {
10234b9bea87SJim Ingham     }
10244b9bea87SJim Ingham 
10254b9bea87SJim Ingham 
10264b9bea87SJim Ingham     bool
10274b9bea87SJim Ingham     Execute
10284b9bea87SJim Ingham     (
10294b9bea87SJim Ingham         Args& command,
10304b9bea87SJim Ingham         CommandReturnObject &result
10314b9bea87SJim Ingham     )
10324b9bea87SJim Ingham     {
10334b9bea87SJim Ingham         StreamString &output_stream = result.GetOutputStream();
10344b9bea87SJim Ingham         result.SetStatus (eReturnStatusSuccessFinishNoResult);
1035a7015092SGreg Clayton         ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
10364b9bea87SJim Ingham         if (exe_ctx.process)
10374b9bea87SJim Ingham         {
10384b9bea87SJim Ingham             const StateType state = exe_ctx.process->GetState();
10394b9bea87SJim Ingham             if (StateIsStoppedState(state))
10404b9bea87SJim Ingham             {
10414b9bea87SJim Ingham                 if (state == eStateExited)
10424b9bea87SJim Ingham                 {
10434b9bea87SJim Ingham                     int exit_status = exe_ctx.process->GetExitStatus();
10444b9bea87SJim Ingham                     const char *exit_description = exe_ctx.process->GetExitDescription();
10454b9bea87SJim Ingham                     output_stream.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n",
10464b9bea87SJim Ingham                                           exe_ctx.process->GetID(),
10474b9bea87SJim Ingham                                           exit_status,
10484b9bea87SJim Ingham                                           exit_status,
10494b9bea87SJim Ingham                                           exit_description ? exit_description : "");
10504b9bea87SJim Ingham                 }
10514b9bea87SJim Ingham                 else
10524b9bea87SJim Ingham                 {
10534b9bea87SJim Ingham                     output_stream.Printf ("Process %d %s\n", exe_ctx.process->GetID(), StateAsCString (state));
10544b9bea87SJim Ingham                     if (exe_ctx.thread == NULL)
10554b9bea87SJim Ingham                         exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
10564b9bea87SJim Ingham                     if (exe_ctx.thread != NULL)
10574b9bea87SJim Ingham                     {
1058a7015092SGreg Clayton                         DisplayThreadsInfo (m_interpreter, &exe_ctx, result, true, true);
10594b9bea87SJim Ingham                     }
10604b9bea87SJim Ingham                     else
10614b9bea87SJim Ingham                     {
10624b9bea87SJim Ingham                         result.AppendError ("No valid thread found in current process.");
10634b9bea87SJim Ingham                         result.SetStatus (eReturnStatusFailed);
10644b9bea87SJim Ingham                     }
10654b9bea87SJim Ingham                 }
10664b9bea87SJim Ingham             }
10674b9bea87SJim Ingham             else
10684b9bea87SJim Ingham             {
10694b9bea87SJim Ingham                 output_stream.Printf ("Process %d is running.\n",
10704b9bea87SJim Ingham                                           exe_ctx.process->GetID());
10714b9bea87SJim Ingham             }
10724b9bea87SJim Ingham         }
10734b9bea87SJim Ingham         else
10744b9bea87SJim Ingham         {
10754b9bea87SJim Ingham             result.AppendError ("No current location or status available.");
10764b9bea87SJim Ingham             result.SetStatus (eReturnStatusFailed);
10774b9bea87SJim Ingham         }
10784b9bea87SJim Ingham         return result.Succeeded();
10794b9bea87SJim Ingham     }
10804b9bea87SJim Ingham };
10814b9bea87SJim Ingham 
10824b9bea87SJim Ingham //-------------------------------------------------------------------------
108335731357SCaroline Tice // CommandObjectProcessHandle
108435731357SCaroline Tice //-------------------------------------------------------------------------
108535731357SCaroline Tice 
108635731357SCaroline Tice class CommandObjectProcessHandle : public CommandObject
108735731357SCaroline Tice {
108835731357SCaroline Tice public:
108935731357SCaroline Tice 
109035731357SCaroline Tice     class CommandOptions : public Options
109135731357SCaroline Tice     {
109235731357SCaroline Tice     public:
109335731357SCaroline Tice 
109435731357SCaroline Tice         CommandOptions () :
109535731357SCaroline Tice             Options ()
109635731357SCaroline Tice         {
109735731357SCaroline Tice             ResetOptionValues ();
109835731357SCaroline Tice         }
109935731357SCaroline Tice 
110035731357SCaroline Tice         ~CommandOptions ()
110135731357SCaroline Tice         {
110235731357SCaroline Tice         }
110335731357SCaroline Tice 
110435731357SCaroline Tice         Error
110535731357SCaroline Tice         SetOptionValue (int option_idx, const char *option_arg)
110635731357SCaroline Tice         {
110735731357SCaroline Tice             Error error;
110835731357SCaroline Tice             char short_option = (char) m_getopt_table[option_idx].val;
110935731357SCaroline Tice 
111035731357SCaroline Tice             switch (short_option)
111135731357SCaroline Tice             {
111235731357SCaroline Tice                 case 's':
111335731357SCaroline Tice                     stop = option_arg;
111435731357SCaroline Tice                     break;
111535731357SCaroline Tice                 case 'n':
111635731357SCaroline Tice                     notify = option_arg;
111735731357SCaroline Tice                     break;
111835731357SCaroline Tice                 case 'p':
111935731357SCaroline Tice                     pass = option_arg;
112035731357SCaroline Tice                     break;
112135731357SCaroline Tice                 default:
112235731357SCaroline Tice                     error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
112335731357SCaroline Tice                     break;
112435731357SCaroline Tice             }
112535731357SCaroline Tice             return error;
112635731357SCaroline Tice         }
112735731357SCaroline Tice 
112835731357SCaroline Tice         void
112935731357SCaroline Tice         ResetOptionValues ()
113035731357SCaroline Tice         {
113135731357SCaroline Tice             Options::ResetOptionValues();
113235731357SCaroline Tice             stop.clear();
113335731357SCaroline Tice             notify.clear();
113435731357SCaroline Tice             pass.clear();
113535731357SCaroline Tice         }
113635731357SCaroline Tice 
113735731357SCaroline Tice         const lldb::OptionDefinition*
113835731357SCaroline Tice         GetDefinitions ()
113935731357SCaroline Tice         {
114035731357SCaroline Tice             return g_option_table;
114135731357SCaroline Tice         }
114235731357SCaroline Tice 
114335731357SCaroline Tice         // Options table: Required for subclasses of Options.
114435731357SCaroline Tice 
114535731357SCaroline Tice         static lldb::OptionDefinition g_option_table[];
114635731357SCaroline Tice 
114735731357SCaroline Tice         // Instance variables to hold the values for command options.
114835731357SCaroline Tice 
114935731357SCaroline Tice         std::string stop;
115035731357SCaroline Tice         std::string notify;
115135731357SCaroline Tice         std::string pass;
115235731357SCaroline Tice     };
115335731357SCaroline Tice 
115435731357SCaroline Tice 
115535731357SCaroline Tice     CommandObjectProcessHandle (CommandInterpreter &interpreter) :
115635731357SCaroline Tice         CommandObject (interpreter,
115735731357SCaroline Tice                        "process handle",
115810ad7993SCaroline Tice                        "Show or update what the process and debugger should do with various signals received from the OS.",
115935731357SCaroline Tice                        NULL)
116035731357SCaroline Tice     {
116110ad7993SCaroline Tice         SetHelpLong ("If no signals are specified, update them all.  If no update option is specified, list the current values.\n");
116235731357SCaroline Tice         CommandArgumentEntry arg;
116335731357SCaroline Tice         CommandArgumentData signal_name_arg;
116435731357SCaroline Tice 
116535731357SCaroline Tice         signal_name_arg.arg_type = eArgTypeSignalName;
116610ad7993SCaroline Tice         signal_name_arg.arg_repetition = eArgRepeatStar;
116735731357SCaroline Tice 
116835731357SCaroline Tice         arg.push_back (signal_name_arg);
116935731357SCaroline Tice 
117035731357SCaroline Tice         m_arguments.push_back (arg);
117135731357SCaroline Tice     }
117235731357SCaroline Tice 
117335731357SCaroline Tice     ~CommandObjectProcessHandle ()
117435731357SCaroline Tice     {
117535731357SCaroline Tice     }
117635731357SCaroline Tice 
117735731357SCaroline Tice     Options *
117835731357SCaroline Tice     GetOptions ()
117935731357SCaroline Tice     {
118035731357SCaroline Tice         return &m_options;
118135731357SCaroline Tice     }
118235731357SCaroline Tice 
118335731357SCaroline Tice     bool
118410ad7993SCaroline Tice     VerifyCommandOptionValue (const std::string &option, int &real_value)
118535731357SCaroline Tice     {
118635731357SCaroline Tice         bool okay = true;
118735731357SCaroline Tice 
118810ad7993SCaroline Tice         bool success = false;
118910ad7993SCaroline Tice         bool tmp_value = Args::StringToBoolean (option.c_str(), false, &success);
119010ad7993SCaroline Tice 
119110ad7993SCaroline Tice         if (success && tmp_value)
119210ad7993SCaroline Tice             real_value = 1;
119310ad7993SCaroline Tice         else if (success && !tmp_value)
119410ad7993SCaroline Tice             real_value = 0;
119535731357SCaroline Tice         else
119635731357SCaroline Tice         {
119735731357SCaroline Tice             // If the value isn't 'true' or 'false', it had better be 0 or 1.
119810ad7993SCaroline Tice             real_value = Args::StringToUInt32 (option.c_str(), 3);
119910ad7993SCaroline Tice             if (real_value != 0 && real_value != 1)
120035731357SCaroline Tice                 okay = false;
120135731357SCaroline Tice         }
120235731357SCaroline Tice 
120335731357SCaroline Tice         return okay;
120435731357SCaroline Tice     }
120535731357SCaroline Tice 
120610ad7993SCaroline Tice     void
120710ad7993SCaroline Tice     PrintSignalHeader (Stream &str)
120810ad7993SCaroline Tice     {
120910ad7993SCaroline Tice         str.Printf ("NAME        PASS   STOP   NOTIFY\n");
121010ad7993SCaroline Tice         str.Printf ("==========  =====  =====  ======\n");
121110ad7993SCaroline Tice     }
121210ad7993SCaroline Tice 
121310ad7993SCaroline Tice     void
121410ad7993SCaroline Tice     PrintSignal (Stream &str, int32_t signo, const char *sig_name, UnixSignals &signals)
121510ad7993SCaroline Tice     {
121610ad7993SCaroline Tice         bool stop;
121710ad7993SCaroline Tice         bool suppress;
121810ad7993SCaroline Tice         bool notify;
121910ad7993SCaroline Tice 
122010ad7993SCaroline Tice         str.Printf ("%-10s  ", sig_name);
122110ad7993SCaroline Tice         if (signals.GetSignalInfo (signo, suppress, stop, notify))
122210ad7993SCaroline Tice         {
122310ad7993SCaroline Tice             bool pass = !suppress;
122410ad7993SCaroline Tice             str.Printf ("%s  %s  %s",
122510ad7993SCaroline Tice                         (pass ? "true " : "false"),
122610ad7993SCaroline Tice                         (stop ? "true " : "false"),
122710ad7993SCaroline Tice                         (notify ? "true " : "false"));
122810ad7993SCaroline Tice         }
122910ad7993SCaroline Tice         str.Printf ("\n");
123010ad7993SCaroline Tice     }
123110ad7993SCaroline Tice 
123210ad7993SCaroline Tice     void
123310ad7993SCaroline Tice     PrintSignalInformation (Stream &str, Args &signal_args, int num_valid_signals, UnixSignals &signals)
123410ad7993SCaroline Tice     {
123510ad7993SCaroline Tice         PrintSignalHeader (str);
123610ad7993SCaroline Tice 
123710ad7993SCaroline Tice         if (num_valid_signals > 0)
123810ad7993SCaroline Tice         {
123910ad7993SCaroline Tice             size_t num_args = signal_args.GetArgumentCount();
124010ad7993SCaroline Tice             for (size_t i = 0; i < num_args; ++i)
124110ad7993SCaroline Tice             {
124210ad7993SCaroline Tice                 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
124310ad7993SCaroline Tice                 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
124410ad7993SCaroline Tice                     PrintSignal (str, signo, signal_args.GetArgumentAtIndex (i), signals);
124510ad7993SCaroline Tice             }
124610ad7993SCaroline Tice         }
124710ad7993SCaroline Tice         else // Print info for ALL signals
124810ad7993SCaroline Tice         {
124910ad7993SCaroline Tice             int32_t signo = signals.GetFirstSignalNumber();
125010ad7993SCaroline Tice             while (signo != LLDB_INVALID_SIGNAL_NUMBER)
125110ad7993SCaroline Tice             {
125210ad7993SCaroline Tice                 PrintSignal (str, signo, signals.GetSignalAsCString (signo), signals);
125310ad7993SCaroline Tice                 signo = signals.GetNextSignalNumber (signo);
125410ad7993SCaroline Tice             }
125510ad7993SCaroline Tice         }
125610ad7993SCaroline Tice     }
125710ad7993SCaroline Tice 
125835731357SCaroline Tice     bool
125935731357SCaroline Tice     Execute (Args &signal_args, CommandReturnObject &result)
126035731357SCaroline Tice     {
126135731357SCaroline Tice         TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
126235731357SCaroline Tice 
126335731357SCaroline Tice         if (!target_sp)
126435731357SCaroline Tice         {
126535731357SCaroline Tice             result.AppendError ("No current target;"
126635731357SCaroline Tice                                 " cannot handle signals until you have a valid target and process.\n");
126735731357SCaroline Tice             result.SetStatus (eReturnStatusFailed);
126835731357SCaroline Tice             return false;
126935731357SCaroline Tice         }
127035731357SCaroline Tice 
127135731357SCaroline Tice         ProcessSP process_sp = target_sp->GetProcessSP();
127235731357SCaroline Tice 
127335731357SCaroline Tice         if (!process_sp)
127435731357SCaroline Tice         {
127535731357SCaroline Tice             result.AppendError ("No current process; cannot handle signals until you have a valid process.\n");
127635731357SCaroline Tice             result.SetStatus (eReturnStatusFailed);
127735731357SCaroline Tice             return false;
127835731357SCaroline Tice         }
127935731357SCaroline Tice 
128035731357SCaroline Tice         int stop_action = -1;   // -1 means leave the current setting alone
128135731357SCaroline Tice         int pass_action = -1;   // -1 means leave the current setting alone
128235731357SCaroline Tice         int notify_action = -1; // -1 means leave the current setting alone
128335731357SCaroline Tice 
128435731357SCaroline Tice         if (! m_options.stop.empty()
128510ad7993SCaroline Tice             && ! VerifyCommandOptionValue (m_options.stop, stop_action))
128635731357SCaroline Tice         {
128735731357SCaroline Tice             result.AppendError ("Invalid argument for command option --stop; must be true or false.\n");
128835731357SCaroline Tice             result.SetStatus (eReturnStatusFailed);
128935731357SCaroline Tice             return false;
129035731357SCaroline Tice         }
129135731357SCaroline Tice 
129235731357SCaroline Tice         if (! m_options.notify.empty()
129310ad7993SCaroline Tice             && ! VerifyCommandOptionValue (m_options.notify, notify_action))
129435731357SCaroline Tice         {
129535731357SCaroline Tice             result.AppendError ("Invalid argument for command option --notify; must be true or false.\n");
129635731357SCaroline Tice             result.SetStatus (eReturnStatusFailed);
129735731357SCaroline Tice             return false;
129835731357SCaroline Tice         }
129935731357SCaroline Tice 
130035731357SCaroline Tice         if (! m_options.pass.empty()
130110ad7993SCaroline Tice             && ! VerifyCommandOptionValue (m_options.pass, pass_action))
130235731357SCaroline Tice         {
130335731357SCaroline Tice             result.AppendError ("Invalid argument for command option --pass; must be true or false.\n");
130435731357SCaroline Tice             result.SetStatus (eReturnStatusFailed);
130535731357SCaroline Tice             return false;
130635731357SCaroline Tice         }
130735731357SCaroline Tice 
130835731357SCaroline Tice         size_t num_args = signal_args.GetArgumentCount();
130935731357SCaroline Tice         UnixSignals &signals = process_sp->GetUnixSignals();
131035731357SCaroline Tice         int num_signals_set = 0;
131135731357SCaroline Tice 
131210ad7993SCaroline Tice         if (num_args > 0)
131310ad7993SCaroline Tice         {
131435731357SCaroline Tice             for (size_t i = 0; i < num_args; ++i)
131535731357SCaroline Tice             {
131635731357SCaroline Tice                 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
131735731357SCaroline Tice                 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
131835731357SCaroline Tice                 {
131910ad7993SCaroline Tice                     // Casting the actions as bools here should be okay, because VerifyCommandOptionValue guarantees
132035731357SCaroline Tice                     // the value is either 0 or 1.
132135731357SCaroline Tice                     if (stop_action != -1)
132235731357SCaroline Tice                         signals.SetShouldStop (signo, (bool) stop_action);
132335731357SCaroline Tice                     if (pass_action != -1)
132435731357SCaroline Tice                     {
132510ad7993SCaroline Tice                         bool suppress = ! ((bool) pass_action);
132610ad7993SCaroline Tice                         signals.SetShouldSuppress (signo, suppress);
132735731357SCaroline Tice                     }
132835731357SCaroline Tice                     if (notify_action != -1)
132935731357SCaroline Tice                         signals.SetShouldNotify (signo, (bool) notify_action);
133035731357SCaroline Tice                     ++num_signals_set;
133135731357SCaroline Tice                 }
133235731357SCaroline Tice                 else
133335731357SCaroline Tice                 {
133435731357SCaroline Tice                     result.AppendErrorWithFormat ("Invalid signal name '%s'\n", signal_args.GetArgumentAtIndex (i));
133535731357SCaroline Tice                 }
133635731357SCaroline Tice             }
133710ad7993SCaroline Tice         }
133810ad7993SCaroline Tice         else
133910ad7993SCaroline Tice         {
134010ad7993SCaroline Tice             // No signal specified, if any command options were specified, update ALL signals.
134110ad7993SCaroline Tice             if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1))
134210ad7993SCaroline Tice             {
134310ad7993SCaroline Tice                 if (m_interpreter.Confirm ("Do you really want to update all the signals?", false))
134410ad7993SCaroline Tice                 {
134510ad7993SCaroline Tice                     int32_t signo = signals.GetFirstSignalNumber();
134610ad7993SCaroline Tice                     while (signo != LLDB_INVALID_SIGNAL_NUMBER)
134710ad7993SCaroline Tice                     {
134810ad7993SCaroline Tice                         if (notify_action != -1)
134910ad7993SCaroline Tice                             signals.SetShouldNotify (signo, (bool) notify_action);
135010ad7993SCaroline Tice                         if (stop_action != -1)
135110ad7993SCaroline Tice                             signals.SetShouldStop (signo, (bool) stop_action);
135210ad7993SCaroline Tice                         if (pass_action != -1)
135310ad7993SCaroline Tice                         {
135410ad7993SCaroline Tice                             bool suppress = ! ((bool) pass_action);
135510ad7993SCaroline Tice                             signals.SetShouldSuppress (signo, suppress);
135610ad7993SCaroline Tice                         }
135710ad7993SCaroline Tice                         signo = signals.GetNextSignalNumber (signo);
135810ad7993SCaroline Tice                     }
135910ad7993SCaroline Tice                 }
136010ad7993SCaroline Tice             }
136110ad7993SCaroline Tice         }
136210ad7993SCaroline Tice 
136310ad7993SCaroline Tice         PrintSignalInformation (result.GetOutputStream(), signal_args, num_signals_set, signals);
136435731357SCaroline Tice 
136535731357SCaroline Tice         if (num_signals_set > 0)
136635731357SCaroline Tice             result.SetStatus (eReturnStatusSuccessFinishNoResult);
136735731357SCaroline Tice         else
136835731357SCaroline Tice             result.SetStatus (eReturnStatusFailed);
136935731357SCaroline Tice 
137035731357SCaroline Tice         return result.Succeeded();
137135731357SCaroline Tice     }
137235731357SCaroline Tice 
137335731357SCaroline Tice protected:
137435731357SCaroline Tice 
137535731357SCaroline Tice     CommandOptions m_options;
137635731357SCaroline Tice };
137735731357SCaroline Tice 
137835731357SCaroline Tice lldb::OptionDefinition
137935731357SCaroline Tice CommandObjectProcessHandle::CommandOptions::g_option_table[] =
138035731357SCaroline Tice {
138135731357SCaroline 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." },
138235731357SCaroline 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." },
138335731357SCaroline Tice { LLDB_OPT_SET_1, false, "pass",  'p', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." },
138435731357SCaroline Tice { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
138535731357SCaroline Tice };
138635731357SCaroline Tice 
138735731357SCaroline Tice //-------------------------------------------------------------------------
138830fdc8d8SChris Lattner // CommandObjectMultiwordProcess
138930fdc8d8SChris Lattner //-------------------------------------------------------------------------
139030fdc8d8SChris Lattner 
13916611103cSGreg Clayton CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter &interpreter) :
1392a7015092SGreg Clayton     CommandObjectMultiword (interpreter,
1393a7015092SGreg Clayton                             "process",
139430fdc8d8SChris Lattner                             "A set of commands for operating on a process.",
139530fdc8d8SChris Lattner                             "process <subcommand> [<subcommand-options>]")
139630fdc8d8SChris Lattner {
1397a7015092SGreg Clayton     LoadSubCommand ("attach",      CommandObjectSP (new CommandObjectProcessAttach (interpreter)));
1398a7015092SGreg Clayton     LoadSubCommand ("launch",      CommandObjectSP (new CommandObjectProcessLaunch (interpreter)));
1399a7015092SGreg Clayton     LoadSubCommand ("continue",    CommandObjectSP (new CommandObjectProcessContinue (interpreter)));
1400a7015092SGreg Clayton     LoadSubCommand ("detach",      CommandObjectSP (new CommandObjectProcessDetach (interpreter)));
1401a7015092SGreg Clayton     LoadSubCommand ("signal",      CommandObjectSP (new CommandObjectProcessSignal (interpreter)));
140235731357SCaroline Tice     LoadSubCommand ("handle",      CommandObjectSP (new CommandObjectProcessHandle (interpreter)));
1403a7015092SGreg Clayton     LoadSubCommand ("status",      CommandObjectSP (new CommandObjectProcessStatus (interpreter)));
1404a7015092SGreg Clayton     LoadSubCommand ("interrupt",   CommandObjectSP (new CommandObjectProcessInterrupt (interpreter)));
1405a7015092SGreg Clayton     LoadSubCommand ("kill",        CommandObjectSP (new CommandObjectProcessKill (interpreter)));
140630fdc8d8SChris Lattner }
140730fdc8d8SChris Lattner 
140830fdc8d8SChris Lattner CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess ()
140930fdc8d8SChris Lattner {
141030fdc8d8SChris Lattner }
141130fdc8d8SChris Lattner 
1412