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 } 468 469 ~CommandObjectProcessAttach () 470 { 471 } 472 473 bool 474 Execute (CommandInterpreter &interpreter, 475 Args& command, 476 CommandReturnObject &result) 477 { 478 Target *target = interpreter.GetDebugger().GetSelectedTarget().get(); 479 480 Process *process = interpreter.GetDebugger().GetExecutionContext().process; 481 if (process) 482 { 483 if (process->IsAlive()) 484 { 485 result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before attaching.\n", 486 process->GetID()); 487 result.SetStatus (eReturnStatusFailed); 488 return false; 489 } 490 } 491 492 if (target == NULL) 493 { 494 // If there isn't a current target create one. 495 TargetSP new_target_sp; 496 FileSpec emptyFileSpec; 497 ArchSpec emptyArchSpec; 498 Error error; 499 500 error = interpreter.GetDebugger().GetTargetList().CreateTarget(interpreter.GetDebugger(), 501 emptyFileSpec, 502 emptyArchSpec, 503 NULL, 504 false, 505 new_target_sp); 506 target = new_target_sp.get(); 507 if (target == NULL || error.Fail()) 508 { 509 result.AppendError(error.AsCString("Error creating empty target")); 510 return false; 511 } 512 interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target); 513 } 514 515 // Record the old executable module, we want to issue a warning if the process of attaching changed the 516 // current executable (like somebody said "file foo" then attached to a PID whose executable was bar.) 517 518 ModuleSP old_exec_module_sp = target->GetExecutableModule(); 519 ArchSpec old_arch_spec = target->GetArchitecture(); 520 521 if (command.GetArgumentCount()) 522 { 523 result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str()); 524 result.SetStatus (eReturnStatusFailed); 525 } 526 else 527 { 528 const char *plugin_name = NULL; 529 530 if (!m_options.plugin_name.empty()) 531 plugin_name = m_options.plugin_name.c_str(); 532 533 process = target->CreateProcess (interpreter.GetDebugger().GetListener(), plugin_name).get(); 534 535 if (process) 536 { 537 Error error; 538 int attach_pid = m_options.pid; 539 540 const char *wait_name = NULL; 541 542 if (m_options.name.empty()) 543 { 544 if (old_exec_module_sp) 545 { 546 wait_name = old_exec_module_sp->GetFileSpec().GetFilename().AsCString(); 547 } 548 } 549 else 550 { 551 wait_name = m_options.name.c_str(); 552 } 553 554 // If we are waiting for a process with this name to show up, do that first. 555 if (m_options.waitfor) 556 { 557 558 if (wait_name == NULL) 559 { 560 result.AppendError("Invalid arguments: must have a file loaded or supply a process name with the waitfor option.\n"); 561 result.SetStatus (eReturnStatusFailed); 562 return false; 563 } 564 565 interpreter.GetDebugger().GetOutputStream().Printf("Waiting to attach to a process named \"%s\".\n", wait_name); 566 error = process->Attach (wait_name, m_options.waitfor); 567 if (error.Success()) 568 { 569 result.SetStatus (eReturnStatusSuccessContinuingNoResult); 570 } 571 else 572 { 573 result.AppendErrorWithFormat ("Waiting for a process to launch named '%s': %s\n", 574 wait_name, 575 error.AsCString()); 576 result.SetStatus (eReturnStatusFailed); 577 return false; 578 } 579 } 580 else 581 { 582 // If the process was specified by name look it up, so we can warn if there are multiple 583 // processes with this pid. 584 585 if (attach_pid == LLDB_INVALID_PROCESS_ID && wait_name != NULL) 586 { 587 std::vector<lldb::pid_t> pids; 588 StringList matches; 589 590 process->ListProcessesMatchingName(wait_name, matches, pids); 591 if (matches.GetSize() > 1) 592 { 593 result.AppendErrorWithFormat("More than one process named %s\n", wait_name); 594 result.SetStatus (eReturnStatusFailed); 595 return false; 596 } 597 else if (matches.GetSize() == 0) 598 { 599 result.AppendErrorWithFormat("Could not find a process named %s\n", wait_name); 600 result.SetStatus (eReturnStatusFailed); 601 return false; 602 } 603 else 604 { 605 attach_pid = pids[0]; 606 } 607 608 } 609 610 if (attach_pid != LLDB_INVALID_PROCESS_ID) 611 { 612 error = process->Attach (attach_pid); 613 if (error.Success()) 614 { 615 result.SetStatus (eReturnStatusSuccessContinuingNoResult); 616 } 617 else 618 { 619 result.AppendErrorWithFormat ("Attaching to process %i failed: %s.\n", 620 attach_pid, 621 error.AsCString()); 622 result.SetStatus (eReturnStatusFailed); 623 } 624 } 625 else 626 { 627 result.AppendErrorWithFormat ("No PID specified for attach\n", 628 attach_pid, 629 error.AsCString()); 630 result.SetStatus (eReturnStatusFailed); 631 632 } 633 } 634 } 635 } 636 637 if (result.Succeeded()) 638 { 639 // Okay, we're done. Last step is to warn if the executable module has changed: 640 if (!old_exec_module_sp) 641 { 642 char new_path[PATH_MAX + 1]; 643 target->GetExecutableModule()->GetFileSpec().GetPath(new_path, PATH_MAX); 644 645 result.AppendMessageWithFormat("Executable module set to \"%s\".\n", 646 new_path); 647 } 648 else if (old_exec_module_sp->GetFileSpec() != target->GetExecutableModule()->GetFileSpec()) 649 { 650 char old_path[PATH_MAX + 1]; 651 char new_path[PATH_MAX + 1]; 652 653 old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX); 654 target->GetExecutableModule()->GetFileSpec().GetPath (new_path, PATH_MAX); 655 656 result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n", 657 old_path, new_path); 658 } 659 660 if (!old_arch_spec.IsValid()) 661 { 662 result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().AsCString()); 663 } 664 else if (old_arch_spec != target->GetArchitecture()) 665 { 666 result.AppendWarningWithFormat("Architecture changed from %s to %s.\n", 667 old_arch_spec.AsCString(), target->GetArchitecture().AsCString()); 668 } 669 } 670 return result.Succeeded(); 671 } 672 673 Options * 674 GetOptions () 675 { 676 return &m_options; 677 } 678 679 protected: 680 681 CommandOptions m_options; 682 }; 683 684 685 lldb::OptionDefinition 686 CommandObjectProcessAttach::CommandOptions::g_option_table[] = 687 { 688 { LLDB_OPT_SET_ALL, false, "plugin", 'P', required_argument, NULL, 0, "<plugin>", "Name of the process plugin you want to use."}, 689 { LLDB_OPT_SET_1, false, "pid", 'p', required_argument, NULL, 0, "<pid>", "The process ID of an existing process to attach to."}, 690 { LLDB_OPT_SET_2, false, "name", 'n', required_argument, NULL, 0, "<process-name>", "The name of the process to attach to."}, 691 { LLDB_OPT_SET_2, false, "waitfor", 'w', no_argument, NULL, 0, NULL, "Wait for the the process with <process-name> to launch."}, 692 { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL } 693 }; 694 695 //------------------------------------------------------------------------- 696 // CommandObjectProcessContinue 697 //------------------------------------------------------------------------- 698 699 class CommandObjectProcessContinue : public CommandObject 700 { 701 public: 702 703 CommandObjectProcessContinue () : 704 CommandObject ("process continue", 705 "Continue execution of all threads in the current process.", 706 "process continue", 707 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused) 708 { 709 } 710 711 712 ~CommandObjectProcessContinue () 713 { 714 } 715 716 bool 717 Execute (CommandInterpreter &interpreter, 718 Args& command, 719 CommandReturnObject &result) 720 { 721 Process *process = interpreter.GetDebugger().GetExecutionContext().process; 722 bool synchronous_execution = interpreter.GetSynchronous (); 723 724 if (process == NULL) 725 { 726 result.AppendError ("no process to continue"); 727 result.SetStatus (eReturnStatusFailed); 728 return false; 729 } 730 731 StateType state = process->GetState(); 732 if (state == eStateStopped) 733 { 734 if (command.GetArgumentCount() != 0) 735 { 736 result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str()); 737 result.SetStatus (eReturnStatusFailed); 738 return false; 739 } 740 741 const uint32_t num_threads = process->GetThreadList().GetSize(); 742 743 // Set the actions that the threads should each take when resuming 744 for (uint32_t idx=0; idx<num_threads; ++idx) 745 { 746 process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning); 747 } 748 749 Error error(process->Resume()); 750 if (error.Success()) 751 { 752 result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID()); 753 if (synchronous_execution) 754 { 755 state = process->WaitForProcessToStop (NULL); 756 757 result.SetDidChangeProcessState (true); 758 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state)); 759 result.SetStatus (eReturnStatusSuccessFinishNoResult); 760 } 761 else 762 { 763 result.SetStatus (eReturnStatusSuccessContinuingNoResult); 764 } 765 } 766 else 767 { 768 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString()); 769 result.SetStatus (eReturnStatusFailed); 770 } 771 } 772 else 773 { 774 result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n", 775 StateAsCString(state)); 776 result.SetStatus (eReturnStatusFailed); 777 } 778 return result.Succeeded(); 779 } 780 }; 781 782 //------------------------------------------------------------------------- 783 // CommandObjectProcessDetach 784 //------------------------------------------------------------------------- 785 786 class CommandObjectProcessDetach : public CommandObject 787 { 788 public: 789 790 CommandObjectProcessDetach () : 791 CommandObject ("process detach", 792 "Detach from the current process being debugged.", 793 "process detach", 794 eFlagProcessMustBeLaunched) 795 { 796 } 797 798 ~CommandObjectProcessDetach () 799 { 800 } 801 802 bool 803 Execute (CommandInterpreter &interpreter, 804 Args& command, 805 CommandReturnObject &result) 806 { 807 Process *process = interpreter.GetDebugger().GetExecutionContext().process; 808 if (process == NULL) 809 { 810 result.AppendError ("must have a valid process in order to detach"); 811 result.SetStatus (eReturnStatusFailed); 812 return false; 813 } 814 815 Error error (process->Detach()); 816 if (error.Success()) 817 { 818 result.SetStatus (eReturnStatusSuccessFinishResult); 819 } 820 else 821 { 822 result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString()); 823 result.SetStatus (eReturnStatusFailed); 824 return false; 825 } 826 return result.Succeeded(); 827 } 828 }; 829 830 //------------------------------------------------------------------------- 831 // CommandObjectProcessSignal 832 //------------------------------------------------------------------------- 833 834 class CommandObjectProcessSignal : public CommandObject 835 { 836 public: 837 838 CommandObjectProcessSignal () : 839 CommandObject ("process signal", 840 "Send a UNIX signal to the current process being debugged.", 841 "process signal <unix-signal-number>") 842 { 843 } 844 845 ~CommandObjectProcessSignal () 846 { 847 } 848 849 bool 850 Execute (CommandInterpreter &interpreter, 851 Args& command, 852 CommandReturnObject &result) 853 { 854 Process *process = interpreter.GetDebugger().GetExecutionContext().process; 855 if (process == NULL) 856 { 857 result.AppendError ("no process to signal"); 858 result.SetStatus (eReturnStatusFailed); 859 return false; 860 } 861 862 if (command.GetArgumentCount() == 1) 863 { 864 int signo = Args::StringToSInt32(command.GetArgumentAtIndex(0), -1, 0); 865 if (signo == -1) 866 { 867 result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0)); 868 result.SetStatus (eReturnStatusFailed); 869 } 870 else 871 { 872 Error error (process->Signal (signo)); 873 if (error.Success()) 874 { 875 result.SetStatus (eReturnStatusSuccessFinishResult); 876 } 877 else 878 { 879 result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString()); 880 result.SetStatus (eReturnStatusFailed); 881 } 882 } 883 } 884 else 885 { 886 result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: \n", m_cmd_name.c_str(), 887 m_cmd_syntax.c_str()); 888 result.SetStatus (eReturnStatusFailed); 889 } 890 return result.Succeeded(); 891 } 892 }; 893 894 895 //------------------------------------------------------------------------- 896 // CommandObjectProcessInterrupt 897 //------------------------------------------------------------------------- 898 899 class CommandObjectProcessInterrupt : public CommandObject 900 { 901 public: 902 903 904 CommandObjectProcessInterrupt () : 905 CommandObject ("process interrupt", 906 "Interrupt the current process being debugged.", 907 "process interrupt", 908 eFlagProcessMustBeLaunched) 909 { 910 } 911 912 ~CommandObjectProcessInterrupt () 913 { 914 } 915 916 bool 917 Execute (CommandInterpreter &interpreter, 918 Args& command, 919 CommandReturnObject &result) 920 { 921 Process *process = interpreter.GetDebugger().GetExecutionContext().process; 922 if (process == NULL) 923 { 924 result.AppendError ("no process to halt"); 925 result.SetStatus (eReturnStatusFailed); 926 return false; 927 } 928 929 if (command.GetArgumentCount() == 0) 930 { 931 Error error(process->Halt ()); 932 if (error.Success()) 933 { 934 result.SetStatus (eReturnStatusSuccessFinishResult); 935 936 // Maybe we should add a "SuspendThreadPlans so we 937 // can halt, and keep in place all the current thread plans. 938 process->GetThreadList().DiscardThreadPlans(); 939 } 940 else 941 { 942 result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString()); 943 result.SetStatus (eReturnStatusFailed); 944 } 945 } 946 else 947 { 948 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n", 949 m_cmd_name.c_str(), 950 m_cmd_syntax.c_str()); 951 result.SetStatus (eReturnStatusFailed); 952 } 953 return result.Succeeded(); 954 } 955 }; 956 957 //------------------------------------------------------------------------- 958 // CommandObjectProcessKill 959 //------------------------------------------------------------------------- 960 961 class CommandObjectProcessKill : public CommandObject 962 { 963 public: 964 965 CommandObjectProcessKill () : 966 CommandObject ("process kill", 967 "Terminate the current process being debugged.", 968 "process kill", 969 eFlagProcessMustBeLaunched) 970 { 971 } 972 973 ~CommandObjectProcessKill () 974 { 975 } 976 977 bool 978 Execute (CommandInterpreter &interpreter, 979 Args& command, 980 CommandReturnObject &result) 981 { 982 Process *process = interpreter.GetDebugger().GetExecutionContext().process; 983 if (process == NULL) 984 { 985 result.AppendError ("no process to kill"); 986 result.SetStatus (eReturnStatusFailed); 987 return false; 988 } 989 990 if (command.GetArgumentCount() == 0) 991 { 992 Error error (process->Destroy()); 993 if (error.Success()) 994 { 995 result.SetStatus (eReturnStatusSuccessFinishResult); 996 } 997 else 998 { 999 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString()); 1000 result.SetStatus (eReturnStatusFailed); 1001 } 1002 } 1003 else 1004 { 1005 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n", 1006 m_cmd_name.c_str(), 1007 m_cmd_syntax.c_str()); 1008 result.SetStatus (eReturnStatusFailed); 1009 } 1010 return result.Succeeded(); 1011 } 1012 }; 1013 1014 //------------------------------------------------------------------------- 1015 // CommandObjectProcessStatus 1016 //------------------------------------------------------------------------- 1017 class CommandObjectProcessStatus : public CommandObject 1018 { 1019 public: 1020 CommandObjectProcessStatus () : 1021 CommandObject ("process status", 1022 "Show the current status and location of executing process.", 1023 "process status", 1024 0) 1025 { 1026 } 1027 1028 ~CommandObjectProcessStatus() 1029 { 1030 } 1031 1032 1033 bool 1034 Execute 1035 ( 1036 CommandInterpreter &interpreter, 1037 Args& command, 1038 CommandReturnObject &result 1039 ) 1040 { 1041 StreamString &output_stream = result.GetOutputStream(); 1042 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1043 ExecutionContext exe_ctx(interpreter.GetDebugger().GetExecutionContext()); 1044 if (exe_ctx.process) 1045 { 1046 const StateType state = exe_ctx.process->GetState(); 1047 if (StateIsStoppedState(state)) 1048 { 1049 if (state == eStateExited) 1050 { 1051 int exit_status = exe_ctx.process->GetExitStatus(); 1052 const char *exit_description = exe_ctx.process->GetExitDescription(); 1053 output_stream.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n", 1054 exe_ctx.process->GetID(), 1055 exit_status, 1056 exit_status, 1057 exit_description ? exit_description : ""); 1058 } 1059 else 1060 { 1061 output_stream.Printf ("Process %d %s\n", exe_ctx.process->GetID(), StateAsCString (state)); 1062 if (exe_ctx.thread == NULL) 1063 exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get(); 1064 if (exe_ctx.thread != NULL) 1065 { 1066 DisplayThreadsInfo (interpreter, &exe_ctx, result, true, true); 1067 } 1068 else 1069 { 1070 result.AppendError ("No valid thread found in current process."); 1071 result.SetStatus (eReturnStatusFailed); 1072 } 1073 } 1074 } 1075 else 1076 { 1077 output_stream.Printf ("Process %d is running.\n", 1078 exe_ctx.process->GetID()); 1079 } 1080 } 1081 else 1082 { 1083 result.AppendError ("No current location or status available."); 1084 result.SetStatus (eReturnStatusFailed); 1085 } 1086 return result.Succeeded(); 1087 } 1088 }; 1089 1090 //------------------------------------------------------------------------- 1091 // CommandObjectMultiwordProcess 1092 //------------------------------------------------------------------------- 1093 1094 CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter &interpreter) : 1095 CommandObjectMultiword ("process", 1096 "A set of commands for operating on a process.", 1097 "process <subcommand> [<subcommand-options>]") 1098 { 1099 LoadSubCommand (interpreter, "attach", CommandObjectSP (new CommandObjectProcessAttach ())); 1100 LoadSubCommand (interpreter, "launch", CommandObjectSP (new CommandObjectProcessLaunch ())); 1101 LoadSubCommand (interpreter, "continue", CommandObjectSP (new CommandObjectProcessContinue ())); 1102 LoadSubCommand (interpreter, "detach", CommandObjectSP (new CommandObjectProcessDetach ())); 1103 LoadSubCommand (interpreter, "signal", CommandObjectSP (new CommandObjectProcessSignal ())); 1104 LoadSubCommand (interpreter, "status", CommandObjectSP (new CommandObjectProcessStatus ())); 1105 LoadSubCommand (interpreter, "interrupt", CommandObjectSP (new CommandObjectProcessInterrupt ())); 1106 LoadSubCommand (interpreter, "kill", CommandObjectSP (new CommandObjectProcessKill ())); 1107 } 1108 1109 CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess () 1110 { 1111 } 1112 1113