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"
21e996fd30SGreg Clayton #include "CommandObjectThread.h"
227fb56d0aSGreg Clayton #include "lldb/Host/Host.h"
23e996fd30SGreg Clayton #include "lldb/Target/Platform.h"
2430fdc8d8SChris Lattner #include "lldb/Target/Process.h"
2530fdc8d8SChris Lattner #include "lldb/Target/Target.h"
2630fdc8d8SChris Lattner #include "lldb/Target/Thread.h"
2730fdc8d8SChris Lattner 
2830fdc8d8SChris Lattner using namespace lldb;
2930fdc8d8SChris Lattner using namespace lldb_private;
3030fdc8d8SChris Lattner 
3130fdc8d8SChris Lattner //-------------------------------------------------------------------------
3230fdc8d8SChris Lattner // CommandObjectProcessLaunch
3330fdc8d8SChris Lattner //-------------------------------------------------------------------------
34bb9caf73SJim Ingham #pragma mark CommandObjectProjectLaunch
3530fdc8d8SChris Lattner class CommandObjectProcessLaunch : public CommandObject
3630fdc8d8SChris Lattner {
3730fdc8d8SChris Lattner public:
3830fdc8d8SChris Lattner 
3930fdc8d8SChris Lattner     class CommandOptions : public Options
4030fdc8d8SChris Lattner     {
4130fdc8d8SChris Lattner     public:
4230fdc8d8SChris Lattner 
43*eb0103f2SGreg Clayton         CommandOptions (CommandInterpreter &interpreter) :
44*eb0103f2SGreg Clayton             Options(interpreter)
4530fdc8d8SChris Lattner         {
4630fdc8d8SChris Lattner             // Keep default values of all options in one place: ResetOptionValues ()
4730fdc8d8SChris Lattner             ResetOptionValues ();
4830fdc8d8SChris Lattner         }
4930fdc8d8SChris Lattner 
5030fdc8d8SChris Lattner         ~CommandOptions ()
5130fdc8d8SChris Lattner         {
5230fdc8d8SChris Lattner         }
5330fdc8d8SChris Lattner 
5430fdc8d8SChris Lattner         Error
5530fdc8d8SChris Lattner         SetOptionValue (int option_idx, const char *option_arg)
5630fdc8d8SChris Lattner         {
5730fdc8d8SChris Lattner             Error error;
5830fdc8d8SChris Lattner             char short_option = (char) m_getopt_table[option_idx].val;
5930fdc8d8SChris Lattner 
6030fdc8d8SChris Lattner             switch (short_option)
6130fdc8d8SChris Lattner             {
6230fdc8d8SChris Lattner                 case 's':   stop_at_entry = true;               break;
63bd82a5d2SGreg Clayton                 case 'e':   stderr_path.assign (option_arg);    break;
64bd82a5d2SGreg Clayton                 case 'i':   stdin_path.assign (option_arg);     break;
65bd82a5d2SGreg Clayton                 case 'o':   stdout_path.assign (option_arg);    break;
66bd82a5d2SGreg Clayton                 case 'p':   plugin_name.assign (option_arg);    break;
67f8da8631SCaroline Tice                 case 'n':   no_stdio = true;                    break;
68bd82a5d2SGreg Clayton                 case 'w':   working_dir.assign (option_arg);    break;
69913c4fa1SGreg Clayton                 case 't':
70913c4fa1SGreg Clayton                     if (option_arg && option_arg[0])
71913c4fa1SGreg Clayton                         tty_name.assign (option_arg);
72913c4fa1SGreg Clayton                     in_new_tty = true;
73913c4fa1SGreg Clayton                     break;
7430fdc8d8SChris Lattner                 default:
7530fdc8d8SChris Lattner                     error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
7630fdc8d8SChris Lattner                     break;
7730fdc8d8SChris Lattner 
7830fdc8d8SChris Lattner             }
7930fdc8d8SChris Lattner             return error;
8030fdc8d8SChris Lattner         }
8130fdc8d8SChris Lattner 
8230fdc8d8SChris Lattner         void
8330fdc8d8SChris Lattner         ResetOptionValues ()
8430fdc8d8SChris Lattner         {
8530fdc8d8SChris Lattner             stop_at_entry = false;
8619388cfcSGreg Clayton             in_new_tty = false;
87913c4fa1SGreg Clayton             tty_name.clear();
8830fdc8d8SChris Lattner             stdin_path.clear();
8930fdc8d8SChris Lattner             stdout_path.clear();
9030fdc8d8SChris Lattner             stderr_path.clear();
9130fdc8d8SChris Lattner             plugin_name.clear();
92bd82a5d2SGreg Clayton             working_dir.clear();
93f8da8631SCaroline Tice             no_stdio = false;
9430fdc8d8SChris Lattner         }
9530fdc8d8SChris Lattner 
96e0d378b3SGreg Clayton         const OptionDefinition*
9730fdc8d8SChris Lattner         GetDefinitions ()
9830fdc8d8SChris Lattner         {
9930fdc8d8SChris Lattner             return g_option_table;
10030fdc8d8SChris Lattner         }
10130fdc8d8SChris Lattner 
10230fdc8d8SChris Lattner         // Options table: Required for subclasses of Options.
10330fdc8d8SChris Lattner 
104e0d378b3SGreg Clayton         static OptionDefinition g_option_table[];
10530fdc8d8SChris Lattner 
10630fdc8d8SChris Lattner         // Instance variables to hold the values for command options.
10730fdc8d8SChris Lattner 
10830fdc8d8SChris Lattner         bool stop_at_entry;
10919388cfcSGreg Clayton         bool in_new_tty;
110f8da8631SCaroline Tice         bool no_stdio;
111913c4fa1SGreg Clayton         std::string tty_name;
11230fdc8d8SChris Lattner         std::string stderr_path;
11330fdc8d8SChris Lattner         std::string stdin_path;
11430fdc8d8SChris Lattner         std::string stdout_path;
11530fdc8d8SChris Lattner         std::string plugin_name;
116bd82a5d2SGreg Clayton         std::string working_dir;
11730fdc8d8SChris Lattner 
11830fdc8d8SChris Lattner     };
11930fdc8d8SChris Lattner 
120a7015092SGreg Clayton     CommandObjectProcessLaunch (CommandInterpreter &interpreter) :
121a7015092SGreg Clayton         CommandObject (interpreter,
122a7015092SGreg Clayton                        "process launch",
123e3d26315SCaroline Tice                        "Launch the executable in the debugger.",
124*eb0103f2SGreg Clayton                        NULL),
125*eb0103f2SGreg Clayton         m_options (interpreter)
12630fdc8d8SChris Lattner     {
127405fe67fSCaroline Tice         CommandArgumentEntry arg;
128405fe67fSCaroline Tice         CommandArgumentData run_args_arg;
129405fe67fSCaroline Tice 
130405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
131405fe67fSCaroline Tice         run_args_arg.arg_type = eArgTypeRunArgs;
132405fe67fSCaroline Tice         run_args_arg.arg_repetition = eArgRepeatOptional;
133405fe67fSCaroline Tice 
134405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
135405fe67fSCaroline Tice         arg.push_back (run_args_arg);
136405fe67fSCaroline Tice 
137405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
138405fe67fSCaroline Tice         m_arguments.push_back (arg);
13930fdc8d8SChris Lattner     }
14030fdc8d8SChris Lattner 
14130fdc8d8SChris Lattner 
14230fdc8d8SChris Lattner     ~CommandObjectProcessLaunch ()
14330fdc8d8SChris Lattner     {
14430fdc8d8SChris Lattner     }
14530fdc8d8SChris Lattner 
14630fdc8d8SChris Lattner     Options *
14730fdc8d8SChris Lattner     GetOptions ()
14830fdc8d8SChris Lattner     {
14930fdc8d8SChris Lattner         return &m_options;
15030fdc8d8SChris Lattner     }
15130fdc8d8SChris Lattner 
15230fdc8d8SChris Lattner     bool
15305faeb71SGreg Clayton     Execute (Args& launch_args, CommandReturnObject &result)
15430fdc8d8SChris Lattner     {
155a7015092SGreg Clayton         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
15630fdc8d8SChris Lattner 
15730fdc8d8SChris Lattner         if (target == NULL)
15830fdc8d8SChris Lattner         {
15930fdc8d8SChris Lattner             result.AppendError ("invalid target, set executable file using 'file' command");
16030fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
16130fdc8d8SChris Lattner             return false;
16230fdc8d8SChris Lattner         }
16330fdc8d8SChris Lattner 
16430fdc8d8SChris Lattner         // If our listener is NULL, users aren't allows to launch
16530fdc8d8SChris Lattner         char filename[PATH_MAX];
16619388cfcSGreg Clayton         const Module *exe_module = target->GetExecutableModule().get();
16771337622SGreg Clayton 
16871337622SGreg Clayton         if (exe_module == NULL)
16971337622SGreg Clayton         {
17071337622SGreg Clayton             result.AppendError ("no file in target, set executable file using 'file' command");
17171337622SGreg Clayton             result.SetStatus (eReturnStatusFailed);
17271337622SGreg Clayton             return false;
17371337622SGreg Clayton         }
17471337622SGreg Clayton 
17530fdc8d8SChris Lattner         exe_module->GetFileSpec().GetPath(filename, sizeof(filename));
17630fdc8d8SChris Lattner 
17771337622SGreg Clayton         StateType state = eStateInvalid;
178a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
17971337622SGreg Clayton         if (process)
18071337622SGreg Clayton         {
18171337622SGreg Clayton             state = process->GetState();
18271337622SGreg Clayton 
18371337622SGreg Clayton             if (process->IsAlive() && state != eStateConnected)
18430fdc8d8SChris Lattner             {
185513c26ceSGreg Clayton                 char message[1024];
186513c26ceSGreg Clayton                 if (process->GetState() == eStateAttaching)
187513c26ceSGreg Clayton                     ::strncpy (message, "There is a pending attach, abort it and launch a new process?", sizeof(message));
188513c26ceSGreg Clayton                 else
189513c26ceSGreg Clayton                     ::strncpy (message, "There is a running process, kill it and restart?", sizeof(message));
190513c26ceSGreg Clayton 
191513c26ceSGreg Clayton                 if (!m_interpreter.Confirm (message, true))
192bb9caf73SJim Ingham                 {
19330fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusFailed);
19430fdc8d8SChris Lattner                     return false;
19530fdc8d8SChris Lattner                 }
196bb9caf73SJim Ingham                 else
197bb9caf73SJim Ingham                 {
198bb9caf73SJim Ingham                     Error error (process->Destroy());
199bb9caf73SJim Ingham                     if (error.Success())
200bb9caf73SJim Ingham                     {
201bb9caf73SJim Ingham                         result.SetStatus (eReturnStatusSuccessFinishResult);
202bb9caf73SJim Ingham                     }
203bb9caf73SJim Ingham                     else
204bb9caf73SJim Ingham                     {
205bb9caf73SJim Ingham                         result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString());
206bb9caf73SJim Ingham                         result.SetStatus (eReturnStatusFailed);
207bb9caf73SJim Ingham                     }
208bb9caf73SJim Ingham                 }
209bb9caf73SJim Ingham             }
21071337622SGreg Clayton         }
21130fdc8d8SChris Lattner 
21271337622SGreg Clayton         if (state != eStateConnected)
21371337622SGreg Clayton         {
21430fdc8d8SChris Lattner             const char *plugin_name;
21530fdc8d8SChris Lattner             if (!m_options.plugin_name.empty())
21630fdc8d8SChris Lattner                 plugin_name = m_options.plugin_name.c_str();
21730fdc8d8SChris Lattner             else
21830fdc8d8SChris Lattner                 plugin_name = NULL;
21930fdc8d8SChris Lattner 
220a7015092SGreg Clayton             process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
221a7015092SGreg Clayton             if (process == NULL)
2223df9a8dfSCaroline Tice             {
22343a8c39bSCaroline Tice                 result.AppendErrorWithFormat ("Failed to find a process plugin for executable.\n");
224a7015092SGreg Clayton                 result.SetStatus (eReturnStatusFailed);
225a7015092SGreg Clayton                 return false;
2263df9a8dfSCaroline Tice             }
22771337622SGreg Clayton         }
22871337622SGreg Clayton 
2293df9a8dfSCaroline Tice 
230a7015092SGreg Clayton         // If no launch args were given on the command line, then use any that
231a7015092SGreg Clayton         // might have been set using the "run-args" set variable.
23230fdc8d8SChris Lattner         if (launch_args.GetArgumentCount() == 0)
23330fdc8d8SChris Lattner         {
234a7015092SGreg Clayton             if (process->GetRunArguments().GetArgumentCount() > 0)
235a7015092SGreg Clayton                 launch_args = process->GetRunArguments();
23630fdc8d8SChris Lattner         }
23730fdc8d8SChris Lattner 
23819388cfcSGreg Clayton         if (m_options.in_new_tty)
23919388cfcSGreg Clayton         {
24071337622SGreg Clayton             if (state == eStateConnected)
24171337622SGreg Clayton             {
24271337622SGreg Clayton                 result.AppendWarning("launch in tty option is ignored when launching through a remote connection");
24371337622SGreg Clayton                 m_options.in_new_tty = false;
24471337622SGreg Clayton             }
24571337622SGreg Clayton             else
24671337622SGreg Clayton             {
24719388cfcSGreg Clayton                 char exec_file_path[PATH_MAX];
24819388cfcSGreg Clayton                 if (exe_module->GetFileSpec().GetPath(exec_file_path, sizeof(exec_file_path)))
24919388cfcSGreg Clayton                 {
25019388cfcSGreg Clayton                     launch_args.InsertArgumentAtIndex(0, exec_file_path);
25119388cfcSGreg Clayton                 }
25219388cfcSGreg Clayton                 else
25319388cfcSGreg Clayton                 {
25419388cfcSGreg Clayton                     result.AppendError("invalid executable");
25519388cfcSGreg Clayton                     result.SetStatus (eReturnStatusFailed);
25619388cfcSGreg Clayton                     return false;
25719388cfcSGreg Clayton                 }
25819388cfcSGreg Clayton             }
25971337622SGreg Clayton         }
26019388cfcSGreg Clayton 
261a7015092SGreg Clayton         Args environment;
26230fdc8d8SChris Lattner 
263a7015092SGreg Clayton         process->GetEnvironmentAsArgs (environment);
264a7015092SGreg Clayton 
265a7015092SGreg Clayton         uint32_t launch_flags = eLaunchFlagNone;
266a7015092SGreg Clayton 
267a7015092SGreg Clayton         if (process->GetDisableASLR())
268a7015092SGreg Clayton             launch_flags |= eLaunchFlagDisableASLR;
269a7015092SGreg Clayton 
270f8da8631SCaroline Tice         if (m_options.no_stdio)
271f8da8631SCaroline Tice             launch_flags |= eLaunchFlagDisableSTDIO;
272f8da8631SCaroline Tice         else if (!m_options.in_new_tty
273f8da8631SCaroline Tice                  && m_options.stdin_path.empty()
274f8da8631SCaroline Tice                  && m_options.stdout_path.empty()
275f8da8631SCaroline Tice                  && m_options.stderr_path.empty())
276f8da8631SCaroline Tice         {
277f8da8631SCaroline Tice             // Only use the settings value if the user hasn't specified any options that would override it.
278f8da8631SCaroline Tice             if (process->GetDisableSTDIO())
279f8da8631SCaroline Tice                 launch_flags |= eLaunchFlagDisableSTDIO;
280f8da8631SCaroline Tice         }
281f8da8631SCaroline Tice 
28219388cfcSGreg Clayton         const char **inferior_argv = launch_args.GetArgumentCount() ? launch_args.GetConstArgumentVector() : NULL;
28319388cfcSGreg Clayton         const char **inferior_envp = environment.GetArgumentCount() ? environment.GetConstArgumentVector() : NULL;
28430fdc8d8SChris Lattner 
28519388cfcSGreg Clayton         Error error;
286bd82a5d2SGreg Clayton         const char *working_dir = NULL;
287bd82a5d2SGreg Clayton         if (!m_options.working_dir.empty())
288bd82a5d2SGreg Clayton             working_dir = m_options.working_dir.c_str();
28919388cfcSGreg Clayton 
29019388cfcSGreg Clayton         if (m_options.in_new_tty)
29119388cfcSGreg Clayton         {
29219388cfcSGreg Clayton 
293913c4fa1SGreg Clayton             lldb::pid_t pid = Host::LaunchInNewTerminal (m_options.tty_name.c_str(),
294913c4fa1SGreg Clayton                                                          inferior_argv,
29519388cfcSGreg Clayton                                                          inferior_envp,
296bd82a5d2SGreg Clayton                                                          working_dir,
29719388cfcSGreg Clayton                                                          &exe_module->GetArchitecture(),
29819388cfcSGreg Clayton                                                          true,
29919388cfcSGreg Clayton                                                          process->GetDisableASLR());
30019388cfcSGreg Clayton 
3013fcbed6bSGreg Clayton             if (pid != LLDB_INVALID_PROCESS_ID)
3023fcbed6bSGreg Clayton                 error = process->Attach (pid);
30319388cfcSGreg Clayton         }
30419388cfcSGreg Clayton         else
30519388cfcSGreg Clayton         {
30630fdc8d8SChris Lattner             const char * stdin_path = NULL;
30730fdc8d8SChris Lattner             const char * stdout_path = NULL;
30830fdc8d8SChris Lattner             const char * stderr_path = NULL;
30930fdc8d8SChris Lattner 
310a7015092SGreg Clayton             // Were any standard input/output/error paths given on the command line?
311a7015092SGreg Clayton             if (m_options.stdin_path.empty() &&
31230fdc8d8SChris Lattner                 m_options.stdout_path.empty() &&
313a7015092SGreg Clayton                 m_options.stderr_path.empty())
31430fdc8d8SChris Lattner             {
315a7015092SGreg Clayton                 // No standard file handles were given on the command line, check
316a7015092SGreg Clayton                 // with the process object in case they were give using "set settings"
317a7015092SGreg Clayton                 stdin_path = process->GetStandardInputPath();
318a7015092SGreg Clayton                 stdout_path = process->GetStandardOutputPath();
319a7015092SGreg Clayton                 stderr_path = process->GetStandardErrorPath();
320a7015092SGreg Clayton             }
321a7015092SGreg Clayton             else
322a7015092SGreg Clayton             {
323a7015092SGreg Clayton                 stdin_path = m_options.stdin_path.empty()  ? NULL : m_options.stdin_path.c_str();
324a7015092SGreg Clayton                 stdout_path = m_options.stdout_path.empty() ? NULL : m_options.stdout_path.c_str();
325a7015092SGreg Clayton                 stderr_path = m_options.stderr_path.empty() ? NULL : m_options.stderr_path.c_str();
32630fdc8d8SChris Lattner             }
32730fdc8d8SChris Lattner 
32819388cfcSGreg Clayton             error = process->Launch (inferior_argv,
32919388cfcSGreg Clayton                                      inferior_envp,
330f681b94fSGreg Clayton                                      launch_flags,
33130fdc8d8SChris Lattner                                      stdin_path,
33230fdc8d8SChris Lattner                                      stdout_path,
333bd82a5d2SGreg Clayton                                      stderr_path,
334bd82a5d2SGreg Clayton                                      working_dir);
33519388cfcSGreg Clayton         }
33630fdc8d8SChris Lattner 
33730fdc8d8SChris Lattner         if (error.Success())
33830fdc8d8SChris Lattner         {
33964195a2cSGreg Clayton             const char *archname = exe_module->GetArchitecture().GetArchitectureName();
34019388cfcSGreg Clayton 
34119388cfcSGreg Clayton             result.AppendMessageWithFormat ("Process %i launched: '%s' (%s)\n", process->GetID(), filename, archname);
34205faeb71SGreg Clayton             result.SetDidChangeProcessState (true);
34330fdc8d8SChris Lattner             if (m_options.stop_at_entry == false)
34430fdc8d8SChris Lattner             {
34505faeb71SGreg Clayton                 result.SetStatus (eReturnStatusSuccessContinuingNoResult);
34630fdc8d8SChris Lattner                 StateType state = process->WaitForProcessToStop (NULL);
34730fdc8d8SChris Lattner 
34830fdc8d8SChris Lattner                 if (state == eStateStopped)
34930fdc8d8SChris Lattner                 {
35005faeb71SGreg Clayton                     error = process->Resume();
35105faeb71SGreg Clayton                     if (error.Success())
35205faeb71SGreg Clayton                     {
35305faeb71SGreg Clayton                         bool synchronous_execution = m_interpreter.GetSynchronous ();
35430fdc8d8SChris Lattner                         if (synchronous_execution)
35530fdc8d8SChris Lattner                         {
35605faeb71SGreg Clayton                             state = process->WaitForProcessToStop (NULL);
35764195a2cSGreg Clayton                             if (!StateIsStoppedState(state))
358514487e8SGreg Clayton                             {
359514487e8SGreg Clayton                                 result.AppendErrorWithFormat ("Process isn't stopped: %s", StateAsCString(state));
360514487e8SGreg Clayton                             }
36130fdc8d8SChris Lattner                             result.SetDidChangeProcessState (true);
36205faeb71SGreg Clayton                             result.SetStatus (eReturnStatusSuccessFinishResult);
36305faeb71SGreg Clayton                         }
36405faeb71SGreg Clayton                         else
36505faeb71SGreg Clayton                         {
36605faeb71SGreg Clayton                             result.SetStatus (eReturnStatusSuccessContinuingNoResult);
36705faeb71SGreg Clayton                         }
36805faeb71SGreg Clayton                     }
369514487e8SGreg Clayton                     else
370514487e8SGreg Clayton                     {
371514487e8SGreg Clayton                         result.AppendErrorWithFormat ("Process resume at entry point failed: %s", error.AsCString());
372514487e8SGreg Clayton                         result.SetStatus (eReturnStatusFailed);
37330fdc8d8SChris Lattner                     }
37430fdc8d8SChris Lattner                 }
375514487e8SGreg Clayton                 else
376514487e8SGreg Clayton                 {
377514487e8SGreg Clayton                     result.AppendErrorWithFormat ("Initial process state wasn't stopped: %s", StateAsCString(state));
378514487e8SGreg Clayton                     result.SetStatus (eReturnStatusFailed);
379514487e8SGreg Clayton                 }
380514487e8SGreg Clayton             }
381514487e8SGreg Clayton         }
382514487e8SGreg Clayton         else
383514487e8SGreg Clayton         {
384514487e8SGreg Clayton             result.AppendErrorWithFormat ("Process launch failed: %s", error.AsCString());
385514487e8SGreg Clayton             result.SetStatus (eReturnStatusFailed);
38630fdc8d8SChris Lattner         }
38730fdc8d8SChris Lattner 
38830fdc8d8SChris Lattner         return result.Succeeded();
38930fdc8d8SChris Lattner     }
39030fdc8d8SChris Lattner 
391ebc09c36SJim Ingham     virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
392ebc09c36SJim Ingham     {
393ebc09c36SJim Ingham         // No repeat for "process launch"...
394ebc09c36SJim Ingham         return "";
395ebc09c36SJim Ingham     }
396ebc09c36SJim Ingham 
39730fdc8d8SChris Lattner protected:
39830fdc8d8SChris Lattner 
39930fdc8d8SChris Lattner     CommandOptions m_options;
40030fdc8d8SChris Lattner };
40130fdc8d8SChris Lattner 
40230fdc8d8SChris Lattner 
40319388cfcSGreg Clayton #define SET1 LLDB_OPT_SET_1
40419388cfcSGreg Clayton #define SET2 LLDB_OPT_SET_2
405f8da8631SCaroline Tice #define SET3 LLDB_OPT_SET_3
40619388cfcSGreg Clayton 
407e0d378b3SGreg Clayton OptionDefinition
40830fdc8d8SChris Lattner CommandObjectProcessLaunch::CommandOptions::g_option_table[] =
40930fdc8d8SChris Lattner {
410f8da8631SCaroline 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."},
41119388cfcSGreg Clayton { SET1              , false, "stdin",         'i', required_argument, NULL, 0, eArgTypePath,    "Redirect stdin for the process to <path>."},
41219388cfcSGreg Clayton { SET1              , false, "stdout",        'o', required_argument, NULL, 0, eArgTypePath,    "Redirect stdout for the process to <path>."},
41319388cfcSGreg Clayton { SET1              , false, "stderr",        'e', required_argument, NULL, 0, eArgTypePath,    "Redirect stderr for the process to <path>."},
414f8da8631SCaroline Tice { SET1 | SET2 | SET3, false, "plugin",        'p', required_argument, NULL, 0, eArgTypePlugin,  "Name of the process plugin you want to use."},
415913c4fa1SGreg 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."},
416f8da8631SCaroline Tice {               SET3, false, "no-stdio",      'n', no_argument,       NULL, 0, eArgTypeNone,    "Do not set up for terminal I/O to go to running process."},
417bd82a5d2SGreg Clayton { SET1 | SET2 | SET3, false, "working-dir",   'w', required_argument, NULL, 0, eArgTypePath,    "Set the current working directory to <path> when running the inferior."},
418deaab222SCaroline Tice { 0,                  false, NULL,             0,  0,                 NULL, 0, eArgTypeNone,    NULL }
41930fdc8d8SChris Lattner };
42030fdc8d8SChris Lattner 
42119388cfcSGreg Clayton #undef SET1
42219388cfcSGreg Clayton #undef SET2
423f8da8631SCaroline Tice #undef SET3
42430fdc8d8SChris Lattner 
42530fdc8d8SChris Lattner //-------------------------------------------------------------------------
42630fdc8d8SChris Lattner // CommandObjectProcessAttach
42730fdc8d8SChris Lattner //-------------------------------------------------------------------------
428bb9caf73SJim Ingham #pragma mark CommandObjectProcessAttach
42930fdc8d8SChris Lattner class CommandObjectProcessAttach : public CommandObject
43030fdc8d8SChris Lattner {
43130fdc8d8SChris Lattner public:
43230fdc8d8SChris Lattner 
43330fdc8d8SChris Lattner     class CommandOptions : public Options
43430fdc8d8SChris Lattner     {
43530fdc8d8SChris Lattner     public:
43630fdc8d8SChris Lattner 
437*eb0103f2SGreg Clayton         CommandOptions (CommandInterpreter &interpreter) :
438*eb0103f2SGreg Clayton             Options(interpreter)
43930fdc8d8SChris Lattner         {
44030fdc8d8SChris Lattner             // Keep default values of all options in one place: ResetOptionValues ()
44130fdc8d8SChris Lattner             ResetOptionValues ();
44230fdc8d8SChris Lattner         }
44330fdc8d8SChris Lattner 
44430fdc8d8SChris Lattner         ~CommandOptions ()
44530fdc8d8SChris Lattner         {
44630fdc8d8SChris Lattner         }
44730fdc8d8SChris Lattner 
44830fdc8d8SChris Lattner         Error
44930fdc8d8SChris Lattner         SetOptionValue (int option_idx, const char *option_arg)
45030fdc8d8SChris Lattner         {
45130fdc8d8SChris Lattner             Error error;
45230fdc8d8SChris Lattner             char short_option = (char) m_getopt_table[option_idx].val;
45330fdc8d8SChris Lattner             bool success = false;
45430fdc8d8SChris Lattner             switch (short_option)
45530fdc8d8SChris Lattner             {
45630fdc8d8SChris Lattner                 case 'p':
45730fdc8d8SChris Lattner                     pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success);
45830fdc8d8SChris Lattner                     if (!success || pid == LLDB_INVALID_PROCESS_ID)
45930fdc8d8SChris Lattner                     {
46030fdc8d8SChris Lattner                         error.SetErrorStringWithFormat("Invalid process ID '%s'.\n", option_arg);
46130fdc8d8SChris Lattner                     }
46230fdc8d8SChris Lattner                     break;
46330fdc8d8SChris Lattner 
46430fdc8d8SChris Lattner                 case 'P':
46530fdc8d8SChris Lattner                     plugin_name = option_arg;
46630fdc8d8SChris Lattner                     break;
46730fdc8d8SChris Lattner 
46830fdc8d8SChris Lattner                 case 'n':
46930fdc8d8SChris Lattner                     name.assign(option_arg);
47030fdc8d8SChris Lattner                     break;
47130fdc8d8SChris Lattner 
47230fdc8d8SChris Lattner                 case 'w':
47330fdc8d8SChris Lattner                     waitfor = true;
47430fdc8d8SChris Lattner                     break;
47530fdc8d8SChris Lattner 
47630fdc8d8SChris Lattner                 default:
47730fdc8d8SChris Lattner                     error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
47830fdc8d8SChris Lattner                     break;
47930fdc8d8SChris Lattner             }
48030fdc8d8SChris Lattner             return error;
48130fdc8d8SChris Lattner         }
48230fdc8d8SChris Lattner 
48330fdc8d8SChris Lattner         void
48430fdc8d8SChris Lattner         ResetOptionValues ()
48530fdc8d8SChris Lattner         {
48630fdc8d8SChris Lattner             pid = LLDB_INVALID_PROCESS_ID;
48730fdc8d8SChris Lattner             name.clear();
48830fdc8d8SChris Lattner             waitfor = false;
48930fdc8d8SChris Lattner         }
49030fdc8d8SChris Lattner 
491e0d378b3SGreg Clayton         const OptionDefinition*
49230fdc8d8SChris Lattner         GetDefinitions ()
49330fdc8d8SChris Lattner         {
49430fdc8d8SChris Lattner             return g_option_table;
49530fdc8d8SChris Lattner         }
49630fdc8d8SChris Lattner 
4975aee162fSJim Ingham         virtual bool
498*eb0103f2SGreg Clayton         HandleOptionArgumentCompletion (Args &input,
4995aee162fSJim Ingham                                         int cursor_index,
5005aee162fSJim Ingham                                         int char_pos,
5015aee162fSJim Ingham                                         OptionElementVector &opt_element_vector,
5025aee162fSJim Ingham                                         int opt_element_index,
5035aee162fSJim Ingham                                         int match_start_point,
5045aee162fSJim Ingham                                         int max_return_elements,
5055aee162fSJim Ingham                                         bool &word_complete,
5065aee162fSJim Ingham                                         StringList &matches)
5075aee162fSJim Ingham         {
5085aee162fSJim Ingham             int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos;
5095aee162fSJim Ingham             int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index;
5105aee162fSJim Ingham 
5115aee162fSJim Ingham             // We are only completing the name option for now...
5125aee162fSJim Ingham 
513e0d378b3SGreg Clayton             const OptionDefinition *opt_defs = GetDefinitions();
5145aee162fSJim Ingham             if (opt_defs[opt_defs_index].short_option == 'n')
5155aee162fSJim Ingham             {
5165aee162fSJim Ingham                 // Are we in the name?
5175aee162fSJim Ingham 
5185aee162fSJim Ingham                 // Look to see if there is a -P argument provided, and if so use that plugin, otherwise
5195aee162fSJim Ingham                 // use the default plugin.
5205aee162fSJim Ingham 
5215aee162fSJim Ingham                 const char *partial_name = NULL;
5225aee162fSJim Ingham                 partial_name = input.GetArgumentAtIndex(opt_arg_pos);
5235aee162fSJim Ingham 
524*eb0103f2SGreg Clayton                 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform ());
525e996fd30SGreg Clayton                 if (platform_sp)
5265aee162fSJim Ingham                 {
527e996fd30SGreg Clayton                     ProcessInfoList process_infos;
52832e0a750SGreg Clayton                     ProcessInfoMatch match_info;
52932e0a750SGreg Clayton                     if (partial_name)
53032e0a750SGreg Clayton                     {
53132e0a750SGreg Clayton                         match_info.GetProcessInfo().SetName(partial_name);
53232e0a750SGreg Clayton                         match_info.SetNameMatchType(eNameMatchStartsWith);
53332e0a750SGreg Clayton                     }
53432e0a750SGreg Clayton                     platform_sp->FindProcesses (match_info, process_infos);
535e996fd30SGreg Clayton                     const uint32_t num_matches = process_infos.GetSize();
536e996fd30SGreg Clayton                     if (num_matches > 0)
537e996fd30SGreg Clayton                     {
538e996fd30SGreg Clayton                         for (uint32_t i=0; i<num_matches; ++i)
539e996fd30SGreg Clayton                         {
540e996fd30SGreg Clayton                             matches.AppendString (process_infos.GetProcessNameAtIndex(i),
541e996fd30SGreg Clayton                                                   process_infos.GetProcessNameLengthAtIndex(i));
5425aee162fSJim Ingham                         }
5435aee162fSJim Ingham                     }
5445aee162fSJim Ingham                 }
5455aee162fSJim Ingham             }
5465aee162fSJim Ingham 
5475aee162fSJim Ingham             return false;
5485aee162fSJim Ingham         }
5495aee162fSJim Ingham 
55030fdc8d8SChris Lattner         // Options table: Required for subclasses of Options.
55130fdc8d8SChris Lattner 
552e0d378b3SGreg Clayton         static OptionDefinition g_option_table[];
55330fdc8d8SChris Lattner 
55430fdc8d8SChris Lattner         // Instance variables to hold the values for command options.
55530fdc8d8SChris Lattner 
55630fdc8d8SChris Lattner         lldb::pid_t pid;
55730fdc8d8SChris Lattner         std::string plugin_name;
55830fdc8d8SChris Lattner         std::string name;
55930fdc8d8SChris Lattner         bool waitfor;
56030fdc8d8SChris Lattner     };
56130fdc8d8SChris Lattner 
562a7015092SGreg Clayton     CommandObjectProcessAttach (CommandInterpreter &interpreter) :
563a7015092SGreg Clayton         CommandObject (interpreter,
564a7015092SGreg Clayton                        "process attach",
565e3d26315SCaroline Tice                        "Attach to a process.",
566*eb0103f2SGreg Clayton                        "process attach <cmd-options>"),
567*eb0103f2SGreg Clayton         m_options (interpreter)
5685aee162fSJim Ingham     {
5695aee162fSJim Ingham     }
5705aee162fSJim Ingham 
5715aee162fSJim Ingham     ~CommandObjectProcessAttach ()
5725aee162fSJim Ingham     {
5735aee162fSJim Ingham     }
5745aee162fSJim Ingham 
5755aee162fSJim Ingham     bool
576a7015092SGreg Clayton     Execute (Args& command,
5775aee162fSJim Ingham              CommandReturnObject &result)
5785aee162fSJim Ingham     {
579a7015092SGreg Clayton         Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
580bb3a283bSJim Ingham         bool synchronous_execution = m_interpreter.GetSynchronous ();
5815aee162fSJim Ingham 
582a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
58371337622SGreg Clayton         StateType state = eStateInvalid;
5845aee162fSJim Ingham         if (process)
5855aee162fSJim Ingham         {
58671337622SGreg Clayton             state = process->GetState();
58771337622SGreg Clayton             if (process->IsAlive() && state != eStateConnected)
5885aee162fSJim Ingham             {
5895aee162fSJim Ingham                 result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before attaching.\n",
5905aee162fSJim Ingham                                               process->GetID());
5915aee162fSJim Ingham                 result.SetStatus (eReturnStatusFailed);
5925aee162fSJim Ingham                 return false;
5935aee162fSJim Ingham             }
5945aee162fSJim Ingham         }
5955aee162fSJim Ingham 
5965aee162fSJim Ingham         if (target == NULL)
5975aee162fSJim Ingham         {
5985aee162fSJim Ingham             // If there isn't a current target create one.
5995aee162fSJim Ingham             TargetSP new_target_sp;
6005aee162fSJim Ingham             FileSpec emptyFileSpec;
6015aee162fSJim Ingham             ArchSpec emptyArchSpec;
6025aee162fSJim Ingham             Error error;
6035aee162fSJim Ingham 
604a7015092SGreg Clayton             error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(),
6055aee162fSJim Ingham                                                                               emptyFileSpec,
6065aee162fSJim Ingham                                                                               emptyArchSpec,
6075aee162fSJim Ingham                                                                               false,
6085aee162fSJim Ingham                                                                               new_target_sp);
6095aee162fSJim Ingham             target = new_target_sp.get();
6105aee162fSJim Ingham             if (target == NULL || error.Fail())
6115aee162fSJim Ingham             {
612b766a73dSGreg Clayton                 result.AppendError(error.AsCString("Error creating target"));
6135aee162fSJim Ingham                 return false;
6145aee162fSJim Ingham             }
615a7015092SGreg Clayton             m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target);
6165aee162fSJim Ingham         }
6175aee162fSJim Ingham 
6185aee162fSJim Ingham         // Record the old executable module, we want to issue a warning if the process of attaching changed the
6195aee162fSJim Ingham         // current executable (like somebody said "file foo" then attached to a PID whose executable was bar.)
6205aee162fSJim Ingham 
6215aee162fSJim Ingham         ModuleSP old_exec_module_sp = target->GetExecutableModule();
6225aee162fSJim Ingham         ArchSpec old_arch_spec = target->GetArchitecture();
6235aee162fSJim Ingham 
6245aee162fSJim Ingham         if (command.GetArgumentCount())
6255aee162fSJim Ingham         {
6265aee162fSJim Ingham             result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str());
6275aee162fSJim Ingham             result.SetStatus (eReturnStatusFailed);
6285aee162fSJim Ingham         }
6295aee162fSJim Ingham         else
6305aee162fSJim Ingham         {
63171337622SGreg Clayton             if (state != eStateConnected)
63271337622SGreg Clayton             {
6335aee162fSJim Ingham                 const char *plugin_name = NULL;
6345aee162fSJim Ingham 
6355aee162fSJim Ingham                 if (!m_options.plugin_name.empty())
6365aee162fSJim Ingham                     plugin_name = m_options.plugin_name.c_str();
6375aee162fSJim Ingham 
638a7015092SGreg Clayton                 process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
63971337622SGreg Clayton             }
6405aee162fSJim Ingham 
6415aee162fSJim Ingham             if (process)
6425aee162fSJim Ingham             {
6435aee162fSJim Ingham                 Error error;
6445aee162fSJim Ingham                 int attach_pid = m_options.pid;
6455aee162fSJim Ingham 
6463a0b9cdfSJim Ingham                 const char *wait_name = NULL;
6473a0b9cdfSJim Ingham 
6485aee162fSJim Ingham                 if (m_options.name.empty())
6495aee162fSJim Ingham                 {
6503a0b9cdfSJim Ingham                     if (old_exec_module_sp)
6513a0b9cdfSJim Ingham                     {
6523a0b9cdfSJim Ingham                         wait_name = old_exec_module_sp->GetFileSpec().GetFilename().AsCString();
6533a0b9cdfSJim Ingham                     }
6545aee162fSJim Ingham                 }
6555aee162fSJim Ingham                 else
6565aee162fSJim Ingham                 {
6573a0b9cdfSJim Ingham                     wait_name = m_options.name.c_str();
6583a0b9cdfSJim Ingham                 }
6593a0b9cdfSJim Ingham 
6603a0b9cdfSJim Ingham                 // If we are waiting for a process with this name to show up, do that first.
6613a0b9cdfSJim Ingham                 if (m_options.waitfor)
6623a0b9cdfSJim Ingham                 {
6633a0b9cdfSJim Ingham 
6643a0b9cdfSJim Ingham                     if (wait_name == NULL)
6653a0b9cdfSJim Ingham                     {
6663a0b9cdfSJim Ingham                         result.AppendError("Invalid arguments: must have a file loaded or supply a process name with the waitfor option.\n");
6673a0b9cdfSJim Ingham                         result.SetStatus (eReturnStatusFailed);
6683a0b9cdfSJim Ingham                         return false;
6693a0b9cdfSJim Ingham                     }
6703a0b9cdfSJim Ingham 
671513c26ceSGreg Clayton                     result.AppendMessageWithFormat("Waiting to attach to a process named \"%s\".\n", wait_name);
6723a0b9cdfSJim Ingham                     error = process->Attach (wait_name, m_options.waitfor);
6735aee162fSJim Ingham                     if (error.Success())
6745aee162fSJim Ingham                     {
6755aee162fSJim Ingham                         result.SetStatus (eReturnStatusSuccessContinuingNoResult);
6765aee162fSJim Ingham                     }
6775aee162fSJim Ingham                     else
6785aee162fSJim Ingham                     {
6795aee162fSJim Ingham                         result.AppendErrorWithFormat ("Waiting for a process to launch named '%s': %s\n",
6803a0b9cdfSJim Ingham                                                          wait_name,
6815aee162fSJim Ingham                                                          error.AsCString());
6825aee162fSJim Ingham                         result.SetStatus (eReturnStatusFailed);
6835aee162fSJim Ingham                         return false;
6845aee162fSJim Ingham                     }
685bb3a283bSJim Ingham                     // If we're synchronous, wait for the stopped event and report that.
686bb3a283bSJim Ingham                     // Otherwise just return.
687bb3a283bSJim Ingham                     // FIXME: in the async case it will now be possible to get to the command
688bb3a283bSJim Ingham                     // interpreter with a state eStateAttaching.  Make sure we handle that correctly.
689bb3a283bSJim Ingham                     if (synchronous_execution)
690bb3a283bSJim Ingham                     {
691bb3a283bSJim Ingham                         StateType state = process->WaitForProcessToStop (NULL);
692bb3a283bSJim Ingham 
693bb3a283bSJim Ingham                         result.SetDidChangeProcessState (true);
694bb3a283bSJim Ingham                         result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
695bb3a283bSJim Ingham                         result.SetStatus (eReturnStatusSuccessFinishNoResult);
696bb3a283bSJim Ingham                     }
697bb3a283bSJim Ingham                     else
698bb3a283bSJim Ingham                     {
699bb3a283bSJim Ingham                         result.SetDidChangeProcessState (true);
700bb3a283bSJim Ingham                         result.SetStatus (eReturnStatusSuccessFinishNoResult);
701bb3a283bSJim Ingham                     }
7025aee162fSJim Ingham                 }
7035aee162fSJim Ingham                 else
7045aee162fSJim Ingham                 {
7055aee162fSJim Ingham                     // If the process was specified by name look it up, so we can warn if there are multiple
7065aee162fSJim Ingham                     // processes with this pid.
7075aee162fSJim Ingham 
7083a0b9cdfSJim Ingham                     if (attach_pid == LLDB_INVALID_PROCESS_ID && wait_name != NULL)
7095aee162fSJim Ingham                     {
710e996fd30SGreg Clayton                         ProcessInfoList process_infos;
711ded470d3SGreg Clayton                         PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform ());
712e996fd30SGreg Clayton                         if (platform_sp)
713e996fd30SGreg Clayton                         {
71432e0a750SGreg Clayton                             ProcessInfoMatch match_info (wait_name, eNameMatchEquals);
71532e0a750SGreg Clayton                             platform_sp->FindProcesses (match_info, process_infos);
716e996fd30SGreg Clayton                         }
717e996fd30SGreg Clayton                         if (process_infos.GetSize() > 1)
7185aee162fSJim Ingham                         {
7193a0b9cdfSJim Ingham                             result.AppendErrorWithFormat("More than one process named %s\n", wait_name);
7205aee162fSJim Ingham                             result.SetStatus (eReturnStatusFailed);
7215aee162fSJim Ingham                             return false;
7225aee162fSJim Ingham                         }
723e996fd30SGreg Clayton                         else if (process_infos.GetSize() == 0)
7245aee162fSJim Ingham                         {
7253a0b9cdfSJim Ingham                             result.AppendErrorWithFormat("Could not find a process named %s\n", wait_name);
7265aee162fSJim Ingham                             result.SetStatus (eReturnStatusFailed);
7275aee162fSJim Ingham                             return false;
7285aee162fSJim Ingham                         }
7295aee162fSJim Ingham                         else
7305aee162fSJim Ingham                         {
731e996fd30SGreg Clayton                             attach_pid = process_infos.GetProcessIDAtIndex (0);
7325aee162fSJim Ingham                         }
7335aee162fSJim Ingham                     }
7345aee162fSJim Ingham 
7355aee162fSJim Ingham                     if (attach_pid != LLDB_INVALID_PROCESS_ID)
7365aee162fSJim Ingham                     {
7375aee162fSJim Ingham                         error = process->Attach (attach_pid);
7385aee162fSJim Ingham                         if (error.Success())
7395aee162fSJim Ingham                         {
7405aee162fSJim Ingham                             result.SetStatus (eReturnStatusSuccessContinuingNoResult);
7415aee162fSJim Ingham                         }
7425aee162fSJim Ingham                         else
7435aee162fSJim Ingham                         {
7445aee162fSJim Ingham                             result.AppendErrorWithFormat ("Attaching to process %i failed: %s.\n",
7455aee162fSJim Ingham                                                          attach_pid,
7465aee162fSJim Ingham                                                          error.AsCString());
7475aee162fSJim Ingham                             result.SetStatus (eReturnStatusFailed);
7485aee162fSJim Ingham                         }
749bb3a283bSJim Ingham                         // See comment for synchronous_execution above.
750bb3a283bSJim Ingham                         if (synchronous_execution)
751bb3a283bSJim Ingham                         {
752bb3a283bSJim Ingham                             StateType state = process->WaitForProcessToStop (NULL);
753bb3a283bSJim Ingham 
754bb3a283bSJim Ingham                             result.SetDidChangeProcessState (true);
755bb3a283bSJim Ingham                             result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
756bb3a283bSJim Ingham                             result.SetStatus (eReturnStatusSuccessFinishNoResult);
757bb3a283bSJim Ingham                         }
758bb3a283bSJim Ingham                         else
759bb3a283bSJim Ingham                         {
760bb3a283bSJim Ingham                             result.SetDidChangeProcessState (true);
761bb3a283bSJim Ingham                             result.SetStatus (eReturnStatusSuccessFinishNoResult);
762bb3a283bSJim Ingham                         }
7635aee162fSJim Ingham                     }
7645aee162fSJim Ingham                     else
7655aee162fSJim Ingham                     {
7665aee162fSJim Ingham                         result.AppendErrorWithFormat ("No PID specified for attach\n",
7675aee162fSJim Ingham                                                          attach_pid,
7685aee162fSJim Ingham                                                          error.AsCString());
7695aee162fSJim Ingham                         result.SetStatus (eReturnStatusFailed);
7705aee162fSJim Ingham 
7715aee162fSJim Ingham                     }
7725aee162fSJim Ingham                 }
7735aee162fSJim Ingham             }
7745aee162fSJim Ingham         }
7755aee162fSJim Ingham 
7765aee162fSJim Ingham         if (result.Succeeded())
7775aee162fSJim Ingham         {
7785aee162fSJim Ingham             // Okay, we're done.  Last step is to warn if the executable module has changed:
779513c26ceSGreg Clayton             char new_path[PATH_MAX];
7805aee162fSJim Ingham             if (!old_exec_module_sp)
7815aee162fSJim Ingham             {
782513c26ceSGreg Clayton                 // We might not have a module if we attached to a raw pid...
783513c26ceSGreg Clayton                 ModuleSP new_module_sp (target->GetExecutableModule());
784513c26ceSGreg Clayton                 if (new_module_sp)
785513c26ceSGreg Clayton                 {
786513c26ceSGreg Clayton                     new_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX);
787513c26ceSGreg Clayton                     result.AppendMessageWithFormat("Executable module set to \"%s\".\n", new_path);
788513c26ceSGreg Clayton                 }
7895aee162fSJim Ingham             }
7905aee162fSJim Ingham             else if (old_exec_module_sp->GetFileSpec() != target->GetExecutableModule()->GetFileSpec())
7915aee162fSJim Ingham             {
792513c26ceSGreg Clayton                 char old_path[PATH_MAX];
7935aee162fSJim Ingham 
7945aee162fSJim Ingham                 old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX);
7955aee162fSJim Ingham                 target->GetExecutableModule()->GetFileSpec().GetPath (new_path, PATH_MAX);
7965aee162fSJim Ingham 
7975aee162fSJim Ingham                 result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n",
7985aee162fSJim Ingham                                                     old_path, new_path);
7995aee162fSJim Ingham             }
8005aee162fSJim Ingham 
8015aee162fSJim Ingham             if (!old_arch_spec.IsValid())
8025aee162fSJim Ingham             {
80364195a2cSGreg Clayton                 result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().GetArchitectureName());
8045aee162fSJim Ingham             }
8055aee162fSJim Ingham             else if (old_arch_spec != target->GetArchitecture())
8065aee162fSJim Ingham             {
8075aee162fSJim Ingham                 result.AppendWarningWithFormat("Architecture changed from %s to %s.\n",
80864195a2cSGreg Clayton                                                 old_arch_spec.GetArchitectureName(), target->GetArchitecture().GetArchitectureName());
8095aee162fSJim Ingham             }
8105aee162fSJim Ingham         }
8115aee162fSJim Ingham         return result.Succeeded();
8125aee162fSJim Ingham     }
8135aee162fSJim Ingham 
8145aee162fSJim Ingham     Options *
8155aee162fSJim Ingham     GetOptions ()
8165aee162fSJim Ingham     {
8175aee162fSJim Ingham         return &m_options;
8185aee162fSJim Ingham     }
8195aee162fSJim Ingham 
82030fdc8d8SChris Lattner protected:
82130fdc8d8SChris Lattner 
82230fdc8d8SChris Lattner     CommandOptions m_options;
82330fdc8d8SChris Lattner };
82430fdc8d8SChris Lattner 
82530fdc8d8SChris Lattner 
826e0d378b3SGreg Clayton OptionDefinition
82730fdc8d8SChris Lattner CommandObjectProcessAttach::CommandOptions::g_option_table[] =
82830fdc8d8SChris Lattner {
829deaab222SCaroline Tice { LLDB_OPT_SET_ALL, false, "plugin", 'P', required_argument, NULL, 0, eArgTypePlugin,        "Name of the process plugin you want to use."},
830deaab222SCaroline Tice { LLDB_OPT_SET_1,   false, "pid",    'p', required_argument, NULL, 0, eArgTypePid,           "The process ID of an existing process to attach to."},
831deaab222SCaroline Tice { LLDB_OPT_SET_2,   false, "name",   'n', required_argument, NULL, 0, eArgTypeProcessName,  "The name of the process to attach to."},
832deaab222SCaroline Tice { LLDB_OPT_SET_2,   false, "waitfor",'w', no_argument,       NULL, 0, eArgTypeNone,              "Wait for the the process with <process-name> to launch."},
833deaab222SCaroline Tice { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
83430fdc8d8SChris Lattner };
83530fdc8d8SChris Lattner 
83630fdc8d8SChris Lattner //-------------------------------------------------------------------------
83730fdc8d8SChris Lattner // CommandObjectProcessContinue
83830fdc8d8SChris Lattner //-------------------------------------------------------------------------
839bb9caf73SJim Ingham #pragma mark CommandObjectProcessContinue
84030fdc8d8SChris Lattner 
84130fdc8d8SChris Lattner class CommandObjectProcessContinue : public CommandObject
84230fdc8d8SChris Lattner {
84330fdc8d8SChris Lattner public:
84430fdc8d8SChris Lattner 
845a7015092SGreg Clayton     CommandObjectProcessContinue (CommandInterpreter &interpreter) :
846a7015092SGreg Clayton         CommandObject (interpreter,
847a7015092SGreg Clayton                        "process continue",
848e3d26315SCaroline Tice                        "Continue execution of all threads in the current process.",
84930fdc8d8SChris Lattner                        "process continue",
85030fdc8d8SChris Lattner                        eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
85130fdc8d8SChris Lattner     {
85230fdc8d8SChris Lattner     }
85330fdc8d8SChris Lattner 
85430fdc8d8SChris Lattner 
85530fdc8d8SChris Lattner     ~CommandObjectProcessContinue ()
85630fdc8d8SChris Lattner     {
85730fdc8d8SChris Lattner     }
85830fdc8d8SChris Lattner 
85930fdc8d8SChris Lattner     bool
860a7015092SGreg Clayton     Execute (Args& command,
86130fdc8d8SChris Lattner              CommandReturnObject &result)
86230fdc8d8SChris Lattner     {
863a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
864a7015092SGreg Clayton         bool synchronous_execution = m_interpreter.GetSynchronous ();
86530fdc8d8SChris Lattner 
86630fdc8d8SChris Lattner         if (process == NULL)
86730fdc8d8SChris Lattner         {
86830fdc8d8SChris Lattner             result.AppendError ("no process to continue");
86930fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
87030fdc8d8SChris Lattner             return false;
87130fdc8d8SChris Lattner          }
87230fdc8d8SChris Lattner 
87330fdc8d8SChris Lattner         StateType state = process->GetState();
87430fdc8d8SChris Lattner         if (state == eStateStopped)
87530fdc8d8SChris Lattner         {
87630fdc8d8SChris Lattner             if (command.GetArgumentCount() != 0)
87730fdc8d8SChris Lattner             {
87830fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str());
87930fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
88030fdc8d8SChris Lattner                 return false;
88130fdc8d8SChris Lattner             }
88230fdc8d8SChris Lattner 
88330fdc8d8SChris Lattner             const uint32_t num_threads = process->GetThreadList().GetSize();
88430fdc8d8SChris Lattner 
88530fdc8d8SChris Lattner             // Set the actions that the threads should each take when resuming
88630fdc8d8SChris Lattner             for (uint32_t idx=0; idx<num_threads; ++idx)
88730fdc8d8SChris Lattner             {
88830fdc8d8SChris Lattner                 process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning);
88930fdc8d8SChris Lattner             }
89030fdc8d8SChris Lattner 
89130fdc8d8SChris Lattner             Error error(process->Resume());
89230fdc8d8SChris Lattner             if (error.Success())
89330fdc8d8SChris Lattner             {
89419388cfcSGreg Clayton                 result.AppendMessageWithFormat ("Process %i resuming\n", process->GetID());
89530fdc8d8SChris Lattner                 if (synchronous_execution)
89630fdc8d8SChris Lattner                 {
897b132097bSGreg Clayton                     state = process->WaitForProcessToStop (NULL);
89830fdc8d8SChris Lattner 
89930fdc8d8SChris Lattner                     result.SetDidChangeProcessState (true);
90030fdc8d8SChris Lattner                     result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state));
90130fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusSuccessFinishNoResult);
90230fdc8d8SChris Lattner                 }
90330fdc8d8SChris Lattner                 else
90430fdc8d8SChris Lattner                 {
90530fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusSuccessContinuingNoResult);
90630fdc8d8SChris Lattner                 }
90730fdc8d8SChris Lattner             }
90830fdc8d8SChris Lattner             else
90930fdc8d8SChris Lattner             {
91030fdc8d8SChris Lattner                 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString());
91130fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
91230fdc8d8SChris Lattner             }
91330fdc8d8SChris Lattner         }
91430fdc8d8SChris Lattner         else
91530fdc8d8SChris Lattner         {
91630fdc8d8SChris Lattner             result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n",
91730fdc8d8SChris Lattner                                          StateAsCString(state));
91830fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
91930fdc8d8SChris Lattner         }
92030fdc8d8SChris Lattner         return result.Succeeded();
92130fdc8d8SChris Lattner     }
92230fdc8d8SChris Lattner };
92330fdc8d8SChris Lattner 
92430fdc8d8SChris Lattner //-------------------------------------------------------------------------
92530fdc8d8SChris Lattner // CommandObjectProcessDetach
92630fdc8d8SChris Lattner //-------------------------------------------------------------------------
927bb9caf73SJim Ingham #pragma mark CommandObjectProcessDetach
92830fdc8d8SChris Lattner 
92930fdc8d8SChris Lattner class CommandObjectProcessDetach : public CommandObject
93030fdc8d8SChris Lattner {
93130fdc8d8SChris Lattner public:
93230fdc8d8SChris Lattner 
933a7015092SGreg Clayton     CommandObjectProcessDetach (CommandInterpreter &interpreter) :
934a7015092SGreg Clayton         CommandObject (interpreter,
935a7015092SGreg Clayton                        "process detach",
936e3d26315SCaroline Tice                        "Detach from the current process being debugged.",
93730fdc8d8SChris Lattner                        "process detach",
93830fdc8d8SChris Lattner                        eFlagProcessMustBeLaunched)
93930fdc8d8SChris Lattner     {
94030fdc8d8SChris Lattner     }
94130fdc8d8SChris Lattner 
94230fdc8d8SChris Lattner     ~CommandObjectProcessDetach ()
94330fdc8d8SChris Lattner     {
94430fdc8d8SChris Lattner     }
94530fdc8d8SChris Lattner 
94630fdc8d8SChris Lattner     bool
947a7015092SGreg Clayton     Execute (Args& command,
94830fdc8d8SChris Lattner              CommandReturnObject &result)
94930fdc8d8SChris Lattner     {
950a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
95130fdc8d8SChris Lattner         if (process == NULL)
95230fdc8d8SChris Lattner         {
95330fdc8d8SChris Lattner             result.AppendError ("must have a valid process in order to detach");
95430fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
95530fdc8d8SChris Lattner             return false;
95630fdc8d8SChris Lattner         }
95730fdc8d8SChris Lattner 
9585d7be2e6SCaroline Tice         result.AppendMessageWithFormat ("Detaching from process %i\n", process->GetID());
95930fdc8d8SChris Lattner         Error error (process->Detach());
96030fdc8d8SChris Lattner         if (error.Success())
96130fdc8d8SChris Lattner         {
96230fdc8d8SChris Lattner             result.SetStatus (eReturnStatusSuccessFinishResult);
96330fdc8d8SChris Lattner         }
96430fdc8d8SChris Lattner         else
96530fdc8d8SChris Lattner         {
96630fdc8d8SChris Lattner             result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString());
96730fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
96830fdc8d8SChris Lattner             return false;
96930fdc8d8SChris Lattner         }
97030fdc8d8SChris Lattner         return result.Succeeded();
97130fdc8d8SChris Lattner     }
97230fdc8d8SChris Lattner };
97330fdc8d8SChris Lattner 
97430fdc8d8SChris Lattner //-------------------------------------------------------------------------
975b766a73dSGreg Clayton // CommandObjectProcessConnect
976b766a73dSGreg Clayton //-------------------------------------------------------------------------
977b766a73dSGreg Clayton #pragma mark CommandObjectProcessConnect
978b766a73dSGreg Clayton 
979b766a73dSGreg Clayton class CommandObjectProcessConnect : public CommandObject
980b766a73dSGreg Clayton {
981b766a73dSGreg Clayton public:
982b766a73dSGreg Clayton 
983b766a73dSGreg Clayton     class CommandOptions : public Options
984b766a73dSGreg Clayton     {
985b766a73dSGreg Clayton     public:
986b766a73dSGreg Clayton 
987*eb0103f2SGreg Clayton         CommandOptions (CommandInterpreter &interpreter) :
988*eb0103f2SGreg Clayton             Options(interpreter)
989b766a73dSGreg Clayton         {
990b766a73dSGreg Clayton             // Keep default values of all options in one place: ResetOptionValues ()
991b766a73dSGreg Clayton             ResetOptionValues ();
992b766a73dSGreg Clayton         }
993b766a73dSGreg Clayton 
994b766a73dSGreg Clayton         ~CommandOptions ()
995b766a73dSGreg Clayton         {
996b766a73dSGreg Clayton         }
997b766a73dSGreg Clayton 
998b766a73dSGreg Clayton         Error
999b766a73dSGreg Clayton         SetOptionValue (int option_idx, const char *option_arg)
1000b766a73dSGreg Clayton         {
1001b766a73dSGreg Clayton             Error error;
1002b766a73dSGreg Clayton             char short_option = (char) m_getopt_table[option_idx].val;
1003b766a73dSGreg Clayton 
1004b766a73dSGreg Clayton             switch (short_option)
1005b766a73dSGreg Clayton             {
1006b766a73dSGreg Clayton             case 'p':
1007b766a73dSGreg Clayton                 plugin_name.assign (option_arg);
1008b766a73dSGreg Clayton                 break;
1009b766a73dSGreg Clayton 
1010b766a73dSGreg Clayton             default:
1011b766a73dSGreg Clayton                 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
1012b766a73dSGreg Clayton                 break;
1013b766a73dSGreg Clayton             }
1014b766a73dSGreg Clayton             return error;
1015b766a73dSGreg Clayton         }
1016b766a73dSGreg Clayton 
1017b766a73dSGreg Clayton         void
1018b766a73dSGreg Clayton         ResetOptionValues ()
1019b766a73dSGreg Clayton         {
1020b766a73dSGreg Clayton             plugin_name.clear();
1021b766a73dSGreg Clayton         }
1022b766a73dSGreg Clayton 
1023e0d378b3SGreg Clayton         const OptionDefinition*
1024b766a73dSGreg Clayton         GetDefinitions ()
1025b766a73dSGreg Clayton         {
1026b766a73dSGreg Clayton             return g_option_table;
1027b766a73dSGreg Clayton         }
1028b766a73dSGreg Clayton 
1029b766a73dSGreg Clayton         // Options table: Required for subclasses of Options.
1030b766a73dSGreg Clayton 
1031e0d378b3SGreg Clayton         static OptionDefinition g_option_table[];
1032b766a73dSGreg Clayton 
1033b766a73dSGreg Clayton         // Instance variables to hold the values for command options.
1034b766a73dSGreg Clayton 
1035b766a73dSGreg Clayton         std::string plugin_name;
1036b766a73dSGreg Clayton     };
1037b766a73dSGreg Clayton 
1038b766a73dSGreg Clayton     CommandObjectProcessConnect (CommandInterpreter &interpreter) :
1039b766a73dSGreg Clayton         CommandObject (interpreter,
1040b766a73dSGreg Clayton                        "process connect",
1041b766a73dSGreg Clayton                        "Connect to a remote debug service.",
1042b766a73dSGreg Clayton                        "process connect <remote-url>",
1043*eb0103f2SGreg Clayton                        0),
1044*eb0103f2SGreg Clayton         m_options (interpreter)
1045b766a73dSGreg Clayton     {
1046b766a73dSGreg Clayton     }
1047b766a73dSGreg Clayton 
1048b766a73dSGreg Clayton     ~CommandObjectProcessConnect ()
1049b766a73dSGreg Clayton     {
1050b766a73dSGreg Clayton     }
1051b766a73dSGreg Clayton 
1052b766a73dSGreg Clayton 
1053b766a73dSGreg Clayton     bool
1054b766a73dSGreg Clayton     Execute (Args& command,
1055b766a73dSGreg Clayton              CommandReturnObject &result)
1056b766a73dSGreg Clayton     {
1057b766a73dSGreg Clayton 
1058b766a73dSGreg Clayton         TargetSP target_sp (m_interpreter.GetDebugger().GetSelectedTarget());
1059b766a73dSGreg Clayton         Error error;
1060b766a73dSGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
1061b766a73dSGreg Clayton         if (process)
1062b766a73dSGreg Clayton         {
1063b766a73dSGreg Clayton             if (process->IsAlive())
1064b766a73dSGreg Clayton             {
1065b766a73dSGreg Clayton                 result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before connecting.\n",
1066b766a73dSGreg Clayton                                               process->GetID());
1067b766a73dSGreg Clayton                 result.SetStatus (eReturnStatusFailed);
1068b766a73dSGreg Clayton                 return false;
1069b766a73dSGreg Clayton             }
1070b766a73dSGreg Clayton         }
1071b766a73dSGreg Clayton 
1072b766a73dSGreg Clayton         if (!target_sp)
1073b766a73dSGreg Clayton         {
1074b766a73dSGreg Clayton             // If there isn't a current target create one.
1075b766a73dSGreg Clayton             FileSpec emptyFileSpec;
1076b766a73dSGreg Clayton             ArchSpec emptyArchSpec;
1077b766a73dSGreg Clayton 
1078b766a73dSGreg Clayton             error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(),
1079b766a73dSGreg Clayton                                                                               emptyFileSpec,
1080b766a73dSGreg Clayton                                                                               emptyArchSpec,
1081b766a73dSGreg Clayton                                                                               false,
1082b766a73dSGreg Clayton                                                                               target_sp);
1083b766a73dSGreg Clayton             if (!target_sp || error.Fail())
1084b766a73dSGreg Clayton             {
1085b766a73dSGreg Clayton                 result.AppendError(error.AsCString("Error creating target"));
1086b766a73dSGreg Clayton                 result.SetStatus (eReturnStatusFailed);
1087b766a73dSGreg Clayton                 return false;
1088b766a73dSGreg Clayton             }
1089b766a73dSGreg Clayton             m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target_sp.get());
1090b766a73dSGreg Clayton         }
1091b766a73dSGreg Clayton 
1092b766a73dSGreg Clayton         if (command.GetArgumentCount() == 1)
1093b766a73dSGreg Clayton         {
1094b766a73dSGreg Clayton             const char *plugin_name = NULL;
1095b766a73dSGreg Clayton             if (!m_options.plugin_name.empty())
1096b766a73dSGreg Clayton                 plugin_name = m_options.plugin_name.c_str();
1097b766a73dSGreg Clayton 
1098b766a73dSGreg Clayton             const char *remote_url = command.GetArgumentAtIndex(0);
1099b766a73dSGreg Clayton             process = target_sp->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get();
1100b766a73dSGreg Clayton 
1101b766a73dSGreg Clayton             if (process)
1102b766a73dSGreg Clayton             {
1103b766a73dSGreg Clayton                 error = process->ConnectRemote (remote_url);
1104b766a73dSGreg Clayton 
1105b766a73dSGreg Clayton                 if (error.Fail())
1106b766a73dSGreg Clayton                 {
1107b766a73dSGreg Clayton                     result.AppendError(error.AsCString("Remote connect failed"));
1108b766a73dSGreg Clayton                     result.SetStatus (eReturnStatusFailed);
1109b766a73dSGreg Clayton                     return false;
1110b766a73dSGreg Clayton                 }
1111b766a73dSGreg Clayton             }
1112b766a73dSGreg Clayton             else
1113b766a73dSGreg Clayton             {
1114b766a73dSGreg Clayton                 result.AppendErrorWithFormat ("Unable to find process plug-in for remote URL '%s'.\nPlease specify a process plug-in name with the --plugin option, or specify an object file using the \"file\" command: \n",
1115b766a73dSGreg Clayton                                               m_cmd_name.c_str(),
1116b766a73dSGreg Clayton                                               m_cmd_syntax.c_str());
1117b766a73dSGreg Clayton                 result.SetStatus (eReturnStatusFailed);
1118b766a73dSGreg Clayton             }
1119b766a73dSGreg Clayton         }
1120b766a73dSGreg Clayton         else
1121b766a73dSGreg Clayton         {
1122b766a73dSGreg Clayton             result.AppendErrorWithFormat ("'%s' takes exactly one argument:\nUsage: \n",
1123b766a73dSGreg Clayton                                           m_cmd_name.c_str(),
1124b766a73dSGreg Clayton                                           m_cmd_syntax.c_str());
1125b766a73dSGreg Clayton             result.SetStatus (eReturnStatusFailed);
1126b766a73dSGreg Clayton         }
1127b766a73dSGreg Clayton         return result.Succeeded();
1128b766a73dSGreg Clayton     }
1129b766a73dSGreg Clayton 
1130b766a73dSGreg Clayton     Options *
1131b766a73dSGreg Clayton     GetOptions ()
1132b766a73dSGreg Clayton     {
1133b766a73dSGreg Clayton         return &m_options;
1134b766a73dSGreg Clayton     }
1135b766a73dSGreg Clayton 
1136b766a73dSGreg Clayton protected:
1137b766a73dSGreg Clayton 
1138b766a73dSGreg Clayton     CommandOptions m_options;
1139b766a73dSGreg Clayton };
1140b766a73dSGreg Clayton 
1141b766a73dSGreg Clayton 
1142e0d378b3SGreg Clayton OptionDefinition
1143b766a73dSGreg Clayton CommandObjectProcessConnect::CommandOptions::g_option_table[] =
1144b766a73dSGreg Clayton {
1145b766a73dSGreg Clayton     { LLDB_OPT_SET_ALL, false, "plugin", 'p', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."},
1146b766a73dSGreg Clayton     { 0,                false, NULL,      0 , 0,                 NULL, 0, eArgTypeNone,   NULL }
1147b766a73dSGreg Clayton };
1148b766a73dSGreg Clayton 
1149b766a73dSGreg Clayton //-------------------------------------------------------------------------
11508f343b09SGreg Clayton // CommandObjectProcessLoad
11518f343b09SGreg Clayton //-------------------------------------------------------------------------
1152bb9caf73SJim Ingham #pragma mark CommandObjectProcessLoad
11538f343b09SGreg Clayton 
11548f343b09SGreg Clayton class CommandObjectProcessLoad : public CommandObject
11558f343b09SGreg Clayton {
11568f343b09SGreg Clayton public:
11578f343b09SGreg Clayton 
11588f343b09SGreg Clayton     CommandObjectProcessLoad (CommandInterpreter &interpreter) :
11598f343b09SGreg Clayton         CommandObject (interpreter,
11608f343b09SGreg Clayton                        "process load",
11618f343b09SGreg Clayton                        "Load a shared library into the current process.",
11628f343b09SGreg Clayton                        "process load <filename> [<filename> ...]",
11638f343b09SGreg Clayton                        eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
11648f343b09SGreg Clayton     {
11658f343b09SGreg Clayton     }
11668f343b09SGreg Clayton 
11678f343b09SGreg Clayton     ~CommandObjectProcessLoad ()
11688f343b09SGreg Clayton     {
11698f343b09SGreg Clayton     }
11708f343b09SGreg Clayton 
11718f343b09SGreg Clayton     bool
11728f343b09SGreg Clayton     Execute (Args& command,
11738f343b09SGreg Clayton              CommandReturnObject &result)
11748f343b09SGreg Clayton     {
11758f343b09SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
11768f343b09SGreg Clayton         if (process == NULL)
11778f343b09SGreg Clayton         {
11788f343b09SGreg Clayton             result.AppendError ("must have a valid process in order to load a shared library");
11798f343b09SGreg Clayton             result.SetStatus (eReturnStatusFailed);
11808f343b09SGreg Clayton             return false;
11818f343b09SGreg Clayton         }
11828f343b09SGreg Clayton 
11838f343b09SGreg Clayton         const uint32_t argc = command.GetArgumentCount();
11848f343b09SGreg Clayton 
11858f343b09SGreg Clayton         for (uint32_t i=0; i<argc; ++i)
11868f343b09SGreg Clayton         {
11878f343b09SGreg Clayton             Error error;
11888f343b09SGreg Clayton             const char *image_path = command.GetArgumentAtIndex(i);
11898f343b09SGreg Clayton             FileSpec image_spec (image_path, false);
11908f343b09SGreg Clayton             uint32_t image_token = process->LoadImage(image_spec, error);
11918f343b09SGreg Clayton             if (image_token != LLDB_INVALID_IMAGE_TOKEN)
11928f343b09SGreg Clayton             {
11938f343b09SGreg Clayton                 result.AppendMessageWithFormat ("Loading \"%s\"...ok\nImage %u loaded.\n", image_path, image_token);
11948f343b09SGreg Clayton                 result.SetStatus (eReturnStatusSuccessFinishResult);
11958f343b09SGreg Clayton             }
11968f343b09SGreg Clayton             else
11978f343b09SGreg Clayton             {
11988f343b09SGreg Clayton                 result.AppendErrorWithFormat ("failed to load '%s': %s", image_path, error.AsCString());
11998f343b09SGreg Clayton                 result.SetStatus (eReturnStatusFailed);
12008f343b09SGreg Clayton             }
12018f343b09SGreg Clayton         }
12028f343b09SGreg Clayton         return result.Succeeded();
12038f343b09SGreg Clayton     }
12048f343b09SGreg Clayton };
12058f343b09SGreg Clayton 
12068f343b09SGreg Clayton 
12078f343b09SGreg Clayton //-------------------------------------------------------------------------
12088f343b09SGreg Clayton // CommandObjectProcessUnload
12098f343b09SGreg Clayton //-------------------------------------------------------------------------
1210bb9caf73SJim Ingham #pragma mark CommandObjectProcessUnload
12118f343b09SGreg Clayton 
12128f343b09SGreg Clayton class CommandObjectProcessUnload : public CommandObject
12138f343b09SGreg Clayton {
12148f343b09SGreg Clayton public:
12158f343b09SGreg Clayton 
12168f343b09SGreg Clayton     CommandObjectProcessUnload (CommandInterpreter &interpreter) :
12178f343b09SGreg Clayton         CommandObject (interpreter,
12188f343b09SGreg Clayton                        "process unload",
12198f343b09SGreg Clayton                        "Unload a shared library from the current process using the index returned by a previous call to \"process load\".",
12208f343b09SGreg Clayton                        "process unload <index>",
12218f343b09SGreg Clayton                        eFlagProcessMustBeLaunched | eFlagProcessMustBePaused)
12228f343b09SGreg Clayton     {
12238f343b09SGreg Clayton     }
12248f343b09SGreg Clayton 
12258f343b09SGreg Clayton     ~CommandObjectProcessUnload ()
12268f343b09SGreg Clayton     {
12278f343b09SGreg Clayton     }
12288f343b09SGreg Clayton 
12298f343b09SGreg Clayton     bool
12308f343b09SGreg Clayton     Execute (Args& command,
12318f343b09SGreg Clayton              CommandReturnObject &result)
12328f343b09SGreg Clayton     {
12338f343b09SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
12348f343b09SGreg Clayton         if (process == NULL)
12358f343b09SGreg Clayton         {
12368f343b09SGreg Clayton             result.AppendError ("must have a valid process in order to load a shared library");
12378f343b09SGreg Clayton             result.SetStatus (eReturnStatusFailed);
12388f343b09SGreg Clayton             return false;
12398f343b09SGreg Clayton         }
12408f343b09SGreg Clayton 
12418f343b09SGreg Clayton         const uint32_t argc = command.GetArgumentCount();
12428f343b09SGreg Clayton 
12438f343b09SGreg Clayton         for (uint32_t i=0; i<argc; ++i)
12448f343b09SGreg Clayton         {
12458f343b09SGreg Clayton             const char *image_token_cstr = command.GetArgumentAtIndex(i);
12468f343b09SGreg Clayton             uint32_t image_token = Args::StringToUInt32(image_token_cstr, LLDB_INVALID_IMAGE_TOKEN, 0);
12478f343b09SGreg Clayton             if (image_token == LLDB_INVALID_IMAGE_TOKEN)
12488f343b09SGreg Clayton             {
12498f343b09SGreg Clayton                 result.AppendErrorWithFormat ("invalid image index argument '%s'", image_token_cstr);
12508f343b09SGreg Clayton                 result.SetStatus (eReturnStatusFailed);
12518f343b09SGreg Clayton                 break;
12528f343b09SGreg Clayton             }
12538f343b09SGreg Clayton             else
12548f343b09SGreg Clayton             {
12558f343b09SGreg Clayton                 Error error (process->UnloadImage(image_token));
12568f343b09SGreg Clayton                 if (error.Success())
12578f343b09SGreg Clayton                 {
12588f343b09SGreg Clayton                     result.AppendMessageWithFormat ("Unloading shared library with index %u...ok\n", image_token);
12598f343b09SGreg Clayton                     result.SetStatus (eReturnStatusSuccessFinishResult);
12608f343b09SGreg Clayton                 }
12618f343b09SGreg Clayton                 else
12628f343b09SGreg Clayton                 {
12638f343b09SGreg Clayton                     result.AppendErrorWithFormat ("failed to unload image: %s", error.AsCString());
12648f343b09SGreg Clayton                     result.SetStatus (eReturnStatusFailed);
12658f343b09SGreg Clayton                     break;
12668f343b09SGreg Clayton                 }
12678f343b09SGreg Clayton             }
12688f343b09SGreg Clayton         }
12698f343b09SGreg Clayton         return result.Succeeded();
12708f343b09SGreg Clayton     }
12718f343b09SGreg Clayton };
12728f343b09SGreg Clayton 
12738f343b09SGreg Clayton //-------------------------------------------------------------------------
127430fdc8d8SChris Lattner // CommandObjectProcessSignal
127530fdc8d8SChris Lattner //-------------------------------------------------------------------------
1276bb9caf73SJim Ingham #pragma mark CommandObjectProcessSignal
127730fdc8d8SChris Lattner 
127830fdc8d8SChris Lattner class CommandObjectProcessSignal : public CommandObject
127930fdc8d8SChris Lattner {
128030fdc8d8SChris Lattner public:
128130fdc8d8SChris Lattner 
1282a7015092SGreg Clayton     CommandObjectProcessSignal (CommandInterpreter &interpreter) :
1283a7015092SGreg Clayton         CommandObject (interpreter,
1284a7015092SGreg Clayton                        "process signal",
1285e3d26315SCaroline Tice                        "Send a UNIX signal to the current process being debugged.",
1286405fe67fSCaroline Tice                        NULL)
128730fdc8d8SChris Lattner     {
1288405fe67fSCaroline Tice         CommandArgumentEntry arg;
1289405fe67fSCaroline Tice         CommandArgumentData signal_arg;
1290405fe67fSCaroline Tice 
1291405fe67fSCaroline Tice         // Define the first (and only) variant of this arg.
1292c0dbdfb6SCaroline Tice         signal_arg.arg_type = eArgTypeUnixSignal;
1293405fe67fSCaroline Tice         signal_arg.arg_repetition = eArgRepeatPlain;
1294405fe67fSCaroline Tice 
1295405fe67fSCaroline Tice         // There is only one variant this argument could be; put it into the argument entry.
1296405fe67fSCaroline Tice         arg.push_back (signal_arg);
1297405fe67fSCaroline Tice 
1298405fe67fSCaroline Tice         // Push the data for the first argument into the m_arguments vector.
1299405fe67fSCaroline Tice         m_arguments.push_back (arg);
130030fdc8d8SChris Lattner     }
130130fdc8d8SChris Lattner 
130230fdc8d8SChris Lattner     ~CommandObjectProcessSignal ()
130330fdc8d8SChris Lattner     {
130430fdc8d8SChris Lattner     }
130530fdc8d8SChris Lattner 
130630fdc8d8SChris Lattner     bool
1307a7015092SGreg Clayton     Execute (Args& command,
130830fdc8d8SChris Lattner              CommandReturnObject &result)
130930fdc8d8SChris Lattner     {
1310a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
131130fdc8d8SChris Lattner         if (process == NULL)
131230fdc8d8SChris Lattner         {
131330fdc8d8SChris Lattner             result.AppendError ("no process to signal");
131430fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
131530fdc8d8SChris Lattner             return false;
131630fdc8d8SChris Lattner         }
131730fdc8d8SChris Lattner 
131830fdc8d8SChris Lattner         if (command.GetArgumentCount() == 1)
131930fdc8d8SChris Lattner         {
1320237cd906SGreg Clayton             int signo = LLDB_INVALID_SIGNAL_NUMBER;
1321237cd906SGreg Clayton 
1322237cd906SGreg Clayton             const char *signal_name = command.GetArgumentAtIndex(0);
1323237cd906SGreg Clayton             if (::isxdigit (signal_name[0]))
1324237cd906SGreg Clayton                 signo = Args::StringToSInt32(signal_name, LLDB_INVALID_SIGNAL_NUMBER, 0);
1325237cd906SGreg Clayton             else
1326237cd906SGreg Clayton                 signo = process->GetUnixSignals().GetSignalNumberFromName (signal_name);
1327237cd906SGreg Clayton 
1328237cd906SGreg Clayton             if (signo == LLDB_INVALID_SIGNAL_NUMBER)
132930fdc8d8SChris Lattner             {
133030fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0));
133130fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
133230fdc8d8SChris Lattner             }
133330fdc8d8SChris Lattner             else
133430fdc8d8SChris Lattner             {
133530fdc8d8SChris Lattner                 Error error (process->Signal (signo));
133630fdc8d8SChris Lattner                 if (error.Success())
133730fdc8d8SChris Lattner                 {
133830fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusSuccessFinishResult);
133930fdc8d8SChris Lattner                 }
134030fdc8d8SChris Lattner                 else
134130fdc8d8SChris Lattner                 {
134230fdc8d8SChris Lattner                     result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString());
134330fdc8d8SChris Lattner                     result.SetStatus (eReturnStatusFailed);
134430fdc8d8SChris Lattner                 }
134530fdc8d8SChris Lattner             }
134630fdc8d8SChris Lattner         }
134730fdc8d8SChris Lattner         else
134830fdc8d8SChris Lattner         {
134930fdc8d8SChris Lattner             result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: \n", m_cmd_name.c_str(),
135030fdc8d8SChris Lattner                                         m_cmd_syntax.c_str());
135130fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
135230fdc8d8SChris Lattner         }
135330fdc8d8SChris Lattner         return result.Succeeded();
135430fdc8d8SChris Lattner     }
135530fdc8d8SChris Lattner };
135630fdc8d8SChris Lattner 
135730fdc8d8SChris Lattner 
135830fdc8d8SChris Lattner //-------------------------------------------------------------------------
135930fdc8d8SChris Lattner // CommandObjectProcessInterrupt
136030fdc8d8SChris Lattner //-------------------------------------------------------------------------
1361bb9caf73SJim Ingham #pragma mark CommandObjectProcessInterrupt
136230fdc8d8SChris Lattner 
136330fdc8d8SChris Lattner class CommandObjectProcessInterrupt : public CommandObject
136430fdc8d8SChris Lattner {
136530fdc8d8SChris Lattner public:
136630fdc8d8SChris Lattner 
136730fdc8d8SChris Lattner 
1368a7015092SGreg Clayton     CommandObjectProcessInterrupt (CommandInterpreter &interpreter) :
1369a7015092SGreg Clayton     CommandObject (interpreter,
1370a7015092SGreg Clayton                    "process interrupt",
1371e3d26315SCaroline Tice                    "Interrupt the current process being debugged.",
137230fdc8d8SChris Lattner                    "process interrupt",
137330fdc8d8SChris Lattner                    eFlagProcessMustBeLaunched)
137430fdc8d8SChris Lattner     {
137530fdc8d8SChris Lattner     }
137630fdc8d8SChris Lattner 
137730fdc8d8SChris Lattner     ~CommandObjectProcessInterrupt ()
137830fdc8d8SChris Lattner     {
137930fdc8d8SChris Lattner     }
138030fdc8d8SChris Lattner 
138130fdc8d8SChris Lattner     bool
1382a7015092SGreg Clayton     Execute (Args& command,
138330fdc8d8SChris Lattner              CommandReturnObject &result)
138430fdc8d8SChris Lattner     {
1385a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
138630fdc8d8SChris Lattner         if (process == NULL)
138730fdc8d8SChris Lattner         {
138830fdc8d8SChris Lattner             result.AppendError ("no process to halt");
138930fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
139030fdc8d8SChris Lattner             return false;
139130fdc8d8SChris Lattner         }
139230fdc8d8SChris Lattner 
139330fdc8d8SChris Lattner         if (command.GetArgumentCount() == 0)
139430fdc8d8SChris Lattner         {
139530fdc8d8SChris Lattner             Error error(process->Halt ());
139630fdc8d8SChris Lattner             if (error.Success())
139730fdc8d8SChris Lattner             {
139830fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusSuccessFinishResult);
139930fdc8d8SChris Lattner 
140030fdc8d8SChris Lattner                 // Maybe we should add a "SuspendThreadPlans so we
140130fdc8d8SChris Lattner                 // can halt, and keep in place all the current thread plans.
140230fdc8d8SChris Lattner                 process->GetThreadList().DiscardThreadPlans();
140330fdc8d8SChris Lattner             }
140430fdc8d8SChris Lattner             else
140530fdc8d8SChris Lattner             {
140630fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString());
140730fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
140830fdc8d8SChris Lattner             }
140930fdc8d8SChris Lattner         }
141030fdc8d8SChris Lattner         else
141130fdc8d8SChris Lattner         {
141230fdc8d8SChris Lattner             result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
141330fdc8d8SChris Lattner                                         m_cmd_name.c_str(),
141430fdc8d8SChris Lattner                                         m_cmd_syntax.c_str());
141530fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
141630fdc8d8SChris Lattner         }
141730fdc8d8SChris Lattner         return result.Succeeded();
141830fdc8d8SChris Lattner     }
141930fdc8d8SChris Lattner };
142030fdc8d8SChris Lattner 
142130fdc8d8SChris Lattner //-------------------------------------------------------------------------
142230fdc8d8SChris Lattner // CommandObjectProcessKill
142330fdc8d8SChris Lattner //-------------------------------------------------------------------------
1424bb9caf73SJim Ingham #pragma mark CommandObjectProcessKill
142530fdc8d8SChris Lattner 
142630fdc8d8SChris Lattner class CommandObjectProcessKill : public CommandObject
142730fdc8d8SChris Lattner {
142830fdc8d8SChris Lattner public:
142930fdc8d8SChris Lattner 
1430a7015092SGreg Clayton     CommandObjectProcessKill (CommandInterpreter &interpreter) :
1431a7015092SGreg Clayton     CommandObject (interpreter,
1432a7015092SGreg Clayton                    "process kill",
1433e3d26315SCaroline Tice                    "Terminate the current process being debugged.",
143430fdc8d8SChris Lattner                    "process kill",
143530fdc8d8SChris Lattner                    eFlagProcessMustBeLaunched)
143630fdc8d8SChris Lattner     {
143730fdc8d8SChris Lattner     }
143830fdc8d8SChris Lattner 
143930fdc8d8SChris Lattner     ~CommandObjectProcessKill ()
144030fdc8d8SChris Lattner     {
144130fdc8d8SChris Lattner     }
144230fdc8d8SChris Lattner 
144330fdc8d8SChris Lattner     bool
1444a7015092SGreg Clayton     Execute (Args& command,
144530fdc8d8SChris Lattner              CommandReturnObject &result)
144630fdc8d8SChris Lattner     {
1447a7015092SGreg Clayton         Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
144830fdc8d8SChris Lattner         if (process == NULL)
144930fdc8d8SChris Lattner         {
145030fdc8d8SChris Lattner             result.AppendError ("no process to kill");
145130fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
145230fdc8d8SChris Lattner             return false;
145330fdc8d8SChris Lattner         }
145430fdc8d8SChris Lattner 
145530fdc8d8SChris Lattner         if (command.GetArgumentCount() == 0)
145630fdc8d8SChris Lattner         {
145730fdc8d8SChris Lattner             Error error (process->Destroy());
145830fdc8d8SChris Lattner             if (error.Success())
145930fdc8d8SChris Lattner             {
146030fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusSuccessFinishResult);
146130fdc8d8SChris Lattner             }
146230fdc8d8SChris Lattner             else
146330fdc8d8SChris Lattner             {
146430fdc8d8SChris Lattner                 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString());
146530fdc8d8SChris Lattner                 result.SetStatus (eReturnStatusFailed);
146630fdc8d8SChris Lattner             }
146730fdc8d8SChris Lattner         }
146830fdc8d8SChris Lattner         else
146930fdc8d8SChris Lattner         {
147030fdc8d8SChris Lattner             result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n",
147130fdc8d8SChris Lattner                                         m_cmd_name.c_str(),
147230fdc8d8SChris Lattner                                         m_cmd_syntax.c_str());
147330fdc8d8SChris Lattner             result.SetStatus (eReturnStatusFailed);
147430fdc8d8SChris Lattner         }
147530fdc8d8SChris Lattner         return result.Succeeded();
147630fdc8d8SChris Lattner     }
147730fdc8d8SChris Lattner };
147830fdc8d8SChris Lattner 
147930fdc8d8SChris Lattner //-------------------------------------------------------------------------
14804b9bea87SJim Ingham // CommandObjectProcessStatus
14814b9bea87SJim Ingham //-------------------------------------------------------------------------
1482bb9caf73SJim Ingham #pragma mark CommandObjectProcessStatus
1483bb9caf73SJim Ingham 
14844b9bea87SJim Ingham class CommandObjectProcessStatus : public CommandObject
14854b9bea87SJim Ingham {
14864b9bea87SJim Ingham public:
1487a7015092SGreg Clayton     CommandObjectProcessStatus (CommandInterpreter &interpreter) :
1488a7015092SGreg Clayton     CommandObject (interpreter,
1489a7015092SGreg Clayton                    "process status",
1490e3d26315SCaroline Tice                    "Show the current status and location of executing process.",
1491e3d26315SCaroline Tice                    "process status",
14924b9bea87SJim Ingham                    0)
14934b9bea87SJim Ingham     {
14944b9bea87SJim Ingham     }
14954b9bea87SJim Ingham 
14964b9bea87SJim Ingham     ~CommandObjectProcessStatus()
14974b9bea87SJim Ingham     {
14984b9bea87SJim Ingham     }
14994b9bea87SJim Ingham 
15004b9bea87SJim Ingham 
15014b9bea87SJim Ingham     bool
15024b9bea87SJim Ingham     Execute
15034b9bea87SJim Ingham     (
15044b9bea87SJim Ingham         Args& command,
15054b9bea87SJim Ingham         CommandReturnObject &result
15064b9bea87SJim Ingham     )
15074b9bea87SJim Ingham     {
150885e8b814SJim Ingham         Stream &output_stream = result.GetOutputStream();
15094b9bea87SJim Ingham         result.SetStatus (eReturnStatusSuccessFinishNoResult);
1510a7015092SGreg Clayton         ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext());
15114b9bea87SJim Ingham         if (exe_ctx.process)
15124b9bea87SJim Ingham         {
15134b9bea87SJim Ingham             const StateType state = exe_ctx.process->GetState();
15144b9bea87SJim Ingham             if (StateIsStoppedState(state))
15154b9bea87SJim Ingham             {
15164b9bea87SJim Ingham                 if (state == eStateExited)
15174b9bea87SJim Ingham                 {
15184b9bea87SJim Ingham                     int exit_status = exe_ctx.process->GetExitStatus();
15194b9bea87SJim Ingham                     const char *exit_description = exe_ctx.process->GetExitDescription();
15204b9bea87SJim Ingham                     output_stream.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n",
15214b9bea87SJim Ingham                                           exe_ctx.process->GetID(),
15224b9bea87SJim Ingham                                           exit_status,
15234b9bea87SJim Ingham                                           exit_status,
15244b9bea87SJim Ingham                                           exit_description ? exit_description : "");
15254b9bea87SJim Ingham                 }
15264b9bea87SJim Ingham                 else
15274b9bea87SJim Ingham                 {
152871337622SGreg Clayton                     if (state == eStateConnected)
152971337622SGreg Clayton                         output_stream.Printf ("Connected to remote target.\n");
153071337622SGreg Clayton                     else
15314b9bea87SJim Ingham                         output_stream.Printf ("Process %d %s\n", exe_ctx.process->GetID(), StateAsCString (state));
15324b9bea87SJim Ingham                     if (exe_ctx.thread == NULL)
15334b9bea87SJim Ingham                         exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get();
15344b9bea87SJim Ingham                     if (exe_ctx.thread != NULL)
15354b9bea87SJim Ingham                     {
1536a7015092SGreg Clayton                         DisplayThreadsInfo (m_interpreter, &exe_ctx, result, true, true);
15374b9bea87SJim Ingham                     }
15384b9bea87SJim Ingham                     else
15394b9bea87SJim Ingham                     {
15404b9bea87SJim Ingham                         result.AppendError ("No valid thread found in current process.");
15414b9bea87SJim Ingham                         result.SetStatus (eReturnStatusFailed);
15424b9bea87SJim Ingham                     }
15434b9bea87SJim Ingham                 }
15444b9bea87SJim Ingham             }
15454b9bea87SJim Ingham             else
15464b9bea87SJim Ingham             {
15474b9bea87SJim Ingham                 output_stream.Printf ("Process %d is running.\n",
15484b9bea87SJim Ingham                                           exe_ctx.process->GetID());
15494b9bea87SJim Ingham             }
15504b9bea87SJim Ingham         }
15514b9bea87SJim Ingham         else
15524b9bea87SJim Ingham         {
15534b9bea87SJim Ingham             result.AppendError ("No current location or status available.");
15544b9bea87SJim Ingham             result.SetStatus (eReturnStatusFailed);
15554b9bea87SJim Ingham         }
15564b9bea87SJim Ingham         return result.Succeeded();
15574b9bea87SJim Ingham     }
15584b9bea87SJim Ingham };
15594b9bea87SJim Ingham 
15604b9bea87SJim Ingham //-------------------------------------------------------------------------
156135731357SCaroline Tice // CommandObjectProcessHandle
156235731357SCaroline Tice //-------------------------------------------------------------------------
1563bb9caf73SJim Ingham #pragma mark CommandObjectProcessHandle
156435731357SCaroline Tice 
156535731357SCaroline Tice class CommandObjectProcessHandle : public CommandObject
156635731357SCaroline Tice {
156735731357SCaroline Tice public:
156835731357SCaroline Tice 
156935731357SCaroline Tice     class CommandOptions : public Options
157035731357SCaroline Tice     {
157135731357SCaroline Tice     public:
157235731357SCaroline Tice 
1573*eb0103f2SGreg Clayton         CommandOptions (CommandInterpreter &interpreter) :
1574*eb0103f2SGreg Clayton             Options (interpreter)
157535731357SCaroline Tice         {
157635731357SCaroline Tice             ResetOptionValues ();
157735731357SCaroline Tice         }
157835731357SCaroline Tice 
157935731357SCaroline Tice         ~CommandOptions ()
158035731357SCaroline Tice         {
158135731357SCaroline Tice         }
158235731357SCaroline Tice 
158335731357SCaroline Tice         Error
158435731357SCaroline Tice         SetOptionValue (int option_idx, const char *option_arg)
158535731357SCaroline Tice         {
158635731357SCaroline Tice             Error error;
158735731357SCaroline Tice             char short_option = (char) m_getopt_table[option_idx].val;
158835731357SCaroline Tice 
158935731357SCaroline Tice             switch (short_option)
159035731357SCaroline Tice             {
159135731357SCaroline Tice                 case 's':
159235731357SCaroline Tice                     stop = option_arg;
159335731357SCaroline Tice                     break;
159435731357SCaroline Tice                 case 'n':
159535731357SCaroline Tice                     notify = option_arg;
159635731357SCaroline Tice                     break;
159735731357SCaroline Tice                 case 'p':
159835731357SCaroline Tice                     pass = option_arg;
159935731357SCaroline Tice                     break;
160035731357SCaroline Tice                 default:
160135731357SCaroline Tice                     error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option);
160235731357SCaroline Tice                     break;
160335731357SCaroline Tice             }
160435731357SCaroline Tice             return error;
160535731357SCaroline Tice         }
160635731357SCaroline Tice 
160735731357SCaroline Tice         void
160835731357SCaroline Tice         ResetOptionValues ()
160935731357SCaroline Tice         {
161035731357SCaroline Tice             stop.clear();
161135731357SCaroline Tice             notify.clear();
161235731357SCaroline Tice             pass.clear();
161335731357SCaroline Tice         }
161435731357SCaroline Tice 
1615e0d378b3SGreg Clayton         const OptionDefinition*
161635731357SCaroline Tice         GetDefinitions ()
161735731357SCaroline Tice         {
161835731357SCaroline Tice             return g_option_table;
161935731357SCaroline Tice         }
162035731357SCaroline Tice 
162135731357SCaroline Tice         // Options table: Required for subclasses of Options.
162235731357SCaroline Tice 
1623e0d378b3SGreg Clayton         static OptionDefinition g_option_table[];
162435731357SCaroline Tice 
162535731357SCaroline Tice         // Instance variables to hold the values for command options.
162635731357SCaroline Tice 
162735731357SCaroline Tice         std::string stop;
162835731357SCaroline Tice         std::string notify;
162935731357SCaroline Tice         std::string pass;
163035731357SCaroline Tice     };
163135731357SCaroline Tice 
163235731357SCaroline Tice 
163335731357SCaroline Tice     CommandObjectProcessHandle (CommandInterpreter &interpreter) :
163435731357SCaroline Tice         CommandObject (interpreter,
163535731357SCaroline Tice                        "process handle",
163610ad7993SCaroline Tice                        "Show or update what the process and debugger should do with various signals received from the OS.",
1637*eb0103f2SGreg Clayton                        NULL),
1638*eb0103f2SGreg Clayton         m_options (interpreter)
163935731357SCaroline Tice     {
164010ad7993SCaroline Tice         SetHelpLong ("If no signals are specified, update them all.  If no update option is specified, list the current values.\n");
164135731357SCaroline Tice         CommandArgumentEntry arg;
1642c0dbdfb6SCaroline Tice         CommandArgumentData signal_arg;
164335731357SCaroline Tice 
1644c0dbdfb6SCaroline Tice         signal_arg.arg_type = eArgTypeUnixSignal;
1645c0dbdfb6SCaroline Tice         signal_arg.arg_repetition = eArgRepeatStar;
164635731357SCaroline Tice 
1647c0dbdfb6SCaroline Tice         arg.push_back (signal_arg);
164835731357SCaroline Tice 
164935731357SCaroline Tice         m_arguments.push_back (arg);
165035731357SCaroline Tice     }
165135731357SCaroline Tice 
165235731357SCaroline Tice     ~CommandObjectProcessHandle ()
165335731357SCaroline Tice     {
165435731357SCaroline Tice     }
165535731357SCaroline Tice 
165635731357SCaroline Tice     Options *
165735731357SCaroline Tice     GetOptions ()
165835731357SCaroline Tice     {
165935731357SCaroline Tice         return &m_options;
166035731357SCaroline Tice     }
166135731357SCaroline Tice 
166235731357SCaroline Tice     bool
166310ad7993SCaroline Tice     VerifyCommandOptionValue (const std::string &option, int &real_value)
166435731357SCaroline Tice     {
166535731357SCaroline Tice         bool okay = true;
166635731357SCaroline Tice 
166710ad7993SCaroline Tice         bool success = false;
166810ad7993SCaroline Tice         bool tmp_value = Args::StringToBoolean (option.c_str(), false, &success);
166910ad7993SCaroline Tice 
167010ad7993SCaroline Tice         if (success && tmp_value)
167110ad7993SCaroline Tice             real_value = 1;
167210ad7993SCaroline Tice         else if (success && !tmp_value)
167310ad7993SCaroline Tice             real_value = 0;
167435731357SCaroline Tice         else
167535731357SCaroline Tice         {
167635731357SCaroline Tice             // If the value isn't 'true' or 'false', it had better be 0 or 1.
167710ad7993SCaroline Tice             real_value = Args::StringToUInt32 (option.c_str(), 3);
167810ad7993SCaroline Tice             if (real_value != 0 && real_value != 1)
167935731357SCaroline Tice                 okay = false;
168035731357SCaroline Tice         }
168135731357SCaroline Tice 
168235731357SCaroline Tice         return okay;
168335731357SCaroline Tice     }
168435731357SCaroline Tice 
168510ad7993SCaroline Tice     void
168610ad7993SCaroline Tice     PrintSignalHeader (Stream &str)
168710ad7993SCaroline Tice     {
168810ad7993SCaroline Tice         str.Printf ("NAME        PASS   STOP   NOTIFY\n");
168910ad7993SCaroline Tice         str.Printf ("==========  =====  =====  ======\n");
169010ad7993SCaroline Tice     }
169110ad7993SCaroline Tice 
169210ad7993SCaroline Tice     void
169310ad7993SCaroline Tice     PrintSignal (Stream &str, int32_t signo, const char *sig_name, UnixSignals &signals)
169410ad7993SCaroline Tice     {
169510ad7993SCaroline Tice         bool stop;
169610ad7993SCaroline Tice         bool suppress;
169710ad7993SCaroline Tice         bool notify;
169810ad7993SCaroline Tice 
169910ad7993SCaroline Tice         str.Printf ("%-10s  ", sig_name);
170010ad7993SCaroline Tice         if (signals.GetSignalInfo (signo, suppress, stop, notify))
170110ad7993SCaroline Tice         {
170210ad7993SCaroline Tice             bool pass = !suppress;
170310ad7993SCaroline Tice             str.Printf ("%s  %s  %s",
170410ad7993SCaroline Tice                         (pass ? "true " : "false"),
170510ad7993SCaroline Tice                         (stop ? "true " : "false"),
170610ad7993SCaroline Tice                         (notify ? "true " : "false"));
170710ad7993SCaroline Tice         }
170810ad7993SCaroline Tice         str.Printf ("\n");
170910ad7993SCaroline Tice     }
171010ad7993SCaroline Tice 
171110ad7993SCaroline Tice     void
171210ad7993SCaroline Tice     PrintSignalInformation (Stream &str, Args &signal_args, int num_valid_signals, UnixSignals &signals)
171310ad7993SCaroline Tice     {
171410ad7993SCaroline Tice         PrintSignalHeader (str);
171510ad7993SCaroline Tice 
171610ad7993SCaroline Tice         if (num_valid_signals > 0)
171710ad7993SCaroline Tice         {
171810ad7993SCaroline Tice             size_t num_args = signal_args.GetArgumentCount();
171910ad7993SCaroline Tice             for (size_t i = 0; i < num_args; ++i)
172010ad7993SCaroline Tice             {
172110ad7993SCaroline Tice                 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
172210ad7993SCaroline Tice                 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
172310ad7993SCaroline Tice                     PrintSignal (str, signo, signal_args.GetArgumentAtIndex (i), signals);
172410ad7993SCaroline Tice             }
172510ad7993SCaroline Tice         }
172610ad7993SCaroline Tice         else // Print info for ALL signals
172710ad7993SCaroline Tice         {
172810ad7993SCaroline Tice             int32_t signo = signals.GetFirstSignalNumber();
172910ad7993SCaroline Tice             while (signo != LLDB_INVALID_SIGNAL_NUMBER)
173010ad7993SCaroline Tice             {
173110ad7993SCaroline Tice                 PrintSignal (str, signo, signals.GetSignalAsCString (signo), signals);
173210ad7993SCaroline Tice                 signo = signals.GetNextSignalNumber (signo);
173310ad7993SCaroline Tice             }
173410ad7993SCaroline Tice         }
173510ad7993SCaroline Tice     }
173610ad7993SCaroline Tice 
173735731357SCaroline Tice     bool
173835731357SCaroline Tice     Execute (Args &signal_args, CommandReturnObject &result)
173935731357SCaroline Tice     {
174035731357SCaroline Tice         TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget();
174135731357SCaroline Tice 
174235731357SCaroline Tice         if (!target_sp)
174335731357SCaroline Tice         {
174435731357SCaroline Tice             result.AppendError ("No current target;"
174535731357SCaroline Tice                                 " cannot handle signals until you have a valid target and process.\n");
174635731357SCaroline Tice             result.SetStatus (eReturnStatusFailed);
174735731357SCaroline Tice             return false;
174835731357SCaroline Tice         }
174935731357SCaroline Tice 
175035731357SCaroline Tice         ProcessSP process_sp = target_sp->GetProcessSP();
175135731357SCaroline Tice 
175235731357SCaroline Tice         if (!process_sp)
175335731357SCaroline Tice         {
175435731357SCaroline Tice             result.AppendError ("No current process; cannot handle signals until you have a valid process.\n");
175535731357SCaroline Tice             result.SetStatus (eReturnStatusFailed);
175635731357SCaroline Tice             return false;
175735731357SCaroline Tice         }
175835731357SCaroline Tice 
175935731357SCaroline Tice         int stop_action = -1;   // -1 means leave the current setting alone
176035731357SCaroline Tice         int pass_action = -1;   // -1 means leave the current setting alone
176135731357SCaroline Tice         int notify_action = -1; // -1 means leave the current setting alone
176235731357SCaroline Tice 
176335731357SCaroline Tice         if (! m_options.stop.empty()
176410ad7993SCaroline Tice             && ! VerifyCommandOptionValue (m_options.stop, stop_action))
176535731357SCaroline Tice         {
176635731357SCaroline Tice             result.AppendError ("Invalid argument for command option --stop; must be true or false.\n");
176735731357SCaroline Tice             result.SetStatus (eReturnStatusFailed);
176835731357SCaroline Tice             return false;
176935731357SCaroline Tice         }
177035731357SCaroline Tice 
177135731357SCaroline Tice         if (! m_options.notify.empty()
177210ad7993SCaroline Tice             && ! VerifyCommandOptionValue (m_options.notify, notify_action))
177335731357SCaroline Tice         {
177435731357SCaroline Tice             result.AppendError ("Invalid argument for command option --notify; must be true or false.\n");
177535731357SCaroline Tice             result.SetStatus (eReturnStatusFailed);
177635731357SCaroline Tice             return false;
177735731357SCaroline Tice         }
177835731357SCaroline Tice 
177935731357SCaroline Tice         if (! m_options.pass.empty()
178010ad7993SCaroline Tice             && ! VerifyCommandOptionValue (m_options.pass, pass_action))
178135731357SCaroline Tice         {
178235731357SCaroline Tice             result.AppendError ("Invalid argument for command option --pass; must be true or false.\n");
178335731357SCaroline Tice             result.SetStatus (eReturnStatusFailed);
178435731357SCaroline Tice             return false;
178535731357SCaroline Tice         }
178635731357SCaroline Tice 
178735731357SCaroline Tice         size_t num_args = signal_args.GetArgumentCount();
178835731357SCaroline Tice         UnixSignals &signals = process_sp->GetUnixSignals();
178935731357SCaroline Tice         int num_signals_set = 0;
179035731357SCaroline Tice 
179110ad7993SCaroline Tice         if (num_args > 0)
179210ad7993SCaroline Tice         {
179335731357SCaroline Tice             for (size_t i = 0; i < num_args; ++i)
179435731357SCaroline Tice             {
179535731357SCaroline Tice                 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i));
179635731357SCaroline Tice                 if (signo != LLDB_INVALID_SIGNAL_NUMBER)
179735731357SCaroline Tice                 {
179810ad7993SCaroline Tice                     // Casting the actions as bools here should be okay, because VerifyCommandOptionValue guarantees
179935731357SCaroline Tice                     // the value is either 0 or 1.
180035731357SCaroline Tice                     if (stop_action != -1)
180135731357SCaroline Tice                         signals.SetShouldStop (signo, (bool) stop_action);
180235731357SCaroline Tice                     if (pass_action != -1)
180335731357SCaroline Tice                     {
180410ad7993SCaroline Tice                         bool suppress = ! ((bool) pass_action);
180510ad7993SCaroline Tice                         signals.SetShouldSuppress (signo, suppress);
180635731357SCaroline Tice                     }
180735731357SCaroline Tice                     if (notify_action != -1)
180835731357SCaroline Tice                         signals.SetShouldNotify (signo, (bool) notify_action);
180935731357SCaroline Tice                     ++num_signals_set;
181035731357SCaroline Tice                 }
181135731357SCaroline Tice                 else
181235731357SCaroline Tice                 {
181335731357SCaroline Tice                     result.AppendErrorWithFormat ("Invalid signal name '%s'\n", signal_args.GetArgumentAtIndex (i));
181435731357SCaroline Tice                 }
181535731357SCaroline Tice             }
181610ad7993SCaroline Tice         }
181710ad7993SCaroline Tice         else
181810ad7993SCaroline Tice         {
181910ad7993SCaroline Tice             // No signal specified, if any command options were specified, update ALL signals.
182010ad7993SCaroline Tice             if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1))
182110ad7993SCaroline Tice             {
182210ad7993SCaroline Tice                 if (m_interpreter.Confirm ("Do you really want to update all the signals?", false))
182310ad7993SCaroline Tice                 {
182410ad7993SCaroline Tice                     int32_t signo = signals.GetFirstSignalNumber();
182510ad7993SCaroline Tice                     while (signo != LLDB_INVALID_SIGNAL_NUMBER)
182610ad7993SCaroline Tice                     {
182710ad7993SCaroline Tice                         if (notify_action != -1)
182810ad7993SCaroline Tice                             signals.SetShouldNotify (signo, (bool) notify_action);
182910ad7993SCaroline Tice                         if (stop_action != -1)
183010ad7993SCaroline Tice                             signals.SetShouldStop (signo, (bool) stop_action);
183110ad7993SCaroline Tice                         if (pass_action != -1)
183210ad7993SCaroline Tice                         {
183310ad7993SCaroline Tice                             bool suppress = ! ((bool) pass_action);
183410ad7993SCaroline Tice                             signals.SetShouldSuppress (signo, suppress);
183510ad7993SCaroline Tice                         }
183610ad7993SCaroline Tice                         signo = signals.GetNextSignalNumber (signo);
183710ad7993SCaroline Tice                     }
183810ad7993SCaroline Tice                 }
183910ad7993SCaroline Tice             }
184010ad7993SCaroline Tice         }
184110ad7993SCaroline Tice 
184210ad7993SCaroline Tice         PrintSignalInformation (result.GetOutputStream(), signal_args, num_signals_set, signals);
184335731357SCaroline Tice 
184435731357SCaroline Tice         if (num_signals_set > 0)
184535731357SCaroline Tice             result.SetStatus (eReturnStatusSuccessFinishNoResult);
184635731357SCaroline Tice         else
184735731357SCaroline Tice             result.SetStatus (eReturnStatusFailed);
184835731357SCaroline Tice 
184935731357SCaroline Tice         return result.Succeeded();
185035731357SCaroline Tice     }
185135731357SCaroline Tice 
185235731357SCaroline Tice protected:
185335731357SCaroline Tice 
185435731357SCaroline Tice     CommandOptions m_options;
185535731357SCaroline Tice };
185635731357SCaroline Tice 
1857e0d378b3SGreg Clayton OptionDefinition
185835731357SCaroline Tice CommandObjectProcessHandle::CommandOptions::g_option_table[] =
185935731357SCaroline Tice {
186035731357SCaroline 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." },
186135731357SCaroline 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." },
186235731357SCaroline Tice { LLDB_OPT_SET_1, false, "pass",  'p', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." },
186335731357SCaroline Tice { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
186435731357SCaroline Tice };
186535731357SCaroline Tice 
186635731357SCaroline Tice //-------------------------------------------------------------------------
186730fdc8d8SChris Lattner // CommandObjectMultiwordProcess
186830fdc8d8SChris Lattner //-------------------------------------------------------------------------
186930fdc8d8SChris Lattner 
18706611103cSGreg Clayton CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter &interpreter) :
1871a7015092SGreg Clayton     CommandObjectMultiword (interpreter,
1872a7015092SGreg Clayton                             "process",
187330fdc8d8SChris Lattner                             "A set of commands for operating on a process.",
187430fdc8d8SChris Lattner                             "process <subcommand> [<subcommand-options>]")
187530fdc8d8SChris Lattner {
1876a7015092SGreg Clayton     LoadSubCommand ("attach",      CommandObjectSP (new CommandObjectProcessAttach (interpreter)));
1877a7015092SGreg Clayton     LoadSubCommand ("launch",      CommandObjectSP (new CommandObjectProcessLaunch (interpreter)));
1878a7015092SGreg Clayton     LoadSubCommand ("continue",    CommandObjectSP (new CommandObjectProcessContinue (interpreter)));
1879b766a73dSGreg Clayton     LoadSubCommand ("connect",     CommandObjectSP (new CommandObjectProcessConnect (interpreter)));
1880a7015092SGreg Clayton     LoadSubCommand ("detach",      CommandObjectSP (new CommandObjectProcessDetach (interpreter)));
18818f343b09SGreg Clayton     LoadSubCommand ("load",        CommandObjectSP (new CommandObjectProcessLoad (interpreter)));
18828f343b09SGreg Clayton     LoadSubCommand ("unload",      CommandObjectSP (new CommandObjectProcessUnload (interpreter)));
1883a7015092SGreg Clayton     LoadSubCommand ("signal",      CommandObjectSP (new CommandObjectProcessSignal (interpreter)));
188435731357SCaroline Tice     LoadSubCommand ("handle",      CommandObjectSP (new CommandObjectProcessHandle (interpreter)));
1885a7015092SGreg Clayton     LoadSubCommand ("status",      CommandObjectSP (new CommandObjectProcessStatus (interpreter)));
1886a7015092SGreg Clayton     LoadSubCommand ("interrupt",   CommandObjectSP (new CommandObjectProcessInterrupt (interpreter)));
1887a7015092SGreg Clayton     LoadSubCommand ("kill",        CommandObjectSP (new CommandObjectProcessKill (interpreter)));
188830fdc8d8SChris Lattner }
188930fdc8d8SChris Lattner 
189030fdc8d8SChris Lattner CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess ()
189130fdc8d8SChris Lattner {
189230fdc8d8SChris Lattner }
189330fdc8d8SChris Lattner 
1894