130fdc8d8SChris Lattner //===-- CommandObjectProcess.cpp --------------------------------*- C++ -*-===// 230fdc8d8SChris Lattner // 330fdc8d8SChris Lattner // The LLVM Compiler Infrastructure 430fdc8d8SChris Lattner // 530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source 630fdc8d8SChris Lattner // License. See LICENSE.TXT for details. 730fdc8d8SChris Lattner // 830fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 930fdc8d8SChris Lattner 1030fdc8d8SChris Lattner #include "CommandObjectProcess.h" 1130fdc8d8SChris Lattner 1230fdc8d8SChris Lattner // C Includes 1330fdc8d8SChris Lattner // C++ Includes 1430fdc8d8SChris Lattner // Other libraries and framework includes 1530fdc8d8SChris Lattner // Project includes 1640af72e1SJim Ingham #include "lldb/Interpreter/Args.h" 1740af72e1SJim Ingham #include "lldb/Interpreter/Options.h" 1830fdc8d8SChris Lattner #include "lldb/Core/State.h" 1930fdc8d8SChris Lattner #include "lldb/Interpreter/CommandInterpreter.h" 2030fdc8d8SChris Lattner #include "lldb/Interpreter/CommandReturnObject.h" 214b9bea87SJim Ingham #include "./CommandObjectThread.h" 2230fdc8d8SChris Lattner #include "lldb/Target/Process.h" 2330fdc8d8SChris Lattner #include "lldb/Target/Target.h" 2430fdc8d8SChris Lattner #include "lldb/Target/Thread.h" 2530fdc8d8SChris Lattner 2630fdc8d8SChris Lattner using namespace lldb; 2730fdc8d8SChris Lattner using namespace lldb_private; 2830fdc8d8SChris Lattner 2930fdc8d8SChris Lattner //------------------------------------------------------------------------- 3030fdc8d8SChris Lattner // CommandObjectProcessLaunch 3130fdc8d8SChris Lattner //------------------------------------------------------------------------- 3230fdc8d8SChris Lattner 3330fdc8d8SChris Lattner class CommandObjectProcessLaunch : public CommandObject 3430fdc8d8SChris Lattner { 3530fdc8d8SChris Lattner public: 3630fdc8d8SChris Lattner 3730fdc8d8SChris Lattner class CommandOptions : public Options 3830fdc8d8SChris Lattner { 3930fdc8d8SChris Lattner public: 4030fdc8d8SChris Lattner 4130fdc8d8SChris Lattner CommandOptions () : 4230fdc8d8SChris Lattner Options() 4330fdc8d8SChris Lattner { 4430fdc8d8SChris Lattner // Keep default values of all options in one place: ResetOptionValues () 4530fdc8d8SChris Lattner ResetOptionValues (); 4630fdc8d8SChris Lattner } 4730fdc8d8SChris Lattner 4830fdc8d8SChris Lattner ~CommandOptions () 4930fdc8d8SChris Lattner { 5030fdc8d8SChris Lattner } 5130fdc8d8SChris Lattner 5230fdc8d8SChris Lattner Error 5330fdc8d8SChris Lattner SetOptionValue (int option_idx, const char *option_arg) 5430fdc8d8SChris Lattner { 5530fdc8d8SChris Lattner Error error; 5630fdc8d8SChris Lattner char short_option = (char) m_getopt_table[option_idx].val; 5730fdc8d8SChris Lattner 5830fdc8d8SChris Lattner switch (short_option) 5930fdc8d8SChris Lattner { 6030fdc8d8SChris Lattner case 's': stop_at_entry = true; break; 6130fdc8d8SChris Lattner case 'e': stderr_path = option_arg; break; 6230fdc8d8SChris Lattner case 'i': stdin_path = option_arg; break; 6330fdc8d8SChris Lattner case 'o': stdout_path = option_arg; break; 6430fdc8d8SChris Lattner case 'p': plugin_name = option_arg; break; 6530fdc8d8SChris Lattner default: 6630fdc8d8SChris Lattner error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option); 6730fdc8d8SChris Lattner break; 6830fdc8d8SChris Lattner 6930fdc8d8SChris Lattner } 7030fdc8d8SChris Lattner return error; 7130fdc8d8SChris Lattner } 7230fdc8d8SChris Lattner 7330fdc8d8SChris Lattner void 7430fdc8d8SChris Lattner ResetOptionValues () 7530fdc8d8SChris Lattner { 7630fdc8d8SChris Lattner Options::ResetOptionValues(); 7730fdc8d8SChris Lattner stop_at_entry = false; 7830fdc8d8SChris Lattner stdin_path.clear(); 7930fdc8d8SChris Lattner stdout_path.clear(); 8030fdc8d8SChris Lattner stderr_path.clear(); 8130fdc8d8SChris Lattner plugin_name.clear(); 8230fdc8d8SChris Lattner } 8330fdc8d8SChris Lattner 8430fdc8d8SChris Lattner const lldb::OptionDefinition* 8530fdc8d8SChris Lattner GetDefinitions () 8630fdc8d8SChris Lattner { 8730fdc8d8SChris Lattner return g_option_table; 8830fdc8d8SChris Lattner } 8930fdc8d8SChris Lattner 9030fdc8d8SChris Lattner // Options table: Required for subclasses of Options. 9130fdc8d8SChris Lattner 9230fdc8d8SChris Lattner static lldb::OptionDefinition g_option_table[]; 9330fdc8d8SChris Lattner 9430fdc8d8SChris Lattner // Instance variables to hold the values for command options. 9530fdc8d8SChris Lattner 9630fdc8d8SChris Lattner bool stop_at_entry; 9730fdc8d8SChris Lattner std::string stderr_path; 9830fdc8d8SChris Lattner std::string stdin_path; 9930fdc8d8SChris Lattner std::string stdout_path; 10030fdc8d8SChris Lattner std::string plugin_name; 10130fdc8d8SChris Lattner 10230fdc8d8SChris Lattner }; 10330fdc8d8SChris Lattner 104a7015092SGreg Clayton CommandObjectProcessLaunch (CommandInterpreter &interpreter) : 105a7015092SGreg Clayton CommandObject (interpreter, 106a7015092SGreg Clayton "process launch", 107e3d26315SCaroline Tice "Launch the executable in the debugger.", 108405fe67fSCaroline Tice NULL) 10930fdc8d8SChris Lattner { 110405fe67fSCaroline Tice CommandArgumentEntry arg; 111405fe67fSCaroline Tice CommandArgumentData run_args_arg; 112405fe67fSCaroline Tice 113405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 114405fe67fSCaroline Tice run_args_arg.arg_type = eArgTypeRunArgs; 115405fe67fSCaroline Tice run_args_arg.arg_repetition = eArgRepeatOptional; 116405fe67fSCaroline Tice 117405fe67fSCaroline Tice // There is only one variant this argument could be; put it into the argument entry. 118405fe67fSCaroline Tice arg.push_back (run_args_arg); 119405fe67fSCaroline Tice 120405fe67fSCaroline Tice // Push the data for the first argument into the m_arguments vector. 121405fe67fSCaroline Tice m_arguments.push_back (arg); 12230fdc8d8SChris Lattner } 12330fdc8d8SChris Lattner 12430fdc8d8SChris Lattner 12530fdc8d8SChris Lattner ~CommandObjectProcessLaunch () 12630fdc8d8SChris Lattner { 12730fdc8d8SChris Lattner } 12830fdc8d8SChris Lattner 12930fdc8d8SChris Lattner Options * 13030fdc8d8SChris Lattner GetOptions () 13130fdc8d8SChris Lattner { 13230fdc8d8SChris Lattner return &m_options; 13330fdc8d8SChris Lattner } 13430fdc8d8SChris Lattner 13530fdc8d8SChris Lattner bool 13605faeb71SGreg Clayton Execute (Args& launch_args, CommandReturnObject &result) 13730fdc8d8SChris Lattner { 138a7015092SGreg Clayton Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 13930fdc8d8SChris Lattner 14030fdc8d8SChris Lattner if (target == NULL) 14130fdc8d8SChris Lattner { 14230fdc8d8SChris Lattner result.AppendError ("invalid target, set executable file using 'file' command"); 14330fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 14430fdc8d8SChris Lattner return false; 14530fdc8d8SChris Lattner } 14630fdc8d8SChris Lattner 14730fdc8d8SChris Lattner // If our listener is NULL, users aren't allows to launch 14830fdc8d8SChris Lattner char filename[PATH_MAX]; 14930fdc8d8SChris Lattner Module *exe_module = target->GetExecutableModule().get(); 15030fdc8d8SChris Lattner exe_module->GetFileSpec().GetPath(filename, sizeof(filename)); 15130fdc8d8SChris Lattner 152a7015092SGreg Clayton Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; 153a7015092SGreg Clayton if (process && process->IsAlive()) 15430fdc8d8SChris Lattner { 15530fdc8d8SChris Lattner result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before running again.\n", 15630fdc8d8SChris Lattner process->GetID()); 15730fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 15830fdc8d8SChris Lattner return false; 15930fdc8d8SChris Lattner } 16030fdc8d8SChris Lattner 16130fdc8d8SChris Lattner const char *plugin_name; 16230fdc8d8SChris Lattner if (!m_options.plugin_name.empty()) 16330fdc8d8SChris Lattner plugin_name = m_options.plugin_name.c_str(); 16430fdc8d8SChris Lattner else 16530fdc8d8SChris Lattner plugin_name = NULL; 16630fdc8d8SChris Lattner 167a7015092SGreg Clayton process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get(); 16830fdc8d8SChris Lattner 169a7015092SGreg Clayton if (process == NULL) 1703df9a8dfSCaroline Tice { 171*43a8c39bSCaroline Tice result.AppendErrorWithFormat ("Failed to find a process plugin for executable.\n"); 172a7015092SGreg Clayton result.SetStatus (eReturnStatusFailed); 173a7015092SGreg Clayton return false; 1743df9a8dfSCaroline Tice } 1753df9a8dfSCaroline Tice 176a7015092SGreg Clayton // If no launch args were given on the command line, then use any that 177a7015092SGreg Clayton // might have been set using the "run-args" set variable. 17830fdc8d8SChris Lattner if (launch_args.GetArgumentCount() == 0) 17930fdc8d8SChris Lattner { 180a7015092SGreg Clayton if (process->GetRunArguments().GetArgumentCount() > 0) 181a7015092SGreg Clayton launch_args = process->GetRunArguments(); 18230fdc8d8SChris Lattner } 18330fdc8d8SChris Lattner 184a7015092SGreg Clayton Args environment; 18530fdc8d8SChris Lattner 186a7015092SGreg Clayton process->GetEnvironmentAsArgs (environment); 187a7015092SGreg Clayton 188a7015092SGreg Clayton uint32_t launch_flags = eLaunchFlagNone; 189a7015092SGreg Clayton 190a7015092SGreg Clayton if (process->GetDisableASLR()) 191a7015092SGreg Clayton launch_flags |= eLaunchFlagDisableASLR; 192a7015092SGreg Clayton 19330fdc8d8SChris Lattner const char *archname = exe_module->GetArchitecture().AsCString(); 19430fdc8d8SChris Lattner 19530fdc8d8SChris Lattner const char * stdin_path = NULL; 19630fdc8d8SChris Lattner const char * stdout_path = NULL; 19730fdc8d8SChris Lattner const char * stderr_path = NULL; 19830fdc8d8SChris Lattner 199a7015092SGreg Clayton // Were any standard input/output/error paths given on the command line? 200a7015092SGreg Clayton if (m_options.stdin_path.empty() && 20130fdc8d8SChris Lattner m_options.stdout_path.empty() && 202a7015092SGreg Clayton m_options.stderr_path.empty()) 20330fdc8d8SChris Lattner { 204a7015092SGreg Clayton // No standard file handles were given on the command line, check 205a7015092SGreg Clayton // with the process object in case they were give using "set settings" 206a7015092SGreg Clayton stdin_path = process->GetStandardInputPath(); 207a7015092SGreg Clayton stdout_path = process->GetStandardOutputPath(); 208a7015092SGreg Clayton stderr_path = process->GetStandardErrorPath(); 209a7015092SGreg Clayton } 210a7015092SGreg Clayton else 211a7015092SGreg Clayton { 212a7015092SGreg Clayton stdin_path = m_options.stdin_path.empty() ? NULL : m_options.stdin_path.c_str(); 213a7015092SGreg Clayton stdout_path = m_options.stdout_path.empty() ? NULL : m_options.stdout_path.c_str(); 214a7015092SGreg Clayton stderr_path = m_options.stderr_path.empty() ? NULL : m_options.stderr_path.c_str(); 21530fdc8d8SChris Lattner } 21630fdc8d8SChris Lattner 217a7015092SGreg Clayton if (stdin_path == NULL) 218a7015092SGreg Clayton stdin_path = "/dev/null"; 219a7015092SGreg Clayton if (stdout_path == NULL) 220a7015092SGreg Clayton stdout_path = "/dev/null"; 221a7015092SGreg Clayton if (stderr_path == NULL) 222a7015092SGreg Clayton stderr_path = "/dev/null"; 223a7015092SGreg Clayton 224a7015092SGreg Clayton Error error (process->Launch (launch_args.GetArgumentCount() ? launch_args.GetConstArgumentVector() : NULL, 225a7015092SGreg Clayton environment.GetArgumentCount() ? environment.GetConstArgumentVector() : NULL, 226f681b94fSGreg Clayton launch_flags, 22730fdc8d8SChris Lattner stdin_path, 22830fdc8d8SChris Lattner stdout_path, 22930fdc8d8SChris Lattner stderr_path)); 23030fdc8d8SChris Lattner 23130fdc8d8SChris Lattner if (error.Success()) 23230fdc8d8SChris Lattner { 23330fdc8d8SChris Lattner result.AppendMessageWithFormat ("Launching '%s' (%s)\n", filename, archname); 23405faeb71SGreg Clayton result.SetDidChangeProcessState (true); 23530fdc8d8SChris Lattner if (m_options.stop_at_entry == false) 23630fdc8d8SChris Lattner { 23705faeb71SGreg Clayton result.SetStatus (eReturnStatusSuccessContinuingNoResult); 23830fdc8d8SChris Lattner StateType state = process->WaitForProcessToStop (NULL); 23930fdc8d8SChris Lattner 24030fdc8d8SChris Lattner if (state == eStateStopped) 24130fdc8d8SChris Lattner { 24205faeb71SGreg Clayton error = process->Resume(); 24305faeb71SGreg Clayton if (error.Success()) 24405faeb71SGreg Clayton { 24505faeb71SGreg Clayton bool synchronous_execution = m_interpreter.GetSynchronous (); 24630fdc8d8SChris Lattner if (synchronous_execution) 24730fdc8d8SChris Lattner { 24805faeb71SGreg Clayton state = process->WaitForProcessToStop (NULL); 24930fdc8d8SChris Lattner result.SetDidChangeProcessState (true); 25005faeb71SGreg Clayton result.SetStatus (eReturnStatusSuccessFinishResult); 25105faeb71SGreg Clayton } 25205faeb71SGreg Clayton else 25305faeb71SGreg Clayton { 25405faeb71SGreg Clayton result.SetStatus (eReturnStatusSuccessContinuingNoResult); 25505faeb71SGreg Clayton } 25605faeb71SGreg Clayton } 25730fdc8d8SChris Lattner } 25830fdc8d8SChris Lattner } 25930fdc8d8SChris Lattner } 26030fdc8d8SChris Lattner 26130fdc8d8SChris Lattner return result.Succeeded(); 26230fdc8d8SChris Lattner } 26330fdc8d8SChris Lattner 264ebc09c36SJim Ingham virtual const char *GetRepeatCommand (Args ¤t_command_args, uint32_t index) 265ebc09c36SJim Ingham { 266ebc09c36SJim Ingham // No repeat for "process launch"... 267ebc09c36SJim Ingham return ""; 268ebc09c36SJim Ingham } 269ebc09c36SJim Ingham 27030fdc8d8SChris Lattner protected: 27130fdc8d8SChris Lattner 27230fdc8d8SChris Lattner CommandOptions m_options; 27330fdc8d8SChris Lattner }; 27430fdc8d8SChris Lattner 27530fdc8d8SChris Lattner 27630fdc8d8SChris Lattner lldb::OptionDefinition 27730fdc8d8SChris Lattner CommandObjectProcessLaunch::CommandOptions::g_option_table[] = 27830fdc8d8SChris Lattner { 279deaab222SCaroline Tice { LLDB_OPT_SET_1, false, "stop-at-entry", 's', no_argument, NULL, 0, eArgTypeNone, "Stop at the entry point of the program when launching a process."}, 280deaab222SCaroline Tice { LLDB_OPT_SET_1, false, "stdin", 'i', required_argument, NULL, 0, eArgTypePath, "Redirect stdin for the process to <path>."}, 281deaab222SCaroline Tice { LLDB_OPT_SET_1, false, "stdout", 'o', required_argument, NULL, 0, eArgTypePath, "Redirect stdout for the process to <path>."}, 282deaab222SCaroline Tice { LLDB_OPT_SET_1, false, "stderr", 'e', required_argument, NULL, 0, eArgTypePath, "Redirect stderr for the process to <path>."}, 283deaab222SCaroline Tice { LLDB_OPT_SET_1, false, "plugin", 'p', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."}, 284deaab222SCaroline Tice { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 28530fdc8d8SChris Lattner }; 28630fdc8d8SChris Lattner 28730fdc8d8SChris Lattner 28830fdc8d8SChris Lattner //------------------------------------------------------------------------- 28930fdc8d8SChris Lattner // CommandObjectProcessAttach 29030fdc8d8SChris Lattner //------------------------------------------------------------------------- 29130fdc8d8SChris Lattner 29230fdc8d8SChris Lattner class CommandObjectProcessAttach : public CommandObject 29330fdc8d8SChris Lattner { 29430fdc8d8SChris Lattner public: 29530fdc8d8SChris Lattner 29630fdc8d8SChris Lattner class CommandOptions : public Options 29730fdc8d8SChris Lattner { 29830fdc8d8SChris Lattner public: 29930fdc8d8SChris Lattner 30030fdc8d8SChris Lattner CommandOptions () : 30130fdc8d8SChris Lattner Options() 30230fdc8d8SChris Lattner { 30330fdc8d8SChris Lattner // Keep default values of all options in one place: ResetOptionValues () 30430fdc8d8SChris Lattner ResetOptionValues (); 30530fdc8d8SChris Lattner } 30630fdc8d8SChris Lattner 30730fdc8d8SChris Lattner ~CommandOptions () 30830fdc8d8SChris Lattner { 30930fdc8d8SChris Lattner } 31030fdc8d8SChris Lattner 31130fdc8d8SChris Lattner Error 31230fdc8d8SChris Lattner SetOptionValue (int option_idx, const char *option_arg) 31330fdc8d8SChris Lattner { 31430fdc8d8SChris Lattner Error error; 31530fdc8d8SChris Lattner char short_option = (char) m_getopt_table[option_idx].val; 31630fdc8d8SChris Lattner bool success = false; 31730fdc8d8SChris Lattner switch (short_option) 31830fdc8d8SChris Lattner { 31930fdc8d8SChris Lattner case 'p': 32030fdc8d8SChris Lattner pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success); 32130fdc8d8SChris Lattner if (!success || pid == LLDB_INVALID_PROCESS_ID) 32230fdc8d8SChris Lattner { 32330fdc8d8SChris Lattner error.SetErrorStringWithFormat("Invalid process ID '%s'.\n", option_arg); 32430fdc8d8SChris Lattner } 32530fdc8d8SChris Lattner break; 32630fdc8d8SChris Lattner 32730fdc8d8SChris Lattner case 'P': 32830fdc8d8SChris Lattner plugin_name = option_arg; 32930fdc8d8SChris Lattner break; 33030fdc8d8SChris Lattner 33130fdc8d8SChris Lattner case 'n': 33230fdc8d8SChris Lattner name.assign(option_arg); 33330fdc8d8SChris Lattner break; 33430fdc8d8SChris Lattner 33530fdc8d8SChris Lattner case 'w': 33630fdc8d8SChris Lattner waitfor = true; 33730fdc8d8SChris Lattner break; 33830fdc8d8SChris Lattner 33930fdc8d8SChris Lattner default: 34030fdc8d8SChris Lattner error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option); 34130fdc8d8SChris Lattner break; 34230fdc8d8SChris Lattner } 34330fdc8d8SChris Lattner return error; 34430fdc8d8SChris Lattner } 34530fdc8d8SChris Lattner 34630fdc8d8SChris Lattner void 34730fdc8d8SChris Lattner ResetOptionValues () 34830fdc8d8SChris Lattner { 34930fdc8d8SChris Lattner Options::ResetOptionValues(); 35030fdc8d8SChris Lattner pid = LLDB_INVALID_PROCESS_ID; 35130fdc8d8SChris Lattner name.clear(); 35230fdc8d8SChris Lattner waitfor = false; 35330fdc8d8SChris Lattner } 35430fdc8d8SChris Lattner 35530fdc8d8SChris Lattner const lldb::OptionDefinition* 35630fdc8d8SChris Lattner GetDefinitions () 35730fdc8d8SChris Lattner { 35830fdc8d8SChris Lattner return g_option_table; 35930fdc8d8SChris Lattner } 36030fdc8d8SChris Lattner 3615aee162fSJim Ingham virtual bool 362a7015092SGreg Clayton HandleOptionArgumentCompletion (CommandInterpreter &interpeter, 3635aee162fSJim Ingham Args &input, 3645aee162fSJim Ingham int cursor_index, 3655aee162fSJim Ingham int char_pos, 3665aee162fSJim Ingham OptionElementVector &opt_element_vector, 3675aee162fSJim Ingham int opt_element_index, 3685aee162fSJim Ingham int match_start_point, 3695aee162fSJim Ingham int max_return_elements, 3705aee162fSJim Ingham bool &word_complete, 3715aee162fSJim Ingham StringList &matches) 3725aee162fSJim Ingham { 3735aee162fSJim Ingham int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos; 3745aee162fSJim Ingham int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index; 3755aee162fSJim Ingham 3765aee162fSJim Ingham // We are only completing the name option for now... 3775aee162fSJim Ingham 3785aee162fSJim Ingham const lldb::OptionDefinition *opt_defs = GetDefinitions(); 3795aee162fSJim Ingham if (opt_defs[opt_defs_index].short_option == 'n') 3805aee162fSJim Ingham { 3815aee162fSJim Ingham // Are we in the name? 3825aee162fSJim Ingham 3835aee162fSJim Ingham // Look to see if there is a -P argument provided, and if so use that plugin, otherwise 3845aee162fSJim Ingham // use the default plugin. 385a7015092SGreg Clayton Process *process = interpeter.GetDebugger().GetExecutionContext().process; 3865aee162fSJim Ingham bool need_to_delete_process = false; 3875aee162fSJim Ingham 3885aee162fSJim Ingham const char *partial_name = NULL; 3895aee162fSJim Ingham partial_name = input.GetArgumentAtIndex(opt_arg_pos); 3905aee162fSJim Ingham 3915aee162fSJim Ingham if (process && process->IsAlive()) 3925aee162fSJim Ingham return true; 3935aee162fSJim Ingham 394a7015092SGreg Clayton Target *target = interpeter.GetDebugger().GetSelectedTarget().get(); 3955aee162fSJim Ingham if (target == NULL) 3965aee162fSJim Ingham { 3975aee162fSJim Ingham // No target has been set yet, for now do host completion. Otherwise I don't know how we would 3985aee162fSJim Ingham // figure out what the right target to use is... 3995aee162fSJim Ingham std::vector<lldb::pid_t> pids; 4005aee162fSJim Ingham Host::ListProcessesMatchingName (partial_name, matches, pids); 4015aee162fSJim Ingham return true; 4025aee162fSJim Ingham } 4035aee162fSJim Ingham if (!process) 4045aee162fSJim Ingham { 405a7015092SGreg Clayton process = target->CreateProcess (interpeter.GetDebugger().GetListener(), partial_name).get(); 4065aee162fSJim Ingham need_to_delete_process = true; 4075aee162fSJim Ingham } 4085aee162fSJim Ingham 4095aee162fSJim Ingham if (process) 4105aee162fSJim Ingham { 4115aee162fSJim Ingham matches.Clear(); 4125aee162fSJim Ingham std::vector<lldb::pid_t> pids; 4135aee162fSJim Ingham process->ListProcessesMatchingName (NULL, matches, pids); 4145aee162fSJim Ingham if (need_to_delete_process) 4155aee162fSJim Ingham target->DeleteCurrentProcess(); 4165aee162fSJim Ingham return true; 4175aee162fSJim Ingham } 4185aee162fSJim Ingham } 4195aee162fSJim Ingham 4205aee162fSJim Ingham return false; 4215aee162fSJim Ingham } 4225aee162fSJim Ingham 42330fdc8d8SChris Lattner // Options table: Required for subclasses of Options. 42430fdc8d8SChris Lattner 42530fdc8d8SChris Lattner static lldb::OptionDefinition g_option_table[]; 42630fdc8d8SChris Lattner 42730fdc8d8SChris Lattner // Instance variables to hold the values for command options. 42830fdc8d8SChris Lattner 42930fdc8d8SChris Lattner lldb::pid_t pid; 43030fdc8d8SChris Lattner std::string plugin_name; 43130fdc8d8SChris Lattner std::string name; 43230fdc8d8SChris Lattner bool waitfor; 43330fdc8d8SChris Lattner }; 43430fdc8d8SChris Lattner 435a7015092SGreg Clayton CommandObjectProcessAttach (CommandInterpreter &interpreter) : 436a7015092SGreg Clayton CommandObject (interpreter, 437a7015092SGreg Clayton "process attach", 438e3d26315SCaroline Tice "Attach to a process.", 4395aee162fSJim Ingham "process attach <cmd-options>") 4405aee162fSJim Ingham { 4415aee162fSJim Ingham } 4425aee162fSJim Ingham 4435aee162fSJim Ingham ~CommandObjectProcessAttach () 4445aee162fSJim Ingham { 4455aee162fSJim Ingham } 4465aee162fSJim Ingham 4475aee162fSJim Ingham bool 448a7015092SGreg Clayton Execute (Args& command, 4495aee162fSJim Ingham CommandReturnObject &result) 4505aee162fSJim Ingham { 451a7015092SGreg Clayton Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 4525aee162fSJim Ingham 453a7015092SGreg Clayton Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; 4545aee162fSJim Ingham if (process) 4555aee162fSJim Ingham { 4565aee162fSJim Ingham if (process->IsAlive()) 4575aee162fSJim Ingham { 4585aee162fSJim Ingham result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before attaching.\n", 4595aee162fSJim Ingham process->GetID()); 4605aee162fSJim Ingham result.SetStatus (eReturnStatusFailed); 4615aee162fSJim Ingham return false; 4625aee162fSJim Ingham } 4635aee162fSJim Ingham } 4645aee162fSJim Ingham 4655aee162fSJim Ingham if (target == NULL) 4665aee162fSJim Ingham { 4675aee162fSJim Ingham // If there isn't a current target create one. 4685aee162fSJim Ingham TargetSP new_target_sp; 4695aee162fSJim Ingham FileSpec emptyFileSpec; 4705aee162fSJim Ingham ArchSpec emptyArchSpec; 4715aee162fSJim Ingham Error error; 4725aee162fSJim Ingham 473a7015092SGreg Clayton error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(), 4745aee162fSJim Ingham emptyFileSpec, 4755aee162fSJim Ingham emptyArchSpec, 4765aee162fSJim Ingham NULL, 4775aee162fSJim Ingham false, 4785aee162fSJim Ingham new_target_sp); 4795aee162fSJim Ingham target = new_target_sp.get(); 4805aee162fSJim Ingham if (target == NULL || error.Fail()) 4815aee162fSJim Ingham { 4825aee162fSJim Ingham result.AppendError(error.AsCString("Error creating empty target")); 4835aee162fSJim Ingham return false; 4845aee162fSJim Ingham } 485a7015092SGreg Clayton m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target); 4865aee162fSJim Ingham } 4875aee162fSJim Ingham 4885aee162fSJim Ingham // Record the old executable module, we want to issue a warning if the process of attaching changed the 4895aee162fSJim Ingham // current executable (like somebody said "file foo" then attached to a PID whose executable was bar.) 4905aee162fSJim Ingham 4915aee162fSJim Ingham ModuleSP old_exec_module_sp = target->GetExecutableModule(); 4925aee162fSJim Ingham ArchSpec old_arch_spec = target->GetArchitecture(); 4935aee162fSJim Ingham 4945aee162fSJim Ingham if (command.GetArgumentCount()) 4955aee162fSJim Ingham { 4965aee162fSJim Ingham result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str()); 4975aee162fSJim Ingham result.SetStatus (eReturnStatusFailed); 4985aee162fSJim Ingham } 4995aee162fSJim Ingham else 5005aee162fSJim Ingham { 5015aee162fSJim Ingham const char *plugin_name = NULL; 5025aee162fSJim Ingham 5035aee162fSJim Ingham if (!m_options.plugin_name.empty()) 5045aee162fSJim Ingham plugin_name = m_options.plugin_name.c_str(); 5055aee162fSJim Ingham 506a7015092SGreg Clayton process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get(); 5075aee162fSJim Ingham 5085aee162fSJim Ingham if (process) 5095aee162fSJim Ingham { 5105aee162fSJim Ingham Error error; 5115aee162fSJim Ingham int attach_pid = m_options.pid; 5125aee162fSJim Ingham 5133a0b9cdfSJim Ingham const char *wait_name = NULL; 5143a0b9cdfSJim Ingham 5155aee162fSJim Ingham if (m_options.name.empty()) 5165aee162fSJim Ingham { 5173a0b9cdfSJim Ingham if (old_exec_module_sp) 5183a0b9cdfSJim Ingham { 5193a0b9cdfSJim Ingham wait_name = old_exec_module_sp->GetFileSpec().GetFilename().AsCString(); 5203a0b9cdfSJim Ingham } 5215aee162fSJim Ingham } 5225aee162fSJim Ingham else 5235aee162fSJim Ingham { 5243a0b9cdfSJim Ingham wait_name = m_options.name.c_str(); 5253a0b9cdfSJim Ingham } 5263a0b9cdfSJim Ingham 5273a0b9cdfSJim Ingham // If we are waiting for a process with this name to show up, do that first. 5283a0b9cdfSJim Ingham if (m_options.waitfor) 5293a0b9cdfSJim Ingham { 5303a0b9cdfSJim Ingham 5313a0b9cdfSJim Ingham if (wait_name == NULL) 5323a0b9cdfSJim Ingham { 5333a0b9cdfSJim Ingham result.AppendError("Invalid arguments: must have a file loaded or supply a process name with the waitfor option.\n"); 5343a0b9cdfSJim Ingham result.SetStatus (eReturnStatusFailed); 5353a0b9cdfSJim Ingham return false; 5363a0b9cdfSJim Ingham } 5373a0b9cdfSJim Ingham 538a7015092SGreg Clayton m_interpreter.GetDebugger().GetOutputStream().Printf("Waiting to attach to a process named \"%s\".\n", wait_name); 5393a0b9cdfSJim Ingham error = process->Attach (wait_name, m_options.waitfor); 5405aee162fSJim Ingham if (error.Success()) 5415aee162fSJim Ingham { 5425aee162fSJim Ingham result.SetStatus (eReturnStatusSuccessContinuingNoResult); 5435aee162fSJim Ingham } 5445aee162fSJim Ingham else 5455aee162fSJim Ingham { 5465aee162fSJim Ingham result.AppendErrorWithFormat ("Waiting for a process to launch named '%s': %s\n", 5473a0b9cdfSJim Ingham wait_name, 5485aee162fSJim Ingham error.AsCString()); 5495aee162fSJim Ingham result.SetStatus (eReturnStatusFailed); 5505aee162fSJim Ingham return false; 5515aee162fSJim Ingham } 5525aee162fSJim Ingham } 5535aee162fSJim Ingham else 5545aee162fSJim Ingham { 5555aee162fSJim Ingham // If the process was specified by name look it up, so we can warn if there are multiple 5565aee162fSJim Ingham // processes with this pid. 5575aee162fSJim Ingham 5583a0b9cdfSJim Ingham if (attach_pid == LLDB_INVALID_PROCESS_ID && wait_name != NULL) 5595aee162fSJim Ingham { 5605aee162fSJim Ingham std::vector<lldb::pid_t> pids; 5615aee162fSJim Ingham StringList matches; 5625aee162fSJim Ingham 5633a0b9cdfSJim Ingham process->ListProcessesMatchingName(wait_name, matches, pids); 5645aee162fSJim Ingham if (matches.GetSize() > 1) 5655aee162fSJim Ingham { 5663a0b9cdfSJim Ingham result.AppendErrorWithFormat("More than one process named %s\n", wait_name); 5675aee162fSJim Ingham result.SetStatus (eReturnStatusFailed); 5685aee162fSJim Ingham return false; 5695aee162fSJim Ingham } 5705aee162fSJim Ingham else if (matches.GetSize() == 0) 5715aee162fSJim Ingham { 5723a0b9cdfSJim Ingham result.AppendErrorWithFormat("Could not find a process named %s\n", wait_name); 5735aee162fSJim Ingham result.SetStatus (eReturnStatusFailed); 5745aee162fSJim Ingham return false; 5755aee162fSJim Ingham } 5765aee162fSJim Ingham else 5775aee162fSJim Ingham { 5785aee162fSJim Ingham attach_pid = pids[0]; 5795aee162fSJim Ingham } 5805aee162fSJim Ingham 5815aee162fSJim Ingham } 5825aee162fSJim Ingham 5835aee162fSJim Ingham if (attach_pid != LLDB_INVALID_PROCESS_ID) 5845aee162fSJim Ingham { 5855aee162fSJim Ingham error = process->Attach (attach_pid); 5865aee162fSJim Ingham if (error.Success()) 5875aee162fSJim Ingham { 5885aee162fSJim Ingham result.SetStatus (eReturnStatusSuccessContinuingNoResult); 5895aee162fSJim Ingham } 5905aee162fSJim Ingham else 5915aee162fSJim Ingham { 5925aee162fSJim Ingham result.AppendErrorWithFormat ("Attaching to process %i failed: %s.\n", 5935aee162fSJim Ingham attach_pid, 5945aee162fSJim Ingham error.AsCString()); 5955aee162fSJim Ingham result.SetStatus (eReturnStatusFailed); 5965aee162fSJim Ingham } 5975aee162fSJim Ingham } 5985aee162fSJim Ingham else 5995aee162fSJim Ingham { 6005aee162fSJim Ingham result.AppendErrorWithFormat ("No PID specified for attach\n", 6015aee162fSJim Ingham attach_pid, 6025aee162fSJim Ingham error.AsCString()); 6035aee162fSJim Ingham result.SetStatus (eReturnStatusFailed); 6045aee162fSJim Ingham 6055aee162fSJim Ingham } 6065aee162fSJim Ingham } 6075aee162fSJim Ingham } 6085aee162fSJim Ingham } 6095aee162fSJim Ingham 6105aee162fSJim Ingham if (result.Succeeded()) 6115aee162fSJim Ingham { 6125aee162fSJim Ingham // Okay, we're done. Last step is to warn if the executable module has changed: 6135aee162fSJim Ingham if (!old_exec_module_sp) 6145aee162fSJim Ingham { 6155aee162fSJim Ingham char new_path[PATH_MAX + 1]; 6165aee162fSJim Ingham target->GetExecutableModule()->GetFileSpec().GetPath(new_path, PATH_MAX); 6175aee162fSJim Ingham 6185aee162fSJim Ingham result.AppendMessageWithFormat("Executable module set to \"%s\".\n", 6195aee162fSJim Ingham new_path); 6205aee162fSJim Ingham } 6215aee162fSJim Ingham else if (old_exec_module_sp->GetFileSpec() != target->GetExecutableModule()->GetFileSpec()) 6225aee162fSJim Ingham { 6235aee162fSJim Ingham char old_path[PATH_MAX + 1]; 6245aee162fSJim Ingham char new_path[PATH_MAX + 1]; 6255aee162fSJim Ingham 6265aee162fSJim Ingham old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX); 6275aee162fSJim Ingham target->GetExecutableModule()->GetFileSpec().GetPath (new_path, PATH_MAX); 6285aee162fSJim Ingham 6295aee162fSJim Ingham result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n", 6305aee162fSJim Ingham old_path, new_path); 6315aee162fSJim Ingham } 6325aee162fSJim Ingham 6335aee162fSJim Ingham if (!old_arch_spec.IsValid()) 6345aee162fSJim Ingham { 6355aee162fSJim Ingham result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().AsCString()); 6365aee162fSJim Ingham } 6375aee162fSJim Ingham else if (old_arch_spec != target->GetArchitecture()) 6385aee162fSJim Ingham { 6395aee162fSJim Ingham result.AppendWarningWithFormat("Architecture changed from %s to %s.\n", 6405aee162fSJim Ingham old_arch_spec.AsCString(), target->GetArchitecture().AsCString()); 6415aee162fSJim Ingham } 6425aee162fSJim Ingham } 6435aee162fSJim Ingham return result.Succeeded(); 6445aee162fSJim Ingham } 6455aee162fSJim Ingham 6465aee162fSJim Ingham Options * 6475aee162fSJim Ingham GetOptions () 6485aee162fSJim Ingham { 6495aee162fSJim Ingham return &m_options; 6505aee162fSJim Ingham } 6515aee162fSJim Ingham 65230fdc8d8SChris Lattner protected: 65330fdc8d8SChris Lattner 65430fdc8d8SChris Lattner CommandOptions m_options; 65530fdc8d8SChris Lattner }; 65630fdc8d8SChris Lattner 65730fdc8d8SChris Lattner 65830fdc8d8SChris Lattner lldb::OptionDefinition 65930fdc8d8SChris Lattner CommandObjectProcessAttach::CommandOptions::g_option_table[] = 66030fdc8d8SChris Lattner { 661deaab222SCaroline Tice { LLDB_OPT_SET_ALL, false, "plugin", 'P', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."}, 662deaab222SCaroline Tice { LLDB_OPT_SET_1, false, "pid", 'p', required_argument, NULL, 0, eArgTypePid, "The process ID of an existing process to attach to."}, 663deaab222SCaroline Tice { LLDB_OPT_SET_2, false, "name", 'n', required_argument, NULL, 0, eArgTypeProcessName, "The name of the process to attach to."}, 664deaab222SCaroline Tice { LLDB_OPT_SET_2, false, "waitfor",'w', no_argument, NULL, 0, eArgTypeNone, "Wait for the the process with <process-name> to launch."}, 665deaab222SCaroline Tice { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 66630fdc8d8SChris Lattner }; 66730fdc8d8SChris Lattner 66830fdc8d8SChris Lattner //------------------------------------------------------------------------- 66930fdc8d8SChris Lattner // CommandObjectProcessContinue 67030fdc8d8SChris Lattner //------------------------------------------------------------------------- 67130fdc8d8SChris Lattner 67230fdc8d8SChris Lattner class CommandObjectProcessContinue : public CommandObject 67330fdc8d8SChris Lattner { 67430fdc8d8SChris Lattner public: 67530fdc8d8SChris Lattner 676a7015092SGreg Clayton CommandObjectProcessContinue (CommandInterpreter &interpreter) : 677a7015092SGreg Clayton CommandObject (interpreter, 678a7015092SGreg Clayton "process continue", 679e3d26315SCaroline Tice "Continue execution of all threads in the current process.", 68030fdc8d8SChris Lattner "process continue", 68130fdc8d8SChris Lattner eFlagProcessMustBeLaunched | eFlagProcessMustBePaused) 68230fdc8d8SChris Lattner { 68330fdc8d8SChris Lattner } 68430fdc8d8SChris Lattner 68530fdc8d8SChris Lattner 68630fdc8d8SChris Lattner ~CommandObjectProcessContinue () 68730fdc8d8SChris Lattner { 68830fdc8d8SChris Lattner } 68930fdc8d8SChris Lattner 69030fdc8d8SChris Lattner bool 691a7015092SGreg Clayton Execute (Args& command, 69230fdc8d8SChris Lattner CommandReturnObject &result) 69330fdc8d8SChris Lattner { 694a7015092SGreg Clayton Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; 695a7015092SGreg Clayton bool synchronous_execution = m_interpreter.GetSynchronous (); 69630fdc8d8SChris Lattner 69730fdc8d8SChris Lattner if (process == NULL) 69830fdc8d8SChris Lattner { 69930fdc8d8SChris Lattner result.AppendError ("no process to continue"); 70030fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 70130fdc8d8SChris Lattner return false; 70230fdc8d8SChris Lattner } 70330fdc8d8SChris Lattner 70430fdc8d8SChris Lattner StateType state = process->GetState(); 70530fdc8d8SChris Lattner if (state == eStateStopped) 70630fdc8d8SChris Lattner { 70730fdc8d8SChris Lattner if (command.GetArgumentCount() != 0) 70830fdc8d8SChris Lattner { 70930fdc8d8SChris Lattner result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str()); 71030fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 71130fdc8d8SChris Lattner return false; 71230fdc8d8SChris Lattner } 71330fdc8d8SChris Lattner 71430fdc8d8SChris Lattner const uint32_t num_threads = process->GetThreadList().GetSize(); 71530fdc8d8SChris Lattner 71630fdc8d8SChris Lattner // Set the actions that the threads should each take when resuming 71730fdc8d8SChris Lattner for (uint32_t idx=0; idx<num_threads; ++idx) 71830fdc8d8SChris Lattner { 71930fdc8d8SChris Lattner process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning); 72030fdc8d8SChris Lattner } 72130fdc8d8SChris Lattner 72230fdc8d8SChris Lattner Error error(process->Resume()); 72330fdc8d8SChris Lattner if (error.Success()) 72430fdc8d8SChris Lattner { 72530fdc8d8SChris Lattner result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID()); 72630fdc8d8SChris Lattner if (synchronous_execution) 72730fdc8d8SChris Lattner { 728b132097bSGreg Clayton state = process->WaitForProcessToStop (NULL); 72930fdc8d8SChris Lattner 73030fdc8d8SChris Lattner result.SetDidChangeProcessState (true); 73130fdc8d8SChris Lattner result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state)); 73230fdc8d8SChris Lattner result.SetStatus (eReturnStatusSuccessFinishNoResult); 73330fdc8d8SChris Lattner } 73430fdc8d8SChris Lattner else 73530fdc8d8SChris Lattner { 73630fdc8d8SChris Lattner result.SetStatus (eReturnStatusSuccessContinuingNoResult); 73730fdc8d8SChris Lattner } 73830fdc8d8SChris Lattner } 73930fdc8d8SChris Lattner else 74030fdc8d8SChris Lattner { 74130fdc8d8SChris Lattner result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString()); 74230fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 74330fdc8d8SChris Lattner } 74430fdc8d8SChris Lattner } 74530fdc8d8SChris Lattner else 74630fdc8d8SChris Lattner { 74730fdc8d8SChris Lattner result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n", 74830fdc8d8SChris Lattner StateAsCString(state)); 74930fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 75030fdc8d8SChris Lattner } 75130fdc8d8SChris Lattner return result.Succeeded(); 75230fdc8d8SChris Lattner } 75330fdc8d8SChris Lattner }; 75430fdc8d8SChris Lattner 75530fdc8d8SChris Lattner //------------------------------------------------------------------------- 75630fdc8d8SChris Lattner // CommandObjectProcessDetach 75730fdc8d8SChris Lattner //------------------------------------------------------------------------- 75830fdc8d8SChris Lattner 75930fdc8d8SChris Lattner class CommandObjectProcessDetach : public CommandObject 76030fdc8d8SChris Lattner { 76130fdc8d8SChris Lattner public: 76230fdc8d8SChris Lattner 763a7015092SGreg Clayton CommandObjectProcessDetach (CommandInterpreter &interpreter) : 764a7015092SGreg Clayton CommandObject (interpreter, 765a7015092SGreg Clayton "process detach", 766e3d26315SCaroline Tice "Detach from the current process being debugged.", 76730fdc8d8SChris Lattner "process detach", 76830fdc8d8SChris Lattner eFlagProcessMustBeLaunched) 76930fdc8d8SChris Lattner { 77030fdc8d8SChris Lattner } 77130fdc8d8SChris Lattner 77230fdc8d8SChris Lattner ~CommandObjectProcessDetach () 77330fdc8d8SChris Lattner { 77430fdc8d8SChris Lattner } 77530fdc8d8SChris Lattner 77630fdc8d8SChris Lattner bool 777a7015092SGreg Clayton Execute (Args& command, 77830fdc8d8SChris Lattner CommandReturnObject &result) 77930fdc8d8SChris Lattner { 780a7015092SGreg Clayton Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; 78130fdc8d8SChris Lattner if (process == NULL) 78230fdc8d8SChris Lattner { 78330fdc8d8SChris Lattner result.AppendError ("must have a valid process in order to detach"); 78430fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 78530fdc8d8SChris Lattner return false; 78630fdc8d8SChris Lattner } 78730fdc8d8SChris Lattner 78830fdc8d8SChris Lattner Error error (process->Detach()); 78930fdc8d8SChris Lattner if (error.Success()) 79030fdc8d8SChris Lattner { 79130fdc8d8SChris Lattner result.SetStatus (eReturnStatusSuccessFinishResult); 79230fdc8d8SChris Lattner } 79330fdc8d8SChris Lattner else 79430fdc8d8SChris Lattner { 79530fdc8d8SChris Lattner result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString()); 79630fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 79730fdc8d8SChris Lattner return false; 79830fdc8d8SChris Lattner } 79930fdc8d8SChris Lattner return result.Succeeded(); 80030fdc8d8SChris Lattner } 80130fdc8d8SChris Lattner }; 80230fdc8d8SChris Lattner 80330fdc8d8SChris Lattner //------------------------------------------------------------------------- 80430fdc8d8SChris Lattner // CommandObjectProcessSignal 80530fdc8d8SChris Lattner //------------------------------------------------------------------------- 80630fdc8d8SChris Lattner 80730fdc8d8SChris Lattner class CommandObjectProcessSignal : public CommandObject 80830fdc8d8SChris Lattner { 80930fdc8d8SChris Lattner public: 81030fdc8d8SChris Lattner 811a7015092SGreg Clayton CommandObjectProcessSignal (CommandInterpreter &interpreter) : 812a7015092SGreg Clayton CommandObject (interpreter, 813a7015092SGreg Clayton "process signal", 814e3d26315SCaroline Tice "Send a UNIX signal to the current process being debugged.", 815405fe67fSCaroline Tice NULL) 81630fdc8d8SChris Lattner { 817405fe67fSCaroline Tice CommandArgumentEntry arg; 818405fe67fSCaroline Tice CommandArgumentData signal_arg; 819405fe67fSCaroline Tice 820405fe67fSCaroline Tice // Define the first (and only) variant of this arg. 821405fe67fSCaroline Tice signal_arg.arg_type = eArgTypeUnixSignalNumber; 822405fe67fSCaroline Tice signal_arg.arg_repetition = eArgRepeatPlain; 823405fe67fSCaroline Tice 824405fe67fSCaroline Tice // There is only one variant this argument could be; put it into the argument entry. 825405fe67fSCaroline Tice arg.push_back (signal_arg); 826405fe67fSCaroline Tice 827405fe67fSCaroline Tice // Push the data for the first argument into the m_arguments vector. 828405fe67fSCaroline Tice m_arguments.push_back (arg); 82930fdc8d8SChris Lattner } 83030fdc8d8SChris Lattner 83130fdc8d8SChris Lattner ~CommandObjectProcessSignal () 83230fdc8d8SChris Lattner { 83330fdc8d8SChris Lattner } 83430fdc8d8SChris Lattner 83530fdc8d8SChris Lattner bool 836a7015092SGreg Clayton Execute (Args& command, 83730fdc8d8SChris Lattner CommandReturnObject &result) 83830fdc8d8SChris Lattner { 839a7015092SGreg Clayton Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; 84030fdc8d8SChris Lattner if (process == NULL) 84130fdc8d8SChris Lattner { 84230fdc8d8SChris Lattner result.AppendError ("no process to signal"); 84330fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 84430fdc8d8SChris Lattner return false; 84530fdc8d8SChris Lattner } 84630fdc8d8SChris Lattner 84730fdc8d8SChris Lattner if (command.GetArgumentCount() == 1) 84830fdc8d8SChris Lattner { 849237cd906SGreg Clayton int signo = LLDB_INVALID_SIGNAL_NUMBER; 850237cd906SGreg Clayton 851237cd906SGreg Clayton const char *signal_name = command.GetArgumentAtIndex(0); 852237cd906SGreg Clayton if (::isxdigit (signal_name[0])) 853237cd906SGreg Clayton signo = Args::StringToSInt32(signal_name, LLDB_INVALID_SIGNAL_NUMBER, 0); 854237cd906SGreg Clayton else 855237cd906SGreg Clayton signo = process->GetUnixSignals().GetSignalNumberFromName (signal_name); 856237cd906SGreg Clayton 857237cd906SGreg Clayton if (signo == LLDB_INVALID_SIGNAL_NUMBER) 85830fdc8d8SChris Lattner { 85930fdc8d8SChris Lattner result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0)); 86030fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 86130fdc8d8SChris Lattner } 86230fdc8d8SChris Lattner else 86330fdc8d8SChris Lattner { 86430fdc8d8SChris Lattner Error error (process->Signal (signo)); 86530fdc8d8SChris Lattner if (error.Success()) 86630fdc8d8SChris Lattner { 86730fdc8d8SChris Lattner result.SetStatus (eReturnStatusSuccessFinishResult); 86830fdc8d8SChris Lattner } 86930fdc8d8SChris Lattner else 87030fdc8d8SChris Lattner { 87130fdc8d8SChris Lattner result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString()); 87230fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 87330fdc8d8SChris Lattner } 87430fdc8d8SChris Lattner } 87530fdc8d8SChris Lattner } 87630fdc8d8SChris Lattner else 87730fdc8d8SChris Lattner { 87830fdc8d8SChris Lattner result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: \n", m_cmd_name.c_str(), 87930fdc8d8SChris Lattner m_cmd_syntax.c_str()); 88030fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 88130fdc8d8SChris Lattner } 88230fdc8d8SChris Lattner return result.Succeeded(); 88330fdc8d8SChris Lattner } 88430fdc8d8SChris Lattner }; 88530fdc8d8SChris Lattner 88630fdc8d8SChris Lattner 88730fdc8d8SChris Lattner //------------------------------------------------------------------------- 88830fdc8d8SChris Lattner // CommandObjectProcessInterrupt 88930fdc8d8SChris Lattner //------------------------------------------------------------------------- 89030fdc8d8SChris Lattner 89130fdc8d8SChris Lattner class CommandObjectProcessInterrupt : public CommandObject 89230fdc8d8SChris Lattner { 89330fdc8d8SChris Lattner public: 89430fdc8d8SChris Lattner 89530fdc8d8SChris Lattner 896a7015092SGreg Clayton CommandObjectProcessInterrupt (CommandInterpreter &interpreter) : 897a7015092SGreg Clayton CommandObject (interpreter, 898a7015092SGreg Clayton "process interrupt", 899e3d26315SCaroline Tice "Interrupt the current process being debugged.", 90030fdc8d8SChris Lattner "process interrupt", 90130fdc8d8SChris Lattner eFlagProcessMustBeLaunched) 90230fdc8d8SChris Lattner { 90330fdc8d8SChris Lattner } 90430fdc8d8SChris Lattner 90530fdc8d8SChris Lattner ~CommandObjectProcessInterrupt () 90630fdc8d8SChris Lattner { 90730fdc8d8SChris Lattner } 90830fdc8d8SChris Lattner 90930fdc8d8SChris Lattner bool 910a7015092SGreg Clayton Execute (Args& command, 91130fdc8d8SChris Lattner CommandReturnObject &result) 91230fdc8d8SChris Lattner { 913a7015092SGreg Clayton Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; 91430fdc8d8SChris Lattner if (process == NULL) 91530fdc8d8SChris Lattner { 91630fdc8d8SChris Lattner result.AppendError ("no process to halt"); 91730fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 91830fdc8d8SChris Lattner return false; 91930fdc8d8SChris Lattner } 92030fdc8d8SChris Lattner 92130fdc8d8SChris Lattner if (command.GetArgumentCount() == 0) 92230fdc8d8SChris Lattner { 92330fdc8d8SChris Lattner Error error(process->Halt ()); 92430fdc8d8SChris Lattner if (error.Success()) 92530fdc8d8SChris Lattner { 92630fdc8d8SChris Lattner result.SetStatus (eReturnStatusSuccessFinishResult); 92730fdc8d8SChris Lattner 92830fdc8d8SChris Lattner // Maybe we should add a "SuspendThreadPlans so we 92930fdc8d8SChris Lattner // can halt, and keep in place all the current thread plans. 93030fdc8d8SChris Lattner process->GetThreadList().DiscardThreadPlans(); 93130fdc8d8SChris Lattner } 93230fdc8d8SChris Lattner else 93330fdc8d8SChris Lattner { 93430fdc8d8SChris Lattner result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString()); 93530fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 93630fdc8d8SChris Lattner } 93730fdc8d8SChris Lattner } 93830fdc8d8SChris Lattner else 93930fdc8d8SChris Lattner { 94030fdc8d8SChris Lattner result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n", 94130fdc8d8SChris Lattner m_cmd_name.c_str(), 94230fdc8d8SChris Lattner m_cmd_syntax.c_str()); 94330fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 94430fdc8d8SChris Lattner } 94530fdc8d8SChris Lattner return result.Succeeded(); 94630fdc8d8SChris Lattner } 94730fdc8d8SChris Lattner }; 94830fdc8d8SChris Lattner 94930fdc8d8SChris Lattner //------------------------------------------------------------------------- 95030fdc8d8SChris Lattner // CommandObjectProcessKill 95130fdc8d8SChris Lattner //------------------------------------------------------------------------- 95230fdc8d8SChris Lattner 95330fdc8d8SChris Lattner class CommandObjectProcessKill : public CommandObject 95430fdc8d8SChris Lattner { 95530fdc8d8SChris Lattner public: 95630fdc8d8SChris Lattner 957a7015092SGreg Clayton CommandObjectProcessKill (CommandInterpreter &interpreter) : 958a7015092SGreg Clayton CommandObject (interpreter, 959a7015092SGreg Clayton "process kill", 960e3d26315SCaroline Tice "Terminate the current process being debugged.", 96130fdc8d8SChris Lattner "process kill", 96230fdc8d8SChris Lattner eFlagProcessMustBeLaunched) 96330fdc8d8SChris Lattner { 96430fdc8d8SChris Lattner } 96530fdc8d8SChris Lattner 96630fdc8d8SChris Lattner ~CommandObjectProcessKill () 96730fdc8d8SChris Lattner { 96830fdc8d8SChris Lattner } 96930fdc8d8SChris Lattner 97030fdc8d8SChris Lattner bool 971a7015092SGreg Clayton Execute (Args& command, 97230fdc8d8SChris Lattner CommandReturnObject &result) 97330fdc8d8SChris Lattner { 974a7015092SGreg Clayton Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; 97530fdc8d8SChris Lattner if (process == NULL) 97630fdc8d8SChris Lattner { 97730fdc8d8SChris Lattner result.AppendError ("no process to kill"); 97830fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 97930fdc8d8SChris Lattner return false; 98030fdc8d8SChris Lattner } 98130fdc8d8SChris Lattner 98230fdc8d8SChris Lattner if (command.GetArgumentCount() == 0) 98330fdc8d8SChris Lattner { 98430fdc8d8SChris Lattner Error error (process->Destroy()); 98530fdc8d8SChris Lattner if (error.Success()) 98630fdc8d8SChris Lattner { 98730fdc8d8SChris Lattner result.SetStatus (eReturnStatusSuccessFinishResult); 98830fdc8d8SChris Lattner } 98930fdc8d8SChris Lattner else 99030fdc8d8SChris Lattner { 99130fdc8d8SChris Lattner result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString()); 99230fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 99330fdc8d8SChris Lattner } 99430fdc8d8SChris Lattner } 99530fdc8d8SChris Lattner else 99630fdc8d8SChris Lattner { 99730fdc8d8SChris Lattner result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n", 99830fdc8d8SChris Lattner m_cmd_name.c_str(), 99930fdc8d8SChris Lattner m_cmd_syntax.c_str()); 100030fdc8d8SChris Lattner result.SetStatus (eReturnStatusFailed); 100130fdc8d8SChris Lattner } 100230fdc8d8SChris Lattner return result.Succeeded(); 100330fdc8d8SChris Lattner } 100430fdc8d8SChris Lattner }; 100530fdc8d8SChris Lattner 100630fdc8d8SChris Lattner //------------------------------------------------------------------------- 10074b9bea87SJim Ingham // CommandObjectProcessStatus 10084b9bea87SJim Ingham //------------------------------------------------------------------------- 10094b9bea87SJim Ingham class CommandObjectProcessStatus : public CommandObject 10104b9bea87SJim Ingham { 10114b9bea87SJim Ingham public: 1012a7015092SGreg Clayton CommandObjectProcessStatus (CommandInterpreter &interpreter) : 1013a7015092SGreg Clayton CommandObject (interpreter, 1014a7015092SGreg Clayton "process status", 1015e3d26315SCaroline Tice "Show the current status and location of executing process.", 1016e3d26315SCaroline Tice "process status", 10174b9bea87SJim Ingham 0) 10184b9bea87SJim Ingham { 10194b9bea87SJim Ingham } 10204b9bea87SJim Ingham 10214b9bea87SJim Ingham ~CommandObjectProcessStatus() 10224b9bea87SJim Ingham { 10234b9bea87SJim Ingham } 10244b9bea87SJim Ingham 10254b9bea87SJim Ingham 10264b9bea87SJim Ingham bool 10274b9bea87SJim Ingham Execute 10284b9bea87SJim Ingham ( 10294b9bea87SJim Ingham Args& command, 10304b9bea87SJim Ingham CommandReturnObject &result 10314b9bea87SJim Ingham ) 10324b9bea87SJim Ingham { 10334b9bea87SJim Ingham StreamString &output_stream = result.GetOutputStream(); 10344b9bea87SJim Ingham result.SetStatus (eReturnStatusSuccessFinishNoResult); 1035a7015092SGreg Clayton ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext()); 10364b9bea87SJim Ingham if (exe_ctx.process) 10374b9bea87SJim Ingham { 10384b9bea87SJim Ingham const StateType state = exe_ctx.process->GetState(); 10394b9bea87SJim Ingham if (StateIsStoppedState(state)) 10404b9bea87SJim Ingham { 10414b9bea87SJim Ingham if (state == eStateExited) 10424b9bea87SJim Ingham { 10434b9bea87SJim Ingham int exit_status = exe_ctx.process->GetExitStatus(); 10444b9bea87SJim Ingham const char *exit_description = exe_ctx.process->GetExitDescription(); 10454b9bea87SJim Ingham output_stream.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n", 10464b9bea87SJim Ingham exe_ctx.process->GetID(), 10474b9bea87SJim Ingham exit_status, 10484b9bea87SJim Ingham exit_status, 10494b9bea87SJim Ingham exit_description ? exit_description : ""); 10504b9bea87SJim Ingham } 10514b9bea87SJim Ingham else 10524b9bea87SJim Ingham { 10534b9bea87SJim Ingham output_stream.Printf ("Process %d %s\n", exe_ctx.process->GetID(), StateAsCString (state)); 10544b9bea87SJim Ingham if (exe_ctx.thread == NULL) 10554b9bea87SJim Ingham exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get(); 10564b9bea87SJim Ingham if (exe_ctx.thread != NULL) 10574b9bea87SJim Ingham { 1058a7015092SGreg Clayton DisplayThreadsInfo (m_interpreter, &exe_ctx, result, true, true); 10594b9bea87SJim Ingham } 10604b9bea87SJim Ingham else 10614b9bea87SJim Ingham { 10624b9bea87SJim Ingham result.AppendError ("No valid thread found in current process."); 10634b9bea87SJim Ingham result.SetStatus (eReturnStatusFailed); 10644b9bea87SJim Ingham } 10654b9bea87SJim Ingham } 10664b9bea87SJim Ingham } 10674b9bea87SJim Ingham else 10684b9bea87SJim Ingham { 10694b9bea87SJim Ingham output_stream.Printf ("Process %d is running.\n", 10704b9bea87SJim Ingham exe_ctx.process->GetID()); 10714b9bea87SJim Ingham } 10724b9bea87SJim Ingham } 10734b9bea87SJim Ingham else 10744b9bea87SJim Ingham { 10754b9bea87SJim Ingham result.AppendError ("No current location or status available."); 10764b9bea87SJim Ingham result.SetStatus (eReturnStatusFailed); 10774b9bea87SJim Ingham } 10784b9bea87SJim Ingham return result.Succeeded(); 10794b9bea87SJim Ingham } 10804b9bea87SJim Ingham }; 10814b9bea87SJim Ingham 10824b9bea87SJim Ingham //------------------------------------------------------------------------- 108335731357SCaroline Tice // CommandObjectProcessHandle 108435731357SCaroline Tice //------------------------------------------------------------------------- 108535731357SCaroline Tice 108635731357SCaroline Tice class CommandObjectProcessHandle : public CommandObject 108735731357SCaroline Tice { 108835731357SCaroline Tice public: 108935731357SCaroline Tice 109035731357SCaroline Tice class CommandOptions : public Options 109135731357SCaroline Tice { 109235731357SCaroline Tice public: 109335731357SCaroline Tice 109435731357SCaroline Tice CommandOptions () : 109535731357SCaroline Tice Options () 109635731357SCaroline Tice { 109735731357SCaroline Tice ResetOptionValues (); 109835731357SCaroline Tice } 109935731357SCaroline Tice 110035731357SCaroline Tice ~CommandOptions () 110135731357SCaroline Tice { 110235731357SCaroline Tice } 110335731357SCaroline Tice 110435731357SCaroline Tice Error 110535731357SCaroline Tice SetOptionValue (int option_idx, const char *option_arg) 110635731357SCaroline Tice { 110735731357SCaroline Tice Error error; 110835731357SCaroline Tice char short_option = (char) m_getopt_table[option_idx].val; 110935731357SCaroline Tice 111035731357SCaroline Tice switch (short_option) 111135731357SCaroline Tice { 111235731357SCaroline Tice case 's': 111335731357SCaroline Tice stop = option_arg; 111435731357SCaroline Tice break; 111535731357SCaroline Tice case 'n': 111635731357SCaroline Tice notify = option_arg; 111735731357SCaroline Tice break; 111835731357SCaroline Tice case 'p': 111935731357SCaroline Tice pass = option_arg; 112035731357SCaroline Tice break; 112135731357SCaroline Tice default: 112235731357SCaroline Tice error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option); 112335731357SCaroline Tice break; 112435731357SCaroline Tice } 112535731357SCaroline Tice return error; 112635731357SCaroline Tice } 112735731357SCaroline Tice 112835731357SCaroline Tice void 112935731357SCaroline Tice ResetOptionValues () 113035731357SCaroline Tice { 113135731357SCaroline Tice Options::ResetOptionValues(); 113235731357SCaroline Tice stop.clear(); 113335731357SCaroline Tice notify.clear(); 113435731357SCaroline Tice pass.clear(); 113535731357SCaroline Tice } 113635731357SCaroline Tice 113735731357SCaroline Tice const lldb::OptionDefinition* 113835731357SCaroline Tice GetDefinitions () 113935731357SCaroline Tice { 114035731357SCaroline Tice return g_option_table; 114135731357SCaroline Tice } 114235731357SCaroline Tice 114335731357SCaroline Tice // Options table: Required for subclasses of Options. 114435731357SCaroline Tice 114535731357SCaroline Tice static lldb::OptionDefinition g_option_table[]; 114635731357SCaroline Tice 114735731357SCaroline Tice // Instance variables to hold the values for command options. 114835731357SCaroline Tice 114935731357SCaroline Tice std::string stop; 115035731357SCaroline Tice std::string notify; 115135731357SCaroline Tice std::string pass; 115235731357SCaroline Tice }; 115335731357SCaroline Tice 115435731357SCaroline Tice 115535731357SCaroline Tice CommandObjectProcessHandle (CommandInterpreter &interpreter) : 115635731357SCaroline Tice CommandObject (interpreter, 115735731357SCaroline Tice "process handle", 115810ad7993SCaroline Tice "Show or update what the process and debugger should do with various signals received from the OS.", 115935731357SCaroline Tice NULL) 116035731357SCaroline Tice { 116110ad7993SCaroline Tice SetHelpLong ("If no signals are specified, update them all. If no update option is specified, list the current values.\n"); 116235731357SCaroline Tice CommandArgumentEntry arg; 116335731357SCaroline Tice CommandArgumentData signal_name_arg; 116435731357SCaroline Tice 116535731357SCaroline Tice signal_name_arg.arg_type = eArgTypeSignalName; 116610ad7993SCaroline Tice signal_name_arg.arg_repetition = eArgRepeatStar; 116735731357SCaroline Tice 116835731357SCaroline Tice arg.push_back (signal_name_arg); 116935731357SCaroline Tice 117035731357SCaroline Tice m_arguments.push_back (arg); 117135731357SCaroline Tice } 117235731357SCaroline Tice 117335731357SCaroline Tice ~CommandObjectProcessHandle () 117435731357SCaroline Tice { 117535731357SCaroline Tice } 117635731357SCaroline Tice 117735731357SCaroline Tice Options * 117835731357SCaroline Tice GetOptions () 117935731357SCaroline Tice { 118035731357SCaroline Tice return &m_options; 118135731357SCaroline Tice } 118235731357SCaroline Tice 118335731357SCaroline Tice bool 118410ad7993SCaroline Tice VerifyCommandOptionValue (const std::string &option, int &real_value) 118535731357SCaroline Tice { 118635731357SCaroline Tice bool okay = true; 118735731357SCaroline Tice 118810ad7993SCaroline Tice bool success = false; 118910ad7993SCaroline Tice bool tmp_value = Args::StringToBoolean (option.c_str(), false, &success); 119010ad7993SCaroline Tice 119110ad7993SCaroline Tice if (success && tmp_value) 119210ad7993SCaroline Tice real_value = 1; 119310ad7993SCaroline Tice else if (success && !tmp_value) 119410ad7993SCaroline Tice real_value = 0; 119535731357SCaroline Tice else 119635731357SCaroline Tice { 119735731357SCaroline Tice // If the value isn't 'true' or 'false', it had better be 0 or 1. 119810ad7993SCaroline Tice real_value = Args::StringToUInt32 (option.c_str(), 3); 119910ad7993SCaroline Tice if (real_value != 0 && real_value != 1) 120035731357SCaroline Tice okay = false; 120135731357SCaroline Tice } 120235731357SCaroline Tice 120335731357SCaroline Tice return okay; 120435731357SCaroline Tice } 120535731357SCaroline Tice 120610ad7993SCaroline Tice void 120710ad7993SCaroline Tice PrintSignalHeader (Stream &str) 120810ad7993SCaroline Tice { 120910ad7993SCaroline Tice str.Printf ("NAME PASS STOP NOTIFY\n"); 121010ad7993SCaroline Tice str.Printf ("========== ===== ===== ======\n"); 121110ad7993SCaroline Tice } 121210ad7993SCaroline Tice 121310ad7993SCaroline Tice void 121410ad7993SCaroline Tice PrintSignal (Stream &str, int32_t signo, const char *sig_name, UnixSignals &signals) 121510ad7993SCaroline Tice { 121610ad7993SCaroline Tice bool stop; 121710ad7993SCaroline Tice bool suppress; 121810ad7993SCaroline Tice bool notify; 121910ad7993SCaroline Tice 122010ad7993SCaroline Tice str.Printf ("%-10s ", sig_name); 122110ad7993SCaroline Tice if (signals.GetSignalInfo (signo, suppress, stop, notify)) 122210ad7993SCaroline Tice { 122310ad7993SCaroline Tice bool pass = !suppress; 122410ad7993SCaroline Tice str.Printf ("%s %s %s", 122510ad7993SCaroline Tice (pass ? "true " : "false"), 122610ad7993SCaroline Tice (stop ? "true " : "false"), 122710ad7993SCaroline Tice (notify ? "true " : "false")); 122810ad7993SCaroline Tice } 122910ad7993SCaroline Tice str.Printf ("\n"); 123010ad7993SCaroline Tice } 123110ad7993SCaroline Tice 123210ad7993SCaroline Tice void 123310ad7993SCaroline Tice PrintSignalInformation (Stream &str, Args &signal_args, int num_valid_signals, UnixSignals &signals) 123410ad7993SCaroline Tice { 123510ad7993SCaroline Tice PrintSignalHeader (str); 123610ad7993SCaroline Tice 123710ad7993SCaroline Tice if (num_valid_signals > 0) 123810ad7993SCaroline Tice { 123910ad7993SCaroline Tice size_t num_args = signal_args.GetArgumentCount(); 124010ad7993SCaroline Tice for (size_t i = 0; i < num_args; ++i) 124110ad7993SCaroline Tice { 124210ad7993SCaroline Tice int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i)); 124310ad7993SCaroline Tice if (signo != LLDB_INVALID_SIGNAL_NUMBER) 124410ad7993SCaroline Tice PrintSignal (str, signo, signal_args.GetArgumentAtIndex (i), signals); 124510ad7993SCaroline Tice } 124610ad7993SCaroline Tice } 124710ad7993SCaroline Tice else // Print info for ALL signals 124810ad7993SCaroline Tice { 124910ad7993SCaroline Tice int32_t signo = signals.GetFirstSignalNumber(); 125010ad7993SCaroline Tice while (signo != LLDB_INVALID_SIGNAL_NUMBER) 125110ad7993SCaroline Tice { 125210ad7993SCaroline Tice PrintSignal (str, signo, signals.GetSignalAsCString (signo), signals); 125310ad7993SCaroline Tice signo = signals.GetNextSignalNumber (signo); 125410ad7993SCaroline Tice } 125510ad7993SCaroline Tice } 125610ad7993SCaroline Tice } 125710ad7993SCaroline Tice 125835731357SCaroline Tice bool 125935731357SCaroline Tice Execute (Args &signal_args, CommandReturnObject &result) 126035731357SCaroline Tice { 126135731357SCaroline Tice TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget(); 126235731357SCaroline Tice 126335731357SCaroline Tice if (!target_sp) 126435731357SCaroline Tice { 126535731357SCaroline Tice result.AppendError ("No current target;" 126635731357SCaroline Tice " cannot handle signals until you have a valid target and process.\n"); 126735731357SCaroline Tice result.SetStatus (eReturnStatusFailed); 126835731357SCaroline Tice return false; 126935731357SCaroline Tice } 127035731357SCaroline Tice 127135731357SCaroline Tice ProcessSP process_sp = target_sp->GetProcessSP(); 127235731357SCaroline Tice 127335731357SCaroline Tice if (!process_sp) 127435731357SCaroline Tice { 127535731357SCaroline Tice result.AppendError ("No current process; cannot handle signals until you have a valid process.\n"); 127635731357SCaroline Tice result.SetStatus (eReturnStatusFailed); 127735731357SCaroline Tice return false; 127835731357SCaroline Tice } 127935731357SCaroline Tice 128035731357SCaroline Tice int stop_action = -1; // -1 means leave the current setting alone 128135731357SCaroline Tice int pass_action = -1; // -1 means leave the current setting alone 128235731357SCaroline Tice int notify_action = -1; // -1 means leave the current setting alone 128335731357SCaroline Tice 128435731357SCaroline Tice if (! m_options.stop.empty() 128510ad7993SCaroline Tice && ! VerifyCommandOptionValue (m_options.stop, stop_action)) 128635731357SCaroline Tice { 128735731357SCaroline Tice result.AppendError ("Invalid argument for command option --stop; must be true or false.\n"); 128835731357SCaroline Tice result.SetStatus (eReturnStatusFailed); 128935731357SCaroline Tice return false; 129035731357SCaroline Tice } 129135731357SCaroline Tice 129235731357SCaroline Tice if (! m_options.notify.empty() 129310ad7993SCaroline Tice && ! VerifyCommandOptionValue (m_options.notify, notify_action)) 129435731357SCaroline Tice { 129535731357SCaroline Tice result.AppendError ("Invalid argument for command option --notify; must be true or false.\n"); 129635731357SCaroline Tice result.SetStatus (eReturnStatusFailed); 129735731357SCaroline Tice return false; 129835731357SCaroline Tice } 129935731357SCaroline Tice 130035731357SCaroline Tice if (! m_options.pass.empty() 130110ad7993SCaroline Tice && ! VerifyCommandOptionValue (m_options.pass, pass_action)) 130235731357SCaroline Tice { 130335731357SCaroline Tice result.AppendError ("Invalid argument for command option --pass; must be true or false.\n"); 130435731357SCaroline Tice result.SetStatus (eReturnStatusFailed); 130535731357SCaroline Tice return false; 130635731357SCaroline Tice } 130735731357SCaroline Tice 130835731357SCaroline Tice size_t num_args = signal_args.GetArgumentCount(); 130935731357SCaroline Tice UnixSignals &signals = process_sp->GetUnixSignals(); 131035731357SCaroline Tice int num_signals_set = 0; 131135731357SCaroline Tice 131210ad7993SCaroline Tice if (num_args > 0) 131310ad7993SCaroline Tice { 131435731357SCaroline Tice for (size_t i = 0; i < num_args; ++i) 131535731357SCaroline Tice { 131635731357SCaroline Tice int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i)); 131735731357SCaroline Tice if (signo != LLDB_INVALID_SIGNAL_NUMBER) 131835731357SCaroline Tice { 131910ad7993SCaroline Tice // Casting the actions as bools here should be okay, because VerifyCommandOptionValue guarantees 132035731357SCaroline Tice // the value is either 0 or 1. 132135731357SCaroline Tice if (stop_action != -1) 132235731357SCaroline Tice signals.SetShouldStop (signo, (bool) stop_action); 132335731357SCaroline Tice if (pass_action != -1) 132435731357SCaroline Tice { 132510ad7993SCaroline Tice bool suppress = ! ((bool) pass_action); 132610ad7993SCaroline Tice signals.SetShouldSuppress (signo, suppress); 132735731357SCaroline Tice } 132835731357SCaroline Tice if (notify_action != -1) 132935731357SCaroline Tice signals.SetShouldNotify (signo, (bool) notify_action); 133035731357SCaroline Tice ++num_signals_set; 133135731357SCaroline Tice } 133235731357SCaroline Tice else 133335731357SCaroline Tice { 133435731357SCaroline Tice result.AppendErrorWithFormat ("Invalid signal name '%s'\n", signal_args.GetArgumentAtIndex (i)); 133535731357SCaroline Tice } 133635731357SCaroline Tice } 133710ad7993SCaroline Tice } 133810ad7993SCaroline Tice else 133910ad7993SCaroline Tice { 134010ad7993SCaroline Tice // No signal specified, if any command options were specified, update ALL signals. 134110ad7993SCaroline Tice if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1)) 134210ad7993SCaroline Tice { 134310ad7993SCaroline Tice if (m_interpreter.Confirm ("Do you really want to update all the signals?", false)) 134410ad7993SCaroline Tice { 134510ad7993SCaroline Tice int32_t signo = signals.GetFirstSignalNumber(); 134610ad7993SCaroline Tice while (signo != LLDB_INVALID_SIGNAL_NUMBER) 134710ad7993SCaroline Tice { 134810ad7993SCaroline Tice if (notify_action != -1) 134910ad7993SCaroline Tice signals.SetShouldNotify (signo, (bool) notify_action); 135010ad7993SCaroline Tice if (stop_action != -1) 135110ad7993SCaroline Tice signals.SetShouldStop (signo, (bool) stop_action); 135210ad7993SCaroline Tice if (pass_action != -1) 135310ad7993SCaroline Tice { 135410ad7993SCaroline Tice bool suppress = ! ((bool) pass_action); 135510ad7993SCaroline Tice signals.SetShouldSuppress (signo, suppress); 135610ad7993SCaroline Tice } 135710ad7993SCaroline Tice signo = signals.GetNextSignalNumber (signo); 135810ad7993SCaroline Tice } 135910ad7993SCaroline Tice } 136010ad7993SCaroline Tice } 136110ad7993SCaroline Tice } 136210ad7993SCaroline Tice 136310ad7993SCaroline Tice PrintSignalInformation (result.GetOutputStream(), signal_args, num_signals_set, signals); 136435731357SCaroline Tice 136535731357SCaroline Tice if (num_signals_set > 0) 136635731357SCaroline Tice result.SetStatus (eReturnStatusSuccessFinishNoResult); 136735731357SCaroline Tice else 136835731357SCaroline Tice result.SetStatus (eReturnStatusFailed); 136935731357SCaroline Tice 137035731357SCaroline Tice return result.Succeeded(); 137135731357SCaroline Tice } 137235731357SCaroline Tice 137335731357SCaroline Tice protected: 137435731357SCaroline Tice 137535731357SCaroline Tice CommandOptions m_options; 137635731357SCaroline Tice }; 137735731357SCaroline Tice 137835731357SCaroline Tice lldb::OptionDefinition 137935731357SCaroline Tice CommandObjectProcessHandle::CommandOptions::g_option_table[] = 138035731357SCaroline Tice { 138135731357SCaroline Tice { LLDB_OPT_SET_1, false, "stop", 's', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the process should be stopped if the signal is received." }, 138235731357SCaroline Tice { LLDB_OPT_SET_1, false, "notify", 'n', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the debugger should notify the user if the signal is received." }, 138335731357SCaroline Tice { LLDB_OPT_SET_1, false, "pass", 'p', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." }, 138435731357SCaroline Tice { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 138535731357SCaroline Tice }; 138635731357SCaroline Tice 138735731357SCaroline Tice //------------------------------------------------------------------------- 138830fdc8d8SChris Lattner // CommandObjectMultiwordProcess 138930fdc8d8SChris Lattner //------------------------------------------------------------------------- 139030fdc8d8SChris Lattner 13916611103cSGreg Clayton CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter &interpreter) : 1392a7015092SGreg Clayton CommandObjectMultiword (interpreter, 1393a7015092SGreg Clayton "process", 139430fdc8d8SChris Lattner "A set of commands for operating on a process.", 139530fdc8d8SChris Lattner "process <subcommand> [<subcommand-options>]") 139630fdc8d8SChris Lattner { 1397a7015092SGreg Clayton LoadSubCommand ("attach", CommandObjectSP (new CommandObjectProcessAttach (interpreter))); 1398a7015092SGreg Clayton LoadSubCommand ("launch", CommandObjectSP (new CommandObjectProcessLaunch (interpreter))); 1399a7015092SGreg Clayton LoadSubCommand ("continue", CommandObjectSP (new CommandObjectProcessContinue (interpreter))); 1400a7015092SGreg Clayton LoadSubCommand ("detach", CommandObjectSP (new CommandObjectProcessDetach (interpreter))); 1401a7015092SGreg Clayton LoadSubCommand ("signal", CommandObjectSP (new CommandObjectProcessSignal (interpreter))); 140235731357SCaroline Tice LoadSubCommand ("handle", CommandObjectSP (new CommandObjectProcessHandle (interpreter))); 1403a7015092SGreg Clayton LoadSubCommand ("status", CommandObjectSP (new CommandObjectProcessStatus (interpreter))); 1404a7015092SGreg Clayton LoadSubCommand ("interrupt", CommandObjectSP (new CommandObjectProcessInterrupt (interpreter))); 1405a7015092SGreg Clayton LoadSubCommand ("kill", CommandObjectSP (new CommandObjectProcessKill (interpreter))); 140630fdc8d8SChris Lattner } 140730fdc8d8SChris Lattner 140830fdc8d8SChris Lattner CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess () 140930fdc8d8SChris Lattner { 141030fdc8d8SChris Lattner } 141130fdc8d8SChris Lattner 1412