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 10430fdc8d8SChris Lattner CommandObjectProcessLaunch () : 10530fdc8d8SChris Lattner CommandObject ("process launch", 106e3d26315SCaroline Tice "Launch the executable in the debugger.", 10730fdc8d8SChris Lattner "process launch [<cmd-options>] [<arguments-for-running-the-program>]") 10830fdc8d8SChris Lattner { 10930fdc8d8SChris Lattner } 11030fdc8d8SChris Lattner 11130fdc8d8SChris Lattner 11230fdc8d8SChris Lattner ~CommandObjectProcessLaunch () 11330fdc8d8SChris Lattner { 11430fdc8d8SChris Lattner } 11530fdc8d8SChris Lattner 11630fdc8d8SChris Lattner Options * 11730fdc8d8SChris Lattner GetOptions () 11830fdc8d8SChris Lattner { 11930fdc8d8SChris Lattner return &m_options; 12030fdc8d8SChris Lattner } 12130fdc8d8SChris Lattner 12230fdc8d8SChris Lattner bool 1236611103cSGreg Clayton Execute (CommandInterpreter &interpreter, 1246611103cSGreg Clayton Args& launch_args, 12530fdc8d8SChris Lattner CommandReturnObject &result) 12630fdc8d8SChris Lattner { 1272976d00aSJim Ingham Target *target = interpreter.GetDebugger().GetSelectedTarget().get(); 1286611103cSGreg Clayton bool synchronous_execution = 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 1446611103cSGreg Clayton Process *process = interpreter.GetDebugger().GetExecutionContext().process; 14530fdc8d8SChris Lattner if (process) 14630fdc8d8SChris Lattner { 14730fdc8d8SChris Lattner if (process->IsAlive()) 14830fdc8d8SChris Lattner { 14930fdc8d8SChris Lattner result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before running again.\n", 15030fdc8d8SChris Lattner process->GetID()); 15130fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 15230fdc8d8SChris Lattner return false; 15330fdc8d8SChris Lattner } 15430fdc8d8SChris Lattner } 15530fdc8d8SChris Lattner 15630fdc8d8SChris Lattner const char *plugin_name; 15730fdc8d8SChris Lattner if (!m_options.plugin_name.empty()) 15830fdc8d8SChris Lattner plugin_name = m_options.plugin_name.c_str(); 15930fdc8d8SChris Lattner else 16030fdc8d8SChris Lattner plugin_name = NULL; 16130fdc8d8SChris Lattner 1626611103cSGreg Clayton process = target->CreateProcess (interpreter.GetDebugger().GetListener(), plugin_name).get(); 16330fdc8d8SChris Lattner 1643df9a8dfSCaroline Tice const char *process_name = process->GetInstanceName().AsCString(); 165101c7c20SCaroline Tice const char *debugger_instance_name = interpreter.GetDebugger().GetInstanceName().AsCString(); 1663df9a8dfSCaroline Tice StreamString run_args_var_name; 1673df9a8dfSCaroline Tice StreamString env_vars_var_name; 1683df9a8dfSCaroline Tice StreamString disable_aslr_var_name; 1693df9a8dfSCaroline Tice lldb::SettableVariableType var_type; 1703df9a8dfSCaroline Tice 1713df9a8dfSCaroline Tice Args *run_args = NULL; 1723df9a8dfSCaroline Tice run_args_var_name.Printf ("process.[%s].run-args", process_name); 1733df9a8dfSCaroline Tice StringList run_args_value = Debugger::GetSettingsController()->GetVariable (run_args_var_name.GetData(), 174101c7c20SCaroline Tice var_type, debugger_instance_name); 175101c7c20SCaroline Tice 1763df9a8dfSCaroline Tice if (run_args_value.GetSize() > 0) 1773df9a8dfSCaroline Tice { 1783df9a8dfSCaroline Tice run_args = new Args; 17937c1b431SChris Lattner for (unsigned i = 0, e = run_args_value.GetSize(); i != e; ++i) 1803df9a8dfSCaroline Tice run_args->AppendArgument(run_args_value.GetStringAtIndex(i)); 1813df9a8dfSCaroline Tice } 1823df9a8dfSCaroline Tice 1833df9a8dfSCaroline Tice Args *environment = NULL; 1843df9a8dfSCaroline Tice env_vars_var_name.Printf ("process.[%s].env-vars", process_name); 1853df9a8dfSCaroline Tice StringList env_vars_value = Debugger::GetSettingsController()->GetVariable (env_vars_var_name.GetData(), 186101c7c20SCaroline Tice var_type, debugger_instance_name); 187101c7c20SCaroline Tice 1883df9a8dfSCaroline Tice if (env_vars_value.GetSize() > 0) 1893df9a8dfSCaroline Tice { 1903df9a8dfSCaroline Tice environment = new Args; 19137c1b431SChris Lattner for (unsigned i = 0, e = env_vars_value.GetSize(); i != e; ++i) 1923df9a8dfSCaroline Tice environment->AppendArgument (env_vars_value.GetStringAtIndex (i)); 1933df9a8dfSCaroline Tice } 1943df9a8dfSCaroline Tice 195f681b94fSGreg Clayton uint32_t launch_flags = eLaunchFlagNone; 1963df9a8dfSCaroline Tice disable_aslr_var_name.Printf ("process.[%s].disable-aslr", process_name); 1973df9a8dfSCaroline Tice StringList disable_aslr_value = Debugger::GetSettingsController()->GetVariable(disable_aslr_var_name.GetData(), 198101c7c20SCaroline Tice var_type, 199101c7c20SCaroline Tice debugger_instance_name); 200101c7c20SCaroline Tice 2013df9a8dfSCaroline Tice if (disable_aslr_value.GetSize() > 0) 2023df9a8dfSCaroline Tice { 2033df9a8dfSCaroline Tice if (strcmp (disable_aslr_value.GetStringAtIndex(0), "true") == 0) 204f681b94fSGreg Clayton launch_flags |= eLaunchFlagDisableASLR; 20530fdc8d8SChris Lattner 2063df9a8dfSCaroline Tice } 2073df9a8dfSCaroline Tice 20830fdc8d8SChris Lattner // There are two possible sources of args to be passed to the process upon launching: Those the user 20930fdc8d8SChris Lattner // typed at the run command (launch_args); or those the user pre-set in the run-args variable (run_args). 21030fdc8d8SChris Lattner 21130fdc8d8SChris Lattner // If launch_args is empty, use run_args. 21230fdc8d8SChris Lattner if (launch_args.GetArgumentCount() == 0) 21330fdc8d8SChris Lattner { 21430fdc8d8SChris Lattner if (run_args != NULL) 21530fdc8d8SChris Lattner launch_args.AppendArguments (*run_args); 21630fdc8d8SChris Lattner } 21730fdc8d8SChris Lattner else 21830fdc8d8SChris Lattner { 21930fdc8d8SChris Lattner // launch-args was not empty; use that, AND re-set run-args to contains launch-args values. 2203df9a8dfSCaroline Tice std::string new_run_args; 2213df9a8dfSCaroline Tice launch_args.GetCommandString (new_run_args); 222101c7c20SCaroline Tice Debugger::GetSettingsController()->SetVariable (run_args_var_name.GetData(), new_run_args.c_str(), 223101c7c20SCaroline Tice lldb::eVarSetOperationAssign, false, 224101c7c20SCaroline Tice interpreter.GetDebugger().GetInstanceName().AsCString()); 22530fdc8d8SChris Lattner } 22630fdc8d8SChris Lattner 22730fdc8d8SChris Lattner 22830fdc8d8SChris Lattner if (process) 22930fdc8d8SChris Lattner { 23030fdc8d8SChris Lattner const char *archname = exe_module->GetArchitecture().AsCString(); 23130fdc8d8SChris Lattner 23230fdc8d8SChris Lattner const char * stdin_path = NULL; 23330fdc8d8SChris Lattner const char * stdout_path = NULL; 23430fdc8d8SChris Lattner const char * stderr_path = NULL; 23530fdc8d8SChris Lattner 23630fdc8d8SChris Lattner if (!(m_options.stdin_path.empty() && 23730fdc8d8SChris Lattner m_options.stdout_path.empty() && 23830fdc8d8SChris Lattner m_options.stderr_path.empty())) 23930fdc8d8SChris Lattner { 24030fdc8d8SChris Lattner stdin_path = m_options.stdin_path.empty() ? "/dev/null" : m_options.stdin_path.c_str(); 24130fdc8d8SChris Lattner stdout_path = m_options.stdout_path.empty() ? "/dev/null" : m_options.stdout_path.c_str(); 24230fdc8d8SChris Lattner stderr_path = m_options.stderr_path.empty() ? "/dev/null" : m_options.stderr_path.c_str(); 24330fdc8d8SChris Lattner } 24430fdc8d8SChris Lattner 24530fdc8d8SChris Lattner Error error (process->Launch (launch_args.GetConstArgumentVector(), 24630fdc8d8SChris Lattner environment ? environment->GetConstArgumentVector() : NULL, 247f681b94fSGreg Clayton launch_flags, 24830fdc8d8SChris Lattner stdin_path, 24930fdc8d8SChris Lattner stdout_path, 25030fdc8d8SChris Lattner stderr_path)); 25130fdc8d8SChris Lattner 25230fdc8d8SChris Lattner if (error.Success()) 25330fdc8d8SChris Lattner { 25430fdc8d8SChris Lattner result.AppendMessageWithFormat ("Launching '%s' (%s)\n", filename, archname); 25530fdc8d8SChris Lattner result.SetStatus (eReturnStatusSuccessContinuingNoResult); 25630fdc8d8SChris Lattner if (m_options.stop_at_entry == false) 25730fdc8d8SChris Lattner { 25830fdc8d8SChris Lattner StateType state = process->WaitForProcessToStop (NULL); 25930fdc8d8SChris Lattner 26030fdc8d8SChris Lattner if (state == eStateStopped) 26130fdc8d8SChris Lattner { 26230fdc8d8SChris Lattner // Call continue_command. 26330fdc8d8SChris Lattner CommandReturnObject continue_result; 2646611103cSGreg Clayton interpreter.HandleCommand("process continue", false, continue_result); 26530fdc8d8SChris Lattner } 26630fdc8d8SChris Lattner 26730fdc8d8SChris Lattner if (synchronous_execution) 26830fdc8d8SChris Lattner { 26930fdc8d8SChris Lattner result.SetDidChangeProcessState (true); 27030fdc8d8SChris Lattner result.SetStatus (eReturnStatusSuccessFinishNoResult); 27130fdc8d8SChris Lattner } 27230fdc8d8SChris Lattner } 27330fdc8d8SChris Lattner } 27430fdc8d8SChris Lattner else 27530fdc8d8SChris Lattner { 27630fdc8d8SChris Lattner result.AppendErrorWithFormat ("Process launch failed: %s", 27730fdc8d8SChris Lattner error.AsCString()); 27830fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 27930fdc8d8SChris Lattner } 28030fdc8d8SChris Lattner } 28130fdc8d8SChris Lattner else 28230fdc8d8SChris Lattner { 28330fdc8d8SChris Lattner result.AppendErrorWithFormat ("Process launch failed: unable to create a process object.\n"); 28430fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 28530fdc8d8SChris Lattner return false; 28630fdc8d8SChris Lattner } 28730fdc8d8SChris Lattner 28830fdc8d8SChris Lattner return result.Succeeded(); 28930fdc8d8SChris Lattner } 29030fdc8d8SChris Lattner 291ebc09c36SJim Ingham virtual const char *GetRepeatCommand (Args ¤t_command_args, uint32_t index) 292ebc09c36SJim Ingham { 293ebc09c36SJim Ingham // No repeat for "process launch"... 294ebc09c36SJim Ingham return ""; 295ebc09c36SJim Ingham } 296ebc09c36SJim Ingham 29730fdc8d8SChris Lattner protected: 29830fdc8d8SChris Lattner 29930fdc8d8SChris Lattner CommandOptions m_options; 30030fdc8d8SChris Lattner }; 30130fdc8d8SChris Lattner 30230fdc8d8SChris Lattner 30330fdc8d8SChris Lattner lldb::OptionDefinition 30430fdc8d8SChris Lattner CommandObjectProcessLaunch::CommandOptions::g_option_table[] = 30530fdc8d8SChris Lattner { 3068651121cSJim Ingham { LLDB_OPT_SET_1, false, "stop-at-entry", 's', no_argument, NULL, 0, NULL, "Stop at the entry point of the program when launching a process."}, 3078651121cSJim Ingham { LLDB_OPT_SET_1, false, "stdin", 'i', required_argument, NULL, 0, "<path>", "Redirect stdin for the process to <path>."}, 3088651121cSJim Ingham { LLDB_OPT_SET_1, false, "stdout", 'o', required_argument, NULL, 0, "<path>", "Redirect stdout for the process to <path>."}, 3098651121cSJim Ingham { LLDB_OPT_SET_1, false, "stderr", 'e', required_argument, NULL, 0, "<path>", "Redirect stderr for the process to <path>."}, 3108651121cSJim Ingham { LLDB_OPT_SET_1, false, "plugin", 'p', required_argument, NULL, 0, "<plugin>", "Name of the process plugin you want to use."}, 31130fdc8d8SChris Lattner { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL } 31230fdc8d8SChris Lattner }; 31330fdc8d8SChris Lattner 31430fdc8d8SChris Lattner 31530fdc8d8SChris Lattner //------------------------------------------------------------------------- 31630fdc8d8SChris Lattner // CommandObjectProcessAttach 31730fdc8d8SChris Lattner //------------------------------------------------------------------------- 31830fdc8d8SChris Lattner 31930fdc8d8SChris Lattner class CommandObjectProcessAttach : public CommandObject 32030fdc8d8SChris Lattner { 32130fdc8d8SChris Lattner public: 32230fdc8d8SChris Lattner 32330fdc8d8SChris Lattner class CommandOptions : public Options 32430fdc8d8SChris Lattner { 32530fdc8d8SChris Lattner public: 32630fdc8d8SChris Lattner 32730fdc8d8SChris Lattner CommandOptions () : 32830fdc8d8SChris Lattner Options() 32930fdc8d8SChris Lattner { 33030fdc8d8SChris Lattner // Keep default values of all options in one place: ResetOptionValues () 33130fdc8d8SChris Lattner ResetOptionValues (); 33230fdc8d8SChris Lattner } 33330fdc8d8SChris Lattner 33430fdc8d8SChris Lattner ~CommandOptions () 33530fdc8d8SChris Lattner { 33630fdc8d8SChris Lattner } 33730fdc8d8SChris Lattner 33830fdc8d8SChris Lattner Error 33930fdc8d8SChris Lattner SetOptionValue (int option_idx, const char *option_arg) 34030fdc8d8SChris Lattner { 34130fdc8d8SChris Lattner Error error; 34230fdc8d8SChris Lattner char short_option = (char) m_getopt_table[option_idx].val; 34330fdc8d8SChris Lattner bool success = false; 34430fdc8d8SChris Lattner switch (short_option) 34530fdc8d8SChris Lattner { 34630fdc8d8SChris Lattner case 'p': 34730fdc8d8SChris Lattner pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success); 34830fdc8d8SChris Lattner if (!success || pid == LLDB_INVALID_PROCESS_ID) 34930fdc8d8SChris Lattner { 35030fdc8d8SChris Lattner error.SetErrorStringWithFormat("Invalid process ID '%s'.\n", option_arg); 35130fdc8d8SChris Lattner } 35230fdc8d8SChris Lattner break; 35330fdc8d8SChris Lattner 35430fdc8d8SChris Lattner case 'P': 35530fdc8d8SChris Lattner plugin_name = option_arg; 35630fdc8d8SChris Lattner break; 35730fdc8d8SChris Lattner 35830fdc8d8SChris Lattner case 'n': 35930fdc8d8SChris Lattner name.assign(option_arg); 36030fdc8d8SChris Lattner break; 36130fdc8d8SChris Lattner 36230fdc8d8SChris Lattner case 'w': 36330fdc8d8SChris Lattner waitfor = true; 36430fdc8d8SChris Lattner break; 36530fdc8d8SChris Lattner 36630fdc8d8SChris Lattner default: 36730fdc8d8SChris Lattner error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option); 36830fdc8d8SChris Lattner break; 36930fdc8d8SChris Lattner } 37030fdc8d8SChris Lattner return error; 37130fdc8d8SChris Lattner } 37230fdc8d8SChris Lattner 37330fdc8d8SChris Lattner void 37430fdc8d8SChris Lattner ResetOptionValues () 37530fdc8d8SChris Lattner { 37630fdc8d8SChris Lattner Options::ResetOptionValues(); 37730fdc8d8SChris Lattner pid = LLDB_INVALID_PROCESS_ID; 37830fdc8d8SChris Lattner name.clear(); 37930fdc8d8SChris Lattner waitfor = false; 38030fdc8d8SChris Lattner } 38130fdc8d8SChris Lattner 38230fdc8d8SChris Lattner const lldb::OptionDefinition* 38330fdc8d8SChris Lattner GetDefinitions () 38430fdc8d8SChris Lattner { 38530fdc8d8SChris Lattner return g_option_table; 38630fdc8d8SChris Lattner } 38730fdc8d8SChris Lattner 3885aee162fSJim Ingham virtual bool 3895aee162fSJim Ingham HandleOptionArgumentCompletion (CommandInterpreter &interpreter, 3905aee162fSJim Ingham Args &input, 3915aee162fSJim Ingham int cursor_index, 3925aee162fSJim Ingham int char_pos, 3935aee162fSJim Ingham OptionElementVector &opt_element_vector, 3945aee162fSJim Ingham int opt_element_index, 3955aee162fSJim Ingham int match_start_point, 3965aee162fSJim Ingham int max_return_elements, 3975aee162fSJim Ingham bool &word_complete, 3985aee162fSJim Ingham StringList &matches) 3995aee162fSJim Ingham { 4005aee162fSJim Ingham int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos; 4015aee162fSJim Ingham int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index; 4025aee162fSJim Ingham 4035aee162fSJim Ingham // We are only completing the name option for now... 4045aee162fSJim Ingham 4055aee162fSJim Ingham const lldb::OptionDefinition *opt_defs = GetDefinitions(); 4065aee162fSJim Ingham if (opt_defs[opt_defs_index].short_option == 'n') 4075aee162fSJim Ingham { 4085aee162fSJim Ingham // Are we in the name? 4095aee162fSJim Ingham 4105aee162fSJim Ingham // Look to see if there is a -P argument provided, and if so use that plugin, otherwise 4115aee162fSJim Ingham // use the default plugin. 4125aee162fSJim Ingham Process *process = interpreter.GetDebugger().GetExecutionContext().process; 4135aee162fSJim Ingham bool need_to_delete_process = false; 4145aee162fSJim Ingham 4155aee162fSJim Ingham const char *partial_name = NULL; 4165aee162fSJim Ingham partial_name = input.GetArgumentAtIndex(opt_arg_pos); 4175aee162fSJim Ingham 4185aee162fSJim Ingham if (process && process->IsAlive()) 4195aee162fSJim Ingham return true; 4205aee162fSJim Ingham 4212976d00aSJim Ingham Target *target = interpreter.GetDebugger().GetSelectedTarget().get(); 4225aee162fSJim Ingham if (target == NULL) 4235aee162fSJim Ingham { 4245aee162fSJim Ingham // No target has been set yet, for now do host completion. Otherwise I don't know how we would 4255aee162fSJim Ingham // figure out what the right target to use is... 4265aee162fSJim Ingham std::vector<lldb::pid_t> pids; 4275aee162fSJim Ingham Host::ListProcessesMatchingName (partial_name, matches, pids); 4285aee162fSJim Ingham return true; 4295aee162fSJim Ingham } 4305aee162fSJim Ingham if (!process) 4315aee162fSJim Ingham { 4325aee162fSJim Ingham process = target->CreateProcess (interpreter.GetDebugger().GetListener(), partial_name).get(); 4335aee162fSJim Ingham need_to_delete_process = true; 4345aee162fSJim Ingham } 4355aee162fSJim Ingham 4365aee162fSJim Ingham if (process) 4375aee162fSJim Ingham { 4385aee162fSJim Ingham matches.Clear(); 4395aee162fSJim Ingham std::vector<lldb::pid_t> pids; 4405aee162fSJim Ingham process->ListProcessesMatchingName (NULL, matches, pids); 4415aee162fSJim Ingham if (need_to_delete_process) 4425aee162fSJim Ingham target->DeleteCurrentProcess(); 4435aee162fSJim Ingham return true; 4445aee162fSJim Ingham } 4455aee162fSJim Ingham } 4465aee162fSJim Ingham 4475aee162fSJim Ingham return false; 4485aee162fSJim Ingham } 4495aee162fSJim Ingham 45030fdc8d8SChris Lattner // Options table: Required for subclasses of Options. 45130fdc8d8SChris Lattner 45230fdc8d8SChris Lattner static lldb::OptionDefinition g_option_table[]; 45330fdc8d8SChris Lattner 45430fdc8d8SChris Lattner // Instance variables to hold the values for command options. 45530fdc8d8SChris Lattner 45630fdc8d8SChris Lattner lldb::pid_t pid; 45730fdc8d8SChris Lattner std::string plugin_name; 45830fdc8d8SChris Lattner std::string name; 45930fdc8d8SChris Lattner bool waitfor; 46030fdc8d8SChris Lattner }; 46130fdc8d8SChris Lattner 4625aee162fSJim Ingham CommandObjectProcessAttach () : 4635aee162fSJim Ingham CommandObject ("process attach", 464e3d26315SCaroline Tice "Attach to a process.", 4655aee162fSJim Ingham "process attach <cmd-options>") 4665aee162fSJim Ingham { 4675aee162fSJim Ingham } 4685aee162fSJim Ingham 4695aee162fSJim Ingham ~CommandObjectProcessAttach () 4705aee162fSJim Ingham { 4715aee162fSJim Ingham } 4725aee162fSJim Ingham 4735aee162fSJim Ingham bool 4745aee162fSJim Ingham Execute (CommandInterpreter &interpreter, 4755aee162fSJim Ingham Args& command, 4765aee162fSJim Ingham CommandReturnObject &result) 4775aee162fSJim Ingham { 4782976d00aSJim Ingham Target *target = interpreter.GetDebugger().GetSelectedTarget().get(); 4795aee162fSJim Ingham 4805aee162fSJim Ingham Process *process = interpreter.GetDebugger().GetExecutionContext().process; 4815aee162fSJim Ingham if (process) 4825aee162fSJim Ingham { 4835aee162fSJim Ingham if (process->IsAlive()) 4845aee162fSJim Ingham { 4855aee162fSJim Ingham result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before attaching.\n", 4865aee162fSJim Ingham process->GetID()); 4875aee162fSJim Ingham result.SetStatus (eReturnStatusFailed); 4885aee162fSJim Ingham return false; 4895aee162fSJim Ingham } 4905aee162fSJim Ingham } 4915aee162fSJim Ingham 4925aee162fSJim Ingham if (target == NULL) 4935aee162fSJim Ingham { 4945aee162fSJim Ingham // If there isn't a current target create one. 4955aee162fSJim Ingham TargetSP new_target_sp; 4965aee162fSJim Ingham FileSpec emptyFileSpec; 4975aee162fSJim Ingham ArchSpec emptyArchSpec; 4985aee162fSJim Ingham Error error; 4995aee162fSJim Ingham 5005aee162fSJim Ingham error = interpreter.GetDebugger().GetTargetList().CreateTarget(interpreter.GetDebugger(), 5015aee162fSJim Ingham emptyFileSpec, 5025aee162fSJim Ingham emptyArchSpec, 5035aee162fSJim Ingham NULL, 5045aee162fSJim Ingham false, 5055aee162fSJim Ingham new_target_sp); 5065aee162fSJim Ingham target = new_target_sp.get(); 5075aee162fSJim Ingham if (target == NULL || error.Fail()) 5085aee162fSJim Ingham { 5095aee162fSJim Ingham result.AppendError(error.AsCString("Error creating empty target")); 5105aee162fSJim Ingham return false; 5115aee162fSJim Ingham } 5122976d00aSJim Ingham interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target); 5135aee162fSJim Ingham } 5145aee162fSJim Ingham 5155aee162fSJim Ingham // Record the old executable module, we want to issue a warning if the process of attaching changed the 5165aee162fSJim Ingham // current executable (like somebody said "file foo" then attached to a PID whose executable was bar.) 5175aee162fSJim Ingham 5185aee162fSJim Ingham ModuleSP old_exec_module_sp = target->GetExecutableModule(); 5195aee162fSJim Ingham ArchSpec old_arch_spec = target->GetArchitecture(); 5205aee162fSJim Ingham 5215aee162fSJim Ingham if (command.GetArgumentCount()) 5225aee162fSJim Ingham { 5235aee162fSJim Ingham result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str()); 5245aee162fSJim Ingham result.SetStatus (eReturnStatusFailed); 5255aee162fSJim Ingham } 5265aee162fSJim Ingham else 5275aee162fSJim Ingham { 5285aee162fSJim Ingham const char *plugin_name = NULL; 5295aee162fSJim Ingham 5305aee162fSJim Ingham if (!m_options.plugin_name.empty()) 5315aee162fSJim Ingham plugin_name = m_options.plugin_name.c_str(); 5325aee162fSJim Ingham 5335aee162fSJim Ingham process = target->CreateProcess (interpreter.GetDebugger().GetListener(), plugin_name).get(); 5345aee162fSJim Ingham 5355aee162fSJim Ingham if (process) 5365aee162fSJim Ingham { 5375aee162fSJim Ingham Error error; 5385aee162fSJim Ingham int attach_pid = m_options.pid; 5395aee162fSJim Ingham 540*3a0b9cdfSJim Ingham const char *wait_name = NULL; 541*3a0b9cdfSJim Ingham 5425aee162fSJim Ingham if (m_options.name.empty()) 5435aee162fSJim Ingham { 544*3a0b9cdfSJim Ingham if (old_exec_module_sp) 545*3a0b9cdfSJim Ingham { 546*3a0b9cdfSJim Ingham wait_name = old_exec_module_sp->GetFileSpec().GetFilename().AsCString(); 547*3a0b9cdfSJim Ingham } 5485aee162fSJim Ingham } 5495aee162fSJim Ingham else 5505aee162fSJim Ingham { 551*3a0b9cdfSJim Ingham wait_name = m_options.name.c_str(); 552*3a0b9cdfSJim Ingham } 553*3a0b9cdfSJim Ingham 554*3a0b9cdfSJim Ingham // If we are waiting for a process with this name to show up, do that first. 555*3a0b9cdfSJim Ingham if (m_options.waitfor) 556*3a0b9cdfSJim Ingham { 557*3a0b9cdfSJim Ingham 558*3a0b9cdfSJim Ingham if (wait_name == NULL) 559*3a0b9cdfSJim Ingham { 560*3a0b9cdfSJim Ingham result.AppendError("Invalid arguments: must have a file loaded or supply a process name with the waitfor option.\n"); 561*3a0b9cdfSJim Ingham result.SetStatus (eReturnStatusFailed); 562*3a0b9cdfSJim Ingham return false; 563*3a0b9cdfSJim Ingham } 564*3a0b9cdfSJim Ingham 565*3a0b9cdfSJim Ingham interpreter.GetDebugger().GetOutputStream().Printf("Waiting to attach to a process named \"%s\".\n", wait_name); 566*3a0b9cdfSJim Ingham error = process->Attach (wait_name, m_options.waitfor); 5675aee162fSJim Ingham if (error.Success()) 5685aee162fSJim Ingham { 5695aee162fSJim Ingham result.SetStatus (eReturnStatusSuccessContinuingNoResult); 5705aee162fSJim Ingham } 5715aee162fSJim Ingham else 5725aee162fSJim Ingham { 5735aee162fSJim Ingham result.AppendErrorWithFormat ("Waiting for a process to launch named '%s': %s\n", 574*3a0b9cdfSJim Ingham wait_name, 5755aee162fSJim Ingham error.AsCString()); 5765aee162fSJim Ingham result.SetStatus (eReturnStatusFailed); 5775aee162fSJim Ingham return false; 5785aee162fSJim Ingham } 5795aee162fSJim Ingham } 5805aee162fSJim Ingham else 5815aee162fSJim Ingham { 5825aee162fSJim Ingham // If the process was specified by name look it up, so we can warn if there are multiple 5835aee162fSJim Ingham // processes with this pid. 5845aee162fSJim Ingham 585*3a0b9cdfSJim Ingham if (attach_pid == LLDB_INVALID_PROCESS_ID && wait_name != NULL) 5865aee162fSJim Ingham { 5875aee162fSJim Ingham std::vector<lldb::pid_t> pids; 5885aee162fSJim Ingham StringList matches; 5895aee162fSJim Ingham 590*3a0b9cdfSJim Ingham process->ListProcessesMatchingName(wait_name, matches, pids); 5915aee162fSJim Ingham if (matches.GetSize() > 1) 5925aee162fSJim Ingham { 593*3a0b9cdfSJim Ingham result.AppendErrorWithFormat("More than one process named %s\n", wait_name); 5945aee162fSJim Ingham result.SetStatus (eReturnStatusFailed); 5955aee162fSJim Ingham return false; 5965aee162fSJim Ingham } 5975aee162fSJim Ingham else if (matches.GetSize() == 0) 5985aee162fSJim Ingham { 599*3a0b9cdfSJim Ingham result.AppendErrorWithFormat("Could not find a process named %s\n", wait_name); 6005aee162fSJim Ingham result.SetStatus (eReturnStatusFailed); 6015aee162fSJim Ingham return false; 6025aee162fSJim Ingham } 6035aee162fSJim Ingham else 6045aee162fSJim Ingham { 6055aee162fSJim Ingham attach_pid = pids[0]; 6065aee162fSJim Ingham } 6075aee162fSJim Ingham 6085aee162fSJim Ingham } 6095aee162fSJim Ingham 6105aee162fSJim Ingham if (attach_pid != LLDB_INVALID_PROCESS_ID) 6115aee162fSJim Ingham { 6125aee162fSJim Ingham error = process->Attach (attach_pid); 6135aee162fSJim Ingham if (error.Success()) 6145aee162fSJim Ingham { 6155aee162fSJim Ingham result.SetStatus (eReturnStatusSuccessContinuingNoResult); 6165aee162fSJim Ingham } 6175aee162fSJim Ingham else 6185aee162fSJim Ingham { 6195aee162fSJim Ingham result.AppendErrorWithFormat ("Attaching to process %i failed: %s.\n", 6205aee162fSJim Ingham attach_pid, 6215aee162fSJim Ingham error.AsCString()); 6225aee162fSJim Ingham result.SetStatus (eReturnStatusFailed); 6235aee162fSJim Ingham } 6245aee162fSJim Ingham } 6255aee162fSJim Ingham else 6265aee162fSJim Ingham { 6275aee162fSJim Ingham result.AppendErrorWithFormat ("No PID specified for attach\n", 6285aee162fSJim Ingham attach_pid, 6295aee162fSJim Ingham error.AsCString()); 6305aee162fSJim Ingham result.SetStatus (eReturnStatusFailed); 6315aee162fSJim Ingham 6325aee162fSJim Ingham } 6335aee162fSJim Ingham } 6345aee162fSJim Ingham } 6355aee162fSJim Ingham } 6365aee162fSJim Ingham 6375aee162fSJim Ingham if (result.Succeeded()) 6385aee162fSJim Ingham { 6395aee162fSJim Ingham // Okay, we're done. Last step is to warn if the executable module has changed: 6405aee162fSJim Ingham if (!old_exec_module_sp) 6415aee162fSJim Ingham { 6425aee162fSJim Ingham char new_path[PATH_MAX + 1]; 6435aee162fSJim Ingham target->GetExecutableModule()->GetFileSpec().GetPath(new_path, PATH_MAX); 6445aee162fSJim Ingham 6455aee162fSJim Ingham result.AppendMessageWithFormat("Executable module set to \"%s\".\n", 6465aee162fSJim Ingham new_path); 6475aee162fSJim Ingham } 6485aee162fSJim Ingham else if (old_exec_module_sp->GetFileSpec() != target->GetExecutableModule()->GetFileSpec()) 6495aee162fSJim Ingham { 6505aee162fSJim Ingham char old_path[PATH_MAX + 1]; 6515aee162fSJim Ingham char new_path[PATH_MAX + 1]; 6525aee162fSJim Ingham 6535aee162fSJim Ingham old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX); 6545aee162fSJim Ingham target->GetExecutableModule()->GetFileSpec().GetPath (new_path, PATH_MAX); 6555aee162fSJim Ingham 6565aee162fSJim Ingham result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n", 6575aee162fSJim Ingham old_path, new_path); 6585aee162fSJim Ingham } 6595aee162fSJim Ingham 6605aee162fSJim Ingham if (!old_arch_spec.IsValid()) 6615aee162fSJim Ingham { 6625aee162fSJim Ingham result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().AsCString()); 6635aee162fSJim Ingham } 6645aee162fSJim Ingham else if (old_arch_spec != target->GetArchitecture()) 6655aee162fSJim Ingham { 6665aee162fSJim Ingham result.AppendWarningWithFormat("Architecture changed from %s to %s.\n", 6675aee162fSJim Ingham old_arch_spec.AsCString(), target->GetArchitecture().AsCString()); 6685aee162fSJim Ingham } 6695aee162fSJim Ingham } 6705aee162fSJim Ingham return result.Succeeded(); 6715aee162fSJim Ingham } 6725aee162fSJim Ingham 6735aee162fSJim Ingham Options * 6745aee162fSJim Ingham GetOptions () 6755aee162fSJim Ingham { 6765aee162fSJim Ingham return &m_options; 6775aee162fSJim Ingham } 6785aee162fSJim Ingham 67930fdc8d8SChris Lattner protected: 68030fdc8d8SChris Lattner 68130fdc8d8SChris Lattner CommandOptions m_options; 68230fdc8d8SChris Lattner }; 68330fdc8d8SChris Lattner 68430fdc8d8SChris Lattner 68530fdc8d8SChris Lattner lldb::OptionDefinition 68630fdc8d8SChris Lattner CommandObjectProcessAttach::CommandOptions::g_option_table[] = 68730fdc8d8SChris Lattner { 6888651121cSJim Ingham { LLDB_OPT_SET_ALL, false, "plugin", 'P', required_argument, NULL, 0, "<plugin>", "Name of the process plugin you want to use."}, 6898651121cSJim Ingham { LLDB_OPT_SET_1, false, "pid", 'p', required_argument, NULL, 0, "<pid>", "The process ID of an existing process to attach to."}, 690*3a0b9cdfSJim Ingham { LLDB_OPT_SET_2, false, "name", 'n', required_argument, NULL, 0, "<process-name>", "The name of the process to attach to."}, 6918651121cSJim Ingham { LLDB_OPT_SET_2, false, "waitfor", 'w', no_argument, NULL, 0, NULL, "Wait for the the process with <process-name> to launch."}, 69230fdc8d8SChris Lattner { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL } 69330fdc8d8SChris Lattner }; 69430fdc8d8SChris Lattner 69530fdc8d8SChris Lattner //------------------------------------------------------------------------- 69630fdc8d8SChris Lattner // CommandObjectProcessContinue 69730fdc8d8SChris Lattner //------------------------------------------------------------------------- 69830fdc8d8SChris Lattner 69930fdc8d8SChris Lattner class CommandObjectProcessContinue : public CommandObject 70030fdc8d8SChris Lattner { 70130fdc8d8SChris Lattner public: 70230fdc8d8SChris Lattner 70330fdc8d8SChris Lattner CommandObjectProcessContinue () : 70430fdc8d8SChris Lattner CommandObject ("process continue", 705e3d26315SCaroline Tice "Continue execution of all threads in the current process.", 70630fdc8d8SChris Lattner "process continue", 70730fdc8d8SChris Lattner eFlagProcessMustBeLaunched | eFlagProcessMustBePaused) 70830fdc8d8SChris Lattner { 70930fdc8d8SChris Lattner } 71030fdc8d8SChris Lattner 71130fdc8d8SChris Lattner 71230fdc8d8SChris Lattner ~CommandObjectProcessContinue () 71330fdc8d8SChris Lattner { 71430fdc8d8SChris Lattner } 71530fdc8d8SChris Lattner 71630fdc8d8SChris Lattner bool 7176611103cSGreg Clayton Execute (CommandInterpreter &interpreter, 7186611103cSGreg Clayton Args& command, 71930fdc8d8SChris Lattner CommandReturnObject &result) 72030fdc8d8SChris Lattner { 7216611103cSGreg Clayton Process *process = interpreter.GetDebugger().GetExecutionContext().process; 7226611103cSGreg Clayton bool synchronous_execution = interpreter.GetSynchronous (); 72330fdc8d8SChris Lattner 72430fdc8d8SChris Lattner if (process == NULL) 72530fdc8d8SChris Lattner { 72630fdc8d8SChris Lattner result.AppendError ("no process to continue"); 72730fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 72830fdc8d8SChris Lattner return false; 72930fdc8d8SChris Lattner } 73030fdc8d8SChris Lattner 73130fdc8d8SChris Lattner StateType state = process->GetState(); 73230fdc8d8SChris Lattner if (state == eStateStopped) 73330fdc8d8SChris Lattner { 73430fdc8d8SChris Lattner if (command.GetArgumentCount() != 0) 73530fdc8d8SChris Lattner { 73630fdc8d8SChris Lattner result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str()); 73730fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 73830fdc8d8SChris Lattner return false; 73930fdc8d8SChris Lattner } 74030fdc8d8SChris Lattner 74130fdc8d8SChris Lattner const uint32_t num_threads = process->GetThreadList().GetSize(); 74230fdc8d8SChris Lattner 74330fdc8d8SChris Lattner // Set the actions that the threads should each take when resuming 74430fdc8d8SChris Lattner for (uint32_t idx=0; idx<num_threads; ++idx) 74530fdc8d8SChris Lattner { 74630fdc8d8SChris Lattner process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning); 74730fdc8d8SChris Lattner } 74830fdc8d8SChris Lattner 74930fdc8d8SChris Lattner Error error(process->Resume()); 75030fdc8d8SChris Lattner if (error.Success()) 75130fdc8d8SChris Lattner { 75230fdc8d8SChris Lattner result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID()); 75330fdc8d8SChris Lattner if (synchronous_execution) 75430fdc8d8SChris Lattner { 755b132097bSGreg Clayton state = process->WaitForProcessToStop (NULL); 75630fdc8d8SChris Lattner 75730fdc8d8SChris Lattner result.SetDidChangeProcessState (true); 75830fdc8d8SChris Lattner result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state)); 75930fdc8d8SChris Lattner result.SetStatus (eReturnStatusSuccessFinishNoResult); 76030fdc8d8SChris Lattner } 76130fdc8d8SChris Lattner else 76230fdc8d8SChris Lattner { 76330fdc8d8SChris Lattner result.SetStatus (eReturnStatusSuccessContinuingNoResult); 76430fdc8d8SChris Lattner } 76530fdc8d8SChris Lattner } 76630fdc8d8SChris Lattner else 76730fdc8d8SChris Lattner { 76830fdc8d8SChris Lattner result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString()); 76930fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 77030fdc8d8SChris Lattner } 77130fdc8d8SChris Lattner } 77230fdc8d8SChris Lattner else 77330fdc8d8SChris Lattner { 77430fdc8d8SChris Lattner result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n", 77530fdc8d8SChris Lattner StateAsCString(state)); 77630fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 77730fdc8d8SChris Lattner } 77830fdc8d8SChris Lattner return result.Succeeded(); 77930fdc8d8SChris Lattner } 78030fdc8d8SChris Lattner }; 78130fdc8d8SChris Lattner 78230fdc8d8SChris Lattner //------------------------------------------------------------------------- 78330fdc8d8SChris Lattner // CommandObjectProcessDetach 78430fdc8d8SChris Lattner //------------------------------------------------------------------------- 78530fdc8d8SChris Lattner 78630fdc8d8SChris Lattner class CommandObjectProcessDetach : public CommandObject 78730fdc8d8SChris Lattner { 78830fdc8d8SChris Lattner public: 78930fdc8d8SChris Lattner 79030fdc8d8SChris Lattner CommandObjectProcessDetach () : 79130fdc8d8SChris Lattner CommandObject ("process detach", 792e3d26315SCaroline Tice "Detach from the current process being debugged.", 79330fdc8d8SChris Lattner "process detach", 79430fdc8d8SChris Lattner eFlagProcessMustBeLaunched) 79530fdc8d8SChris Lattner { 79630fdc8d8SChris Lattner } 79730fdc8d8SChris Lattner 79830fdc8d8SChris Lattner ~CommandObjectProcessDetach () 79930fdc8d8SChris Lattner { 80030fdc8d8SChris Lattner } 80130fdc8d8SChris Lattner 80230fdc8d8SChris Lattner bool 8036611103cSGreg Clayton Execute (CommandInterpreter &interpreter, 8046611103cSGreg Clayton Args& command, 80530fdc8d8SChris Lattner CommandReturnObject &result) 80630fdc8d8SChris Lattner { 8076611103cSGreg Clayton Process *process = interpreter.GetDebugger().GetExecutionContext().process; 80830fdc8d8SChris Lattner if (process == NULL) 80930fdc8d8SChris Lattner { 81030fdc8d8SChris Lattner result.AppendError ("must have a valid process in order to detach"); 81130fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 81230fdc8d8SChris Lattner return false; 81330fdc8d8SChris Lattner } 81430fdc8d8SChris Lattner 81530fdc8d8SChris Lattner Error error (process->Detach()); 81630fdc8d8SChris Lattner if (error.Success()) 81730fdc8d8SChris Lattner { 81830fdc8d8SChris Lattner result.SetStatus (eReturnStatusSuccessFinishResult); 81930fdc8d8SChris Lattner } 82030fdc8d8SChris Lattner else 82130fdc8d8SChris Lattner { 82230fdc8d8SChris Lattner result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString()); 82330fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 82430fdc8d8SChris Lattner return false; 82530fdc8d8SChris Lattner } 82630fdc8d8SChris Lattner return result.Succeeded(); 82730fdc8d8SChris Lattner } 82830fdc8d8SChris Lattner }; 82930fdc8d8SChris Lattner 83030fdc8d8SChris Lattner //------------------------------------------------------------------------- 83130fdc8d8SChris Lattner // CommandObjectProcessSignal 83230fdc8d8SChris Lattner //------------------------------------------------------------------------- 83330fdc8d8SChris Lattner 83430fdc8d8SChris Lattner class CommandObjectProcessSignal : public CommandObject 83530fdc8d8SChris Lattner { 83630fdc8d8SChris Lattner public: 83730fdc8d8SChris Lattner 83830fdc8d8SChris Lattner CommandObjectProcessSignal () : 83930fdc8d8SChris Lattner CommandObject ("process signal", 840e3d26315SCaroline Tice "Send a UNIX signal to the current process being debugged.", 84130fdc8d8SChris Lattner "process signal <unix-signal-number>") 84230fdc8d8SChris Lattner { 84330fdc8d8SChris Lattner } 84430fdc8d8SChris Lattner 84530fdc8d8SChris Lattner ~CommandObjectProcessSignal () 84630fdc8d8SChris Lattner { 84730fdc8d8SChris Lattner } 84830fdc8d8SChris Lattner 84930fdc8d8SChris Lattner bool 8506611103cSGreg Clayton Execute (CommandInterpreter &interpreter, 8516611103cSGreg Clayton Args& command, 85230fdc8d8SChris Lattner CommandReturnObject &result) 85330fdc8d8SChris Lattner { 8546611103cSGreg Clayton Process *process = interpreter.GetDebugger().GetExecutionContext().process; 85530fdc8d8SChris Lattner if (process == NULL) 85630fdc8d8SChris Lattner { 85730fdc8d8SChris Lattner result.AppendError ("no process to signal"); 85830fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 85930fdc8d8SChris Lattner return false; 86030fdc8d8SChris Lattner } 86130fdc8d8SChris Lattner 86230fdc8d8SChris Lattner if (command.GetArgumentCount() == 1) 86330fdc8d8SChris Lattner { 86430fdc8d8SChris Lattner int signo = Args::StringToSInt32(command.GetArgumentAtIndex(0), -1, 0); 86530fdc8d8SChris Lattner if (signo == -1) 86630fdc8d8SChris Lattner { 86730fdc8d8SChris Lattner result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0)); 86830fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 86930fdc8d8SChris Lattner } 87030fdc8d8SChris Lattner else 87130fdc8d8SChris Lattner { 87230fdc8d8SChris Lattner Error error (process->Signal (signo)); 87330fdc8d8SChris Lattner if (error.Success()) 87430fdc8d8SChris Lattner { 87530fdc8d8SChris Lattner result.SetStatus (eReturnStatusSuccessFinishResult); 87630fdc8d8SChris Lattner } 87730fdc8d8SChris Lattner else 87830fdc8d8SChris Lattner { 87930fdc8d8SChris Lattner result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString()); 88030fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 88130fdc8d8SChris Lattner } 88230fdc8d8SChris Lattner } 88330fdc8d8SChris Lattner } 88430fdc8d8SChris Lattner else 88530fdc8d8SChris Lattner { 88630fdc8d8SChris Lattner result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: \n", m_cmd_name.c_str(), 88730fdc8d8SChris Lattner m_cmd_syntax.c_str()); 88830fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 88930fdc8d8SChris Lattner } 89030fdc8d8SChris Lattner return result.Succeeded(); 89130fdc8d8SChris Lattner } 89230fdc8d8SChris Lattner }; 89330fdc8d8SChris Lattner 89430fdc8d8SChris Lattner 89530fdc8d8SChris Lattner //------------------------------------------------------------------------- 89630fdc8d8SChris Lattner // CommandObjectProcessInterrupt 89730fdc8d8SChris Lattner //------------------------------------------------------------------------- 89830fdc8d8SChris Lattner 89930fdc8d8SChris Lattner class CommandObjectProcessInterrupt : public CommandObject 90030fdc8d8SChris Lattner { 90130fdc8d8SChris Lattner public: 90230fdc8d8SChris Lattner 90330fdc8d8SChris Lattner 90430fdc8d8SChris Lattner CommandObjectProcessInterrupt () : 90530fdc8d8SChris Lattner CommandObject ("process interrupt", 906e3d26315SCaroline Tice "Interrupt the current process being debugged.", 90730fdc8d8SChris Lattner "process interrupt", 90830fdc8d8SChris Lattner eFlagProcessMustBeLaunched) 90930fdc8d8SChris Lattner { 91030fdc8d8SChris Lattner } 91130fdc8d8SChris Lattner 91230fdc8d8SChris Lattner ~CommandObjectProcessInterrupt () 91330fdc8d8SChris Lattner { 91430fdc8d8SChris Lattner } 91530fdc8d8SChris Lattner 91630fdc8d8SChris Lattner bool 9176611103cSGreg Clayton Execute (CommandInterpreter &interpreter, 9186611103cSGreg Clayton Args& command, 91930fdc8d8SChris Lattner CommandReturnObject &result) 92030fdc8d8SChris Lattner { 9216611103cSGreg Clayton Process *process = interpreter.GetDebugger().GetExecutionContext().process; 92230fdc8d8SChris Lattner if (process == NULL) 92330fdc8d8SChris Lattner { 92430fdc8d8SChris Lattner result.AppendError ("no process to halt"); 92530fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 92630fdc8d8SChris Lattner return false; 92730fdc8d8SChris Lattner } 92830fdc8d8SChris Lattner 92930fdc8d8SChris Lattner if (command.GetArgumentCount() == 0) 93030fdc8d8SChris Lattner { 93130fdc8d8SChris Lattner Error error(process->Halt ()); 93230fdc8d8SChris Lattner if (error.Success()) 93330fdc8d8SChris Lattner { 93430fdc8d8SChris Lattner result.SetStatus (eReturnStatusSuccessFinishResult); 93530fdc8d8SChris Lattner 93630fdc8d8SChris Lattner // Maybe we should add a "SuspendThreadPlans so we 93730fdc8d8SChris Lattner // can halt, and keep in place all the current thread plans. 93830fdc8d8SChris Lattner process->GetThreadList().DiscardThreadPlans(); 93930fdc8d8SChris Lattner } 94030fdc8d8SChris Lattner else 94130fdc8d8SChris Lattner { 94230fdc8d8SChris Lattner result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString()); 94330fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 94430fdc8d8SChris Lattner } 94530fdc8d8SChris Lattner } 94630fdc8d8SChris Lattner else 94730fdc8d8SChris Lattner { 94830fdc8d8SChris Lattner result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n", 94930fdc8d8SChris Lattner m_cmd_name.c_str(), 95030fdc8d8SChris Lattner m_cmd_syntax.c_str()); 95130fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 95230fdc8d8SChris Lattner } 95330fdc8d8SChris Lattner return result.Succeeded(); 95430fdc8d8SChris Lattner } 95530fdc8d8SChris Lattner }; 95630fdc8d8SChris Lattner 95730fdc8d8SChris Lattner //------------------------------------------------------------------------- 95830fdc8d8SChris Lattner // CommandObjectProcessKill 95930fdc8d8SChris Lattner //------------------------------------------------------------------------- 96030fdc8d8SChris Lattner 96130fdc8d8SChris Lattner class CommandObjectProcessKill : public CommandObject 96230fdc8d8SChris Lattner { 96330fdc8d8SChris Lattner public: 96430fdc8d8SChris Lattner 96530fdc8d8SChris Lattner CommandObjectProcessKill () : 96630fdc8d8SChris Lattner CommandObject ("process kill", 967e3d26315SCaroline Tice "Terminate the current process being debugged.", 96830fdc8d8SChris Lattner "process kill", 96930fdc8d8SChris Lattner eFlagProcessMustBeLaunched) 97030fdc8d8SChris Lattner { 97130fdc8d8SChris Lattner } 97230fdc8d8SChris Lattner 97330fdc8d8SChris Lattner ~CommandObjectProcessKill () 97430fdc8d8SChris Lattner { 97530fdc8d8SChris Lattner } 97630fdc8d8SChris Lattner 97730fdc8d8SChris Lattner bool 9786611103cSGreg Clayton Execute (CommandInterpreter &interpreter, 9796611103cSGreg Clayton Args& command, 98030fdc8d8SChris Lattner CommandReturnObject &result) 98130fdc8d8SChris Lattner { 9826611103cSGreg Clayton Process *process = interpreter.GetDebugger().GetExecutionContext().process; 98330fdc8d8SChris Lattner if (process == NULL) 98430fdc8d8SChris Lattner { 98530fdc8d8SChris Lattner result.AppendError ("no process to kill"); 98630fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 98730fdc8d8SChris Lattner return false; 98830fdc8d8SChris Lattner } 98930fdc8d8SChris Lattner 99030fdc8d8SChris Lattner if (command.GetArgumentCount() == 0) 99130fdc8d8SChris Lattner { 99230fdc8d8SChris Lattner Error error (process->Destroy()); 99330fdc8d8SChris Lattner if (error.Success()) 99430fdc8d8SChris Lattner { 99530fdc8d8SChris Lattner result.SetStatus (eReturnStatusSuccessFinishResult); 99630fdc8d8SChris Lattner } 99730fdc8d8SChris Lattner else 99830fdc8d8SChris Lattner { 99930fdc8d8SChris Lattner result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString()); 100030fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 100130fdc8d8SChris Lattner } 100230fdc8d8SChris Lattner } 100330fdc8d8SChris Lattner else 100430fdc8d8SChris Lattner { 100530fdc8d8SChris Lattner result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n", 100630fdc8d8SChris Lattner m_cmd_name.c_str(), 100730fdc8d8SChris Lattner m_cmd_syntax.c_str()); 100830fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 100930fdc8d8SChris Lattner } 101030fdc8d8SChris Lattner return result.Succeeded(); 101130fdc8d8SChris Lattner } 101230fdc8d8SChris Lattner }; 101330fdc8d8SChris Lattner 101430fdc8d8SChris Lattner //------------------------------------------------------------------------- 10154b9bea87SJim Ingham // CommandObjectProcessStatus 10164b9bea87SJim Ingham //------------------------------------------------------------------------- 10174b9bea87SJim Ingham class CommandObjectProcessStatus : public CommandObject 10184b9bea87SJim Ingham { 10194b9bea87SJim Ingham public: 10204b9bea87SJim Ingham CommandObjectProcessStatus () : 1021e3d26315SCaroline Tice CommandObject ("process status", 1022e3d26315SCaroline Tice "Show the current status and location of executing process.", 1023e3d26315SCaroline Tice "process status", 10244b9bea87SJim Ingham 0) 10254b9bea87SJim Ingham { 10264b9bea87SJim Ingham } 10274b9bea87SJim Ingham 10284b9bea87SJim Ingham ~CommandObjectProcessStatus() 10294b9bea87SJim Ingham { 10304b9bea87SJim Ingham } 10314b9bea87SJim Ingham 10324b9bea87SJim Ingham 10334b9bea87SJim Ingham bool 10344b9bea87SJim Ingham Execute 10354b9bea87SJim Ingham ( 10366611103cSGreg Clayton CommandInterpreter &interpreter, 10374b9bea87SJim Ingham Args& command, 10384b9bea87SJim Ingham CommandReturnObject &result 10394b9bea87SJim Ingham ) 10404b9bea87SJim Ingham { 10414b9bea87SJim Ingham StreamString &output_stream = result.GetOutputStream(); 10424b9bea87SJim Ingham result.SetStatus (eReturnStatusSuccessFinishNoResult); 10436611103cSGreg Clayton ExecutionContext exe_ctx(interpreter.GetDebugger().GetExecutionContext()); 10444b9bea87SJim Ingham if (exe_ctx.process) 10454b9bea87SJim Ingham { 10464b9bea87SJim Ingham const StateType state = exe_ctx.process->GetState(); 10474b9bea87SJim Ingham if (StateIsStoppedState(state)) 10484b9bea87SJim Ingham { 10494b9bea87SJim Ingham if (state == eStateExited) 10504b9bea87SJim Ingham { 10514b9bea87SJim Ingham int exit_status = exe_ctx.process->GetExitStatus(); 10524b9bea87SJim Ingham const char *exit_description = exe_ctx.process->GetExitDescription(); 10534b9bea87SJim Ingham output_stream.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n", 10544b9bea87SJim Ingham exe_ctx.process->GetID(), 10554b9bea87SJim Ingham exit_status, 10564b9bea87SJim Ingham exit_status, 10574b9bea87SJim Ingham exit_description ? exit_description : ""); 10584b9bea87SJim Ingham } 10594b9bea87SJim Ingham else 10604b9bea87SJim Ingham { 10614b9bea87SJim Ingham output_stream.Printf ("Process %d %s\n", exe_ctx.process->GetID(), StateAsCString (state)); 10624b9bea87SJim Ingham if (exe_ctx.thread == NULL) 10634b9bea87SJim Ingham exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get(); 10644b9bea87SJim Ingham if (exe_ctx.thread != NULL) 10654b9bea87SJim Ingham { 10664b9bea87SJim Ingham DisplayThreadsInfo (interpreter, &exe_ctx, result, true, true); 10674b9bea87SJim Ingham } 10684b9bea87SJim Ingham else 10694b9bea87SJim Ingham { 10704b9bea87SJim Ingham result.AppendError ("No valid thread found in current process."); 10714b9bea87SJim Ingham result.SetStatus (eReturnStatusFailed); 10724b9bea87SJim Ingham } 10734b9bea87SJim Ingham } 10744b9bea87SJim Ingham } 10754b9bea87SJim Ingham else 10764b9bea87SJim Ingham { 10774b9bea87SJim Ingham output_stream.Printf ("Process %d is running.\n", 10784b9bea87SJim Ingham exe_ctx.process->GetID()); 10794b9bea87SJim Ingham } 10804b9bea87SJim Ingham } 10814b9bea87SJim Ingham else 10824b9bea87SJim Ingham { 10834b9bea87SJim Ingham result.AppendError ("No current location or status available."); 10844b9bea87SJim Ingham result.SetStatus (eReturnStatusFailed); 10854b9bea87SJim Ingham } 10864b9bea87SJim Ingham return result.Succeeded(); 10874b9bea87SJim Ingham } 10884b9bea87SJim Ingham }; 10894b9bea87SJim Ingham 10904b9bea87SJim Ingham //------------------------------------------------------------------------- 109130fdc8d8SChris Lattner // CommandObjectMultiwordProcess 109230fdc8d8SChris Lattner //------------------------------------------------------------------------- 109330fdc8d8SChris Lattner 10946611103cSGreg Clayton CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter &interpreter) : 109530fdc8d8SChris Lattner CommandObjectMultiword ("process", 109630fdc8d8SChris Lattner "A set of commands for operating on a process.", 109730fdc8d8SChris Lattner "process <subcommand> [<subcommand-options>]") 109830fdc8d8SChris Lattner { 10996611103cSGreg Clayton LoadSubCommand (interpreter, "attach", CommandObjectSP (new CommandObjectProcessAttach ())); 11006611103cSGreg Clayton LoadSubCommand (interpreter, "launch", CommandObjectSP (new CommandObjectProcessLaunch ())); 11016611103cSGreg Clayton LoadSubCommand (interpreter, "continue", CommandObjectSP (new CommandObjectProcessContinue ())); 11026611103cSGreg Clayton LoadSubCommand (interpreter, "detach", CommandObjectSP (new CommandObjectProcessDetach ())); 11036611103cSGreg Clayton LoadSubCommand (interpreter, "signal", CommandObjectSP (new CommandObjectProcessSignal ())); 11046611103cSGreg Clayton LoadSubCommand (interpreter, "status", CommandObjectSP (new CommandObjectProcessStatus ())); 11056611103cSGreg Clayton LoadSubCommand (interpreter, "interrupt", CommandObjectSP (new CommandObjectProcessInterrupt ())); 11066611103cSGreg Clayton LoadSubCommand (interpreter, "kill", CommandObjectSP (new CommandObjectProcessKill ())); 110730fdc8d8SChris Lattner } 110830fdc8d8SChris Lattner 110930fdc8d8SChris Lattner CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess () 111030fdc8d8SChris Lattner { 111130fdc8d8SChris Lattner } 111230fdc8d8SChris Lattner 1113