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