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