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", 10630fdc8d8SChris Lattner "Launches 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 { 1276611103cSGreg Clayton Target *target = interpreter.GetDebugger().GetCurrentTarget().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 1646611103cSGreg Clayton const Args *environment = interpreter.GetEnvironmentVariables(); 1656611103cSGreg Clayton const Args *run_args = interpreter.GetProgramArguments(); 16630fdc8d8SChris Lattner 16730fdc8d8SChris Lattner // There are two possible sources of args to be passed to the process upon launching: Those the user 16830fdc8d8SChris Lattner // typed at the run command (launch_args); or those the user pre-set in the run-args variable (run_args). 16930fdc8d8SChris Lattner 17030fdc8d8SChris Lattner // If launch_args is empty, use run_args. 17130fdc8d8SChris Lattner if (launch_args.GetArgumentCount() == 0) 17230fdc8d8SChris Lattner { 17330fdc8d8SChris Lattner if (run_args != NULL) 17430fdc8d8SChris Lattner launch_args.AppendArguments (*run_args); 17530fdc8d8SChris Lattner } 17630fdc8d8SChris Lattner else 17730fdc8d8SChris Lattner { 17830fdc8d8SChris Lattner // launch-args was not empty; use that, AND re-set run-args to contains launch-args values. 1796611103cSGreg Clayton StateVariable *run_args_var = interpreter.GetStateVariable ("run-args"); 18030fdc8d8SChris Lattner if (run_args_var != NULL) 18130fdc8d8SChris Lattner { 18230fdc8d8SChris Lattner run_args_var->ArrayClearValues(); 18330fdc8d8SChris Lattner run_args_var->GetArgs().AppendArguments (launch_args); 18430fdc8d8SChris Lattner } 18530fdc8d8SChris Lattner } 18630fdc8d8SChris Lattner 18730fdc8d8SChris Lattner 18830fdc8d8SChris Lattner if (process) 18930fdc8d8SChris Lattner { 19030fdc8d8SChris Lattner const char *archname = exe_module->GetArchitecture().AsCString(); 19130fdc8d8SChris Lattner 19230fdc8d8SChris Lattner const char * stdin_path = NULL; 19330fdc8d8SChris Lattner const char * stdout_path = NULL; 19430fdc8d8SChris Lattner const char * stderr_path = NULL; 19530fdc8d8SChris Lattner 19630fdc8d8SChris Lattner if (!(m_options.stdin_path.empty() && 19730fdc8d8SChris Lattner m_options.stdout_path.empty() && 19830fdc8d8SChris Lattner m_options.stderr_path.empty())) 19930fdc8d8SChris Lattner { 20030fdc8d8SChris Lattner stdin_path = m_options.stdin_path.empty() ? "/dev/null" : m_options.stdin_path.c_str(); 20130fdc8d8SChris Lattner stdout_path = m_options.stdout_path.empty() ? "/dev/null" : m_options.stdout_path.c_str(); 20230fdc8d8SChris Lattner stderr_path = m_options.stderr_path.empty() ? "/dev/null" : m_options.stderr_path.c_str(); 20330fdc8d8SChris Lattner } 20430fdc8d8SChris Lattner 20530fdc8d8SChris Lattner Error error (process->Launch (launch_args.GetConstArgumentVector(), 20630fdc8d8SChris Lattner environment ? environment->GetConstArgumentVector() : NULL, 20730fdc8d8SChris Lattner stdin_path, 20830fdc8d8SChris Lattner stdout_path, 20930fdc8d8SChris Lattner stderr_path)); 21030fdc8d8SChris Lattner 21130fdc8d8SChris Lattner if (error.Success()) 21230fdc8d8SChris Lattner { 21330fdc8d8SChris Lattner result.AppendMessageWithFormat ("Launching '%s' (%s)\n", filename, archname); 21430fdc8d8SChris Lattner result.SetStatus (eReturnStatusSuccessContinuingNoResult); 21530fdc8d8SChris Lattner if (m_options.stop_at_entry == false) 21630fdc8d8SChris Lattner { 21730fdc8d8SChris Lattner StateType state = process->WaitForProcessToStop (NULL); 21830fdc8d8SChris Lattner 21930fdc8d8SChris Lattner if (state == eStateStopped) 22030fdc8d8SChris Lattner { 22130fdc8d8SChris Lattner // Call continue_command. 22230fdc8d8SChris Lattner CommandReturnObject continue_result; 2236611103cSGreg Clayton interpreter.HandleCommand("process continue", false, continue_result); 22430fdc8d8SChris Lattner } 22530fdc8d8SChris Lattner 22630fdc8d8SChris Lattner if (synchronous_execution) 22730fdc8d8SChris Lattner { 22830fdc8d8SChris Lattner result.SetDidChangeProcessState (true); 22930fdc8d8SChris Lattner result.SetStatus (eReturnStatusSuccessFinishNoResult); 23030fdc8d8SChris Lattner } 23130fdc8d8SChris Lattner } 23230fdc8d8SChris Lattner } 23330fdc8d8SChris Lattner else 23430fdc8d8SChris Lattner { 23530fdc8d8SChris Lattner result.AppendErrorWithFormat ("Process launch failed: %s", 23630fdc8d8SChris Lattner error.AsCString()); 23730fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 23830fdc8d8SChris Lattner } 23930fdc8d8SChris Lattner } 24030fdc8d8SChris Lattner else 24130fdc8d8SChris Lattner { 24230fdc8d8SChris Lattner result.AppendErrorWithFormat ("Process launch failed: unable to create a process object.\n"); 24330fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 24430fdc8d8SChris Lattner return false; 24530fdc8d8SChris Lattner } 24630fdc8d8SChris Lattner 24730fdc8d8SChris Lattner return result.Succeeded(); 24830fdc8d8SChris Lattner } 24930fdc8d8SChris Lattner 250ebc09c36SJim Ingham virtual const char *GetRepeatCommand (Args ¤t_command_args, uint32_t index) 251ebc09c36SJim Ingham { 252ebc09c36SJim Ingham // No repeat for "process launch"... 253ebc09c36SJim Ingham return ""; 254ebc09c36SJim Ingham } 255ebc09c36SJim Ingham 25630fdc8d8SChris Lattner protected: 25730fdc8d8SChris Lattner 25830fdc8d8SChris Lattner CommandOptions m_options; 25930fdc8d8SChris Lattner }; 26030fdc8d8SChris Lattner 26130fdc8d8SChris Lattner 26230fdc8d8SChris Lattner lldb::OptionDefinition 26330fdc8d8SChris Lattner CommandObjectProcessLaunch::CommandOptions::g_option_table[] = 26430fdc8d8SChris Lattner { 2658651121cSJim 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."}, 2668651121cSJim Ingham { LLDB_OPT_SET_1, false, "stdin", 'i', required_argument, NULL, 0, "<path>", "Redirect stdin for the process to <path>."}, 2678651121cSJim Ingham { LLDB_OPT_SET_1, false, "stdout", 'o', required_argument, NULL, 0, "<path>", "Redirect stdout for the process to <path>."}, 2688651121cSJim Ingham { LLDB_OPT_SET_1, false, "stderr", 'e', required_argument, NULL, 0, "<path>", "Redirect stderr for the process to <path>."}, 2698651121cSJim Ingham { LLDB_OPT_SET_1, false, "plugin", 'p', required_argument, NULL, 0, "<plugin>", "Name of the process plugin you want to use."}, 27030fdc8d8SChris Lattner { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL } 27130fdc8d8SChris Lattner }; 27230fdc8d8SChris Lattner 27330fdc8d8SChris Lattner 27430fdc8d8SChris Lattner //------------------------------------------------------------------------- 27530fdc8d8SChris Lattner // CommandObjectProcessAttach 27630fdc8d8SChris Lattner //------------------------------------------------------------------------- 27730fdc8d8SChris Lattner 27830fdc8d8SChris Lattner class CommandObjectProcessAttach : public CommandObject 27930fdc8d8SChris Lattner { 28030fdc8d8SChris Lattner public: 28130fdc8d8SChris Lattner 28230fdc8d8SChris Lattner class CommandOptions : public Options 28330fdc8d8SChris Lattner { 28430fdc8d8SChris Lattner public: 28530fdc8d8SChris Lattner 28630fdc8d8SChris Lattner CommandOptions () : 28730fdc8d8SChris Lattner Options() 28830fdc8d8SChris Lattner { 28930fdc8d8SChris Lattner // Keep default values of all options in one place: ResetOptionValues () 29030fdc8d8SChris Lattner ResetOptionValues (); 29130fdc8d8SChris Lattner } 29230fdc8d8SChris Lattner 29330fdc8d8SChris Lattner ~CommandOptions () 29430fdc8d8SChris Lattner { 29530fdc8d8SChris Lattner } 29630fdc8d8SChris Lattner 29730fdc8d8SChris Lattner Error 29830fdc8d8SChris Lattner SetOptionValue (int option_idx, const char *option_arg) 29930fdc8d8SChris Lattner { 30030fdc8d8SChris Lattner Error error; 30130fdc8d8SChris Lattner char short_option = (char) m_getopt_table[option_idx].val; 30230fdc8d8SChris Lattner bool success = false; 30330fdc8d8SChris Lattner switch (short_option) 30430fdc8d8SChris Lattner { 30530fdc8d8SChris Lattner case 'p': 30630fdc8d8SChris Lattner pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success); 30730fdc8d8SChris Lattner if (!success || pid == LLDB_INVALID_PROCESS_ID) 30830fdc8d8SChris Lattner { 30930fdc8d8SChris Lattner error.SetErrorStringWithFormat("Invalid process ID '%s'.\n", option_arg); 31030fdc8d8SChris Lattner } 31130fdc8d8SChris Lattner break; 31230fdc8d8SChris Lattner 31330fdc8d8SChris Lattner case 'P': 31430fdc8d8SChris Lattner plugin_name = option_arg; 31530fdc8d8SChris Lattner break; 31630fdc8d8SChris Lattner 31730fdc8d8SChris Lattner case 'n': 31830fdc8d8SChris Lattner name.assign(option_arg); 31930fdc8d8SChris Lattner break; 32030fdc8d8SChris Lattner 32130fdc8d8SChris Lattner case 'w': 32230fdc8d8SChris Lattner waitfor = true; 32330fdc8d8SChris Lattner break; 32430fdc8d8SChris Lattner 32530fdc8d8SChris Lattner default: 32630fdc8d8SChris Lattner error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option); 32730fdc8d8SChris Lattner break; 32830fdc8d8SChris Lattner } 32930fdc8d8SChris Lattner return error; 33030fdc8d8SChris Lattner } 33130fdc8d8SChris Lattner 33230fdc8d8SChris Lattner void 33330fdc8d8SChris Lattner ResetOptionValues () 33430fdc8d8SChris Lattner { 33530fdc8d8SChris Lattner Options::ResetOptionValues(); 33630fdc8d8SChris Lattner pid = LLDB_INVALID_PROCESS_ID; 33730fdc8d8SChris Lattner name.clear(); 33830fdc8d8SChris Lattner waitfor = false; 33930fdc8d8SChris Lattner } 34030fdc8d8SChris Lattner 34130fdc8d8SChris Lattner const lldb::OptionDefinition* 34230fdc8d8SChris Lattner GetDefinitions () 34330fdc8d8SChris Lattner { 34430fdc8d8SChris Lattner return g_option_table; 34530fdc8d8SChris Lattner } 34630fdc8d8SChris Lattner 347*5aee162fSJim Ingham virtual bool 348*5aee162fSJim Ingham HandleOptionArgumentCompletion (CommandInterpreter &interpreter, 349*5aee162fSJim Ingham Args &input, 350*5aee162fSJim Ingham int cursor_index, 351*5aee162fSJim Ingham int char_pos, 352*5aee162fSJim Ingham OptionElementVector &opt_element_vector, 353*5aee162fSJim Ingham int opt_element_index, 354*5aee162fSJim Ingham int match_start_point, 355*5aee162fSJim Ingham int max_return_elements, 356*5aee162fSJim Ingham bool &word_complete, 357*5aee162fSJim Ingham StringList &matches) 358*5aee162fSJim Ingham { 359*5aee162fSJim Ingham int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos; 360*5aee162fSJim Ingham int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index; 361*5aee162fSJim Ingham 362*5aee162fSJim Ingham // We are only completing the name option for now... 363*5aee162fSJim Ingham 364*5aee162fSJim Ingham const lldb::OptionDefinition *opt_defs = GetDefinitions(); 365*5aee162fSJim Ingham if (opt_defs[opt_defs_index].short_option == 'n') 366*5aee162fSJim Ingham { 367*5aee162fSJim Ingham // Are we in the name? 368*5aee162fSJim Ingham 369*5aee162fSJim Ingham // Look to see if there is a -P argument provided, and if so use that plugin, otherwise 370*5aee162fSJim Ingham // use the default plugin. 371*5aee162fSJim Ingham Process *process = interpreter.GetDebugger().GetExecutionContext().process; 372*5aee162fSJim Ingham bool need_to_delete_process = false; 373*5aee162fSJim Ingham 374*5aee162fSJim Ingham const char *partial_name = NULL; 375*5aee162fSJim Ingham partial_name = input.GetArgumentAtIndex(opt_arg_pos); 376*5aee162fSJim Ingham 377*5aee162fSJim Ingham if (process && process->IsAlive()) 378*5aee162fSJim Ingham return true; 379*5aee162fSJim Ingham 380*5aee162fSJim Ingham Target *target = interpreter.GetDebugger().GetCurrentTarget().get(); 381*5aee162fSJim Ingham if (target == NULL) 382*5aee162fSJim Ingham { 383*5aee162fSJim Ingham // No target has been set yet, for now do host completion. Otherwise I don't know how we would 384*5aee162fSJim Ingham // figure out what the right target to use is... 385*5aee162fSJim Ingham std::vector<lldb::pid_t> pids; 386*5aee162fSJim Ingham Host::ListProcessesMatchingName (partial_name, matches, pids); 387*5aee162fSJim Ingham return true; 388*5aee162fSJim Ingham } 389*5aee162fSJim Ingham if (!process) 390*5aee162fSJim Ingham { 391*5aee162fSJim Ingham process = target->CreateProcess (interpreter.GetDebugger().GetListener(), partial_name).get(); 392*5aee162fSJim Ingham need_to_delete_process = true; 393*5aee162fSJim Ingham } 394*5aee162fSJim Ingham 395*5aee162fSJim Ingham if (process) 396*5aee162fSJim Ingham { 397*5aee162fSJim Ingham matches.Clear(); 398*5aee162fSJim Ingham std::vector<lldb::pid_t> pids; 399*5aee162fSJim Ingham process->ListProcessesMatchingName (NULL, matches, pids); 400*5aee162fSJim Ingham if (need_to_delete_process) 401*5aee162fSJim Ingham target->DeleteCurrentProcess(); 402*5aee162fSJim Ingham return true; 403*5aee162fSJim Ingham } 404*5aee162fSJim Ingham } 405*5aee162fSJim Ingham 406*5aee162fSJim Ingham return false; 407*5aee162fSJim Ingham } 408*5aee162fSJim Ingham 40930fdc8d8SChris Lattner // Options table: Required for subclasses of Options. 41030fdc8d8SChris Lattner 41130fdc8d8SChris Lattner static lldb::OptionDefinition g_option_table[]; 41230fdc8d8SChris Lattner 41330fdc8d8SChris Lattner // Instance variables to hold the values for command options. 41430fdc8d8SChris Lattner 41530fdc8d8SChris Lattner lldb::pid_t pid; 41630fdc8d8SChris Lattner std::string plugin_name; 41730fdc8d8SChris Lattner std::string name; 41830fdc8d8SChris Lattner bool waitfor; 41930fdc8d8SChris Lattner }; 42030fdc8d8SChris Lattner 421*5aee162fSJim Ingham CommandObjectProcessAttach () : 422*5aee162fSJim Ingham CommandObject ("process attach", 423*5aee162fSJim Ingham "Attaches to a process.", 424*5aee162fSJim Ingham "process attach <cmd-options>") 425*5aee162fSJim Ingham { 426*5aee162fSJim Ingham SetHelpLong("Currently, you must set the executable file before you can attach " 427*5aee162fSJim Ingham "to a process.\n"); 428*5aee162fSJim Ingham } 429*5aee162fSJim Ingham 430*5aee162fSJim Ingham ~CommandObjectProcessAttach () 431*5aee162fSJim Ingham { 432*5aee162fSJim Ingham } 433*5aee162fSJim Ingham 434*5aee162fSJim Ingham bool 435*5aee162fSJim Ingham Execute (CommandInterpreter &interpreter, 436*5aee162fSJim Ingham Args& command, 437*5aee162fSJim Ingham CommandReturnObject &result) 438*5aee162fSJim Ingham { 439*5aee162fSJim Ingham Target *target = interpreter.GetDebugger().GetCurrentTarget().get(); 440*5aee162fSJim Ingham 441*5aee162fSJim Ingham Process *process = interpreter.GetDebugger().GetExecutionContext().process; 442*5aee162fSJim Ingham if (process) 443*5aee162fSJim Ingham { 444*5aee162fSJim Ingham if (process->IsAlive()) 445*5aee162fSJim Ingham { 446*5aee162fSJim Ingham result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before attaching.\n", 447*5aee162fSJim Ingham process->GetID()); 448*5aee162fSJim Ingham result.SetStatus (eReturnStatusFailed); 449*5aee162fSJim Ingham return false; 450*5aee162fSJim Ingham } 451*5aee162fSJim Ingham } 452*5aee162fSJim Ingham 453*5aee162fSJim Ingham if (target == NULL) 454*5aee162fSJim Ingham { 455*5aee162fSJim Ingham // If there isn't a current target create one. 456*5aee162fSJim Ingham TargetSP new_target_sp; 457*5aee162fSJim Ingham FileSpec emptyFileSpec; 458*5aee162fSJim Ingham ArchSpec emptyArchSpec; 459*5aee162fSJim Ingham Error error; 460*5aee162fSJim Ingham 461*5aee162fSJim Ingham error = interpreter.GetDebugger().GetTargetList().CreateTarget(interpreter.GetDebugger(), 462*5aee162fSJim Ingham emptyFileSpec, 463*5aee162fSJim Ingham emptyArchSpec, 464*5aee162fSJim Ingham NULL, 465*5aee162fSJim Ingham false, 466*5aee162fSJim Ingham new_target_sp); 467*5aee162fSJim Ingham target = new_target_sp.get(); 468*5aee162fSJim Ingham if (target == NULL || error.Fail()) 469*5aee162fSJim Ingham { 470*5aee162fSJim Ingham result.AppendError(error.AsCString("Error creating empty target")); 471*5aee162fSJim Ingham return false; 472*5aee162fSJim Ingham } 473*5aee162fSJim Ingham interpreter.GetDebugger().GetTargetList().SetCurrentTarget(target); 474*5aee162fSJim Ingham } 475*5aee162fSJim Ingham 476*5aee162fSJim Ingham // Record the old executable module, we want to issue a warning if the process of attaching changed the 477*5aee162fSJim Ingham // current executable (like somebody said "file foo" then attached to a PID whose executable was bar.) 478*5aee162fSJim Ingham 479*5aee162fSJim Ingham ModuleSP old_exec_module_sp = target->GetExecutableModule(); 480*5aee162fSJim Ingham ArchSpec old_arch_spec = target->GetArchitecture(); 481*5aee162fSJim Ingham 482*5aee162fSJim Ingham if (command.GetArgumentCount()) 483*5aee162fSJim Ingham { 484*5aee162fSJim Ingham result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str()); 485*5aee162fSJim Ingham result.SetStatus (eReturnStatusFailed); 486*5aee162fSJim Ingham } 487*5aee162fSJim Ingham else 488*5aee162fSJim Ingham { 489*5aee162fSJim Ingham const char *plugin_name = NULL; 490*5aee162fSJim Ingham 491*5aee162fSJim Ingham if (!m_options.plugin_name.empty()) 492*5aee162fSJim Ingham plugin_name = m_options.plugin_name.c_str(); 493*5aee162fSJim Ingham 494*5aee162fSJim Ingham process = target->CreateProcess (interpreter.GetDebugger().GetListener(), plugin_name).get(); 495*5aee162fSJim Ingham 496*5aee162fSJim Ingham if (process) 497*5aee162fSJim Ingham { 498*5aee162fSJim Ingham Error error; 499*5aee162fSJim Ingham int attach_pid = m_options.pid; 500*5aee162fSJim Ingham 501*5aee162fSJim Ingham // If we are waiting for a process with this name to show up, do that first. 502*5aee162fSJim Ingham if (m_options.waitfor) 503*5aee162fSJim Ingham { 504*5aee162fSJim Ingham if (m_options.name.empty()) 505*5aee162fSJim Ingham { 506*5aee162fSJim Ingham result.AppendError("Invalid arguments: must supply a process name with the waitfor option.\n"); 507*5aee162fSJim Ingham result.SetStatus (eReturnStatusFailed); 508*5aee162fSJim Ingham return false; 509*5aee162fSJim Ingham } 510*5aee162fSJim Ingham else 511*5aee162fSJim Ingham { 512*5aee162fSJim Ingham error = process->Attach (m_options.name.c_str(), m_options.waitfor); 513*5aee162fSJim Ingham if (error.Success()) 514*5aee162fSJim Ingham { 515*5aee162fSJim Ingham result.SetStatus (eReturnStatusSuccessContinuingNoResult); 516*5aee162fSJim Ingham } 517*5aee162fSJim Ingham else 518*5aee162fSJim Ingham { 519*5aee162fSJim Ingham result.AppendErrorWithFormat ("Waiting for a process to launch named '%s': %s\n", 520*5aee162fSJim Ingham m_options.name.c_str(), 521*5aee162fSJim Ingham error.AsCString()); 522*5aee162fSJim Ingham result.SetStatus (eReturnStatusFailed); 523*5aee162fSJim Ingham return false; 524*5aee162fSJim Ingham } 525*5aee162fSJim Ingham } 526*5aee162fSJim Ingham } 527*5aee162fSJim Ingham else 528*5aee162fSJim Ingham { 529*5aee162fSJim Ingham // If the process was specified by name look it up, so we can warn if there are multiple 530*5aee162fSJim Ingham // processes with this pid. 531*5aee162fSJim Ingham 532*5aee162fSJim Ingham if (attach_pid == LLDB_INVALID_PROCESS_ID && !m_options.name.empty()) 533*5aee162fSJim Ingham { 534*5aee162fSJim Ingham std::vector<lldb::pid_t> pids; 535*5aee162fSJim Ingham StringList matches; 536*5aee162fSJim Ingham 537*5aee162fSJim Ingham process->ListProcessesMatchingName(m_options.name.c_str(), matches, pids); 538*5aee162fSJim Ingham if (matches.GetSize() > 1) 539*5aee162fSJim Ingham { 540*5aee162fSJim Ingham result.AppendErrorWithFormat("More than one process named %s\n", m_options.name.c_str()); 541*5aee162fSJim Ingham result.SetStatus (eReturnStatusFailed); 542*5aee162fSJim Ingham return false; 543*5aee162fSJim Ingham } 544*5aee162fSJim Ingham else if (matches.GetSize() == 0) 545*5aee162fSJim Ingham { 546*5aee162fSJim Ingham result.AppendErrorWithFormat("Could not find a process named %s\n", m_options.name.c_str()); 547*5aee162fSJim Ingham result.SetStatus (eReturnStatusFailed); 548*5aee162fSJim Ingham return false; 549*5aee162fSJim Ingham } 550*5aee162fSJim Ingham else 551*5aee162fSJim Ingham { 552*5aee162fSJim Ingham attach_pid = pids[0]; 553*5aee162fSJim Ingham } 554*5aee162fSJim Ingham 555*5aee162fSJim Ingham } 556*5aee162fSJim Ingham 557*5aee162fSJim Ingham if (attach_pid != LLDB_INVALID_PROCESS_ID) 558*5aee162fSJim Ingham { 559*5aee162fSJim Ingham error = process->Attach (attach_pid); 560*5aee162fSJim Ingham if (error.Success()) 561*5aee162fSJim Ingham { 562*5aee162fSJim Ingham result.SetStatus (eReturnStatusSuccessContinuingNoResult); 563*5aee162fSJim Ingham } 564*5aee162fSJim Ingham else 565*5aee162fSJim Ingham { 566*5aee162fSJim Ingham result.AppendErrorWithFormat ("Attaching to process %i failed: %s.\n", 567*5aee162fSJim Ingham attach_pid, 568*5aee162fSJim Ingham error.AsCString()); 569*5aee162fSJim Ingham result.SetStatus (eReturnStatusFailed); 570*5aee162fSJim Ingham } 571*5aee162fSJim Ingham } 572*5aee162fSJim Ingham else 573*5aee162fSJim Ingham { 574*5aee162fSJim Ingham result.AppendErrorWithFormat ("No PID specified for attach\n", 575*5aee162fSJim Ingham attach_pid, 576*5aee162fSJim Ingham error.AsCString()); 577*5aee162fSJim Ingham result.SetStatus (eReturnStatusFailed); 578*5aee162fSJim Ingham 579*5aee162fSJim Ingham } 580*5aee162fSJim Ingham } 581*5aee162fSJim Ingham } 582*5aee162fSJim Ingham } 583*5aee162fSJim Ingham 584*5aee162fSJim Ingham if (result.Succeeded()) 585*5aee162fSJim Ingham { 586*5aee162fSJim Ingham // Okay, we're done. Last step is to warn if the executable module has changed: 587*5aee162fSJim Ingham if (!old_exec_module_sp) 588*5aee162fSJim Ingham { 589*5aee162fSJim Ingham char new_path[PATH_MAX + 1]; 590*5aee162fSJim Ingham target->GetExecutableModule()->GetFileSpec().GetPath(new_path, PATH_MAX); 591*5aee162fSJim Ingham 592*5aee162fSJim Ingham result.AppendMessageWithFormat("Executable module set to \"%s\".\n", 593*5aee162fSJim Ingham new_path); 594*5aee162fSJim Ingham } 595*5aee162fSJim Ingham else if (old_exec_module_sp->GetFileSpec() != target->GetExecutableModule()->GetFileSpec()) 596*5aee162fSJim Ingham { 597*5aee162fSJim Ingham char old_path[PATH_MAX + 1]; 598*5aee162fSJim Ingham char new_path[PATH_MAX + 1]; 599*5aee162fSJim Ingham 600*5aee162fSJim Ingham old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX); 601*5aee162fSJim Ingham target->GetExecutableModule()->GetFileSpec().GetPath (new_path, PATH_MAX); 602*5aee162fSJim Ingham 603*5aee162fSJim Ingham result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n", 604*5aee162fSJim Ingham old_path, new_path); 605*5aee162fSJim Ingham } 606*5aee162fSJim Ingham 607*5aee162fSJim Ingham if (!old_arch_spec.IsValid()) 608*5aee162fSJim Ingham { 609*5aee162fSJim Ingham result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().AsCString()); 610*5aee162fSJim Ingham } 611*5aee162fSJim Ingham else if (old_arch_spec != target->GetArchitecture()) 612*5aee162fSJim Ingham { 613*5aee162fSJim Ingham result.AppendWarningWithFormat("Architecture changed from %s to %s.\n", 614*5aee162fSJim Ingham old_arch_spec.AsCString(), target->GetArchitecture().AsCString()); 615*5aee162fSJim Ingham } 616*5aee162fSJim Ingham } 617*5aee162fSJim Ingham return result.Succeeded(); 618*5aee162fSJim Ingham } 619*5aee162fSJim Ingham 620*5aee162fSJim Ingham Options * 621*5aee162fSJim Ingham GetOptions () 622*5aee162fSJim Ingham { 623*5aee162fSJim Ingham return &m_options; 624*5aee162fSJim Ingham } 625*5aee162fSJim Ingham 62630fdc8d8SChris Lattner protected: 62730fdc8d8SChris Lattner 62830fdc8d8SChris Lattner CommandOptions m_options; 62930fdc8d8SChris Lattner }; 63030fdc8d8SChris Lattner 63130fdc8d8SChris Lattner 63230fdc8d8SChris Lattner lldb::OptionDefinition 63330fdc8d8SChris Lattner CommandObjectProcessAttach::CommandOptions::g_option_table[] = 63430fdc8d8SChris Lattner { 6358651121cSJim Ingham { LLDB_OPT_SET_ALL, false, "plugin", 'P', required_argument, NULL, 0, "<plugin>", "Name of the process plugin you want to use."}, 6368651121cSJim Ingham { LLDB_OPT_SET_1, false, "pid", 'p', required_argument, NULL, 0, "<pid>", "The process ID of an existing process to attach to."}, 6378651121cSJim Ingham { LLDB_OPT_SET_2, true, "name", 'n', required_argument, NULL, 0, "<process-name>", "The name of the process to attach to."}, 6388651121cSJim Ingham { LLDB_OPT_SET_2, false, "waitfor", 'w', no_argument, NULL, 0, NULL, "Wait for the the process with <process-name> to launch."}, 63930fdc8d8SChris Lattner { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL } 64030fdc8d8SChris Lattner }; 64130fdc8d8SChris Lattner 64230fdc8d8SChris Lattner //------------------------------------------------------------------------- 64330fdc8d8SChris Lattner // CommandObjectProcessContinue 64430fdc8d8SChris Lattner //------------------------------------------------------------------------- 64530fdc8d8SChris Lattner 64630fdc8d8SChris Lattner class CommandObjectProcessContinue : public CommandObject 64730fdc8d8SChris Lattner { 64830fdc8d8SChris Lattner public: 64930fdc8d8SChris Lattner 65030fdc8d8SChris Lattner CommandObjectProcessContinue () : 65130fdc8d8SChris Lattner CommandObject ("process continue", 65230fdc8d8SChris Lattner "Continues execution all threads in the current process.", 65330fdc8d8SChris Lattner "process continue", 65430fdc8d8SChris Lattner eFlagProcessMustBeLaunched | eFlagProcessMustBePaused) 65530fdc8d8SChris Lattner { 65630fdc8d8SChris Lattner } 65730fdc8d8SChris Lattner 65830fdc8d8SChris Lattner 65930fdc8d8SChris Lattner ~CommandObjectProcessContinue () 66030fdc8d8SChris Lattner { 66130fdc8d8SChris Lattner } 66230fdc8d8SChris Lattner 66330fdc8d8SChris Lattner bool 6646611103cSGreg Clayton Execute (CommandInterpreter &interpreter, 6656611103cSGreg Clayton Args& command, 66630fdc8d8SChris Lattner CommandReturnObject &result) 66730fdc8d8SChris Lattner { 6686611103cSGreg Clayton Process *process = interpreter.GetDebugger().GetExecutionContext().process; 6696611103cSGreg Clayton bool synchronous_execution = interpreter.GetSynchronous (); 67030fdc8d8SChris Lattner 67130fdc8d8SChris Lattner if (process == NULL) 67230fdc8d8SChris Lattner { 67330fdc8d8SChris Lattner result.AppendError ("no process to continue"); 67430fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 67530fdc8d8SChris Lattner return false; 67630fdc8d8SChris Lattner } 67730fdc8d8SChris Lattner 67830fdc8d8SChris Lattner StateType state = process->GetState(); 67930fdc8d8SChris Lattner if (state == eStateStopped) 68030fdc8d8SChris Lattner { 68130fdc8d8SChris Lattner if (command.GetArgumentCount() != 0) 68230fdc8d8SChris Lattner { 68330fdc8d8SChris Lattner result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str()); 68430fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 68530fdc8d8SChris Lattner return false; 68630fdc8d8SChris Lattner } 68730fdc8d8SChris Lattner 68830fdc8d8SChris Lattner const uint32_t num_threads = process->GetThreadList().GetSize(); 68930fdc8d8SChris Lattner 69030fdc8d8SChris Lattner // Set the actions that the threads should each take when resuming 69130fdc8d8SChris Lattner for (uint32_t idx=0; idx<num_threads; ++idx) 69230fdc8d8SChris Lattner { 69330fdc8d8SChris Lattner process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning); 69430fdc8d8SChris Lattner } 69530fdc8d8SChris Lattner 69630fdc8d8SChris Lattner Error error(process->Resume()); 69730fdc8d8SChris Lattner if (error.Success()) 69830fdc8d8SChris Lattner { 69930fdc8d8SChris Lattner result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID()); 70030fdc8d8SChris Lattner if (synchronous_execution) 70130fdc8d8SChris Lattner { 702b132097bSGreg Clayton state = process->WaitForProcessToStop (NULL); 70330fdc8d8SChris Lattner 70430fdc8d8SChris Lattner result.SetDidChangeProcessState (true); 70530fdc8d8SChris Lattner result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state)); 70630fdc8d8SChris Lattner result.SetStatus (eReturnStatusSuccessFinishNoResult); 70730fdc8d8SChris Lattner } 70830fdc8d8SChris Lattner else 70930fdc8d8SChris Lattner { 71030fdc8d8SChris Lattner result.SetStatus (eReturnStatusSuccessContinuingNoResult); 71130fdc8d8SChris Lattner } 71230fdc8d8SChris Lattner } 71330fdc8d8SChris Lattner else 71430fdc8d8SChris Lattner { 71530fdc8d8SChris Lattner result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString()); 71630fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 71730fdc8d8SChris Lattner } 71830fdc8d8SChris Lattner } 71930fdc8d8SChris Lattner else 72030fdc8d8SChris Lattner { 72130fdc8d8SChris Lattner result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n", 72230fdc8d8SChris Lattner StateAsCString(state)); 72330fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 72430fdc8d8SChris Lattner } 72530fdc8d8SChris Lattner return result.Succeeded(); 72630fdc8d8SChris Lattner } 72730fdc8d8SChris Lattner }; 72830fdc8d8SChris Lattner 72930fdc8d8SChris Lattner //------------------------------------------------------------------------- 73030fdc8d8SChris Lattner // CommandObjectProcessDetach 73130fdc8d8SChris Lattner //------------------------------------------------------------------------- 73230fdc8d8SChris Lattner 73330fdc8d8SChris Lattner class CommandObjectProcessDetach : public CommandObject 73430fdc8d8SChris Lattner { 73530fdc8d8SChris Lattner public: 73630fdc8d8SChris Lattner 73730fdc8d8SChris Lattner CommandObjectProcessDetach () : 73830fdc8d8SChris Lattner CommandObject ("process detach", 73930fdc8d8SChris Lattner "Detaches from the current process being debugged.", 74030fdc8d8SChris Lattner "process detach", 74130fdc8d8SChris Lattner eFlagProcessMustBeLaunched) 74230fdc8d8SChris Lattner { 74330fdc8d8SChris Lattner } 74430fdc8d8SChris Lattner 74530fdc8d8SChris Lattner ~CommandObjectProcessDetach () 74630fdc8d8SChris Lattner { 74730fdc8d8SChris Lattner } 74830fdc8d8SChris Lattner 74930fdc8d8SChris Lattner bool 7506611103cSGreg Clayton Execute (CommandInterpreter &interpreter, 7516611103cSGreg Clayton Args& command, 75230fdc8d8SChris Lattner CommandReturnObject &result) 75330fdc8d8SChris Lattner { 7546611103cSGreg Clayton Process *process = interpreter.GetDebugger().GetExecutionContext().process; 75530fdc8d8SChris Lattner if (process == NULL) 75630fdc8d8SChris Lattner { 75730fdc8d8SChris Lattner result.AppendError ("must have a valid process in order to detach"); 75830fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 75930fdc8d8SChris Lattner return false; 76030fdc8d8SChris Lattner } 76130fdc8d8SChris Lattner 76230fdc8d8SChris Lattner Error error (process->Detach()); 76330fdc8d8SChris Lattner if (error.Success()) 76430fdc8d8SChris Lattner { 76530fdc8d8SChris Lattner result.SetStatus (eReturnStatusSuccessFinishResult); 76630fdc8d8SChris Lattner } 76730fdc8d8SChris Lattner else 76830fdc8d8SChris Lattner { 76930fdc8d8SChris Lattner result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString()); 77030fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 77130fdc8d8SChris Lattner return false; 77230fdc8d8SChris Lattner } 77330fdc8d8SChris Lattner return result.Succeeded(); 77430fdc8d8SChris Lattner } 77530fdc8d8SChris Lattner }; 77630fdc8d8SChris Lattner 77730fdc8d8SChris Lattner //------------------------------------------------------------------------- 77830fdc8d8SChris Lattner // CommandObjectProcessSignal 77930fdc8d8SChris Lattner //------------------------------------------------------------------------- 78030fdc8d8SChris Lattner 78130fdc8d8SChris Lattner class CommandObjectProcessSignal : public CommandObject 78230fdc8d8SChris Lattner { 78330fdc8d8SChris Lattner public: 78430fdc8d8SChris Lattner 78530fdc8d8SChris Lattner CommandObjectProcessSignal () : 78630fdc8d8SChris Lattner CommandObject ("process signal", 78730fdc8d8SChris Lattner "Sends a UNIX signal to the current process being debugged.", 78830fdc8d8SChris Lattner "process signal <unix-signal-number>") 78930fdc8d8SChris Lattner { 79030fdc8d8SChris Lattner } 79130fdc8d8SChris Lattner 79230fdc8d8SChris Lattner ~CommandObjectProcessSignal () 79330fdc8d8SChris Lattner { 79430fdc8d8SChris Lattner } 79530fdc8d8SChris Lattner 79630fdc8d8SChris Lattner bool 7976611103cSGreg Clayton Execute (CommandInterpreter &interpreter, 7986611103cSGreg Clayton Args& command, 79930fdc8d8SChris Lattner CommandReturnObject &result) 80030fdc8d8SChris Lattner { 8016611103cSGreg Clayton Process *process = interpreter.GetDebugger().GetExecutionContext().process; 80230fdc8d8SChris Lattner if (process == NULL) 80330fdc8d8SChris Lattner { 80430fdc8d8SChris Lattner result.AppendError ("no process to signal"); 80530fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 80630fdc8d8SChris Lattner return false; 80730fdc8d8SChris Lattner } 80830fdc8d8SChris Lattner 80930fdc8d8SChris Lattner if (command.GetArgumentCount() == 1) 81030fdc8d8SChris Lattner { 81130fdc8d8SChris Lattner int signo = Args::StringToSInt32(command.GetArgumentAtIndex(0), -1, 0); 81230fdc8d8SChris Lattner if (signo == -1) 81330fdc8d8SChris Lattner { 81430fdc8d8SChris Lattner result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0)); 81530fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 81630fdc8d8SChris Lattner } 81730fdc8d8SChris Lattner else 81830fdc8d8SChris Lattner { 81930fdc8d8SChris Lattner Error error (process->Signal (signo)); 82030fdc8d8SChris Lattner if (error.Success()) 82130fdc8d8SChris Lattner { 82230fdc8d8SChris Lattner result.SetStatus (eReturnStatusSuccessFinishResult); 82330fdc8d8SChris Lattner } 82430fdc8d8SChris Lattner else 82530fdc8d8SChris Lattner { 82630fdc8d8SChris Lattner result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString()); 82730fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 82830fdc8d8SChris Lattner } 82930fdc8d8SChris Lattner } 83030fdc8d8SChris Lattner } 83130fdc8d8SChris Lattner else 83230fdc8d8SChris Lattner { 83330fdc8d8SChris Lattner result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: \n", m_cmd_name.c_str(), 83430fdc8d8SChris Lattner m_cmd_syntax.c_str()); 83530fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 83630fdc8d8SChris Lattner } 83730fdc8d8SChris Lattner return result.Succeeded(); 83830fdc8d8SChris Lattner } 83930fdc8d8SChris Lattner }; 84030fdc8d8SChris Lattner 84130fdc8d8SChris Lattner 84230fdc8d8SChris Lattner //------------------------------------------------------------------------- 84330fdc8d8SChris Lattner // CommandObjectProcessInterrupt 84430fdc8d8SChris Lattner //------------------------------------------------------------------------- 84530fdc8d8SChris Lattner 84630fdc8d8SChris Lattner class CommandObjectProcessInterrupt : public CommandObject 84730fdc8d8SChris Lattner { 84830fdc8d8SChris Lattner public: 84930fdc8d8SChris Lattner 85030fdc8d8SChris Lattner 85130fdc8d8SChris Lattner CommandObjectProcessInterrupt () : 85230fdc8d8SChris Lattner CommandObject ("process interrupt", 85330fdc8d8SChris Lattner "Interrupts the current process being debugged.", 85430fdc8d8SChris Lattner "process interrupt", 85530fdc8d8SChris Lattner eFlagProcessMustBeLaunched) 85630fdc8d8SChris Lattner { 85730fdc8d8SChris Lattner } 85830fdc8d8SChris Lattner 85930fdc8d8SChris Lattner ~CommandObjectProcessInterrupt () 86030fdc8d8SChris Lattner { 86130fdc8d8SChris Lattner } 86230fdc8d8SChris Lattner 86330fdc8d8SChris Lattner bool 8646611103cSGreg Clayton Execute (CommandInterpreter &interpreter, 8656611103cSGreg Clayton Args& command, 86630fdc8d8SChris Lattner CommandReturnObject &result) 86730fdc8d8SChris Lattner { 8686611103cSGreg Clayton Process *process = interpreter.GetDebugger().GetExecutionContext().process; 86930fdc8d8SChris Lattner if (process == NULL) 87030fdc8d8SChris Lattner { 87130fdc8d8SChris Lattner result.AppendError ("no process to halt"); 87230fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 87330fdc8d8SChris Lattner return false; 87430fdc8d8SChris Lattner } 87530fdc8d8SChris Lattner 87630fdc8d8SChris Lattner if (command.GetArgumentCount() == 0) 87730fdc8d8SChris Lattner { 87830fdc8d8SChris Lattner Error error(process->Halt ()); 87930fdc8d8SChris Lattner if (error.Success()) 88030fdc8d8SChris Lattner { 88130fdc8d8SChris Lattner result.SetStatus (eReturnStatusSuccessFinishResult); 88230fdc8d8SChris Lattner 88330fdc8d8SChris Lattner // Maybe we should add a "SuspendThreadPlans so we 88430fdc8d8SChris Lattner // can halt, and keep in place all the current thread plans. 88530fdc8d8SChris Lattner process->GetThreadList().DiscardThreadPlans(); 88630fdc8d8SChris Lattner } 88730fdc8d8SChris Lattner else 88830fdc8d8SChris Lattner { 88930fdc8d8SChris Lattner result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString()); 89030fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 89130fdc8d8SChris Lattner } 89230fdc8d8SChris Lattner } 89330fdc8d8SChris Lattner else 89430fdc8d8SChris Lattner { 89530fdc8d8SChris Lattner result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n", 89630fdc8d8SChris Lattner m_cmd_name.c_str(), 89730fdc8d8SChris Lattner m_cmd_syntax.c_str()); 89830fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 89930fdc8d8SChris Lattner } 90030fdc8d8SChris Lattner return result.Succeeded(); 90130fdc8d8SChris Lattner } 90230fdc8d8SChris Lattner }; 90330fdc8d8SChris Lattner 90430fdc8d8SChris Lattner //------------------------------------------------------------------------- 90530fdc8d8SChris Lattner // CommandObjectProcessKill 90630fdc8d8SChris Lattner //------------------------------------------------------------------------- 90730fdc8d8SChris Lattner 90830fdc8d8SChris Lattner class CommandObjectProcessKill : public CommandObject 90930fdc8d8SChris Lattner { 91030fdc8d8SChris Lattner public: 91130fdc8d8SChris Lattner 91230fdc8d8SChris Lattner CommandObjectProcessKill () : 91330fdc8d8SChris Lattner CommandObject ("process kill", 91430fdc8d8SChris Lattner "Terminates the current process being debugged.", 91530fdc8d8SChris Lattner "process kill", 91630fdc8d8SChris Lattner eFlagProcessMustBeLaunched) 91730fdc8d8SChris Lattner { 91830fdc8d8SChris Lattner } 91930fdc8d8SChris Lattner 92030fdc8d8SChris Lattner ~CommandObjectProcessKill () 92130fdc8d8SChris Lattner { 92230fdc8d8SChris Lattner } 92330fdc8d8SChris Lattner 92430fdc8d8SChris Lattner bool 9256611103cSGreg Clayton Execute (CommandInterpreter &interpreter, 9266611103cSGreg Clayton Args& command, 92730fdc8d8SChris Lattner CommandReturnObject &result) 92830fdc8d8SChris Lattner { 9296611103cSGreg Clayton Process *process = interpreter.GetDebugger().GetExecutionContext().process; 93030fdc8d8SChris Lattner if (process == NULL) 93130fdc8d8SChris Lattner { 93230fdc8d8SChris Lattner result.AppendError ("no process to kill"); 93330fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 93430fdc8d8SChris Lattner return false; 93530fdc8d8SChris Lattner } 93630fdc8d8SChris Lattner 93730fdc8d8SChris Lattner if (command.GetArgumentCount() == 0) 93830fdc8d8SChris Lattner { 93930fdc8d8SChris Lattner Error error (process->Destroy()); 94030fdc8d8SChris Lattner if (error.Success()) 94130fdc8d8SChris Lattner { 94230fdc8d8SChris Lattner result.SetStatus (eReturnStatusSuccessFinishResult); 94330fdc8d8SChris Lattner } 94430fdc8d8SChris Lattner else 94530fdc8d8SChris Lattner { 94630fdc8d8SChris Lattner result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString()); 94730fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 94830fdc8d8SChris Lattner } 94930fdc8d8SChris Lattner } 95030fdc8d8SChris Lattner else 95130fdc8d8SChris Lattner { 95230fdc8d8SChris Lattner result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n", 95330fdc8d8SChris Lattner m_cmd_name.c_str(), 95430fdc8d8SChris Lattner m_cmd_syntax.c_str()); 95530fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 95630fdc8d8SChris Lattner } 95730fdc8d8SChris Lattner return result.Succeeded(); 95830fdc8d8SChris Lattner } 95930fdc8d8SChris Lattner }; 96030fdc8d8SChris Lattner 96130fdc8d8SChris Lattner //------------------------------------------------------------------------- 9624b9bea87SJim Ingham // CommandObjectProcessStatus 9634b9bea87SJim Ingham //------------------------------------------------------------------------- 9644b9bea87SJim Ingham class CommandObjectProcessStatus : public CommandObject 9654b9bea87SJim Ingham { 9664b9bea87SJim Ingham public: 9674b9bea87SJim Ingham CommandObjectProcessStatus () : 9684b9bea87SJim Ingham CommandObject ("status", 9694b9bea87SJim Ingham "Shows the current status and location of executing process.", 9704b9bea87SJim Ingham "status", 9714b9bea87SJim Ingham 0) 9724b9bea87SJim Ingham { 9734b9bea87SJim Ingham } 9744b9bea87SJim Ingham 9754b9bea87SJim Ingham ~CommandObjectProcessStatus() 9764b9bea87SJim Ingham { 9774b9bea87SJim Ingham } 9784b9bea87SJim Ingham 9794b9bea87SJim Ingham 9804b9bea87SJim Ingham bool 9814b9bea87SJim Ingham Execute 9824b9bea87SJim Ingham ( 9836611103cSGreg Clayton CommandInterpreter &interpreter, 9844b9bea87SJim Ingham Args& command, 9854b9bea87SJim Ingham CommandReturnObject &result 9864b9bea87SJim Ingham ) 9874b9bea87SJim Ingham { 9884b9bea87SJim Ingham StreamString &output_stream = result.GetOutputStream(); 9894b9bea87SJim Ingham result.SetStatus (eReturnStatusSuccessFinishNoResult); 9906611103cSGreg Clayton ExecutionContext exe_ctx(interpreter.GetDebugger().GetExecutionContext()); 9914b9bea87SJim Ingham if (exe_ctx.process) 9924b9bea87SJim Ingham { 9934b9bea87SJim Ingham const StateType state = exe_ctx.process->GetState(); 9944b9bea87SJim Ingham if (StateIsStoppedState(state)) 9954b9bea87SJim Ingham { 9964b9bea87SJim Ingham if (state == eStateExited) 9974b9bea87SJim Ingham { 9984b9bea87SJim Ingham int exit_status = exe_ctx.process->GetExitStatus(); 9994b9bea87SJim Ingham const char *exit_description = exe_ctx.process->GetExitDescription(); 10004b9bea87SJim Ingham output_stream.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n", 10014b9bea87SJim Ingham exe_ctx.process->GetID(), 10024b9bea87SJim Ingham exit_status, 10034b9bea87SJim Ingham exit_status, 10044b9bea87SJim Ingham exit_description ? exit_description : ""); 10054b9bea87SJim Ingham } 10064b9bea87SJim Ingham else 10074b9bea87SJim Ingham { 10084b9bea87SJim Ingham output_stream.Printf ("Process %d %s\n", exe_ctx.process->GetID(), StateAsCString (state)); 10094b9bea87SJim Ingham if (exe_ctx.thread == NULL) 10104b9bea87SJim Ingham exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get(); 10114b9bea87SJim Ingham if (exe_ctx.thread != NULL) 10124b9bea87SJim Ingham { 10134b9bea87SJim Ingham DisplayThreadsInfo (interpreter, &exe_ctx, result, true, true); 10144b9bea87SJim Ingham } 10154b9bea87SJim Ingham else 10164b9bea87SJim Ingham { 10174b9bea87SJim Ingham result.AppendError ("No valid thread found in current process."); 10184b9bea87SJim Ingham result.SetStatus (eReturnStatusFailed); 10194b9bea87SJim Ingham } 10204b9bea87SJim Ingham } 10214b9bea87SJim Ingham } 10224b9bea87SJim Ingham else 10234b9bea87SJim Ingham { 10244b9bea87SJim Ingham output_stream.Printf ("Process %d is running.\n", 10254b9bea87SJim Ingham exe_ctx.process->GetID()); 10264b9bea87SJim Ingham } 10274b9bea87SJim Ingham } 10284b9bea87SJim Ingham else 10294b9bea87SJim Ingham { 10304b9bea87SJim Ingham result.AppendError ("No current location or status available."); 10314b9bea87SJim Ingham result.SetStatus (eReturnStatusFailed); 10324b9bea87SJim Ingham } 10334b9bea87SJim Ingham return result.Succeeded(); 10344b9bea87SJim Ingham } 10354b9bea87SJim Ingham }; 10364b9bea87SJim Ingham 10374b9bea87SJim Ingham //------------------------------------------------------------------------- 103830fdc8d8SChris Lattner // CommandObjectMultiwordProcess 103930fdc8d8SChris Lattner //------------------------------------------------------------------------- 104030fdc8d8SChris Lattner 10416611103cSGreg Clayton CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter &interpreter) : 104230fdc8d8SChris Lattner CommandObjectMultiword ("process", 104330fdc8d8SChris Lattner "A set of commands for operating on a process.", 104430fdc8d8SChris Lattner "process <subcommand> [<subcommand-options>]") 104530fdc8d8SChris Lattner { 10466611103cSGreg Clayton LoadSubCommand (interpreter, "attach", CommandObjectSP (new CommandObjectProcessAttach ())); 10476611103cSGreg Clayton LoadSubCommand (interpreter, "launch", CommandObjectSP (new CommandObjectProcessLaunch ())); 10486611103cSGreg Clayton LoadSubCommand (interpreter, "continue", CommandObjectSP (new CommandObjectProcessContinue ())); 10496611103cSGreg Clayton LoadSubCommand (interpreter, "detach", CommandObjectSP (new CommandObjectProcessDetach ())); 10506611103cSGreg Clayton LoadSubCommand (interpreter, "signal", CommandObjectSP (new CommandObjectProcessSignal ())); 10516611103cSGreg Clayton LoadSubCommand (interpreter, "status", CommandObjectSP (new CommandObjectProcessStatus ())); 10526611103cSGreg Clayton LoadSubCommand (interpreter, "interrupt", CommandObjectSP (new CommandObjectProcessInterrupt ())); 10536611103cSGreg Clayton LoadSubCommand (interpreter, "kill", CommandObjectSP (new CommandObjectProcessKill ())); 105430fdc8d8SChris Lattner } 105530fdc8d8SChris Lattner 105630fdc8d8SChris Lattner CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess () 105730fdc8d8SChris Lattner { 105830fdc8d8SChris Lattner } 105930fdc8d8SChris Lattner 1060