1254721Semaste//===-- CommandObjectProcess.cpp --------------------------------*- C++ -*-===// 2254721Semaste// 3254721Semaste// The LLVM Compiler Infrastructure 4254721Semaste// 5254721Semaste// This file is distributed under the University of Illinois Open Source 6254721Semaste// License. See LICENSE.TXT for details. 7254721Semaste// 8254721Semaste//===----------------------------------------------------------------------===// 9254721Semaste 10254721Semaste#include "lldb/lldb-python.h" 11254721Semaste 12254721Semaste#include "CommandObjectProcess.h" 13254721Semaste 14254721Semaste// C Includes 15254721Semaste// C++ Includes 16254721Semaste// Other libraries and framework includes 17254721Semaste// Project includes 18254721Semaste#include "lldb/Breakpoint/Breakpoint.h" 19254721Semaste#include "lldb/Breakpoint/BreakpointLocation.h" 20254721Semaste#include "lldb/Breakpoint/BreakpointSite.h" 21254721Semaste#include "lldb/Core/State.h" 22254721Semaste#include "lldb/Core/Module.h" 23254721Semaste#include "lldb/Host/Host.h" 24254721Semaste#include "lldb/Interpreter/Args.h" 25254721Semaste#include "lldb/Interpreter/Options.h" 26254721Semaste#include "lldb/Interpreter/CommandInterpreter.h" 27254721Semaste#include "lldb/Interpreter/CommandReturnObject.h" 28254721Semaste#include "lldb/Target/Platform.h" 29254721Semaste#include "lldb/Target/Process.h" 30254721Semaste#include "lldb/Target/StopInfo.h" 31254721Semaste#include "lldb/Target/Target.h" 32254721Semaste#include "lldb/Target/Thread.h" 33254721Semaste 34254721Semasteusing namespace lldb; 35254721Semasteusing namespace lldb_private; 36254721Semaste 37254721Semasteclass CommandObjectProcessLaunchOrAttach : public CommandObjectParsed 38254721Semaste{ 39254721Semastepublic: 40254721Semaste CommandObjectProcessLaunchOrAttach (CommandInterpreter &interpreter, 41254721Semaste const char *name, 42254721Semaste const char *help, 43254721Semaste const char *syntax, 44254721Semaste uint32_t flags, 45254721Semaste const char *new_process_action) : 46254721Semaste CommandObjectParsed (interpreter, name, help, syntax, flags), 47254721Semaste m_new_process_action (new_process_action) {} 48254721Semaste 49254721Semaste virtual ~CommandObjectProcessLaunchOrAttach () {} 50254721Semasteprotected: 51254721Semaste bool 52269024Semaste StopProcessIfNecessary (Process *process, StateType &state, CommandReturnObject &result) 53254721Semaste { 54254721Semaste state = eStateInvalid; 55254721Semaste if (process) 56254721Semaste { 57254721Semaste state = process->GetState(); 58254721Semaste 59254721Semaste if (process->IsAlive() && state != eStateConnected) 60254721Semaste { 61254721Semaste char message[1024]; 62254721Semaste if (process->GetState() == eStateAttaching) 63254721Semaste ::snprintf (message, sizeof(message), "There is a pending attach, abort it and %s?", m_new_process_action.c_str()); 64254721Semaste else if (process->GetShouldDetach()) 65254721Semaste ::snprintf (message, sizeof(message), "There is a running process, detach from it and %s?", m_new_process_action.c_str()); 66254721Semaste else 67254721Semaste ::snprintf (message, sizeof(message), "There is a running process, kill it and %s?", m_new_process_action.c_str()); 68254721Semaste 69254721Semaste if (!m_interpreter.Confirm (message, true)) 70254721Semaste { 71254721Semaste result.SetStatus (eReturnStatusFailed); 72254721Semaste return false; 73254721Semaste } 74254721Semaste else 75254721Semaste { 76254721Semaste if (process->GetShouldDetach()) 77254721Semaste { 78254721Semaste bool keep_stopped = false; 79254721Semaste Error detach_error (process->Detach(keep_stopped)); 80254721Semaste if (detach_error.Success()) 81254721Semaste { 82254721Semaste result.SetStatus (eReturnStatusSuccessFinishResult); 83254721Semaste process = NULL; 84254721Semaste } 85254721Semaste else 86254721Semaste { 87254721Semaste result.AppendErrorWithFormat ("Failed to detach from process: %s\n", detach_error.AsCString()); 88254721Semaste result.SetStatus (eReturnStatusFailed); 89254721Semaste } 90254721Semaste } 91254721Semaste else 92254721Semaste { 93254721Semaste Error destroy_error (process->Destroy()); 94254721Semaste if (destroy_error.Success()) 95254721Semaste { 96254721Semaste result.SetStatus (eReturnStatusSuccessFinishResult); 97254721Semaste process = NULL; 98254721Semaste } 99254721Semaste else 100254721Semaste { 101254721Semaste result.AppendErrorWithFormat ("Failed to kill process: %s\n", destroy_error.AsCString()); 102254721Semaste result.SetStatus (eReturnStatusFailed); 103254721Semaste } 104254721Semaste } 105254721Semaste } 106254721Semaste } 107254721Semaste } 108254721Semaste return result.Succeeded(); 109254721Semaste } 110254721Semaste std::string m_new_process_action; 111254721Semaste}; 112254721Semaste//------------------------------------------------------------------------- 113254721Semaste// CommandObjectProcessLaunch 114254721Semaste//------------------------------------------------------------------------- 115254721Semaste#pragma mark CommandObjectProcessLaunch 116254721Semasteclass CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach 117254721Semaste{ 118254721Semastepublic: 119254721Semaste 120254721Semaste CommandObjectProcessLaunch (CommandInterpreter &interpreter) : 121254721Semaste CommandObjectProcessLaunchOrAttach (interpreter, 122254721Semaste "process launch", 123254721Semaste "Launch the executable in the debugger.", 124254721Semaste NULL, 125254721Semaste eFlagRequiresTarget, 126254721Semaste "restart"), 127254721Semaste m_options (interpreter) 128254721Semaste { 129254721Semaste CommandArgumentEntry arg; 130254721Semaste CommandArgumentData run_args_arg; 131254721Semaste 132254721Semaste // Define the first (and only) variant of this arg. 133254721Semaste run_args_arg.arg_type = eArgTypeRunArgs; 134254721Semaste run_args_arg.arg_repetition = eArgRepeatOptional; 135254721Semaste 136254721Semaste // There is only one variant this argument could be; put it into the argument entry. 137254721Semaste arg.push_back (run_args_arg); 138254721Semaste 139254721Semaste // Push the data for the first argument into the m_arguments vector. 140254721Semaste m_arguments.push_back (arg); 141254721Semaste } 142254721Semaste 143254721Semaste 144254721Semaste ~CommandObjectProcessLaunch () 145254721Semaste { 146254721Semaste } 147254721Semaste 148254721Semaste virtual int 149254721Semaste HandleArgumentCompletion (Args &input, 150254721Semaste int &cursor_index, 151254721Semaste int &cursor_char_position, 152254721Semaste OptionElementVector &opt_element_vector, 153254721Semaste int match_start_point, 154254721Semaste int max_return_elements, 155254721Semaste bool &word_complete, 156254721Semaste StringList &matches) 157254721Semaste { 158254721Semaste std::string completion_str (input.GetArgumentAtIndex(cursor_index)); 159254721Semaste completion_str.erase (cursor_char_position); 160254721Semaste 161254721Semaste CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter, 162254721Semaste CommandCompletions::eDiskFileCompletion, 163254721Semaste completion_str.c_str(), 164254721Semaste match_start_point, 165254721Semaste max_return_elements, 166254721Semaste NULL, 167254721Semaste word_complete, 168254721Semaste matches); 169254721Semaste return matches.GetSize(); 170254721Semaste } 171254721Semaste 172254721Semaste Options * 173254721Semaste GetOptions () 174254721Semaste { 175254721Semaste return &m_options; 176254721Semaste } 177254721Semaste 178254721Semaste virtual const char *GetRepeatCommand (Args ¤t_command_args, uint32_t index) 179254721Semaste { 180254721Semaste // No repeat for "process launch"... 181254721Semaste return ""; 182254721Semaste } 183254721Semaste 184254721Semasteprotected: 185254721Semaste bool 186254721Semaste DoExecute (Args& launch_args, CommandReturnObject &result) 187254721Semaste { 188254721Semaste Debugger &debugger = m_interpreter.GetDebugger(); 189254721Semaste Target *target = debugger.GetSelectedTarget().get(); 190254721Semaste // If our listener is NULL, users aren't allows to launch 191269024Semaste ModuleSP exe_module_sp = target->GetExecutableModule(); 192254721Semaste 193269024Semaste if (exe_module_sp == NULL) 194254721Semaste { 195254721Semaste result.AppendError ("no file in target, create a debug target using the 'target create' command"); 196254721Semaste result.SetStatus (eReturnStatusFailed); 197254721Semaste return false; 198254721Semaste } 199254721Semaste 200254721Semaste StateType state = eStateInvalid; 201254721Semaste 202269024Semaste if (!StopProcessIfNecessary(m_exe_ctx.GetProcessPtr(), state, result)) 203254721Semaste return false; 204254721Semaste 205254721Semaste const char *target_settings_argv0 = target->GetArg0(); 206254721Semaste 207269024Semaste if (target->GetDisableASLR()) 208269024Semaste m_options.launch_info.GetFlags().Set (eLaunchFlagDisableASLR); 209254721Semaste 210269024Semaste if (target->GetDisableSTDIO()) 211269024Semaste m_options.launch_info.GetFlags().Set (eLaunchFlagDisableSTDIO); 212269024Semaste 213269024Semaste Args environment; 214269024Semaste target->GetEnvironmentAsArgs (environment); 215269024Semaste if (environment.GetArgumentCount() > 0) 216269024Semaste m_options.launch_info.GetEnvironmentEntries ().AppendArguments (environment); 217269024Semaste 218254721Semaste if (target_settings_argv0) 219254721Semaste { 220254721Semaste m_options.launch_info.GetArguments().AppendArgument (target_settings_argv0); 221269024Semaste m_options.launch_info.SetExecutableFile(exe_module_sp->GetPlatformFileSpec(), false); 222254721Semaste } 223254721Semaste else 224254721Semaste { 225269024Semaste m_options.launch_info.SetExecutableFile(exe_module_sp->GetPlatformFileSpec(), true); 226254721Semaste } 227254721Semaste 228254721Semaste if (launch_args.GetArgumentCount() == 0) 229254721Semaste { 230254721Semaste Args target_setting_args; 231254721Semaste if (target->GetRunArguments(target_setting_args)) 232254721Semaste m_options.launch_info.GetArguments().AppendArguments (target_setting_args); 233254721Semaste } 234254721Semaste else 235254721Semaste { 236254721Semaste m_options.launch_info.GetArguments().AppendArguments (launch_args); 237254721Semaste // Save the arguments for subsequent runs in the current target. 238254721Semaste target->SetRunArguments (launch_args); 239254721Semaste } 240254721Semaste 241269024Semaste Error error = target->Launch(debugger.GetListener(), m_options.launch_info); 242254721Semaste 243254721Semaste if (error.Success()) 244254721Semaste { 245269024Semaste const char *archname = exe_module_sp->GetArchitecture().GetArchitectureName(); 246269024Semaste ProcessSP process_sp (target->GetProcessSP()); 247269024Semaste if (process_sp) 248254721Semaste { 249269024Semaste result.AppendMessageWithFormat ("Process %" PRIu64 " launched: '%s' (%s)\n", process_sp->GetID(), exe_module_sp->GetFileSpec().GetPath().c_str(), archname); 250269024Semaste result.SetStatus (eReturnStatusSuccessFinishResult); 251269024Semaste result.SetDidChangeProcessState (true); 252254721Semaste } 253269024Semaste else 254269024Semaste { 255269024Semaste result.AppendError("no error returned from Target::Launch, and target has no process"); 256269024Semaste result.SetStatus (eReturnStatusFailed); 257269024Semaste } 258254721Semaste } 259254721Semaste else 260254721Semaste { 261269024Semaste result.AppendError(error.AsCString()); 262254721Semaste result.SetStatus (eReturnStatusFailed); 263254721Semaste } 264254721Semaste return result.Succeeded(); 265254721Semaste } 266254721Semaste 267254721Semasteprotected: 268254721Semaste ProcessLaunchCommandOptions m_options; 269254721Semaste}; 270254721Semaste 271254721Semaste 272254721Semaste//#define SET1 LLDB_OPT_SET_1 273254721Semaste//#define SET2 LLDB_OPT_SET_2 274254721Semaste//#define SET3 LLDB_OPT_SET_3 275254721Semaste// 276254721Semaste//OptionDefinition 277254721Semaste//CommandObjectProcessLaunch::CommandOptions::g_option_table[] = 278254721Semaste//{ 279263363Semaste//{ SET1 | SET2 | SET3, false, "stop-at-entry", 's', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Stop at the entry point of the program when launching a process."}, 280263363Semaste//{ SET1 , false, "stdin", 'i', OptionParser::eRequiredArgument, NULL, 0, eArgTypeDirectoryName, "Redirect stdin for the process to <path>."}, 281263363Semaste//{ SET1 , false, "stdout", 'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypeDirectoryName, "Redirect stdout for the process to <path>."}, 282263363Semaste//{ SET1 , false, "stderr", 'e', OptionParser::eRequiredArgument, NULL, 0, eArgTypeDirectoryName, "Redirect stderr for the process to <path>."}, 283263363Semaste//{ SET1 | SET2 | SET3, false, "plugin", 'p', OptionParser::eRequiredArgument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."}, 284263363Semaste//{ SET2 , false, "tty", 't', OptionParser::eOptionalArgument, NULL, 0, eArgTypeDirectoryName, "Start the process in a terminal. If <path> is specified, look for a terminal whose name contains <path>, else start the process in a new terminal."}, 285263363Semaste//{ SET3, false, "no-stdio", 'n', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Do not set up for terminal I/O to go to running process."}, 286263363Semaste//{ SET1 | SET2 | SET3, false, "working-dir", 'w', OptionParser::eRequiredArgument, NULL, 0, eArgTypeDirectoryName, "Set the current working directory to <path> when running the inferior."}, 287254721Semaste//{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 288254721Semaste//}; 289254721Semaste// 290254721Semaste//#undef SET1 291254721Semaste//#undef SET2 292254721Semaste//#undef SET3 293254721Semaste 294254721Semaste//------------------------------------------------------------------------- 295254721Semaste// CommandObjectProcessAttach 296254721Semaste//------------------------------------------------------------------------- 297254721Semaste#pragma mark CommandObjectProcessAttach 298254721Semasteclass CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach 299254721Semaste{ 300254721Semastepublic: 301254721Semaste 302254721Semaste class CommandOptions : public Options 303254721Semaste { 304254721Semaste public: 305254721Semaste 306254721Semaste CommandOptions (CommandInterpreter &interpreter) : 307254721Semaste Options(interpreter) 308254721Semaste { 309254721Semaste // Keep default values of all options in one place: OptionParsingStarting () 310254721Semaste OptionParsingStarting (); 311254721Semaste } 312254721Semaste 313254721Semaste ~CommandOptions () 314254721Semaste { 315254721Semaste } 316254721Semaste 317254721Semaste Error 318254721Semaste SetOptionValue (uint32_t option_idx, const char *option_arg) 319254721Semaste { 320254721Semaste Error error; 321254721Semaste const int short_option = m_getopt_table[option_idx].val; 322254721Semaste bool success = false; 323254721Semaste switch (short_option) 324254721Semaste { 325254721Semaste case 'c': 326254721Semaste attach_info.SetContinueOnceAttached(true); 327254721Semaste break; 328254721Semaste 329254721Semaste case 'p': 330254721Semaste { 331254721Semaste lldb::pid_t pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success); 332254721Semaste if (!success || pid == LLDB_INVALID_PROCESS_ID) 333254721Semaste { 334254721Semaste error.SetErrorStringWithFormat("invalid process ID '%s'", option_arg); 335254721Semaste } 336254721Semaste else 337254721Semaste { 338254721Semaste attach_info.SetProcessID (pid); 339254721Semaste } 340254721Semaste } 341254721Semaste break; 342254721Semaste 343254721Semaste case 'P': 344254721Semaste attach_info.SetProcessPluginName (option_arg); 345254721Semaste break; 346254721Semaste 347254721Semaste case 'n': 348254721Semaste attach_info.GetExecutableFile().SetFile(option_arg, false); 349254721Semaste break; 350254721Semaste 351254721Semaste case 'w': 352254721Semaste attach_info.SetWaitForLaunch(true); 353254721Semaste break; 354254721Semaste 355254721Semaste case 'i': 356254721Semaste attach_info.SetIgnoreExisting(false); 357254721Semaste break; 358254721Semaste 359254721Semaste default: 360254721Semaste error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 361254721Semaste break; 362254721Semaste } 363254721Semaste return error; 364254721Semaste } 365254721Semaste 366254721Semaste void 367254721Semaste OptionParsingStarting () 368254721Semaste { 369254721Semaste attach_info.Clear(); 370254721Semaste } 371254721Semaste 372254721Semaste const OptionDefinition* 373254721Semaste GetDefinitions () 374254721Semaste { 375254721Semaste return g_option_table; 376254721Semaste } 377254721Semaste 378254721Semaste virtual bool 379254721Semaste HandleOptionArgumentCompletion (Args &input, 380254721Semaste int cursor_index, 381254721Semaste int char_pos, 382254721Semaste OptionElementVector &opt_element_vector, 383254721Semaste int opt_element_index, 384254721Semaste int match_start_point, 385254721Semaste int max_return_elements, 386254721Semaste bool &word_complete, 387254721Semaste StringList &matches) 388254721Semaste { 389254721Semaste int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos; 390254721Semaste int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index; 391254721Semaste 392254721Semaste // We are only completing the name option for now... 393254721Semaste 394254721Semaste const OptionDefinition *opt_defs = GetDefinitions(); 395254721Semaste if (opt_defs[opt_defs_index].short_option == 'n') 396254721Semaste { 397254721Semaste // Are we in the name? 398254721Semaste 399254721Semaste // Look to see if there is a -P argument provided, and if so use that plugin, otherwise 400254721Semaste // use the default plugin. 401254721Semaste 402254721Semaste const char *partial_name = NULL; 403254721Semaste partial_name = input.GetArgumentAtIndex(opt_arg_pos); 404254721Semaste 405254721Semaste PlatformSP platform_sp (m_interpreter.GetPlatform (true)); 406254721Semaste if (platform_sp) 407254721Semaste { 408254721Semaste ProcessInstanceInfoList process_infos; 409254721Semaste ProcessInstanceInfoMatch match_info; 410254721Semaste if (partial_name) 411254721Semaste { 412254721Semaste match_info.GetProcessInfo().GetExecutableFile().SetFile(partial_name, false); 413254721Semaste match_info.SetNameMatchType(eNameMatchStartsWith); 414254721Semaste } 415254721Semaste platform_sp->FindProcesses (match_info, process_infos); 416254721Semaste const size_t num_matches = process_infos.GetSize(); 417254721Semaste if (num_matches > 0) 418254721Semaste { 419254721Semaste for (size_t i=0; i<num_matches; ++i) 420254721Semaste { 421254721Semaste matches.AppendString (process_infos.GetProcessNameAtIndex(i), 422254721Semaste process_infos.GetProcessNameLengthAtIndex(i)); 423254721Semaste } 424254721Semaste } 425254721Semaste } 426254721Semaste } 427254721Semaste 428254721Semaste return false; 429254721Semaste } 430254721Semaste 431254721Semaste // Options table: Required for subclasses of Options. 432254721Semaste 433254721Semaste static OptionDefinition g_option_table[]; 434254721Semaste 435254721Semaste // Instance variables to hold the values for command options. 436254721Semaste 437254721Semaste ProcessAttachInfo attach_info; 438254721Semaste }; 439254721Semaste 440254721Semaste CommandObjectProcessAttach (CommandInterpreter &interpreter) : 441254721Semaste CommandObjectProcessLaunchOrAttach (interpreter, 442254721Semaste "process attach", 443254721Semaste "Attach to a process.", 444254721Semaste "process attach <cmd-options>", 445254721Semaste 0, 446254721Semaste "attach"), 447254721Semaste m_options (interpreter) 448254721Semaste { 449254721Semaste } 450254721Semaste 451254721Semaste ~CommandObjectProcessAttach () 452254721Semaste { 453254721Semaste } 454254721Semaste 455254721Semaste Options * 456254721Semaste GetOptions () 457254721Semaste { 458254721Semaste return &m_options; 459254721Semaste } 460254721Semaste 461254721Semasteprotected: 462254721Semaste bool 463254721Semaste DoExecute (Args& command, 464254721Semaste CommandReturnObject &result) 465254721Semaste { 466254721Semaste Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 467254721Semaste // N.B. The attach should be synchronous. It doesn't help much to get the prompt back between initiating the attach 468254721Semaste // and the target actually stopping. So even if the interpreter is set to be asynchronous, we wait for the stop 469254721Semaste // ourselves here. 470254721Semaste 471254721Semaste StateType state = eStateInvalid; 472254721Semaste Process *process = m_exe_ctx.GetProcessPtr(); 473254721Semaste 474254721Semaste if (!StopProcessIfNecessary (process, state, result)) 475254721Semaste return false; 476254721Semaste 477254721Semaste if (target == NULL) 478254721Semaste { 479254721Semaste // If there isn't a current target create one. 480254721Semaste TargetSP new_target_sp; 481254721Semaste Error error; 482254721Semaste 483254721Semaste error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(), 484254721Semaste NULL, 485254721Semaste NULL, 486254721Semaste false, 487254721Semaste NULL, // No platform options 488254721Semaste new_target_sp); 489254721Semaste target = new_target_sp.get(); 490254721Semaste if (target == NULL || error.Fail()) 491254721Semaste { 492254721Semaste result.AppendError(error.AsCString("Error creating target")); 493254721Semaste return false; 494254721Semaste } 495254721Semaste m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target); 496254721Semaste } 497254721Semaste 498254721Semaste // Record the old executable module, we want to issue a warning if the process of attaching changed the 499254721Semaste // current executable (like somebody said "file foo" then attached to a PID whose executable was bar.) 500254721Semaste 501254721Semaste ModuleSP old_exec_module_sp = target->GetExecutableModule(); 502254721Semaste ArchSpec old_arch_spec = target->GetArchitecture(); 503254721Semaste 504254721Semaste if (command.GetArgumentCount()) 505254721Semaste { 506254721Semaste result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: %s\n", m_cmd_name.c_str(), m_cmd_syntax.c_str()); 507254721Semaste result.SetStatus (eReturnStatusFailed); 508254721Semaste } 509254721Semaste else 510254721Semaste { 511254721Semaste if (state != eStateConnected) 512254721Semaste { 513254721Semaste const char *plugin_name = m_options.attach_info.GetProcessPluginName(); 514254721Semaste process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name, NULL).get(); 515254721Semaste } 516254721Semaste 517254721Semaste if (process) 518254721Semaste { 519254721Semaste Error error; 520254721Semaste // If no process info was specified, then use the target executable 521254721Semaste // name as the process to attach to by default 522254721Semaste if (!m_options.attach_info.ProcessInfoSpecified ()) 523254721Semaste { 524254721Semaste if (old_exec_module_sp) 525254721Semaste m_options.attach_info.GetExecutableFile().GetFilename() = old_exec_module_sp->GetPlatformFileSpec().GetFilename(); 526254721Semaste 527254721Semaste if (!m_options.attach_info.ProcessInfoSpecified ()) 528254721Semaste { 529254721Semaste error.SetErrorString ("no process specified, create a target with a file, or specify the --pid or --name command option"); 530254721Semaste } 531254721Semaste } 532254721Semaste 533254721Semaste if (error.Success()) 534254721Semaste { 535269024Semaste ListenerSP listener_sp (new Listener("lldb.CommandObjectProcessAttach.DoExecute.attach.hijack")); 536269024Semaste m_options.attach_info.SetHijackListener(listener_sp); 537269024Semaste process->HijackProcessEvents(listener_sp.get()); 538254721Semaste error = process->Attach (m_options.attach_info); 539254721Semaste 540254721Semaste if (error.Success()) 541254721Semaste { 542254721Semaste result.SetStatus (eReturnStatusSuccessContinuingNoResult); 543269024Semaste StateType state = process->WaitForProcessToStop (NULL, NULL, false, listener_sp.get()); 544269024Semaste 545269024Semaste process->RestoreProcessEvents(); 546269024Semaste 547269024Semaste result.SetDidChangeProcessState (true); 548269024Semaste 549269024Semaste if (state == eStateStopped) 550269024Semaste { 551269024Semaste result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state)); 552269024Semaste result.SetStatus (eReturnStatusSuccessFinishNoResult); 553269024Semaste } 554269024Semaste else 555269024Semaste { 556269024Semaste result.AppendError ("attach failed: process did not stop (no such process or permission problem?)"); 557269024Semaste process->Destroy(); 558269024Semaste result.SetStatus (eReturnStatusFailed); 559269024Semaste } 560254721Semaste } 561254721Semaste else 562254721Semaste { 563254721Semaste result.AppendErrorWithFormat ("attach failed: %s\n", error.AsCString()); 564254721Semaste result.SetStatus (eReturnStatusFailed); 565254721Semaste } 566254721Semaste } 567254721Semaste } 568254721Semaste } 569254721Semaste 570254721Semaste if (result.Succeeded()) 571254721Semaste { 572254721Semaste // Okay, we're done. Last step is to warn if the executable module has changed: 573254721Semaste char new_path[PATH_MAX]; 574254721Semaste ModuleSP new_exec_module_sp (target->GetExecutableModule()); 575254721Semaste if (!old_exec_module_sp) 576254721Semaste { 577254721Semaste // We might not have a module if we attached to a raw pid... 578254721Semaste if (new_exec_module_sp) 579254721Semaste { 580254721Semaste new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX); 581254721Semaste result.AppendMessageWithFormat("Executable module set to \"%s\".\n", new_path); 582254721Semaste } 583254721Semaste } 584254721Semaste else if (old_exec_module_sp->GetFileSpec() != new_exec_module_sp->GetFileSpec()) 585254721Semaste { 586254721Semaste char old_path[PATH_MAX]; 587254721Semaste 588254721Semaste old_exec_module_sp->GetFileSpec().GetPath (old_path, PATH_MAX); 589254721Semaste new_exec_module_sp->GetFileSpec().GetPath (new_path, PATH_MAX); 590254721Semaste 591254721Semaste result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n", 592254721Semaste old_path, new_path); 593254721Semaste } 594254721Semaste 595254721Semaste if (!old_arch_spec.IsValid()) 596254721Semaste { 597254721Semaste result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().GetTriple().getTriple().c_str()); 598254721Semaste } 599254721Semaste else if (!old_arch_spec.IsExactMatch(target->GetArchitecture())) 600254721Semaste { 601254721Semaste result.AppendWarningWithFormat("Architecture changed from %s to %s.\n", 602254721Semaste old_arch_spec.GetTriple().getTriple().c_str(), 603254721Semaste target->GetArchitecture().GetTriple().getTriple().c_str()); 604254721Semaste } 605254721Semaste 606254721Semaste // This supports the use-case scenario of immediately continuing the process once attached. 607254721Semaste if (m_options.attach_info.GetContinueOnceAttached()) 608254721Semaste m_interpreter.HandleCommand("process continue", eLazyBoolNo, result); 609254721Semaste } 610254721Semaste return result.Succeeded(); 611254721Semaste } 612254721Semaste 613254721Semaste CommandOptions m_options; 614254721Semaste}; 615254721Semaste 616254721Semaste 617254721SemasteOptionDefinition 618254721SemasteCommandObjectProcessAttach::CommandOptions::g_option_table[] = 619254721Semaste{ 620263363Semaste{ LLDB_OPT_SET_ALL, false, "continue",'c', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Immediately continue the process once attached."}, 621263363Semaste{ LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."}, 622263363Semaste{ LLDB_OPT_SET_1, false, "pid", 'p', OptionParser::eRequiredArgument, NULL, 0, eArgTypePid, "The process ID of an existing process to attach to."}, 623263363Semaste{ LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, NULL, 0, eArgTypeProcessName, "The name of the process to attach to."}, 624263363Semaste{ LLDB_OPT_SET_2, false, "include-existing", 'i', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Include existing processes when doing attach -w."}, 625263363Semaste{ LLDB_OPT_SET_2, false, "waitfor", 'w', OptionParser::eNoArgument, NULL, 0, eArgTypeNone, "Wait for the process with <process-name> to launch."}, 626254721Semaste{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 627254721Semaste}; 628254721Semaste 629254721Semaste//------------------------------------------------------------------------- 630254721Semaste// CommandObjectProcessContinue 631254721Semaste//------------------------------------------------------------------------- 632254721Semaste#pragma mark CommandObjectProcessContinue 633254721Semaste 634254721Semasteclass CommandObjectProcessContinue : public CommandObjectParsed 635254721Semaste{ 636254721Semastepublic: 637254721Semaste 638254721Semaste CommandObjectProcessContinue (CommandInterpreter &interpreter) : 639254721Semaste CommandObjectParsed (interpreter, 640254721Semaste "process continue", 641254721Semaste "Continue execution of all threads in the current process.", 642254721Semaste "process continue", 643254721Semaste eFlagRequiresProcess | 644254721Semaste eFlagTryTargetAPILock | 645254721Semaste eFlagProcessMustBeLaunched | 646254721Semaste eFlagProcessMustBePaused ), 647254721Semaste m_options(interpreter) 648254721Semaste { 649254721Semaste } 650254721Semaste 651254721Semaste 652254721Semaste ~CommandObjectProcessContinue () 653254721Semaste { 654254721Semaste } 655254721Semaste 656254721Semasteprotected: 657254721Semaste 658254721Semaste class CommandOptions : public Options 659254721Semaste { 660254721Semaste public: 661254721Semaste 662254721Semaste CommandOptions (CommandInterpreter &interpreter) : 663254721Semaste Options(interpreter) 664254721Semaste { 665254721Semaste // Keep default values of all options in one place: OptionParsingStarting () 666254721Semaste OptionParsingStarting (); 667254721Semaste } 668254721Semaste 669254721Semaste ~CommandOptions () 670254721Semaste { 671254721Semaste } 672254721Semaste 673254721Semaste Error 674254721Semaste SetOptionValue (uint32_t option_idx, const char *option_arg) 675254721Semaste { 676254721Semaste Error error; 677254721Semaste const int short_option = m_getopt_table[option_idx].val; 678254721Semaste bool success = false; 679254721Semaste switch (short_option) 680254721Semaste { 681254721Semaste case 'i': 682254721Semaste m_ignore = Args::StringToUInt32 (option_arg, 0, 0, &success); 683254721Semaste if (!success) 684254721Semaste error.SetErrorStringWithFormat ("invalid value for ignore option: \"%s\", should be a number.", option_arg); 685254721Semaste break; 686254721Semaste 687254721Semaste default: 688254721Semaste error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 689254721Semaste break; 690254721Semaste } 691254721Semaste return error; 692254721Semaste } 693254721Semaste 694254721Semaste void 695254721Semaste OptionParsingStarting () 696254721Semaste { 697254721Semaste m_ignore = 0; 698254721Semaste } 699254721Semaste 700254721Semaste const OptionDefinition* 701254721Semaste GetDefinitions () 702254721Semaste { 703254721Semaste return g_option_table; 704254721Semaste } 705254721Semaste 706254721Semaste // Options table: Required for subclasses of Options. 707254721Semaste 708254721Semaste static OptionDefinition g_option_table[]; 709254721Semaste 710254721Semaste uint32_t m_ignore; 711254721Semaste }; 712254721Semaste 713254721Semaste bool 714254721Semaste DoExecute (Args& command, CommandReturnObject &result) 715254721Semaste { 716254721Semaste Process *process = m_exe_ctx.GetProcessPtr(); 717254721Semaste bool synchronous_execution = m_interpreter.GetSynchronous (); 718254721Semaste StateType state = process->GetState(); 719254721Semaste if (state == eStateStopped) 720254721Semaste { 721254721Semaste if (command.GetArgumentCount() != 0) 722254721Semaste { 723254721Semaste result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str()); 724254721Semaste result.SetStatus (eReturnStatusFailed); 725254721Semaste return false; 726254721Semaste } 727254721Semaste 728254721Semaste if (m_options.m_ignore > 0) 729254721Semaste { 730254721Semaste ThreadSP sel_thread_sp(process->GetThreadList().GetSelectedThread()); 731254721Semaste if (sel_thread_sp) 732254721Semaste { 733254721Semaste StopInfoSP stop_info_sp = sel_thread_sp->GetStopInfo(); 734254721Semaste if (stop_info_sp && stop_info_sp->GetStopReason() == eStopReasonBreakpoint) 735254721Semaste { 736254721Semaste lldb::break_id_t bp_site_id = (lldb::break_id_t)stop_info_sp->GetValue(); 737254721Semaste BreakpointSiteSP bp_site_sp(process->GetBreakpointSiteList().FindByID(bp_site_id)); 738254721Semaste if (bp_site_sp) 739254721Semaste { 740254721Semaste const size_t num_owners = bp_site_sp->GetNumberOfOwners(); 741254721Semaste for (size_t i = 0; i < num_owners; i++) 742254721Semaste { 743254721Semaste Breakpoint &bp_ref = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint(); 744254721Semaste if (!bp_ref.IsInternal()) 745254721Semaste { 746254721Semaste bp_ref.SetIgnoreCount(m_options.m_ignore); 747254721Semaste } 748254721Semaste } 749254721Semaste } 750254721Semaste } 751254721Semaste } 752254721Semaste } 753254721Semaste 754254721Semaste { // Scope for thread list mutex: 755254721Semaste Mutex::Locker locker (process->GetThreadList().GetMutex()); 756254721Semaste const uint32_t num_threads = process->GetThreadList().GetSize(); 757254721Semaste 758254721Semaste // Set the actions that the threads should each take when resuming 759254721Semaste for (uint32_t idx=0; idx<num_threads; ++idx) 760254721Semaste { 761254721Semaste process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning); 762254721Semaste } 763254721Semaste } 764254721Semaste 765254721Semaste Error error(process->Resume()); 766254721Semaste if (error.Success()) 767254721Semaste { 768254721Semaste result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID()); 769254721Semaste if (synchronous_execution) 770254721Semaste { 771254721Semaste state = process->WaitForProcessToStop (NULL); 772254721Semaste 773254721Semaste result.SetDidChangeProcessState (true); 774254721Semaste result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state)); 775254721Semaste result.SetStatus (eReturnStatusSuccessFinishNoResult); 776254721Semaste } 777254721Semaste else 778254721Semaste { 779254721Semaste result.SetStatus (eReturnStatusSuccessContinuingNoResult); 780254721Semaste } 781254721Semaste } 782254721Semaste else 783254721Semaste { 784254721Semaste result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString()); 785254721Semaste result.SetStatus (eReturnStatusFailed); 786254721Semaste } 787254721Semaste } 788254721Semaste else 789254721Semaste { 790254721Semaste result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n", 791254721Semaste StateAsCString(state)); 792254721Semaste result.SetStatus (eReturnStatusFailed); 793254721Semaste } 794254721Semaste return result.Succeeded(); 795254721Semaste } 796254721Semaste 797254721Semaste Options * 798254721Semaste GetOptions () 799254721Semaste { 800254721Semaste return &m_options; 801254721Semaste } 802254721Semaste 803254721Semaste CommandOptions m_options; 804254721Semaste 805254721Semaste}; 806254721Semaste 807254721SemasteOptionDefinition 808254721SemasteCommandObjectProcessContinue::CommandOptions::g_option_table[] = 809254721Semaste{ 810263363Semaste{ LLDB_OPT_SET_ALL, false, "ignore-count",'i', OptionParser::eRequiredArgument, NULL, 0, eArgTypeUnsignedInteger, 811254721Semaste "Ignore <N> crossings of the breakpoint (if it exists) for the currently selected thread."}, 812254721Semaste{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 813254721Semaste}; 814254721Semaste 815254721Semaste//------------------------------------------------------------------------- 816254721Semaste// CommandObjectProcessDetach 817254721Semaste//------------------------------------------------------------------------- 818254721Semaste#pragma mark CommandObjectProcessDetach 819254721Semaste 820254721Semasteclass CommandObjectProcessDetach : public CommandObjectParsed 821254721Semaste{ 822254721Semastepublic: 823254721Semaste class CommandOptions : public Options 824254721Semaste { 825254721Semaste public: 826254721Semaste 827254721Semaste CommandOptions (CommandInterpreter &interpreter) : 828254721Semaste Options (interpreter) 829254721Semaste { 830254721Semaste OptionParsingStarting (); 831254721Semaste } 832254721Semaste 833254721Semaste ~CommandOptions () 834254721Semaste { 835254721Semaste } 836254721Semaste 837254721Semaste Error 838254721Semaste SetOptionValue (uint32_t option_idx, const char *option_arg) 839254721Semaste { 840254721Semaste Error error; 841254721Semaste const int short_option = m_getopt_table[option_idx].val; 842254721Semaste 843254721Semaste switch (short_option) 844254721Semaste { 845254721Semaste case 's': 846254721Semaste bool tmp_result; 847254721Semaste bool success; 848254721Semaste tmp_result = Args::StringToBoolean(option_arg, false, &success); 849254721Semaste if (!success) 850254721Semaste error.SetErrorStringWithFormat("invalid boolean option: \"%s\"", option_arg); 851254721Semaste else 852254721Semaste { 853254721Semaste if (tmp_result) 854254721Semaste m_keep_stopped = eLazyBoolYes; 855254721Semaste else 856254721Semaste m_keep_stopped = eLazyBoolNo; 857254721Semaste } 858254721Semaste break; 859254721Semaste default: 860254721Semaste error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 861254721Semaste break; 862254721Semaste } 863254721Semaste return error; 864254721Semaste } 865254721Semaste 866254721Semaste void 867254721Semaste OptionParsingStarting () 868254721Semaste { 869254721Semaste m_keep_stopped = eLazyBoolCalculate; 870254721Semaste } 871254721Semaste 872254721Semaste const OptionDefinition* 873254721Semaste GetDefinitions () 874254721Semaste { 875254721Semaste return g_option_table; 876254721Semaste } 877254721Semaste 878254721Semaste // Options table: Required for subclasses of Options. 879254721Semaste 880254721Semaste static OptionDefinition g_option_table[]; 881254721Semaste 882254721Semaste // Instance variables to hold the values for command options. 883254721Semaste LazyBool m_keep_stopped; 884254721Semaste }; 885254721Semaste 886254721Semaste CommandObjectProcessDetach (CommandInterpreter &interpreter) : 887254721Semaste CommandObjectParsed (interpreter, 888254721Semaste "process detach", 889254721Semaste "Detach from the current process being debugged.", 890254721Semaste "process detach", 891254721Semaste eFlagRequiresProcess | 892254721Semaste eFlagTryTargetAPILock | 893254721Semaste eFlagProcessMustBeLaunched), 894254721Semaste m_options(interpreter) 895254721Semaste { 896254721Semaste } 897254721Semaste 898254721Semaste ~CommandObjectProcessDetach () 899254721Semaste { 900254721Semaste } 901254721Semaste 902254721Semaste Options * 903254721Semaste GetOptions () 904254721Semaste { 905254721Semaste return &m_options; 906254721Semaste } 907254721Semaste 908254721Semaste 909254721Semasteprotected: 910254721Semaste bool 911254721Semaste DoExecute (Args& command, CommandReturnObject &result) 912254721Semaste { 913254721Semaste Process *process = m_exe_ctx.GetProcessPtr(); 914254721Semaste result.AppendMessageWithFormat ("Detaching from process %" PRIu64 "\n", process->GetID()); 915254721Semaste // FIXME: This will be a Command Option: 916254721Semaste bool keep_stopped; 917254721Semaste if (m_options.m_keep_stopped == eLazyBoolCalculate) 918254721Semaste { 919254721Semaste // Check the process default: 920254721Semaste if (process->GetDetachKeepsStopped()) 921254721Semaste keep_stopped = true; 922254721Semaste else 923254721Semaste keep_stopped = false; 924254721Semaste } 925254721Semaste else if (m_options.m_keep_stopped == eLazyBoolYes) 926254721Semaste keep_stopped = true; 927254721Semaste else 928254721Semaste keep_stopped = false; 929254721Semaste 930254721Semaste Error error (process->Detach(keep_stopped)); 931254721Semaste if (error.Success()) 932254721Semaste { 933254721Semaste result.SetStatus (eReturnStatusSuccessFinishResult); 934254721Semaste } 935254721Semaste else 936254721Semaste { 937254721Semaste result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString()); 938254721Semaste result.SetStatus (eReturnStatusFailed); 939254721Semaste return false; 940254721Semaste } 941254721Semaste return result.Succeeded(); 942254721Semaste } 943254721Semaste 944254721Semaste CommandOptions m_options; 945254721Semaste}; 946254721Semaste 947254721SemasteOptionDefinition 948254721SemasteCommandObjectProcessDetach::CommandOptions::g_option_table[] = 949254721Semaste{ 950263363Semaste{ LLDB_OPT_SET_1, false, "keep-stopped", 's', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "Whether or not the process should be kept stopped on detach (if possible)." }, 951254721Semaste{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 952254721Semaste}; 953254721Semaste 954254721Semaste//------------------------------------------------------------------------- 955254721Semaste// CommandObjectProcessConnect 956254721Semaste//------------------------------------------------------------------------- 957254721Semaste#pragma mark CommandObjectProcessConnect 958254721Semaste 959254721Semasteclass CommandObjectProcessConnect : public CommandObjectParsed 960254721Semaste{ 961254721Semastepublic: 962254721Semaste 963254721Semaste class CommandOptions : public Options 964254721Semaste { 965254721Semaste public: 966254721Semaste 967254721Semaste CommandOptions (CommandInterpreter &interpreter) : 968254721Semaste Options(interpreter) 969254721Semaste { 970254721Semaste // Keep default values of all options in one place: OptionParsingStarting () 971254721Semaste OptionParsingStarting (); 972254721Semaste } 973254721Semaste 974254721Semaste ~CommandOptions () 975254721Semaste { 976254721Semaste } 977254721Semaste 978254721Semaste Error 979254721Semaste SetOptionValue (uint32_t option_idx, const char *option_arg) 980254721Semaste { 981254721Semaste Error error; 982254721Semaste const int short_option = m_getopt_table[option_idx].val; 983254721Semaste 984254721Semaste switch (short_option) 985254721Semaste { 986254721Semaste case 'p': 987254721Semaste plugin_name.assign (option_arg); 988254721Semaste break; 989254721Semaste 990254721Semaste default: 991254721Semaste error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 992254721Semaste break; 993254721Semaste } 994254721Semaste return error; 995254721Semaste } 996254721Semaste 997254721Semaste void 998254721Semaste OptionParsingStarting () 999254721Semaste { 1000254721Semaste plugin_name.clear(); 1001254721Semaste } 1002254721Semaste 1003254721Semaste const OptionDefinition* 1004254721Semaste GetDefinitions () 1005254721Semaste { 1006254721Semaste return g_option_table; 1007254721Semaste } 1008254721Semaste 1009254721Semaste // Options table: Required for subclasses of Options. 1010254721Semaste 1011254721Semaste static OptionDefinition g_option_table[]; 1012254721Semaste 1013254721Semaste // Instance variables to hold the values for command options. 1014254721Semaste 1015254721Semaste std::string plugin_name; 1016254721Semaste }; 1017254721Semaste 1018254721Semaste CommandObjectProcessConnect (CommandInterpreter &interpreter) : 1019254721Semaste CommandObjectParsed (interpreter, 1020254721Semaste "process connect", 1021254721Semaste "Connect to a remote debug service.", 1022254721Semaste "process connect <remote-url>", 1023254721Semaste 0), 1024254721Semaste m_options (interpreter) 1025254721Semaste { 1026254721Semaste } 1027254721Semaste 1028254721Semaste ~CommandObjectProcessConnect () 1029254721Semaste { 1030254721Semaste } 1031254721Semaste 1032254721Semaste 1033254721Semaste Options * 1034254721Semaste GetOptions () 1035254721Semaste { 1036254721Semaste return &m_options; 1037254721Semaste } 1038254721Semaste 1039254721Semasteprotected: 1040254721Semaste bool 1041254721Semaste DoExecute (Args& command, 1042254721Semaste CommandReturnObject &result) 1043254721Semaste { 1044254721Semaste 1045254721Semaste TargetSP target_sp (m_interpreter.GetDebugger().GetSelectedTarget()); 1046254721Semaste Error error; 1047254721Semaste Process *process = m_exe_ctx.GetProcessPtr(); 1048254721Semaste if (process) 1049254721Semaste { 1050254721Semaste if (process->IsAlive()) 1051254721Semaste { 1052254721Semaste result.AppendErrorWithFormat ("Process %" PRIu64 " is currently being debugged, kill the process before connecting.\n", 1053254721Semaste process->GetID()); 1054254721Semaste result.SetStatus (eReturnStatusFailed); 1055254721Semaste return false; 1056254721Semaste } 1057254721Semaste } 1058254721Semaste 1059254721Semaste if (!target_sp) 1060254721Semaste { 1061254721Semaste // If there isn't a current target create one. 1062254721Semaste 1063254721Semaste error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(), 1064254721Semaste NULL, 1065254721Semaste NULL, 1066254721Semaste false, 1067254721Semaste NULL, // No platform options 1068254721Semaste target_sp); 1069254721Semaste if (!target_sp || error.Fail()) 1070254721Semaste { 1071254721Semaste result.AppendError(error.AsCString("Error creating target")); 1072254721Semaste result.SetStatus (eReturnStatusFailed); 1073254721Semaste return false; 1074254721Semaste } 1075254721Semaste m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target_sp.get()); 1076254721Semaste } 1077254721Semaste 1078254721Semaste if (command.GetArgumentCount() == 1) 1079254721Semaste { 1080254721Semaste const char *plugin_name = NULL; 1081254721Semaste if (!m_options.plugin_name.empty()) 1082254721Semaste plugin_name = m_options.plugin_name.c_str(); 1083254721Semaste 1084254721Semaste const char *remote_url = command.GetArgumentAtIndex(0); 1085254721Semaste process = target_sp->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name, NULL).get(); 1086254721Semaste 1087254721Semaste if (process) 1088254721Semaste { 1089269024Semaste error = process->ConnectRemote (process->GetTarget().GetDebugger().GetOutputFile().get(), remote_url); 1090254721Semaste 1091254721Semaste if (error.Fail()) 1092254721Semaste { 1093254721Semaste result.AppendError(error.AsCString("Remote connect failed")); 1094254721Semaste result.SetStatus (eReturnStatusFailed); 1095254721Semaste target_sp->DeleteCurrentProcess(); 1096254721Semaste return false; 1097254721Semaste } 1098254721Semaste } 1099254721Semaste else 1100254721Semaste { 1101254721Semaste result.AppendErrorWithFormat ("Unable to find process plug-in for remote URL '%s'.\nPlease specify a process plug-in name with the --plugin option, or specify an object file using the \"file\" command.\n", 1102254721Semaste remote_url); 1103254721Semaste result.SetStatus (eReturnStatusFailed); 1104254721Semaste } 1105254721Semaste } 1106254721Semaste else 1107254721Semaste { 1108254721Semaste result.AppendErrorWithFormat ("'%s' takes exactly one argument:\nUsage: %s\n", 1109254721Semaste m_cmd_name.c_str(), 1110254721Semaste m_cmd_syntax.c_str()); 1111254721Semaste result.SetStatus (eReturnStatusFailed); 1112254721Semaste } 1113254721Semaste return result.Succeeded(); 1114254721Semaste } 1115254721Semaste 1116254721Semaste CommandOptions m_options; 1117254721Semaste}; 1118254721Semaste 1119254721SemasteOptionDefinition 1120254721SemasteCommandObjectProcessConnect::CommandOptions::g_option_table[] = 1121254721Semaste{ 1122263363Semaste { LLDB_OPT_SET_ALL, false, "plugin", 'p', OptionParser::eRequiredArgument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."}, 1123254721Semaste { 0, false, NULL, 0 , 0, NULL, 0, eArgTypeNone, NULL } 1124254721Semaste}; 1125254721Semaste 1126254721Semaste//------------------------------------------------------------------------- 1127254721Semaste// CommandObjectProcessPlugin 1128254721Semaste//------------------------------------------------------------------------- 1129254721Semaste#pragma mark CommandObjectProcessPlugin 1130254721Semaste 1131254721Semasteclass CommandObjectProcessPlugin : public CommandObjectProxy 1132254721Semaste{ 1133254721Semastepublic: 1134254721Semaste 1135254721Semaste CommandObjectProcessPlugin (CommandInterpreter &interpreter) : 1136254721Semaste CommandObjectProxy (interpreter, 1137254721Semaste "process plugin", 1138254721Semaste "Send a custom command to the current process plug-in.", 1139254721Semaste "process plugin <args>", 1140254721Semaste 0) 1141254721Semaste { 1142254721Semaste } 1143254721Semaste 1144254721Semaste ~CommandObjectProcessPlugin () 1145254721Semaste { 1146254721Semaste } 1147254721Semaste 1148254721Semaste virtual CommandObject * 1149254721Semaste GetProxyCommandObject() 1150254721Semaste { 1151254721Semaste Process *process = m_interpreter.GetExecutionContext().GetProcessPtr(); 1152254721Semaste if (process) 1153254721Semaste return process->GetPluginCommandObject(); 1154254721Semaste return NULL; 1155254721Semaste } 1156254721Semaste}; 1157254721Semaste 1158254721Semaste 1159254721Semaste//------------------------------------------------------------------------- 1160254721Semaste// CommandObjectProcessLoad 1161254721Semaste//------------------------------------------------------------------------- 1162254721Semaste#pragma mark CommandObjectProcessLoad 1163254721Semaste 1164254721Semasteclass CommandObjectProcessLoad : public CommandObjectParsed 1165254721Semaste{ 1166254721Semastepublic: 1167254721Semaste 1168254721Semaste CommandObjectProcessLoad (CommandInterpreter &interpreter) : 1169254721Semaste CommandObjectParsed (interpreter, 1170254721Semaste "process load", 1171254721Semaste "Load a shared library into the current process.", 1172254721Semaste "process load <filename> [<filename> ...]", 1173254721Semaste eFlagRequiresProcess | 1174254721Semaste eFlagTryTargetAPILock | 1175254721Semaste eFlagProcessMustBeLaunched | 1176254721Semaste eFlagProcessMustBePaused ) 1177254721Semaste { 1178254721Semaste } 1179254721Semaste 1180254721Semaste ~CommandObjectProcessLoad () 1181254721Semaste { 1182254721Semaste } 1183254721Semaste 1184254721Semasteprotected: 1185254721Semaste bool 1186254721Semaste DoExecute (Args& command, 1187254721Semaste CommandReturnObject &result) 1188254721Semaste { 1189254721Semaste Process *process = m_exe_ctx.GetProcessPtr(); 1190254721Semaste 1191254721Semaste const size_t argc = command.GetArgumentCount(); 1192254721Semaste 1193254721Semaste for (uint32_t i=0; i<argc; ++i) 1194254721Semaste { 1195254721Semaste Error error; 1196254721Semaste const char *image_path = command.GetArgumentAtIndex(i); 1197254721Semaste FileSpec image_spec (image_path, false); 1198254721Semaste process->GetTarget().GetPlatform()->ResolveRemotePath(image_spec, image_spec); 1199254721Semaste uint32_t image_token = process->LoadImage(image_spec, error); 1200254721Semaste if (image_token != LLDB_INVALID_IMAGE_TOKEN) 1201254721Semaste { 1202254721Semaste result.AppendMessageWithFormat ("Loading \"%s\"...ok\nImage %u loaded.\n", image_path, image_token); 1203254721Semaste result.SetStatus (eReturnStatusSuccessFinishResult); 1204254721Semaste } 1205254721Semaste else 1206254721Semaste { 1207254721Semaste result.AppendErrorWithFormat ("failed to load '%s': %s", image_path, error.AsCString()); 1208254721Semaste result.SetStatus (eReturnStatusFailed); 1209254721Semaste } 1210254721Semaste } 1211254721Semaste return result.Succeeded(); 1212254721Semaste } 1213254721Semaste}; 1214254721Semaste 1215254721Semaste 1216254721Semaste//------------------------------------------------------------------------- 1217254721Semaste// CommandObjectProcessUnload 1218254721Semaste//------------------------------------------------------------------------- 1219254721Semaste#pragma mark CommandObjectProcessUnload 1220254721Semaste 1221254721Semasteclass CommandObjectProcessUnload : public CommandObjectParsed 1222254721Semaste{ 1223254721Semastepublic: 1224254721Semaste 1225254721Semaste CommandObjectProcessUnload (CommandInterpreter &interpreter) : 1226254721Semaste CommandObjectParsed (interpreter, 1227254721Semaste "process unload", 1228254721Semaste "Unload a shared library from the current process using the index returned by a previous call to \"process load\".", 1229254721Semaste "process unload <index>", 1230254721Semaste eFlagRequiresProcess | 1231254721Semaste eFlagTryTargetAPILock | 1232254721Semaste eFlagProcessMustBeLaunched | 1233254721Semaste eFlagProcessMustBePaused ) 1234254721Semaste { 1235254721Semaste } 1236254721Semaste 1237254721Semaste ~CommandObjectProcessUnload () 1238254721Semaste { 1239254721Semaste } 1240254721Semaste 1241254721Semasteprotected: 1242254721Semaste bool 1243254721Semaste DoExecute (Args& command, 1244254721Semaste CommandReturnObject &result) 1245254721Semaste { 1246254721Semaste Process *process = m_exe_ctx.GetProcessPtr(); 1247254721Semaste 1248254721Semaste const size_t argc = command.GetArgumentCount(); 1249254721Semaste 1250254721Semaste for (uint32_t i=0; i<argc; ++i) 1251254721Semaste { 1252254721Semaste const char *image_token_cstr = command.GetArgumentAtIndex(i); 1253254721Semaste uint32_t image_token = Args::StringToUInt32(image_token_cstr, LLDB_INVALID_IMAGE_TOKEN, 0); 1254254721Semaste if (image_token == LLDB_INVALID_IMAGE_TOKEN) 1255254721Semaste { 1256254721Semaste result.AppendErrorWithFormat ("invalid image index argument '%s'", image_token_cstr); 1257254721Semaste result.SetStatus (eReturnStatusFailed); 1258254721Semaste break; 1259254721Semaste } 1260254721Semaste else 1261254721Semaste { 1262254721Semaste Error error (process->UnloadImage(image_token)); 1263254721Semaste if (error.Success()) 1264254721Semaste { 1265254721Semaste result.AppendMessageWithFormat ("Unloading shared library with index %u...ok\n", image_token); 1266254721Semaste result.SetStatus (eReturnStatusSuccessFinishResult); 1267254721Semaste } 1268254721Semaste else 1269254721Semaste { 1270254721Semaste result.AppendErrorWithFormat ("failed to unload image: %s", error.AsCString()); 1271254721Semaste result.SetStatus (eReturnStatusFailed); 1272254721Semaste break; 1273254721Semaste } 1274254721Semaste } 1275254721Semaste } 1276254721Semaste return result.Succeeded(); 1277254721Semaste } 1278254721Semaste}; 1279254721Semaste 1280254721Semaste//------------------------------------------------------------------------- 1281254721Semaste// CommandObjectProcessSignal 1282254721Semaste//------------------------------------------------------------------------- 1283254721Semaste#pragma mark CommandObjectProcessSignal 1284254721Semaste 1285254721Semasteclass CommandObjectProcessSignal : public CommandObjectParsed 1286254721Semaste{ 1287254721Semastepublic: 1288254721Semaste 1289254721Semaste CommandObjectProcessSignal (CommandInterpreter &interpreter) : 1290254721Semaste CommandObjectParsed (interpreter, 1291254721Semaste "process signal", 1292254721Semaste "Send a UNIX signal to the current process being debugged.", 1293254721Semaste NULL, 1294254721Semaste eFlagRequiresProcess | eFlagTryTargetAPILock) 1295254721Semaste { 1296254721Semaste CommandArgumentEntry arg; 1297254721Semaste CommandArgumentData signal_arg; 1298254721Semaste 1299254721Semaste // Define the first (and only) variant of this arg. 1300254721Semaste signal_arg.arg_type = eArgTypeUnixSignal; 1301254721Semaste signal_arg.arg_repetition = eArgRepeatPlain; 1302254721Semaste 1303254721Semaste // There is only one variant this argument could be; put it into the argument entry. 1304254721Semaste arg.push_back (signal_arg); 1305254721Semaste 1306254721Semaste // Push the data for the first argument into the m_arguments vector. 1307254721Semaste m_arguments.push_back (arg); 1308254721Semaste } 1309254721Semaste 1310254721Semaste ~CommandObjectProcessSignal () 1311254721Semaste { 1312254721Semaste } 1313254721Semaste 1314254721Semasteprotected: 1315254721Semaste bool 1316254721Semaste DoExecute (Args& command, 1317254721Semaste CommandReturnObject &result) 1318254721Semaste { 1319254721Semaste Process *process = m_exe_ctx.GetProcessPtr(); 1320254721Semaste 1321254721Semaste if (command.GetArgumentCount() == 1) 1322254721Semaste { 1323254721Semaste int signo = LLDB_INVALID_SIGNAL_NUMBER; 1324254721Semaste 1325254721Semaste const char *signal_name = command.GetArgumentAtIndex(0); 1326254721Semaste if (::isxdigit (signal_name[0])) 1327254721Semaste signo = Args::StringToSInt32(signal_name, LLDB_INVALID_SIGNAL_NUMBER, 0); 1328254721Semaste else 1329254721Semaste signo = process->GetUnixSignals().GetSignalNumberFromName (signal_name); 1330254721Semaste 1331254721Semaste if (signo == LLDB_INVALID_SIGNAL_NUMBER) 1332254721Semaste { 1333254721Semaste result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0)); 1334254721Semaste result.SetStatus (eReturnStatusFailed); 1335254721Semaste } 1336254721Semaste else 1337254721Semaste { 1338254721Semaste Error error (process->Signal (signo)); 1339254721Semaste if (error.Success()) 1340254721Semaste { 1341254721Semaste result.SetStatus (eReturnStatusSuccessFinishResult); 1342254721Semaste } 1343254721Semaste else 1344254721Semaste { 1345254721Semaste result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString()); 1346254721Semaste result.SetStatus (eReturnStatusFailed); 1347254721Semaste } 1348254721Semaste } 1349254721Semaste } 1350254721Semaste else 1351254721Semaste { 1352254721Semaste result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: %s\n", m_cmd_name.c_str(), 1353254721Semaste m_cmd_syntax.c_str()); 1354254721Semaste result.SetStatus (eReturnStatusFailed); 1355254721Semaste } 1356254721Semaste return result.Succeeded(); 1357254721Semaste } 1358254721Semaste}; 1359254721Semaste 1360254721Semaste 1361254721Semaste//------------------------------------------------------------------------- 1362254721Semaste// CommandObjectProcessInterrupt 1363254721Semaste//------------------------------------------------------------------------- 1364254721Semaste#pragma mark CommandObjectProcessInterrupt 1365254721Semaste 1366254721Semasteclass CommandObjectProcessInterrupt : public CommandObjectParsed 1367254721Semaste{ 1368254721Semastepublic: 1369254721Semaste 1370254721Semaste 1371254721Semaste CommandObjectProcessInterrupt (CommandInterpreter &interpreter) : 1372254721Semaste CommandObjectParsed (interpreter, 1373254721Semaste "process interrupt", 1374254721Semaste "Interrupt the current process being debugged.", 1375254721Semaste "process interrupt", 1376254721Semaste eFlagRequiresProcess | 1377254721Semaste eFlagTryTargetAPILock | 1378254721Semaste eFlagProcessMustBeLaunched) 1379254721Semaste { 1380254721Semaste } 1381254721Semaste 1382254721Semaste ~CommandObjectProcessInterrupt () 1383254721Semaste { 1384254721Semaste } 1385254721Semaste 1386254721Semasteprotected: 1387254721Semaste bool 1388254721Semaste DoExecute (Args& command, 1389254721Semaste CommandReturnObject &result) 1390254721Semaste { 1391254721Semaste Process *process = m_exe_ctx.GetProcessPtr(); 1392254721Semaste if (process == NULL) 1393254721Semaste { 1394254721Semaste result.AppendError ("no process to halt"); 1395254721Semaste result.SetStatus (eReturnStatusFailed); 1396254721Semaste return false; 1397254721Semaste } 1398254721Semaste 1399254721Semaste if (command.GetArgumentCount() == 0) 1400254721Semaste { 1401254721Semaste bool clear_thread_plans = true; 1402254721Semaste Error error(process->Halt (clear_thread_plans)); 1403254721Semaste if (error.Success()) 1404254721Semaste { 1405254721Semaste result.SetStatus (eReturnStatusSuccessFinishResult); 1406254721Semaste } 1407254721Semaste else 1408254721Semaste { 1409254721Semaste result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString()); 1410254721Semaste result.SetStatus (eReturnStatusFailed); 1411254721Semaste } 1412254721Semaste } 1413254721Semaste else 1414254721Semaste { 1415254721Semaste result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n", 1416254721Semaste m_cmd_name.c_str(), 1417254721Semaste m_cmd_syntax.c_str()); 1418254721Semaste result.SetStatus (eReturnStatusFailed); 1419254721Semaste } 1420254721Semaste return result.Succeeded(); 1421254721Semaste } 1422254721Semaste}; 1423254721Semaste 1424254721Semaste//------------------------------------------------------------------------- 1425254721Semaste// CommandObjectProcessKill 1426254721Semaste//------------------------------------------------------------------------- 1427254721Semaste#pragma mark CommandObjectProcessKill 1428254721Semaste 1429254721Semasteclass CommandObjectProcessKill : public CommandObjectParsed 1430254721Semaste{ 1431254721Semastepublic: 1432254721Semaste 1433254721Semaste CommandObjectProcessKill (CommandInterpreter &interpreter) : 1434254721Semaste CommandObjectParsed (interpreter, 1435254721Semaste "process kill", 1436254721Semaste "Terminate the current process being debugged.", 1437254721Semaste "process kill", 1438254721Semaste eFlagRequiresProcess | 1439254721Semaste eFlagTryTargetAPILock | 1440254721Semaste eFlagProcessMustBeLaunched) 1441254721Semaste { 1442254721Semaste } 1443254721Semaste 1444254721Semaste ~CommandObjectProcessKill () 1445254721Semaste { 1446254721Semaste } 1447254721Semaste 1448254721Semasteprotected: 1449254721Semaste bool 1450254721Semaste DoExecute (Args& command, 1451254721Semaste CommandReturnObject &result) 1452254721Semaste { 1453254721Semaste Process *process = m_exe_ctx.GetProcessPtr(); 1454254721Semaste if (process == NULL) 1455254721Semaste { 1456254721Semaste result.AppendError ("no process to kill"); 1457254721Semaste result.SetStatus (eReturnStatusFailed); 1458254721Semaste return false; 1459254721Semaste } 1460254721Semaste 1461254721Semaste if (command.GetArgumentCount() == 0) 1462254721Semaste { 1463254721Semaste Error error (process->Destroy()); 1464254721Semaste if (error.Success()) 1465254721Semaste { 1466254721Semaste result.SetStatus (eReturnStatusSuccessFinishResult); 1467254721Semaste } 1468254721Semaste else 1469254721Semaste { 1470254721Semaste result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString()); 1471254721Semaste result.SetStatus (eReturnStatusFailed); 1472254721Semaste } 1473254721Semaste } 1474254721Semaste else 1475254721Semaste { 1476254721Semaste result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n", 1477254721Semaste m_cmd_name.c_str(), 1478254721Semaste m_cmd_syntax.c_str()); 1479254721Semaste result.SetStatus (eReturnStatusFailed); 1480254721Semaste } 1481254721Semaste return result.Succeeded(); 1482254721Semaste } 1483254721Semaste}; 1484254721Semaste 1485254721Semaste//------------------------------------------------------------------------- 1486254721Semaste// CommandObjectProcessStatus 1487254721Semaste//------------------------------------------------------------------------- 1488254721Semaste#pragma mark CommandObjectProcessStatus 1489254721Semaste 1490254721Semasteclass CommandObjectProcessStatus : public CommandObjectParsed 1491254721Semaste{ 1492254721Semastepublic: 1493254721Semaste CommandObjectProcessStatus (CommandInterpreter &interpreter) : 1494254721Semaste CommandObjectParsed (interpreter, 1495254721Semaste "process status", 1496254721Semaste "Show the current status and location of executing process.", 1497254721Semaste "process status", 1498254721Semaste eFlagRequiresProcess | eFlagTryTargetAPILock) 1499254721Semaste { 1500254721Semaste } 1501254721Semaste 1502254721Semaste ~CommandObjectProcessStatus() 1503254721Semaste { 1504254721Semaste } 1505254721Semaste 1506254721Semaste 1507254721Semaste bool 1508254721Semaste DoExecute (Args& command, CommandReturnObject &result) 1509254721Semaste { 1510254721Semaste Stream &strm = result.GetOutputStream(); 1511254721Semaste result.SetStatus (eReturnStatusSuccessFinishNoResult); 1512254721Semaste // No need to check "process" for validity as eFlagRequiresProcess ensures it is valid 1513254721Semaste Process *process = m_exe_ctx.GetProcessPtr(); 1514254721Semaste const bool only_threads_with_stop_reason = true; 1515254721Semaste const uint32_t start_frame = 0; 1516254721Semaste const uint32_t num_frames = 1; 1517254721Semaste const uint32_t num_frames_with_source = 1; 1518254721Semaste process->GetStatus(strm); 1519254721Semaste process->GetThreadStatus (strm, 1520254721Semaste only_threads_with_stop_reason, 1521254721Semaste start_frame, 1522254721Semaste num_frames, 1523254721Semaste num_frames_with_source); 1524254721Semaste return result.Succeeded(); 1525254721Semaste } 1526254721Semaste}; 1527254721Semaste 1528254721Semaste//------------------------------------------------------------------------- 1529254721Semaste// CommandObjectProcessHandle 1530254721Semaste//------------------------------------------------------------------------- 1531254721Semaste#pragma mark CommandObjectProcessHandle 1532254721Semaste 1533254721Semasteclass CommandObjectProcessHandle : public CommandObjectParsed 1534254721Semaste{ 1535254721Semastepublic: 1536254721Semaste 1537254721Semaste class CommandOptions : public Options 1538254721Semaste { 1539254721Semaste public: 1540254721Semaste 1541254721Semaste CommandOptions (CommandInterpreter &interpreter) : 1542254721Semaste Options (interpreter) 1543254721Semaste { 1544254721Semaste OptionParsingStarting (); 1545254721Semaste } 1546254721Semaste 1547254721Semaste ~CommandOptions () 1548254721Semaste { 1549254721Semaste } 1550254721Semaste 1551254721Semaste Error 1552254721Semaste SetOptionValue (uint32_t option_idx, const char *option_arg) 1553254721Semaste { 1554254721Semaste Error error; 1555254721Semaste const int short_option = m_getopt_table[option_idx].val; 1556254721Semaste 1557254721Semaste switch (short_option) 1558254721Semaste { 1559254721Semaste case 's': 1560254721Semaste stop = option_arg; 1561254721Semaste break; 1562254721Semaste case 'n': 1563254721Semaste notify = option_arg; 1564254721Semaste break; 1565254721Semaste case 'p': 1566254721Semaste pass = option_arg; 1567254721Semaste break; 1568254721Semaste default: 1569254721Semaste error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 1570254721Semaste break; 1571254721Semaste } 1572254721Semaste return error; 1573254721Semaste } 1574254721Semaste 1575254721Semaste void 1576254721Semaste OptionParsingStarting () 1577254721Semaste { 1578254721Semaste stop.clear(); 1579254721Semaste notify.clear(); 1580254721Semaste pass.clear(); 1581254721Semaste } 1582254721Semaste 1583254721Semaste const OptionDefinition* 1584254721Semaste GetDefinitions () 1585254721Semaste { 1586254721Semaste return g_option_table; 1587254721Semaste } 1588254721Semaste 1589254721Semaste // Options table: Required for subclasses of Options. 1590254721Semaste 1591254721Semaste static OptionDefinition g_option_table[]; 1592254721Semaste 1593254721Semaste // Instance variables to hold the values for command options. 1594254721Semaste 1595254721Semaste std::string stop; 1596254721Semaste std::string notify; 1597254721Semaste std::string pass; 1598254721Semaste }; 1599254721Semaste 1600254721Semaste 1601254721Semaste CommandObjectProcessHandle (CommandInterpreter &interpreter) : 1602254721Semaste CommandObjectParsed (interpreter, 1603254721Semaste "process handle", 1604254721Semaste "Show or update what the process and debugger should do with various signals received from the OS.", 1605254721Semaste NULL), 1606254721Semaste m_options (interpreter) 1607254721Semaste { 1608254721Semaste SetHelpLong ("If no signals are specified, update them all. If no update option is specified, list the current values.\n"); 1609254721Semaste CommandArgumentEntry arg; 1610254721Semaste CommandArgumentData signal_arg; 1611254721Semaste 1612254721Semaste signal_arg.arg_type = eArgTypeUnixSignal; 1613254721Semaste signal_arg.arg_repetition = eArgRepeatStar; 1614254721Semaste 1615254721Semaste arg.push_back (signal_arg); 1616254721Semaste 1617254721Semaste m_arguments.push_back (arg); 1618254721Semaste } 1619254721Semaste 1620254721Semaste ~CommandObjectProcessHandle () 1621254721Semaste { 1622254721Semaste } 1623254721Semaste 1624254721Semaste Options * 1625254721Semaste GetOptions () 1626254721Semaste { 1627254721Semaste return &m_options; 1628254721Semaste } 1629254721Semaste 1630254721Semaste bool 1631254721Semaste VerifyCommandOptionValue (const std::string &option, int &real_value) 1632254721Semaste { 1633254721Semaste bool okay = true; 1634254721Semaste 1635254721Semaste bool success = false; 1636254721Semaste bool tmp_value = Args::StringToBoolean (option.c_str(), false, &success); 1637254721Semaste 1638254721Semaste if (success && tmp_value) 1639254721Semaste real_value = 1; 1640254721Semaste else if (success && !tmp_value) 1641254721Semaste real_value = 0; 1642254721Semaste else 1643254721Semaste { 1644254721Semaste // If the value isn't 'true' or 'false', it had better be 0 or 1. 1645254721Semaste real_value = Args::StringToUInt32 (option.c_str(), 3); 1646254721Semaste if (real_value != 0 && real_value != 1) 1647254721Semaste okay = false; 1648254721Semaste } 1649254721Semaste 1650254721Semaste return okay; 1651254721Semaste } 1652254721Semaste 1653254721Semaste void 1654254721Semaste PrintSignalHeader (Stream &str) 1655254721Semaste { 1656254721Semaste str.Printf ("NAME PASS STOP NOTIFY\n"); 1657254721Semaste str.Printf ("========== ===== ===== ======\n"); 1658254721Semaste } 1659254721Semaste 1660254721Semaste void 1661254721Semaste PrintSignal (Stream &str, int32_t signo, const char *sig_name, UnixSignals &signals) 1662254721Semaste { 1663254721Semaste bool stop; 1664254721Semaste bool suppress; 1665254721Semaste bool notify; 1666254721Semaste 1667254721Semaste str.Printf ("%-10s ", sig_name); 1668254721Semaste if (signals.GetSignalInfo (signo, suppress, stop, notify)) 1669254721Semaste { 1670254721Semaste bool pass = !suppress; 1671254721Semaste str.Printf ("%s %s %s", 1672254721Semaste (pass ? "true " : "false"), 1673254721Semaste (stop ? "true " : "false"), 1674254721Semaste (notify ? "true " : "false")); 1675254721Semaste } 1676254721Semaste str.Printf ("\n"); 1677254721Semaste } 1678254721Semaste 1679254721Semaste void 1680254721Semaste PrintSignalInformation (Stream &str, Args &signal_args, int num_valid_signals, UnixSignals &signals) 1681254721Semaste { 1682254721Semaste PrintSignalHeader (str); 1683254721Semaste 1684254721Semaste if (num_valid_signals > 0) 1685254721Semaste { 1686254721Semaste size_t num_args = signal_args.GetArgumentCount(); 1687254721Semaste for (size_t i = 0; i < num_args; ++i) 1688254721Semaste { 1689254721Semaste int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i)); 1690254721Semaste if (signo != LLDB_INVALID_SIGNAL_NUMBER) 1691254721Semaste PrintSignal (str, signo, signal_args.GetArgumentAtIndex (i), signals); 1692254721Semaste } 1693254721Semaste } 1694254721Semaste else // Print info for ALL signals 1695254721Semaste { 1696254721Semaste int32_t signo = signals.GetFirstSignalNumber(); 1697254721Semaste while (signo != LLDB_INVALID_SIGNAL_NUMBER) 1698254721Semaste { 1699254721Semaste PrintSignal (str, signo, signals.GetSignalAsCString (signo), signals); 1700254721Semaste signo = signals.GetNextSignalNumber (signo); 1701254721Semaste } 1702254721Semaste } 1703254721Semaste } 1704254721Semaste 1705254721Semasteprotected: 1706254721Semaste bool 1707254721Semaste DoExecute (Args &signal_args, CommandReturnObject &result) 1708254721Semaste { 1709254721Semaste TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget(); 1710254721Semaste 1711254721Semaste if (!target_sp) 1712254721Semaste { 1713254721Semaste result.AppendError ("No current target;" 1714254721Semaste " cannot handle signals until you have a valid target and process.\n"); 1715254721Semaste result.SetStatus (eReturnStatusFailed); 1716254721Semaste return false; 1717254721Semaste } 1718254721Semaste 1719254721Semaste ProcessSP process_sp = target_sp->GetProcessSP(); 1720254721Semaste 1721254721Semaste if (!process_sp) 1722254721Semaste { 1723254721Semaste result.AppendError ("No current process; cannot handle signals until you have a valid process.\n"); 1724254721Semaste result.SetStatus (eReturnStatusFailed); 1725254721Semaste return false; 1726254721Semaste } 1727254721Semaste 1728254721Semaste int stop_action = -1; // -1 means leave the current setting alone 1729254721Semaste int pass_action = -1; // -1 means leave the current setting alone 1730254721Semaste int notify_action = -1; // -1 means leave the current setting alone 1731254721Semaste 1732254721Semaste if (! m_options.stop.empty() 1733254721Semaste && ! VerifyCommandOptionValue (m_options.stop, stop_action)) 1734254721Semaste { 1735254721Semaste result.AppendError ("Invalid argument for command option --stop; must be true or false.\n"); 1736254721Semaste result.SetStatus (eReturnStatusFailed); 1737254721Semaste return false; 1738254721Semaste } 1739254721Semaste 1740254721Semaste if (! m_options.notify.empty() 1741254721Semaste && ! VerifyCommandOptionValue (m_options.notify, notify_action)) 1742254721Semaste { 1743254721Semaste result.AppendError ("Invalid argument for command option --notify; must be true or false.\n"); 1744254721Semaste result.SetStatus (eReturnStatusFailed); 1745254721Semaste return false; 1746254721Semaste } 1747254721Semaste 1748254721Semaste if (! m_options.pass.empty() 1749254721Semaste && ! VerifyCommandOptionValue (m_options.pass, pass_action)) 1750254721Semaste { 1751254721Semaste result.AppendError ("Invalid argument for command option --pass; must be true or false.\n"); 1752254721Semaste result.SetStatus (eReturnStatusFailed); 1753254721Semaste return false; 1754254721Semaste } 1755254721Semaste 1756254721Semaste size_t num_args = signal_args.GetArgumentCount(); 1757254721Semaste UnixSignals &signals = process_sp->GetUnixSignals(); 1758254721Semaste int num_signals_set = 0; 1759254721Semaste 1760254721Semaste if (num_args > 0) 1761254721Semaste { 1762254721Semaste for (size_t i = 0; i < num_args; ++i) 1763254721Semaste { 1764254721Semaste int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i)); 1765254721Semaste if (signo != LLDB_INVALID_SIGNAL_NUMBER) 1766254721Semaste { 1767254721Semaste // Casting the actions as bools here should be okay, because VerifyCommandOptionValue guarantees 1768254721Semaste // the value is either 0 or 1. 1769254721Semaste if (stop_action != -1) 1770254721Semaste signals.SetShouldStop (signo, (bool) stop_action); 1771254721Semaste if (pass_action != -1) 1772254721Semaste { 1773254721Semaste bool suppress = ! ((bool) pass_action); 1774254721Semaste signals.SetShouldSuppress (signo, suppress); 1775254721Semaste } 1776254721Semaste if (notify_action != -1) 1777254721Semaste signals.SetShouldNotify (signo, (bool) notify_action); 1778254721Semaste ++num_signals_set; 1779254721Semaste } 1780254721Semaste else 1781254721Semaste { 1782254721Semaste result.AppendErrorWithFormat ("Invalid signal name '%s'\n", signal_args.GetArgumentAtIndex (i)); 1783254721Semaste } 1784254721Semaste } 1785254721Semaste } 1786254721Semaste else 1787254721Semaste { 1788254721Semaste // No signal specified, if any command options were specified, update ALL signals. 1789254721Semaste if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1)) 1790254721Semaste { 1791254721Semaste if (m_interpreter.Confirm ("Do you really want to update all the signals?", false)) 1792254721Semaste { 1793254721Semaste int32_t signo = signals.GetFirstSignalNumber(); 1794254721Semaste while (signo != LLDB_INVALID_SIGNAL_NUMBER) 1795254721Semaste { 1796254721Semaste if (notify_action != -1) 1797254721Semaste signals.SetShouldNotify (signo, (bool) notify_action); 1798254721Semaste if (stop_action != -1) 1799254721Semaste signals.SetShouldStop (signo, (bool) stop_action); 1800254721Semaste if (pass_action != -1) 1801254721Semaste { 1802254721Semaste bool suppress = ! ((bool) pass_action); 1803254721Semaste signals.SetShouldSuppress (signo, suppress); 1804254721Semaste } 1805254721Semaste signo = signals.GetNextSignalNumber (signo); 1806254721Semaste } 1807254721Semaste } 1808254721Semaste } 1809254721Semaste } 1810254721Semaste 1811254721Semaste PrintSignalInformation (result.GetOutputStream(), signal_args, num_signals_set, signals); 1812254721Semaste 1813254721Semaste if (num_signals_set > 0) 1814254721Semaste result.SetStatus (eReturnStatusSuccessFinishNoResult); 1815254721Semaste else 1816254721Semaste result.SetStatus (eReturnStatusFailed); 1817254721Semaste 1818254721Semaste return result.Succeeded(); 1819254721Semaste } 1820254721Semaste 1821254721Semaste CommandOptions m_options; 1822254721Semaste}; 1823254721Semaste 1824254721SemasteOptionDefinition 1825254721SemasteCommandObjectProcessHandle::CommandOptions::g_option_table[] = 1826254721Semaste{ 1827263363Semaste{ LLDB_OPT_SET_1, false, "stop", 's', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "Whether or not the process should be stopped if the signal is received." }, 1828263363Semaste{ LLDB_OPT_SET_1, false, "notify", 'n', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "Whether or not the debugger should notify the user if the signal is received." }, 1829263363Semaste{ LLDB_OPT_SET_1, false, "pass", 'p', OptionParser::eRequiredArgument, NULL, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." }, 1830254721Semaste{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 1831254721Semaste}; 1832254721Semaste 1833254721Semaste//------------------------------------------------------------------------- 1834254721Semaste// CommandObjectMultiwordProcess 1835254721Semaste//------------------------------------------------------------------------- 1836254721Semaste 1837254721SemasteCommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter &interpreter) : 1838254721Semaste CommandObjectMultiword (interpreter, 1839254721Semaste "process", 1840254721Semaste "A set of commands for operating on a process.", 1841254721Semaste "process <subcommand> [<subcommand-options>]") 1842254721Semaste{ 1843254721Semaste LoadSubCommand ("attach", CommandObjectSP (new CommandObjectProcessAttach (interpreter))); 1844254721Semaste LoadSubCommand ("launch", CommandObjectSP (new CommandObjectProcessLaunch (interpreter))); 1845254721Semaste LoadSubCommand ("continue", CommandObjectSP (new CommandObjectProcessContinue (interpreter))); 1846254721Semaste LoadSubCommand ("connect", CommandObjectSP (new CommandObjectProcessConnect (interpreter))); 1847254721Semaste LoadSubCommand ("detach", CommandObjectSP (new CommandObjectProcessDetach (interpreter))); 1848254721Semaste LoadSubCommand ("load", CommandObjectSP (new CommandObjectProcessLoad (interpreter))); 1849254721Semaste LoadSubCommand ("unload", CommandObjectSP (new CommandObjectProcessUnload (interpreter))); 1850254721Semaste LoadSubCommand ("signal", CommandObjectSP (new CommandObjectProcessSignal (interpreter))); 1851254721Semaste LoadSubCommand ("handle", CommandObjectSP (new CommandObjectProcessHandle (interpreter))); 1852254721Semaste LoadSubCommand ("status", CommandObjectSP (new CommandObjectProcessStatus (interpreter))); 1853254721Semaste LoadSubCommand ("interrupt", CommandObjectSP (new CommandObjectProcessInterrupt (interpreter))); 1854254721Semaste LoadSubCommand ("kill", CommandObjectSP (new CommandObjectProcessKill (interpreter))); 1855254721Semaste LoadSubCommand ("plugin", CommandObjectSP (new CommandObjectProcessPlugin (interpreter))); 1856254721Semaste} 1857254721Semaste 1858254721SemasteCommandObjectMultiwordProcess::~CommandObjectMultiwordProcess () 1859254721Semaste{ 1860254721Semaste} 1861254721Semaste 1862