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 "Launches 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 (Args& launch_args, 124 CommandContext *context, 125 CommandInterpreter *interpreter, 126 CommandReturnObject &result) 127 { 128 Target *target = context->GetTarget(); 129 bool synchronous_execution = interpreter->GetSynchronous (); 130 // bool launched = false; 131 // bool stopped_after_launch = false; 132 133 if (target == NULL) 134 { 135 result.AppendError ("invalid target, set executable file using 'file' command"); 136 result.SetStatus (eReturnStatusFailed); 137 return false; 138 } 139 140 // If our listener is NULL, users aren't allows to launch 141 Listener *listener = interpreter->GetListener(); 142 if (listener == NULL) 143 { 144 result.AppendError ("operation not allowed through the command interpreter"); 145 result.SetStatus (eReturnStatusFailed); 146 return false; 147 } 148 149 char filename[PATH_MAX]; 150 Module *exe_module = target->GetExecutableModule().get(); 151 exe_module->GetFileSpec().GetPath(filename, sizeof(filename)); 152 153 Process *process = context->GetExecutionContext().process; 154 if (process) 155 { 156 if (process->IsAlive()) 157 { 158 result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before running again.\n", 159 process->GetID()); 160 result.SetStatus (eReturnStatusFailed); 161 return false; 162 } 163 } 164 165 const char *plugin_name; 166 if (!m_options.plugin_name.empty()) 167 plugin_name = m_options.plugin_name.c_str(); 168 else 169 plugin_name = NULL; 170 171 process = target->CreateProcess (*listener, plugin_name).get(); 172 173 const Args *environment = interpreter->GetEnvironmentVariables(); 174 const Args *run_args = interpreter->GetProgramArguments(); 175 176 // There are two possible sources of args to be passed to the process upon launching: Those the user 177 // typed at the run command (launch_args); or those the user pre-set in the run-args variable (run_args). 178 179 // If launch_args is empty, use run_args. 180 if (launch_args.GetArgumentCount() == 0) 181 { 182 if (run_args != NULL) 183 launch_args.AppendArguments (*run_args); 184 } 185 else 186 { 187 // launch-args was not empty; use that, AND re-set run-args to contains launch-args values. 188 StateVariable *run_args_var = interpreter->GetStateVariable ("run-args"); 189 if (run_args_var != NULL) 190 { 191 run_args_var->ArrayClearValues(); 192 run_args_var->GetArgs().AppendArguments (launch_args); 193 } 194 } 195 196 197 if (process) 198 { 199 const char *archname = exe_module->GetArchitecture().AsCString(); 200 201 const char * stdin_path = NULL; 202 const char * stdout_path = NULL; 203 const char * stderr_path = NULL; 204 205 if (!(m_options.stdin_path.empty() && 206 m_options.stdout_path.empty() && 207 m_options.stderr_path.empty())) 208 { 209 stdin_path = m_options.stdin_path.empty() ? "/dev/null" : m_options.stdin_path.c_str(); 210 stdout_path = m_options.stdout_path.empty() ? "/dev/null" : m_options.stdout_path.c_str(); 211 stderr_path = m_options.stderr_path.empty() ? "/dev/null" : m_options.stderr_path.c_str(); 212 } 213 214 Error error (process->Launch (launch_args.GetConstArgumentVector(), 215 environment ? environment->GetConstArgumentVector() : NULL, 216 stdin_path, 217 stdout_path, 218 stderr_path)); 219 220 if (error.Success()) 221 { 222 result.AppendMessageWithFormat ("Launching '%s' (%s)\n", filename, archname); 223 result.SetStatus (eReturnStatusSuccessContinuingNoResult); 224 if (m_options.stop_at_entry == false) 225 { 226 StateType state = process->WaitForProcessToStop (NULL); 227 228 if (state == eStateStopped) 229 { 230 // Call continue_command. 231 CommandReturnObject continue_result; 232 interpreter->HandleCommand("process continue", false, continue_result); 233 } 234 235 if (synchronous_execution) 236 { 237 result.SetDidChangeProcessState (true); 238 result.SetStatus (eReturnStatusSuccessFinishNoResult); 239 } 240 } 241 } 242 else 243 { 244 result.AppendErrorWithFormat ("Process launch failed: %s", 245 error.AsCString()); 246 result.SetStatus (eReturnStatusFailed); 247 } 248 } 249 else 250 { 251 result.AppendErrorWithFormat ("Process launch failed: unable to create a process object.\n"); 252 result.SetStatus (eReturnStatusFailed); 253 return false; 254 } 255 256 return result.Succeeded(); 257 } 258 259 protected: 260 261 CommandOptions m_options; 262 }; 263 264 265 lldb::OptionDefinition 266 CommandObjectProcessLaunch::CommandOptions::g_option_table[] = 267 { 268 { 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."}, 269 { LLDB_OPT_SET_1, false, "stdin", 'i', required_argument, NULL, 0, "<path>", "Redirect stdin for the process to <path>."}, 270 { LLDB_OPT_SET_1, false, "stdout", 'o', required_argument, NULL, 0, "<path>", "Redirect stdout for the process to <path>."}, 271 { LLDB_OPT_SET_1, false, "stderr", 'e', required_argument, NULL, 0, "<path>", "Redirect stderr for the process to <path>."}, 272 { LLDB_OPT_SET_1, false, "plugin", 'p', required_argument, NULL, 0, "<plugin>", "Name of the process plugin you want to use."}, 273 { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL } 274 }; 275 276 277 //------------------------------------------------------------------------- 278 // CommandObjectProcessAttach 279 //------------------------------------------------------------------------- 280 281 class CommandObjectProcessAttach : public CommandObject 282 { 283 public: 284 285 CommandObjectProcessAttach () : 286 CommandObject ("process attach", 287 "Attaches to a process.", 288 "process attach <cmd-options>") 289 { 290 SetHelpLong("Currently, you must set the executable file before you can attach " 291 "to a process.\n"); 292 } 293 294 ~CommandObjectProcessAttach () 295 { 296 } 297 298 bool 299 Execute (Args& command, 300 CommandContext *context, 301 CommandInterpreter *interpreter, 302 CommandReturnObject &result) 303 { 304 Target *target = context->GetTarget(); 305 if (target == NULL) 306 { 307 result.AppendError ("invalid target, set executable file using 'file' command"); 308 result.SetStatus (eReturnStatusFailed); 309 return false; 310 } 311 312 // If our listener is NULL, users aren't allows to launch 313 Listener *listener = interpreter->GetListener(); 314 if (listener == NULL) 315 { 316 result.AppendError ("operation not allowed through the command interpreter"); 317 result.SetStatus (eReturnStatusFailed); 318 return false; 319 } 320 Process *process = context->GetExecutionContext().process; 321 if (process) 322 { 323 if (process->IsAlive()) 324 { 325 result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before attaching.\n", process->GetID()); 326 result.SetStatus (eReturnStatusFailed); 327 return false; 328 } 329 } 330 331 if (command.GetArgumentCount()) 332 { 333 result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str()); 334 result.SetStatus (eReturnStatusFailed); 335 } 336 else 337 { 338 const char *plugin_name = NULL; 339 340 if (!m_options.plugin_name.empty()) 341 plugin_name = m_options.plugin_name.c_str(); 342 343 process = target->CreateProcess (*listener, plugin_name).get(); 344 345 if (process) 346 { 347 Error error; 348 int attach_pid = m_options.pid; 349 350 if (attach_pid != LLDB_INVALID_PROCESS_ID) 351 { 352 error = process->Attach (attach_pid); 353 if (error.Success()) 354 { 355 result.SetStatus (eReturnStatusSuccessContinuingNoResult); 356 } 357 else 358 { 359 result.AppendErrorWithFormat ("Attaching to process %i failed: %s.\n", 360 attach_pid, 361 error.AsCString()); 362 result.SetStatus (eReturnStatusFailed); 363 } 364 } 365 else if (!m_options.name.empty()) 366 { 367 error = process->Attach (m_options.name.c_str(), m_options.waitfor); 368 if (error.Success()) 369 { 370 result.SetStatus (eReturnStatusSuccessContinuingNoResult); 371 } 372 else 373 { 374 if (m_options.waitfor) 375 result.AppendErrorWithFormat ("Waiting for a process to launch named '%s': %s\n", 376 m_options.name.c_str(), 377 error.AsCString()); 378 else 379 result.AppendErrorWithFormat ("Failed to a process named '%s': %s\n", 380 m_options.name.c_str(), 381 error.AsCString()); 382 result.SetStatus (eReturnStatusFailed); 383 } 384 } 385 } 386 } 387 return result.Succeeded(); 388 } 389 390 Options * 391 GetOptions () 392 { 393 return &m_options; 394 } 395 396 class CommandOptions : public Options 397 { 398 public: 399 400 CommandOptions () : 401 Options() 402 { 403 // Keep default values of all options in one place: ResetOptionValues () 404 ResetOptionValues (); 405 } 406 407 ~CommandOptions () 408 { 409 } 410 411 Error 412 SetOptionValue (int option_idx, const char *option_arg) 413 { 414 Error error; 415 char short_option = (char) m_getopt_table[option_idx].val; 416 bool success = false; 417 switch (short_option) 418 { 419 case 'p': 420 pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success); 421 if (!success || pid == LLDB_INVALID_PROCESS_ID) 422 { 423 error.SetErrorStringWithFormat("Invalid process ID '%s'.\n", option_arg); 424 } 425 break; 426 427 case 'P': 428 plugin_name = option_arg; 429 break; 430 431 case 'n': 432 name.assign(option_arg); 433 break; 434 435 case 'w': 436 waitfor = true; 437 break; 438 439 default: 440 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option); 441 break; 442 } 443 return error; 444 } 445 446 void 447 ResetOptionValues () 448 { 449 Options::ResetOptionValues(); 450 pid = LLDB_INVALID_PROCESS_ID; 451 name.clear(); 452 waitfor = false; 453 } 454 455 const lldb::OptionDefinition* 456 GetDefinitions () 457 { 458 return g_option_table; 459 } 460 461 // Options table: Required for subclasses of Options. 462 463 static lldb::OptionDefinition g_option_table[]; 464 465 // Instance variables to hold the values for command options. 466 467 lldb::pid_t pid; 468 std::string plugin_name; 469 std::string name; 470 bool waitfor; 471 }; 472 473 protected: 474 475 CommandOptions m_options; 476 }; 477 478 479 lldb::OptionDefinition 480 CommandObjectProcessAttach::CommandOptions::g_option_table[] = 481 { 482 { LLDB_OPT_SET_ALL, false, "plugin", 'P', required_argument, NULL, 0, "<plugin>", "Name of the process plugin you want to use."}, 483 { LLDB_OPT_SET_1, false, "pid", 'p', required_argument, NULL, 0, "<pid>", "The process ID of an existing process to attach to."}, 484 { LLDB_OPT_SET_2, true, "name", 'n', required_argument, NULL, 0, "<process-name>", "The name of the process to attach to."}, 485 { LLDB_OPT_SET_2, false, "waitfor", 'w', no_argument, NULL, 0, NULL, "Wait for the the process with <process-name> to launch."}, 486 { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL } 487 }; 488 489 //------------------------------------------------------------------------- 490 // CommandObjectProcessContinue 491 //------------------------------------------------------------------------- 492 493 class CommandObjectProcessContinue : public CommandObject 494 { 495 public: 496 497 CommandObjectProcessContinue () : 498 CommandObject ("process continue", 499 "Continues execution all threads in the current process.", 500 "process continue", 501 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused) 502 { 503 } 504 505 506 ~CommandObjectProcessContinue () 507 { 508 } 509 510 bool 511 Execute (Args& command, 512 CommandContext *context, 513 CommandInterpreter *interpreter, 514 CommandReturnObject &result) 515 { 516 Process *process = context->GetExecutionContext().process; 517 bool synchronous_execution = interpreter->GetSynchronous (); 518 519 if (process == NULL) 520 { 521 result.AppendError ("no process to continue"); 522 result.SetStatus (eReturnStatusFailed); 523 return false; 524 } 525 526 StateType state = process->GetState(); 527 if (state == eStateStopped) 528 { 529 if (command.GetArgumentCount() != 0) 530 { 531 result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str()); 532 result.SetStatus (eReturnStatusFailed); 533 return false; 534 } 535 536 const uint32_t num_threads = process->GetThreadList().GetSize(); 537 538 // Set the actions that the threads should each take when resuming 539 for (uint32_t idx=0; idx<num_threads; ++idx) 540 { 541 process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning); 542 } 543 544 Error error(process->Resume()); 545 if (error.Success()) 546 { 547 result.AppendMessageWithFormat ("Resuming process %i\n", process->GetID()); 548 if (synchronous_execution) 549 { 550 StateType state = process->WaitForProcessToStop (NULL); 551 552 result.SetDidChangeProcessState (true); 553 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state)); 554 result.SetStatus (eReturnStatusSuccessFinishNoResult); 555 } 556 else 557 { 558 result.SetStatus (eReturnStatusSuccessContinuingNoResult); 559 } 560 } 561 else 562 { 563 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString()); 564 result.SetStatus (eReturnStatusFailed); 565 } 566 } 567 else 568 { 569 result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n", 570 StateAsCString(state)); 571 result.SetStatus (eReturnStatusFailed); 572 } 573 return result.Succeeded(); 574 } 575 }; 576 577 //------------------------------------------------------------------------- 578 // CommandObjectProcessDetach 579 //------------------------------------------------------------------------- 580 581 class CommandObjectProcessDetach : public CommandObject 582 { 583 public: 584 585 CommandObjectProcessDetach () : 586 CommandObject ("process detach", 587 "Detaches from the current process being debugged.", 588 "process detach", 589 eFlagProcessMustBeLaunched) 590 { 591 } 592 593 ~CommandObjectProcessDetach () 594 { 595 } 596 597 bool 598 Execute (Args& command, 599 CommandContext *context, 600 CommandInterpreter *interpreter, 601 CommandReturnObject &result) 602 { 603 Process *process = context->GetExecutionContext().process; 604 if (process == NULL) 605 { 606 result.AppendError ("must have a valid process in order to detach"); 607 result.SetStatus (eReturnStatusFailed); 608 return false; 609 } 610 611 Error error (process->Detach()); 612 if (error.Success()) 613 { 614 result.SetStatus (eReturnStatusSuccessFinishResult); 615 } 616 else 617 { 618 result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString()); 619 result.SetStatus (eReturnStatusFailed); 620 return false; 621 } 622 return result.Succeeded(); 623 } 624 }; 625 626 //------------------------------------------------------------------------- 627 // CommandObjectProcessSignal 628 //------------------------------------------------------------------------- 629 630 class CommandObjectProcessSignal : public CommandObject 631 { 632 public: 633 634 CommandObjectProcessSignal () : 635 CommandObject ("process signal", 636 "Sends a UNIX signal to the current process being debugged.", 637 "process signal <unix-signal-number>") 638 { 639 } 640 641 ~CommandObjectProcessSignal () 642 { 643 } 644 645 bool 646 Execute (Args& command, 647 CommandContext *context, 648 CommandInterpreter *interpreter, 649 CommandReturnObject &result) 650 { 651 Process *process = context->GetExecutionContext().process; 652 if (process == NULL) 653 { 654 result.AppendError ("no process to signal"); 655 result.SetStatus (eReturnStatusFailed); 656 return false; 657 } 658 659 if (command.GetArgumentCount() == 1) 660 { 661 int signo = Args::StringToSInt32(command.GetArgumentAtIndex(0), -1, 0); 662 if (signo == -1) 663 { 664 result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0)); 665 result.SetStatus (eReturnStatusFailed); 666 } 667 else 668 { 669 Error error (process->Signal (signo)); 670 if (error.Success()) 671 { 672 result.SetStatus (eReturnStatusSuccessFinishResult); 673 } 674 else 675 { 676 result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString()); 677 result.SetStatus (eReturnStatusFailed); 678 } 679 } 680 } 681 else 682 { 683 result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: \n", m_cmd_name.c_str(), 684 m_cmd_syntax.c_str()); 685 result.SetStatus (eReturnStatusFailed); 686 } 687 return result.Succeeded(); 688 } 689 }; 690 691 692 //------------------------------------------------------------------------- 693 // CommandObjectProcessInterrupt 694 //------------------------------------------------------------------------- 695 696 class CommandObjectProcessInterrupt : public CommandObject 697 { 698 public: 699 700 701 CommandObjectProcessInterrupt () : 702 CommandObject ("process interrupt", 703 "Interrupts the current process being debugged.", 704 "process interrupt", 705 eFlagProcessMustBeLaunched) 706 { 707 } 708 709 ~CommandObjectProcessInterrupt () 710 { 711 } 712 713 bool 714 Execute (Args& command, 715 CommandContext *context, 716 CommandInterpreter *interpreter, 717 CommandReturnObject &result) 718 { 719 Process *process = context->GetExecutionContext().process; 720 if (process == NULL) 721 { 722 result.AppendError ("no process to halt"); 723 result.SetStatus (eReturnStatusFailed); 724 return false; 725 } 726 727 if (command.GetArgumentCount() == 0) 728 { 729 Error error(process->Halt ()); 730 if (error.Success()) 731 { 732 result.SetStatus (eReturnStatusSuccessFinishResult); 733 734 // Maybe we should add a "SuspendThreadPlans so we 735 // can halt, and keep in place all the current thread plans. 736 process->GetThreadList().DiscardThreadPlans(); 737 } 738 else 739 { 740 result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString()); 741 result.SetStatus (eReturnStatusFailed); 742 } 743 } 744 else 745 { 746 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n", 747 m_cmd_name.c_str(), 748 m_cmd_syntax.c_str()); 749 result.SetStatus (eReturnStatusFailed); 750 } 751 return result.Succeeded(); 752 } 753 }; 754 755 //------------------------------------------------------------------------- 756 // CommandObjectProcessKill 757 //------------------------------------------------------------------------- 758 759 class CommandObjectProcessKill : public CommandObject 760 { 761 public: 762 763 CommandObjectProcessKill () : 764 CommandObject ("process kill", 765 "Terminates the current process being debugged.", 766 "process kill", 767 eFlagProcessMustBeLaunched) 768 { 769 } 770 771 ~CommandObjectProcessKill () 772 { 773 } 774 775 bool 776 Execute (Args& command, 777 CommandContext *context, 778 CommandInterpreter *interpreter, 779 CommandReturnObject &result) 780 { 781 Process *process = context->GetExecutionContext().process; 782 if (process == NULL) 783 { 784 result.AppendError ("no process to kill"); 785 result.SetStatus (eReturnStatusFailed); 786 return false; 787 } 788 789 if (command.GetArgumentCount() == 0) 790 { 791 Error error (process->Destroy()); 792 if (error.Success()) 793 { 794 result.SetStatus (eReturnStatusSuccessFinishResult); 795 } 796 else 797 { 798 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString()); 799 result.SetStatus (eReturnStatusFailed); 800 } 801 } 802 else 803 { 804 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n", 805 m_cmd_name.c_str(), 806 m_cmd_syntax.c_str()); 807 result.SetStatus (eReturnStatusFailed); 808 } 809 return result.Succeeded(); 810 } 811 }; 812 813 //------------------------------------------------------------------------- 814 // CommandObjectProcessStatus 815 //------------------------------------------------------------------------- 816 class CommandObjectProcessStatus : public CommandObject 817 { 818 public: 819 CommandObjectProcessStatus () : 820 CommandObject ("status", 821 "Shows the current status and location of executing process.", 822 "status", 823 0) 824 { 825 } 826 827 ~CommandObjectProcessStatus() 828 { 829 } 830 831 832 bool 833 Execute 834 ( 835 Args& command, 836 CommandContext *context, 837 CommandInterpreter *interpreter, 838 CommandReturnObject &result 839 ) 840 { 841 StreamString &output_stream = result.GetOutputStream(); 842 result.SetStatus (eReturnStatusSuccessFinishNoResult); 843 ExecutionContext exe_ctx(context->GetExecutionContext()); 844 if (exe_ctx.process) 845 { 846 const StateType state = exe_ctx.process->GetState(); 847 if (StateIsStoppedState(state)) 848 { 849 if (state == eStateExited) 850 { 851 int exit_status = exe_ctx.process->GetExitStatus(); 852 const char *exit_description = exe_ctx.process->GetExitDescription(); 853 output_stream.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n", 854 exe_ctx.process->GetID(), 855 exit_status, 856 exit_status, 857 exit_description ? exit_description : ""); 858 } 859 else 860 { 861 output_stream.Printf ("Process %d %s\n", exe_ctx.process->GetID(), StateAsCString (state)); 862 if (exe_ctx.thread == NULL) 863 exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get(); 864 if (exe_ctx.thread != NULL) 865 { 866 DisplayThreadsInfo (interpreter, &exe_ctx, result, true, true); 867 } 868 else 869 { 870 result.AppendError ("No valid thread found in current process."); 871 result.SetStatus (eReturnStatusFailed); 872 } 873 } 874 } 875 else 876 { 877 output_stream.Printf ("Process %d is running.\n", 878 exe_ctx.process->GetID()); 879 } 880 } 881 else 882 { 883 result.AppendError ("No current location or status available."); 884 result.SetStatus (eReturnStatusFailed); 885 } 886 return result.Succeeded(); 887 } 888 }; 889 890 //------------------------------------------------------------------------- 891 // CommandObjectMultiwordProcess 892 //------------------------------------------------------------------------- 893 894 CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter *interpreter) : 895 CommandObjectMultiword ("process", 896 "A set of commands for operating on a process.", 897 "process <subcommand> [<subcommand-options>]") 898 { 899 LoadSubCommand (CommandObjectSP (new CommandObjectProcessAttach ()), "attach", interpreter); 900 LoadSubCommand (CommandObjectSP (new CommandObjectProcessLaunch ()), "launch", interpreter); 901 LoadSubCommand (CommandObjectSP (new CommandObjectProcessContinue ()), "continue", interpreter); 902 LoadSubCommand (CommandObjectSP (new CommandObjectProcessDetach ()), "detach", interpreter); 903 LoadSubCommand (CommandObjectSP (new CommandObjectProcessSignal ()), "signal", interpreter); 904 LoadSubCommand (CommandObjectSP (new CommandObjectProcessStatus ()), "status", interpreter); 905 LoadSubCommand (CommandObjectSP (new CommandObjectProcessInterrupt ()), "interrupt", interpreter); 906 LoadSubCommand (CommandObjectSP (new CommandObjectProcessKill ()), "kill", interpreter); 907 } 908 909 CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess () 910 { 911 } 912 913