130fdc8d8SChris Lattner //===-- CommandObjectProcess.cpp --------------------------------*- C++ -*-===// 230fdc8d8SChris Lattner // 330fdc8d8SChris Lattner // The LLVM Compiler Infrastructure 430fdc8d8SChris Lattner // 530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source 630fdc8d8SChris Lattner // License. See LICENSE.TXT for details. 730fdc8d8SChris Lattner // 830fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 930fdc8d8SChris Lattner 1030fdc8d8SChris Lattner #include "CommandObjectProcess.h" 1130fdc8d8SChris Lattner 1230fdc8d8SChris Lattner // C Includes 1330fdc8d8SChris Lattner // C++ Includes 1430fdc8d8SChris Lattner // Other libraries and framework includes 1530fdc8d8SChris Lattner // Project includes 1640af72e1SJim Ingham #include "lldb/Interpreter/Args.h" 1740af72e1SJim Ingham #include "lldb/Interpreter/Options.h" 1830fdc8d8SChris Lattner #include "lldb/Core/State.h" 1930fdc8d8SChris Lattner #include "lldb/Interpreter/CommandInterpreter.h" 2030fdc8d8SChris Lattner #include "lldb/Interpreter/CommandReturnObject.h" 214b9bea87SJim Ingham #include "./CommandObjectThread.h" 2230fdc8d8SChris Lattner #include "lldb/Target/Process.h" 2330fdc8d8SChris Lattner #include "lldb/Target/Target.h" 2430fdc8d8SChris Lattner #include "lldb/Target/Thread.h" 2530fdc8d8SChris Lattner 2630fdc8d8SChris Lattner using namespace lldb; 2730fdc8d8SChris Lattner using namespace lldb_private; 2830fdc8d8SChris Lattner 2930fdc8d8SChris Lattner //------------------------------------------------------------------------- 3030fdc8d8SChris Lattner // CommandObjectProcessLaunch 3130fdc8d8SChris Lattner //------------------------------------------------------------------------- 3230fdc8d8SChris Lattner 3330fdc8d8SChris Lattner class CommandObjectProcessLaunch : public CommandObject 3430fdc8d8SChris Lattner { 3530fdc8d8SChris Lattner public: 3630fdc8d8SChris Lattner 3730fdc8d8SChris Lattner class CommandOptions : public Options 3830fdc8d8SChris Lattner { 3930fdc8d8SChris Lattner public: 4030fdc8d8SChris Lattner 4130fdc8d8SChris Lattner CommandOptions () : 4230fdc8d8SChris Lattner Options() 4330fdc8d8SChris Lattner { 4430fdc8d8SChris Lattner // Keep default values of all options in one place: ResetOptionValues () 4530fdc8d8SChris Lattner ResetOptionValues (); 4630fdc8d8SChris Lattner } 4730fdc8d8SChris Lattner 4830fdc8d8SChris Lattner ~CommandOptions () 4930fdc8d8SChris Lattner { 5030fdc8d8SChris Lattner } 5130fdc8d8SChris Lattner 5230fdc8d8SChris Lattner Error 5330fdc8d8SChris Lattner SetOptionValue (int option_idx, const char *option_arg) 5430fdc8d8SChris Lattner { 5530fdc8d8SChris Lattner Error error; 5630fdc8d8SChris Lattner char short_option = (char) m_getopt_table[option_idx].val; 5730fdc8d8SChris Lattner 5830fdc8d8SChris Lattner switch (short_option) 5930fdc8d8SChris Lattner { 6030fdc8d8SChris Lattner case 's': stop_at_entry = true; break; 6130fdc8d8SChris Lattner case 'e': stderr_path = option_arg; break; 6230fdc8d8SChris Lattner case 'i': stdin_path = option_arg; break; 6330fdc8d8SChris Lattner case 'o': stdout_path = option_arg; break; 6430fdc8d8SChris Lattner case 'p': plugin_name = option_arg; break; 6530fdc8d8SChris Lattner default: 6630fdc8d8SChris Lattner error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option); 6730fdc8d8SChris Lattner break; 6830fdc8d8SChris Lattner 6930fdc8d8SChris Lattner } 7030fdc8d8SChris Lattner return error; 7130fdc8d8SChris Lattner } 7230fdc8d8SChris Lattner 7330fdc8d8SChris Lattner void 7430fdc8d8SChris Lattner ResetOptionValues () 7530fdc8d8SChris Lattner { 7630fdc8d8SChris Lattner Options::ResetOptionValues(); 7730fdc8d8SChris Lattner stop_at_entry = false; 7830fdc8d8SChris Lattner stdin_path.clear(); 7930fdc8d8SChris Lattner stdout_path.clear(); 8030fdc8d8SChris Lattner stderr_path.clear(); 8130fdc8d8SChris Lattner plugin_name.clear(); 8230fdc8d8SChris Lattner } 8330fdc8d8SChris Lattner 8430fdc8d8SChris Lattner const lldb::OptionDefinition* 8530fdc8d8SChris Lattner GetDefinitions () 8630fdc8d8SChris Lattner { 8730fdc8d8SChris Lattner return g_option_table; 8830fdc8d8SChris Lattner } 8930fdc8d8SChris Lattner 9030fdc8d8SChris Lattner // Options table: Required for subclasses of Options. 9130fdc8d8SChris Lattner 9230fdc8d8SChris Lattner static lldb::OptionDefinition g_option_table[]; 9330fdc8d8SChris Lattner 9430fdc8d8SChris Lattner // Instance variables to hold the values for command options. 9530fdc8d8SChris Lattner 9630fdc8d8SChris Lattner bool stop_at_entry; 9730fdc8d8SChris Lattner std::string stderr_path; 9830fdc8d8SChris Lattner std::string stdin_path; 9930fdc8d8SChris Lattner std::string stdout_path; 10030fdc8d8SChris Lattner std::string plugin_name; 10130fdc8d8SChris Lattner 10230fdc8d8SChris Lattner }; 10330fdc8d8SChris Lattner 104a7015092SGreg Clayton CommandObjectProcessLaunch (CommandInterpreter &interpreter) : 105a7015092SGreg Clayton CommandObject (interpreter, 106a7015092SGreg Clayton "process launch", 107e3d26315SCaroline Tice "Launch the executable in the debugger.", 10830fdc8d8SChris Lattner "process launch [<cmd-options>] [<arguments-for-running-the-program>]") 10930fdc8d8SChris Lattner { 11030fdc8d8SChris Lattner } 11130fdc8d8SChris Lattner 11230fdc8d8SChris Lattner 11330fdc8d8SChris Lattner ~CommandObjectProcessLaunch () 11430fdc8d8SChris Lattner { 11530fdc8d8SChris Lattner } 11630fdc8d8SChris Lattner 11730fdc8d8SChris Lattner Options * 11830fdc8d8SChris Lattner GetOptions () 11930fdc8d8SChris Lattner { 12030fdc8d8SChris Lattner return &m_options; 12130fdc8d8SChris Lattner } 12230fdc8d8SChris Lattner 12330fdc8d8SChris Lattner bool 124a7015092SGreg Clayton Execute (Args& launch_args, 12530fdc8d8SChris Lattner CommandReturnObject &result) 12630fdc8d8SChris Lattner { 127a7015092SGreg Clayton Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 128a7015092SGreg Clayton bool synchronous_execution = m_interpreter.GetSynchronous (); 12930fdc8d8SChris Lattner // bool launched = false; 13030fdc8d8SChris Lattner // bool stopped_after_launch = false; 13130fdc8d8SChris Lattner 13230fdc8d8SChris Lattner if (target == NULL) 13330fdc8d8SChris Lattner { 13430fdc8d8SChris Lattner result.AppendError ("invalid target, set executable file using 'file' command"); 13530fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 13630fdc8d8SChris Lattner return false; 13730fdc8d8SChris Lattner } 13830fdc8d8SChris Lattner 13930fdc8d8SChris Lattner // If our listener is NULL, users aren't allows to launch 14030fdc8d8SChris Lattner char filename[PATH_MAX]; 14130fdc8d8SChris Lattner Module *exe_module = target->GetExecutableModule().get(); 14230fdc8d8SChris Lattner exe_module->GetFileSpec().GetPath(filename, sizeof(filename)); 14330fdc8d8SChris Lattner 144a7015092SGreg Clayton Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; 145a7015092SGreg Clayton if (process && process->IsAlive()) 14630fdc8d8SChris Lattner { 14730fdc8d8SChris Lattner result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before running again.\n", 14830fdc8d8SChris Lattner process->GetID()); 14930fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 15030fdc8d8SChris Lattner return false; 15130fdc8d8SChris Lattner } 15230fdc8d8SChris Lattner 15330fdc8d8SChris Lattner const char *plugin_name; 15430fdc8d8SChris Lattner if (!m_options.plugin_name.empty()) 15530fdc8d8SChris Lattner plugin_name = m_options.plugin_name.c_str(); 15630fdc8d8SChris Lattner else 15730fdc8d8SChris Lattner plugin_name = NULL; 15830fdc8d8SChris Lattner 159a7015092SGreg Clayton process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get(); 16030fdc8d8SChris Lattner 161a7015092SGreg Clayton if (process == NULL) 1623df9a8dfSCaroline Tice { 163a7015092SGreg Clayton result.AppendErrorWithFormat ("Failed to find a process plugin for executable"); 164a7015092SGreg Clayton result.SetStatus (eReturnStatusFailed); 165a7015092SGreg Clayton return false; 1663df9a8dfSCaroline Tice } 1673df9a8dfSCaroline Tice 168a7015092SGreg Clayton // If no launch args were given on the command line, then use any that 169a7015092SGreg Clayton // might have been set using the "run-args" set variable. 17030fdc8d8SChris Lattner if (launch_args.GetArgumentCount() == 0) 17130fdc8d8SChris Lattner { 172a7015092SGreg Clayton if (process->GetRunArguments().GetArgumentCount() > 0) 173a7015092SGreg Clayton launch_args = process->GetRunArguments(); 17430fdc8d8SChris Lattner } 17530fdc8d8SChris Lattner 176a7015092SGreg Clayton Args environment; 17730fdc8d8SChris Lattner 178a7015092SGreg Clayton process->GetEnvironmentAsArgs (environment); 179a7015092SGreg Clayton 180a7015092SGreg Clayton uint32_t launch_flags = eLaunchFlagNone; 181a7015092SGreg Clayton 182a7015092SGreg Clayton if (process->GetDisableASLR()) 183a7015092SGreg Clayton launch_flags |= eLaunchFlagDisableASLR; 184a7015092SGreg Clayton 18530fdc8d8SChris Lattner const char *archname = exe_module->GetArchitecture().AsCString(); 18630fdc8d8SChris Lattner 18730fdc8d8SChris Lattner const char * stdin_path = NULL; 18830fdc8d8SChris Lattner const char * stdout_path = NULL; 18930fdc8d8SChris Lattner const char * stderr_path = NULL; 19030fdc8d8SChris Lattner 191a7015092SGreg Clayton // Were any standard input/output/error paths given on the command line? 192a7015092SGreg Clayton if (m_options.stdin_path.empty() && 19330fdc8d8SChris Lattner m_options.stdout_path.empty() && 194a7015092SGreg Clayton m_options.stderr_path.empty()) 19530fdc8d8SChris Lattner { 196a7015092SGreg Clayton // No standard file handles were given on the command line, check 197a7015092SGreg Clayton // with the process object in case they were give using "set settings" 198a7015092SGreg Clayton stdin_path = process->GetStandardInputPath(); 199a7015092SGreg Clayton stdout_path = process->GetStandardOutputPath(); 200a7015092SGreg Clayton stderr_path = process->GetStandardErrorPath(); 201a7015092SGreg Clayton } 202a7015092SGreg Clayton else 203a7015092SGreg Clayton { 204a7015092SGreg Clayton stdin_path = m_options.stdin_path.empty() ? NULL : m_options.stdin_path.c_str(); 205a7015092SGreg Clayton stdout_path = m_options.stdout_path.empty() ? NULL : m_options.stdout_path.c_str(); 206a7015092SGreg Clayton stderr_path = m_options.stderr_path.empty() ? NULL : m_options.stderr_path.c_str(); 20730fdc8d8SChris Lattner } 20830fdc8d8SChris Lattner 209a7015092SGreg Clayton if (stdin_path == NULL) 210a7015092SGreg Clayton stdin_path = "/dev/null"; 211a7015092SGreg Clayton if (stdout_path == NULL) 212a7015092SGreg Clayton stdout_path = "/dev/null"; 213a7015092SGreg Clayton if (stderr_path == NULL) 214a7015092SGreg Clayton stderr_path = "/dev/null"; 215a7015092SGreg Clayton 216a7015092SGreg Clayton Error error (process->Launch (launch_args.GetArgumentCount() ? launch_args.GetConstArgumentVector() : NULL, 217a7015092SGreg Clayton environment.GetArgumentCount() ? environment.GetConstArgumentVector() : NULL, 218f681b94fSGreg Clayton launch_flags, 21930fdc8d8SChris Lattner stdin_path, 22030fdc8d8SChris Lattner stdout_path, 22130fdc8d8SChris Lattner stderr_path)); 22230fdc8d8SChris Lattner 22330fdc8d8SChris Lattner if (error.Success()) 22430fdc8d8SChris Lattner { 22530fdc8d8SChris Lattner result.AppendMessageWithFormat ("Launching '%s' (%s)\n", filename, archname); 22630fdc8d8SChris Lattner result.SetStatus (eReturnStatusSuccessContinuingNoResult); 22730fdc8d8SChris Lattner if (m_options.stop_at_entry == false) 22830fdc8d8SChris Lattner { 22930fdc8d8SChris Lattner StateType state = process->WaitForProcessToStop (NULL); 23030fdc8d8SChris Lattner 23130fdc8d8SChris Lattner if (state == eStateStopped) 23230fdc8d8SChris Lattner { 23330fdc8d8SChris Lattner // Call continue_command. 23430fdc8d8SChris Lattner CommandReturnObject continue_result; 235a7015092SGreg Clayton m_interpreter.HandleCommand("process continue", false, continue_result); 23630fdc8d8SChris Lattner } 23730fdc8d8SChris Lattner 23830fdc8d8SChris Lattner if (synchronous_execution) 23930fdc8d8SChris Lattner { 24030fdc8d8SChris Lattner result.SetDidChangeProcessState (true); 24130fdc8d8SChris Lattner result.SetStatus (eReturnStatusSuccessFinishNoResult); 24230fdc8d8SChris Lattner } 24330fdc8d8SChris Lattner } 24430fdc8d8SChris Lattner } 24530fdc8d8SChris Lattner 24630fdc8d8SChris Lattner return result.Succeeded(); 24730fdc8d8SChris Lattner } 24830fdc8d8SChris Lattner 249ebc09c36SJim Ingham virtual const char *GetRepeatCommand (Args ¤t_command_args, uint32_t index) 250ebc09c36SJim Ingham { 251ebc09c36SJim Ingham // No repeat for "process launch"... 252ebc09c36SJim Ingham return ""; 253ebc09c36SJim Ingham } 254ebc09c36SJim Ingham 25530fdc8d8SChris Lattner protected: 25630fdc8d8SChris Lattner 25730fdc8d8SChris Lattner CommandOptions m_options; 25830fdc8d8SChris Lattner }; 25930fdc8d8SChris Lattner 26030fdc8d8SChris Lattner 26130fdc8d8SChris Lattner lldb::OptionDefinition 26230fdc8d8SChris Lattner CommandObjectProcessLaunch::CommandOptions::g_option_table[] = 26330fdc8d8SChris Lattner { 264*deaab222SCaroline Tice { LLDB_OPT_SET_1, false, "stop-at-entry", 's', no_argument, NULL, 0, eArgTypeNone, "Stop at the entry point of the program when launching a process."}, 265*deaab222SCaroline Tice { LLDB_OPT_SET_1, false, "stdin", 'i', required_argument, NULL, 0, eArgTypePath, "Redirect stdin for the process to <path>."}, 266*deaab222SCaroline Tice { LLDB_OPT_SET_1, false, "stdout", 'o', required_argument, NULL, 0, eArgTypePath, "Redirect stdout for the process to <path>."}, 267*deaab222SCaroline Tice { LLDB_OPT_SET_1, false, "stderr", 'e', required_argument, NULL, 0, eArgTypePath, "Redirect stderr for the process to <path>."}, 268*deaab222SCaroline Tice { LLDB_OPT_SET_1, false, "plugin", 'p', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."}, 269*deaab222SCaroline Tice { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 27030fdc8d8SChris Lattner }; 27130fdc8d8SChris Lattner 27230fdc8d8SChris Lattner 27330fdc8d8SChris Lattner //------------------------------------------------------------------------- 27430fdc8d8SChris Lattner // CommandObjectProcessAttach 27530fdc8d8SChris Lattner //------------------------------------------------------------------------- 27630fdc8d8SChris Lattner 27730fdc8d8SChris Lattner class CommandObjectProcessAttach : public CommandObject 27830fdc8d8SChris Lattner { 27930fdc8d8SChris Lattner public: 28030fdc8d8SChris Lattner 28130fdc8d8SChris Lattner class CommandOptions : public Options 28230fdc8d8SChris Lattner { 28330fdc8d8SChris Lattner public: 28430fdc8d8SChris Lattner 28530fdc8d8SChris Lattner CommandOptions () : 28630fdc8d8SChris Lattner Options() 28730fdc8d8SChris Lattner { 28830fdc8d8SChris Lattner // Keep default values of all options in one place: ResetOptionValues () 28930fdc8d8SChris Lattner ResetOptionValues (); 29030fdc8d8SChris Lattner } 29130fdc8d8SChris Lattner 29230fdc8d8SChris Lattner ~CommandOptions () 29330fdc8d8SChris Lattner { 29430fdc8d8SChris Lattner } 29530fdc8d8SChris Lattner 29630fdc8d8SChris Lattner Error 29730fdc8d8SChris Lattner SetOptionValue (int option_idx, const char *option_arg) 29830fdc8d8SChris Lattner { 29930fdc8d8SChris Lattner Error error; 30030fdc8d8SChris Lattner char short_option = (char) m_getopt_table[option_idx].val; 30130fdc8d8SChris Lattner bool success = false; 30230fdc8d8SChris Lattner switch (short_option) 30330fdc8d8SChris Lattner { 30430fdc8d8SChris Lattner case 'p': 30530fdc8d8SChris Lattner pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success); 30630fdc8d8SChris Lattner if (!success || pid == LLDB_INVALID_PROCESS_ID) 30730fdc8d8SChris Lattner { 30830fdc8d8SChris Lattner error.SetErrorStringWithFormat("Invalid process ID '%s'.\n", option_arg); 30930fdc8d8SChris Lattner } 31030fdc8d8SChris Lattner break; 31130fdc8d8SChris Lattner 31230fdc8d8SChris Lattner case 'P': 31330fdc8d8SChris Lattner plugin_name = option_arg; 31430fdc8d8SChris Lattner break; 31530fdc8d8SChris Lattner 31630fdc8d8SChris Lattner case 'n': 31730fdc8d8SChris Lattner name.assign(option_arg); 31830fdc8d8SChris Lattner break; 31930fdc8d8SChris Lattner 32030fdc8d8SChris Lattner case 'w': 32130fdc8d8SChris Lattner waitfor = true; 32230fdc8d8SChris Lattner break; 32330fdc8d8SChris Lattner 32430fdc8d8SChris Lattner default: 32530fdc8d8SChris Lattner error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option); 32630fdc8d8SChris Lattner break; 32730fdc8d8SChris Lattner } 32830fdc8d8SChris Lattner return error; 32930fdc8d8SChris Lattner } 33030fdc8d8SChris Lattner 33130fdc8d8SChris Lattner void 33230fdc8d8SChris Lattner ResetOptionValues () 33330fdc8d8SChris Lattner { 33430fdc8d8SChris Lattner Options::ResetOptionValues(); 33530fdc8d8SChris Lattner pid = LLDB_INVALID_PROCESS_ID; 33630fdc8d8SChris Lattner name.clear(); 33730fdc8d8SChris Lattner waitfor = false; 33830fdc8d8SChris Lattner } 33930fdc8d8SChris Lattner 34030fdc8d8SChris Lattner const lldb::OptionDefinition* 34130fdc8d8SChris Lattner GetDefinitions () 34230fdc8d8SChris Lattner { 34330fdc8d8SChris Lattner return g_option_table; 34430fdc8d8SChris Lattner } 34530fdc8d8SChris Lattner 3465aee162fSJim Ingham virtual bool 347a7015092SGreg Clayton HandleOptionArgumentCompletion (CommandInterpreter &interpeter, 3485aee162fSJim Ingham Args &input, 3495aee162fSJim Ingham int cursor_index, 3505aee162fSJim Ingham int char_pos, 3515aee162fSJim Ingham OptionElementVector &opt_element_vector, 3525aee162fSJim Ingham int opt_element_index, 3535aee162fSJim Ingham int match_start_point, 3545aee162fSJim Ingham int max_return_elements, 3555aee162fSJim Ingham bool &word_complete, 3565aee162fSJim Ingham StringList &matches) 3575aee162fSJim Ingham { 3585aee162fSJim Ingham int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos; 3595aee162fSJim Ingham int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index; 3605aee162fSJim Ingham 3615aee162fSJim Ingham // We are only completing the name option for now... 3625aee162fSJim Ingham 3635aee162fSJim Ingham const lldb::OptionDefinition *opt_defs = GetDefinitions(); 3645aee162fSJim Ingham if (opt_defs[opt_defs_index].short_option == 'n') 3655aee162fSJim Ingham { 3665aee162fSJim Ingham // Are we in the name? 3675aee162fSJim Ingham 3685aee162fSJim Ingham // Look to see if there is a -P argument provided, and if so use that plugin, otherwise 3695aee162fSJim Ingham // use the default plugin. 370a7015092SGreg Clayton Process *process = interpeter.GetDebugger().GetExecutionContext().process; 3715aee162fSJim Ingham bool need_to_delete_process = false; 3725aee162fSJim Ingham 3735aee162fSJim Ingham const char *partial_name = NULL; 3745aee162fSJim Ingham partial_name = input.GetArgumentAtIndex(opt_arg_pos); 3755aee162fSJim Ingham 3765aee162fSJim Ingham if (process && process->IsAlive()) 3775aee162fSJim Ingham return true; 3785aee162fSJim Ingham 379a7015092SGreg Clayton Target *target = interpeter.GetDebugger().GetSelectedTarget().get(); 3805aee162fSJim Ingham if (target == NULL) 3815aee162fSJim Ingham { 3825aee162fSJim Ingham // No target has been set yet, for now do host completion. Otherwise I don't know how we would 3835aee162fSJim Ingham // figure out what the right target to use is... 3845aee162fSJim Ingham std::vector<lldb::pid_t> pids; 3855aee162fSJim Ingham Host::ListProcessesMatchingName (partial_name, matches, pids); 3865aee162fSJim Ingham return true; 3875aee162fSJim Ingham } 3885aee162fSJim Ingham if (!process) 3895aee162fSJim Ingham { 390a7015092SGreg Clayton process = target->CreateProcess (interpeter.GetDebugger().GetListener(), partial_name).get(); 3915aee162fSJim Ingham need_to_delete_process = true; 3925aee162fSJim Ingham } 3935aee162fSJim Ingham 3945aee162fSJim Ingham if (process) 3955aee162fSJim Ingham { 3965aee162fSJim Ingham matches.Clear(); 3975aee162fSJim Ingham std::vector<lldb::pid_t> pids; 3985aee162fSJim Ingham process->ListProcessesMatchingName (NULL, matches, pids); 3995aee162fSJim Ingham if (need_to_delete_process) 4005aee162fSJim Ingham target->DeleteCurrentProcess(); 4015aee162fSJim Ingham return true; 4025aee162fSJim Ingham } 4035aee162fSJim Ingham } 4045aee162fSJim Ingham 4055aee162fSJim Ingham return false; 4065aee162fSJim Ingham } 4075aee162fSJim Ingham 40830fdc8d8SChris Lattner // Options table: Required for subclasses of Options. 40930fdc8d8SChris Lattner 41030fdc8d8SChris Lattner static lldb::OptionDefinition g_option_table[]; 41130fdc8d8SChris Lattner 41230fdc8d8SChris Lattner // Instance variables to hold the values for command options. 41330fdc8d8SChris Lattner 41430fdc8d8SChris Lattner lldb::pid_t pid; 41530fdc8d8SChris Lattner std::string plugin_name; 41630fdc8d8SChris Lattner std::string name; 41730fdc8d8SChris Lattner bool waitfor; 41830fdc8d8SChris Lattner }; 41930fdc8d8SChris Lattner 420a7015092SGreg Clayton CommandObjectProcessAttach (CommandInterpreter &interpreter) : 421a7015092SGreg Clayton CommandObject (interpreter, 422a7015092SGreg Clayton "process attach", 423e3d26315SCaroline Tice "Attach to a process.", 4245aee162fSJim Ingham "process attach <cmd-options>") 4255aee162fSJim Ingham { 4265aee162fSJim Ingham } 4275aee162fSJim Ingham 4285aee162fSJim Ingham ~CommandObjectProcessAttach () 4295aee162fSJim Ingham { 4305aee162fSJim Ingham } 4315aee162fSJim Ingham 4325aee162fSJim Ingham bool 433a7015092SGreg Clayton Execute (Args& command, 4345aee162fSJim Ingham CommandReturnObject &result) 4355aee162fSJim Ingham { 436a7015092SGreg Clayton Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 4375aee162fSJim Ingham 438a7015092SGreg Clayton Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; 4395aee162fSJim Ingham if (process) 4405aee162fSJim Ingham { 4415aee162fSJim Ingham if (process->IsAlive()) 4425aee162fSJim Ingham { 4435aee162fSJim Ingham result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before attaching.\n", 4445aee162fSJim Ingham process->GetID()); 4455aee162fSJim Ingham result.SetStatus (eReturnStatusFailed); 4465aee162fSJim Ingham return false; 4475aee162fSJim Ingham } 4485aee162fSJim Ingham } 4495aee162fSJim Ingham 4505aee162fSJim Ingham if (target == NULL) 4515aee162fSJim Ingham { 4525aee162fSJim Ingham // If there isn't a current target create one. 4535aee162fSJim Ingham TargetSP new_target_sp; 4545aee162fSJim Ingham FileSpec emptyFileSpec; 4555aee162fSJim Ingham ArchSpec emptyArchSpec; 4565aee162fSJim Ingham Error error; 4575aee162fSJim Ingham 458a7015092SGreg Clayton error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(), 4595aee162fSJim Ingham emptyFileSpec, 4605aee162fSJim Ingham emptyArchSpec, 4615aee162fSJim Ingham NULL, 4625aee162fSJim Ingham false, 4635aee162fSJim Ingham new_target_sp); 4645aee162fSJim Ingham target = new_target_sp.get(); 4655aee162fSJim Ingham if (target == NULL || error.Fail()) 4665aee162fSJim Ingham { 4675aee162fSJim Ingham result.AppendError(error.AsCString("Error creating empty target")); 4685aee162fSJim Ingham return false; 4695aee162fSJim Ingham } 470a7015092SGreg Clayton m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target); 4715aee162fSJim Ingham } 4725aee162fSJim Ingham 4735aee162fSJim Ingham // Record the old executable module, we want to issue a warning if the process of attaching changed the 4745aee162fSJim Ingham // current executable (like somebody said "file foo" then attached to a PID whose executable was bar.) 4755aee162fSJim Ingham 4765aee162fSJim Ingham ModuleSP old_exec_module_sp = target->GetExecutableModule(); 4775aee162fSJim Ingham ArchSpec old_arch_spec = target->GetArchitecture(); 4785aee162fSJim Ingham 4795aee162fSJim Ingham if (command.GetArgumentCount()) 4805aee162fSJim Ingham { 4815aee162fSJim Ingham result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str()); 4825aee162fSJim Ingham result.SetStatus (eReturnStatusFailed); 4835aee162fSJim Ingham } 4845aee162fSJim Ingham else 4855aee162fSJim Ingham { 4865aee162fSJim Ingham const char *plugin_name = NULL; 4875aee162fSJim Ingham 4885aee162fSJim Ingham if (!m_options.plugin_name.empty()) 4895aee162fSJim Ingham plugin_name = m_options.plugin_name.c_str(); 4905aee162fSJim Ingham 491a7015092SGreg Clayton process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get(); 4925aee162fSJim Ingham 4935aee162fSJim Ingham if (process) 4945aee162fSJim Ingham { 4955aee162fSJim Ingham Error error; 4965aee162fSJim Ingham int attach_pid = m_options.pid; 4975aee162fSJim Ingham 4983a0b9cdfSJim Ingham const char *wait_name = NULL; 4993a0b9cdfSJim Ingham 5005aee162fSJim Ingham if (m_options.name.empty()) 5015aee162fSJim Ingham { 5023a0b9cdfSJim Ingham if (old_exec_module_sp) 5033a0b9cdfSJim Ingham { 5043a0b9cdfSJim Ingham wait_name = old_exec_module_sp->GetFileSpec().GetFilename().AsCString(); 5053a0b9cdfSJim Ingham } 5065aee162fSJim Ingham } 5075aee162fSJim Ingham else 5085aee162fSJim Ingham { 5093a0b9cdfSJim Ingham wait_name = m_options.name.c_str(); 5103a0b9cdfSJim Ingham } 5113a0b9cdfSJim Ingham 5123a0b9cdfSJim Ingham // If we are waiting for a process with this name to show up, do that first. 5133a0b9cdfSJim Ingham if (m_options.waitfor) 5143a0b9cdfSJim Ingham { 5153a0b9cdfSJim Ingham 5163a0b9cdfSJim Ingham if (wait_name == NULL) 5173a0b9cdfSJim Ingham { 5183a0b9cdfSJim Ingham result.AppendError("Invalid arguments: must have a file loaded or supply a process name with the waitfor option.\n"); 5193a0b9cdfSJim Ingham result.SetStatus (eReturnStatusFailed); 5203a0b9cdfSJim Ingham return false; 5213a0b9cdfSJim Ingham } 5223a0b9cdfSJim Ingham 523a7015092SGreg Clayton m_interpreter.GetDebugger().GetOutputStream().Printf("Waiting to attach to a process named \"%s\".\n", wait_name); 5243a0b9cdfSJim Ingham error = process->Attach (wait_name, m_options.waitfor); 5255aee162fSJim Ingham if (error.Success()) 5265aee162fSJim Ingham { 5275aee162fSJim Ingham result.SetStatus (eReturnStatusSuccessContinuingNoResult); 5285aee162fSJim Ingham } 5295aee162fSJim Ingham else 5305aee162fSJim Ingham { 5315aee162fSJim Ingham result.AppendErrorWithFormat ("Waiting for a process to launch named '%s': %s\n", 5323a0b9cdfSJim Ingham wait_name, 5335aee162fSJim Ingham error.AsCString()); 5345aee162fSJim Ingham result.SetStatus (eReturnStatusFailed); 5355aee162fSJim Ingham return false; 5365aee162fSJim Ingham } 5375aee162fSJim Ingham } 5385aee162fSJim Ingham else 5395aee162fSJim Ingham { 5405aee162fSJim Ingham // If the process was specified by name look it up, so we can warn if there are multiple 5415aee162fSJim Ingham // processes with this pid. 5425aee162fSJim Ingham 5433a0b9cdfSJim Ingham if (attach_pid == LLDB_INVALID_PROCESS_ID && wait_name != NULL) 5445aee162fSJim Ingham { 5455aee162fSJim Ingham std::vector<lldb::pid_t> pids; 5465aee162fSJim Ingham StringList matches; 5475aee162fSJim Ingham 5483a0b9cdfSJim Ingham process->ListProcessesMatchingName(wait_name, matches, pids); 5495aee162fSJim Ingham if (matches.GetSize() > 1) 5505aee162fSJim Ingham { 5513a0b9cdfSJim Ingham result.AppendErrorWithFormat("More than one process named %s\n", wait_name); 5525aee162fSJim Ingham result.SetStatus (eReturnStatusFailed); 5535aee162fSJim Ingham return false; 5545aee162fSJim Ingham } 5555aee162fSJim Ingham else if (matches.GetSize() == 0) 5565aee162fSJim Ingham { 5573a0b9cdfSJim Ingham result.AppendErrorWithFormat("Could not find a process named %s\n", wait_name); 5585aee162fSJim Ingham result.SetStatus (eReturnStatusFailed); 5595aee162fSJim Ingham return false; 5605aee162fSJim Ingham } 5615aee162fSJim Ingham else 5625aee162fSJim Ingham { 5635aee162fSJim Ingham attach_pid = pids[0]; 5645aee162fSJim Ingham } 5655aee162fSJim Ingham 5665aee162fSJim Ingham } 5675aee162fSJim Ingham 5685aee162fSJim Ingham if (attach_pid != LLDB_INVALID_PROCESS_ID) 5695aee162fSJim Ingham { 5705aee162fSJim Ingham error = process->Attach (attach_pid); 5715aee162fSJim Ingham if (error.Success()) 5725aee162fSJim Ingham { 5735aee162fSJim Ingham result.SetStatus (eReturnStatusSuccessContinuingNoResult); 5745aee162fSJim Ingham } 5755aee162fSJim Ingham else 5765aee162fSJim Ingham { 5775aee162fSJim Ingham result.AppendErrorWithFormat ("Attaching to process %i failed: %s.\n", 5785aee162fSJim Ingham attach_pid, 5795aee162fSJim Ingham error.AsCString()); 5805aee162fSJim Ingham result.SetStatus (eReturnStatusFailed); 5815aee162fSJim Ingham } 5825aee162fSJim Ingham } 5835aee162fSJim Ingham else 5845aee162fSJim Ingham { 5855aee162fSJim Ingham result.AppendErrorWithFormat ("No PID specified for attach\n", 5865aee162fSJim Ingham attach_pid, 5875aee162fSJim Ingham error.AsCString()); 5885aee162fSJim Ingham result.SetStatus (eReturnStatusFailed); 5895aee162fSJim Ingham 5905aee162fSJim Ingham } 5915aee162fSJim Ingham } 5925aee162fSJim Ingham } 5935aee162fSJim Ingham } 5945aee162fSJim Ingham 5955aee162fSJim Ingham if (result.Succeeded()) 5965aee162fSJim Ingham { 5975aee162fSJim Ingham // Okay, we're done. Last step is to warn if the executable module has changed: 5985aee162fSJim Ingham if (!old_exec_module_sp) 5995aee162fSJim Ingham { 6005aee162fSJim Ingham char new_path[PATH_MAX + 1]; 6015aee162fSJim Ingham target->GetExecutableModule()->GetFileSpec().GetPath(new_path, PATH_MAX); 6025aee162fSJim Ingham 6035aee162fSJim Ingham result.AppendMessageWithFormat("Executable module set to \"%s\".\n", 6045aee162fSJim Ingham new_path); 6055aee162fSJim Ingham } 6065aee162fSJim Ingham else if (old_exec_module_sp->GetFileSpec() != target->GetExecutableModule()->GetFileSpec()) 6075aee162fSJim Ingham { 6085aee162fSJim Ingham char old_path[PATH_MAX + 1]; 6095aee162fSJim Ingham char new_path[PATH_MAX + 1]; 6105aee162fSJim Ingham 6115aee162fSJim Ingham old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX); 6125aee162fSJim Ingham target->GetExecutableModule()->GetFileSpec().GetPath (new_path, PATH_MAX); 6135aee162fSJim Ingham 6145aee162fSJim Ingham result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n", 6155aee162fSJim Ingham old_path, new_path); 6165aee162fSJim Ingham } 6175aee162fSJim Ingham 6185aee162fSJim Ingham if (!old_arch_spec.IsValid()) 6195aee162fSJim Ingham { 6205aee162fSJim Ingham result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().AsCString()); 6215aee162fSJim Ingham } 6225aee162fSJim Ingham else if (old_arch_spec != target->GetArchitecture()) 6235aee162fSJim Ingham { 6245aee162fSJim Ingham result.AppendWarningWithFormat("Architecture changed from %s to %s.\n", 6255aee162fSJim Ingham old_arch_spec.AsCString(), target->GetArchitecture().AsCString()); 6265aee162fSJim Ingham } 6275aee162fSJim Ingham } 6285aee162fSJim Ingham return result.Succeeded(); 6295aee162fSJim Ingham } 6305aee162fSJim Ingham 6315aee162fSJim Ingham Options * 6325aee162fSJim Ingham GetOptions () 6335aee162fSJim Ingham { 6345aee162fSJim Ingham return &m_options; 6355aee162fSJim Ingham } 6365aee162fSJim Ingham 63730fdc8d8SChris Lattner protected: 63830fdc8d8SChris Lattner 63930fdc8d8SChris Lattner CommandOptions m_options; 64030fdc8d8SChris Lattner }; 64130fdc8d8SChris Lattner 64230fdc8d8SChris Lattner 64330fdc8d8SChris Lattner lldb::OptionDefinition 64430fdc8d8SChris Lattner CommandObjectProcessAttach::CommandOptions::g_option_table[] = 64530fdc8d8SChris Lattner { 646*deaab222SCaroline Tice { LLDB_OPT_SET_ALL, false, "plugin", 'P', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."}, 647*deaab222SCaroline Tice { LLDB_OPT_SET_1, false, "pid", 'p', required_argument, NULL, 0, eArgTypePid, "The process ID of an existing process to attach to."}, 648*deaab222SCaroline Tice { LLDB_OPT_SET_2, false, "name", 'n', required_argument, NULL, 0, eArgTypeProcessName, "The name of the process to attach to."}, 649*deaab222SCaroline Tice { LLDB_OPT_SET_2, false, "waitfor",'w', no_argument, NULL, 0, eArgTypeNone, "Wait for the the process with <process-name> to launch."}, 650*deaab222SCaroline Tice { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 65130fdc8d8SChris Lattner }; 65230fdc8d8SChris Lattner 65330fdc8d8SChris Lattner //------------------------------------------------------------------------- 65430fdc8d8SChris Lattner // CommandObjectProcessContinue 65530fdc8d8SChris Lattner //------------------------------------------------------------------------- 65630fdc8d8SChris Lattner 65730fdc8d8SChris Lattner class CommandObjectProcessContinue : public CommandObject 65830fdc8d8SChris Lattner { 65930fdc8d8SChris Lattner public: 66030fdc8d8SChris Lattner 661a7015092SGreg Clayton CommandObjectProcessContinue (CommandInterpreter &interpreter) : 662a7015092SGreg Clayton CommandObject (interpreter, 663a7015092SGreg Clayton "process continue", 664e3d26315SCaroline Tice "Continue execution of all threads in the current process.", 66530fdc8d8SChris Lattner "process continue", 66630fdc8d8SChris Lattner eFlagProcessMustBeLaunched | eFlagProcessMustBePaused) 66730fdc8d8SChris Lattner { 66830fdc8d8SChris Lattner } 66930fdc8d8SChris Lattner 67030fdc8d8SChris Lattner 67130fdc8d8SChris Lattner ~CommandObjectProcessContinue () 67230fdc8d8SChris Lattner { 67330fdc8d8SChris Lattner } 67430fdc8d8SChris Lattner 67530fdc8d8SChris Lattner bool 676a7015092SGreg Clayton Execute (Args& command, 67730fdc8d8SChris Lattner CommandReturnObject &result) 67830fdc8d8SChris Lattner { 679a7015092SGreg Clayton Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; 680a7015092SGreg Clayton bool synchronous_execution = m_interpreter.GetSynchronous (); 68130fdc8d8SChris Lattner 68230fdc8d8SChris Lattner if (process == NULL) 68330fdc8d8SChris Lattner { 68430fdc8d8SChris Lattner result.AppendError ("no process to continue"); 68530fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 68630fdc8d8SChris Lattner return false; 68730fdc8d8SChris Lattner } 68830fdc8d8SChris Lattner 68930fdc8d8SChris Lattner StateType state = process->GetState(); 69030fdc8d8SChris Lattner if (state == eStateStopped) 69130fdc8d8SChris Lattner { 69230fdc8d8SChris Lattner if (command.GetArgumentCount() != 0) 69330fdc8d8SChris Lattner { 69430fdc8d8SChris Lattner result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str()); 69530fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 69630fdc8d8SChris Lattner return false; 69730fdc8d8SChris Lattner } 69830fdc8d8SChris Lattner 69930fdc8d8SChris Lattner const uint32_t num_threads = process->GetThreadList().GetSize(); 70030fdc8d8SChris Lattner 70130fdc8d8SChris Lattner // Set the actions that the threads should each take when resuming 70230fdc8d8SChris Lattner for (uint32_t idx=0; idx<num_threads; ++idx) 70330fdc8d8SChris Lattner { 70430fdc8d8SChris Lattner process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning); 70530fdc8d8SChris Lattner } 70630fdc8d8SChris Lattner 70730fdc8d8SChris Lattner Error error(process->Resume()); 70830fdc8d8SChris Lattner if (error.Success()) 70930fdc8d8SChris Lattner { 71030fdc8d8SChris Lattner result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID()); 71130fdc8d8SChris Lattner if (synchronous_execution) 71230fdc8d8SChris Lattner { 713b132097bSGreg Clayton state = process->WaitForProcessToStop (NULL); 71430fdc8d8SChris Lattner 71530fdc8d8SChris Lattner result.SetDidChangeProcessState (true); 71630fdc8d8SChris Lattner result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state)); 71730fdc8d8SChris Lattner result.SetStatus (eReturnStatusSuccessFinishNoResult); 71830fdc8d8SChris Lattner } 71930fdc8d8SChris Lattner else 72030fdc8d8SChris Lattner { 72130fdc8d8SChris Lattner result.SetStatus (eReturnStatusSuccessContinuingNoResult); 72230fdc8d8SChris Lattner } 72330fdc8d8SChris Lattner } 72430fdc8d8SChris Lattner else 72530fdc8d8SChris Lattner { 72630fdc8d8SChris Lattner result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString()); 72730fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 72830fdc8d8SChris Lattner } 72930fdc8d8SChris Lattner } 73030fdc8d8SChris Lattner else 73130fdc8d8SChris Lattner { 73230fdc8d8SChris Lattner result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n", 73330fdc8d8SChris Lattner StateAsCString(state)); 73430fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 73530fdc8d8SChris Lattner } 73630fdc8d8SChris Lattner return result.Succeeded(); 73730fdc8d8SChris Lattner } 73830fdc8d8SChris Lattner }; 73930fdc8d8SChris Lattner 74030fdc8d8SChris Lattner //------------------------------------------------------------------------- 74130fdc8d8SChris Lattner // CommandObjectProcessDetach 74230fdc8d8SChris Lattner //------------------------------------------------------------------------- 74330fdc8d8SChris Lattner 74430fdc8d8SChris Lattner class CommandObjectProcessDetach : public CommandObject 74530fdc8d8SChris Lattner { 74630fdc8d8SChris Lattner public: 74730fdc8d8SChris Lattner 748a7015092SGreg Clayton CommandObjectProcessDetach (CommandInterpreter &interpreter) : 749a7015092SGreg Clayton CommandObject (interpreter, 750a7015092SGreg Clayton "process detach", 751e3d26315SCaroline Tice "Detach from the current process being debugged.", 75230fdc8d8SChris Lattner "process detach", 75330fdc8d8SChris Lattner eFlagProcessMustBeLaunched) 75430fdc8d8SChris Lattner { 75530fdc8d8SChris Lattner } 75630fdc8d8SChris Lattner 75730fdc8d8SChris Lattner ~CommandObjectProcessDetach () 75830fdc8d8SChris Lattner { 75930fdc8d8SChris Lattner } 76030fdc8d8SChris Lattner 76130fdc8d8SChris Lattner bool 762a7015092SGreg Clayton Execute (Args& command, 76330fdc8d8SChris Lattner CommandReturnObject &result) 76430fdc8d8SChris Lattner { 765a7015092SGreg Clayton Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; 76630fdc8d8SChris Lattner if (process == NULL) 76730fdc8d8SChris Lattner { 76830fdc8d8SChris Lattner result.AppendError ("must have a valid process in order to detach"); 76930fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 77030fdc8d8SChris Lattner return false; 77130fdc8d8SChris Lattner } 77230fdc8d8SChris Lattner 77330fdc8d8SChris Lattner Error error (process->Detach()); 77430fdc8d8SChris Lattner if (error.Success()) 77530fdc8d8SChris Lattner { 77630fdc8d8SChris Lattner result.SetStatus (eReturnStatusSuccessFinishResult); 77730fdc8d8SChris Lattner } 77830fdc8d8SChris Lattner else 77930fdc8d8SChris Lattner { 78030fdc8d8SChris Lattner result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString()); 78130fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 78230fdc8d8SChris Lattner return false; 78330fdc8d8SChris Lattner } 78430fdc8d8SChris Lattner return result.Succeeded(); 78530fdc8d8SChris Lattner } 78630fdc8d8SChris Lattner }; 78730fdc8d8SChris Lattner 78830fdc8d8SChris Lattner //------------------------------------------------------------------------- 78930fdc8d8SChris Lattner // CommandObjectProcessSignal 79030fdc8d8SChris Lattner //------------------------------------------------------------------------- 79130fdc8d8SChris Lattner 79230fdc8d8SChris Lattner class CommandObjectProcessSignal : public CommandObject 79330fdc8d8SChris Lattner { 79430fdc8d8SChris Lattner public: 79530fdc8d8SChris Lattner 796a7015092SGreg Clayton CommandObjectProcessSignal (CommandInterpreter &interpreter) : 797a7015092SGreg Clayton CommandObject (interpreter, 798a7015092SGreg Clayton "process signal", 799e3d26315SCaroline Tice "Send a UNIX signal to the current process being debugged.", 80030fdc8d8SChris Lattner "process signal <unix-signal-number>") 80130fdc8d8SChris Lattner { 80230fdc8d8SChris Lattner } 80330fdc8d8SChris Lattner 80430fdc8d8SChris Lattner ~CommandObjectProcessSignal () 80530fdc8d8SChris Lattner { 80630fdc8d8SChris Lattner } 80730fdc8d8SChris Lattner 80830fdc8d8SChris Lattner bool 809a7015092SGreg Clayton Execute (Args& command, 81030fdc8d8SChris Lattner CommandReturnObject &result) 81130fdc8d8SChris Lattner { 812a7015092SGreg Clayton Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; 81330fdc8d8SChris Lattner if (process == NULL) 81430fdc8d8SChris Lattner { 81530fdc8d8SChris Lattner result.AppendError ("no process to signal"); 81630fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 81730fdc8d8SChris Lattner return false; 81830fdc8d8SChris Lattner } 81930fdc8d8SChris Lattner 82030fdc8d8SChris Lattner if (command.GetArgumentCount() == 1) 82130fdc8d8SChris Lattner { 82230fdc8d8SChris Lattner int signo = Args::StringToSInt32(command.GetArgumentAtIndex(0), -1, 0); 82330fdc8d8SChris Lattner if (signo == -1) 82430fdc8d8SChris Lattner { 82530fdc8d8SChris Lattner result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0)); 82630fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 82730fdc8d8SChris Lattner } 82830fdc8d8SChris Lattner else 82930fdc8d8SChris Lattner { 83030fdc8d8SChris Lattner Error error (process->Signal (signo)); 83130fdc8d8SChris Lattner if (error.Success()) 83230fdc8d8SChris Lattner { 83330fdc8d8SChris Lattner result.SetStatus (eReturnStatusSuccessFinishResult); 83430fdc8d8SChris Lattner } 83530fdc8d8SChris Lattner else 83630fdc8d8SChris Lattner { 83730fdc8d8SChris Lattner result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString()); 83830fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 83930fdc8d8SChris Lattner } 84030fdc8d8SChris Lattner } 84130fdc8d8SChris Lattner } 84230fdc8d8SChris Lattner else 84330fdc8d8SChris Lattner { 84430fdc8d8SChris Lattner result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: \n", m_cmd_name.c_str(), 84530fdc8d8SChris Lattner m_cmd_syntax.c_str()); 84630fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 84730fdc8d8SChris Lattner } 84830fdc8d8SChris Lattner return result.Succeeded(); 84930fdc8d8SChris Lattner } 85030fdc8d8SChris Lattner }; 85130fdc8d8SChris Lattner 85230fdc8d8SChris Lattner 85330fdc8d8SChris Lattner //------------------------------------------------------------------------- 85430fdc8d8SChris Lattner // CommandObjectProcessInterrupt 85530fdc8d8SChris Lattner //------------------------------------------------------------------------- 85630fdc8d8SChris Lattner 85730fdc8d8SChris Lattner class CommandObjectProcessInterrupt : public CommandObject 85830fdc8d8SChris Lattner { 85930fdc8d8SChris Lattner public: 86030fdc8d8SChris Lattner 86130fdc8d8SChris Lattner 862a7015092SGreg Clayton CommandObjectProcessInterrupt (CommandInterpreter &interpreter) : 863a7015092SGreg Clayton CommandObject (interpreter, 864a7015092SGreg Clayton "process interrupt", 865e3d26315SCaroline Tice "Interrupt the current process being debugged.", 86630fdc8d8SChris Lattner "process interrupt", 86730fdc8d8SChris Lattner eFlagProcessMustBeLaunched) 86830fdc8d8SChris Lattner { 86930fdc8d8SChris Lattner } 87030fdc8d8SChris Lattner 87130fdc8d8SChris Lattner ~CommandObjectProcessInterrupt () 87230fdc8d8SChris Lattner { 87330fdc8d8SChris Lattner } 87430fdc8d8SChris Lattner 87530fdc8d8SChris Lattner bool 876a7015092SGreg Clayton Execute (Args& command, 87730fdc8d8SChris Lattner CommandReturnObject &result) 87830fdc8d8SChris Lattner { 879a7015092SGreg Clayton Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; 88030fdc8d8SChris Lattner if (process == NULL) 88130fdc8d8SChris Lattner { 88230fdc8d8SChris Lattner result.AppendError ("no process to halt"); 88330fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 88430fdc8d8SChris Lattner return false; 88530fdc8d8SChris Lattner } 88630fdc8d8SChris Lattner 88730fdc8d8SChris Lattner if (command.GetArgumentCount() == 0) 88830fdc8d8SChris Lattner { 88930fdc8d8SChris Lattner Error error(process->Halt ()); 89030fdc8d8SChris Lattner if (error.Success()) 89130fdc8d8SChris Lattner { 89230fdc8d8SChris Lattner result.SetStatus (eReturnStatusSuccessFinishResult); 89330fdc8d8SChris Lattner 89430fdc8d8SChris Lattner // Maybe we should add a "SuspendThreadPlans so we 89530fdc8d8SChris Lattner // can halt, and keep in place all the current thread plans. 89630fdc8d8SChris Lattner process->GetThreadList().DiscardThreadPlans(); 89730fdc8d8SChris Lattner } 89830fdc8d8SChris Lattner else 89930fdc8d8SChris Lattner { 90030fdc8d8SChris Lattner result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString()); 90130fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 90230fdc8d8SChris Lattner } 90330fdc8d8SChris Lattner } 90430fdc8d8SChris Lattner else 90530fdc8d8SChris Lattner { 90630fdc8d8SChris Lattner result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n", 90730fdc8d8SChris Lattner m_cmd_name.c_str(), 90830fdc8d8SChris Lattner m_cmd_syntax.c_str()); 90930fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 91030fdc8d8SChris Lattner } 91130fdc8d8SChris Lattner return result.Succeeded(); 91230fdc8d8SChris Lattner } 91330fdc8d8SChris Lattner }; 91430fdc8d8SChris Lattner 91530fdc8d8SChris Lattner //------------------------------------------------------------------------- 91630fdc8d8SChris Lattner // CommandObjectProcessKill 91730fdc8d8SChris Lattner //------------------------------------------------------------------------- 91830fdc8d8SChris Lattner 91930fdc8d8SChris Lattner class CommandObjectProcessKill : public CommandObject 92030fdc8d8SChris Lattner { 92130fdc8d8SChris Lattner public: 92230fdc8d8SChris Lattner 923a7015092SGreg Clayton CommandObjectProcessKill (CommandInterpreter &interpreter) : 924a7015092SGreg Clayton CommandObject (interpreter, 925a7015092SGreg Clayton "process kill", 926e3d26315SCaroline Tice "Terminate the current process being debugged.", 92730fdc8d8SChris Lattner "process kill", 92830fdc8d8SChris Lattner eFlagProcessMustBeLaunched) 92930fdc8d8SChris Lattner { 93030fdc8d8SChris Lattner } 93130fdc8d8SChris Lattner 93230fdc8d8SChris Lattner ~CommandObjectProcessKill () 93330fdc8d8SChris Lattner { 93430fdc8d8SChris Lattner } 93530fdc8d8SChris Lattner 93630fdc8d8SChris Lattner bool 937a7015092SGreg Clayton Execute (Args& command, 93830fdc8d8SChris Lattner CommandReturnObject &result) 93930fdc8d8SChris Lattner { 940a7015092SGreg Clayton Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; 94130fdc8d8SChris Lattner if (process == NULL) 94230fdc8d8SChris Lattner { 94330fdc8d8SChris Lattner result.AppendError ("no process to kill"); 94430fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 94530fdc8d8SChris Lattner return false; 94630fdc8d8SChris Lattner } 94730fdc8d8SChris Lattner 94830fdc8d8SChris Lattner if (command.GetArgumentCount() == 0) 94930fdc8d8SChris Lattner { 95030fdc8d8SChris Lattner Error error (process->Destroy()); 95130fdc8d8SChris Lattner if (error.Success()) 95230fdc8d8SChris Lattner { 95330fdc8d8SChris Lattner result.SetStatus (eReturnStatusSuccessFinishResult); 95430fdc8d8SChris Lattner } 95530fdc8d8SChris Lattner else 95630fdc8d8SChris Lattner { 95730fdc8d8SChris Lattner result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString()); 95830fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 95930fdc8d8SChris Lattner } 96030fdc8d8SChris Lattner } 96130fdc8d8SChris Lattner else 96230fdc8d8SChris Lattner { 96330fdc8d8SChris Lattner result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n", 96430fdc8d8SChris Lattner m_cmd_name.c_str(), 96530fdc8d8SChris Lattner m_cmd_syntax.c_str()); 96630fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 96730fdc8d8SChris Lattner } 96830fdc8d8SChris Lattner return result.Succeeded(); 96930fdc8d8SChris Lattner } 97030fdc8d8SChris Lattner }; 97130fdc8d8SChris Lattner 97230fdc8d8SChris Lattner //------------------------------------------------------------------------- 9734b9bea87SJim Ingham // CommandObjectProcessStatus 9744b9bea87SJim Ingham //------------------------------------------------------------------------- 9754b9bea87SJim Ingham class CommandObjectProcessStatus : public CommandObject 9764b9bea87SJim Ingham { 9774b9bea87SJim Ingham public: 978a7015092SGreg Clayton CommandObjectProcessStatus (CommandInterpreter &interpreter) : 979a7015092SGreg Clayton CommandObject (interpreter, 980a7015092SGreg Clayton "process status", 981e3d26315SCaroline Tice "Show the current status and location of executing process.", 982e3d26315SCaroline Tice "process status", 9834b9bea87SJim Ingham 0) 9844b9bea87SJim Ingham { 9854b9bea87SJim Ingham } 9864b9bea87SJim Ingham 9874b9bea87SJim Ingham ~CommandObjectProcessStatus() 9884b9bea87SJim Ingham { 9894b9bea87SJim Ingham } 9904b9bea87SJim Ingham 9914b9bea87SJim Ingham 9924b9bea87SJim Ingham bool 9934b9bea87SJim Ingham Execute 9944b9bea87SJim Ingham ( 9954b9bea87SJim Ingham Args& command, 9964b9bea87SJim Ingham CommandReturnObject &result 9974b9bea87SJim Ingham ) 9984b9bea87SJim Ingham { 9994b9bea87SJim Ingham StreamString &output_stream = result.GetOutputStream(); 10004b9bea87SJim Ingham result.SetStatus (eReturnStatusSuccessFinishNoResult); 1001a7015092SGreg Clayton ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext()); 10024b9bea87SJim Ingham if (exe_ctx.process) 10034b9bea87SJim Ingham { 10044b9bea87SJim Ingham const StateType state = exe_ctx.process->GetState(); 10054b9bea87SJim Ingham if (StateIsStoppedState(state)) 10064b9bea87SJim Ingham { 10074b9bea87SJim Ingham if (state == eStateExited) 10084b9bea87SJim Ingham { 10094b9bea87SJim Ingham int exit_status = exe_ctx.process->GetExitStatus(); 10104b9bea87SJim Ingham const char *exit_description = exe_ctx.process->GetExitDescription(); 10114b9bea87SJim Ingham output_stream.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n", 10124b9bea87SJim Ingham exe_ctx.process->GetID(), 10134b9bea87SJim Ingham exit_status, 10144b9bea87SJim Ingham exit_status, 10154b9bea87SJim Ingham exit_description ? exit_description : ""); 10164b9bea87SJim Ingham } 10174b9bea87SJim Ingham else 10184b9bea87SJim Ingham { 10194b9bea87SJim Ingham output_stream.Printf ("Process %d %s\n", exe_ctx.process->GetID(), StateAsCString (state)); 10204b9bea87SJim Ingham if (exe_ctx.thread == NULL) 10214b9bea87SJim Ingham exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get(); 10224b9bea87SJim Ingham if (exe_ctx.thread != NULL) 10234b9bea87SJim Ingham { 1024a7015092SGreg Clayton DisplayThreadsInfo (m_interpreter, &exe_ctx, result, true, true); 10254b9bea87SJim Ingham } 10264b9bea87SJim Ingham else 10274b9bea87SJim Ingham { 10284b9bea87SJim Ingham result.AppendError ("No valid thread found in current process."); 10294b9bea87SJim Ingham result.SetStatus (eReturnStatusFailed); 10304b9bea87SJim Ingham } 10314b9bea87SJim Ingham } 10324b9bea87SJim Ingham } 10334b9bea87SJim Ingham else 10344b9bea87SJim Ingham { 10354b9bea87SJim Ingham output_stream.Printf ("Process %d is running.\n", 10364b9bea87SJim Ingham exe_ctx.process->GetID()); 10374b9bea87SJim Ingham } 10384b9bea87SJim Ingham } 10394b9bea87SJim Ingham else 10404b9bea87SJim Ingham { 10414b9bea87SJim Ingham result.AppendError ("No current location or status available."); 10424b9bea87SJim Ingham result.SetStatus (eReturnStatusFailed); 10434b9bea87SJim Ingham } 10444b9bea87SJim Ingham return result.Succeeded(); 10454b9bea87SJim Ingham } 10464b9bea87SJim Ingham }; 10474b9bea87SJim Ingham 10484b9bea87SJim Ingham //------------------------------------------------------------------------- 104930fdc8d8SChris Lattner // CommandObjectMultiwordProcess 105030fdc8d8SChris Lattner //------------------------------------------------------------------------- 105130fdc8d8SChris Lattner 10526611103cSGreg Clayton CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter &interpreter) : 1053a7015092SGreg Clayton CommandObjectMultiword (interpreter, 1054a7015092SGreg Clayton "process", 105530fdc8d8SChris Lattner "A set of commands for operating on a process.", 105630fdc8d8SChris Lattner "process <subcommand> [<subcommand-options>]") 105730fdc8d8SChris Lattner { 1058a7015092SGreg Clayton LoadSubCommand ("attach", CommandObjectSP (new CommandObjectProcessAttach (interpreter))); 1059a7015092SGreg Clayton LoadSubCommand ("launch", CommandObjectSP (new CommandObjectProcessLaunch (interpreter))); 1060a7015092SGreg Clayton LoadSubCommand ("continue", CommandObjectSP (new CommandObjectProcessContinue (interpreter))); 1061a7015092SGreg Clayton LoadSubCommand ("detach", CommandObjectSP (new CommandObjectProcessDetach (interpreter))); 1062a7015092SGreg Clayton LoadSubCommand ("signal", CommandObjectSP (new CommandObjectProcessSignal (interpreter))); 1063a7015092SGreg Clayton LoadSubCommand ("status", CommandObjectSP (new CommandObjectProcessStatus (interpreter))); 1064a7015092SGreg Clayton LoadSubCommand ("interrupt", CommandObjectSP (new CommandObjectProcessInterrupt (interpreter))); 1065a7015092SGreg Clayton LoadSubCommand ("kill", CommandObjectSP (new CommandObjectProcessKill (interpreter))); 106630fdc8d8SChris Lattner } 106730fdc8d8SChris Lattner 106830fdc8d8SChris Lattner CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess () 106930fdc8d8SChris Lattner { 107030fdc8d8SChris Lattner } 107130fdc8d8SChris Lattner 1072