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