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/Interpreter/CommandInterpreter.h" 20 #include "lldb/Interpreter/CommandReturnObject.h" 21 #include "./CommandObjectThread.h" 22 #include "lldb/Target/Process.h" 23 #include "lldb/Target/Target.h" 24 #include "lldb/Target/Thread.h" 25 26 using namespace lldb; 27 using namespace lldb_private; 28 29 //------------------------------------------------------------------------- 30 // CommandObjectProcessLaunch 31 //------------------------------------------------------------------------- 32 33 class CommandObjectProcessLaunch : public CommandObject 34 { 35 public: 36 37 class CommandOptions : public Options 38 { 39 public: 40 41 CommandOptions () : 42 Options() 43 { 44 // Keep default values of all options in one place: ResetOptionValues () 45 ResetOptionValues (); 46 } 47 48 ~CommandOptions () 49 { 50 } 51 52 Error 53 SetOptionValue (int option_idx, const char *option_arg) 54 { 55 Error error; 56 char short_option = (char) m_getopt_table[option_idx].val; 57 58 switch (short_option) 59 { 60 case 's': stop_at_entry = true; break; 61 case 'e': stderr_path = option_arg; break; 62 case 'i': stdin_path = option_arg; break; 63 case 'o': stdout_path = option_arg; break; 64 case 'p': plugin_name = option_arg; break; 65 default: 66 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option); 67 break; 68 69 } 70 return error; 71 } 72 73 void 74 ResetOptionValues () 75 { 76 Options::ResetOptionValues(); 77 stop_at_entry = false; 78 stdin_path.clear(); 79 stdout_path.clear(); 80 stderr_path.clear(); 81 plugin_name.clear(); 82 } 83 84 const lldb::OptionDefinition* 85 GetDefinitions () 86 { 87 return g_option_table; 88 } 89 90 // Options table: Required for subclasses of Options. 91 92 static lldb::OptionDefinition g_option_table[]; 93 94 // Instance variables to hold the values for command options. 95 96 bool stop_at_entry; 97 std::string stderr_path; 98 std::string stdin_path; 99 std::string stdout_path; 100 std::string plugin_name; 101 102 }; 103 104 CommandObjectProcessLaunch () : 105 CommandObject ("process launch", 106 "Launch the executable in the debugger.", 107 "process launch [<cmd-options>] [<arguments-for-running-the-program>]") 108 { 109 } 110 111 112 ~CommandObjectProcessLaunch () 113 { 114 } 115 116 Options * 117 GetOptions () 118 { 119 return &m_options; 120 } 121 122 bool 123 Execute (CommandInterpreter &interpreter, 124 Args& launch_args, 125 CommandReturnObject &result) 126 { 127 Target *target = interpreter.GetDebugger().GetSelectedTarget().get(); 128 bool synchronous_execution = interpreter.GetSynchronous (); 129 // bool launched = false; 130 // bool stopped_after_launch = false; 131 132 if (target == NULL) 133 { 134 result.AppendError ("invalid target, set executable file using 'file' command"); 135 result.SetStatus (eReturnStatusFailed); 136 return false; 137 } 138 139 // If our listener is NULL, users aren't allows to launch 140 char filename[PATH_MAX]; 141 Module *exe_module = target->GetExecutableModule().get(); 142 exe_module->GetFileSpec().GetPath(filename, sizeof(filename)); 143 144 Process *process = interpreter.GetDebugger().GetExecutionContext().process; 145 if (process) 146 { 147 if (process->IsAlive()) 148 { 149 result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before running again.\n", 150 process->GetID()); 151 result.SetStatus (eReturnStatusFailed); 152 return false; 153 } 154 } 155 156 const char *plugin_name; 157 if (!m_options.plugin_name.empty()) 158 plugin_name = m_options.plugin_name.c_str(); 159 else 160 plugin_name = NULL; 161 162 process = target->CreateProcess (interpreter.GetDebugger().GetListener(), plugin_name).get(); 163 164 const char *process_name = process->GetInstanceName().AsCString(); 165 const char *debugger_instance_name = interpreter.GetDebugger().GetInstanceName().AsCString(); 166 StreamString run_args_var_name; 167 StreamString env_vars_var_name; 168 StreamString disable_aslr_var_name; 169 lldb::SettableVariableType var_type; 170 171 Args *run_args = NULL; 172 run_args_var_name.Printf ("process.[%s].run-args", process_name); 173 StringList run_args_value = Debugger::GetSettingsController()->GetVariable (run_args_var_name.GetData(), 174 var_type, debugger_instance_name); 175 176 if (run_args_value.GetSize() > 0) 177 { 178 run_args = new Args; 179 for (unsigned i = 0, e = run_args_value.GetSize(); i != e; ++i) 180 run_args->AppendArgument(run_args_value.GetStringAtIndex(i)); 181 } 182 183 Args *environment = NULL; 184 env_vars_var_name.Printf ("process.[%s].env-vars", process_name); 185 StringList env_vars_value = Debugger::GetSettingsController()->GetVariable (env_vars_var_name.GetData(), 186 var_type, debugger_instance_name); 187 188 if (env_vars_value.GetSize() > 0) 189 { 190 environment = new Args; 191 for (unsigned i = 0, e = env_vars_value.GetSize(); i != e; ++i) 192 environment->AppendArgument (env_vars_value.GetStringAtIndex (i)); 193 } 194 195 uint32_t launch_flags = eLaunchFlagNone; 196 disable_aslr_var_name.Printf ("process.[%s].disable-aslr", process_name); 197 StringList disable_aslr_value = Debugger::GetSettingsController()->GetVariable(disable_aslr_var_name.GetData(), 198 var_type, 199 debugger_instance_name); 200 201 if (disable_aslr_value.GetSize() > 0) 202 { 203 if (strcmp (disable_aslr_value.GetStringAtIndex(0), "true") == 0) 204 launch_flags |= eLaunchFlagDisableASLR; 205 206 } 207 208 // There are two possible sources of args to be passed to the process upon launching: Those the user 209 // typed at the run command (launch_args); or those the user pre-set in the run-args variable (run_args). 210 211 // If launch_args is empty, use run_args. 212 if (launch_args.GetArgumentCount() == 0) 213 { 214 if (run_args != NULL) 215 launch_args.AppendArguments (*run_args); 216 } 217 else 218 { 219 // launch-args was not empty; use that, AND re-set run-args to contains launch-args values. 220 std::string new_run_args; 221 launch_args.GetCommandString (new_run_args); 222 Debugger::GetSettingsController()->SetVariable (run_args_var_name.GetData(), new_run_args.c_str(), 223 lldb::eVarSetOperationAssign, false, 224 interpreter.GetDebugger().GetInstanceName().AsCString()); 225 } 226 227 228 if (process) 229 { 230 const char *archname = exe_module->GetArchitecture().AsCString(); 231 232 const char * stdin_path = NULL; 233 const char * stdout_path = NULL; 234 const char * stderr_path = NULL; 235 236 if (!(m_options.stdin_path.empty() && 237 m_options.stdout_path.empty() && 238 m_options.stderr_path.empty())) 239 { 240 stdin_path = m_options.stdin_path.empty() ? "/dev/null" : m_options.stdin_path.c_str(); 241 stdout_path = m_options.stdout_path.empty() ? "/dev/null" : m_options.stdout_path.c_str(); 242 stderr_path = m_options.stderr_path.empty() ? "/dev/null" : m_options.stderr_path.c_str(); 243 } 244 245 Error error (process->Launch (launch_args.GetConstArgumentVector(), 246 environment ? environment->GetConstArgumentVector() : NULL, 247 launch_flags, 248 stdin_path, 249 stdout_path, 250 stderr_path)); 251 252 if (error.Success()) 253 { 254 result.AppendMessageWithFormat ("Launching '%s' (%s)\n", filename, archname); 255 result.SetStatus (eReturnStatusSuccessContinuingNoResult); 256 if (m_options.stop_at_entry == false) 257 { 258 StateType state = process->WaitForProcessToStop (NULL); 259 260 if (state == eStateStopped) 261 { 262 // Call continue_command. 263 CommandReturnObject continue_result; 264 interpreter.HandleCommand("process continue", false, continue_result); 265 } 266 267 if (synchronous_execution) 268 { 269 result.SetDidChangeProcessState (true); 270 result.SetStatus (eReturnStatusSuccessFinishNoResult); 271 } 272 } 273 } 274 else 275 { 276 result.AppendErrorWithFormat ("Process launch failed: %s", 277 error.AsCString()); 278 result.SetStatus (eReturnStatusFailed); 279 } 280 } 281 else 282 { 283 result.AppendErrorWithFormat ("Process launch failed: unable to create a process object.\n"); 284 result.SetStatus (eReturnStatusFailed); 285 return false; 286 } 287 288 return result.Succeeded(); 289 } 290 291 virtual const char *GetRepeatCommand (Args ¤t_command_args, uint32_t index) 292 { 293 // No repeat for "process launch"... 294 return ""; 295 } 296 297 protected: 298 299 CommandOptions m_options; 300 }; 301 302 303 lldb::OptionDefinition 304 CommandObjectProcessLaunch::CommandOptions::g_option_table[] = 305 { 306 { LLDB_OPT_SET_1, false, "stop-at-entry", 's', no_argument, NULL, 0, NULL, "Stop at the entry point of the program when launching a process."}, 307 { LLDB_OPT_SET_1, false, "stdin", 'i', required_argument, NULL, 0, "<path>", "Redirect stdin for the process to <path>."}, 308 { LLDB_OPT_SET_1, false, "stdout", 'o', required_argument, NULL, 0, "<path>", "Redirect stdout for the process to <path>."}, 309 { LLDB_OPT_SET_1, false, "stderr", 'e', required_argument, NULL, 0, "<path>", "Redirect stderr for the process to <path>."}, 310 { LLDB_OPT_SET_1, false, "plugin", 'p', required_argument, NULL, 0, "<plugin>", "Name of the process plugin you want to use."}, 311 { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL } 312 }; 313 314 315 //------------------------------------------------------------------------- 316 // CommandObjectProcessAttach 317 //------------------------------------------------------------------------- 318 319 class CommandObjectProcessAttach : public CommandObject 320 { 321 public: 322 323 class CommandOptions : public Options 324 { 325 public: 326 327 CommandOptions () : 328 Options() 329 { 330 // Keep default values of all options in one place: ResetOptionValues () 331 ResetOptionValues (); 332 } 333 334 ~CommandOptions () 335 { 336 } 337 338 Error 339 SetOptionValue (int option_idx, const char *option_arg) 340 { 341 Error error; 342 char short_option = (char) m_getopt_table[option_idx].val; 343 bool success = false; 344 switch (short_option) 345 { 346 case 'p': 347 pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success); 348 if (!success || pid == LLDB_INVALID_PROCESS_ID) 349 { 350 error.SetErrorStringWithFormat("Invalid process ID '%s'.\n", option_arg); 351 } 352 break; 353 354 case 'P': 355 plugin_name = option_arg; 356 break; 357 358 case 'n': 359 name.assign(option_arg); 360 break; 361 362 case 'w': 363 waitfor = true; 364 break; 365 366 default: 367 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option); 368 break; 369 } 370 return error; 371 } 372 373 void 374 ResetOptionValues () 375 { 376 Options::ResetOptionValues(); 377 pid = LLDB_INVALID_PROCESS_ID; 378 name.clear(); 379 waitfor = false; 380 } 381 382 const lldb::OptionDefinition* 383 GetDefinitions () 384 { 385 return g_option_table; 386 } 387 388 virtual bool 389 HandleOptionArgumentCompletion (CommandInterpreter &interpreter, 390 Args &input, 391 int cursor_index, 392 int char_pos, 393 OptionElementVector &opt_element_vector, 394 int opt_element_index, 395 int match_start_point, 396 int max_return_elements, 397 bool &word_complete, 398 StringList &matches) 399 { 400 int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos; 401 int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index; 402 403 // We are only completing the name option for now... 404 405 const lldb::OptionDefinition *opt_defs = GetDefinitions(); 406 if (opt_defs[opt_defs_index].short_option == 'n') 407 { 408 // Are we in the name? 409 410 // Look to see if there is a -P argument provided, and if so use that plugin, otherwise 411 // use the default plugin. 412 Process *process = interpreter.GetDebugger().GetExecutionContext().process; 413 bool need_to_delete_process = false; 414 415 const char *partial_name = NULL; 416 partial_name = input.GetArgumentAtIndex(opt_arg_pos); 417 418 if (process && process->IsAlive()) 419 return true; 420 421 Target *target = interpreter.GetDebugger().GetSelectedTarget().get(); 422 if (target == NULL) 423 { 424 // No target has been set yet, for now do host completion. Otherwise I don't know how we would 425 // figure out what the right target to use is... 426 std::vector<lldb::pid_t> pids; 427 Host::ListProcessesMatchingName (partial_name, matches, pids); 428 return true; 429 } 430 if (!process) 431 { 432 process = target->CreateProcess (interpreter.GetDebugger().GetListener(), partial_name).get(); 433 need_to_delete_process = true; 434 } 435 436 if (process) 437 { 438 matches.Clear(); 439 std::vector<lldb::pid_t> pids; 440 process->ListProcessesMatchingName (NULL, matches, pids); 441 if (need_to_delete_process) 442 target->DeleteCurrentProcess(); 443 return true; 444 } 445 } 446 447 return false; 448 } 449 450 // Options table: Required for subclasses of Options. 451 452 static lldb::OptionDefinition g_option_table[]; 453 454 // Instance variables to hold the values for command options. 455 456 lldb::pid_t pid; 457 std::string plugin_name; 458 std::string name; 459 bool waitfor; 460 }; 461 462 CommandObjectProcessAttach () : 463 CommandObject ("process attach", 464 "Attach to a process.", 465 "process attach <cmd-options>") 466 { 467 SetHelpLong("Currently, you must set the executable file before you can attach " 468 "to a process.\n"); 469 } 470 471 ~CommandObjectProcessAttach () 472 { 473 } 474 475 bool 476 Execute (CommandInterpreter &interpreter, 477 Args& command, 478 CommandReturnObject &result) 479 { 480 Target *target = interpreter.GetDebugger().GetSelectedTarget().get(); 481 482 Process *process = interpreter.GetDebugger().GetExecutionContext().process; 483 if (process) 484 { 485 if (process->IsAlive()) 486 { 487 result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before attaching.\n", 488 process->GetID()); 489 result.SetStatus (eReturnStatusFailed); 490 return false; 491 } 492 } 493 494 if (target == NULL) 495 { 496 // If there isn't a current target create one. 497 TargetSP new_target_sp; 498 FileSpec emptyFileSpec; 499 ArchSpec emptyArchSpec; 500 Error error; 501 502 error = interpreter.GetDebugger().GetTargetList().CreateTarget(interpreter.GetDebugger(), 503 emptyFileSpec, 504 emptyArchSpec, 505 NULL, 506 false, 507 new_target_sp); 508 target = new_target_sp.get(); 509 if (target == NULL || error.Fail()) 510 { 511 result.AppendError(error.AsCString("Error creating empty target")); 512 return false; 513 } 514 interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target); 515 } 516 517 // Record the old executable module, we want to issue a warning if the process of attaching changed the 518 // current executable (like somebody said "file foo" then attached to a PID whose executable was bar.) 519 520 ModuleSP old_exec_module_sp = target->GetExecutableModule(); 521 ArchSpec old_arch_spec = target->GetArchitecture(); 522 523 if (command.GetArgumentCount()) 524 { 525 result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str()); 526 result.SetStatus (eReturnStatusFailed); 527 } 528 else 529 { 530 const char *plugin_name = NULL; 531 532 if (!m_options.plugin_name.empty()) 533 plugin_name = m_options.plugin_name.c_str(); 534 535 process = target->CreateProcess (interpreter.GetDebugger().GetListener(), plugin_name).get(); 536 537 if (process) 538 { 539 Error error; 540 int attach_pid = m_options.pid; 541 542 // If we are waiting for a process with this name to show up, do that first. 543 if (m_options.waitfor) 544 { 545 if (m_options.name.empty()) 546 { 547 result.AppendError("Invalid arguments: must supply a process name with the waitfor option.\n"); 548 result.SetStatus (eReturnStatusFailed); 549 return false; 550 } 551 else 552 { 553 error = process->Attach (m_options.name.c_str(), m_options.waitfor); 554 if (error.Success()) 555 { 556 result.SetStatus (eReturnStatusSuccessContinuingNoResult); 557 } 558 else 559 { 560 result.AppendErrorWithFormat ("Waiting for a process to launch named '%s': %s\n", 561 m_options.name.c_str(), 562 error.AsCString()); 563 result.SetStatus (eReturnStatusFailed); 564 return false; 565 } 566 } 567 } 568 else 569 { 570 // If the process was specified by name look it up, so we can warn if there are multiple 571 // processes with this pid. 572 573 if (attach_pid == LLDB_INVALID_PROCESS_ID && !m_options.name.empty()) 574 { 575 std::vector<lldb::pid_t> pids; 576 StringList matches; 577 578 process->ListProcessesMatchingName(m_options.name.c_str(), matches, pids); 579 if (matches.GetSize() > 1) 580 { 581 result.AppendErrorWithFormat("More than one process named %s\n", m_options.name.c_str()); 582 result.SetStatus (eReturnStatusFailed); 583 return false; 584 } 585 else if (matches.GetSize() == 0) 586 { 587 result.AppendErrorWithFormat("Could not find a process named %s\n", m_options.name.c_str()); 588 result.SetStatus (eReturnStatusFailed); 589 return false; 590 } 591 else 592 { 593 attach_pid = pids[0]; 594 } 595 596 } 597 598 if (attach_pid != LLDB_INVALID_PROCESS_ID) 599 { 600 error = process->Attach (attach_pid); 601 if (error.Success()) 602 { 603 result.SetStatus (eReturnStatusSuccessContinuingNoResult); 604 } 605 else 606 { 607 result.AppendErrorWithFormat ("Attaching to process %i failed: %s.\n", 608 attach_pid, 609 error.AsCString()); 610 result.SetStatus (eReturnStatusFailed); 611 } 612 } 613 else 614 { 615 result.AppendErrorWithFormat ("No PID specified for attach\n", 616 attach_pid, 617 error.AsCString()); 618 result.SetStatus (eReturnStatusFailed); 619 620 } 621 } 622 } 623 } 624 625 if (result.Succeeded()) 626 { 627 // Okay, we're done. Last step is to warn if the executable module has changed: 628 if (!old_exec_module_sp) 629 { 630 char new_path[PATH_MAX + 1]; 631 target->GetExecutableModule()->GetFileSpec().GetPath(new_path, PATH_MAX); 632 633 result.AppendMessageWithFormat("Executable module set to \"%s\".\n", 634 new_path); 635 } 636 else if (old_exec_module_sp->GetFileSpec() != target->GetExecutableModule()->GetFileSpec()) 637 { 638 char old_path[PATH_MAX + 1]; 639 char new_path[PATH_MAX + 1]; 640 641 old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX); 642 target->GetExecutableModule()->GetFileSpec().GetPath (new_path, PATH_MAX); 643 644 result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n", 645 old_path, new_path); 646 } 647 648 if (!old_arch_spec.IsValid()) 649 { 650 result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().AsCString()); 651 } 652 else if (old_arch_spec != target->GetArchitecture()) 653 { 654 result.AppendWarningWithFormat("Architecture changed from %s to %s.\n", 655 old_arch_spec.AsCString(), target->GetArchitecture().AsCString()); 656 } 657 } 658 return result.Succeeded(); 659 } 660 661 Options * 662 GetOptions () 663 { 664 return &m_options; 665 } 666 667 protected: 668 669 CommandOptions m_options; 670 }; 671 672 673 lldb::OptionDefinition 674 CommandObjectProcessAttach::CommandOptions::g_option_table[] = 675 { 676 { LLDB_OPT_SET_ALL, false, "plugin", 'P', required_argument, NULL, 0, "<plugin>", "Name of the process plugin you want to use."}, 677 { LLDB_OPT_SET_1, false, "pid", 'p', required_argument, NULL, 0, "<pid>", "The process ID of an existing process to attach to."}, 678 { LLDB_OPT_SET_2, true, "name", 'n', required_argument, NULL, 0, "<process-name>", "The name of the process to attach to."}, 679 { LLDB_OPT_SET_2, false, "waitfor", 'w', no_argument, NULL, 0, NULL, "Wait for the the process with <process-name> to launch."}, 680 { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL } 681 }; 682 683 //------------------------------------------------------------------------- 684 // CommandObjectProcessContinue 685 //------------------------------------------------------------------------- 686 687 class CommandObjectProcessContinue : public CommandObject 688 { 689 public: 690 691 CommandObjectProcessContinue () : 692 CommandObject ("process continue", 693 "Continue execution of all threads in the current process.", 694 "process continue", 695 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused) 696 { 697 } 698 699 700 ~CommandObjectProcessContinue () 701 { 702 } 703 704 bool 705 Execute (CommandInterpreter &interpreter, 706 Args& command, 707 CommandReturnObject &result) 708 { 709 Process *process = interpreter.GetDebugger().GetExecutionContext().process; 710 bool synchronous_execution = interpreter.GetSynchronous (); 711 712 if (process == NULL) 713 { 714 result.AppendError ("no process to continue"); 715 result.SetStatus (eReturnStatusFailed); 716 return false; 717 } 718 719 StateType state = process->GetState(); 720 if (state == eStateStopped) 721 { 722 if (command.GetArgumentCount() != 0) 723 { 724 result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str()); 725 result.SetStatus (eReturnStatusFailed); 726 return false; 727 } 728 729 const uint32_t num_threads = process->GetThreadList().GetSize(); 730 731 // Set the actions that the threads should each take when resuming 732 for (uint32_t idx=0; idx<num_threads; ++idx) 733 { 734 process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning); 735 } 736 737 Error error(process->Resume()); 738 if (error.Success()) 739 { 740 result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID()); 741 if (synchronous_execution) 742 { 743 state = process->WaitForProcessToStop (NULL); 744 745 result.SetDidChangeProcessState (true); 746 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state)); 747 result.SetStatus (eReturnStatusSuccessFinishNoResult); 748 } 749 else 750 { 751 result.SetStatus (eReturnStatusSuccessContinuingNoResult); 752 } 753 } 754 else 755 { 756 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString()); 757 result.SetStatus (eReturnStatusFailed); 758 } 759 } 760 else 761 { 762 result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n", 763 StateAsCString(state)); 764 result.SetStatus (eReturnStatusFailed); 765 } 766 return result.Succeeded(); 767 } 768 }; 769 770 //------------------------------------------------------------------------- 771 // CommandObjectProcessDetach 772 //------------------------------------------------------------------------- 773 774 class CommandObjectProcessDetach : public CommandObject 775 { 776 public: 777 778 CommandObjectProcessDetach () : 779 CommandObject ("process detach", 780 "Detach from the current process being debugged.", 781 "process detach", 782 eFlagProcessMustBeLaunched) 783 { 784 } 785 786 ~CommandObjectProcessDetach () 787 { 788 } 789 790 bool 791 Execute (CommandInterpreter &interpreter, 792 Args& command, 793 CommandReturnObject &result) 794 { 795 Process *process = interpreter.GetDebugger().GetExecutionContext().process; 796 if (process == NULL) 797 { 798 result.AppendError ("must have a valid process in order to detach"); 799 result.SetStatus (eReturnStatusFailed); 800 return false; 801 } 802 803 Error error (process->Detach()); 804 if (error.Success()) 805 { 806 result.SetStatus (eReturnStatusSuccessFinishResult); 807 } 808 else 809 { 810 result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString()); 811 result.SetStatus (eReturnStatusFailed); 812 return false; 813 } 814 return result.Succeeded(); 815 } 816 }; 817 818 //------------------------------------------------------------------------- 819 // CommandObjectProcessSignal 820 //------------------------------------------------------------------------- 821 822 class CommandObjectProcessSignal : public CommandObject 823 { 824 public: 825 826 CommandObjectProcessSignal () : 827 CommandObject ("process signal", 828 "Send a UNIX signal to the current process being debugged.", 829 "process signal <unix-signal-number>") 830 { 831 } 832 833 ~CommandObjectProcessSignal () 834 { 835 } 836 837 bool 838 Execute (CommandInterpreter &interpreter, 839 Args& command, 840 CommandReturnObject &result) 841 { 842 Process *process = interpreter.GetDebugger().GetExecutionContext().process; 843 if (process == NULL) 844 { 845 result.AppendError ("no process to signal"); 846 result.SetStatus (eReturnStatusFailed); 847 return false; 848 } 849 850 if (command.GetArgumentCount() == 1) 851 { 852 int signo = Args::StringToSInt32(command.GetArgumentAtIndex(0), -1, 0); 853 if (signo == -1) 854 { 855 result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0)); 856 result.SetStatus (eReturnStatusFailed); 857 } 858 else 859 { 860 Error error (process->Signal (signo)); 861 if (error.Success()) 862 { 863 result.SetStatus (eReturnStatusSuccessFinishResult); 864 } 865 else 866 { 867 result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString()); 868 result.SetStatus (eReturnStatusFailed); 869 } 870 } 871 } 872 else 873 { 874 result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: \n", m_cmd_name.c_str(), 875 m_cmd_syntax.c_str()); 876 result.SetStatus (eReturnStatusFailed); 877 } 878 return result.Succeeded(); 879 } 880 }; 881 882 883 //------------------------------------------------------------------------- 884 // CommandObjectProcessInterrupt 885 //------------------------------------------------------------------------- 886 887 class CommandObjectProcessInterrupt : public CommandObject 888 { 889 public: 890 891 892 CommandObjectProcessInterrupt () : 893 CommandObject ("process interrupt", 894 "Interrupt the current process being debugged.", 895 "process interrupt", 896 eFlagProcessMustBeLaunched) 897 { 898 } 899 900 ~CommandObjectProcessInterrupt () 901 { 902 } 903 904 bool 905 Execute (CommandInterpreter &interpreter, 906 Args& command, 907 CommandReturnObject &result) 908 { 909 Process *process = interpreter.GetDebugger().GetExecutionContext().process; 910 if (process == NULL) 911 { 912 result.AppendError ("no process to halt"); 913 result.SetStatus (eReturnStatusFailed); 914 return false; 915 } 916 917 if (command.GetArgumentCount() == 0) 918 { 919 Error error(process->Halt ()); 920 if (error.Success()) 921 { 922 result.SetStatus (eReturnStatusSuccessFinishResult); 923 924 // Maybe we should add a "SuspendThreadPlans so we 925 // can halt, and keep in place all the current thread plans. 926 process->GetThreadList().DiscardThreadPlans(); 927 } 928 else 929 { 930 result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString()); 931 result.SetStatus (eReturnStatusFailed); 932 } 933 } 934 else 935 { 936 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n", 937 m_cmd_name.c_str(), 938 m_cmd_syntax.c_str()); 939 result.SetStatus (eReturnStatusFailed); 940 } 941 return result.Succeeded(); 942 } 943 }; 944 945 //------------------------------------------------------------------------- 946 // CommandObjectProcessKill 947 //------------------------------------------------------------------------- 948 949 class CommandObjectProcessKill : public CommandObject 950 { 951 public: 952 953 CommandObjectProcessKill () : 954 CommandObject ("process kill", 955 "Terminate the current process being debugged.", 956 "process kill", 957 eFlagProcessMustBeLaunched) 958 { 959 } 960 961 ~CommandObjectProcessKill () 962 { 963 } 964 965 bool 966 Execute (CommandInterpreter &interpreter, 967 Args& command, 968 CommandReturnObject &result) 969 { 970 Process *process = interpreter.GetDebugger().GetExecutionContext().process; 971 if (process == NULL) 972 { 973 result.AppendError ("no process to kill"); 974 result.SetStatus (eReturnStatusFailed); 975 return false; 976 } 977 978 if (command.GetArgumentCount() == 0) 979 { 980 Error error (process->Destroy()); 981 if (error.Success()) 982 { 983 result.SetStatus (eReturnStatusSuccessFinishResult); 984 } 985 else 986 { 987 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString()); 988 result.SetStatus (eReturnStatusFailed); 989 } 990 } 991 else 992 { 993 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n", 994 m_cmd_name.c_str(), 995 m_cmd_syntax.c_str()); 996 result.SetStatus (eReturnStatusFailed); 997 } 998 return result.Succeeded(); 999 } 1000 }; 1001 1002 //------------------------------------------------------------------------- 1003 // CommandObjectProcessStatus 1004 //------------------------------------------------------------------------- 1005 class CommandObjectProcessStatus : public CommandObject 1006 { 1007 public: 1008 CommandObjectProcessStatus () : 1009 CommandObject ("process status", 1010 "Show the current status and location of executing process.", 1011 "process status", 1012 0) 1013 { 1014 } 1015 1016 ~CommandObjectProcessStatus() 1017 { 1018 } 1019 1020 1021 bool 1022 Execute 1023 ( 1024 CommandInterpreter &interpreter, 1025 Args& command, 1026 CommandReturnObject &result 1027 ) 1028 { 1029 StreamString &output_stream = result.GetOutputStream(); 1030 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1031 ExecutionContext exe_ctx(interpreter.GetDebugger().GetExecutionContext()); 1032 if (exe_ctx.process) 1033 { 1034 const StateType state = exe_ctx.process->GetState(); 1035 if (StateIsStoppedState(state)) 1036 { 1037 if (state == eStateExited) 1038 { 1039 int exit_status = exe_ctx.process->GetExitStatus(); 1040 const char *exit_description = exe_ctx.process->GetExitDescription(); 1041 output_stream.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n", 1042 exe_ctx.process->GetID(), 1043 exit_status, 1044 exit_status, 1045 exit_description ? exit_description : ""); 1046 } 1047 else 1048 { 1049 output_stream.Printf ("Process %d %s\n", exe_ctx.process->GetID(), StateAsCString (state)); 1050 if (exe_ctx.thread == NULL) 1051 exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get(); 1052 if (exe_ctx.thread != NULL) 1053 { 1054 DisplayThreadsInfo (interpreter, &exe_ctx, result, true, true); 1055 } 1056 else 1057 { 1058 result.AppendError ("No valid thread found in current process."); 1059 result.SetStatus (eReturnStatusFailed); 1060 } 1061 } 1062 } 1063 else 1064 { 1065 output_stream.Printf ("Process %d is running.\n", 1066 exe_ctx.process->GetID()); 1067 } 1068 } 1069 else 1070 { 1071 result.AppendError ("No current location or status available."); 1072 result.SetStatus (eReturnStatusFailed); 1073 } 1074 return result.Succeeded(); 1075 } 1076 }; 1077 1078 //------------------------------------------------------------------------- 1079 // CommandObjectMultiwordProcess 1080 //------------------------------------------------------------------------- 1081 1082 CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter &interpreter) : 1083 CommandObjectMultiword ("process", 1084 "A set of commands for operating on a process.", 1085 "process <subcommand> [<subcommand-options>]") 1086 { 1087 LoadSubCommand (interpreter, "attach", CommandObjectSP (new CommandObjectProcessAttach ())); 1088 LoadSubCommand (interpreter, "launch", CommandObjectSP (new CommandObjectProcessLaunch ())); 1089 LoadSubCommand (interpreter, "continue", CommandObjectSP (new CommandObjectProcessContinue ())); 1090 LoadSubCommand (interpreter, "detach", CommandObjectSP (new CommandObjectProcessDetach ())); 1091 LoadSubCommand (interpreter, "signal", CommandObjectSP (new CommandObjectProcessSignal ())); 1092 LoadSubCommand (interpreter, "status", CommandObjectSP (new CommandObjectProcessStatus ())); 1093 LoadSubCommand (interpreter, "interrupt", CommandObjectSP (new CommandObjectProcessInterrupt ())); 1094 LoadSubCommand (interpreter, "kill", CommandObjectSP (new CommandObjectProcessKill ())); 1095 } 1096 1097 CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess () 1098 { 1099 } 1100 1101