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