1 //===-- CommandObjectProcess.cpp --------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "lldb/lldb-python.h" 11 12 #include "CommandObjectProcess.h" 13 14 // C Includes 15 // C++ Includes 16 // Other libraries and framework includes 17 // Project includes 18 #include "lldb/Breakpoint/Breakpoint.h" 19 #include "lldb/Breakpoint/BreakpointLocation.h" 20 #include "lldb/Breakpoint/BreakpointSite.h" 21 #include "lldb/Core/State.h" 22 #include "lldb/Core/Module.h" 23 #include "lldb/Host/Host.h" 24 #include "lldb/Interpreter/Args.h" 25 #include "lldb/Interpreter/Options.h" 26 #include "lldb/Interpreter/CommandInterpreter.h" 27 #include "lldb/Interpreter/CommandReturnObject.h" 28 #include "lldb/Target/Platform.h" 29 #include "lldb/Target/Process.h" 30 #include "lldb/Target/StopInfo.h" 31 #include "lldb/Target/Target.h" 32 #include "lldb/Target/Thread.h" 33 34 using namespace lldb; 35 using namespace lldb_private; 36 37 class CommandObjectProcessLaunchOrAttach : public CommandObjectParsed 38 { 39 public: 40 CommandObjectProcessLaunchOrAttach (CommandInterpreter &interpreter, 41 const char *name, 42 const char *help, 43 const char *syntax, 44 uint32_t flags, 45 const char *new_process_action) : 46 CommandObjectParsed (interpreter, name, help, syntax, flags), 47 m_new_process_action (new_process_action) {} 48 49 virtual ~CommandObjectProcessLaunchOrAttach () {} 50 protected: 51 bool 52 StopProcessIfNecessary (Process *&process, StateType &state, CommandReturnObject &result) 53 { 54 state = eStateInvalid; 55 if (process) 56 { 57 state = process->GetState(); 58 59 if (process->IsAlive() && state != eStateConnected) 60 { 61 char message[1024]; 62 if (process->GetState() == eStateAttaching) 63 ::snprintf (message, sizeof(message), "There is a pending attach, abort it and %s?", m_new_process_action.c_str()); 64 else if (process->GetShouldDetach()) 65 ::snprintf (message, sizeof(message), "There is a running process, detach from it and %s?", m_new_process_action.c_str()); 66 else 67 ::snprintf (message, sizeof(message), "There is a running process, kill it and %s?", m_new_process_action.c_str()); 68 69 if (!m_interpreter.Confirm (message, true)) 70 { 71 result.SetStatus (eReturnStatusFailed); 72 return false; 73 } 74 else 75 { 76 if (process->GetShouldDetach()) 77 { 78 Error detach_error (process->Detach()); 79 if (detach_error.Success()) 80 { 81 result.SetStatus (eReturnStatusSuccessFinishResult); 82 process = NULL; 83 } 84 else 85 { 86 result.AppendErrorWithFormat ("Failed to detach from process: %s\n", detach_error.AsCString()); 87 result.SetStatus (eReturnStatusFailed); 88 } 89 } 90 else 91 { 92 Error destroy_error (process->Destroy()); 93 if (destroy_error.Success()) 94 { 95 result.SetStatus (eReturnStatusSuccessFinishResult); 96 process = NULL; 97 } 98 else 99 { 100 result.AppendErrorWithFormat ("Failed to kill process: %s\n", destroy_error.AsCString()); 101 result.SetStatus (eReturnStatusFailed); 102 } 103 } 104 } 105 } 106 } 107 return result.Succeeded(); 108 } 109 std::string m_new_process_action; 110 }; 111 //------------------------------------------------------------------------- 112 // CommandObjectProcessLaunch 113 //------------------------------------------------------------------------- 114 #pragma mark CommandObjectProcessLaunch 115 class CommandObjectProcessLaunch : public CommandObjectProcessLaunchOrAttach 116 { 117 public: 118 119 CommandObjectProcessLaunch (CommandInterpreter &interpreter) : 120 CommandObjectProcessLaunchOrAttach (interpreter, 121 "process launch", 122 "Launch the executable in the debugger.", 123 NULL, 124 eFlagRequiresTarget, 125 "restart"), 126 m_options (interpreter) 127 { 128 CommandArgumentEntry arg; 129 CommandArgumentData run_args_arg; 130 131 // Define the first (and only) variant of this arg. 132 run_args_arg.arg_type = eArgTypeRunArgs; 133 run_args_arg.arg_repetition = eArgRepeatOptional; 134 135 // There is only one variant this argument could be; put it into the argument entry. 136 arg.push_back (run_args_arg); 137 138 // Push the data for the first argument into the m_arguments vector. 139 m_arguments.push_back (arg); 140 } 141 142 143 ~CommandObjectProcessLaunch () 144 { 145 } 146 147 virtual int 148 HandleArgumentCompletion (Args &input, 149 int &cursor_index, 150 int &cursor_char_position, 151 OptionElementVector &opt_element_vector, 152 int match_start_point, 153 int max_return_elements, 154 bool &word_complete, 155 StringList &matches) 156 { 157 std::string completion_str (input.GetArgumentAtIndex(cursor_index)); 158 completion_str.erase (cursor_char_position); 159 160 CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter, 161 CommandCompletions::eDiskFileCompletion, 162 completion_str.c_str(), 163 match_start_point, 164 max_return_elements, 165 NULL, 166 word_complete, 167 matches); 168 return matches.GetSize(); 169 } 170 171 Options * 172 GetOptions () 173 { 174 return &m_options; 175 } 176 177 virtual const char *GetRepeatCommand (Args ¤t_command_args, uint32_t index) 178 { 179 // No repeat for "process launch"... 180 return ""; 181 } 182 183 protected: 184 bool 185 DoExecute (Args& launch_args, CommandReturnObject &result) 186 { 187 Debugger &debugger = m_interpreter.GetDebugger(); 188 Target *target = debugger.GetSelectedTarget().get(); 189 Error error; 190 // If our listener is NULL, users aren't allows to launch 191 char filename[PATH_MAX]; 192 const Module *exe_module = target->GetExecutableModulePointer(); 193 194 if (exe_module == NULL) 195 { 196 result.AppendError ("no file in target, create a debug target using the 'target create' command"); 197 result.SetStatus (eReturnStatusFailed); 198 return false; 199 } 200 201 StateType state = eStateInvalid; 202 Process *process = m_exe_ctx.GetProcessPtr(); 203 204 if (!StopProcessIfNecessary(process, state, result)) 205 return false; 206 207 const char *target_settings_argv0 = target->GetArg0(); 208 209 exe_module->GetFileSpec().GetPath (filename, sizeof(filename)); 210 211 if (target_settings_argv0) 212 { 213 m_options.launch_info.GetArguments().AppendArgument (target_settings_argv0); 214 m_options.launch_info.SetExecutableFile(exe_module->GetPlatformFileSpec(), false); 215 } 216 else 217 { 218 m_options.launch_info.SetExecutableFile(exe_module->GetPlatformFileSpec(), true); 219 } 220 221 if (launch_args.GetArgumentCount() == 0) 222 { 223 Args target_setting_args; 224 if (target->GetRunArguments(target_setting_args)) 225 m_options.launch_info.GetArguments().AppendArguments (target_setting_args); 226 } 227 else 228 { 229 m_options.launch_info.GetArguments().AppendArguments (launch_args); 230 231 // Save the arguments for subsequent runs in the current target. 232 target->SetRunArguments (launch_args); 233 } 234 235 if (target->GetDisableASLR()) 236 m_options.launch_info.GetFlags().Set (eLaunchFlagDisableASLR); 237 238 if (target->GetDisableSTDIO()) 239 m_options.launch_info.GetFlags().Set (eLaunchFlagDisableSTDIO); 240 241 m_options.launch_info.GetFlags().Set (eLaunchFlagDebug); 242 243 Args environment; 244 target->GetEnvironmentAsArgs (environment); 245 if (environment.GetArgumentCount() > 0) 246 m_options.launch_info.GetEnvironmentEntries ().AppendArguments (environment); 247 248 // Get the value of synchronous execution here. If you wait till after you have started to 249 // run, then you could have hit a breakpoint, whose command might switch the value, and 250 // then you'll pick up that incorrect value. 251 bool synchronous_execution = m_interpreter.GetSynchronous (); 252 253 // Finalize the file actions, and if none were given, default to opening 254 // up a pseudo terminal 255 const bool default_to_use_pty = true; 256 m_options.launch_info.FinalizeFileActions (target, default_to_use_pty); 257 258 if (state == eStateConnected) 259 { 260 if (m_options.launch_info.GetFlags().Test (eLaunchFlagLaunchInTTY)) 261 { 262 result.AppendWarning("can't launch in tty when launching through a remote connection"); 263 m_options.launch_info.GetFlags().Clear (eLaunchFlagLaunchInTTY); 264 } 265 } 266 267 if (!m_options.launch_info.GetArchitecture().IsValid()) 268 m_options.launch_info.GetArchitecture() = target->GetArchitecture(); 269 270 PlatformSP platform_sp (target->GetPlatform()); 271 272 if (platform_sp && platform_sp->CanDebugProcess ()) 273 { 274 process = target->GetPlatform()->DebugProcess (m_options.launch_info, 275 debugger, 276 target, 277 debugger.GetListener(), 278 error).get(); 279 } 280 else 281 { 282 const char *plugin_name = m_options.launch_info.GetProcessPluginName(); 283 process = target->CreateProcess (debugger.GetListener(), plugin_name, NULL).get(); 284 if (process) 285 error = process->Launch (m_options.launch_info); 286 } 287 288 if (process == NULL) 289 { 290 result.SetError (error, "failed to launch or debug process"); 291 return false; 292 } 293 294 295 if (error.Success()) 296 { 297 const char *archname = exe_module->GetArchitecture().GetArchitectureName(); 298 299 result.AppendMessageWithFormat ("Process %" PRIu64 " launched: '%s' (%s)\n", process->GetID(), filename, archname); 300 result.SetDidChangeProcessState (true); 301 if (m_options.launch_info.GetFlags().Test(eLaunchFlagStopAtEntry) == false) 302 { 303 result.SetStatus (eReturnStatusSuccessContinuingNoResult); 304 StateType state = process->WaitForProcessToStop (NULL); 305 306 if (state == eStateStopped) 307 { 308 error = process->Resume(); 309 if (error.Success()) 310 { 311 if (synchronous_execution) 312 { 313 state = process->WaitForProcessToStop (NULL); 314 const bool must_be_alive = true; 315 if (!StateIsStoppedState(state, must_be_alive)) 316 { 317 result.AppendErrorWithFormat ("process isn't stopped: %s", StateAsCString(state)); 318 } 319 result.SetDidChangeProcessState (true); 320 result.SetStatus (eReturnStatusSuccessFinishResult); 321 } 322 else 323 { 324 result.SetStatus (eReturnStatusSuccessContinuingNoResult); 325 } 326 } 327 else 328 { 329 result.AppendErrorWithFormat ("process resume at entry point failed: %s", error.AsCString()); 330 result.SetStatus (eReturnStatusFailed); 331 } 332 } 333 else 334 { 335 result.AppendErrorWithFormat ("initial process state wasn't stopped: %s", StateAsCString(state)); 336 result.SetStatus (eReturnStatusFailed); 337 } 338 } 339 } 340 else 341 { 342 result.AppendErrorWithFormat ("process launch failed: %s", error.AsCString()); 343 result.SetStatus (eReturnStatusFailed); 344 } 345 346 return result.Succeeded(); 347 } 348 349 protected: 350 ProcessLaunchCommandOptions m_options; 351 }; 352 353 354 //#define SET1 LLDB_OPT_SET_1 355 //#define SET2 LLDB_OPT_SET_2 356 //#define SET3 LLDB_OPT_SET_3 357 // 358 //OptionDefinition 359 //CommandObjectProcessLaunch::CommandOptions::g_option_table[] = 360 //{ 361 //{ 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."}, 362 //{ SET1 , false, "stdin", 'i', required_argument, NULL, 0, eArgTypeDirectoryName, "Redirect stdin for the process to <path>."}, 363 //{ SET1 , false, "stdout", 'o', required_argument, NULL, 0, eArgTypeDirectoryName, "Redirect stdout for the process to <path>."}, 364 //{ SET1 , false, "stderr", 'e', required_argument, NULL, 0, eArgTypeDirectoryName, "Redirect stderr for the process to <path>."}, 365 //{ SET1 | SET2 | SET3, false, "plugin", 'p', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."}, 366 //{ 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."}, 367 //{ SET3, false, "no-stdio", 'n', no_argument, NULL, 0, eArgTypeNone, "Do not set up for terminal I/O to go to running process."}, 368 //{ SET1 | SET2 | SET3, false, "working-dir", 'w', required_argument, NULL, 0, eArgTypeDirectoryName, "Set the current working directory to <path> when running the inferior."}, 369 //{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 370 //}; 371 // 372 //#undef SET1 373 //#undef SET2 374 //#undef SET3 375 376 //------------------------------------------------------------------------- 377 // CommandObjectProcessAttach 378 //------------------------------------------------------------------------- 379 #pragma mark CommandObjectProcessAttach 380 class CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach 381 { 382 public: 383 384 class CommandOptions : public Options 385 { 386 public: 387 388 CommandOptions (CommandInterpreter &interpreter) : 389 Options(interpreter) 390 { 391 // Keep default values of all options in one place: OptionParsingStarting () 392 OptionParsingStarting (); 393 } 394 395 ~CommandOptions () 396 { 397 } 398 399 Error 400 SetOptionValue (uint32_t option_idx, const char *option_arg) 401 { 402 Error error; 403 const int short_option = m_getopt_table[option_idx].val; 404 bool success = false; 405 switch (short_option) 406 { 407 case 'c': 408 attach_info.SetContinueOnceAttached(true); 409 break; 410 411 case 'p': 412 { 413 lldb::pid_t pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success); 414 if (!success || pid == LLDB_INVALID_PROCESS_ID) 415 { 416 error.SetErrorStringWithFormat("invalid process ID '%s'", option_arg); 417 } 418 else 419 { 420 attach_info.SetProcessID (pid); 421 } 422 } 423 break; 424 425 case 'P': 426 attach_info.SetProcessPluginName (option_arg); 427 break; 428 429 case 'n': 430 attach_info.GetExecutableFile().SetFile(option_arg, false); 431 break; 432 433 case 'w': 434 attach_info.SetWaitForLaunch(true); 435 break; 436 437 case 'i': 438 attach_info.SetIgnoreExisting(false); 439 break; 440 441 default: 442 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 443 break; 444 } 445 return error; 446 } 447 448 void 449 OptionParsingStarting () 450 { 451 attach_info.Clear(); 452 } 453 454 const OptionDefinition* 455 GetDefinitions () 456 { 457 return g_option_table; 458 } 459 460 virtual bool 461 HandleOptionArgumentCompletion (Args &input, 462 int cursor_index, 463 int char_pos, 464 OptionElementVector &opt_element_vector, 465 int opt_element_index, 466 int match_start_point, 467 int max_return_elements, 468 bool &word_complete, 469 StringList &matches) 470 { 471 int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos; 472 int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index; 473 474 // We are only completing the name option for now... 475 476 const OptionDefinition *opt_defs = GetDefinitions(); 477 if (opt_defs[opt_defs_index].short_option == 'n') 478 { 479 // Are we in the name? 480 481 // Look to see if there is a -P argument provided, and if so use that plugin, otherwise 482 // use the default plugin. 483 484 const char *partial_name = NULL; 485 partial_name = input.GetArgumentAtIndex(opt_arg_pos); 486 487 PlatformSP platform_sp (m_interpreter.GetPlatform (true)); 488 if (platform_sp) 489 { 490 ProcessInstanceInfoList process_infos; 491 ProcessInstanceInfoMatch match_info; 492 if (partial_name) 493 { 494 match_info.GetProcessInfo().GetExecutableFile().SetFile(partial_name, false); 495 match_info.SetNameMatchType(eNameMatchStartsWith); 496 } 497 platform_sp->FindProcesses (match_info, process_infos); 498 const size_t num_matches = process_infos.GetSize(); 499 if (num_matches > 0) 500 { 501 for (size_t i=0; i<num_matches; ++i) 502 { 503 matches.AppendString (process_infos.GetProcessNameAtIndex(i), 504 process_infos.GetProcessNameLengthAtIndex(i)); 505 } 506 } 507 } 508 } 509 510 return false; 511 } 512 513 // Options table: Required for subclasses of Options. 514 515 static OptionDefinition g_option_table[]; 516 517 // Instance variables to hold the values for command options. 518 519 ProcessAttachInfo attach_info; 520 }; 521 522 CommandObjectProcessAttach (CommandInterpreter &interpreter) : 523 CommandObjectProcessLaunchOrAttach (interpreter, 524 "process attach", 525 "Attach to a process.", 526 "process attach <cmd-options>", 527 0, 528 "attach"), 529 m_options (interpreter) 530 { 531 } 532 533 ~CommandObjectProcessAttach () 534 { 535 } 536 537 Options * 538 GetOptions () 539 { 540 return &m_options; 541 } 542 543 protected: 544 bool 545 DoExecute (Args& command, 546 CommandReturnObject &result) 547 { 548 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 549 // N.B. The attach should be synchronous. It doesn't help much to get the prompt back between initiating the attach 550 // and the target actually stopping. So even if the interpreter is set to be asynchronous, we wait for the stop 551 // ourselves here. 552 553 StateType state = eStateInvalid; 554 Process *process = m_exe_ctx.GetProcessPtr(); 555 556 if (!StopProcessIfNecessary (process, state, result)) 557 return false; 558 559 if (target == NULL) 560 { 561 // If there isn't a current target create one. 562 TargetSP new_target_sp; 563 Error error; 564 565 error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(), 566 NULL, 567 NULL, 568 false, 569 NULL, // No platform options 570 new_target_sp); 571 target = new_target_sp.get(); 572 if (target == NULL || error.Fail()) 573 { 574 result.AppendError(error.AsCString("Error creating target")); 575 return false; 576 } 577 m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target); 578 } 579 580 // Record the old executable module, we want to issue a warning if the process of attaching changed the 581 // current executable (like somebody said "file foo" then attached to a PID whose executable was bar.) 582 583 ModuleSP old_exec_module_sp = target->GetExecutableModule(); 584 ArchSpec old_arch_spec = target->GetArchitecture(); 585 586 if (command.GetArgumentCount()) 587 { 588 result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: %s\n", m_cmd_name.c_str(), m_cmd_syntax.c_str()); 589 result.SetStatus (eReturnStatusFailed); 590 } 591 else 592 { 593 if (state != eStateConnected) 594 { 595 const char *plugin_name = m_options.attach_info.GetProcessPluginName(); 596 process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name, NULL).get(); 597 } 598 599 if (process) 600 { 601 Error error; 602 // If no process info was specified, then use the target executable 603 // name as the process to attach to by default 604 if (!m_options.attach_info.ProcessInfoSpecified ()) 605 { 606 if (old_exec_module_sp) 607 m_options.attach_info.GetExecutableFile().GetFilename() = old_exec_module_sp->GetPlatformFileSpec().GetFilename(); 608 609 if (!m_options.attach_info.ProcessInfoSpecified ()) 610 { 611 error.SetErrorString ("no process specified, create a target with a file, or specify the --pid or --name command option"); 612 } 613 } 614 615 if (error.Success()) 616 { 617 error = process->Attach (m_options.attach_info); 618 619 if (error.Success()) 620 { 621 result.SetStatus (eReturnStatusSuccessContinuingNoResult); 622 } 623 else 624 { 625 result.AppendErrorWithFormat ("attach failed: %s\n", error.AsCString()); 626 result.SetStatus (eReturnStatusFailed); 627 return false; 628 } 629 // If we're synchronous, wait for the stopped event and report that. 630 // Otherwise just return. 631 // FIXME: in the async case it will now be possible to get to the command 632 // interpreter with a state eStateAttaching. Make sure we handle that correctly. 633 StateType state = process->WaitForProcessToStop (NULL); 634 635 result.SetDidChangeProcessState (true); 636 637 if (state == eStateStopped) 638 { 639 result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state)); 640 result.SetStatus (eReturnStatusSuccessFinishNoResult); 641 } 642 else 643 { 644 result.AppendError ("attach failed: process did not stop (no such process or permission problem?)"); 645 process->Destroy(); 646 result.SetStatus (eReturnStatusFailed); 647 return false; 648 } 649 } 650 } 651 } 652 653 if (result.Succeeded()) 654 { 655 // Okay, we're done. Last step is to warn if the executable module has changed: 656 char new_path[PATH_MAX]; 657 ModuleSP new_exec_module_sp (target->GetExecutableModule()); 658 if (!old_exec_module_sp) 659 { 660 // We might not have a module if we attached to a raw pid... 661 if (new_exec_module_sp) 662 { 663 new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX); 664 result.AppendMessageWithFormat("Executable module set to \"%s\".\n", new_path); 665 } 666 } 667 else if (old_exec_module_sp->GetFileSpec() != new_exec_module_sp->GetFileSpec()) 668 { 669 char old_path[PATH_MAX]; 670 671 old_exec_module_sp->GetFileSpec().GetPath (old_path, PATH_MAX); 672 new_exec_module_sp->GetFileSpec().GetPath (new_path, PATH_MAX); 673 674 result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n", 675 old_path, new_path); 676 } 677 678 if (!old_arch_spec.IsValid()) 679 { 680 result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().GetTriple().getTriple().c_str()); 681 } 682 else if (!old_arch_spec.IsExactMatch(target->GetArchitecture())) 683 { 684 result.AppendWarningWithFormat("Architecture changed from %s to %s.\n", 685 old_arch_spec.GetTriple().getTriple().c_str(), 686 target->GetArchitecture().GetTriple().getTriple().c_str()); 687 } 688 689 // This supports the use-case scenario of immediately continuing the process once attached. 690 if (m_options.attach_info.GetContinueOnceAttached()) 691 m_interpreter.HandleCommand("process continue", eLazyBoolNo, result); 692 } 693 return result.Succeeded(); 694 } 695 696 CommandOptions m_options; 697 }; 698 699 700 OptionDefinition 701 CommandObjectProcessAttach::CommandOptions::g_option_table[] = 702 { 703 { LLDB_OPT_SET_ALL, false, "continue",'c', no_argument, NULL, 0, eArgTypeNone, "Immediately continue the process once attached."}, 704 { LLDB_OPT_SET_ALL, false, "plugin", 'P', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."}, 705 { LLDB_OPT_SET_1, false, "pid", 'p', required_argument, NULL, 0, eArgTypePid, "The process ID of an existing process to attach to."}, 706 { LLDB_OPT_SET_2, false, "name", 'n', required_argument, NULL, 0, eArgTypeProcessName, "The name of the process to attach to."}, 707 { LLDB_OPT_SET_2, false, "include-existing", 'i', no_argument, NULL, 0, eArgTypeNone, "Include existing processes when doing attach -w."}, 708 { LLDB_OPT_SET_2, false, "waitfor", 'w', no_argument, NULL, 0, eArgTypeNone, "Wait for the process with <process-name> to launch."}, 709 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 710 }; 711 712 //------------------------------------------------------------------------- 713 // CommandObjectProcessContinue 714 //------------------------------------------------------------------------- 715 #pragma mark CommandObjectProcessContinue 716 717 class CommandObjectProcessContinue : public CommandObjectParsed 718 { 719 public: 720 721 CommandObjectProcessContinue (CommandInterpreter &interpreter) : 722 CommandObjectParsed (interpreter, 723 "process continue", 724 "Continue execution of all threads in the current process.", 725 "process continue", 726 eFlagRequiresProcess | 727 eFlagTryTargetAPILock | 728 eFlagProcessMustBeLaunched | 729 eFlagProcessMustBePaused ), 730 m_options(interpreter) 731 { 732 } 733 734 735 ~CommandObjectProcessContinue () 736 { 737 } 738 739 protected: 740 741 class CommandOptions : public Options 742 { 743 public: 744 745 CommandOptions (CommandInterpreter &interpreter) : 746 Options(interpreter) 747 { 748 // Keep default values of all options in one place: OptionParsingStarting () 749 OptionParsingStarting (); 750 } 751 752 ~CommandOptions () 753 { 754 } 755 756 Error 757 SetOptionValue (uint32_t option_idx, const char *option_arg) 758 { 759 Error error; 760 const int short_option = m_getopt_table[option_idx].val; 761 bool success = false; 762 switch (short_option) 763 { 764 case 'i': 765 m_ignore = Args::StringToUInt32 (option_arg, 0, 0, &success); 766 if (!success) 767 error.SetErrorStringWithFormat ("invalid value for ignore option: \"%s\", should be a number.", option_arg); 768 break; 769 770 default: 771 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 772 break; 773 } 774 return error; 775 } 776 777 void 778 OptionParsingStarting () 779 { 780 m_ignore = 0; 781 } 782 783 const OptionDefinition* 784 GetDefinitions () 785 { 786 return g_option_table; 787 } 788 789 // Options table: Required for subclasses of Options. 790 791 static OptionDefinition g_option_table[]; 792 793 uint32_t m_ignore; 794 }; 795 796 bool 797 DoExecute (Args& command, CommandReturnObject &result) 798 { 799 Process *process = m_exe_ctx.GetProcessPtr(); 800 bool synchronous_execution = m_interpreter.GetSynchronous (); 801 StateType state = process->GetState(); 802 if (state == eStateStopped) 803 { 804 if (command.GetArgumentCount() != 0) 805 { 806 result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str()); 807 result.SetStatus (eReturnStatusFailed); 808 return false; 809 } 810 811 if (m_options.m_ignore > 0) 812 { 813 ThreadSP sel_thread_sp(process->GetThreadList().GetSelectedThread()); 814 if (sel_thread_sp) 815 { 816 StopInfoSP stop_info_sp = sel_thread_sp->GetStopInfo(); 817 if (stop_info_sp && stop_info_sp->GetStopReason() == eStopReasonBreakpoint) 818 { 819 lldb::break_id_t bp_site_id = (lldb::break_id_t)stop_info_sp->GetValue(); 820 BreakpointSiteSP bp_site_sp(process->GetBreakpointSiteList().FindByID(bp_site_id)); 821 if (bp_site_sp) 822 { 823 const size_t num_owners = bp_site_sp->GetNumberOfOwners(); 824 for (size_t i = 0; i < num_owners; i++) 825 { 826 Breakpoint &bp_ref = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint(); 827 if (!bp_ref.IsInternal()) 828 { 829 bp_ref.SetIgnoreCount(m_options.m_ignore); 830 } 831 } 832 } 833 } 834 } 835 } 836 837 { // Scope for thread list mutex: 838 Mutex::Locker locker (process->GetThreadList().GetMutex()); 839 const uint32_t num_threads = process->GetThreadList().GetSize(); 840 841 // Set the actions that the threads should each take when resuming 842 for (uint32_t idx=0; idx<num_threads; ++idx) 843 { 844 process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning); 845 } 846 } 847 848 Error error(process->Resume()); 849 if (error.Success()) 850 { 851 result.AppendMessageWithFormat ("Process %" PRIu64 " resuming\n", process->GetID()); 852 if (synchronous_execution) 853 { 854 state = process->WaitForProcessToStop (NULL); 855 856 result.SetDidChangeProcessState (true); 857 result.AppendMessageWithFormat ("Process %" PRIu64 " %s\n", process->GetID(), StateAsCString (state)); 858 result.SetStatus (eReturnStatusSuccessFinishNoResult); 859 } 860 else 861 { 862 result.SetStatus (eReturnStatusSuccessContinuingNoResult); 863 } 864 } 865 else 866 { 867 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString()); 868 result.SetStatus (eReturnStatusFailed); 869 } 870 } 871 else 872 { 873 result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n", 874 StateAsCString(state)); 875 result.SetStatus (eReturnStatusFailed); 876 } 877 return result.Succeeded(); 878 } 879 880 Options * 881 GetOptions () 882 { 883 return &m_options; 884 } 885 886 CommandOptions m_options; 887 888 }; 889 890 OptionDefinition 891 CommandObjectProcessContinue::CommandOptions::g_option_table[] = 892 { 893 { LLDB_OPT_SET_ALL, false, "ignore-count",'i', required_argument, NULL, 0, eArgTypeUnsignedInteger, 894 "Ignore <N> crossings of the breakpoint (if it exists) for the currently selected thread."}, 895 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 896 }; 897 898 //------------------------------------------------------------------------- 899 // CommandObjectProcessDetach 900 //------------------------------------------------------------------------- 901 #pragma mark CommandObjectProcessDetach 902 903 class CommandObjectProcessDetach : public CommandObjectParsed 904 { 905 public: 906 907 CommandObjectProcessDetach (CommandInterpreter &interpreter) : 908 CommandObjectParsed (interpreter, 909 "process detach", 910 "Detach from the current process being debugged.", 911 "process detach", 912 eFlagRequiresProcess | 913 eFlagTryTargetAPILock | 914 eFlagProcessMustBeLaunched) 915 { 916 } 917 918 ~CommandObjectProcessDetach () 919 { 920 } 921 922 protected: 923 bool 924 DoExecute (Args& command, CommandReturnObject &result) 925 { 926 Process *process = m_exe_ctx.GetProcessPtr(); 927 result.AppendMessageWithFormat ("Detaching from process %" PRIu64 "\n", process->GetID()); 928 Error error (process->Detach()); 929 if (error.Success()) 930 { 931 result.SetStatus (eReturnStatusSuccessFinishResult); 932 } 933 else 934 { 935 result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString()); 936 result.SetStatus (eReturnStatusFailed); 937 return false; 938 } 939 return result.Succeeded(); 940 } 941 }; 942 943 //------------------------------------------------------------------------- 944 // CommandObjectProcessConnect 945 //------------------------------------------------------------------------- 946 #pragma mark CommandObjectProcessConnect 947 948 class CommandObjectProcessConnect : public CommandObjectParsed 949 { 950 public: 951 952 class CommandOptions : public Options 953 { 954 public: 955 956 CommandOptions (CommandInterpreter &interpreter) : 957 Options(interpreter) 958 { 959 // Keep default values of all options in one place: OptionParsingStarting () 960 OptionParsingStarting (); 961 } 962 963 ~CommandOptions () 964 { 965 } 966 967 Error 968 SetOptionValue (uint32_t option_idx, const char *option_arg) 969 { 970 Error error; 971 const int short_option = m_getopt_table[option_idx].val; 972 973 switch (short_option) 974 { 975 case 'p': 976 plugin_name.assign (option_arg); 977 break; 978 979 default: 980 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 981 break; 982 } 983 return error; 984 } 985 986 void 987 OptionParsingStarting () 988 { 989 plugin_name.clear(); 990 } 991 992 const OptionDefinition* 993 GetDefinitions () 994 { 995 return g_option_table; 996 } 997 998 // Options table: Required for subclasses of Options. 999 1000 static OptionDefinition g_option_table[]; 1001 1002 // Instance variables to hold the values for command options. 1003 1004 std::string plugin_name; 1005 }; 1006 1007 CommandObjectProcessConnect (CommandInterpreter &interpreter) : 1008 CommandObjectParsed (interpreter, 1009 "process connect", 1010 "Connect to a remote debug service.", 1011 "process connect <remote-url>", 1012 0), 1013 m_options (interpreter) 1014 { 1015 } 1016 1017 ~CommandObjectProcessConnect () 1018 { 1019 } 1020 1021 1022 Options * 1023 GetOptions () 1024 { 1025 return &m_options; 1026 } 1027 1028 protected: 1029 bool 1030 DoExecute (Args& command, 1031 CommandReturnObject &result) 1032 { 1033 1034 TargetSP target_sp (m_interpreter.GetDebugger().GetSelectedTarget()); 1035 Error error; 1036 Process *process = m_exe_ctx.GetProcessPtr(); 1037 if (process) 1038 { 1039 if (process->IsAlive()) 1040 { 1041 result.AppendErrorWithFormat ("Process %" PRIu64 " is currently being debugged, kill the process before connecting.\n", 1042 process->GetID()); 1043 result.SetStatus (eReturnStatusFailed); 1044 return false; 1045 } 1046 } 1047 1048 if (!target_sp) 1049 { 1050 // If there isn't a current target create one. 1051 1052 error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(), 1053 NULL, 1054 NULL, 1055 false, 1056 NULL, // No platform options 1057 target_sp); 1058 if (!target_sp || error.Fail()) 1059 { 1060 result.AppendError(error.AsCString("Error creating target")); 1061 result.SetStatus (eReturnStatusFailed); 1062 return false; 1063 } 1064 m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target_sp.get()); 1065 } 1066 1067 if (command.GetArgumentCount() == 1) 1068 { 1069 const char *plugin_name = NULL; 1070 if (!m_options.plugin_name.empty()) 1071 plugin_name = m_options.plugin_name.c_str(); 1072 1073 const char *remote_url = command.GetArgumentAtIndex(0); 1074 process = target_sp->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name, NULL).get(); 1075 1076 if (process) 1077 { 1078 error = process->ConnectRemote (&process->GetTarget().GetDebugger().GetOutputStream(), remote_url); 1079 1080 if (error.Fail()) 1081 { 1082 result.AppendError(error.AsCString("Remote connect failed")); 1083 result.SetStatus (eReturnStatusFailed); 1084 target_sp->DeleteCurrentProcess(); 1085 return false; 1086 } 1087 } 1088 else 1089 { 1090 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", 1091 remote_url); 1092 result.SetStatus (eReturnStatusFailed); 1093 } 1094 } 1095 else 1096 { 1097 result.AppendErrorWithFormat ("'%s' takes exactly one argument:\nUsage: %s\n", 1098 m_cmd_name.c_str(), 1099 m_cmd_syntax.c_str()); 1100 result.SetStatus (eReturnStatusFailed); 1101 } 1102 return result.Succeeded(); 1103 } 1104 1105 CommandOptions m_options; 1106 }; 1107 1108 OptionDefinition 1109 CommandObjectProcessConnect::CommandOptions::g_option_table[] = 1110 { 1111 { LLDB_OPT_SET_ALL, false, "plugin", 'p', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."}, 1112 { 0, false, NULL, 0 , 0, NULL, 0, eArgTypeNone, NULL } 1113 }; 1114 1115 //------------------------------------------------------------------------- 1116 // CommandObjectProcessPlugin 1117 //------------------------------------------------------------------------- 1118 #pragma mark CommandObjectProcessPlugin 1119 1120 class CommandObjectProcessPlugin : public CommandObjectProxy 1121 { 1122 public: 1123 1124 CommandObjectProcessPlugin (CommandInterpreter &interpreter) : 1125 CommandObjectProxy (interpreter, 1126 "process plugin", 1127 "Send a custom command to the current process plug-in.", 1128 "process plugin <args>", 1129 0) 1130 { 1131 } 1132 1133 ~CommandObjectProcessPlugin () 1134 { 1135 } 1136 1137 virtual CommandObject * 1138 GetProxyCommandObject() 1139 { 1140 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr(); 1141 if (process) 1142 return process->GetPluginCommandObject(); 1143 return NULL; 1144 } 1145 }; 1146 1147 1148 //------------------------------------------------------------------------- 1149 // CommandObjectProcessLoad 1150 //------------------------------------------------------------------------- 1151 #pragma mark CommandObjectProcessLoad 1152 1153 class CommandObjectProcessLoad : public CommandObjectParsed 1154 { 1155 public: 1156 1157 CommandObjectProcessLoad (CommandInterpreter &interpreter) : 1158 CommandObjectParsed (interpreter, 1159 "process load", 1160 "Load a shared library into the current process.", 1161 "process load <filename> [<filename> ...]", 1162 eFlagRequiresProcess | 1163 eFlagTryTargetAPILock | 1164 eFlagProcessMustBeLaunched | 1165 eFlagProcessMustBePaused ) 1166 { 1167 } 1168 1169 ~CommandObjectProcessLoad () 1170 { 1171 } 1172 1173 protected: 1174 bool 1175 DoExecute (Args& command, 1176 CommandReturnObject &result) 1177 { 1178 Process *process = m_exe_ctx.GetProcessPtr(); 1179 1180 const size_t argc = command.GetArgumentCount(); 1181 1182 for (uint32_t i=0; i<argc; ++i) 1183 { 1184 Error error; 1185 const char *image_path = command.GetArgumentAtIndex(i); 1186 FileSpec image_spec (image_path, false); 1187 process->GetTarget().GetPlatform()->ResolveRemotePath(image_spec, image_spec); 1188 uint32_t image_token = process->LoadImage(image_spec, error); 1189 if (image_token != LLDB_INVALID_IMAGE_TOKEN) 1190 { 1191 result.AppendMessageWithFormat ("Loading \"%s\"...ok\nImage %u loaded.\n", image_path, image_token); 1192 result.SetStatus (eReturnStatusSuccessFinishResult); 1193 } 1194 else 1195 { 1196 result.AppendErrorWithFormat ("failed to load '%s': %s", image_path, error.AsCString()); 1197 result.SetStatus (eReturnStatusFailed); 1198 } 1199 } 1200 return result.Succeeded(); 1201 } 1202 }; 1203 1204 1205 //------------------------------------------------------------------------- 1206 // CommandObjectProcessUnload 1207 //------------------------------------------------------------------------- 1208 #pragma mark CommandObjectProcessUnload 1209 1210 class CommandObjectProcessUnload : public CommandObjectParsed 1211 { 1212 public: 1213 1214 CommandObjectProcessUnload (CommandInterpreter &interpreter) : 1215 CommandObjectParsed (interpreter, 1216 "process unload", 1217 "Unload a shared library from the current process using the index returned by a previous call to \"process load\".", 1218 "process unload <index>", 1219 eFlagRequiresProcess | 1220 eFlagTryTargetAPILock | 1221 eFlagProcessMustBeLaunched | 1222 eFlagProcessMustBePaused ) 1223 { 1224 } 1225 1226 ~CommandObjectProcessUnload () 1227 { 1228 } 1229 1230 protected: 1231 bool 1232 DoExecute (Args& command, 1233 CommandReturnObject &result) 1234 { 1235 Process *process = m_exe_ctx.GetProcessPtr(); 1236 1237 const size_t argc = command.GetArgumentCount(); 1238 1239 for (uint32_t i=0; i<argc; ++i) 1240 { 1241 const char *image_token_cstr = command.GetArgumentAtIndex(i); 1242 uint32_t image_token = Args::StringToUInt32(image_token_cstr, LLDB_INVALID_IMAGE_TOKEN, 0); 1243 if (image_token == LLDB_INVALID_IMAGE_TOKEN) 1244 { 1245 result.AppendErrorWithFormat ("invalid image index argument '%s'", image_token_cstr); 1246 result.SetStatus (eReturnStatusFailed); 1247 break; 1248 } 1249 else 1250 { 1251 Error error (process->UnloadImage(image_token)); 1252 if (error.Success()) 1253 { 1254 result.AppendMessageWithFormat ("Unloading shared library with index %u...ok\n", image_token); 1255 result.SetStatus (eReturnStatusSuccessFinishResult); 1256 } 1257 else 1258 { 1259 result.AppendErrorWithFormat ("failed to unload image: %s", error.AsCString()); 1260 result.SetStatus (eReturnStatusFailed); 1261 break; 1262 } 1263 } 1264 } 1265 return result.Succeeded(); 1266 } 1267 }; 1268 1269 //------------------------------------------------------------------------- 1270 // CommandObjectProcessSignal 1271 //------------------------------------------------------------------------- 1272 #pragma mark CommandObjectProcessSignal 1273 1274 class CommandObjectProcessSignal : public CommandObjectParsed 1275 { 1276 public: 1277 1278 CommandObjectProcessSignal (CommandInterpreter &interpreter) : 1279 CommandObjectParsed (interpreter, 1280 "process signal", 1281 "Send a UNIX signal to the current process being debugged.", 1282 NULL, 1283 eFlagRequiresProcess | eFlagTryTargetAPILock) 1284 { 1285 CommandArgumentEntry arg; 1286 CommandArgumentData signal_arg; 1287 1288 // Define the first (and only) variant of this arg. 1289 signal_arg.arg_type = eArgTypeUnixSignal; 1290 signal_arg.arg_repetition = eArgRepeatPlain; 1291 1292 // There is only one variant this argument could be; put it into the argument entry. 1293 arg.push_back (signal_arg); 1294 1295 // Push the data for the first argument into the m_arguments vector. 1296 m_arguments.push_back (arg); 1297 } 1298 1299 ~CommandObjectProcessSignal () 1300 { 1301 } 1302 1303 protected: 1304 bool 1305 DoExecute (Args& command, 1306 CommandReturnObject &result) 1307 { 1308 Process *process = m_exe_ctx.GetProcessPtr(); 1309 1310 if (command.GetArgumentCount() == 1) 1311 { 1312 int signo = LLDB_INVALID_SIGNAL_NUMBER; 1313 1314 const char *signal_name = command.GetArgumentAtIndex(0); 1315 if (::isxdigit (signal_name[0])) 1316 signo = Args::StringToSInt32(signal_name, LLDB_INVALID_SIGNAL_NUMBER, 0); 1317 else 1318 signo = process->GetUnixSignals().GetSignalNumberFromName (signal_name); 1319 1320 if (signo == LLDB_INVALID_SIGNAL_NUMBER) 1321 { 1322 result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0)); 1323 result.SetStatus (eReturnStatusFailed); 1324 } 1325 else 1326 { 1327 Error error (process->Signal (signo)); 1328 if (error.Success()) 1329 { 1330 result.SetStatus (eReturnStatusSuccessFinishResult); 1331 } 1332 else 1333 { 1334 result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString()); 1335 result.SetStatus (eReturnStatusFailed); 1336 } 1337 } 1338 } 1339 else 1340 { 1341 result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: %s\n", m_cmd_name.c_str(), 1342 m_cmd_syntax.c_str()); 1343 result.SetStatus (eReturnStatusFailed); 1344 } 1345 return result.Succeeded(); 1346 } 1347 }; 1348 1349 1350 //------------------------------------------------------------------------- 1351 // CommandObjectProcessInterrupt 1352 //------------------------------------------------------------------------- 1353 #pragma mark CommandObjectProcessInterrupt 1354 1355 class CommandObjectProcessInterrupt : public CommandObjectParsed 1356 { 1357 public: 1358 1359 1360 CommandObjectProcessInterrupt (CommandInterpreter &interpreter) : 1361 CommandObjectParsed (interpreter, 1362 "process interrupt", 1363 "Interrupt the current process being debugged.", 1364 "process interrupt", 1365 eFlagRequiresProcess | 1366 eFlagTryTargetAPILock | 1367 eFlagProcessMustBeLaunched) 1368 { 1369 } 1370 1371 ~CommandObjectProcessInterrupt () 1372 { 1373 } 1374 1375 protected: 1376 bool 1377 DoExecute (Args& command, 1378 CommandReturnObject &result) 1379 { 1380 Process *process = m_exe_ctx.GetProcessPtr(); 1381 if (process == NULL) 1382 { 1383 result.AppendError ("no process to halt"); 1384 result.SetStatus (eReturnStatusFailed); 1385 return false; 1386 } 1387 1388 if (command.GetArgumentCount() == 0) 1389 { 1390 Error error(process->Halt ()); 1391 if (error.Success()) 1392 { 1393 result.SetStatus (eReturnStatusSuccessFinishResult); 1394 1395 // Maybe we should add a "SuspendThreadPlans so we 1396 // can halt, and keep in place all the current thread plans. 1397 process->GetThreadList().DiscardThreadPlans(); 1398 } 1399 else 1400 { 1401 result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString()); 1402 result.SetStatus (eReturnStatusFailed); 1403 } 1404 } 1405 else 1406 { 1407 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n", 1408 m_cmd_name.c_str(), 1409 m_cmd_syntax.c_str()); 1410 result.SetStatus (eReturnStatusFailed); 1411 } 1412 return result.Succeeded(); 1413 } 1414 }; 1415 1416 //------------------------------------------------------------------------- 1417 // CommandObjectProcessKill 1418 //------------------------------------------------------------------------- 1419 #pragma mark CommandObjectProcessKill 1420 1421 class CommandObjectProcessKill : public CommandObjectParsed 1422 { 1423 public: 1424 1425 CommandObjectProcessKill (CommandInterpreter &interpreter) : 1426 CommandObjectParsed (interpreter, 1427 "process kill", 1428 "Terminate the current process being debugged.", 1429 "process kill", 1430 eFlagRequiresProcess | 1431 eFlagTryTargetAPILock | 1432 eFlagProcessMustBeLaunched) 1433 { 1434 } 1435 1436 ~CommandObjectProcessKill () 1437 { 1438 } 1439 1440 protected: 1441 bool 1442 DoExecute (Args& command, 1443 CommandReturnObject &result) 1444 { 1445 Process *process = m_exe_ctx.GetProcessPtr(); 1446 if (process == NULL) 1447 { 1448 result.AppendError ("no process to kill"); 1449 result.SetStatus (eReturnStatusFailed); 1450 return false; 1451 } 1452 1453 if (command.GetArgumentCount() == 0) 1454 { 1455 Error error (process->Destroy()); 1456 if (error.Success()) 1457 { 1458 result.SetStatus (eReturnStatusSuccessFinishResult); 1459 } 1460 else 1461 { 1462 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString()); 1463 result.SetStatus (eReturnStatusFailed); 1464 } 1465 } 1466 else 1467 { 1468 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n", 1469 m_cmd_name.c_str(), 1470 m_cmd_syntax.c_str()); 1471 result.SetStatus (eReturnStatusFailed); 1472 } 1473 return result.Succeeded(); 1474 } 1475 }; 1476 1477 //------------------------------------------------------------------------- 1478 // CommandObjectProcessStatus 1479 //------------------------------------------------------------------------- 1480 #pragma mark CommandObjectProcessStatus 1481 1482 class CommandObjectProcessStatus : public CommandObjectParsed 1483 { 1484 public: 1485 CommandObjectProcessStatus (CommandInterpreter &interpreter) : 1486 CommandObjectParsed (interpreter, 1487 "process status", 1488 "Show the current status and location of executing process.", 1489 "process status", 1490 eFlagRequiresProcess | eFlagTryTargetAPILock) 1491 { 1492 } 1493 1494 ~CommandObjectProcessStatus() 1495 { 1496 } 1497 1498 1499 bool 1500 DoExecute (Args& command, CommandReturnObject &result) 1501 { 1502 Stream &strm = result.GetOutputStream(); 1503 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1504 // No need to check "process" for validity as eFlagRequiresProcess ensures it is valid 1505 Process *process = m_exe_ctx.GetProcessPtr(); 1506 const bool only_threads_with_stop_reason = true; 1507 const uint32_t start_frame = 0; 1508 const uint32_t num_frames = 1; 1509 const uint32_t num_frames_with_source = 1; 1510 process->GetStatus(strm); 1511 process->GetThreadStatus (strm, 1512 only_threads_with_stop_reason, 1513 start_frame, 1514 num_frames, 1515 num_frames_with_source); 1516 return result.Succeeded(); 1517 } 1518 }; 1519 1520 //------------------------------------------------------------------------- 1521 // CommandObjectProcessHandle 1522 //------------------------------------------------------------------------- 1523 #pragma mark CommandObjectProcessHandle 1524 1525 class CommandObjectProcessHandle : public CommandObjectParsed 1526 { 1527 public: 1528 1529 class CommandOptions : public Options 1530 { 1531 public: 1532 1533 CommandOptions (CommandInterpreter &interpreter) : 1534 Options (interpreter) 1535 { 1536 OptionParsingStarting (); 1537 } 1538 1539 ~CommandOptions () 1540 { 1541 } 1542 1543 Error 1544 SetOptionValue (uint32_t option_idx, const char *option_arg) 1545 { 1546 Error error; 1547 const int short_option = m_getopt_table[option_idx].val; 1548 1549 switch (short_option) 1550 { 1551 case 's': 1552 stop = option_arg; 1553 break; 1554 case 'n': 1555 notify = option_arg; 1556 break; 1557 case 'p': 1558 pass = option_arg; 1559 break; 1560 default: 1561 error.SetErrorStringWithFormat("invalid short option character '%c'", short_option); 1562 break; 1563 } 1564 return error; 1565 } 1566 1567 void 1568 OptionParsingStarting () 1569 { 1570 stop.clear(); 1571 notify.clear(); 1572 pass.clear(); 1573 } 1574 1575 const OptionDefinition* 1576 GetDefinitions () 1577 { 1578 return g_option_table; 1579 } 1580 1581 // Options table: Required for subclasses of Options. 1582 1583 static OptionDefinition g_option_table[]; 1584 1585 // Instance variables to hold the values for command options. 1586 1587 std::string stop; 1588 std::string notify; 1589 std::string pass; 1590 }; 1591 1592 1593 CommandObjectProcessHandle (CommandInterpreter &interpreter) : 1594 CommandObjectParsed (interpreter, 1595 "process handle", 1596 "Show or update what the process and debugger should do with various signals received from the OS.", 1597 NULL), 1598 m_options (interpreter) 1599 { 1600 SetHelpLong ("If no signals are specified, update them all. If no update option is specified, list the current values.\n"); 1601 CommandArgumentEntry arg; 1602 CommandArgumentData signal_arg; 1603 1604 signal_arg.arg_type = eArgTypeUnixSignal; 1605 signal_arg.arg_repetition = eArgRepeatStar; 1606 1607 arg.push_back (signal_arg); 1608 1609 m_arguments.push_back (arg); 1610 } 1611 1612 ~CommandObjectProcessHandle () 1613 { 1614 } 1615 1616 Options * 1617 GetOptions () 1618 { 1619 return &m_options; 1620 } 1621 1622 bool 1623 VerifyCommandOptionValue (const std::string &option, int &real_value) 1624 { 1625 bool okay = true; 1626 1627 bool success = false; 1628 bool tmp_value = Args::StringToBoolean (option.c_str(), false, &success); 1629 1630 if (success && tmp_value) 1631 real_value = 1; 1632 else if (success && !tmp_value) 1633 real_value = 0; 1634 else 1635 { 1636 // If the value isn't 'true' or 'false', it had better be 0 or 1. 1637 real_value = Args::StringToUInt32 (option.c_str(), 3); 1638 if (real_value != 0 && real_value != 1) 1639 okay = false; 1640 } 1641 1642 return okay; 1643 } 1644 1645 void 1646 PrintSignalHeader (Stream &str) 1647 { 1648 str.Printf ("NAME PASS STOP NOTIFY\n"); 1649 str.Printf ("========== ===== ===== ======\n"); 1650 } 1651 1652 void 1653 PrintSignal (Stream &str, int32_t signo, const char *sig_name, UnixSignals &signals) 1654 { 1655 bool stop; 1656 bool suppress; 1657 bool notify; 1658 1659 str.Printf ("%-10s ", sig_name); 1660 if (signals.GetSignalInfo (signo, suppress, stop, notify)) 1661 { 1662 bool pass = !suppress; 1663 str.Printf ("%s %s %s", 1664 (pass ? "true " : "false"), 1665 (stop ? "true " : "false"), 1666 (notify ? "true " : "false")); 1667 } 1668 str.Printf ("\n"); 1669 } 1670 1671 void 1672 PrintSignalInformation (Stream &str, Args &signal_args, int num_valid_signals, UnixSignals &signals) 1673 { 1674 PrintSignalHeader (str); 1675 1676 if (num_valid_signals > 0) 1677 { 1678 size_t num_args = signal_args.GetArgumentCount(); 1679 for (size_t i = 0; i < num_args; ++i) 1680 { 1681 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i)); 1682 if (signo != LLDB_INVALID_SIGNAL_NUMBER) 1683 PrintSignal (str, signo, signal_args.GetArgumentAtIndex (i), signals); 1684 } 1685 } 1686 else // Print info for ALL signals 1687 { 1688 int32_t signo = signals.GetFirstSignalNumber(); 1689 while (signo != LLDB_INVALID_SIGNAL_NUMBER) 1690 { 1691 PrintSignal (str, signo, signals.GetSignalAsCString (signo), signals); 1692 signo = signals.GetNextSignalNumber (signo); 1693 } 1694 } 1695 } 1696 1697 protected: 1698 bool 1699 DoExecute (Args &signal_args, CommandReturnObject &result) 1700 { 1701 TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget(); 1702 1703 if (!target_sp) 1704 { 1705 result.AppendError ("No current target;" 1706 " cannot handle signals until you have a valid target and process.\n"); 1707 result.SetStatus (eReturnStatusFailed); 1708 return false; 1709 } 1710 1711 ProcessSP process_sp = target_sp->GetProcessSP(); 1712 1713 if (!process_sp) 1714 { 1715 result.AppendError ("No current process; cannot handle signals until you have a valid process.\n"); 1716 result.SetStatus (eReturnStatusFailed); 1717 return false; 1718 } 1719 1720 int stop_action = -1; // -1 means leave the current setting alone 1721 int pass_action = -1; // -1 means leave the current setting alone 1722 int notify_action = -1; // -1 means leave the current setting alone 1723 1724 if (! m_options.stop.empty() 1725 && ! VerifyCommandOptionValue (m_options.stop, stop_action)) 1726 { 1727 result.AppendError ("Invalid argument for command option --stop; must be true or false.\n"); 1728 result.SetStatus (eReturnStatusFailed); 1729 return false; 1730 } 1731 1732 if (! m_options.notify.empty() 1733 && ! VerifyCommandOptionValue (m_options.notify, notify_action)) 1734 { 1735 result.AppendError ("Invalid argument for command option --notify; must be true or false.\n"); 1736 result.SetStatus (eReturnStatusFailed); 1737 return false; 1738 } 1739 1740 if (! m_options.pass.empty() 1741 && ! VerifyCommandOptionValue (m_options.pass, pass_action)) 1742 { 1743 result.AppendError ("Invalid argument for command option --pass; must be true or false.\n"); 1744 result.SetStatus (eReturnStatusFailed); 1745 return false; 1746 } 1747 1748 size_t num_args = signal_args.GetArgumentCount(); 1749 UnixSignals &signals = process_sp->GetUnixSignals(); 1750 int num_signals_set = 0; 1751 1752 if (num_args > 0) 1753 { 1754 for (size_t i = 0; i < num_args; ++i) 1755 { 1756 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i)); 1757 if (signo != LLDB_INVALID_SIGNAL_NUMBER) 1758 { 1759 // Casting the actions as bools here should be okay, because VerifyCommandOptionValue guarantees 1760 // the value is either 0 or 1. 1761 if (stop_action != -1) 1762 signals.SetShouldStop (signo, (bool) stop_action); 1763 if (pass_action != -1) 1764 { 1765 bool suppress = ! ((bool) pass_action); 1766 signals.SetShouldSuppress (signo, suppress); 1767 } 1768 if (notify_action != -1) 1769 signals.SetShouldNotify (signo, (bool) notify_action); 1770 ++num_signals_set; 1771 } 1772 else 1773 { 1774 result.AppendErrorWithFormat ("Invalid signal name '%s'\n", signal_args.GetArgumentAtIndex (i)); 1775 } 1776 } 1777 } 1778 else 1779 { 1780 // No signal specified, if any command options were specified, update ALL signals. 1781 if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1)) 1782 { 1783 if (m_interpreter.Confirm ("Do you really want to update all the signals?", false)) 1784 { 1785 int32_t signo = signals.GetFirstSignalNumber(); 1786 while (signo != LLDB_INVALID_SIGNAL_NUMBER) 1787 { 1788 if (notify_action != -1) 1789 signals.SetShouldNotify (signo, (bool) notify_action); 1790 if (stop_action != -1) 1791 signals.SetShouldStop (signo, (bool) stop_action); 1792 if (pass_action != -1) 1793 { 1794 bool suppress = ! ((bool) pass_action); 1795 signals.SetShouldSuppress (signo, suppress); 1796 } 1797 signo = signals.GetNextSignalNumber (signo); 1798 } 1799 } 1800 } 1801 } 1802 1803 PrintSignalInformation (result.GetOutputStream(), signal_args, num_signals_set, signals); 1804 1805 if (num_signals_set > 0) 1806 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1807 else 1808 result.SetStatus (eReturnStatusFailed); 1809 1810 return result.Succeeded(); 1811 } 1812 1813 CommandOptions m_options; 1814 }; 1815 1816 OptionDefinition 1817 CommandObjectProcessHandle::CommandOptions::g_option_table[] = 1818 { 1819 { 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." }, 1820 { 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." }, 1821 { LLDB_OPT_SET_1, false, "pass", 'p', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." }, 1822 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 1823 }; 1824 1825 //------------------------------------------------------------------------- 1826 // CommandObjectMultiwordProcess 1827 //------------------------------------------------------------------------- 1828 1829 CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter &interpreter) : 1830 CommandObjectMultiword (interpreter, 1831 "process", 1832 "A set of commands for operating on a process.", 1833 "process <subcommand> [<subcommand-options>]") 1834 { 1835 LoadSubCommand ("attach", CommandObjectSP (new CommandObjectProcessAttach (interpreter))); 1836 LoadSubCommand ("launch", CommandObjectSP (new CommandObjectProcessLaunch (interpreter))); 1837 LoadSubCommand ("continue", CommandObjectSP (new CommandObjectProcessContinue (interpreter))); 1838 LoadSubCommand ("connect", CommandObjectSP (new CommandObjectProcessConnect (interpreter))); 1839 LoadSubCommand ("detach", CommandObjectSP (new CommandObjectProcessDetach (interpreter))); 1840 LoadSubCommand ("load", CommandObjectSP (new CommandObjectProcessLoad (interpreter))); 1841 LoadSubCommand ("unload", CommandObjectSP (new CommandObjectProcessUnload (interpreter))); 1842 LoadSubCommand ("signal", CommandObjectSP (new CommandObjectProcessSignal (interpreter))); 1843 LoadSubCommand ("handle", CommandObjectSP (new CommandObjectProcessHandle (interpreter))); 1844 LoadSubCommand ("status", CommandObjectSP (new CommandObjectProcessStatus (interpreter))); 1845 LoadSubCommand ("interrupt", CommandObjectSP (new CommandObjectProcessInterrupt (interpreter))); 1846 LoadSubCommand ("kill", CommandObjectSP (new CommandObjectProcessKill (interpreter))); 1847 LoadSubCommand ("plugin", CommandObjectSP (new CommandObjectProcessPlugin (interpreter))); 1848 } 1849 1850 CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess () 1851 { 1852 } 1853 1854