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