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, create a debug target using the 'target create' 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->GetExecutableModulePointer(); 166 167 if (exe_module == NULL) 168 { 169 result.AppendError ("no file in target, create a debug target using the 'target create' 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().GetProcessPtr(); 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 %llu 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 // N.B. The attach should be synchronous. It doesn't help much to get the prompt back between initiating the attach 566 // and the target actually stopping. So even if the interpreter is set to be asynchronous, we wait for the stop 567 // ourselves here. 568 569 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr(); 570 StateType state = eStateInvalid; 571 if (process) 572 { 573 state = process->GetState(); 574 if (process->IsAlive() && state != eStateConnected) 575 { 576 result.AppendErrorWithFormat ("Process %llu is currently being debugged, kill the process before attaching.\n", 577 process->GetID()); 578 result.SetStatus (eReturnStatusFailed); 579 return false; 580 } 581 } 582 583 if (target == NULL) 584 { 585 // If there isn't a current target create one. 586 TargetSP new_target_sp; 587 FileSpec emptyFileSpec; 588 Error error; 589 590 error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(), 591 emptyFileSpec, 592 NULL, 593 false, 594 NULL, // No platform options 595 new_target_sp); 596 target = new_target_sp.get(); 597 if (target == NULL || error.Fail()) 598 { 599 result.AppendError(error.AsCString("Error creating target")); 600 return false; 601 } 602 m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target); 603 } 604 605 // Record the old executable module, we want to issue a warning if the process of attaching changed the 606 // current executable (like somebody said "file foo" then attached to a PID whose executable was bar.) 607 608 ModuleSP old_exec_module_sp = target->GetExecutableModule(); 609 ArchSpec old_arch_spec = target->GetArchitecture(); 610 611 if (command.GetArgumentCount()) 612 { 613 result.AppendErrorWithFormat("Invalid arguments for '%s'.\nUsage: %s\n", m_cmd_name.c_str(), m_cmd_syntax.c_str()); 614 result.SetStatus (eReturnStatusFailed); 615 } 616 else 617 { 618 if (state != eStateConnected) 619 { 620 const char *plugin_name = NULL; 621 622 if (!m_options.plugin_name.empty()) 623 plugin_name = m_options.plugin_name.c_str(); 624 625 process = target->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get(); 626 } 627 628 if (process) 629 { 630 Error error; 631 int attach_pid = m_options.pid; 632 633 const char *wait_name = NULL; 634 635 if (m_options.name.empty()) 636 { 637 if (old_exec_module_sp) 638 { 639 wait_name = old_exec_module_sp->GetFileSpec().GetFilename().AsCString(); 640 } 641 } 642 else 643 { 644 wait_name = m_options.name.c_str(); 645 } 646 647 // If we are waiting for a process with this name to show up, do that first. 648 if (m_options.waitfor) 649 { 650 651 if (wait_name == NULL) 652 { 653 result.AppendError("Invalid arguments: must have a file loaded or supply a process name with the waitfor option.\n"); 654 result.SetStatus (eReturnStatusFailed); 655 return false; 656 } 657 658 result.AppendMessageWithFormat("Waiting to attach to a process named \"%s\".\n", wait_name); 659 error = process->Attach (wait_name, m_options.waitfor); 660 if (error.Success()) 661 { 662 result.SetStatus (eReturnStatusSuccessContinuingNoResult); 663 } 664 else 665 { 666 result.AppendErrorWithFormat ("Waiting for a process to launch named '%s': %s\n", 667 wait_name, 668 error.AsCString()); 669 result.SetStatus (eReturnStatusFailed); 670 return false; 671 } 672 // If we're synchronous, wait for the stopped event and report that. 673 // Otherwise just return. 674 // FIXME: in the async case it will now be possible to get to the command 675 // interpreter with a state eStateAttaching. Make sure we handle that correctly. 676 StateType state = process->WaitForProcessToStop (NULL); 677 678 result.SetDidChangeProcessState (true); 679 result.AppendMessageWithFormat ("Process %llu %s\n", process->GetID(), StateAsCString (state)); 680 result.SetStatus (eReturnStatusSuccessFinishNoResult); 681 } 682 else 683 { 684 // If the process was specified by name look it up, so we can warn if there are multiple 685 // processes with this pid. 686 687 if (attach_pid == LLDB_INVALID_PROCESS_ID && wait_name != NULL) 688 { 689 ProcessInstanceInfoList process_infos; 690 PlatformSP platform_sp (m_interpreter.GetPlatform (true)); 691 if (platform_sp) 692 { 693 ProcessInstanceInfoMatch match_info (wait_name, eNameMatchEquals); 694 platform_sp->FindProcesses (match_info, process_infos); 695 } 696 if (process_infos.GetSize() > 1) 697 { 698 result.AppendErrorWithFormat("More than one process named %s\n", wait_name); 699 result.SetStatus (eReturnStatusFailed); 700 return false; 701 } 702 else if (process_infos.GetSize() == 0) 703 { 704 result.AppendErrorWithFormat("Could not find a process named %s\n", wait_name); 705 result.SetStatus (eReturnStatusFailed); 706 return false; 707 } 708 else 709 { 710 attach_pid = process_infos.GetProcessIDAtIndex (0); 711 } 712 } 713 714 if (attach_pid != LLDB_INVALID_PROCESS_ID) 715 { 716 error = process->Attach (attach_pid); 717 if (error.Success()) 718 { 719 result.SetStatus (eReturnStatusSuccessContinuingNoResult); 720 } 721 else 722 { 723 result.AppendErrorWithFormat ("Attaching to process %i failed: %s.\n", 724 attach_pid, 725 error.AsCString()); 726 result.SetStatus (eReturnStatusFailed); 727 } 728 StateType state = process->WaitForProcessToStop (NULL); 729 730 result.SetDidChangeProcessState (true); 731 result.AppendMessageWithFormat ("Process %llu %s\n", process->GetID(), StateAsCString (state)); 732 result.SetStatus (eReturnStatusSuccessFinishNoResult); 733 } 734 else 735 { 736 result.AppendErrorWithFormat ("No PID specified for attach\n"); 737 result.SetStatus (eReturnStatusFailed); 738 739 } 740 } 741 } 742 } 743 744 if (result.Succeeded()) 745 { 746 // Okay, we're done. Last step is to warn if the executable module has changed: 747 char new_path[PATH_MAX]; 748 ModuleSP new_exec_module_sp (target->GetExecutableModule()); 749 if (!old_exec_module_sp) 750 { 751 // We might not have a module if we attached to a raw pid... 752 if (new_exec_module_sp) 753 { 754 new_exec_module_sp->GetFileSpec().GetPath(new_path, PATH_MAX); 755 result.AppendMessageWithFormat("Executable module set to \"%s\".\n", new_path); 756 } 757 } 758 else if (old_exec_module_sp->GetFileSpec() != new_exec_module_sp->GetFileSpec()) 759 { 760 char old_path[PATH_MAX]; 761 762 old_exec_module_sp->GetFileSpec().GetPath (old_path, PATH_MAX); 763 new_exec_module_sp->GetFileSpec().GetPath (new_path, PATH_MAX); 764 765 result.AppendWarningWithFormat("Executable module changed from \"%s\" to \"%s\".\n", 766 old_path, new_path); 767 } 768 769 if (!old_arch_spec.IsValid()) 770 { 771 result.AppendMessageWithFormat ("Architecture set to: %s.\n", target->GetArchitecture().GetArchitectureName()); 772 } 773 else if (old_arch_spec != target->GetArchitecture()) 774 { 775 result.AppendWarningWithFormat("Architecture changed from %s to %s.\n", 776 old_arch_spec.GetArchitectureName(), target->GetArchitecture().GetArchitectureName()); 777 } 778 } 779 return result.Succeeded(); 780 } 781 782 Options * 783 GetOptions () 784 { 785 return &m_options; 786 } 787 788 protected: 789 790 CommandOptions m_options; 791 }; 792 793 794 OptionDefinition 795 CommandObjectProcessAttach::CommandOptions::g_option_table[] = 796 { 797 { LLDB_OPT_SET_ALL, false, "plugin", 'P', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."}, 798 { LLDB_OPT_SET_1, false, "pid", 'p', required_argument, NULL, 0, eArgTypePid, "The process ID of an existing process to attach to."}, 799 { LLDB_OPT_SET_2, false, "name", 'n', required_argument, NULL, 0, eArgTypeProcessName, "The name of the process to attach to."}, 800 { LLDB_OPT_SET_2, false, "waitfor",'w', no_argument, NULL, 0, eArgTypeNone, "Wait for the the process with <process-name> to launch."}, 801 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 802 }; 803 804 //------------------------------------------------------------------------- 805 // CommandObjectProcessContinue 806 //------------------------------------------------------------------------- 807 #pragma mark CommandObjectProcessContinue 808 809 class CommandObjectProcessContinue : public CommandObject 810 { 811 public: 812 813 CommandObjectProcessContinue (CommandInterpreter &interpreter) : 814 CommandObject (interpreter, 815 "process continue", 816 "Continue execution of all threads in the current process.", 817 "process continue", 818 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused) 819 { 820 } 821 822 823 ~CommandObjectProcessContinue () 824 { 825 } 826 827 bool 828 Execute (Args& command, 829 CommandReturnObject &result) 830 { 831 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr(); 832 bool synchronous_execution = m_interpreter.GetSynchronous (); 833 834 if (process == NULL) 835 { 836 result.AppendError ("no process to continue"); 837 result.SetStatus (eReturnStatusFailed); 838 return false; 839 } 840 841 StateType state = process->GetState(); 842 if (state == eStateStopped) 843 { 844 if (command.GetArgumentCount() != 0) 845 { 846 result.AppendErrorWithFormat ("The '%s' command does not take any arguments.\n", m_cmd_name.c_str()); 847 result.SetStatus (eReturnStatusFailed); 848 return false; 849 } 850 851 const uint32_t num_threads = process->GetThreadList().GetSize(); 852 853 // Set the actions that the threads should each take when resuming 854 for (uint32_t idx=0; idx<num_threads; ++idx) 855 { 856 process->GetThreadList().GetThreadAtIndex(idx)->SetResumeState (eStateRunning); 857 } 858 859 Error error(process->Resume()); 860 if (error.Success()) 861 { 862 result.AppendMessageWithFormat ("Process %llu resuming\n", process->GetID()); 863 if (synchronous_execution) 864 { 865 state = process->WaitForProcessToStop (NULL); 866 867 result.SetDidChangeProcessState (true); 868 result.AppendMessageWithFormat ("Process %llu %s\n", process->GetID(), StateAsCString (state)); 869 result.SetStatus (eReturnStatusSuccessFinishNoResult); 870 } 871 else 872 { 873 result.SetStatus (eReturnStatusSuccessContinuingNoResult); 874 } 875 } 876 else 877 { 878 result.AppendErrorWithFormat("Failed to resume process: %s.\n", error.AsCString()); 879 result.SetStatus (eReturnStatusFailed); 880 } 881 } 882 else 883 { 884 result.AppendErrorWithFormat ("Process cannot be continued from its current state (%s).\n", 885 StateAsCString(state)); 886 result.SetStatus (eReturnStatusFailed); 887 } 888 return result.Succeeded(); 889 } 890 }; 891 892 //------------------------------------------------------------------------- 893 // CommandObjectProcessDetach 894 //------------------------------------------------------------------------- 895 #pragma mark CommandObjectProcessDetach 896 897 class CommandObjectProcessDetach : public CommandObject 898 { 899 public: 900 901 CommandObjectProcessDetach (CommandInterpreter &interpreter) : 902 CommandObject (interpreter, 903 "process detach", 904 "Detach from the current process being debugged.", 905 "process detach", 906 eFlagProcessMustBeLaunched) 907 { 908 } 909 910 ~CommandObjectProcessDetach () 911 { 912 } 913 914 bool 915 Execute (Args& command, 916 CommandReturnObject &result) 917 { 918 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr(); 919 if (process == NULL) 920 { 921 result.AppendError ("must have a valid process in order to detach"); 922 result.SetStatus (eReturnStatusFailed); 923 return false; 924 } 925 926 result.AppendMessageWithFormat ("Detaching from process %llu\n", process->GetID()); 927 Error error (process->Detach()); 928 if (error.Success()) 929 { 930 result.SetStatus (eReturnStatusSuccessFinishResult); 931 } 932 else 933 { 934 result.AppendErrorWithFormat ("Detach failed: %s\n", error.AsCString()); 935 result.SetStatus (eReturnStatusFailed); 936 return false; 937 } 938 return result.Succeeded(); 939 } 940 }; 941 942 //------------------------------------------------------------------------- 943 // CommandObjectProcessConnect 944 //------------------------------------------------------------------------- 945 #pragma mark CommandObjectProcessConnect 946 947 class CommandObjectProcessConnect : public CommandObject 948 { 949 public: 950 951 class CommandOptions : public Options 952 { 953 public: 954 955 CommandOptions (CommandInterpreter &interpreter) : 956 Options(interpreter) 957 { 958 // Keep default values of all options in one place: OptionParsingStarting () 959 OptionParsingStarting (); 960 } 961 962 ~CommandOptions () 963 { 964 } 965 966 Error 967 SetOptionValue (uint32_t option_idx, const char *option_arg) 968 { 969 Error error; 970 char short_option = (char) m_getopt_table[option_idx].val; 971 972 switch (short_option) 973 { 974 case 'p': 975 plugin_name.assign (option_arg); 976 break; 977 978 default: 979 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option); 980 break; 981 } 982 return error; 983 } 984 985 void 986 OptionParsingStarting () 987 { 988 plugin_name.clear(); 989 } 990 991 const OptionDefinition* 992 GetDefinitions () 993 { 994 return g_option_table; 995 } 996 997 // Options table: Required for subclasses of Options. 998 999 static OptionDefinition g_option_table[]; 1000 1001 // Instance variables to hold the values for command options. 1002 1003 std::string plugin_name; 1004 }; 1005 1006 CommandObjectProcessConnect (CommandInterpreter &interpreter) : 1007 CommandObject (interpreter, 1008 "process connect", 1009 "Connect to a remote debug service.", 1010 "process connect <remote-url>", 1011 0), 1012 m_options (interpreter) 1013 { 1014 } 1015 1016 ~CommandObjectProcessConnect () 1017 { 1018 } 1019 1020 1021 bool 1022 Execute (Args& command, 1023 CommandReturnObject &result) 1024 { 1025 1026 TargetSP target_sp (m_interpreter.GetDebugger().GetSelectedTarget()); 1027 Error error; 1028 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr(); 1029 if (process) 1030 { 1031 if (process->IsAlive()) 1032 { 1033 result.AppendErrorWithFormat ("Process %llu is currently being debugged, kill the process before connecting.\n", 1034 process->GetID()); 1035 result.SetStatus (eReturnStatusFailed); 1036 return false; 1037 } 1038 } 1039 1040 if (!target_sp) 1041 { 1042 // If there isn't a current target create one. 1043 FileSpec emptyFileSpec; 1044 1045 error = m_interpreter.GetDebugger().GetTargetList().CreateTarget (m_interpreter.GetDebugger(), 1046 emptyFileSpec, 1047 NULL, 1048 false, 1049 NULL, // No platform options 1050 target_sp); 1051 if (!target_sp || error.Fail()) 1052 { 1053 result.AppendError(error.AsCString("Error creating target")); 1054 result.SetStatus (eReturnStatusFailed); 1055 return false; 1056 } 1057 m_interpreter.GetDebugger().GetTargetList().SetSelectedTarget(target_sp.get()); 1058 } 1059 1060 if (command.GetArgumentCount() == 1) 1061 { 1062 const char *plugin_name = NULL; 1063 if (!m_options.plugin_name.empty()) 1064 plugin_name = m_options.plugin_name.c_str(); 1065 1066 const char *remote_url = command.GetArgumentAtIndex(0); 1067 process = target_sp->CreateProcess (m_interpreter.GetDebugger().GetListener(), plugin_name).get(); 1068 1069 if (process) 1070 { 1071 error = process->ConnectRemote (remote_url); 1072 1073 if (error.Fail()) 1074 { 1075 result.AppendError(error.AsCString("Remote connect failed")); 1076 result.SetStatus (eReturnStatusFailed); 1077 return false; 1078 } 1079 } 1080 else 1081 { 1082 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", 1083 m_cmd_name.c_str()); 1084 result.SetStatus (eReturnStatusFailed); 1085 } 1086 } 1087 else 1088 { 1089 result.AppendErrorWithFormat ("'%s' takes exactly one argument:\nUsage: %s\n", 1090 m_cmd_name.c_str(), 1091 m_cmd_syntax.c_str()); 1092 result.SetStatus (eReturnStatusFailed); 1093 } 1094 return result.Succeeded(); 1095 } 1096 1097 Options * 1098 GetOptions () 1099 { 1100 return &m_options; 1101 } 1102 1103 protected: 1104 1105 CommandOptions m_options; 1106 }; 1107 1108 1109 OptionDefinition 1110 CommandObjectProcessConnect::CommandOptions::g_option_table[] = 1111 { 1112 { LLDB_OPT_SET_ALL, false, "plugin", 'p', required_argument, NULL, 0, eArgTypePlugin, "Name of the process plugin you want to use."}, 1113 { 0, false, NULL, 0 , 0, NULL, 0, eArgTypeNone, NULL } 1114 }; 1115 1116 //------------------------------------------------------------------------- 1117 // CommandObjectProcessLoad 1118 //------------------------------------------------------------------------- 1119 #pragma mark CommandObjectProcessLoad 1120 1121 class CommandObjectProcessLoad : public CommandObject 1122 { 1123 public: 1124 1125 CommandObjectProcessLoad (CommandInterpreter &interpreter) : 1126 CommandObject (interpreter, 1127 "process load", 1128 "Load a shared library into the current process.", 1129 "process load <filename> [<filename> ...]", 1130 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused) 1131 { 1132 } 1133 1134 ~CommandObjectProcessLoad () 1135 { 1136 } 1137 1138 bool 1139 Execute (Args& command, 1140 CommandReturnObject &result) 1141 { 1142 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr(); 1143 if (process == NULL) 1144 { 1145 result.AppendError ("must have a valid process in order to load a shared library"); 1146 result.SetStatus (eReturnStatusFailed); 1147 return false; 1148 } 1149 1150 const uint32_t argc = command.GetArgumentCount(); 1151 1152 for (uint32_t i=0; i<argc; ++i) 1153 { 1154 Error error; 1155 const char *image_path = command.GetArgumentAtIndex(i); 1156 FileSpec image_spec (image_path, false); 1157 process->GetTarget().GetPlatform()->ResolveRemotePath(image_spec, image_spec); 1158 uint32_t image_token = process->LoadImage(image_spec, error); 1159 if (image_token != LLDB_INVALID_IMAGE_TOKEN) 1160 { 1161 result.AppendMessageWithFormat ("Loading \"%s\"...ok\nImage %u loaded.\n", image_path, image_token); 1162 result.SetStatus (eReturnStatusSuccessFinishResult); 1163 } 1164 else 1165 { 1166 result.AppendErrorWithFormat ("failed to load '%s': %s", image_path, error.AsCString()); 1167 result.SetStatus (eReturnStatusFailed); 1168 } 1169 } 1170 return result.Succeeded(); 1171 } 1172 }; 1173 1174 1175 //------------------------------------------------------------------------- 1176 // CommandObjectProcessUnload 1177 //------------------------------------------------------------------------- 1178 #pragma mark CommandObjectProcessUnload 1179 1180 class CommandObjectProcessUnload : public CommandObject 1181 { 1182 public: 1183 1184 CommandObjectProcessUnload (CommandInterpreter &interpreter) : 1185 CommandObject (interpreter, 1186 "process unload", 1187 "Unload a shared library from the current process using the index returned by a previous call to \"process load\".", 1188 "process unload <index>", 1189 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused) 1190 { 1191 } 1192 1193 ~CommandObjectProcessUnload () 1194 { 1195 } 1196 1197 bool 1198 Execute (Args& command, 1199 CommandReturnObject &result) 1200 { 1201 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr(); 1202 if (process == NULL) 1203 { 1204 result.AppendError ("must have a valid process in order to load a shared library"); 1205 result.SetStatus (eReturnStatusFailed); 1206 return false; 1207 } 1208 1209 const uint32_t argc = command.GetArgumentCount(); 1210 1211 for (uint32_t i=0; i<argc; ++i) 1212 { 1213 const char *image_token_cstr = command.GetArgumentAtIndex(i); 1214 uint32_t image_token = Args::StringToUInt32(image_token_cstr, LLDB_INVALID_IMAGE_TOKEN, 0); 1215 if (image_token == LLDB_INVALID_IMAGE_TOKEN) 1216 { 1217 result.AppendErrorWithFormat ("invalid image index argument '%s'", image_token_cstr); 1218 result.SetStatus (eReturnStatusFailed); 1219 break; 1220 } 1221 else 1222 { 1223 Error error (process->UnloadImage(image_token)); 1224 if (error.Success()) 1225 { 1226 result.AppendMessageWithFormat ("Unloading shared library with index %u...ok\n", image_token); 1227 result.SetStatus (eReturnStatusSuccessFinishResult); 1228 } 1229 else 1230 { 1231 result.AppendErrorWithFormat ("failed to unload image: %s", error.AsCString()); 1232 result.SetStatus (eReturnStatusFailed); 1233 break; 1234 } 1235 } 1236 } 1237 return result.Succeeded(); 1238 } 1239 }; 1240 1241 //------------------------------------------------------------------------- 1242 // CommandObjectProcessSignal 1243 //------------------------------------------------------------------------- 1244 #pragma mark CommandObjectProcessSignal 1245 1246 class CommandObjectProcessSignal : public CommandObject 1247 { 1248 public: 1249 1250 CommandObjectProcessSignal (CommandInterpreter &interpreter) : 1251 CommandObject (interpreter, 1252 "process signal", 1253 "Send a UNIX signal to the current process being debugged.", 1254 NULL) 1255 { 1256 CommandArgumentEntry arg; 1257 CommandArgumentData signal_arg; 1258 1259 // Define the first (and only) variant of this arg. 1260 signal_arg.arg_type = eArgTypeUnixSignal; 1261 signal_arg.arg_repetition = eArgRepeatPlain; 1262 1263 // There is only one variant this argument could be; put it into the argument entry. 1264 arg.push_back (signal_arg); 1265 1266 // Push the data for the first argument into the m_arguments vector. 1267 m_arguments.push_back (arg); 1268 } 1269 1270 ~CommandObjectProcessSignal () 1271 { 1272 } 1273 1274 bool 1275 Execute (Args& command, 1276 CommandReturnObject &result) 1277 { 1278 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr(); 1279 if (process == NULL) 1280 { 1281 result.AppendError ("no process to signal"); 1282 result.SetStatus (eReturnStatusFailed); 1283 return false; 1284 } 1285 1286 if (command.GetArgumentCount() == 1) 1287 { 1288 int signo = LLDB_INVALID_SIGNAL_NUMBER; 1289 1290 const char *signal_name = command.GetArgumentAtIndex(0); 1291 if (::isxdigit (signal_name[0])) 1292 signo = Args::StringToSInt32(signal_name, LLDB_INVALID_SIGNAL_NUMBER, 0); 1293 else 1294 signo = process->GetUnixSignals().GetSignalNumberFromName (signal_name); 1295 1296 if (signo == LLDB_INVALID_SIGNAL_NUMBER) 1297 { 1298 result.AppendErrorWithFormat ("Invalid signal argument '%s'.\n", command.GetArgumentAtIndex(0)); 1299 result.SetStatus (eReturnStatusFailed); 1300 } 1301 else 1302 { 1303 Error error (process->Signal (signo)); 1304 if (error.Success()) 1305 { 1306 result.SetStatus (eReturnStatusSuccessFinishResult); 1307 } 1308 else 1309 { 1310 result.AppendErrorWithFormat ("Failed to send signal %i: %s\n", signo, error.AsCString()); 1311 result.SetStatus (eReturnStatusFailed); 1312 } 1313 } 1314 } 1315 else 1316 { 1317 result.AppendErrorWithFormat("'%s' takes exactly one signal number argument:\nUsage: %s\n", m_cmd_name.c_str(), 1318 m_cmd_syntax.c_str()); 1319 result.SetStatus (eReturnStatusFailed); 1320 } 1321 return result.Succeeded(); 1322 } 1323 }; 1324 1325 1326 //------------------------------------------------------------------------- 1327 // CommandObjectProcessInterrupt 1328 //------------------------------------------------------------------------- 1329 #pragma mark CommandObjectProcessInterrupt 1330 1331 class CommandObjectProcessInterrupt : public CommandObject 1332 { 1333 public: 1334 1335 1336 CommandObjectProcessInterrupt (CommandInterpreter &interpreter) : 1337 CommandObject (interpreter, 1338 "process interrupt", 1339 "Interrupt the current process being debugged.", 1340 "process interrupt", 1341 eFlagProcessMustBeLaunched) 1342 { 1343 } 1344 1345 ~CommandObjectProcessInterrupt () 1346 { 1347 } 1348 1349 bool 1350 Execute (Args& command, 1351 CommandReturnObject &result) 1352 { 1353 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr(); 1354 if (process == NULL) 1355 { 1356 result.AppendError ("no process to halt"); 1357 result.SetStatus (eReturnStatusFailed); 1358 return false; 1359 } 1360 1361 if (command.GetArgumentCount() == 0) 1362 { 1363 Error error(process->Halt ()); 1364 if (error.Success()) 1365 { 1366 result.SetStatus (eReturnStatusSuccessFinishResult); 1367 1368 // Maybe we should add a "SuspendThreadPlans so we 1369 // can halt, and keep in place all the current thread plans. 1370 process->GetThreadList().DiscardThreadPlans(); 1371 } 1372 else 1373 { 1374 result.AppendErrorWithFormat ("Failed to halt process: %s\n", error.AsCString()); 1375 result.SetStatus (eReturnStatusFailed); 1376 } 1377 } 1378 else 1379 { 1380 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n", 1381 m_cmd_name.c_str(), 1382 m_cmd_syntax.c_str()); 1383 result.SetStatus (eReturnStatusFailed); 1384 } 1385 return result.Succeeded(); 1386 } 1387 }; 1388 1389 //------------------------------------------------------------------------- 1390 // CommandObjectProcessKill 1391 //------------------------------------------------------------------------- 1392 #pragma mark CommandObjectProcessKill 1393 1394 class CommandObjectProcessKill : public CommandObject 1395 { 1396 public: 1397 1398 CommandObjectProcessKill (CommandInterpreter &interpreter) : 1399 CommandObject (interpreter, 1400 "process kill", 1401 "Terminate the current process being debugged.", 1402 "process kill", 1403 eFlagProcessMustBeLaunched) 1404 { 1405 } 1406 1407 ~CommandObjectProcessKill () 1408 { 1409 } 1410 1411 bool 1412 Execute (Args& command, 1413 CommandReturnObject &result) 1414 { 1415 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr(); 1416 if (process == NULL) 1417 { 1418 result.AppendError ("no process to kill"); 1419 result.SetStatus (eReturnStatusFailed); 1420 return false; 1421 } 1422 1423 if (command.GetArgumentCount() == 0) 1424 { 1425 Error error (process->Destroy()); 1426 if (error.Success()) 1427 { 1428 result.SetStatus (eReturnStatusSuccessFinishResult); 1429 } 1430 else 1431 { 1432 result.AppendErrorWithFormat ("Failed to kill process: %s\n", error.AsCString()); 1433 result.SetStatus (eReturnStatusFailed); 1434 } 1435 } 1436 else 1437 { 1438 result.AppendErrorWithFormat("'%s' takes no arguments:\nUsage: %s\n", 1439 m_cmd_name.c_str(), 1440 m_cmd_syntax.c_str()); 1441 result.SetStatus (eReturnStatusFailed); 1442 } 1443 return result.Succeeded(); 1444 } 1445 }; 1446 1447 //------------------------------------------------------------------------- 1448 // CommandObjectProcessStatus 1449 //------------------------------------------------------------------------- 1450 #pragma mark CommandObjectProcessStatus 1451 1452 class CommandObjectProcessStatus : public CommandObject 1453 { 1454 public: 1455 CommandObjectProcessStatus (CommandInterpreter &interpreter) : 1456 CommandObject (interpreter, 1457 "process status", 1458 "Show the current status and location of executing process.", 1459 "process status", 1460 0) 1461 { 1462 } 1463 1464 ~CommandObjectProcessStatus() 1465 { 1466 } 1467 1468 1469 bool 1470 Execute 1471 ( 1472 Args& command, 1473 CommandReturnObject &result 1474 ) 1475 { 1476 Stream &strm = result.GetOutputStream(); 1477 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1478 ExecutionContext exe_ctx(m_interpreter.GetExecutionContext()); 1479 Process *process = exe_ctx.GetProcessPtr(); 1480 if (process) 1481 { 1482 const bool only_threads_with_stop_reason = true; 1483 const uint32_t start_frame = 0; 1484 const uint32_t num_frames = 1; 1485 const uint32_t num_frames_with_source = 1; 1486 process->GetStatus(strm); 1487 process->GetThreadStatus (strm, 1488 only_threads_with_stop_reason, 1489 start_frame, 1490 num_frames, 1491 num_frames_with_source); 1492 1493 } 1494 else 1495 { 1496 result.AppendError ("No process."); 1497 result.SetStatus (eReturnStatusFailed); 1498 } 1499 return result.Succeeded(); 1500 } 1501 }; 1502 1503 //------------------------------------------------------------------------- 1504 // CommandObjectProcessHandle 1505 //------------------------------------------------------------------------- 1506 #pragma mark CommandObjectProcessHandle 1507 1508 class CommandObjectProcessHandle : public CommandObject 1509 { 1510 public: 1511 1512 class CommandOptions : public Options 1513 { 1514 public: 1515 1516 CommandOptions (CommandInterpreter &interpreter) : 1517 Options (interpreter) 1518 { 1519 OptionParsingStarting (); 1520 } 1521 1522 ~CommandOptions () 1523 { 1524 } 1525 1526 Error 1527 SetOptionValue (uint32_t option_idx, const char *option_arg) 1528 { 1529 Error error; 1530 char short_option = (char) m_getopt_table[option_idx].val; 1531 1532 switch (short_option) 1533 { 1534 case 's': 1535 stop = option_arg; 1536 break; 1537 case 'n': 1538 notify = option_arg; 1539 break; 1540 case 'p': 1541 pass = option_arg; 1542 break; 1543 default: 1544 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option); 1545 break; 1546 } 1547 return error; 1548 } 1549 1550 void 1551 OptionParsingStarting () 1552 { 1553 stop.clear(); 1554 notify.clear(); 1555 pass.clear(); 1556 } 1557 1558 const OptionDefinition* 1559 GetDefinitions () 1560 { 1561 return g_option_table; 1562 } 1563 1564 // Options table: Required for subclasses of Options. 1565 1566 static OptionDefinition g_option_table[]; 1567 1568 // Instance variables to hold the values for command options. 1569 1570 std::string stop; 1571 std::string notify; 1572 std::string pass; 1573 }; 1574 1575 1576 CommandObjectProcessHandle (CommandInterpreter &interpreter) : 1577 CommandObject (interpreter, 1578 "process handle", 1579 "Show or update what the process and debugger should do with various signals received from the OS.", 1580 NULL), 1581 m_options (interpreter) 1582 { 1583 SetHelpLong ("If no signals are specified, update them all. If no update option is specified, list the current values.\n"); 1584 CommandArgumentEntry arg; 1585 CommandArgumentData signal_arg; 1586 1587 signal_arg.arg_type = eArgTypeUnixSignal; 1588 signal_arg.arg_repetition = eArgRepeatStar; 1589 1590 arg.push_back (signal_arg); 1591 1592 m_arguments.push_back (arg); 1593 } 1594 1595 ~CommandObjectProcessHandle () 1596 { 1597 } 1598 1599 Options * 1600 GetOptions () 1601 { 1602 return &m_options; 1603 } 1604 1605 bool 1606 VerifyCommandOptionValue (const std::string &option, int &real_value) 1607 { 1608 bool okay = true; 1609 1610 bool success = false; 1611 bool tmp_value = Args::StringToBoolean (option.c_str(), false, &success); 1612 1613 if (success && tmp_value) 1614 real_value = 1; 1615 else if (success && !tmp_value) 1616 real_value = 0; 1617 else 1618 { 1619 // If the value isn't 'true' or 'false', it had better be 0 or 1. 1620 real_value = Args::StringToUInt32 (option.c_str(), 3); 1621 if (real_value != 0 && real_value != 1) 1622 okay = false; 1623 } 1624 1625 return okay; 1626 } 1627 1628 void 1629 PrintSignalHeader (Stream &str) 1630 { 1631 str.Printf ("NAME PASS STOP NOTIFY\n"); 1632 str.Printf ("========== ===== ===== ======\n"); 1633 } 1634 1635 void 1636 PrintSignal (Stream &str, int32_t signo, const char *sig_name, UnixSignals &signals) 1637 { 1638 bool stop; 1639 bool suppress; 1640 bool notify; 1641 1642 str.Printf ("%-10s ", sig_name); 1643 if (signals.GetSignalInfo (signo, suppress, stop, notify)) 1644 { 1645 bool pass = !suppress; 1646 str.Printf ("%s %s %s", 1647 (pass ? "true " : "false"), 1648 (stop ? "true " : "false"), 1649 (notify ? "true " : "false")); 1650 } 1651 str.Printf ("\n"); 1652 } 1653 1654 void 1655 PrintSignalInformation (Stream &str, Args &signal_args, int num_valid_signals, UnixSignals &signals) 1656 { 1657 PrintSignalHeader (str); 1658 1659 if (num_valid_signals > 0) 1660 { 1661 size_t num_args = signal_args.GetArgumentCount(); 1662 for (size_t i = 0; i < num_args; ++i) 1663 { 1664 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i)); 1665 if (signo != LLDB_INVALID_SIGNAL_NUMBER) 1666 PrintSignal (str, signo, signal_args.GetArgumentAtIndex (i), signals); 1667 } 1668 } 1669 else // Print info for ALL signals 1670 { 1671 int32_t signo = signals.GetFirstSignalNumber(); 1672 while (signo != LLDB_INVALID_SIGNAL_NUMBER) 1673 { 1674 PrintSignal (str, signo, signals.GetSignalAsCString (signo), signals); 1675 signo = signals.GetNextSignalNumber (signo); 1676 } 1677 } 1678 } 1679 1680 bool 1681 Execute (Args &signal_args, CommandReturnObject &result) 1682 { 1683 TargetSP target_sp = m_interpreter.GetDebugger().GetSelectedTarget(); 1684 1685 if (!target_sp) 1686 { 1687 result.AppendError ("No current target;" 1688 " cannot handle signals until you have a valid target and process.\n"); 1689 result.SetStatus (eReturnStatusFailed); 1690 return false; 1691 } 1692 1693 ProcessSP process_sp = target_sp->GetProcessSP(); 1694 1695 if (!process_sp) 1696 { 1697 result.AppendError ("No current process; cannot handle signals until you have a valid process.\n"); 1698 result.SetStatus (eReturnStatusFailed); 1699 return false; 1700 } 1701 1702 int stop_action = -1; // -1 means leave the current setting alone 1703 int pass_action = -1; // -1 means leave the current setting alone 1704 int notify_action = -1; // -1 means leave the current setting alone 1705 1706 if (! m_options.stop.empty() 1707 && ! VerifyCommandOptionValue (m_options.stop, stop_action)) 1708 { 1709 result.AppendError ("Invalid argument for command option --stop; must be true or false.\n"); 1710 result.SetStatus (eReturnStatusFailed); 1711 return false; 1712 } 1713 1714 if (! m_options.notify.empty() 1715 && ! VerifyCommandOptionValue (m_options.notify, notify_action)) 1716 { 1717 result.AppendError ("Invalid argument for command option --notify; must be true or false.\n"); 1718 result.SetStatus (eReturnStatusFailed); 1719 return false; 1720 } 1721 1722 if (! m_options.pass.empty() 1723 && ! VerifyCommandOptionValue (m_options.pass, pass_action)) 1724 { 1725 result.AppendError ("Invalid argument for command option --pass; must be true or false.\n"); 1726 result.SetStatus (eReturnStatusFailed); 1727 return false; 1728 } 1729 1730 size_t num_args = signal_args.GetArgumentCount(); 1731 UnixSignals &signals = process_sp->GetUnixSignals(); 1732 int num_signals_set = 0; 1733 1734 if (num_args > 0) 1735 { 1736 for (size_t i = 0; i < num_args; ++i) 1737 { 1738 int32_t signo = signals.GetSignalNumberFromName (signal_args.GetArgumentAtIndex (i)); 1739 if (signo != LLDB_INVALID_SIGNAL_NUMBER) 1740 { 1741 // Casting the actions as bools here should be okay, because VerifyCommandOptionValue guarantees 1742 // the value is either 0 or 1. 1743 if (stop_action != -1) 1744 signals.SetShouldStop (signo, (bool) stop_action); 1745 if (pass_action != -1) 1746 { 1747 bool suppress = ! ((bool) pass_action); 1748 signals.SetShouldSuppress (signo, suppress); 1749 } 1750 if (notify_action != -1) 1751 signals.SetShouldNotify (signo, (bool) notify_action); 1752 ++num_signals_set; 1753 } 1754 else 1755 { 1756 result.AppendErrorWithFormat ("Invalid signal name '%s'\n", signal_args.GetArgumentAtIndex (i)); 1757 } 1758 } 1759 } 1760 else 1761 { 1762 // No signal specified, if any command options were specified, update ALL signals. 1763 if ((notify_action != -1) || (stop_action != -1) || (pass_action != -1)) 1764 { 1765 if (m_interpreter.Confirm ("Do you really want to update all the signals?", false)) 1766 { 1767 int32_t signo = signals.GetFirstSignalNumber(); 1768 while (signo != LLDB_INVALID_SIGNAL_NUMBER) 1769 { 1770 if (notify_action != -1) 1771 signals.SetShouldNotify (signo, (bool) notify_action); 1772 if (stop_action != -1) 1773 signals.SetShouldStop (signo, (bool) stop_action); 1774 if (pass_action != -1) 1775 { 1776 bool suppress = ! ((bool) pass_action); 1777 signals.SetShouldSuppress (signo, suppress); 1778 } 1779 signo = signals.GetNextSignalNumber (signo); 1780 } 1781 } 1782 } 1783 } 1784 1785 PrintSignalInformation (result.GetOutputStream(), signal_args, num_signals_set, signals); 1786 1787 if (num_signals_set > 0) 1788 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1789 else 1790 result.SetStatus (eReturnStatusFailed); 1791 1792 return result.Succeeded(); 1793 } 1794 1795 protected: 1796 1797 CommandOptions m_options; 1798 }; 1799 1800 OptionDefinition 1801 CommandObjectProcessHandle::CommandOptions::g_option_table[] = 1802 { 1803 { 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." }, 1804 { 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." }, 1805 { LLDB_OPT_SET_1, false, "pass", 'p', required_argument, NULL, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." }, 1806 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 1807 }; 1808 1809 //------------------------------------------------------------------------- 1810 // CommandObjectMultiwordProcess 1811 //------------------------------------------------------------------------- 1812 1813 CommandObjectMultiwordProcess::CommandObjectMultiwordProcess (CommandInterpreter &interpreter) : 1814 CommandObjectMultiword (interpreter, 1815 "process", 1816 "A set of commands for operating on a process.", 1817 "process <subcommand> [<subcommand-options>]") 1818 { 1819 LoadSubCommand ("attach", CommandObjectSP (new CommandObjectProcessAttach (interpreter))); 1820 LoadSubCommand ("launch", CommandObjectSP (new CommandObjectProcessLaunch (interpreter))); 1821 LoadSubCommand ("continue", CommandObjectSP (new CommandObjectProcessContinue (interpreter))); 1822 LoadSubCommand ("connect", CommandObjectSP (new CommandObjectProcessConnect (interpreter))); 1823 LoadSubCommand ("detach", CommandObjectSP (new CommandObjectProcessDetach (interpreter))); 1824 LoadSubCommand ("load", CommandObjectSP (new CommandObjectProcessLoad (interpreter))); 1825 LoadSubCommand ("unload", CommandObjectSP (new CommandObjectProcessUnload (interpreter))); 1826 LoadSubCommand ("signal", CommandObjectSP (new CommandObjectProcessSignal (interpreter))); 1827 LoadSubCommand ("handle", CommandObjectSP (new CommandObjectProcessHandle (interpreter))); 1828 LoadSubCommand ("status", CommandObjectSP (new CommandObjectProcessStatus (interpreter))); 1829 LoadSubCommand ("interrupt", CommandObjectSP (new CommandObjectProcessInterrupt (interpreter))); 1830 LoadSubCommand ("kill", CommandObjectSP (new CommandObjectProcessKill (interpreter))); 1831 } 1832 1833 CommandObjectMultiwordProcess::~CommandObjectMultiwordProcess () 1834 { 1835 } 1836 1837