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