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/Host/Host.h" 23 #include "lldb/Target/Platform.h" 24 #include "lldb/Target/Process.h" 25 #include "lldb/Target/Target.h" 26 #include "lldb/Target/Thread.h" 27 28 using namespace lldb; 29 using namespace lldb_private; 30 31 //------------------------------------------------------------------------- 32 // CommandObjectProcessLaunch 33 //------------------------------------------------------------------------- 34 #pragma mark CommandObjectProjectLaunch 35 class CommandObjectProcessLaunch : public CommandObject 36 { 37 public: 38 39 class CommandOptions : public Options 40 { 41 public: 42 43 CommandOptions () : 44 Options() 45 { 46 // Keep default values of all options in one place: ResetOptionValues () 47 ResetOptionValues (); 48 } 49 50 ~CommandOptions () 51 { 52 } 53 54 Error 55 SetOptionValue (int option_idx, const char *option_arg) 56 { 57 Error error; 58 char short_option = (char) m_getopt_table[option_idx].val; 59 60 switch (short_option) 61 { 62 case 's': stop_at_entry = true; break; 63 case 'e': stderr_path.assign (option_arg); break; 64 case 'i': stdin_path.assign (option_arg); break; 65 case 'o': stdout_path.assign (option_arg); break; 66 case 'p': plugin_name.assign (option_arg); break; 67 case 'n': no_stdio = true; break; 68 case 'w': working_dir.assign (option_arg); break; 69 case 't': 70 if (option_arg && option_arg[0]) 71 tty_name.assign (option_arg); 72 in_new_tty = true; 73 break; 74 default: 75 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option); 76 break; 77 78 } 79 return error; 80 } 81 82 void 83 ResetOptionValues () 84 { 85 stop_at_entry = false; 86 in_new_tty = false; 87 tty_name.clear(); 88 stdin_path.clear(); 89 stdout_path.clear(); 90 stderr_path.clear(); 91 plugin_name.clear(); 92 working_dir.clear(); 93 no_stdio = false; 94 } 95 96 const OptionDefinition* 97 GetDefinitions () 98 { 99 return g_option_table; 100 } 101 102 // Options table: Required for subclasses of Options. 103 104 static OptionDefinition g_option_table[]; 105 106 // Instance variables to hold the values for command options. 107 108 bool stop_at_entry; 109 bool in_new_tty; 110 bool no_stdio; 111 std::string tty_name; 112 std::string stderr_path; 113 std::string stdin_path; 114 std::string stdout_path; 115 std::string plugin_name; 116 std::string working_dir; 117 118 }; 119 120 CommandObjectProcessLaunch (CommandInterpreter &interpreter) : 121 CommandObject (interpreter, 122 "process launch", 123 "Launch the executable in the debugger.", 124 NULL) 125 { 126 CommandArgumentEntry arg; 127 CommandArgumentData run_args_arg; 128 129 // Define the first (and only) variant of this arg. 130 run_args_arg.arg_type = eArgTypeRunArgs; 131 run_args_arg.arg_repetition = eArgRepeatOptional; 132 133 // There is only one variant this argument could be; put it into the argument entry. 134 arg.push_back (run_args_arg); 135 136 // Push the data for the first argument into the m_arguments vector. 137 m_arguments.push_back (arg); 138 } 139 140 141 ~CommandObjectProcessLaunch () 142 { 143 } 144 145 Options * 146 GetOptions () 147 { 148 return &m_options; 149 } 150 151 bool 152 Execute (Args& launch_args, CommandReturnObject &result) 153 { 154 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 155 156 if (target == NULL) 157 { 158 result.AppendError ("invalid target, set executable file using 'file' command"); 159 result.SetStatus (eReturnStatusFailed); 160 return false; 161 } 162 163 // If our listener is NULL, users aren't allows to launch 164 char filename[PATH_MAX]; 165 const Module *exe_module = target->GetExecutableModule().get(); 166 167 if (exe_module == NULL) 168 { 169 result.AppendError ("no file in target, set executable file using 'file' command"); 170 result.SetStatus (eReturnStatusFailed); 171 return false; 172 } 173 174 exe_module->GetFileSpec().GetPath(filename, sizeof(filename)); 175 176 StateType state = eStateInvalid; 177 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; 178 if (process) 179 { 180 state = process->GetState(); 181 182 if (process->IsAlive() && state != eStateConnected) 183 { 184 char message[1024]; 185 if (process->GetState() == eStateAttaching) 186 ::strncpy (message, "There is a pending attach, abort it and launch a new process?", sizeof(message)); 187 else 188 ::strncpy (message, "There is a running process, kill it and restart?", sizeof(message)); 189 190 if (!m_interpreter.Confirm (message, true)) 191 { 192 result.SetStatus (eReturnStatusFailed); 193 return false; 194 } 195 else 196 { 197 Error error (process->Destroy()); 198 if (error.Success()) 199 { 200 result.SetStatus (eReturnStatusSuccessFinishResult); 201 } 202 else 203 { 204 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString()); 205 result.SetStatus (eReturnStatusFailed); 206 } 207 } 208 } 209 } 210 211 if (state != eStateConnected) 212 { 213 const char *plugin_name; 214 if (!m_options.plugin_name.empty()) 215 plugin_name = m_options.plugin_name.c_str(); 216 else 217 plugin_name = NULL; 218 219 process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get(); 220 if (process == NULL) 221 { 222 result.AppendErrorWithFormat ("Failed to find a process plugin for executable.\n"); 223 result.SetStatus (eReturnStatusFailed); 224 return false; 225 } 226 } 227 228 229 // If no launch args were given on the command line, then use any that 230 // might have been set using the "run-args" set variable. 231 if (launch_args.GetArgumentCount() == 0) 232 { 233 if (process->GetRunArguments().GetArgumentCount() > 0) 234 launch_args = process->GetRunArguments(); 235 } 236 237 if (m_options.in_new_tty) 238 { 239 if (state == eStateConnected) 240 { 241 result.AppendWarning("launch in tty option is ignored when launching through a remote connection"); 242 m_options.in_new_tty = false; 243 } 244 else 245 { 246 char exec_file_path[PATH_MAX]; 247 if (exe_module->GetFileSpec().GetPath(exec_file_path, sizeof(exec_file_path))) 248 { 249 launch_args.InsertArgumentAtIndex(0, exec_file_path); 250 } 251 else 252 { 253 result.AppendError("invalid executable"); 254 result.SetStatus (eReturnStatusFailed); 255 return false; 256 } 257 } 258 } 259 260 Args environment; 261 262 process->GetEnvironmentAsArgs (environment); 263 264 uint32_t launch_flags = eLaunchFlagNone; 265 266 if (process->GetDisableASLR()) 267 launch_flags |= eLaunchFlagDisableASLR; 268 269 if (m_options.no_stdio) 270 launch_flags |= eLaunchFlagDisableSTDIO; 271 else if (!m_options.in_new_tty 272 && m_options.stdin_path.empty() 273 && m_options.stdout_path.empty() 274 && m_options.stderr_path.empty()) 275 { 276 // Only use the settings value if the user hasn't specified any options that would override it. 277 if (process->GetDisableSTDIO()) 278 launch_flags |= eLaunchFlagDisableSTDIO; 279 } 280 281 const char **inferior_argv = launch_args.GetArgumentCount() ? launch_args.GetConstArgumentVector() : NULL; 282 const char **inferior_envp = environment.GetArgumentCount() ? environment.GetConstArgumentVector() : NULL; 283 284 Error error; 285 const char *working_dir = NULL; 286 if (!m_options.working_dir.empty()) 287 working_dir = m_options.working_dir.c_str(); 288 289 if (m_options.in_new_tty) 290 { 291 292 lldb::pid_t pid = Host::LaunchInNewTerminal (m_options.tty_name.c_str(), 293 inferior_argv, 294 inferior_envp, 295 working_dir, 296 &exe_module->GetArchitecture(), 297 true, 298 process->GetDisableASLR()); 299 300 if (pid != LLDB_INVALID_PROCESS_ID) 301 error = process->Attach (pid); 302 } 303 else 304 { 305 const char * stdin_path = NULL; 306 const char * stdout_path = NULL; 307 const char * stderr_path = NULL; 308 309 // Were any standard input/output/error paths given on the command line? 310 if (m_options.stdin_path.empty() && 311 m_options.stdout_path.empty() && 312 m_options.stderr_path.empty()) 313 { 314 // No standard file handles were given on the command line, check 315 // with the process object in case they were give using "set settings" 316 stdin_path = process->GetStandardInputPath(); 317 stdout_path = process->GetStandardOutputPath(); 318 stderr_path = process->GetStandardErrorPath(); 319 } 320 else 321 { 322 stdin_path = m_options.stdin_path.empty() ? NULL : m_options.stdin_path.c_str(); 323 stdout_path = m_options.stdout_path.empty() ? NULL : m_options.stdout_path.c_str(); 324 stderr_path = m_options.stderr_path.empty() ? NULL : m_options.stderr_path.c_str(); 325 } 326 327 error = process->Launch (inferior_argv, 328 inferior_envp, 329 launch_flags, 330 stdin_path, 331 stdout_path, 332 stderr_path, 333 working_dir); 334 } 335 336 if (error.Success()) 337 { 338 const char *archname = exe_module->GetArchitecture().GetArchitectureName(); 339 340 result.AppendMessageWithFormat ("Process %i launched: '%s' (%s)\n", process->GetID(), filename, archname); 341 result.SetDidChangeProcessState (true); 342 if (m_options.stop_at_entry == false) 343 { 344 result.SetStatus (eReturnStatusSuccessContinuingNoResult); 345 StateType state = process->WaitForProcessToStop (NULL); 346 347 if (state == eStateStopped) 348 { 349 error = process->Resume(); 350 if (error.Success()) 351 { 352 bool synchronous_execution = m_interpreter.GetSynchronous (); 353 if (synchronous_execution) 354 { 355 state = process->WaitForProcessToStop (NULL); 356 if (!StateIsStoppedState(state)) 357 { 358 result.AppendErrorWithFormat ("Process isn't stopped: %s", StateAsCString(state)); 359 } 360 result.SetDidChangeProcessState (true); 361 result.SetStatus (eReturnStatusSuccessFinishResult); 362 } 363 else 364 { 365 result.SetStatus (eReturnStatusSuccessContinuingNoResult); 366 } 367 } 368 else 369 { 370 result.AppendErrorWithFormat ("Process resume at entry point failed: %s", error.AsCString()); 371 result.SetStatus (eReturnStatusFailed); 372 } 373 } 374 else 375 { 376 result.AppendErrorWithFormat ("Initial process state wasn't stopped: %s", StateAsCString(state)); 377 result.SetStatus (eReturnStatusFailed); 378 } 379 } 380 } 381 else 382 { 383 result.AppendErrorWithFormat ("Process launch failed: %s", error.AsCString()); 384 result.SetStatus (eReturnStatusFailed); 385 } 386 387 return result.Succeeded(); 388 } 389 390 virtual const char *GetRepeatCommand (Args ¤t_command_args, uint32_t index) 391 { 392 // No repeat for "process launch"... 393 return ""; 394 } 395 396 protected: 397 398 CommandOptions m_options; 399 }; 400 401 402 #define SET1 LLDB_OPT_SET_1 403 #define SET2 LLDB_OPT_SET_2 404 #define SET3 LLDB_OPT_SET_3 405 406 OptionDefinition 407 CommandObjectProcessLaunch::CommandOptions::g_option_table[] = 408 { 409 { SET1 | SET2 | SET3, false, "stop-at-entry", 's', no_argument, NULL, 0, eArgTypeNone, "Stop at the entry point of the program when launching a process."}, 410 { SET1 , false, "stdin", 'i', required_argument, NULL, 0, eArgTypePath, "Redirect stdin for the process to <path>."}, 411 { SET1 , false, "stdout", 'o', required_argument, NULL, 0, eArgTypePath, "Redirect stdout for the process to <path>."}, 412 { SET1 , false, "stderr", 'e', required_argument, NULL, 0, eArgTypePath, "Redirect stderr for the process to <path>."}, 413 { SET1 | SET2 | SET3, false, "plugin", 'p', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."}, 414 { SET2 , false, "tty", 't', optional_argument, NULL, 0, eArgTypePath, "Start the process in a terminal. If <path> is specified, look for a terminal whose name contains <path>, else start the process in a new terminal."}, 415 { SET3, false, "no-stdio", 'n', no_argument, NULL, 0, eArgTypeNone, "Do not set up for terminal I/O to go to running process."}, 416 { SET1 | SET2 | SET3, false, "working-dir", 'w', required_argument, NULL, 0, eArgTypePath, "Set the current working directory to <path> when running the inferior."}, 417 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 418 }; 419 420 #undef SET1 421 #undef SET2 422 #undef SET3 423 424 //------------------------------------------------------------------------- 425 // CommandObjectProcessAttach 426 //------------------------------------------------------------------------- 427 #pragma mark CommandObjectProcessAttach 428 class CommandObjectProcessAttach : public CommandObject 429 { 430 public: 431 432 class CommandOptions : public Options 433 { 434 public: 435 436 CommandOptions () : 437 Options() 438 { 439 // Keep default values of all options in one place: ResetOptionValues () 440 ResetOptionValues (); 441 } 442 443 ~CommandOptions () 444 { 445 } 446 447 Error 448 SetOptionValue (int option_idx, const char *option_arg) 449 { 450 Error error; 451 char short_option = (char) m_getopt_table[option_idx].val; 452 bool success = false; 453 switch (short_option) 454 { 455 case 'p': 456 pid = Args::StringToUInt32 (option_arg, LLDB_INVALID_PROCESS_ID, 0, &success); 457 if (!success || pid == LLDB_INVALID_PROCESS_ID) 458 { 459 error.SetErrorStringWithFormat("Invalid process ID '%s'.\n", option_arg); 460 } 461 break; 462 463 case 'P': 464 plugin_name = option_arg; 465 break; 466 467 case 'n': 468 name.assign(option_arg); 469 break; 470 471 case 'w': 472 waitfor = true; 473 break; 474 475 default: 476 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option); 477 break; 478 } 479 return error; 480 } 481 482 void 483 ResetOptionValues () 484 { 485 pid = LLDB_INVALID_PROCESS_ID; 486 name.clear(); 487 waitfor = false; 488 } 489 490 const OptionDefinition* 491 GetDefinitions () 492 { 493 return g_option_table; 494 } 495 496 virtual bool 497 HandleOptionArgumentCompletion (CommandInterpreter &interpeter, 498 Args &input, 499 int cursor_index, 500 int char_pos, 501 OptionElementVector &opt_element_vector, 502 int opt_element_index, 503 int match_start_point, 504 int max_return_elements, 505 bool &word_complete, 506 StringList &matches) 507 { 508 int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos; 509 int opt_defs_index = opt_element_vector[opt_element_index].opt_defs_index; 510 511 // We are only completing the name option for now... 512 513 const OptionDefinition *opt_defs = GetDefinitions(); 514 if (opt_defs[opt_defs_index].short_option == 'n') 515 { 516 // Are we in the name? 517 518 // Look to see if there is a -P argument provided, and if so use that plugin, otherwise 519 // use the default plugin. 520 521 const char *partial_name = NULL; 522 partial_name = input.GetArgumentAtIndex(opt_arg_pos); 523 524 PlatformSP platform_sp (interpeter.GetDebugger().GetPlatformList().GetSelectedPlatform ()); 525 if (platform_sp) 526 { 527 ProcessInfoList process_infos; 528 ProcessInfoMatch match_info; 529 if (partial_name) 530 { 531 match_info.GetProcessInfo().SetName(partial_name); 532 match_info.SetNameMatchType(eNameMatchStartsWith); 533 } 534 platform_sp->FindProcesses (match_info, process_infos); 535 const uint32_t num_matches = process_infos.GetSize(); 536 if (num_matches > 0) 537 { 538 for (uint32_t i=0; i<num_matches; ++i) 539 { 540 matches.AppendString (process_infos.GetProcessNameAtIndex(i), 541 process_infos.GetProcessNameLengthAtIndex(i)); 542 } 543 } 544 } 545 } 546 547 return false; 548 } 549 550 // Options table: Required for subclasses of Options. 551 552 static OptionDefinition g_option_table[]; 553 554 // Instance variables to hold the values for command options. 555 556 lldb::pid_t pid; 557 std::string plugin_name; 558 std::string name; 559 bool waitfor; 560 }; 561 562 CommandObjectProcessAttach (CommandInterpreter &interpreter) : 563 CommandObject (interpreter, 564 "process attach", 565 "Attach to a process.", 566 "process attach <cmd-options>") 567 { 568 } 569 570 ~CommandObjectProcessAttach () 571 { 572 } 573 574 bool 575 Execute (Args& command, 576 CommandReturnObject &result) 577 { 578 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 579 bool synchronous_execution = m_interpreter.GetSynchronous (); 580 581 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; 582 StateType state = eStateInvalid; 583 if (process) 584 { 585 state = process->GetState(); 586 if (process->IsAlive() && state != eStateConnected) 587 { 588 result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before attaching.\n", 589 process->GetID()); 590 result.SetStatus (eReturnStatusFailed); 591 return false; 592 } 593 } 594 595 if (target == NULL) 596 { 597 // If there isn't a current target create one. 598 TargetSP new_target_sp; 599 FileSpec emptyFileSpec; 600 ArchSpec emptyArchSpec; 601 Error error; 602 603 error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(), 604 emptyFileSpec, 605 emptyArchSpec, 606 false, 607 new_target_sp); 608 target = new_target_sp.get(); 609 if (target == NULL || error.Fail()) 610 { 611 result.AppendError(error.AsCString("Error creating target")); 612 return false; 613 } 614 m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target); 615 } 616 617 // Record the old executable module, we want to issue a warning if the process of attaching changed the 618 // current executable (like somebody said "file foo" then attached to a PID whose executable was bar.) 619 620 ModuleSP old_exec_module_sp = target->GetExecutableModule(); 621 ArchSpec old_arch_spec = target->GetArchitecture(); 622 623 if (command.GetArgumentCount()) 624 { 625 result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: \n", m_cmd_name.c_str(), m_cmd_syntax.c_str()); 626 result.SetStatus (eReturnStatusFailed); 627 } 628 else 629 { 630 if (state != eStateConnected) 631 { 632 const char *plugin_name = NULL; 633 634 if (!m_options.plugin_name.empty()) 635 plugin_name = m_options.plugin_name.c_str(); 636 637 process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get(); 638 } 639 640 if (process) 641 { 642 Error error; 643 int attach_pid = m_options.pid; 644 645 const char *wait_name = NULL; 646 647 if (m_options.name.empty()) 648 { 649 if (old_exec_module_sp) 650 { 651 wait_name = old_exec_module_sp->GetFileSpec().GetFilename().AsCString(); 652 } 653 } 654 else 655 { 656 wait_name = m_options.name.c_str(); 657 } 658 659 // If we are waiting for a process with this name to show up, do that first. 660 if (m_options.waitfor) 661 { 662 663 if (wait_name == NULL) 664 { 665 result.AppendError("Invalid arguments: must have a file loaded or supply a process name with the waitfor option.\n"); 666 result.SetStatus (eReturnStatusFailed); 667 return false; 668 } 669 670 result.AppendMessageWithFormat("Waiting to attach to a process named \"%s\".\n", wait_name); 671 error = process->Attach (wait_name, m_options.waitfor); 672 if (error.Success()) 673 { 674 result.SetStatus (eReturnStatusSuccessContinuingNoResult); 675 } 676 else 677 { 678 result.AppendErrorWithFormat ("Waiting for a process to launch named '%s': %s\n", 679 wait_name, 680 error.AsCString()); 681 result.SetStatus (eReturnStatusFailed); 682 return false; 683 } 684 // If we're synchronous, wait for the stopped event and report that. 685 // Otherwise just return. 686 // FIXME: in the async case it will now be possible to get to the command 687 // interpreter with a state eStateAttaching. Make sure we handle that correctly. 688 if (synchronous_execution) 689 { 690 StateType state = process->WaitForProcessToStop (NULL); 691 692 result.SetDidChangeProcessState (true); 693 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state)); 694 result.SetStatus (eReturnStatusSuccessFinishNoResult); 695 } 696 else 697 { 698 result.SetDidChangeProcessState (true); 699 result.SetStatus (eReturnStatusSuccessFinishNoResult); 700 } 701 } 702 else 703 { 704 // If the process was specified by name look it up, so we can warn if there are multiple 705 // processes with this pid. 706 707 if (attach_pid == LLDB_INVALID_PROCESS_ID && wait_name != NULL) 708 { 709 ProcessInfoList process_infos; 710 PlatformSP platform_sp (m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform ()); 711 if (platform_sp) 712 { 713 ProcessInfoMatch match_info (wait_name, eNameMatchEquals); 714 platform_sp->FindProcesses (match_info, process_infos); 715 } 716 if (process_infos.GetSize() > 1) 717 { 718 result.AppendErrorWithFormat("More than one process named %s\n", wait_name); 719 result.SetStatus (eReturnStatusFailed); 720 return false; 721 } 722 else if (process_infos.GetSize() == 0) 723 { 724 result.AppendErrorWithFormat("Could not find a process named %s\n", wait_name); 725 result.SetStatus (eReturnStatusFailed); 726 return false; 727 } 728 else 729 { 730 attach_pid = process_infos.GetProcessIDAtIndex (0); 731 } 732 } 733 734 if (attach_pid != LLDB_INVALID_PROCESS_ID) 735 { 736 error = process->Attach (attach_pid); 737 if (error.Success()) 738 { 739 result.SetStatus (eReturnStatusSuccessContinuingNoResult); 740 } 741 else 742 { 743 result.AppendErrorWithFormat ("Attaching to process %i failed: %s.\n", 744 attach_pid, 745 error.AsCString()); 746 result.SetStatus (eReturnStatusFailed); 747 } 748 // See comment for synchronous_execution above. 749 if (synchronous_execution) 750 { 751 StateType state = process->WaitForProcessToStop (NULL); 752 753 result.SetDidChangeProcessState (true); 754 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state)); 755 result.SetStatus (eReturnStatusSuccessFinishNoResult); 756 } 757 else 758 { 759 result.SetDidChangeProcessState (true); 760 result.SetStatus (eReturnStatusSuccessFinishNoResult); 761 } 762 } 763 else 764 { 765 result.AppendErrorWithFormat ("No PID specified for attach\n", 766 attach_pid, 767 error.AsCString()); 768 result.SetStatus (eReturnStatusFailed); 769 770 } 771 } 772 } 773 } 774 775 if (result.Succeeded()) 776 { 777 // Okay, we're done. Last step is to warn if the executable module has changed: 778 char new_path[PATH_MAX]; 779 if (!old_exec_module_sp) 780 { 781 // We might not have a module if we attached to a raw pid... 782 ModuleSP new_module_sp (target->GetExecutableModule()); 783 if (new_module_sp) 784 { 785 new_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX); 786 result.AppendMessageWithFormat("Executable module set to \"%s\".\n", new_path); 787 } 788 } 789 else if (old_exec_module_sp->GetFileSpec() != target->GetExecutableModule()->GetFileSpec()) 790 { 791 char old_path[PATH_MAX]; 792 793 old_exec_module_sp->GetFileSpec().GetPath(old_path, PATH_MAX); 794 target->GetExecutableModule()->GetFileSpec().GetPath (new_path, PATH_MAX); 795 796 result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n", 797 old_path, new_path); 798 } 799 800 if (!old_arch_spec.IsValid()) 801 { 802 result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().GetArchitectureName()); 803 } 804 else if (old_arch_spec != target->GetArchitecture()) 805 { 806 result.AppendWarningWithFormat("Architecture changed from %s to %s.\n", 807 old_arch_spec.GetArchitectureName(), target->GetArchitecture().GetArchitectureName()); 808 } 809 } 810 return result.Succeeded(); 811 } 812 813 Options * 814 GetOptions () 815 { 816 return &m_options; 817 } 818 819 protected: 820 821 CommandOptions m_options; 822 }; 823 824 825 OptionDefinition 826 CommandObjectProcessAttach::CommandOptions::g_option_table[] = 827 { 828 { LLDB_OPT_SET_ALL, false, "plugin", 'P', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."}, 829 { LLDB_OPT_SET_1, false, "pid", 'p', required_argument, NULL, 0, eArgTypePid, "The process ID of an existing process to attach to."}, 830 { LLDB_OPT_SET_2, false, "name", 'n', required_argument, NULL, 0, eArgTypeProcessName, "The name of the process to attach to."}, 831 { LLDB_OPT_SET_2, false, "waitfor",'w', no_argument, NULL, 0, eArgTypeNone, "Wait for the the process with <process-name> to launch."}, 832 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 833 }; 834 835 //------------------------------------------------------------------------- 836 // CommandObjectProcessContinue 837 //------------------------------------------------------------------------- 838 #pragma mark CommandObjectProcessContinue 839 840 class CommandObjectProcessContinue : public CommandObject 841 { 842 public: 843 844 CommandObjectProcessContinue (CommandInterpreter &interpreter) : 845 CommandObject (interpreter, 846 "process continue", 847 "Continue execution of all threads in the current process.", 848 "process continue", 849 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused) 850 { 851 } 852 853 854 ~CommandObjectProcessContinue () 855 { 856 } 857 858 bool 859 Execute (Args& command, 860 CommandReturnObject &result) 861 { 862 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; 863 bool synchronous_execution = m_interpreter.GetSynchronous (); 864 865 if (process == NULL) 866 { 867 result.AppendError ("no process to continue"); 868 result.SetStatus (eReturnStatusFailed); 869 return false; 870 } 871 872 StateType state = process->GetState(); 873 if (state == eStateStopped) 874 { 875 if (command.GetArgumentCount() != 0) 876 { 877 result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str()); 878 result.SetStatus (eReturnStatusFailed); 879 return false; 880 } 881 882 const uint32_t num_threads = process->GetThreadList().GetSize(); 883 884 // Set the actions that the threads should each take when resuming 885 for (uint32_t idx=0; idx<num_threads; ++idx) 886 { 887 process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning); 888 } 889 890 Error error(process->Resume()); 891 if (error.Success()) 892 { 893 result.AppendMessageWithFormat ("Process %i resuming\n", process->GetID()); 894 if (synchronous_execution) 895 { 896 state = process->WaitForProcessToStop (NULL); 897 898 result.SetDidChangeProcessState (true); 899 result.AppendMessageWithFormat ("Process %i %s\n", process->GetID(), StateAsCString (state)); 900 result.SetStatus (eReturnStatusSuccessFinishNoResult); 901 } 902 else 903 { 904 result.SetStatus (eReturnStatusSuccessContinuingNoResult); 905 } 906 } 907 else 908 { 909 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString()); 910 result.SetStatus (eReturnStatusFailed); 911 } 912 } 913 else 914 { 915 result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n", 916 StateAsCString(state)); 917 result.SetStatus (eReturnStatusFailed); 918 } 919 return result.Succeeded(); 920 } 921 }; 922 923 //------------------------------------------------------------------------- 924 // CommandObjectProcessDetach 925 //------------------------------------------------------------------------- 926 #pragma mark CommandObjectProcessDetach 927 928 class CommandObjectProcessDetach : public CommandObject 929 { 930 public: 931 932 CommandObjectProcessDetach (CommandInterpreter &interpreter) : 933 CommandObject (interpreter, 934 "process detach", 935 "Detach from the current process being debugged.", 936 "process detach", 937 eFlagProcessMustBeLaunched) 938 { 939 } 940 941 ~CommandObjectProcessDetach () 942 { 943 } 944 945 bool 946 Execute (Args& command, 947 CommandReturnObject &result) 948 { 949 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; 950 if (process == NULL) 951 { 952 result.AppendError ("must have a valid process in order to detach"); 953 result.SetStatus (eReturnStatusFailed); 954 return false; 955 } 956 957 result.AppendMessageWithFormat ("Detaching from process %i\n", process->GetID()); 958 Error error (process->Detach()); 959 if (error.Success()) 960 { 961 result.SetStatus (eReturnStatusSuccessFinishResult); 962 } 963 else 964 { 965 result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString()); 966 result.SetStatus (eReturnStatusFailed); 967 return false; 968 } 969 return result.Succeeded(); 970 } 971 }; 972 973 //------------------------------------------------------------------------- 974 // CommandObjectProcessConnect 975 //------------------------------------------------------------------------- 976 #pragma mark CommandObjectProcessConnect 977 978 class CommandObjectProcessConnect : public CommandObject 979 { 980 public: 981 982 class CommandOptions : public Options 983 { 984 public: 985 986 CommandOptions () : 987 Options() 988 { 989 // Keep default values of all options in one place: ResetOptionValues () 990 ResetOptionValues (); 991 } 992 993 ~CommandOptions () 994 { 995 } 996 997 Error 998 SetOptionValue (int option_idx, const char *option_arg) 999 { 1000 Error error; 1001 char short_option = (char) m_getopt_table[option_idx].val; 1002 1003 switch (short_option) 1004 { 1005 case 'p': 1006 plugin_name.assign (option_arg); 1007 break; 1008 1009 default: 1010 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option); 1011 break; 1012 } 1013 return error; 1014 } 1015 1016 void 1017 ResetOptionValues () 1018 { 1019 plugin_name.clear(); 1020 } 1021 1022 const OptionDefinition* 1023 GetDefinitions () 1024 { 1025 return g_option_table; 1026 } 1027 1028 // Options table: Required for subclasses of Options. 1029 1030 static OptionDefinition g_option_table[]; 1031 1032 // Instance variables to hold the values for command options. 1033 1034 std::string plugin_name; 1035 }; 1036 1037 CommandObjectProcessConnect (CommandInterpreter &interpreter) : 1038 CommandObject (interpreter, 1039 "process connect", 1040 "Connect to a remote debug service.", 1041 "process connect <remote-url>", 1042 0) 1043 { 1044 } 1045 1046 ~CommandObjectProcessConnect () 1047 { 1048 } 1049 1050 1051 bool 1052 Execute (Args& command, 1053 CommandReturnObject &result) 1054 { 1055 1056 TargetSP target_sp (m_interpreter.GetDebugger().GetSelectedTarget()); 1057 Error error; 1058 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; 1059 if (process) 1060 { 1061 if (process->IsAlive()) 1062 { 1063 result.AppendErrorWithFormat ("Process %u is currently being debugged, kill the process before connecting.\n", 1064 process->GetID()); 1065 result.SetStatus (eReturnStatusFailed); 1066 return false; 1067 } 1068 } 1069 1070 if (!target_sp) 1071 { 1072 // If there isn't a current target create one. 1073 FileSpec emptyFileSpec; 1074 ArchSpec emptyArchSpec; 1075 1076 error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(), 1077 emptyFileSpec, 1078 emptyArchSpec, 1079 false, 1080 target_sp); 1081 if (!target_sp || error.Fail()) 1082 { 1083 result.AppendError(error.AsCString("Error creating target")); 1084 result.SetStatus (eReturnStatusFailed); 1085 return false; 1086 } 1087 m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target_sp.get()); 1088 } 1089 1090 if (command.GetArgumentCount() == 1) 1091 { 1092 const char *plugin_name = NULL; 1093 if (!m_options.plugin_name.empty()) 1094 plugin_name = m_options.plugin_name.c_str(); 1095 1096 const char *remote_url = command.GetArgumentAtIndex(0); 1097 process = target_sp->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get(); 1098 1099 if (process) 1100 { 1101 error = process->ConnectRemote (remote_url); 1102 1103 if (error.Fail()) 1104 { 1105 result.AppendError(error.AsCString("Remote connect failed")); 1106 result.SetStatus (eReturnStatusFailed); 1107 return false; 1108 } 1109 } 1110 else 1111 { 1112 result.AppendErrorWithFormat ("Unable to find process plug-in for remote URL '%s'.\nPlease specify a process plug-in name with the --plugin option, or specify an object file using the \"file\" command: \n", 1113 m_cmd_name.c_str(), 1114 m_cmd_syntax.c_str()); 1115 result.SetStatus (eReturnStatusFailed); 1116 } 1117 } 1118 else 1119 { 1120 result.AppendErrorWithFormat ("'%s' takes exactly one argument:\nUsage: \n", 1121 m_cmd_name.c_str(), 1122 m_cmd_syntax.c_str()); 1123 result.SetStatus (eReturnStatusFailed); 1124 } 1125 return result.Succeeded(); 1126 } 1127 1128 Options * 1129 GetOptions () 1130 { 1131 return &m_options; 1132 } 1133 1134 protected: 1135 1136 CommandOptions m_options; 1137 }; 1138 1139 1140 OptionDefinition 1141 CommandObjectProcessConnect::CommandOptions::g_option_table[] = 1142 { 1143 { LLDB_OPT_SET_ALL, false, "plugin", 'p', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."}, 1144 { 0, false, NULL, 0 , 0, NULL, 0, eArgTypeNone, NULL } 1145 }; 1146 1147 //------------------------------------------------------------------------- 1148 // CommandObjectProcessLoad 1149 //------------------------------------------------------------------------- 1150 #pragma mark CommandObjectProcessLoad 1151 1152 class CommandObjectProcessLoad : public CommandObject 1153 { 1154 public: 1155 1156 CommandObjectProcessLoad (CommandInterpreter &interpreter) : 1157 CommandObject (interpreter, 1158 "process load", 1159 "Load a shared library into the current process.", 1160 "process load <filename> [<filename> ...]", 1161 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused) 1162 { 1163 } 1164 1165 ~CommandObjectProcessLoad () 1166 { 1167 } 1168 1169 bool 1170 Execute (Args& command, 1171 CommandReturnObject &result) 1172 { 1173 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; 1174 if (process == NULL) 1175 { 1176 result.AppendError ("must have a valid process in order to load a shared library"); 1177 result.SetStatus (eReturnStatusFailed); 1178 return false; 1179 } 1180 1181 const uint32_t argc = command.GetArgumentCount(); 1182 1183 for (uint32_t i=0; i<argc; ++i) 1184 { 1185 Error error; 1186 const char *image_path = command.GetArgumentAtIndex(i); 1187 FileSpec image_spec (image_path, false); 1188 uint32_t image_token = process->LoadImage(image_spec, error); 1189 if (image_token != LLDB_INVALID_IMAGE_TOKEN) 1190 { 1191 result.AppendMessageWithFormat ("Loading \"%s\"...ok\nImage %u loaded.\n", image_path, image_token); 1192 result.SetStatus (eReturnStatusSuccessFinishResult); 1193 } 1194 else 1195 { 1196 result.AppendErrorWithFormat ("failed to load '%s': %s", image_path, error.AsCString()); 1197 result.SetStatus (eReturnStatusFailed); 1198 } 1199 } 1200 return result.Succeeded(); 1201 } 1202 }; 1203 1204 1205 //------------------------------------------------------------------------- 1206 // CommandObjectProcessUnload 1207 //------------------------------------------------------------------------- 1208 #pragma mark CommandObjectProcessUnload 1209 1210 class CommandObjectProcessUnload : public CommandObject 1211 { 1212 public: 1213 1214 CommandObjectProcessUnload (CommandInterpreter &interpreter) : 1215 CommandObject (interpreter, 1216 "process unload", 1217 "Unload a shared library from the current process using the index returned by a previous call to \"process load\".", 1218 "process unload <index>", 1219 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused) 1220 { 1221 } 1222 1223 ~CommandObjectProcessUnload () 1224 { 1225 } 1226 1227 bool 1228 Execute (Args& command, 1229 CommandReturnObject &result) 1230 { 1231 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; 1232 if (process == NULL) 1233 { 1234 result.AppendError ("must have a valid process in order to load a shared library"); 1235 result.SetStatus (eReturnStatusFailed); 1236 return false; 1237 } 1238 1239 const uint32_t argc = command.GetArgumentCount(); 1240 1241 for (uint32_t i=0; i<argc; ++i) 1242 { 1243 const char *image_token_cstr = command.GetArgumentAtIndex(i); 1244 uint32_t image_token = Args::StringToUInt32(image_token_cstr, LLDB_INVALID_IMAGE_TOKEN, 0); 1245 if (image_token == LLDB_INVALID_IMAGE_TOKEN) 1246 { 1247 result.AppendErrorWithFormat ("invalid image index argument '%s'", image_token_cstr); 1248 result.SetStatus (eReturnStatusFailed); 1249 break; 1250 } 1251 else 1252 { 1253 Error error (process->UnloadImage(image_token)); 1254 if (error.Success()) 1255 { 1256 result.AppendMessageWithFormat ("Unloading shared library with index %u...ok\n", image_token); 1257 result.SetStatus (eReturnStatusSuccessFinishResult); 1258 } 1259 else 1260 { 1261 result.AppendErrorWithFormat ("failed to unload image: %s", error.AsCString()); 1262 result.SetStatus (eReturnStatusFailed); 1263 break; 1264 } 1265 } 1266 } 1267 return result.Succeeded(); 1268 } 1269 }; 1270 1271 //------------------------------------------------------------------------- 1272 // CommandObjectProcessSignal 1273 //------------------------------------------------------------------------- 1274 #pragma mark CommandObjectProcessSignal 1275 1276 class CommandObjectProcessSignal : public CommandObject 1277 { 1278 public: 1279 1280 CommandObjectProcessSignal (CommandInterpreter &interpreter) : 1281 CommandObject (interpreter, 1282 "process signal", 1283 "Send a UNIX signal to the current process being debugged.", 1284 NULL) 1285 { 1286 CommandArgumentEntry arg; 1287 CommandArgumentData signal_arg; 1288 1289 // Define the first (and only) variant of this arg. 1290 signal_arg.arg_type = eArgTypeUnixSignal; 1291 signal_arg.arg_repetition = eArgRepeatPlain; 1292 1293 // There is only one variant this argument could be; put it into the argument entry. 1294 arg.push_back (signal_arg); 1295 1296 // Push the data for the first argument into the m_arguments vector. 1297 m_arguments.push_back (arg); 1298 } 1299 1300 ~CommandObjectProcessSignal () 1301 { 1302 } 1303 1304 bool 1305 Execute (Args& command, 1306 CommandReturnObject &result) 1307 { 1308 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; 1309 if (process == NULL) 1310 { 1311 result.AppendError ("no process to signal"); 1312 result.SetStatus (eReturnStatusFailed); 1313 return false; 1314 } 1315 1316 if (command.GetArgumentCount() == 1) 1317 { 1318 int signo = LLDB_INVALID_SIGNAL_NUMBER; 1319 1320 const char *signal_name = command.GetArgumentAtIndex(0); 1321 if (::isxdigit (signal_name[0])) 1322 signo = Args::StringToSInt32(signal_name, LLDB_INVALID_SIGNAL_NUMBER, 0); 1323 else 1324 signo = process->GetUnixSignals().GetSignalNumberFromName (signal_name); 1325 1326 if (signo == LLDB_INVALID_SIGNAL_NUMBER) 1327 { 1328 result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0)); 1329 result.SetStatus (eReturnStatusFailed); 1330 } 1331 else 1332 { 1333 Error error (process->Signal (signo)); 1334 if (error.Success()) 1335 { 1336 result.SetStatus (eReturnStatusSuccessFinishResult); 1337 } 1338 else 1339 { 1340 result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString()); 1341 result.SetStatus (eReturnStatusFailed); 1342 } 1343 } 1344 } 1345 else 1346 { 1347 result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: \n", m_cmd_name.c_str(), 1348 m_cmd_syntax.c_str()); 1349 result.SetStatus (eReturnStatusFailed); 1350 } 1351 return result.Succeeded(); 1352 } 1353 }; 1354 1355 1356 //------------------------------------------------------------------------- 1357 // CommandObjectProcessInterrupt 1358 //------------------------------------------------------------------------- 1359 #pragma mark CommandObjectProcessInterrupt 1360 1361 class CommandObjectProcessInterrupt : public CommandObject 1362 { 1363 public: 1364 1365 1366 CommandObjectProcessInterrupt (CommandInterpreter &interpreter) : 1367 CommandObject (interpreter, 1368 "process interrupt", 1369 "Interrupt the current process being debugged.", 1370 "process interrupt", 1371 eFlagProcessMustBeLaunched) 1372 { 1373 } 1374 1375 ~CommandObjectProcessInterrupt () 1376 { 1377 } 1378 1379 bool 1380 Execute (Args& command, 1381 CommandReturnObject &result) 1382 { 1383 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; 1384 if (process == NULL) 1385 { 1386 result.AppendError ("no process to halt"); 1387 result.SetStatus (eReturnStatusFailed); 1388 return false; 1389 } 1390 1391 if (command.GetArgumentCount() == 0) 1392 { 1393 Error error(process->Halt ()); 1394 if (error.Success()) 1395 { 1396 result.SetStatus (eReturnStatusSuccessFinishResult); 1397 1398 // Maybe we should add a "SuspendThreadPlans so we 1399 // can halt, and keep in place all the current thread plans. 1400 process->GetThreadList().DiscardThreadPlans(); 1401 } 1402 else 1403 { 1404 result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString()); 1405 result.SetStatus (eReturnStatusFailed); 1406 } 1407 } 1408 else 1409 { 1410 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n", 1411 m_cmd_name.c_str(), 1412 m_cmd_syntax.c_str()); 1413 result.SetStatus (eReturnStatusFailed); 1414 } 1415 return result.Succeeded(); 1416 } 1417 }; 1418 1419 //------------------------------------------------------------------------- 1420 // CommandObjectProcessKill 1421 //------------------------------------------------------------------------- 1422 #pragma mark CommandObjectProcessKill 1423 1424 class CommandObjectProcessKill : public CommandObject 1425 { 1426 public: 1427 1428 CommandObjectProcessKill (CommandInterpreter &interpreter) : 1429 CommandObject (interpreter, 1430 "process kill", 1431 "Terminate the current process being debugged.", 1432 "process kill", 1433 eFlagProcessMustBeLaunched) 1434 { 1435 } 1436 1437 ~CommandObjectProcessKill () 1438 { 1439 } 1440 1441 bool 1442 Execute (Args& command, 1443 CommandReturnObject &result) 1444 { 1445 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process; 1446 if (process == NULL) 1447 { 1448 result.AppendError ("no process to kill"); 1449 result.SetStatus (eReturnStatusFailed); 1450 return false; 1451 } 1452 1453 if (command.GetArgumentCount() == 0) 1454 { 1455 Error error (process->Destroy()); 1456 if (error.Success()) 1457 { 1458 result.SetStatus (eReturnStatusSuccessFinishResult); 1459 } 1460 else 1461 { 1462 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString()); 1463 result.SetStatus (eReturnStatusFailed); 1464 } 1465 } 1466 else 1467 { 1468 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: \n", 1469 m_cmd_name.c_str(), 1470 m_cmd_syntax.c_str()); 1471 result.SetStatus (eReturnStatusFailed); 1472 } 1473 return result.Succeeded(); 1474 } 1475 }; 1476 1477 //------------------------------------------------------------------------- 1478 // CommandObjectProcessStatus 1479 //------------------------------------------------------------------------- 1480 #pragma mark CommandObjectProcessStatus 1481 1482 class CommandObjectProcessStatus : public CommandObject 1483 { 1484 public: 1485 CommandObjectProcessStatus (CommandInterpreter &interpreter) : 1486 CommandObject (interpreter, 1487 "process status", 1488 "Show the current status and location of executing process.", 1489 "process status", 1490 0) 1491 { 1492 } 1493 1494 ~CommandObjectProcessStatus() 1495 { 1496 } 1497 1498 1499 bool 1500 Execute 1501 ( 1502 Args& command, 1503 CommandReturnObject &result 1504 ) 1505 { 1506 Stream &output_stream = result.GetOutputStream(); 1507 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1508 ExecutionContext exe_ctx(m_interpreter.GetDebugger().GetExecutionContext()); 1509 if (exe_ctx.process) 1510 { 1511 const StateType state = exe_ctx.process->GetState(); 1512 if (StateIsStoppedState(state)) 1513 { 1514 if (state == eStateExited) 1515 { 1516 int exit_status = exe_ctx.process->GetExitStatus(); 1517 const char *exit_description = exe_ctx.process->GetExitDescription(); 1518 output_stream.Printf ("Process %d exited with status = %i (0x%8.8x) %s\n", 1519 exe_ctx.process->GetID(), 1520 exit_status, 1521 exit_status, 1522 exit_description ? exit_description : ""); 1523 } 1524 else 1525 { 1526 if (state == eStateConnected) 1527 output_stream.Printf ("Connected to remote target.\n"); 1528 else 1529 output_stream.Printf ("Process %d %s\n", exe_ctx.process->GetID(), StateAsCString (state)); 1530 if (exe_ctx.thread == NULL) 1531 exe_ctx.thread = exe_ctx.process->GetThreadList().GetThreadAtIndex(0).get(); 1532 if (exe_ctx.thread != NULL) 1533 { 1534 DisplayThreadsInfo (m_interpreter, &exe_ctx, result, true, true); 1535 } 1536 else 1537 { 1538 result.AppendError ("No valid thread found in current process."); 1539 result.SetStatus (eReturnStatusFailed); 1540 } 1541 } 1542 } 1543 else 1544 { 1545 output_stream.Printf ("Process %d is running.\n", 1546 exe_ctx.process->GetID()); 1547 } 1548 } 1549 else 1550 { 1551 result.AppendError ("No current location or status available."); 1552 result.SetStatus (eReturnStatusFailed); 1553 } 1554 return result.Succeeded(); 1555 } 1556 }; 1557 1558 //------------------------------------------------------------------------- 1559 // CommandObjectProcessHandle 1560 //------------------------------------------------------------------------- 1561 #pragma mark CommandObjectProcessHandle 1562 1563 class CommandObjectProcessHandle : public CommandObject 1564 { 1565 public: 1566 1567 class CommandOptions : public Options 1568 { 1569 public: 1570 1571 CommandOptions () : 1572 Options () 1573 { 1574 ResetOptionValues (); 1575 } 1576 1577 ~CommandOptions () 1578 { 1579 } 1580 1581 Error 1582 SetOptionValue (int option_idx, const char *option_arg) 1583 { 1584 Error error; 1585 char short_option = (char) m_getopt_table[option_idx].val; 1586 1587 switch (short_option) 1588 { 1589 case 's': 1590 stop = option_arg; 1591 break; 1592 case 'n': 1593 notify = option_arg; 1594 break; 1595 case 'p': 1596 pass = option_arg; 1597 break; 1598 default: 1599 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option); 1600 break; 1601 } 1602 return error; 1603 } 1604 1605 void 1606 ResetOptionValues () 1607 { 1608 stop.clear(); 1609 notify.clear(); 1610 pass.clear(); 1611 } 1612 1613 const OptionDefinition* 1614 GetDefinitions () 1615 { 1616 return g_option_table; 1617 } 1618 1619 // Options table: Required for subclasses of Options. 1620 1621 static OptionDefinition g_option_table[]; 1622 1623 // Instance variables to hold the values for command options. 1624 1625 std::string stop; 1626 std::string notify; 1627 std::string pass; 1628 }; 1629 1630 1631 CommandObjectProcessHandle (CommandInterpreter &interpreter) : 1632 CommandObject (interpreter, 1633 "process handle", 1634 "Show or update what the process and debugger should do with various signals received from the OS.", 1635 NULL) 1636 { 1637 SetHelpLong ("If no signals are specified, update them all. If no update option is specified, list the current values.\n"); 1638 CommandArgumentEntry arg; 1639 CommandArgumentData signal_arg; 1640 1641 signal_arg.arg_type = eArgTypeUnixSignal; 1642 signal_arg.arg_repetition = eArgRepeatStar; 1643 1644 arg.push_back (signal_arg); 1645 1646 m_arguments.push_back (arg); 1647 } 1648 1649 ~CommandObjectProcessHandle () 1650 { 1651 } 1652 1653 Options * 1654 GetOptions () 1655 { 1656 return &m_options; 1657 } 1658 1659 bool 1660 VerifyCommandOptionValue (const std::string &option, int &real_value) 1661 { 1662 bool okay = true; 1663 1664 bool success = false; 1665 bool tmp_value = Args::StringToBoolean (option.c_str(), false, &success); 1666 1667 if (success && tmp_value) 1668 real_value = 1; 1669 else if (success && !tmp_value) 1670 real_value = 0; 1671 else 1672 { 1673 // If the value isn't 'true' or 'false', it had better be 0 or 1. 1674 real_value = Args::StringToUInt32 (option.c_str(), 3); 1675 if (real_value != 0 && real_value != 1) 1676 okay = false; 1677 } 1678 1679 return okay; 1680 } 1681 1682 void 1683 PrintSignalHeader (Stream &str) 1684 { 1685 str.Printf ("NAME PASS STOP NOTIFY\n"); 1686 str.Printf ("========== ===== ===== ======\n"); 1687 } 1688 1689 void 1690 PrintSignal (Stream &str, int32_t signo, const char *sig_name, UnixSignals &signals) 1691 { 1692 bool stop; 1693 bool suppress; 1694 bool notify; 1695 1696 str.Printf ("%-10s ", sig_name); 1697 if (signals.GetSignalInfo (signo, suppress, stop, notify)) 1698 { 1699 bool pass = !suppress; 1700 str.Printf ("%s %s %s", 1701 (pass ? "true " : "false"), 1702 (stop ? "true " : "false"), 1703 (notify ? "true " : "false")); 1704 } 1705 str.Printf ("\n"); 1706 } 1707 1708 void 1709 PrintSignalInformation (Stream &str, Args &signal_args, int num_valid_signals, UnixSignals &signals) 1710 { 1711 PrintSignalHeader (str); 1712 1713 if (num_valid_signals > 0) 1714 { 1715 size_t num_args = signal_args.GetArgumentCount(); 1716 for (size_t i = 0; i < num_args; ++i) 1717 { 1718 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i)); 1719 if (signo != LLDB_INVALID_SIGNAL_NUMBER) 1720 PrintSignal (str, signo, signal_args.GetArgumentAtIndex (i), signals); 1721 } 1722 } 1723 else // Print info for ALL signals 1724 { 1725 int32_t signo = signals.GetFirstSignalNumber(); 1726 while (signo != LLDB_INVALID_SIGNAL_NUMBER) 1727 { 1728 PrintSignal (str, signo, signals.GetSignalAsCString (signo), signals); 1729 signo = signals.GetNextSignalNumber (signo); 1730 } 1731 } 1732 } 1733 1734 bool 1735 Execute (Args &signal_args, CommandReturnObject &result) 1736 { 1737 TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget(); 1738 1739 if (!target_sp) 1740 { 1741 result.AppendError ("No current target;" 1742 " cannot handle signals until you have a valid target and process.\n"); 1743 result.SetStatus (eReturnStatusFailed); 1744 return false; 1745 } 1746 1747 ProcessSP process_sp = target_sp->GetProcessSP(); 1748 1749 if (!process_sp) 1750 { 1751 result.AppendError ("No current process; cannot handle signals until you have a valid process.\n"); 1752 result.SetStatus (eReturnStatusFailed); 1753 return false; 1754 } 1755 1756 int stop_action = -1; // -1 means leave the current setting alone 1757 int pass_action = -1; // -1 means leave the current setting alone 1758 int notify_action = -1; // -1 means leave the current setting alone 1759 1760 if (! m_options.stop.empty() 1761 && ! VerifyCommandOptionValue (m_options.stop, stop_action)) 1762 { 1763 result.AppendError ("Invalid argument for command option --stop; must be true or false.\n"); 1764 result.SetStatus (eReturnStatusFailed); 1765 return false; 1766 } 1767 1768 if (! m_options.notify.empty() 1769 && ! VerifyCommandOptionValue (m_options.notify, notify_action)) 1770 { 1771 result.AppendError ("Invalid argument for command option --notify; must be true or false.\n"); 1772 result.SetStatus (eReturnStatusFailed); 1773 return false; 1774 } 1775 1776 if (! m_options.pass.empty() 1777 && ! VerifyCommandOptionValue (m_options.pass, pass_action)) 1778 { 1779 result.AppendError ("Invalid argument for command option --pass; must be true or false.\n"); 1780 result.SetStatus (eReturnStatusFailed); 1781 return false; 1782 } 1783 1784 size_t num_args = signal_args.GetArgumentCount(); 1785 UnixSignals &signals = process_sp->GetUnixSignals(); 1786 int num_signals_set = 0; 1787 1788 if (num_args > 0) 1789 { 1790 for (size_t i = 0; i < num_args; ++i) 1791 { 1792 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i)); 1793 if (signo != LLDB_INVALID_SIGNAL_NUMBER) 1794 { 1795 // Casting the actions as bools here should be okay, because VerifyCommandOptionValue guarantees 1796 // the value is either 0 or 1. 1797 if (stop_action != -1) 1798 signals.SetShouldStop (signo, (bool) stop_action); 1799 if (pass_action != -1) 1800 { 1801 bool suppress = ! ((bool) pass_action); 1802 signals.SetShouldSuppress (signo, suppress); 1803 } 1804 if (notify_action != -1) 1805 signals.SetShouldNotify (signo, (bool) notify_action); 1806 ++num_signals_set; 1807 } 1808 else 1809 { 1810 result.AppendErrorWithFormat ("Invalid signal name '%s'\n", signal_args.GetArgumentAtIndex (i)); 1811 } 1812 } 1813 } 1814 else 1815 { 1816 // No signal specified, if any command options were specified, update ALL signals. 1817 if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1)) 1818 { 1819 if (m_interpreter.Confirm ("Do you really want to update all the signals?", false)) 1820 { 1821 int32_t signo = signals.GetFirstSignalNumber(); 1822 while (signo != LLDB_INVALID_SIGNAL_NUMBER) 1823 { 1824 if (notify_action != -1) 1825 signals.SetShouldNotify (signo, (bool) notify_action); 1826 if (stop_action != -1) 1827 signals.SetShouldStop (signo, (bool) stop_action); 1828 if (pass_action != -1) 1829 { 1830 bool suppress = ! ((bool) pass_action); 1831 signals.SetShouldSuppress (signo, suppress); 1832 } 1833 signo = signals.GetNextSignalNumber (signo); 1834 } 1835 } 1836 } 1837 } 1838 1839 PrintSignalInformation (result.GetOutputStream(), signal_args, num_signals_set, signals); 1840 1841 if (num_signals_set > 0) 1842 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1843 else 1844 result.SetStatus (eReturnStatusFailed); 1845 1846 return result.Succeeded(); 1847 } 1848 1849 protected: 1850 1851 CommandOptions m_options; 1852 }; 1853 1854 OptionDefinition 1855 CommandObjectProcessHandle::CommandOptions::g_option_table[] = 1856 { 1857 { LLDB_OPT_SET_1, false, "stop", 's', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the process should be stopped if the signal is received." }, 1858 { LLDB_OPT_SET_1, false, "notify", 'n', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the debugger should notify the user if the signal is received." }, 1859 { LLDB_OPT_SET_1, false, "pass", 'p', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." }, 1860 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 1861 }; 1862 1863 //------------------------------------------------------------------------- 1864 // CommandObjectMultiwordProcess 1865 //------------------------------------------------------------------------- 1866 1867 CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter &interpreter) : 1868 CommandObjectMultiword (interpreter, 1869 "process", 1870 "A set of commands for operating on a process.", 1871 "process <subcommand> [<subcommand-options>]") 1872 { 1873 LoadSubCommand ("attach", CommandObjectSP (new CommandObjectProcessAttach (interpreter))); 1874 LoadSubCommand ("launch", CommandObjectSP (new CommandObjectProcessLaunch (interpreter))); 1875 LoadSubCommand ("continue", CommandObjectSP (new CommandObjectProcessContinue (interpreter))); 1876 LoadSubCommand ("connect", CommandObjectSP (new CommandObjectProcessConnect (interpreter))); 1877 LoadSubCommand ("detach", CommandObjectSP (new CommandObjectProcessDetach (interpreter))); 1878 LoadSubCommand ("load", CommandObjectSP (new CommandObjectProcessLoad (interpreter))); 1879 LoadSubCommand ("unload", CommandObjectSP (new CommandObjectProcessUnload (interpreter))); 1880 LoadSubCommand ("signal", CommandObjectSP (new CommandObjectProcessSignal (interpreter))); 1881 LoadSubCommand ("handle", CommandObjectSP (new CommandObjectProcessHandle (interpreter))); 1882 LoadSubCommand ("status", CommandObjectSP (new CommandObjectProcessStatus (interpreter))); 1883 LoadSubCommand ("interrupt", CommandObjectSP (new CommandObjectProcessInterrupt (interpreter))); 1884 LoadSubCommand ("kill", CommandObjectSP (new CommandObjectProcessKill (interpreter))); 1885 } 1886 1887 CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess () 1888 { 1889 } 1890 1891