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