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