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