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