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 //-------------------------------------------------------------------------
32bb9caf73SJim Ingham #pragma mark CommandObjectProjectLaunch
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;
61bd82a5d2SGreg Clayton                 case 'e':   stderr_path.assign (option_arg);    break;
62bd82a5d2SGreg Clayton                 case 'i':   stdin_path.assign (option_arg);     break;
63bd82a5d2SGreg Clayton                 case 'o':   stdout_path.assign (option_arg);    break;
64bd82a5d2SGreg Clayton                 case 'p':   plugin_name.assign (option_arg);    break;
65f8da8631SCaroline Tice                 case 'n':   no_stdio = true;                    break;
66bd82a5d2SGreg Clayton                 case 'w':   working_dir.assign (option_arg);    break;
67913c4fa1SGreg Clayton                 case 't':
68913c4fa1SGreg Clayton                     if (option_arg && option_arg[0])
69913c4fa1SGreg Clayton                         tty_name.assign (option_arg);
70913c4fa1SGreg Clayton                     in_new_tty = true;
71913c4fa1SGreg Clayton                     break;
7230fdc8d8SChris Lattner                 default:
7330fdc8d8SChris Lattner                     error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
7430fdc8d8SChris Lattner                     break;
7530fdc8d8SChris Lattner 
7630fdc8d8SChris Lattner             }
7730fdc8d8SChris Lattner             return error;
7830fdc8d8SChris Lattner         }
7930fdc8d8SChris Lattner 
8030fdc8d8SChris Lattner         void
8130fdc8d8SChris Lattner         ResetOptionValues ()
8230fdc8d8SChris Lattner         {
8330fdc8d8SChris Lattner             Options::ResetOptionValues();
8430fdc8d8SChris Lattner             stop_at_entry = false;
8519388cfcSGreg Clayton             in_new_tty = false;
86913c4fa1SGreg Clayton             tty_name.clear();
8730fdc8d8SChris Lattner             stdin_path.clear();
8830fdc8d8SChris Lattner             stdout_path.clear();
8930fdc8d8SChris Lattner             stderr_path.clear();
9030fdc8d8SChris Lattner             plugin_name.clear();
91bd82a5d2SGreg Clayton             working_dir.clear();
92f8da8631SCaroline Tice             no_stdio = false;
9330fdc8d8SChris Lattner         }
9430fdc8d8SChris Lattner 
9530fdc8d8SChris Lattner         const lldb::OptionDefinition*
9630fdc8d8SChris Lattner         GetDefinitions ()
9730fdc8d8SChris Lattner         {
9830fdc8d8SChris Lattner             return g_option_table;
9930fdc8d8SChris Lattner         }
10030fdc8d8SChris Lattner 
10130fdc8d8SChris Lattner         // Options table: Required for subclasses of Options.
10230fdc8d8SChris Lattner 
10330fdc8d8SChris Lattner         static lldb::OptionDefinition g_option_table[];
10430fdc8d8SChris Lattner 
10530fdc8d8SChris Lattner         // Instance variables to hold the values for command options.
10630fdc8d8SChris Lattner 
10730fdc8d8SChris Lattner         bool stop_at_entry;
10819388cfcSGreg Clayton         bool in_new_tty;
109f8da8631SCaroline Tice         bool no_stdio;
110913c4fa1SGreg Clayton         std::string tty_name;
11130fdc8d8SChris Lattner         std::string stderr_path;
11230fdc8d8SChris Lattner         std::string stdin_path;
11330fdc8d8SChris Lattner         std::string stdout_path;
11430fdc8d8SChris Lattner         std::string plugin_name;
115bd82a5d2SGreg Clayton         std::string working_dir;
11630fdc8d8SChris Lattner 
11730fdc8d8SChris Lattner     };
11830fdc8d8SChris Lattner 
119a7015092SGreg Clayton     CommandObjectProcessLaunch (CommandInterpreter &interpreter) :
120a7015092SGreg Clayton         CommandObject (interpreter,
121a7015092SGreg Clayton                        "process launch",
122e3d26315SCaroline Tice                        "Launch the executable in the debugger.",
123405fe67fSCaroline Tice                        NULL)
12430fdc8d8SChris Lattner     {
125405fe67fSCaroline Tice         CommandArgumentEntry arg;
126405fe67fSCaroline Tice         CommandArgumentData run_args_arg;
127405fe67fSCaroline Tice 
128405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
129405fe67fSCaroline Tice         run_args_arg.arg_type = eArgTypeRunArgs;
130405fe67fSCaroline Tice         run_args_arg.arg_repetition = eArgRepeatOptional;
131405fe67fSCaroline Tice 
132405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
133405fe67fSCaroline Tice         arg.push_back (run_args_arg);
134405fe67fSCaroline Tice 
135405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
136405fe67fSCaroline Tice         m_arguments.push_back (arg);
13730fdc8d8SChris Lattner     }
13830fdc8d8SChris Lattner 
13930fdc8d8SChris Lattner 
14030fdc8d8SChris Lattner     ~CommandObjectProcessLaunch ()
14130fdc8d8SChris Lattner     {
14230fdc8d8SChris Lattner     }
14330fdc8d8SChris Lattner 
14430fdc8d8SChris Lattner     Options *
14530fdc8d8SChris Lattner     GetOptions ()
14630fdc8d8SChris Lattner     {
14730fdc8d8SChris Lattner         return &m_options;
14830fdc8d8SChris Lattner     }
14930fdc8d8SChris Lattner 
15030fdc8d8SChris Lattner     bool
15105faeb71SGreg Clayton     Execute (Args& launch_args, CommandReturnObject &result)
15230fdc8d8SChris Lattner     {
153a7015092SGreg Clayton         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
15430fdc8d8SChris Lattner 
15530fdc8d8SChris Lattner         if (target == NULL)
15630fdc8d8SChris Lattner         {
15730fdc8d8SChris Lattner             result.AppendError ("invalid target, set executable file using 'file' command");
15830fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
15930fdc8d8SChris Lattner             return false;
16030fdc8d8SChris Lattner         }
16130fdc8d8SChris Lattner 
16230fdc8d8SChris Lattner         // If our listener is NULL, users aren't allows to launch
16330fdc8d8SChris Lattner         char filename[PATH_MAX];
16419388cfcSGreg Clayton         const Module *exe_module = target->GetExecutableModule().get();
16530fdc8d8SChris Lattner         exe_module->GetFileSpec().GetPath(filename, sizeof(filename));
16630fdc8d8SChris Lattner 
167a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
168a7015092SGreg Clayton         if (process && process->IsAlive())
16930fdc8d8SChris Lattner         {
170bb9caf73SJim Ingham             if (!m_interpreter.Confirm ("There is a running process, kill it and restart?", true))
171bb9caf73SJim Ingham             {
172bb9caf73SJim Ingham                 result.AppendErrorWithFormat ("Process %u is currently being debugged, restart cancelled.\n",
17330fdc8d8SChris Lattner                                               process->GetID());
17430fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
17530fdc8d8SChris Lattner                 return false;
17630fdc8d8SChris Lattner             }
177bb9caf73SJim Ingham             else
178bb9caf73SJim Ingham             {
179bb9caf73SJim Ingham                 Error error (process->Destroy());
180bb9caf73SJim Ingham                 if (error.Success())
181bb9caf73SJim Ingham                 {
182bb9caf73SJim Ingham                     result.SetStatus (eReturnStatusSuccessFinishResult);
183bb9caf73SJim Ingham                 }
184bb9caf73SJim Ingham                 else
185bb9caf73SJim Ingham                 {
186bb9caf73SJim Ingham                     result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString());
187bb9caf73SJim Ingham                     result.SetStatus (eReturnStatusFailed);
188bb9caf73SJim Ingham                 }
189bb9caf73SJim Ingham             }
190bb9caf73SJim Ingham         }
19130fdc8d8SChris Lattner 
19230fdc8d8SChris Lattner         const char *plugin_name;
19330fdc8d8SChris Lattner         if (!m_options.plugin_name.empty())
19430fdc8d8SChris Lattner             plugin_name = m_options.plugin_name.c_str();
19530fdc8d8SChris Lattner         else
19630fdc8d8SChris Lattner             plugin_name = NULL;
19730fdc8d8SChris Lattner 
198a7015092SGreg Clayton         process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
19930fdc8d8SChris Lattner 
200a7015092SGreg Clayton         if (process == NULL)
2013df9a8dfSCaroline Tice         {
20243a8c39bSCaroline Tice             result.AppendErrorWithFormat ("Failed to find a process plugin for executable.\n");
203a7015092SGreg Clayton             result.SetStatus (eReturnStatusFailed);
204a7015092SGreg Clayton             return false;
2053df9a8dfSCaroline Tice         }
2063df9a8dfSCaroline Tice 
207a7015092SGreg Clayton         // If no launch args were given on the command line, then use any that
208a7015092SGreg Clayton         // might have been set using the "run-args" set variable.
20930fdc8d8SChris Lattner         if (launch_args.GetArgumentCount() == 0)
21030fdc8d8SChris Lattner         {
211a7015092SGreg Clayton             if (process->GetRunArguments().GetArgumentCount() > 0)
212a7015092SGreg Clayton                 launch_args = process->GetRunArguments();
21330fdc8d8SChris Lattner         }
21430fdc8d8SChris Lattner 
21519388cfcSGreg Clayton         if (m_options.in_new_tty)
21619388cfcSGreg Clayton         {
21719388cfcSGreg Clayton             char exec_file_path[PATH_MAX];
21819388cfcSGreg Clayton             if (exe_module->GetFileSpec().GetPath(exec_file_path, sizeof(exec_file_path)))
21919388cfcSGreg Clayton             {
22019388cfcSGreg Clayton                 launch_args.InsertArgumentAtIndex(0, exec_file_path);
22119388cfcSGreg Clayton             }
22219388cfcSGreg Clayton             else
22319388cfcSGreg Clayton             {
22419388cfcSGreg Clayton                 result.AppendError("invalid executable");
22519388cfcSGreg Clayton                 result.SetStatus (eReturnStatusFailed);
22619388cfcSGreg Clayton                 return false;
22719388cfcSGreg Clayton             }
22819388cfcSGreg Clayton         }
22919388cfcSGreg Clayton 
230a7015092SGreg Clayton         Args environment;
23130fdc8d8SChris Lattner 
232a7015092SGreg Clayton         process->GetEnvironmentAsArgs (environment);
233a7015092SGreg Clayton 
234a7015092SGreg Clayton         uint32_t launch_flags = eLaunchFlagNone;
235a7015092SGreg Clayton 
236a7015092SGreg Clayton         if (process->GetDisableASLR())
237a7015092SGreg Clayton             launch_flags |= eLaunchFlagDisableASLR;
238a7015092SGreg Clayton 
239f8da8631SCaroline Tice         if (m_options.no_stdio)
240f8da8631SCaroline Tice             launch_flags |= eLaunchFlagDisableSTDIO;
241f8da8631SCaroline Tice         else if (!m_options.in_new_tty
242f8da8631SCaroline Tice                  && m_options.stdin_path.empty()
243f8da8631SCaroline Tice                  && m_options.stdout_path.empty()
244f8da8631SCaroline Tice                  && m_options.stderr_path.empty())
245f8da8631SCaroline Tice         {
246f8da8631SCaroline Tice             // Only use the settings value if the user hasn't specified any options that would override it.
247f8da8631SCaroline Tice             if (process->GetDisableSTDIO())
248f8da8631SCaroline Tice                 launch_flags |= eLaunchFlagDisableSTDIO;
249f8da8631SCaroline Tice         }
250f8da8631SCaroline Tice 
25119388cfcSGreg Clayton         const char **inferior_argv = launch_args.GetArgumentCount() ? launch_args.GetConstArgumentVector() : NULL;
25219388cfcSGreg Clayton         const char **inferior_envp = environment.GetArgumentCount() ? environment.GetConstArgumentVector() : NULL;
25330fdc8d8SChris Lattner 
25419388cfcSGreg Clayton         Error error;
255bd82a5d2SGreg Clayton         const char *working_dir = NULL;
256bd82a5d2SGreg Clayton         if (!m_options.working_dir.empty())
257bd82a5d2SGreg Clayton             working_dir = m_options.working_dir.c_str();
25819388cfcSGreg Clayton 
25919388cfcSGreg Clayton         if (m_options.in_new_tty)
26019388cfcSGreg Clayton         {
26119388cfcSGreg Clayton 
262913c4fa1SGreg Clayton             lldb::pid_t pid = Host::LaunchInNewTerminal (m_options.tty_name.c_str(),
263913c4fa1SGreg Clayton                                                          inferior_argv,
26419388cfcSGreg Clayton                                                          inferior_envp,
265bd82a5d2SGreg Clayton                                                          working_dir,
26619388cfcSGreg Clayton                                                          &exe_module->GetArchitecture(),
26719388cfcSGreg Clayton                                                          true,
26819388cfcSGreg Clayton                                                          process->GetDisableASLR());
26919388cfcSGreg Clayton 
2703fcbed6bSGreg Clayton             if (pid != LLDB_INVALID_PROCESS_ID)
2713fcbed6bSGreg Clayton                 error = process->Attach (pid);
27219388cfcSGreg Clayton         }
27319388cfcSGreg Clayton         else
27419388cfcSGreg Clayton         {
27530fdc8d8SChris Lattner             const char * stdin_path = NULL;
27630fdc8d8SChris Lattner             const char * stdout_path = NULL;
27730fdc8d8SChris Lattner             const char * stderr_path = NULL;
27830fdc8d8SChris Lattner 
279a7015092SGreg Clayton             // Were any standard input/output/error paths given on the command line?
280a7015092SGreg Clayton             if (m_options.stdin_path.empty() &&
28130fdc8d8SChris Lattner                 m_options.stdout_path.empty() &&
282a7015092SGreg Clayton                 m_options.stderr_path.empty())
28330fdc8d8SChris Lattner             {
284a7015092SGreg Clayton                 // No standard file handles were given on the command line, check
285a7015092SGreg Clayton                 // with the process object in case they were give using "set settings"
286a7015092SGreg Clayton                 stdin_path = process->GetStandardInputPath();
287a7015092SGreg Clayton                 stdout_path = process->GetStandardOutputPath();
288a7015092SGreg Clayton                 stderr_path = process->GetStandardErrorPath();
289a7015092SGreg Clayton             }
290a7015092SGreg Clayton             else
291a7015092SGreg Clayton             {
292a7015092SGreg Clayton                 stdin_path = m_options.stdin_path.empty()  ? NULL : m_options.stdin_path.c_str();
293a7015092SGreg Clayton                 stdout_path = m_options.stdout_path.empty() ? NULL : m_options.stdout_path.c_str();
294a7015092SGreg Clayton                 stderr_path = m_options.stderr_path.empty() ? NULL : m_options.stderr_path.c_str();
29530fdc8d8SChris Lattner             }
29630fdc8d8SChris Lattner 
29719388cfcSGreg Clayton             error = process->Launch (inferior_argv,
29819388cfcSGreg Clayton                                      inferior_envp,
299f681b94fSGreg Clayton                                      launch_flags,
30030fdc8d8SChris Lattner                                      stdin_path,
30130fdc8d8SChris Lattner                                      stdout_path,
302bd82a5d2SGreg Clayton                                      stderr_path,
303bd82a5d2SGreg Clayton                                      working_dir);
30419388cfcSGreg Clayton         }
30530fdc8d8SChris Lattner 
30630fdc8d8SChris Lattner         if (error.Success())
30730fdc8d8SChris Lattner         {
30819388cfcSGreg Clayton             const char *archname = exe_module->GetArchitecture().AsCString();
30919388cfcSGreg Clayton 
31019388cfcSGreg Clayton             result.AppendMessageWithFormat ("Process %i launched: '%s' (%s)\n", process->GetID(), filename, archname);
31105faeb71SGreg Clayton             result.SetDidChangeProcessState (true);
31230fdc8d8SChris Lattner             if (m_options.stop_at_entry == false)
31330fdc8d8SChris Lattner             {
31405faeb71SGreg Clayton                 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
31530fdc8d8SChris Lattner                 StateType state = process->WaitForProcessToStop (NULL);
31630fdc8d8SChris Lattner 
31730fdc8d8SChris Lattner                 if (state == eStateStopped)
31830fdc8d8SChris Lattner                 {
31905faeb71SGreg Clayton                     error = process->Resume();
32005faeb71SGreg Clayton                     if (error.Success())
32105faeb71SGreg Clayton                     {
32205faeb71SGreg Clayton                         bool synchronous_execution = m_interpreter.GetSynchronous ();
32330fdc8d8SChris Lattner                         if (synchronous_execution)
32430fdc8d8SChris Lattner                         {
32505faeb71SGreg Clayton                             state = process->WaitForProcessToStop (NULL);
32630fdc8d8SChris Lattner                             result.SetDidChangeProcessState (true);
32705faeb71SGreg Clayton                             result.SetStatus (eReturnStatusSuccessFinishResult);
32805faeb71SGreg Clayton                         }
32905faeb71SGreg Clayton                         else
33005faeb71SGreg Clayton                         {
33105faeb71SGreg Clayton                             result.SetStatus (eReturnStatusSuccessContinuingNoResult);
33205faeb71SGreg Clayton                         }
33305faeb71SGreg Clayton                     }
33430fdc8d8SChris Lattner                 }
33530fdc8d8SChris Lattner             }
33630fdc8d8SChris Lattner         }
33730fdc8d8SChris Lattner 
33830fdc8d8SChris Lattner         return result.Succeeded();
33930fdc8d8SChris Lattner     }
34030fdc8d8SChris Lattner 
341ebc09c36SJim Ingham     virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
342ebc09c36SJim Ingham     {
343ebc09c36SJim Ingham         // No repeat for "process launch"...
344ebc09c36SJim Ingham         return "";
345ebc09c36SJim Ingham     }
346ebc09c36SJim Ingham 
34730fdc8d8SChris Lattner protected:
34830fdc8d8SChris Lattner 
34930fdc8d8SChris Lattner     CommandOptions m_options;
35030fdc8d8SChris Lattner };
35130fdc8d8SChris Lattner 
35230fdc8d8SChris Lattner 
35319388cfcSGreg Clayton #define SET1 LLDB_OPT_SET_1
35419388cfcSGreg Clayton #define SET2 LLDB_OPT_SET_2
355f8da8631SCaroline Tice #define SET3 LLDB_OPT_SET_3
35619388cfcSGreg Clayton 
35730fdc8d8SChris Lattner lldb::OptionDefinition
35830fdc8d8SChris Lattner CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
35930fdc8d8SChris Lattner {
360f8da8631SCaroline Tice { SET1 | SET2 | SET3, false, "stop-at-entry", 's', no_argument,       NULL, 0, eArgTypeNone,    "Stop at the entry point of the program when launching a process."},
36119388cfcSGreg Clayton { SET1              , false, "stdin",         'i', required_argument, NULL, 0, eArgTypePath,    "Redirect stdin for the process to <path>."},
36219388cfcSGreg Clayton { SET1              , false, "stdout",        'o', required_argument, NULL, 0, eArgTypePath,    "Redirect stdout for the process to <path>."},
36319388cfcSGreg Clayton { SET1              , false, "stderr",        'e', required_argument, NULL, 0, eArgTypePath,    "Redirect stderr for the process to <path>."},
364f8da8631SCaroline Tice { SET1 | SET2 | SET3, false, "plugin",        'p', required_argument, NULL, 0, eArgTypePlugin,  "Name of the process plugin you want to use."},
365913c4fa1SGreg Clayton {        SET2       , false, "tty",           't', optional_argument, NULL, 0, eArgTypePath,    "Start the process in a terminal. If <path> is specified, look for a terminal whose name contains <path>, else start the process in a new terminal."},
366f8da8631SCaroline Tice {               SET3, false, "no-stdio",      'n', no_argument,       NULL, 0, eArgTypeNone,    "Do not set up for terminal I/O to go to running process."},
367bd82a5d2SGreg Clayton { SET1 | SET2 | SET3, false, "working-dir",   'w', required_argument, NULL, 0, eArgTypePath,    "Set the current working directory to <path> when running the inferior."},
368deaab222SCaroline Tice { 0,                  false, NULL,             0,  0,                 NULL, 0, eArgTypeNone,    NULL }
36930fdc8d8SChris Lattner };
37030fdc8d8SChris Lattner 
37119388cfcSGreg Clayton #undef SET1
37219388cfcSGreg Clayton #undef SET2
373f8da8631SCaroline Tice #undef SET3
37430fdc8d8SChris Lattner 
37530fdc8d8SChris Lattner //-------------------------------------------------------------------------
37630fdc8d8SChris Lattner // CommandObjectProcessAttach
37730fdc8d8SChris Lattner //-------------------------------------------------------------------------
378bb9caf73SJim Ingham #pragma mark CommandObjectProcessAttach
37930fdc8d8SChris Lattner class CommandObjectProcessAttach : public CommandObject
38030fdc8d8SChris Lattner {
38130fdc8d8SChris Lattner public:
38230fdc8d8SChris Lattner 
38330fdc8d8SChris Lattner     class CommandOptions : public Options
38430fdc8d8SChris Lattner     {
38530fdc8d8SChris Lattner     public:
38630fdc8d8SChris Lattner 
38730fdc8d8SChris Lattner         CommandOptions () :
38830fdc8d8SChris Lattner             Options()
38930fdc8d8SChris Lattner         {
39030fdc8d8SChris Lattner             // Keep default values of all options in one place: ResetOptionValues ()
39130fdc8d8SChris Lattner             ResetOptionValues ();
39230fdc8d8SChris Lattner         }
39330fdc8d8SChris Lattner 
39430fdc8d8SChris Lattner         ~CommandOptions ()
39530fdc8d8SChris Lattner         {
39630fdc8d8SChris Lattner         }
39730fdc8d8SChris Lattner 
39830fdc8d8SChris Lattner         Error
39930fdc8d8SChris Lattner         SetOptionValue (int option_idx, const char *option_arg)
40030fdc8d8SChris Lattner         {
40130fdc8d8SChris Lattner             Error error;
40230fdc8d8SChris Lattner             char short_option = (char) m_getopt_table[option_idx].val;
40330fdc8d8SChris Lattner             bool success = false;
40430fdc8d8SChris Lattner             switch (short_option)
40530fdc8d8SChris Lattner             {
40630fdc8d8SChris Lattner                 case 'p':
40730fdc8d8SChris Lattner                     pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success);
40830fdc8d8SChris Lattner                     if (!success || pid == LLDB_INVALID_PROCESS_ID)
40930fdc8d8SChris Lattner                     {
41030fdc8d8SChris Lattner                         error.SetErrorStringWithFormat("Invalid process ID '%s'.\n", option_arg);
41130fdc8d8SChris Lattner                     }
41230fdc8d8SChris Lattner                     break;
41330fdc8d8SChris Lattner 
41430fdc8d8SChris Lattner                 case 'P':
41530fdc8d8SChris Lattner                     plugin_name = option_arg;
41630fdc8d8SChris Lattner                     break;
41730fdc8d8SChris Lattner 
41830fdc8d8SChris Lattner                 case 'n':
41930fdc8d8SChris Lattner                     name.assign(option_arg);
42030fdc8d8SChris Lattner                     break;
42130fdc8d8SChris Lattner 
42230fdc8d8SChris Lattner                 case 'w':
42330fdc8d8SChris Lattner                     waitfor = true;
42430fdc8d8SChris Lattner                     break;
42530fdc8d8SChris Lattner 
42630fdc8d8SChris Lattner                 default:
42730fdc8d8SChris Lattner                     error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
42830fdc8d8SChris Lattner                     break;
42930fdc8d8SChris Lattner             }
43030fdc8d8SChris Lattner             return error;
43130fdc8d8SChris Lattner         }
43230fdc8d8SChris Lattner 
43330fdc8d8SChris Lattner         void
43430fdc8d8SChris Lattner         ResetOptionValues ()
43530fdc8d8SChris Lattner         {
43630fdc8d8SChris Lattner             Options::ResetOptionValues();
43730fdc8d8SChris Lattner             pid = LLDB_INVALID_PROCESS_ID;
43830fdc8d8SChris Lattner             name.clear();
43930fdc8d8SChris Lattner             waitfor = false;
44030fdc8d8SChris Lattner         }
44130fdc8d8SChris Lattner 
44230fdc8d8SChris Lattner         const lldb::OptionDefinition*
44330fdc8d8SChris Lattner         GetDefinitions ()
44430fdc8d8SChris Lattner         {
44530fdc8d8SChris Lattner             return g_option_table;
44630fdc8d8SChris Lattner         }
44730fdc8d8SChris Lattner 
4485aee162fSJim Ingham         virtual bool
449a7015092SGreg Clayton         HandleOptionArgumentCompletion (CommandInterpreter &interpeter,
4505aee162fSJim Ingham                                         Args &input,
4515aee162fSJim Ingham                                         int cursor_index,
4525aee162fSJim Ingham                                         int char_pos,
4535aee162fSJim Ingham                                         OptionElementVector &opt_element_vector,
4545aee162fSJim Ingham                                         int opt_element_index,
4555aee162fSJim Ingham                                         int match_start_point,
4565aee162fSJim Ingham                                         int max_return_elements,
4575aee162fSJim Ingham                                         bool &word_complete,
4585aee162fSJim Ingham                                         StringList &matches)
4595aee162fSJim Ingham         {
4605aee162fSJim Ingham             int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
4615aee162fSJim Ingham             int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
4625aee162fSJim Ingham 
4635aee162fSJim Ingham             // We are only completing the name option for now...
4645aee162fSJim Ingham 
4655aee162fSJim Ingham             const lldb::OptionDefinition *opt_defs = GetDefinitions();
4665aee162fSJim Ingham             if (opt_defs[opt_defs_index].short_option == 'n')
4675aee162fSJim Ingham             {
4685aee162fSJim Ingham                 // Are we in the name?
4695aee162fSJim Ingham 
4705aee162fSJim Ingham                 // Look to see if there is a -P argument provided, and if so use that plugin, otherwise
4715aee162fSJim Ingham                 // use the default plugin.
472a7015092SGreg Clayton                 Process *process = interpeter.GetDebugger().GetExecutionContext().process;
4735aee162fSJim Ingham                 bool need_to_delete_process = false;
4745aee162fSJim Ingham 
4755aee162fSJim Ingham                 const char *partial_name = NULL;
4765aee162fSJim Ingham                 partial_name = input.GetArgumentAtIndex(opt_arg_pos);
4775aee162fSJim Ingham 
4785aee162fSJim Ingham                 if (process && process->IsAlive())
4795aee162fSJim Ingham                     return true;
4805aee162fSJim Ingham 
481a7015092SGreg Clayton                 Target *target = interpeter.GetDebugger().GetSelectedTarget().get();
4825aee162fSJim Ingham                 if (target == NULL)
4835aee162fSJim Ingham                 {
4845aee162fSJim Ingham                     // No target has been set yet, for now do host completion.  Otherwise I don't know how we would
4855aee162fSJim Ingham                     // figure out what the right target to use is...
4865aee162fSJim Ingham                     std::vector<lldb::pid_t> pids;
4875aee162fSJim Ingham                     Host::ListProcessesMatchingName (partial_name, matches, pids);
4885aee162fSJim Ingham                     return true;
4895aee162fSJim Ingham                 }
4905aee162fSJim Ingham                 if (!process)
4915aee162fSJim Ingham                 {
492a7015092SGreg Clayton                     process = target->CreateProcess (interpeter.GetDebugger().GetListener(), partial_name).get();
4935aee162fSJim Ingham                     need_to_delete_process = true;
4945aee162fSJim Ingham                 }
4955aee162fSJim Ingham 
4965aee162fSJim Ingham                 if (process)
4975aee162fSJim Ingham                 {
4985aee162fSJim Ingham                     matches.Clear();
4995aee162fSJim Ingham                     std::vector<lldb::pid_t> pids;
5005aee162fSJim Ingham                     process->ListProcessesMatchingName (NULL, matches, pids);
5015aee162fSJim Ingham                     if (need_to_delete_process)
5025aee162fSJim Ingham                         target->DeleteCurrentProcess();
5035aee162fSJim Ingham                     return true;
5045aee162fSJim Ingham                 }
5055aee162fSJim Ingham             }
5065aee162fSJim Ingham 
5075aee162fSJim Ingham             return false;
5085aee162fSJim Ingham         }
5095aee162fSJim Ingham 
51030fdc8d8SChris Lattner         // Options table: Required for subclasses of Options.
51130fdc8d8SChris Lattner 
51230fdc8d8SChris Lattner         static lldb::OptionDefinition g_option_table[];
51330fdc8d8SChris Lattner 
51430fdc8d8SChris Lattner         // Instance variables to hold the values for command options.
51530fdc8d8SChris Lattner 
51630fdc8d8SChris Lattner         lldb::pid_t pid;
51730fdc8d8SChris Lattner         std::string plugin_name;
51830fdc8d8SChris Lattner         std::string name;
51930fdc8d8SChris Lattner         bool waitfor;
52030fdc8d8SChris Lattner     };
52130fdc8d8SChris Lattner 
522a7015092SGreg Clayton     CommandObjectProcessAttach (CommandInterpreter &interpreter) :
523a7015092SGreg Clayton         CommandObject (interpreter,
524a7015092SGreg Clayton                        "process attach",
525e3d26315SCaroline Tice                        "Attach to a process.",
5265aee162fSJim Ingham                        "process attach <cmd-options>")
5275aee162fSJim Ingham     {
5285aee162fSJim Ingham     }
5295aee162fSJim Ingham 
5305aee162fSJim Ingham     ~CommandObjectProcessAttach ()
5315aee162fSJim Ingham     {
5325aee162fSJim Ingham     }
5335aee162fSJim Ingham 
5345aee162fSJim Ingham     bool
535a7015092SGreg Clayton     Execute (Args& command,
5365aee162fSJim Ingham              CommandReturnObject &result)
5375aee162fSJim Ingham     {
538a7015092SGreg Clayton         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
539*bb3a283bSJim Ingham         bool synchronous_execution = m_interpreter.GetSynchronous ();
5405aee162fSJim Ingham 
541a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
5425aee162fSJim Ingham         if (process)
5435aee162fSJim Ingham         {
5445aee162fSJim Ingham             if (process->IsAlive())
5455aee162fSJim Ingham             {
5465aee162fSJim Ingham                 result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before attaching.\n",
5475aee162fSJim Ingham                                               process->GetID());
5485aee162fSJim Ingham                 result.SetStatus (eReturnStatusFailed);
5495aee162fSJim Ingham                 return false;
5505aee162fSJim Ingham             }
5515aee162fSJim Ingham         }
5525aee162fSJim Ingham 
5535aee162fSJim Ingham         if (target == NULL)
5545aee162fSJim Ingham         {
5555aee162fSJim Ingham             // If there isn't a current target create one.
5565aee162fSJim Ingham             TargetSP new_target_sp;
5575aee162fSJim Ingham             FileSpec emptyFileSpec;
5585aee162fSJim Ingham             ArchSpec emptyArchSpec;
5595aee162fSJim Ingham             Error error;
5605aee162fSJim Ingham 
561a7015092SGreg Clayton             error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(),
5625aee162fSJim Ingham                                                                               emptyFileSpec,
5635aee162fSJim Ingham                                                                               emptyArchSpec,
5645aee162fSJim Ingham                                                                               NULL,
5655aee162fSJim Ingham                                                                               false,
5665aee162fSJim Ingham                                                                               new_target_sp);
5675aee162fSJim Ingham             target = new_target_sp.get();
5685aee162fSJim Ingham             if (target == NULL || error.Fail())
5695aee162fSJim Ingham             {
5705aee162fSJim Ingham                 result.AppendError(error.AsCString("Error creating empty target"));
5715aee162fSJim Ingham                 return false;
5725aee162fSJim Ingham             }
573a7015092SGreg Clayton             m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target);
5745aee162fSJim Ingham         }
5755aee162fSJim Ingham 
5765aee162fSJim Ingham         // Record the old executable module, we want to issue a warning if the process of attaching changed the
5775aee162fSJim Ingham         // current executable (like somebody said "file foo" then attached to a PID whose executable was bar.)
5785aee162fSJim Ingham 
5795aee162fSJim Ingham         ModuleSP old_exec_module_sp = target->GetExecutableModule();
5805aee162fSJim Ingham         ArchSpec old_arch_spec = target->GetArchitecture();
5815aee162fSJim Ingham 
5825aee162fSJim Ingham         if (command.GetArgumentCount())
5835aee162fSJim Ingham         {
5845aee162fSJim Ingham             result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
5855aee162fSJim Ingham             result.SetStatus (eReturnStatusFailed);
5865aee162fSJim Ingham         }
5875aee162fSJim Ingham         else
5885aee162fSJim Ingham         {
5895aee162fSJim Ingham             const char *plugin_name = NULL;
5905aee162fSJim Ingham 
5915aee162fSJim Ingham             if (!m_options.plugin_name.empty())
5925aee162fSJim Ingham                 plugin_name = m_options.plugin_name.c_str();
5935aee162fSJim Ingham 
594a7015092SGreg Clayton             process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
5955aee162fSJim Ingham 
5965aee162fSJim Ingham             if (process)
5975aee162fSJim Ingham             {
5985aee162fSJim Ingham                 Error error;
5995aee162fSJim Ingham                 int attach_pid = m_options.pid;
6005aee162fSJim Ingham 
6013a0b9cdfSJim Ingham                 const char *wait_name = NULL;
6023a0b9cdfSJim Ingham 
6035aee162fSJim Ingham                 if (m_options.name.empty())
6045aee162fSJim Ingham                 {
6053a0b9cdfSJim Ingham                     if (old_exec_module_sp)
6063a0b9cdfSJim Ingham                     {
6073a0b9cdfSJim Ingham                         wait_name = old_exec_module_sp->GetFileSpec().GetFilename().AsCString();
6083a0b9cdfSJim Ingham                     }
6095aee162fSJim Ingham                 }
6105aee162fSJim Ingham                 else
6115aee162fSJim Ingham                 {
6123a0b9cdfSJim Ingham                     wait_name = m_options.name.c_str();
6133a0b9cdfSJim Ingham                 }
6143a0b9cdfSJim Ingham 
6153a0b9cdfSJim Ingham                 // If we are waiting for a process with this name to show up, do that first.
6163a0b9cdfSJim Ingham                 if (m_options.waitfor)
6173a0b9cdfSJim Ingham                 {
6183a0b9cdfSJim Ingham 
6193a0b9cdfSJim Ingham                     if (wait_name == NULL)
6203a0b9cdfSJim Ingham                     {
6213a0b9cdfSJim Ingham                         result.AppendError("Invalid arguments: must have a file loaded or supply a process name with the waitfor option.\n");
6223a0b9cdfSJim Ingham                         result.SetStatus (eReturnStatusFailed);
6233a0b9cdfSJim Ingham                         return false;
6243a0b9cdfSJim Ingham                     }
6253a0b9cdfSJim Ingham 
626a7015092SGreg Clayton                     m_interpreter.GetDebugger().GetOutputStream().Printf("Waiting to attach to a process named \"%s\".\n", wait_name);
6273a0b9cdfSJim Ingham                     error = process->Attach (wait_name, m_options.waitfor);
6285aee162fSJim Ingham                     if (error.Success())
6295aee162fSJim Ingham                     {
6305aee162fSJim Ingham                         result.SetStatus (eReturnStatusSuccessContinuingNoResult);
6315aee162fSJim Ingham                     }
6325aee162fSJim Ingham                     else
6335aee162fSJim Ingham                     {
6345aee162fSJim Ingham                         result.AppendErrorWithFormat ("Waiting for a process to launch named '%s': %s\n",
6353a0b9cdfSJim Ingham                                                          wait_name,
6365aee162fSJim Ingham                                                          error.AsCString());
6375aee162fSJim Ingham                         result.SetStatus (eReturnStatusFailed);
6385aee162fSJim Ingham                         return false;
6395aee162fSJim Ingham                     }
640*bb3a283bSJim Ingham                     // If we're synchronous, wait for the stopped event and report that.
641*bb3a283bSJim Ingham                     // Otherwise just return.
642*bb3a283bSJim Ingham                     // FIXME: in the async case it will now be possible to get to the command
643*bb3a283bSJim Ingham                     // interpreter with a state eStateAttaching.  Make sure we handle that correctly.
644*bb3a283bSJim Ingham                     if (synchronous_execution)
645*bb3a283bSJim Ingham                     {
646*bb3a283bSJim Ingham                         StateType state = process->WaitForProcessToStop (NULL);
647*bb3a283bSJim Ingham 
648*bb3a283bSJim Ingham                         result.SetDidChangeProcessState (true);
649*bb3a283bSJim Ingham                         result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
650*bb3a283bSJim Ingham                         result.SetStatus (eReturnStatusSuccessFinishNoResult);
651*bb3a283bSJim Ingham                     }
652*bb3a283bSJim Ingham                     else
653*bb3a283bSJim Ingham                     {
654*bb3a283bSJim Ingham                         result.SetDidChangeProcessState (true);
655*bb3a283bSJim Ingham                         result.AppendMessageWithFormat ("Starting to attach to process.");
656*bb3a283bSJim Ingham                         result.SetStatus (eReturnStatusSuccessFinishNoResult);
657*bb3a283bSJim Ingham                     }
6585aee162fSJim Ingham                 }
6595aee162fSJim Ingham                 else
6605aee162fSJim Ingham                 {
6615aee162fSJim Ingham                     // If the process was specified by name look it up, so we can warn if there are multiple
6625aee162fSJim Ingham                     // processes with this pid.
6635aee162fSJim Ingham 
6643a0b9cdfSJim Ingham                     if (attach_pid == LLDB_INVALID_PROCESS_ID && wait_name != NULL)
6655aee162fSJim Ingham                     {
6665aee162fSJim Ingham                         std::vector<lldb::pid_t> pids;
6675aee162fSJim Ingham                         StringList matches;
6685aee162fSJim Ingham 
6693a0b9cdfSJim Ingham                         process->ListProcessesMatchingName(wait_name, matches, pids);
6705aee162fSJim Ingham                         if (matches.GetSize() > 1)
6715aee162fSJim Ingham                         {
6723a0b9cdfSJim Ingham                             result.AppendErrorWithFormat("More than one process named %s\n", wait_name);
6735aee162fSJim Ingham                             result.SetStatus (eReturnStatusFailed);
6745aee162fSJim Ingham                             return false;
6755aee162fSJim Ingham                         }
6765aee162fSJim Ingham                         else if (matches.GetSize() == 0)
6775aee162fSJim Ingham                         {
6783a0b9cdfSJim Ingham                             result.AppendErrorWithFormat("Could not find a process named %s\n", wait_name);
6795aee162fSJim Ingham                             result.SetStatus (eReturnStatusFailed);
6805aee162fSJim Ingham                             return false;
6815aee162fSJim Ingham                         }
6825aee162fSJim Ingham                         else
6835aee162fSJim Ingham                         {
6845aee162fSJim Ingham                             attach_pid = pids[0];
6855aee162fSJim Ingham                         }
6865aee162fSJim Ingham 
6875aee162fSJim Ingham                     }
6885aee162fSJim Ingham 
6895aee162fSJim Ingham                     if (attach_pid != LLDB_INVALID_PROCESS_ID)
6905aee162fSJim Ingham                     {
6915aee162fSJim Ingham                         error = process->Attach (attach_pid);
6925aee162fSJim Ingham                         if (error.Success())
6935aee162fSJim Ingham                         {
6945aee162fSJim Ingham                             result.SetStatus (eReturnStatusSuccessContinuingNoResult);
6955aee162fSJim Ingham                         }
6965aee162fSJim Ingham                         else
6975aee162fSJim Ingham                         {
6985aee162fSJim Ingham                             result.AppendErrorWithFormat ("Attaching to process %i failed: %s.\n",
6995aee162fSJim Ingham                                                          attach_pid,
7005aee162fSJim Ingham                                                          error.AsCString());
7015aee162fSJim Ingham                             result.SetStatus (eReturnStatusFailed);
7025aee162fSJim Ingham                         }
703*bb3a283bSJim Ingham                         // See comment for synchronous_execution above.
704*bb3a283bSJim Ingham                         if (synchronous_execution)
705*bb3a283bSJim Ingham                         {
706*bb3a283bSJim Ingham                             StateType state = process->WaitForProcessToStop (NULL);
707*bb3a283bSJim Ingham 
708*bb3a283bSJim Ingham                             result.SetDidChangeProcessState (true);
709*bb3a283bSJim Ingham                             result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
710*bb3a283bSJim Ingham                             result.SetStatus (eReturnStatusSuccessFinishNoResult);
711*bb3a283bSJim Ingham                         }
712*bb3a283bSJim Ingham                         else
713*bb3a283bSJim Ingham                         {
714*bb3a283bSJim Ingham                             result.SetDidChangeProcessState (true);
715*bb3a283bSJim Ingham                             result.AppendMessageWithFormat ("Starting to attach to process.");
716*bb3a283bSJim Ingham                             result.SetStatus (eReturnStatusSuccessFinishNoResult);
717*bb3a283bSJim Ingham                         }
7185aee162fSJim Ingham                     }
7195aee162fSJim Ingham                     else
7205aee162fSJim Ingham                     {
7215aee162fSJim Ingham                         result.AppendErrorWithFormat ("No PID specified for attach\n",
7225aee162fSJim Ingham                                                          attach_pid,
7235aee162fSJim Ingham                                                          error.AsCString());
7245aee162fSJim Ingham                         result.SetStatus (eReturnStatusFailed);
7255aee162fSJim Ingham 
7265aee162fSJim Ingham                     }
7275aee162fSJim Ingham                 }
7285aee162fSJim Ingham             }
7295aee162fSJim Ingham         }
7305aee162fSJim Ingham 
7315aee162fSJim Ingham         if (result.Succeeded())
7325aee162fSJim Ingham         {
7335aee162fSJim Ingham             // Okay, we're done.  Last step is to warn if the executable module has changed:
7345aee162fSJim Ingham             if (!old_exec_module_sp)
7355aee162fSJim Ingham             {
7365aee162fSJim Ingham                 char new_path[PATH_MAX + 1];
7375aee162fSJim Ingham                 target->GetExecutableModule()->GetFileSpec().GetPath(new_path, PATH_MAX);
7385aee162fSJim Ingham 
7395aee162fSJim Ingham                 result.AppendMessageWithFormat("Executable module set to \"%s\".\n",
7405aee162fSJim Ingham                     new_path);
7415aee162fSJim Ingham             }
7425aee162fSJim Ingham             else if (old_exec_module_sp->GetFileSpec() != target->GetExecutableModule()->GetFileSpec())
7435aee162fSJim Ingham             {
7445aee162fSJim Ingham                 char old_path[PATH_MAX + 1];
7455aee162fSJim Ingham                 char new_path[PATH_MAX + 1];
7465aee162fSJim Ingham 
7475aee162fSJim Ingham                 old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX);
7485aee162fSJim Ingham                 target->GetExecutableModule()->GetFileSpec().GetPath (new_path, PATH_MAX);
7495aee162fSJim Ingham 
7505aee162fSJim Ingham                 result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n",
7515aee162fSJim Ingham                                                     old_path, new_path);
7525aee162fSJim Ingham             }
7535aee162fSJim Ingham 
7545aee162fSJim Ingham             if (!old_arch_spec.IsValid())
7555aee162fSJim Ingham             {
7565aee162fSJim Ingham                 result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().AsCString());
7575aee162fSJim Ingham             }
7585aee162fSJim Ingham             else if (old_arch_spec != target->GetArchitecture())
7595aee162fSJim Ingham             {
7605aee162fSJim Ingham                 result.AppendWarningWithFormat("Architecture changed from %s to %s.\n",
7615aee162fSJim Ingham                                                 old_arch_spec.AsCString(), target->GetArchitecture().AsCString());
7625aee162fSJim Ingham             }
7635aee162fSJim Ingham         }
7645aee162fSJim Ingham         return result.Succeeded();
7655aee162fSJim Ingham     }
7665aee162fSJim Ingham 
7675aee162fSJim Ingham     Options *
7685aee162fSJim Ingham     GetOptions ()
7695aee162fSJim Ingham     {
7705aee162fSJim Ingham         return &m_options;
7715aee162fSJim Ingham     }
7725aee162fSJim Ingham 
77330fdc8d8SChris Lattner protected:
77430fdc8d8SChris Lattner 
77530fdc8d8SChris Lattner     CommandOptions m_options;
77630fdc8d8SChris Lattner };
77730fdc8d8SChris Lattner 
77830fdc8d8SChris Lattner 
77930fdc8d8SChris Lattner lldb::OptionDefinition
78030fdc8d8SChris Lattner CommandObjectProcessAttach::CommandOptions::g_option_table[] =
78130fdc8d8SChris Lattner {
782deaab222SCaroline Tice { LLDB_OPT_SET_ALL, false, "plugin", 'P', required_argument, NULL, 0, eArgTypePlugin,        "Name of the process plugin you want to use."},
783deaab222SCaroline Tice { LLDB_OPT_SET_1,   false, "pid",    'p', required_argument, NULL, 0, eArgTypePid,           "The process ID of an existing process to attach to."},
784deaab222SCaroline Tice { LLDB_OPT_SET_2,   false, "name",   'n', required_argument, NULL, 0, eArgTypeProcessName,  "The name of the process to attach to."},
785deaab222SCaroline Tice { LLDB_OPT_SET_2,   false, "waitfor",'w', no_argument,       NULL, 0, eArgTypeNone,              "Wait for the the process with <process-name> to launch."},
786deaab222SCaroline Tice { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
78730fdc8d8SChris Lattner };
78830fdc8d8SChris Lattner 
78930fdc8d8SChris Lattner //-------------------------------------------------------------------------
79030fdc8d8SChris Lattner // CommandObjectProcessContinue
79130fdc8d8SChris Lattner //-------------------------------------------------------------------------
792bb9caf73SJim Ingham #pragma mark CommandObjectProcessContinue
79330fdc8d8SChris Lattner 
79430fdc8d8SChris Lattner class CommandObjectProcessContinue : public CommandObject
79530fdc8d8SChris Lattner {
79630fdc8d8SChris Lattner public:
79730fdc8d8SChris Lattner 
798a7015092SGreg Clayton     CommandObjectProcessContinue (CommandInterpreter &interpreter) :
799a7015092SGreg Clayton         CommandObject (interpreter,
800a7015092SGreg Clayton                        "process continue",
801e3d26315SCaroline Tice                        "Continue execution of all threads in the current process.",
80230fdc8d8SChris Lattner                        "process continue",
80330fdc8d8SChris Lattner                        eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
80430fdc8d8SChris Lattner     {
80530fdc8d8SChris Lattner     }
80630fdc8d8SChris Lattner 
80730fdc8d8SChris Lattner 
80830fdc8d8SChris Lattner     ~CommandObjectProcessContinue ()
80930fdc8d8SChris Lattner     {
81030fdc8d8SChris Lattner     }
81130fdc8d8SChris Lattner 
81230fdc8d8SChris Lattner     bool
813a7015092SGreg Clayton     Execute (Args& command,
81430fdc8d8SChris Lattner              CommandReturnObject &result)
81530fdc8d8SChris Lattner     {
816a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
817a7015092SGreg Clayton         bool synchronous_execution = m_interpreter.GetSynchronous ();
81830fdc8d8SChris Lattner 
81930fdc8d8SChris Lattner         if (process == NULL)
82030fdc8d8SChris Lattner         {
82130fdc8d8SChris Lattner             result.AppendError ("no process to continue");
82230fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
82330fdc8d8SChris Lattner             return false;
82430fdc8d8SChris Lattner          }
82530fdc8d8SChris Lattner 
82630fdc8d8SChris Lattner         StateType state = process->GetState();
82730fdc8d8SChris Lattner         if (state == eStateStopped)
82830fdc8d8SChris Lattner         {
82930fdc8d8SChris Lattner             if (command.GetArgumentCount() != 0)
83030fdc8d8SChris Lattner             {
83130fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str());
83230fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
83330fdc8d8SChris Lattner                 return false;
83430fdc8d8SChris Lattner             }
83530fdc8d8SChris Lattner 
83630fdc8d8SChris Lattner             const uint32_t num_threads = process->GetThreadList().GetSize();
83730fdc8d8SChris Lattner 
83830fdc8d8SChris Lattner             // Set the actions that the threads should each take when resuming
83930fdc8d8SChris Lattner             for (uint32_t idx=0; idx<num_threads; ++idx)
84030fdc8d8SChris Lattner             {
84130fdc8d8SChris Lattner                 process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning);
84230fdc8d8SChris Lattner             }
84330fdc8d8SChris Lattner 
84430fdc8d8SChris Lattner             Error error(process->Resume());
84530fdc8d8SChris Lattner             if (error.Success())
84630fdc8d8SChris Lattner             {
84719388cfcSGreg Clayton                 result.AppendMessageWithFormat ("Process %i resuming\n", process->GetID());
84830fdc8d8SChris Lattner                 if (synchronous_execution)
84930fdc8d8SChris Lattner                 {
850b132097bSGreg Clayton                     state = process->WaitForProcessToStop (NULL);
85130fdc8d8SChris Lattner 
85230fdc8d8SChris Lattner                     result.SetDidChangeProcessState (true);
85330fdc8d8SChris Lattner                     result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
85430fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
85530fdc8d8SChris Lattner                 }
85630fdc8d8SChris Lattner                 else
85730fdc8d8SChris Lattner                 {
85830fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusSuccessContinuingNoResult);
85930fdc8d8SChris Lattner                 }
86030fdc8d8SChris Lattner             }
86130fdc8d8SChris Lattner             else
86230fdc8d8SChris Lattner             {
86330fdc8d8SChris Lattner                 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
86430fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
86530fdc8d8SChris Lattner             }
86630fdc8d8SChris Lattner         }
86730fdc8d8SChris Lattner         else
86830fdc8d8SChris Lattner         {
86930fdc8d8SChris Lattner             result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
87030fdc8d8SChris Lattner                                          StateAsCString(state));
87130fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
87230fdc8d8SChris Lattner         }
87330fdc8d8SChris Lattner         return result.Succeeded();
87430fdc8d8SChris Lattner     }
87530fdc8d8SChris Lattner };
87630fdc8d8SChris Lattner 
87730fdc8d8SChris Lattner //-------------------------------------------------------------------------
87830fdc8d8SChris Lattner // CommandObjectProcessDetach
87930fdc8d8SChris Lattner //-------------------------------------------------------------------------
880bb9caf73SJim Ingham #pragma mark CommandObjectProcessDetach
88130fdc8d8SChris Lattner 
88230fdc8d8SChris Lattner class CommandObjectProcessDetach : public CommandObject
88330fdc8d8SChris Lattner {
88430fdc8d8SChris Lattner public:
88530fdc8d8SChris Lattner 
886a7015092SGreg Clayton     CommandObjectProcessDetach (CommandInterpreter &interpreter) :
887a7015092SGreg Clayton         CommandObject (interpreter,
888a7015092SGreg Clayton                        "process detach",
889e3d26315SCaroline Tice                        "Detach from the current process being debugged.",
89030fdc8d8SChris Lattner                        "process detach",
89130fdc8d8SChris Lattner                        eFlagProcessMustBeLaunched)
89230fdc8d8SChris Lattner     {
89330fdc8d8SChris Lattner     }
89430fdc8d8SChris Lattner 
89530fdc8d8SChris Lattner     ~CommandObjectProcessDetach ()
89630fdc8d8SChris Lattner     {
89730fdc8d8SChris Lattner     }
89830fdc8d8SChris Lattner 
89930fdc8d8SChris Lattner     bool
900a7015092SGreg Clayton     Execute (Args& command,
90130fdc8d8SChris Lattner              CommandReturnObject &result)
90230fdc8d8SChris Lattner     {
903a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
90430fdc8d8SChris Lattner         if (process == NULL)
90530fdc8d8SChris Lattner         {
90630fdc8d8SChris Lattner             result.AppendError ("must have a valid process in order to detach");
90730fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
90830fdc8d8SChris Lattner             return false;
90930fdc8d8SChris Lattner         }
91030fdc8d8SChris Lattner 
9115d7be2e6SCaroline Tice         result.AppendMessageWithFormat ("Detaching from process %i\n", process->GetID());
91230fdc8d8SChris Lattner         Error error (process->Detach());
91330fdc8d8SChris Lattner         if (error.Success())
91430fdc8d8SChris Lattner         {
91530fdc8d8SChris Lattner             result.SetStatus (eReturnStatusSuccessFinishResult);
91630fdc8d8SChris Lattner         }
91730fdc8d8SChris Lattner         else
91830fdc8d8SChris Lattner         {
91930fdc8d8SChris Lattner             result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString());
92030fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
92130fdc8d8SChris Lattner             return false;
92230fdc8d8SChris Lattner         }
92330fdc8d8SChris Lattner         return result.Succeeded();
92430fdc8d8SChris Lattner     }
92530fdc8d8SChris Lattner };
92630fdc8d8SChris Lattner 
92730fdc8d8SChris Lattner //-------------------------------------------------------------------------
9288f343b09SGreg Clayton // CommandObjectProcessLoad
9298f343b09SGreg Clayton //-------------------------------------------------------------------------
930bb9caf73SJim Ingham #pragma mark CommandObjectProcessLoad
9318f343b09SGreg Clayton 
9328f343b09SGreg Clayton class CommandObjectProcessLoad : public CommandObject
9338f343b09SGreg Clayton {
9348f343b09SGreg Clayton public:
9358f343b09SGreg Clayton 
9368f343b09SGreg Clayton     CommandObjectProcessLoad (CommandInterpreter &interpreter) :
9378f343b09SGreg Clayton         CommandObject (interpreter,
9388f343b09SGreg Clayton                        "process load",
9398f343b09SGreg Clayton                        "Load a shared library into the current process.",
9408f343b09SGreg Clayton                        "process load <filename> [<filename> ...]",
9418f343b09SGreg Clayton                        eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
9428f343b09SGreg Clayton     {
9438f343b09SGreg Clayton     }
9448f343b09SGreg Clayton 
9458f343b09SGreg Clayton     ~CommandObjectProcessLoad ()
9468f343b09SGreg Clayton     {
9478f343b09SGreg Clayton     }
9488f343b09SGreg Clayton 
9498f343b09SGreg Clayton     bool
9508f343b09SGreg Clayton     Execute (Args& command,
9518f343b09SGreg Clayton              CommandReturnObject &result)
9528f343b09SGreg Clayton     {
9538f343b09SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
9548f343b09SGreg Clayton         if (process == NULL)
9558f343b09SGreg Clayton         {
9568f343b09SGreg Clayton             result.AppendError ("must have a valid process in order to load a shared library");
9578f343b09SGreg Clayton             result.SetStatus (eReturnStatusFailed);
9588f343b09SGreg Clayton             return false;
9598f343b09SGreg Clayton         }
9608f343b09SGreg Clayton 
9618f343b09SGreg Clayton         const uint32_t argc = command.GetArgumentCount();
9628f343b09SGreg Clayton 
9638f343b09SGreg Clayton         for (uint32_t i=0; i<argc; ++i)
9648f343b09SGreg Clayton         {
9658f343b09SGreg Clayton             Error error;
9668f343b09SGreg Clayton             const char *image_path = command.GetArgumentAtIndex(i);
9678f343b09SGreg Clayton             FileSpec image_spec (image_path, false);
9688f343b09SGreg Clayton             uint32_t image_token = process->LoadImage(image_spec, error);
9698f343b09SGreg Clayton             if (image_token != LLDB_INVALID_IMAGE_TOKEN)
9708f343b09SGreg Clayton             {
9718f343b09SGreg Clayton                 result.AppendMessageWithFormat ("Loading \"%s\"...ok\nImage %u loaded.\n", image_path, image_token);
9728f343b09SGreg Clayton                 result.SetStatus (eReturnStatusSuccessFinishResult);
9738f343b09SGreg Clayton             }
9748f343b09SGreg Clayton             else
9758f343b09SGreg Clayton             {
9768f343b09SGreg Clayton                 result.AppendErrorWithFormat ("failed to load '%s': %s", image_path, error.AsCString());
9778f343b09SGreg Clayton                 result.SetStatus (eReturnStatusFailed);
9788f343b09SGreg Clayton             }
9798f343b09SGreg Clayton         }
9808f343b09SGreg Clayton         return result.Succeeded();
9818f343b09SGreg Clayton     }
9828f343b09SGreg Clayton };
9838f343b09SGreg Clayton 
9848f343b09SGreg Clayton 
9858f343b09SGreg Clayton //-------------------------------------------------------------------------
9868f343b09SGreg Clayton // CommandObjectProcessUnload
9878f343b09SGreg Clayton //-------------------------------------------------------------------------
988bb9caf73SJim Ingham #pragma mark CommandObjectProcessUnload
9898f343b09SGreg Clayton 
9908f343b09SGreg Clayton class CommandObjectProcessUnload : public CommandObject
9918f343b09SGreg Clayton {
9928f343b09SGreg Clayton public:
9938f343b09SGreg Clayton 
9948f343b09SGreg Clayton     CommandObjectProcessUnload (CommandInterpreter &interpreter) :
9958f343b09SGreg Clayton         CommandObject (interpreter,
9968f343b09SGreg Clayton                        "process unload",
9978f343b09SGreg Clayton                        "Unload a shared library from the current process using the index returned by a previous call to \"process load\".",
9988f343b09SGreg Clayton                        "process unload <index>",
9998f343b09SGreg Clayton                        eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
10008f343b09SGreg Clayton     {
10018f343b09SGreg Clayton     }
10028f343b09SGreg Clayton 
10038f343b09SGreg Clayton     ~CommandObjectProcessUnload ()
10048f343b09SGreg Clayton     {
10058f343b09SGreg Clayton     }
10068f343b09SGreg Clayton 
10078f343b09SGreg Clayton     bool
10088f343b09SGreg Clayton     Execute (Args& command,
10098f343b09SGreg Clayton              CommandReturnObject &result)
10108f343b09SGreg Clayton     {
10118f343b09SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
10128f343b09SGreg Clayton         if (process == NULL)
10138f343b09SGreg Clayton         {
10148f343b09SGreg Clayton             result.AppendError ("must have a valid process in order to load a shared library");
10158f343b09SGreg Clayton             result.SetStatus (eReturnStatusFailed);
10168f343b09SGreg Clayton             return false;
10178f343b09SGreg Clayton         }
10188f343b09SGreg Clayton 
10198f343b09SGreg Clayton         const uint32_t argc = command.GetArgumentCount();
10208f343b09SGreg Clayton 
10218f343b09SGreg Clayton         for (uint32_t i=0; i<argc; ++i)
10228f343b09SGreg Clayton         {
10238f343b09SGreg Clayton             const char *image_token_cstr = command.GetArgumentAtIndex(i);
10248f343b09SGreg Clayton             uint32_t image_token = Args::StringToUInt32(image_token_cstr, LLDB_INVALID_IMAGE_TOKEN, 0);
10258f343b09SGreg Clayton             if (image_token == LLDB_INVALID_IMAGE_TOKEN)
10268f343b09SGreg Clayton             {
10278f343b09SGreg Clayton                 result.AppendErrorWithFormat ("invalid image index argument '%s'", image_token_cstr);
10288f343b09SGreg Clayton                 result.SetStatus (eReturnStatusFailed);
10298f343b09SGreg Clayton                 break;
10308f343b09SGreg Clayton             }
10318f343b09SGreg Clayton             else
10328f343b09SGreg Clayton             {
10338f343b09SGreg Clayton                 Error error (process->UnloadImage(image_token));
10348f343b09SGreg Clayton                 if (error.Success())
10358f343b09SGreg Clayton                 {
10368f343b09SGreg Clayton                     result.AppendMessageWithFormat ("Unloading shared library with index %u...ok\n", image_token);
10378f343b09SGreg Clayton                     result.SetStatus (eReturnStatusSuccessFinishResult);
10388f343b09SGreg Clayton                 }
10398f343b09SGreg Clayton                 else
10408f343b09SGreg Clayton                 {
10418f343b09SGreg Clayton                     result.AppendErrorWithFormat ("failed to unload image: %s", error.AsCString());
10428f343b09SGreg Clayton                     result.SetStatus (eReturnStatusFailed);
10438f343b09SGreg Clayton                     break;
10448f343b09SGreg Clayton                 }
10458f343b09SGreg Clayton             }
10468f343b09SGreg Clayton         }
10478f343b09SGreg Clayton         return result.Succeeded();
10488f343b09SGreg Clayton     }
10498f343b09SGreg Clayton };
10508f343b09SGreg Clayton 
10518f343b09SGreg Clayton //-------------------------------------------------------------------------
105230fdc8d8SChris Lattner // CommandObjectProcessSignal
105330fdc8d8SChris Lattner //-------------------------------------------------------------------------
1054bb9caf73SJim Ingham #pragma mark CommandObjectProcessSignal
105530fdc8d8SChris Lattner 
105630fdc8d8SChris Lattner class CommandObjectProcessSignal : public CommandObject
105730fdc8d8SChris Lattner {
105830fdc8d8SChris Lattner public:
105930fdc8d8SChris Lattner 
1060a7015092SGreg Clayton     CommandObjectProcessSignal (CommandInterpreter &interpreter) :
1061a7015092SGreg Clayton         CommandObject (interpreter,
1062a7015092SGreg Clayton                        "process signal",
1063e3d26315SCaroline Tice                        "Send a UNIX signal to the current process being debugged.",
1064405fe67fSCaroline Tice                        NULL)
106530fdc8d8SChris Lattner     {
1066405fe67fSCaroline Tice         CommandArgumentEntry arg;
1067405fe67fSCaroline Tice         CommandArgumentData signal_arg;
1068405fe67fSCaroline Tice 
1069405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
1070c0dbdfb6SCaroline Tice         signal_arg.arg_type = eArgTypeUnixSignal;
1071405fe67fSCaroline Tice         signal_arg.arg_repetition = eArgRepeatPlain;
1072405fe67fSCaroline Tice 
1073405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
1074405fe67fSCaroline Tice         arg.push_back (signal_arg);
1075405fe67fSCaroline Tice 
1076405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
1077405fe67fSCaroline Tice         m_arguments.push_back (arg);
107830fdc8d8SChris Lattner     }
107930fdc8d8SChris Lattner 
108030fdc8d8SChris Lattner     ~CommandObjectProcessSignal ()
108130fdc8d8SChris Lattner     {
108230fdc8d8SChris Lattner     }
108330fdc8d8SChris Lattner 
108430fdc8d8SChris Lattner     bool
1085a7015092SGreg Clayton     Execute (Args& command,
108630fdc8d8SChris Lattner              CommandReturnObject &result)
108730fdc8d8SChris Lattner     {
1088a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
108930fdc8d8SChris Lattner         if (process == NULL)
109030fdc8d8SChris Lattner         {
109130fdc8d8SChris Lattner             result.AppendError ("no process to signal");
109230fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
109330fdc8d8SChris Lattner             return false;
109430fdc8d8SChris Lattner         }
109530fdc8d8SChris Lattner 
109630fdc8d8SChris Lattner         if (command.GetArgumentCount() == 1)
109730fdc8d8SChris Lattner         {
1098237cd906SGreg Clayton             int signo = LLDB_INVALID_SIGNAL_NUMBER;
1099237cd906SGreg Clayton 
1100237cd906SGreg Clayton             const char *signal_name = command.GetArgumentAtIndex(0);
1101237cd906SGreg Clayton             if (::isxdigit (signal_name[0]))
1102237cd906SGreg Clayton                 signo = Args::StringToSInt32(signal_name, LLDB_INVALID_SIGNAL_NUMBER, 0);
1103237cd906SGreg Clayton             else
1104237cd906SGreg Clayton                 signo = process->GetUnixSignals().GetSignalNumberFromName (signal_name);
1105237cd906SGreg Clayton 
1106237cd906SGreg Clayton             if (signo == LLDB_INVALID_SIGNAL_NUMBER)
110730fdc8d8SChris Lattner             {
110830fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0));
110930fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
111030fdc8d8SChris Lattner             }
111130fdc8d8SChris Lattner             else
111230fdc8d8SChris Lattner             {
111330fdc8d8SChris Lattner                 Error error (process->Signal (signo));
111430fdc8d8SChris Lattner                 if (error.Success())
111530fdc8d8SChris Lattner                 {
111630fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusSuccessFinishResult);
111730fdc8d8SChris Lattner                 }
111830fdc8d8SChris Lattner                 else
111930fdc8d8SChris Lattner                 {
112030fdc8d8SChris Lattner                     result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString());
112130fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusFailed);
112230fdc8d8SChris Lattner                 }
112330fdc8d8SChris Lattner             }
112430fdc8d8SChris Lattner         }
112530fdc8d8SChris Lattner         else
112630fdc8d8SChris Lattner         {
112730fdc8d8SChris Lattner             result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: \n", m_cmd_name.c_str(),
112830fdc8d8SChris Lattner                                         m_cmd_syntax.c_str());
112930fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
113030fdc8d8SChris Lattner         }
113130fdc8d8SChris Lattner         return result.Succeeded();
113230fdc8d8SChris Lattner     }
113330fdc8d8SChris Lattner };
113430fdc8d8SChris Lattner 
113530fdc8d8SChris Lattner 
113630fdc8d8SChris Lattner //-------------------------------------------------------------------------
113730fdc8d8SChris Lattner // CommandObjectProcessInterrupt
113830fdc8d8SChris Lattner //-------------------------------------------------------------------------
1139bb9caf73SJim Ingham #pragma mark CommandObjectProcessInterrupt
114030fdc8d8SChris Lattner 
114130fdc8d8SChris Lattner class CommandObjectProcessInterrupt : public CommandObject
114230fdc8d8SChris Lattner {
114330fdc8d8SChris Lattner public:
114430fdc8d8SChris Lattner 
114530fdc8d8SChris Lattner 
1146a7015092SGreg Clayton     CommandObjectProcessInterrupt (CommandInterpreter &interpreter) :
1147a7015092SGreg Clayton     CommandObject (interpreter,
1148a7015092SGreg Clayton                    "process interrupt",
1149e3d26315SCaroline Tice                    "Interrupt the current process being debugged.",
115030fdc8d8SChris Lattner                    "process interrupt",
115130fdc8d8SChris Lattner                    eFlagProcessMustBeLaunched)
115230fdc8d8SChris Lattner     {
115330fdc8d8SChris Lattner     }
115430fdc8d8SChris Lattner 
115530fdc8d8SChris Lattner     ~CommandObjectProcessInterrupt ()
115630fdc8d8SChris Lattner     {
115730fdc8d8SChris Lattner     }
115830fdc8d8SChris Lattner 
115930fdc8d8SChris Lattner     bool
1160a7015092SGreg Clayton     Execute (Args& command,
116130fdc8d8SChris Lattner              CommandReturnObject &result)
116230fdc8d8SChris Lattner     {
1163a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
116430fdc8d8SChris Lattner         if (process == NULL)
116530fdc8d8SChris Lattner         {
116630fdc8d8SChris Lattner             result.AppendError ("no process to halt");
116730fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
116830fdc8d8SChris Lattner             return false;
116930fdc8d8SChris Lattner         }
117030fdc8d8SChris Lattner 
117130fdc8d8SChris Lattner         if (command.GetArgumentCount() == 0)
117230fdc8d8SChris Lattner         {
117330fdc8d8SChris Lattner             Error error(process->Halt ());
117430fdc8d8SChris Lattner             if (error.Success())
117530fdc8d8SChris Lattner             {
117630fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusSuccessFinishResult);
117730fdc8d8SChris Lattner 
117830fdc8d8SChris Lattner                 // Maybe we should add a "SuspendThreadPlans so we
117930fdc8d8SChris Lattner                 // can halt, and keep in place all the current thread plans.
118030fdc8d8SChris Lattner                 process->GetThreadList().DiscardThreadPlans();
118130fdc8d8SChris Lattner             }
118230fdc8d8SChris Lattner             else
118330fdc8d8SChris Lattner             {
118430fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString());
118530fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
118630fdc8d8SChris Lattner             }
118730fdc8d8SChris Lattner         }
118830fdc8d8SChris Lattner         else
118930fdc8d8SChris Lattner         {
119030fdc8d8SChris Lattner             result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
119130fdc8d8SChris Lattner                                         m_cmd_name.c_str(),
119230fdc8d8SChris Lattner                                         m_cmd_syntax.c_str());
119330fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
119430fdc8d8SChris Lattner         }
119530fdc8d8SChris Lattner         return result.Succeeded();
119630fdc8d8SChris Lattner     }
119730fdc8d8SChris Lattner };
119830fdc8d8SChris Lattner 
119930fdc8d8SChris Lattner //-------------------------------------------------------------------------
120030fdc8d8SChris Lattner // CommandObjectProcessKill
120130fdc8d8SChris Lattner //-------------------------------------------------------------------------
1202bb9caf73SJim Ingham #pragma mark CommandObjectProcessKill
120330fdc8d8SChris Lattner 
120430fdc8d8SChris Lattner class CommandObjectProcessKill : public CommandObject
120530fdc8d8SChris Lattner {
120630fdc8d8SChris Lattner public:
120730fdc8d8SChris Lattner 
1208a7015092SGreg Clayton     CommandObjectProcessKill (CommandInterpreter &interpreter) :
1209a7015092SGreg Clayton     CommandObject (interpreter,
1210a7015092SGreg Clayton                    "process kill",
1211e3d26315SCaroline Tice                    "Terminate the current process being debugged.",
121230fdc8d8SChris Lattner                    "process kill",
121330fdc8d8SChris Lattner                    eFlagProcessMustBeLaunched)
121430fdc8d8SChris Lattner     {
121530fdc8d8SChris Lattner     }
121630fdc8d8SChris Lattner 
121730fdc8d8SChris Lattner     ~CommandObjectProcessKill ()
121830fdc8d8SChris Lattner     {
121930fdc8d8SChris Lattner     }
122030fdc8d8SChris Lattner 
122130fdc8d8SChris Lattner     bool
1222a7015092SGreg Clayton     Execute (Args& command,
122330fdc8d8SChris Lattner              CommandReturnObject &result)
122430fdc8d8SChris Lattner     {
1225a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
122630fdc8d8SChris Lattner         if (process == NULL)
122730fdc8d8SChris Lattner         {
122830fdc8d8SChris Lattner             result.AppendError ("no process to kill");
122930fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
123030fdc8d8SChris Lattner             return false;
123130fdc8d8SChris Lattner         }
123230fdc8d8SChris Lattner 
123330fdc8d8SChris Lattner         if (command.GetArgumentCount() == 0)
123430fdc8d8SChris Lattner         {
123530fdc8d8SChris Lattner             Error error (process->Destroy());
123630fdc8d8SChris Lattner             if (error.Success())
123730fdc8d8SChris Lattner             {
123830fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusSuccessFinishResult);
123930fdc8d8SChris Lattner             }
124030fdc8d8SChris Lattner             else
124130fdc8d8SChris Lattner             {
124230fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString());
124330fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
124430fdc8d8SChris Lattner             }
124530fdc8d8SChris Lattner         }
124630fdc8d8SChris Lattner         else
124730fdc8d8SChris Lattner         {
124830fdc8d8SChris Lattner             result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
124930fdc8d8SChris Lattner                                         m_cmd_name.c_str(),
125030fdc8d8SChris Lattner                                         m_cmd_syntax.c_str());
125130fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
125230fdc8d8SChris Lattner         }
125330fdc8d8SChris Lattner         return result.Succeeded();
125430fdc8d8SChris Lattner     }
125530fdc8d8SChris Lattner };
125630fdc8d8SChris Lattner 
125730fdc8d8SChris Lattner //-------------------------------------------------------------------------
12584b9bea87SJim Ingham // CommandObjectProcessStatus
12594b9bea87SJim Ingham //-------------------------------------------------------------------------
1260bb9caf73SJim Ingham #pragma mark CommandObjectProcessStatus
1261bb9caf73SJim Ingham 
12624b9bea87SJim Ingham class CommandObjectProcessStatus : public CommandObject
12634b9bea87SJim Ingham {
12644b9bea87SJim Ingham public:
1265a7015092SGreg Clayton     CommandObjectProcessStatus (CommandInterpreter &interpreter) :
1266a7015092SGreg Clayton     CommandObject (interpreter,
1267a7015092SGreg Clayton                    "process status",
1268e3d26315SCaroline Tice                    "Show the current status and location of executing process.",
1269e3d26315SCaroline Tice                    "process status",
12704b9bea87SJim Ingham                    0)
12714b9bea87SJim Ingham     {
12724b9bea87SJim Ingham     }
12734b9bea87SJim Ingham 
12744b9bea87SJim Ingham     ~CommandObjectProcessStatus()
12754b9bea87SJim Ingham     {
12764b9bea87SJim Ingham     }
12774b9bea87SJim Ingham 
12784b9bea87SJim Ingham 
12794b9bea87SJim Ingham     bool
12804b9bea87SJim Ingham     Execute
12814b9bea87SJim Ingham     (
12824b9bea87SJim Ingham         Args& command,
12834b9bea87SJim Ingham         CommandReturnObject &result
12844b9bea87SJim Ingham     )
12854b9bea87SJim Ingham     {
12864b9bea87SJim Ingham         StreamString &output_stream = result.GetOutputStream();
12874b9bea87SJim Ingham         result.SetStatus (eReturnStatusSuccessFinishNoResult);
1288a7015092SGreg Clayton         ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
12894b9bea87SJim Ingham         if (exe_ctx.process)
12904b9bea87SJim Ingham         {
12914b9bea87SJim Ingham             const StateType state = exe_ctx.process->GetState();
12924b9bea87SJim Ingham             if (StateIsStoppedState(state))
12934b9bea87SJim Ingham             {
12944b9bea87SJim Ingham                 if (state == eStateExited)
12954b9bea87SJim Ingham                 {
12964b9bea87SJim Ingham                     int exit_status = exe_ctx.process->GetExitStatus();
12974b9bea87SJim Ingham                     const char *exit_description = exe_ctx.process->GetExitDescription();
12984b9bea87SJim Ingham                     output_stream.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n",
12994b9bea87SJim Ingham                                           exe_ctx.process->GetID(),
13004b9bea87SJim Ingham                                           exit_status,
13014b9bea87SJim Ingham                                           exit_status,
13024b9bea87SJim Ingham                                           exit_description ? exit_description : "");
13034b9bea87SJim Ingham                 }
13044b9bea87SJim Ingham                 else
13054b9bea87SJim Ingham                 {
13064b9bea87SJim Ingham                     output_stream.Printf ("Process %d %s\n", exe_ctx.process->GetID(), StateAsCString (state));
13074b9bea87SJim Ingham                     if (exe_ctx.thread == NULL)
13084b9bea87SJim Ingham                         exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
13094b9bea87SJim Ingham                     if (exe_ctx.thread != NULL)
13104b9bea87SJim Ingham                     {
1311a7015092SGreg Clayton                         DisplayThreadsInfo (m_interpreter, &exe_ctx, result, true, true);
13124b9bea87SJim Ingham                     }
13134b9bea87SJim Ingham                     else
13144b9bea87SJim Ingham                     {
13154b9bea87SJim Ingham                         result.AppendError ("No valid thread found in current process.");
13164b9bea87SJim Ingham                         result.SetStatus (eReturnStatusFailed);
13174b9bea87SJim Ingham                     }
13184b9bea87SJim Ingham                 }
13194b9bea87SJim Ingham             }
13204b9bea87SJim Ingham             else
13214b9bea87SJim Ingham             {
13224b9bea87SJim Ingham                 output_stream.Printf ("Process %d is running.\n",
13234b9bea87SJim Ingham                                           exe_ctx.process->GetID());
13244b9bea87SJim Ingham             }
13254b9bea87SJim Ingham         }
13264b9bea87SJim Ingham         else
13274b9bea87SJim Ingham         {
13284b9bea87SJim Ingham             result.AppendError ("No current location or status available.");
13294b9bea87SJim Ingham             result.SetStatus (eReturnStatusFailed);
13304b9bea87SJim Ingham         }
13314b9bea87SJim Ingham         return result.Succeeded();
13324b9bea87SJim Ingham     }
13334b9bea87SJim Ingham };
13344b9bea87SJim Ingham 
13354b9bea87SJim Ingham //-------------------------------------------------------------------------
133635731357SCaroline Tice // CommandObjectProcessHandle
133735731357SCaroline Tice //-------------------------------------------------------------------------
1338bb9caf73SJim Ingham #pragma mark CommandObjectProcessHandle
133935731357SCaroline Tice 
134035731357SCaroline Tice class CommandObjectProcessHandle : public CommandObject
134135731357SCaroline Tice {
134235731357SCaroline Tice public:
134335731357SCaroline Tice 
134435731357SCaroline Tice     class CommandOptions : public Options
134535731357SCaroline Tice     {
134635731357SCaroline Tice     public:
134735731357SCaroline Tice 
134835731357SCaroline Tice         CommandOptions () :
134935731357SCaroline Tice             Options ()
135035731357SCaroline Tice         {
135135731357SCaroline Tice             ResetOptionValues ();
135235731357SCaroline Tice         }
135335731357SCaroline Tice 
135435731357SCaroline Tice         ~CommandOptions ()
135535731357SCaroline Tice         {
135635731357SCaroline Tice         }
135735731357SCaroline Tice 
135835731357SCaroline Tice         Error
135935731357SCaroline Tice         SetOptionValue (int option_idx, const char *option_arg)
136035731357SCaroline Tice         {
136135731357SCaroline Tice             Error error;
136235731357SCaroline Tice             char short_option = (char) m_getopt_table[option_idx].val;
136335731357SCaroline Tice 
136435731357SCaroline Tice             switch (short_option)
136535731357SCaroline Tice             {
136635731357SCaroline Tice                 case 's':
136735731357SCaroline Tice                     stop = option_arg;
136835731357SCaroline Tice                     break;
136935731357SCaroline Tice                 case 'n':
137035731357SCaroline Tice                     notify = option_arg;
137135731357SCaroline Tice                     break;
137235731357SCaroline Tice                 case 'p':
137335731357SCaroline Tice                     pass = option_arg;
137435731357SCaroline Tice                     break;
137535731357SCaroline Tice                 default:
137635731357SCaroline Tice                     error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
137735731357SCaroline Tice                     break;
137835731357SCaroline Tice             }
137935731357SCaroline Tice             return error;
138035731357SCaroline Tice         }
138135731357SCaroline Tice 
138235731357SCaroline Tice         void
138335731357SCaroline Tice         ResetOptionValues ()
138435731357SCaroline Tice         {
138535731357SCaroline Tice             Options::ResetOptionValues();
138635731357SCaroline Tice             stop.clear();
138735731357SCaroline Tice             notify.clear();
138835731357SCaroline Tice             pass.clear();
138935731357SCaroline Tice         }
139035731357SCaroline Tice 
139135731357SCaroline Tice         const lldb::OptionDefinition*
139235731357SCaroline Tice         GetDefinitions ()
139335731357SCaroline Tice         {
139435731357SCaroline Tice             return g_option_table;
139535731357SCaroline Tice         }
139635731357SCaroline Tice 
139735731357SCaroline Tice         // Options table: Required for subclasses of Options.
139835731357SCaroline Tice 
139935731357SCaroline Tice         static lldb::OptionDefinition g_option_table[];
140035731357SCaroline Tice 
140135731357SCaroline Tice         // Instance variables to hold the values for command options.
140235731357SCaroline Tice 
140335731357SCaroline Tice         std::string stop;
140435731357SCaroline Tice         std::string notify;
140535731357SCaroline Tice         std::string pass;
140635731357SCaroline Tice     };
140735731357SCaroline Tice 
140835731357SCaroline Tice 
140935731357SCaroline Tice     CommandObjectProcessHandle (CommandInterpreter &interpreter) :
141035731357SCaroline Tice         CommandObject (interpreter,
141135731357SCaroline Tice                        "process handle",
141210ad7993SCaroline Tice                        "Show or update what the process and debugger should do with various signals received from the OS.",
141335731357SCaroline Tice                        NULL)
141435731357SCaroline Tice     {
141510ad7993SCaroline Tice         SetHelpLong ("If no signals are specified, update them all.  If no update option is specified, list the current values.\n");
141635731357SCaroline Tice         CommandArgumentEntry arg;
1417c0dbdfb6SCaroline Tice         CommandArgumentData signal_arg;
141835731357SCaroline Tice 
1419c0dbdfb6SCaroline Tice         signal_arg.arg_type = eArgTypeUnixSignal;
1420c0dbdfb6SCaroline Tice         signal_arg.arg_repetition = eArgRepeatStar;
142135731357SCaroline Tice 
1422c0dbdfb6SCaroline Tice         arg.push_back (signal_arg);
142335731357SCaroline Tice 
142435731357SCaroline Tice         m_arguments.push_back (arg);
142535731357SCaroline Tice     }
142635731357SCaroline Tice 
142735731357SCaroline Tice     ~CommandObjectProcessHandle ()
142835731357SCaroline Tice     {
142935731357SCaroline Tice     }
143035731357SCaroline Tice 
143135731357SCaroline Tice     Options *
143235731357SCaroline Tice     GetOptions ()
143335731357SCaroline Tice     {
143435731357SCaroline Tice         return &m_options;
143535731357SCaroline Tice     }
143635731357SCaroline Tice 
143735731357SCaroline Tice     bool
143810ad7993SCaroline Tice     VerifyCommandOptionValue (const std::string &option, int &real_value)
143935731357SCaroline Tice     {
144035731357SCaroline Tice         bool okay = true;
144135731357SCaroline Tice 
144210ad7993SCaroline Tice         bool success = false;
144310ad7993SCaroline Tice         bool tmp_value = Args::StringToBoolean (option.c_str(), false, &success);
144410ad7993SCaroline Tice 
144510ad7993SCaroline Tice         if (success && tmp_value)
144610ad7993SCaroline Tice             real_value = 1;
144710ad7993SCaroline Tice         else if (success && !tmp_value)
144810ad7993SCaroline Tice             real_value = 0;
144935731357SCaroline Tice         else
145035731357SCaroline Tice         {
145135731357SCaroline Tice             // If the value isn't 'true' or 'false', it had better be 0 or 1.
145210ad7993SCaroline Tice             real_value = Args::StringToUInt32 (option.c_str(), 3);
145310ad7993SCaroline Tice             if (real_value != 0 && real_value != 1)
145435731357SCaroline Tice                 okay = false;
145535731357SCaroline Tice         }
145635731357SCaroline Tice 
145735731357SCaroline Tice         return okay;
145835731357SCaroline Tice     }
145935731357SCaroline Tice 
146010ad7993SCaroline Tice     void
146110ad7993SCaroline Tice     PrintSignalHeader (Stream &str)
146210ad7993SCaroline Tice     {
146310ad7993SCaroline Tice         str.Printf ("NAME        PASS   STOP   NOTIFY\n");
146410ad7993SCaroline Tice         str.Printf ("==========  =====  =====  ======\n");
146510ad7993SCaroline Tice     }
146610ad7993SCaroline Tice 
146710ad7993SCaroline Tice     void
146810ad7993SCaroline Tice     PrintSignal (Stream &str, int32_t signo, const char *sig_name, UnixSignals &signals)
146910ad7993SCaroline Tice     {
147010ad7993SCaroline Tice         bool stop;
147110ad7993SCaroline Tice         bool suppress;
147210ad7993SCaroline Tice         bool notify;
147310ad7993SCaroline Tice 
147410ad7993SCaroline Tice         str.Printf ("%-10s  ", sig_name);
147510ad7993SCaroline Tice         if (signals.GetSignalInfo (signo, suppress, stop, notify))
147610ad7993SCaroline Tice         {
147710ad7993SCaroline Tice             bool pass = !suppress;
147810ad7993SCaroline Tice             str.Printf ("%s  %s  %s",
147910ad7993SCaroline Tice                         (pass ? "true " : "false"),
148010ad7993SCaroline Tice                         (stop ? "true " : "false"),
148110ad7993SCaroline Tice                         (notify ? "true " : "false"));
148210ad7993SCaroline Tice         }
148310ad7993SCaroline Tice         str.Printf ("\n");
148410ad7993SCaroline Tice     }
148510ad7993SCaroline Tice 
148610ad7993SCaroline Tice     void
148710ad7993SCaroline Tice     PrintSignalInformation (Stream &str, Args &signal_args, int num_valid_signals, UnixSignals &signals)
148810ad7993SCaroline Tice     {
148910ad7993SCaroline Tice         PrintSignalHeader (str);
149010ad7993SCaroline Tice 
149110ad7993SCaroline Tice         if (num_valid_signals > 0)
149210ad7993SCaroline Tice         {
149310ad7993SCaroline Tice             size_t num_args = signal_args.GetArgumentCount();
149410ad7993SCaroline Tice             for (size_t i = 0; i < num_args; ++i)
149510ad7993SCaroline Tice             {
149610ad7993SCaroline Tice                 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
149710ad7993SCaroline Tice                 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
149810ad7993SCaroline Tice                     PrintSignal (str, signo, signal_args.GetArgumentAtIndex (i), signals);
149910ad7993SCaroline Tice             }
150010ad7993SCaroline Tice         }
150110ad7993SCaroline Tice         else // Print info for ALL signals
150210ad7993SCaroline Tice         {
150310ad7993SCaroline Tice             int32_t signo = signals.GetFirstSignalNumber();
150410ad7993SCaroline Tice             while (signo != LLDB_INVALID_SIGNAL_NUMBER)
150510ad7993SCaroline Tice             {
150610ad7993SCaroline Tice                 PrintSignal (str, signo, signals.GetSignalAsCString (signo), signals);
150710ad7993SCaroline Tice                 signo = signals.GetNextSignalNumber (signo);
150810ad7993SCaroline Tice             }
150910ad7993SCaroline Tice         }
151010ad7993SCaroline Tice     }
151110ad7993SCaroline Tice 
151235731357SCaroline Tice     bool
151335731357SCaroline Tice     Execute (Args &signal_args, CommandReturnObject &result)
151435731357SCaroline Tice     {
151535731357SCaroline Tice         TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
151635731357SCaroline Tice 
151735731357SCaroline Tice         if (!target_sp)
151835731357SCaroline Tice         {
151935731357SCaroline Tice             result.AppendError ("No current target;"
152035731357SCaroline Tice                                 " cannot handle signals until you have a valid target and process.\n");
152135731357SCaroline Tice             result.SetStatus (eReturnStatusFailed);
152235731357SCaroline Tice             return false;
152335731357SCaroline Tice         }
152435731357SCaroline Tice 
152535731357SCaroline Tice         ProcessSP process_sp = target_sp->GetProcessSP();
152635731357SCaroline Tice 
152735731357SCaroline Tice         if (!process_sp)
152835731357SCaroline Tice         {
152935731357SCaroline Tice             result.AppendError ("No current process; cannot handle signals until you have a valid process.\n");
153035731357SCaroline Tice             result.SetStatus (eReturnStatusFailed);
153135731357SCaroline Tice             return false;
153235731357SCaroline Tice         }
153335731357SCaroline Tice 
153435731357SCaroline Tice         int stop_action = -1;   // -1 means leave the current setting alone
153535731357SCaroline Tice         int pass_action = -1;   // -1 means leave the current setting alone
153635731357SCaroline Tice         int notify_action = -1; // -1 means leave the current setting alone
153735731357SCaroline Tice 
153835731357SCaroline Tice         if (! m_options.stop.empty()
153910ad7993SCaroline Tice             && ! VerifyCommandOptionValue (m_options.stop, stop_action))
154035731357SCaroline Tice         {
154135731357SCaroline Tice             result.AppendError ("Invalid argument for command option --stop; must be true or false.\n");
154235731357SCaroline Tice             result.SetStatus (eReturnStatusFailed);
154335731357SCaroline Tice             return false;
154435731357SCaroline Tice         }
154535731357SCaroline Tice 
154635731357SCaroline Tice         if (! m_options.notify.empty()
154710ad7993SCaroline Tice             && ! VerifyCommandOptionValue (m_options.notify, notify_action))
154835731357SCaroline Tice         {
154935731357SCaroline Tice             result.AppendError ("Invalid argument for command option --notify; must be true or false.\n");
155035731357SCaroline Tice             result.SetStatus (eReturnStatusFailed);
155135731357SCaroline Tice             return false;
155235731357SCaroline Tice         }
155335731357SCaroline Tice 
155435731357SCaroline Tice         if (! m_options.pass.empty()
155510ad7993SCaroline Tice             && ! VerifyCommandOptionValue (m_options.pass, pass_action))
155635731357SCaroline Tice         {
155735731357SCaroline Tice             result.AppendError ("Invalid argument for command option --pass; must be true or false.\n");
155835731357SCaroline Tice             result.SetStatus (eReturnStatusFailed);
155935731357SCaroline Tice             return false;
156035731357SCaroline Tice         }
156135731357SCaroline Tice 
156235731357SCaroline Tice         size_t num_args = signal_args.GetArgumentCount();
156335731357SCaroline Tice         UnixSignals &signals = process_sp->GetUnixSignals();
156435731357SCaroline Tice         int num_signals_set = 0;
156535731357SCaroline Tice 
156610ad7993SCaroline Tice         if (num_args > 0)
156710ad7993SCaroline Tice         {
156835731357SCaroline Tice             for (size_t i = 0; i < num_args; ++i)
156935731357SCaroline Tice             {
157035731357SCaroline Tice                 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
157135731357SCaroline Tice                 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
157235731357SCaroline Tice                 {
157310ad7993SCaroline Tice                     // Casting the actions as bools here should be okay, because VerifyCommandOptionValue guarantees
157435731357SCaroline Tice                     // the value is either 0 or 1.
157535731357SCaroline Tice                     if (stop_action != -1)
157635731357SCaroline Tice                         signals.SetShouldStop (signo, (bool) stop_action);
157735731357SCaroline Tice                     if (pass_action != -1)
157835731357SCaroline Tice                     {
157910ad7993SCaroline Tice                         bool suppress = ! ((bool) pass_action);
158010ad7993SCaroline Tice                         signals.SetShouldSuppress (signo, suppress);
158135731357SCaroline Tice                     }
158235731357SCaroline Tice                     if (notify_action != -1)
158335731357SCaroline Tice                         signals.SetShouldNotify (signo, (bool) notify_action);
158435731357SCaroline Tice                     ++num_signals_set;
158535731357SCaroline Tice                 }
158635731357SCaroline Tice                 else
158735731357SCaroline Tice                 {
158835731357SCaroline Tice                     result.AppendErrorWithFormat ("Invalid signal name '%s'\n", signal_args.GetArgumentAtIndex (i));
158935731357SCaroline Tice                 }
159035731357SCaroline Tice             }
159110ad7993SCaroline Tice         }
159210ad7993SCaroline Tice         else
159310ad7993SCaroline Tice         {
159410ad7993SCaroline Tice             // No signal specified, if any command options were specified, update ALL signals.
159510ad7993SCaroline Tice             if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1))
159610ad7993SCaroline Tice             {
159710ad7993SCaroline Tice                 if (m_interpreter.Confirm ("Do you really want to update all the signals?", false))
159810ad7993SCaroline Tice                 {
159910ad7993SCaroline Tice                     int32_t signo = signals.GetFirstSignalNumber();
160010ad7993SCaroline Tice                     while (signo != LLDB_INVALID_SIGNAL_NUMBER)
160110ad7993SCaroline Tice                     {
160210ad7993SCaroline Tice                         if (notify_action != -1)
160310ad7993SCaroline Tice                             signals.SetShouldNotify (signo, (bool) notify_action);
160410ad7993SCaroline Tice                         if (stop_action != -1)
160510ad7993SCaroline Tice                             signals.SetShouldStop (signo, (bool) stop_action);
160610ad7993SCaroline Tice                         if (pass_action != -1)
160710ad7993SCaroline Tice                         {
160810ad7993SCaroline Tice                             bool suppress = ! ((bool) pass_action);
160910ad7993SCaroline Tice                             signals.SetShouldSuppress (signo, suppress);
161010ad7993SCaroline Tice                         }
161110ad7993SCaroline Tice                         signo = signals.GetNextSignalNumber (signo);
161210ad7993SCaroline Tice                     }
161310ad7993SCaroline Tice                 }
161410ad7993SCaroline Tice             }
161510ad7993SCaroline Tice         }
161610ad7993SCaroline Tice 
161710ad7993SCaroline Tice         PrintSignalInformation (result.GetOutputStream(), signal_args, num_signals_set, signals);
161835731357SCaroline Tice 
161935731357SCaroline Tice         if (num_signals_set > 0)
162035731357SCaroline Tice             result.SetStatus (eReturnStatusSuccessFinishNoResult);
162135731357SCaroline Tice         else
162235731357SCaroline Tice             result.SetStatus (eReturnStatusFailed);
162335731357SCaroline Tice 
162435731357SCaroline Tice         return result.Succeeded();
162535731357SCaroline Tice     }
162635731357SCaroline Tice 
162735731357SCaroline Tice protected:
162835731357SCaroline Tice 
162935731357SCaroline Tice     CommandOptions m_options;
163035731357SCaroline Tice };
163135731357SCaroline Tice 
163235731357SCaroline Tice lldb::OptionDefinition
163335731357SCaroline Tice CommandObjectProcessHandle::CommandOptions::g_option_table[] =
163435731357SCaroline Tice {
163535731357SCaroline 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." },
163635731357SCaroline 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." },
163735731357SCaroline Tice { LLDB_OPT_SET_1, false, "pass",  'p', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." },
163835731357SCaroline Tice { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
163935731357SCaroline Tice };
164035731357SCaroline Tice 
164135731357SCaroline Tice //-------------------------------------------------------------------------
164230fdc8d8SChris Lattner // CommandObjectMultiwordProcess
164330fdc8d8SChris Lattner //-------------------------------------------------------------------------
164430fdc8d8SChris Lattner 
16456611103cSGreg Clayton CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter &interpreter) :
1646a7015092SGreg Clayton     CommandObjectMultiword (interpreter,
1647a7015092SGreg Clayton                             "process",
164830fdc8d8SChris Lattner                             "A set of commands for operating on a process.",
164930fdc8d8SChris Lattner                             "process <subcommand> [<subcommand-options>]")
165030fdc8d8SChris Lattner {
1651a7015092SGreg Clayton     LoadSubCommand ("attach",      CommandObjectSP (new CommandObjectProcessAttach (interpreter)));
1652a7015092SGreg Clayton     LoadSubCommand ("launch",      CommandObjectSP (new CommandObjectProcessLaunch (interpreter)));
1653a7015092SGreg Clayton     LoadSubCommand ("continue",    CommandObjectSP (new CommandObjectProcessContinue (interpreter)));
1654a7015092SGreg Clayton     LoadSubCommand ("detach",      CommandObjectSP (new CommandObjectProcessDetach (interpreter)));
16558f343b09SGreg Clayton     LoadSubCommand ("load",        CommandObjectSP (new CommandObjectProcessLoad (interpreter)));
16568f343b09SGreg Clayton     LoadSubCommand ("unload",      CommandObjectSP (new CommandObjectProcessUnload (interpreter)));
1657a7015092SGreg Clayton     LoadSubCommand ("signal",      CommandObjectSP (new CommandObjectProcessSignal (interpreter)));
165835731357SCaroline Tice     LoadSubCommand ("handle",      CommandObjectSP (new CommandObjectProcessHandle (interpreter)));
1659a7015092SGreg Clayton     LoadSubCommand ("status",      CommandObjectSP (new CommandObjectProcessStatus (interpreter)));
1660a7015092SGreg Clayton     LoadSubCommand ("interrupt",   CommandObjectSP (new CommandObjectProcessInterrupt (interpreter)));
1661a7015092SGreg Clayton     LoadSubCommand ("kill",        CommandObjectSP (new CommandObjectProcessKill (interpreter)));
166230fdc8d8SChris Lattner }
166330fdc8d8SChris Lattner 
166430fdc8d8SChris Lattner CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess ()
166530fdc8d8SChris Lattner {
166630fdc8d8SChris Lattner }
166730fdc8d8SChris Lattner 
1668