1 //===-- CommandObjectTarget.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 "CommandObjectTarget.h" 11 12 // C Includes 13 #include <errno.h> 14 15 // C++ Includes 16 // Other libraries and framework includes 17 // Project includes 18 #include "lldb/Interpreter/Args.h" 19 #include "lldb/Core/Debugger.h" 20 #include "lldb/Core/InputReader.h" 21 #include "lldb/Core/State.h" 22 #include "lldb/Core/Timer.h" 23 #include "lldb/Interpreter/CommandInterpreter.h" 24 #include "lldb/Interpreter/CommandReturnObject.h" 25 #include "lldb/Interpreter/OptionGroupArchitecture.h" 26 #include "lldb/Interpreter/OptionGroupPlatform.h" 27 #include "lldb/Target/Process.h" 28 #include "lldb/Target/StackFrame.h" 29 #include "lldb/Target/Thread.h" 30 #include "lldb/Target/ThreadSpec.h" 31 32 using namespace lldb; 33 using namespace lldb_private; 34 35 36 37 static void 38 DumpTargetInfo (uint32_t target_idx, Target *target, const char *prefix_cstr, bool show_stopped_process_status, Stream &strm) 39 { 40 ArchSpec &target_arch = target->GetArchitecture(); 41 42 ModuleSP exe_module_sp (target->GetExecutableModule ()); 43 char exe_path[PATH_MAX]; 44 bool exe_valid = false; 45 if (exe_module_sp) 46 exe_valid = exe_module_sp->GetFileSpec().GetPath (exe_path, sizeof(exe_path)); 47 48 if (!exe_valid) 49 ::strcpy (exe_path, "<none>"); 50 51 strm.Printf ("%starget #%u: %s", prefix_cstr ? prefix_cstr : "", target_idx, exe_path); 52 53 uint32_t properties = 0; 54 if (target_arch.IsValid()) 55 { 56 strm.Printf ("%sarch=%s", properties++ > 0 ? ", " : " ( ", target_arch.GetTriple().str().c_str()); 57 properties++; 58 } 59 PlatformSP platform_sp (target->GetPlatform()); 60 if (platform_sp) 61 strm.Printf ("%splatform=%s", properties++ > 0 ? ", " : " ( ", platform_sp->GetName()); 62 63 ProcessSP process_sp (target->GetProcessSP()); 64 bool show_process_status = false; 65 if (process_sp) 66 { 67 lldb::pid_t pid = process_sp->GetID(); 68 StateType state = process_sp->GetState(); 69 if (show_stopped_process_status) 70 show_process_status = StateIsStoppedState(state); 71 const char *state_cstr = StateAsCString (state); 72 if (pid != LLDB_INVALID_PROCESS_ID) 73 strm.Printf ("%spid=%i", properties++ > 0 ? ", " : " ( ", pid); 74 strm.Printf ("%sstate=%s", properties++ > 0 ? ", " : " ( ", state_cstr); 75 } 76 if (properties > 0) 77 strm.PutCString (" )\n"); 78 else 79 strm.EOL(); 80 if (show_process_status) 81 { 82 const bool only_threads_with_stop_reason = true; 83 const uint32_t start_frame = 0; 84 const uint32_t num_frames = 1; 85 const uint32_t num_frames_with_source = 1; 86 process_sp->GetStatus (strm); 87 process_sp->GetThreadStatus (strm, 88 only_threads_with_stop_reason, 89 start_frame, 90 num_frames, 91 num_frames_with_source); 92 93 } 94 } 95 96 static uint32_t 97 DumpTargetList (TargetList &target_list, bool show_stopped_process_status, Stream &strm) 98 { 99 const uint32_t num_targets = target_list.GetNumTargets(); 100 if (num_targets) 101 { 102 TargetSP selected_target_sp (target_list.GetSelectedTarget()); 103 strm.PutCString ("Current targets:\n"); 104 for (uint32_t i=0; i<num_targets; ++i) 105 { 106 TargetSP target_sp (target_list.GetTargetAtIndex (i)); 107 if (target_sp) 108 { 109 bool is_selected = target_sp.get() == selected_target_sp.get(); 110 DumpTargetInfo (i, 111 target_sp.get(), 112 is_selected ? "* " : " ", 113 show_stopped_process_status, 114 strm); 115 } 116 } 117 } 118 return num_targets; 119 } 120 #pragma mark CommandObjectTargetCreate 121 122 //------------------------------------------------------------------------- 123 // "target create" 124 //------------------------------------------------------------------------- 125 126 class CommandObjectTargetCreate : public CommandObject 127 { 128 public: 129 CommandObjectTargetCreate(CommandInterpreter &interpreter) : 130 CommandObject (interpreter, 131 "target create", 132 "Create a target using the argument as the main executable.", 133 NULL), 134 m_option_group (interpreter), 135 m_file_options (), 136 m_platform_options(true) // Do include the "--platform" option in the platform settings by passing true 137 { 138 CommandArgumentEntry arg; 139 CommandArgumentData file_arg; 140 141 // Define the first (and only) variant of this arg. 142 file_arg.arg_type = eArgTypeFilename; 143 file_arg.arg_repetition = eArgRepeatPlain; 144 145 // There is only one variant this argument could be; put it into the argument entry. 146 arg.push_back (file_arg); 147 148 // Push the data for the first argument into the m_arguments vector. 149 m_arguments.push_back (arg); 150 151 m_option_group.Append (&m_file_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 152 m_option_group.Append (&m_platform_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 153 m_option_group.Finalize(); 154 } 155 156 ~CommandObjectTargetCreate () 157 { 158 } 159 160 Options * 161 GetOptions () 162 { 163 return &m_option_group; 164 } 165 166 bool 167 Execute (Args& command, CommandReturnObject &result) 168 { 169 const int argc = command.GetArgumentCount(); 170 if (argc == 1) 171 { 172 const char *file_path = command.GetArgumentAtIndex(0); 173 Timer scoped_timer(__PRETTY_FUNCTION__, "(lldb) target create '%s'", file_path); 174 FileSpec file_spec (file_path, true); 175 176 bool select = true; 177 PlatformSP platform_sp; 178 179 Error error; 180 181 if (m_platform_options.PlatformWasSpecified ()) 182 { 183 platform_sp = m_platform_options.CreatePlatformWithOptions(m_interpreter, select, error); 184 if (!platform_sp) 185 { 186 result.AppendError(error.AsCString()); 187 result.SetStatus (eReturnStatusFailed); 188 return false; 189 } 190 } 191 ArchSpec file_arch; 192 193 const char *arch_cstr = m_file_options.GetArchitectureName(); 194 if (arch_cstr) 195 { 196 if (!platform_sp) 197 platform_sp = m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform(); 198 if (!m_file_options.GetArchitecture(platform_sp.get(), file_arch)) 199 { 200 result.AppendErrorWithFormat("invalid architecture '%s'\n", arch_cstr); 201 result.SetStatus (eReturnStatusFailed); 202 return false; 203 } 204 } 205 206 if (! file_spec.Exists() && !file_spec.ResolveExecutableLocation()) 207 { 208 result.AppendErrorWithFormat ("File '%s' does not exist.\n", file_path); 209 result.SetStatus (eReturnStatusFailed); 210 return false; 211 } 212 213 TargetSP target_sp; 214 Debugger &debugger = m_interpreter.GetDebugger(); 215 error = debugger.GetTargetList().CreateTarget (debugger, file_spec, file_arch, true, target_sp); 216 217 if (target_sp) 218 { 219 debugger.GetTargetList().SetSelectedTarget(target_sp.get()); 220 result.AppendMessageWithFormat ("Current executable set to '%s' (%s).\n", file_path, target_sp->GetArchitecture().GetArchitectureName()); 221 result.SetStatus (eReturnStatusSuccessFinishNoResult); 222 } 223 else 224 { 225 result.AppendError(error.AsCString()); 226 result.SetStatus (eReturnStatusFailed); 227 } 228 } 229 else 230 { 231 result.AppendErrorWithFormat("'%s' takes exactly one executable path argument.\n", m_cmd_name.c_str()); 232 result.SetStatus (eReturnStatusFailed); 233 } 234 return result.Succeeded(); 235 236 } 237 238 int 239 HandleArgumentCompletion (Args &input, 240 int &cursor_index, 241 int &cursor_char_position, 242 OptionElementVector &opt_element_vector, 243 int match_start_point, 244 int max_return_elements, 245 bool &word_complete, 246 StringList &matches) 247 { 248 std::string completion_str (input.GetArgumentAtIndex(cursor_index)); 249 completion_str.erase (cursor_char_position); 250 251 CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter, 252 CommandCompletions::eDiskFileCompletion, 253 completion_str.c_str(), 254 match_start_point, 255 max_return_elements, 256 NULL, 257 word_complete, 258 matches); 259 return matches.GetSize(); 260 } 261 private: 262 OptionGroupOptions m_option_group; 263 OptionGroupArchitecture m_file_options; 264 OptionGroupPlatform m_platform_options; 265 266 }; 267 268 #pragma mark CommandObjectTargetList 269 270 //---------------------------------------------------------------------- 271 // "target list" 272 //---------------------------------------------------------------------- 273 274 class CommandObjectTargetList : public CommandObject 275 { 276 public: 277 CommandObjectTargetList (CommandInterpreter &interpreter) : 278 CommandObject (interpreter, 279 "target list", 280 "List all current targets in the current debug session.", 281 NULL, 282 0) 283 { 284 } 285 286 virtual 287 ~CommandObjectTargetList () 288 { 289 } 290 291 virtual bool 292 Execute (Args& args, CommandReturnObject &result) 293 { 294 if (args.GetArgumentCount() == 0) 295 { 296 Stream &strm = result.GetOutputStream(); 297 298 bool show_stopped_process_status = false; 299 if (DumpTargetList (m_interpreter.GetDebugger().GetTargetList(), show_stopped_process_status, strm) == 0) 300 { 301 strm.PutCString ("No targets.\n"); 302 } 303 } 304 else 305 { 306 result.AppendError ("the 'target list' command takes no arguments\n"); 307 result.SetStatus (eReturnStatusFailed); 308 } 309 return result.Succeeded(); 310 } 311 }; 312 313 314 #pragma mark CommandObjectTargetSelect 315 316 //---------------------------------------------------------------------- 317 // "target select" 318 //---------------------------------------------------------------------- 319 320 class CommandObjectTargetSelect : public CommandObject 321 { 322 public: 323 CommandObjectTargetSelect (CommandInterpreter &interpreter) : 324 CommandObject (interpreter, 325 "target select", 326 "Select a target as the current target by target index.", 327 NULL, 328 0) 329 { 330 } 331 332 virtual 333 ~CommandObjectTargetSelect () 334 { 335 } 336 337 virtual bool 338 Execute (Args& args, CommandReturnObject &result) 339 { 340 if (args.GetArgumentCount() == 1) 341 { 342 bool success = false; 343 const char *target_idx_arg = args.GetArgumentAtIndex(0); 344 uint32_t target_idx = Args::StringToUInt32 (target_idx_arg, UINT32_MAX, 0, &success); 345 if (success) 346 { 347 TargetList &target_list = m_interpreter.GetDebugger().GetTargetList(); 348 const uint32_t num_targets = target_list.GetNumTargets(); 349 if (target_idx < num_targets) 350 { 351 TargetSP target_sp (target_list.GetTargetAtIndex (target_idx)); 352 if (target_sp) 353 { 354 Stream &strm = result.GetOutputStream(); 355 target_list.SetSelectedTarget (target_sp.get()); 356 bool show_stopped_process_status = false; 357 DumpTargetList (target_list, show_stopped_process_status, strm); 358 } 359 else 360 { 361 result.AppendErrorWithFormat ("target #%u is NULL in target list\n", target_idx); 362 result.SetStatus (eReturnStatusFailed); 363 } 364 } 365 else 366 { 367 result.AppendErrorWithFormat ("index %u is out of range, valid target indexes are 0 - %u\n", 368 target_idx, 369 num_targets - 1); 370 result.SetStatus (eReturnStatusFailed); 371 } 372 } 373 else 374 { 375 result.AppendErrorWithFormat("invalid index string value '%s'\n", target_idx_arg); 376 result.SetStatus (eReturnStatusFailed); 377 } 378 } 379 else 380 { 381 result.AppendError ("'target select' takes a single argument: a target index\n"); 382 result.SetStatus (eReturnStatusFailed); 383 } 384 return result.Succeeded(); 385 } 386 }; 387 388 389 #pragma mark CommandObjectTargetImageSearchPaths 390 391 class CommandObjectTargetImageSearchPathsAdd : public CommandObject 392 { 393 public: 394 395 CommandObjectTargetImageSearchPathsAdd (CommandInterpreter &interpreter) : 396 CommandObject (interpreter, 397 "target image-search-paths add", 398 "Add new image search paths substitution pairs to the current target.", 399 NULL) 400 { 401 CommandArgumentEntry arg; 402 CommandArgumentData old_prefix_arg; 403 CommandArgumentData new_prefix_arg; 404 405 // Define the first variant of this arg pair. 406 old_prefix_arg.arg_type = eArgTypeOldPathPrefix; 407 old_prefix_arg.arg_repetition = eArgRepeatPairPlus; 408 409 // Define the first variant of this arg pair. 410 new_prefix_arg.arg_type = eArgTypeNewPathPrefix; 411 new_prefix_arg.arg_repetition = eArgRepeatPairPlus; 412 413 // There are two required arguments that must always occur together, i.e. an argument "pair". Because they 414 // must always occur together, they are treated as two variants of one argument rather than two independent 415 // arguments. Push them both into the first argument position for m_arguments... 416 417 arg.push_back (old_prefix_arg); 418 arg.push_back (new_prefix_arg); 419 420 m_arguments.push_back (arg); 421 } 422 423 ~CommandObjectTargetImageSearchPathsAdd () 424 { 425 } 426 427 bool 428 Execute (Args& command, 429 CommandReturnObject &result) 430 { 431 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 432 if (target) 433 { 434 uint32_t argc = command.GetArgumentCount(); 435 if (argc & 1) 436 { 437 result.AppendError ("add requires an even number of arguments\n"); 438 result.SetStatus (eReturnStatusFailed); 439 } 440 else 441 { 442 for (uint32_t i=0; i<argc; i+=2) 443 { 444 const char *from = command.GetArgumentAtIndex(i); 445 const char *to = command.GetArgumentAtIndex(i+1); 446 447 if (from[0] && to[0]) 448 { 449 bool last_pair = ((argc - i) == 2); 450 target->GetImageSearchPathList().Append (ConstString(from), 451 ConstString(to), 452 last_pair); // Notify if this is the last pair 453 result.SetStatus (eReturnStatusSuccessFinishNoResult); 454 } 455 else 456 { 457 if (from[0]) 458 result.AppendError ("<path-prefix> can't be empty\n"); 459 else 460 result.AppendError ("<new-path-prefix> can't be empty\n"); 461 result.SetStatus (eReturnStatusFailed); 462 } 463 } 464 } 465 } 466 else 467 { 468 result.AppendError ("invalid target\n"); 469 result.SetStatus (eReturnStatusFailed); 470 } 471 return result.Succeeded(); 472 } 473 }; 474 475 class CommandObjectTargetImageSearchPathsClear : public CommandObject 476 { 477 public: 478 479 CommandObjectTargetImageSearchPathsClear (CommandInterpreter &interpreter) : 480 CommandObject (interpreter, 481 "target image-search-paths clear", 482 "Clear all current image search path substitution pairs from the current target.", 483 "target image-search-paths clear") 484 { 485 } 486 487 ~CommandObjectTargetImageSearchPathsClear () 488 { 489 } 490 491 bool 492 Execute (Args& command, 493 CommandReturnObject &result) 494 { 495 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 496 if (target) 497 { 498 bool notify = true; 499 target->GetImageSearchPathList().Clear(notify); 500 result.SetStatus (eReturnStatusSuccessFinishNoResult); 501 } 502 else 503 { 504 result.AppendError ("invalid target\n"); 505 result.SetStatus (eReturnStatusFailed); 506 } 507 return result.Succeeded(); 508 } 509 }; 510 511 class CommandObjectTargetImageSearchPathsInsert : public CommandObject 512 { 513 public: 514 515 CommandObjectTargetImageSearchPathsInsert (CommandInterpreter &interpreter) : 516 CommandObject (interpreter, 517 "target image-search-paths insert", 518 "Insert a new image search path substitution pair into the current target at the specified index.", 519 NULL) 520 { 521 CommandArgumentEntry arg1; 522 CommandArgumentEntry arg2; 523 CommandArgumentData index_arg; 524 CommandArgumentData old_prefix_arg; 525 CommandArgumentData new_prefix_arg; 526 527 // Define the first and only variant of this arg. 528 index_arg.arg_type = eArgTypeIndex; 529 index_arg.arg_repetition = eArgRepeatPlain; 530 531 // Put the one and only variant into the first arg for m_arguments: 532 arg1.push_back (index_arg); 533 534 // Define the first variant of this arg pair. 535 old_prefix_arg.arg_type = eArgTypeOldPathPrefix; 536 old_prefix_arg.arg_repetition = eArgRepeatPairPlus; 537 538 // Define the first variant of this arg pair. 539 new_prefix_arg.arg_type = eArgTypeNewPathPrefix; 540 new_prefix_arg.arg_repetition = eArgRepeatPairPlus; 541 542 // There are two required arguments that must always occur together, i.e. an argument "pair". Because they 543 // must always occur together, they are treated as two variants of one argument rather than two independent 544 // arguments. Push them both into the same argument position for m_arguments... 545 546 arg2.push_back (old_prefix_arg); 547 arg2.push_back (new_prefix_arg); 548 549 // Add arguments to m_arguments. 550 m_arguments.push_back (arg1); 551 m_arguments.push_back (arg2); 552 } 553 554 ~CommandObjectTargetImageSearchPathsInsert () 555 { 556 } 557 558 bool 559 Execute (Args& command, 560 CommandReturnObject &result) 561 { 562 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 563 if (target) 564 { 565 uint32_t argc = command.GetArgumentCount(); 566 // check for at least 3 arguments and an odd nubmer of parameters 567 if (argc >= 3 && argc & 1) 568 { 569 bool success = false; 570 571 uint32_t insert_idx = Args::StringToUInt32(command.GetArgumentAtIndex(0), UINT32_MAX, 0, &success); 572 573 if (!success) 574 { 575 result.AppendErrorWithFormat("<index> parameter is not an integer: '%s'.\n", command.GetArgumentAtIndex(0)); 576 result.SetStatus (eReturnStatusFailed); 577 return result.Succeeded(); 578 } 579 580 // shift off the index 581 command.Shift(); 582 argc = command.GetArgumentCount(); 583 584 for (uint32_t i=0; i<argc; i+=2, ++insert_idx) 585 { 586 const char *from = command.GetArgumentAtIndex(i); 587 const char *to = command.GetArgumentAtIndex(i+1); 588 589 if (from[0] && to[0]) 590 { 591 bool last_pair = ((argc - i) == 2); 592 target->GetImageSearchPathList().Insert (ConstString(from), 593 ConstString(to), 594 insert_idx, 595 last_pair); 596 result.SetStatus (eReturnStatusSuccessFinishNoResult); 597 } 598 else 599 { 600 if (from[0]) 601 result.AppendError ("<path-prefix> can't be empty\n"); 602 else 603 result.AppendError ("<new-path-prefix> can't be empty\n"); 604 result.SetStatus (eReturnStatusFailed); 605 return false; 606 } 607 } 608 } 609 else 610 { 611 result.AppendError ("insert requires at least three arguments\n"); 612 result.SetStatus (eReturnStatusFailed); 613 return result.Succeeded(); 614 } 615 616 } 617 else 618 { 619 result.AppendError ("invalid target\n"); 620 result.SetStatus (eReturnStatusFailed); 621 } 622 return result.Succeeded(); 623 } 624 }; 625 626 class CommandObjectTargetImageSearchPathsList : public CommandObject 627 { 628 public: 629 630 CommandObjectTargetImageSearchPathsList (CommandInterpreter &interpreter) : 631 CommandObject (interpreter, 632 "target image-search-paths list", 633 "List all current image search path substitution pairs in the current target.", 634 "target image-search-paths list") 635 { 636 } 637 638 ~CommandObjectTargetImageSearchPathsList () 639 { 640 } 641 642 bool 643 Execute (Args& command, 644 CommandReturnObject &result) 645 { 646 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 647 if (target) 648 { 649 if (command.GetArgumentCount() != 0) 650 { 651 result.AppendError ("list takes no arguments\n"); 652 result.SetStatus (eReturnStatusFailed); 653 return result.Succeeded(); 654 } 655 656 target->GetImageSearchPathList().Dump(&result.GetOutputStream()); 657 result.SetStatus (eReturnStatusSuccessFinishResult); 658 } 659 else 660 { 661 result.AppendError ("invalid target\n"); 662 result.SetStatus (eReturnStatusFailed); 663 } 664 return result.Succeeded(); 665 } 666 }; 667 668 class CommandObjectTargetImageSearchPathsQuery : public CommandObject 669 { 670 public: 671 672 CommandObjectTargetImageSearchPathsQuery (CommandInterpreter &interpreter) : 673 CommandObject (interpreter, 674 "target image-search-paths query", 675 "Transform a path using the first applicable image search path.", 676 NULL) 677 { 678 CommandArgumentEntry arg; 679 CommandArgumentData path_arg; 680 681 // Define the first (and only) variant of this arg. 682 path_arg.arg_type = eArgTypePath; 683 path_arg.arg_repetition = eArgRepeatPlain; 684 685 // There is only one variant this argument could be; put it into the argument entry. 686 arg.push_back (path_arg); 687 688 // Push the data for the first argument into the m_arguments vector. 689 m_arguments.push_back (arg); 690 } 691 692 ~CommandObjectTargetImageSearchPathsQuery () 693 { 694 } 695 696 bool 697 Execute (Args& command, 698 CommandReturnObject &result) 699 { 700 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 701 if (target) 702 { 703 if (command.GetArgumentCount() != 1) 704 { 705 result.AppendError ("query requires one argument\n"); 706 result.SetStatus (eReturnStatusFailed); 707 return result.Succeeded(); 708 } 709 710 ConstString orig(command.GetArgumentAtIndex(0)); 711 ConstString transformed; 712 if (target->GetImageSearchPathList().RemapPath(orig, transformed)) 713 result.GetOutputStream().Printf("%s\n", transformed.GetCString()); 714 else 715 result.GetOutputStream().Printf("%s\n", orig.GetCString()); 716 717 result.SetStatus (eReturnStatusSuccessFinishResult); 718 } 719 else 720 { 721 result.AppendError ("invalid target\n"); 722 result.SetStatus (eReturnStatusFailed); 723 } 724 return result.Succeeded(); 725 } 726 }; 727 728 // TODO: implement the target select later when we start doing multiple targets 729 //#pragma mark CommandObjectTargetSelect 730 // 731 ////------------------------------------------------------------------------- 732 //// CommandObjectTargetSelect 733 ////------------------------------------------------------------------------- 734 // 735 //class CommandObjectTargetSelect : public CommandObject 736 //{ 737 //public: 738 // 739 // CommandObjectTargetSelect () : 740 // CommandObject (interpreter, 741 // frame select", 742 // "Select the current frame by index in the current thread.", 743 // "frame select <frame-index>") 744 // { 745 // } 746 // 747 // ~CommandObjectTargetSelect () 748 // { 749 // } 750 // 751 // bool 752 // Execute (Args& command, 753 // Debugger *context, 754 // CommandInterpreter &m_interpreter, 755 // CommandReturnObject &result) 756 // { 757 // ExecutionContext exe_ctx (context->GetExecutionContext()); 758 // if (exe_ctx.thread) 759 // { 760 // if (command.GetArgumentCount() == 1) 761 // { 762 // const char *frame_idx_cstr = command.GetArgumentAtIndex(0); 763 // 764 // const uint32_t num_frames = exe_ctx.thread->GetStackFrameCount(); 765 // const uint32_t frame_idx = Args::StringToUInt32 (frame_idx_cstr, UINT32_MAX, 0); 766 // if (frame_idx < num_frames) 767 // { 768 // exe_ctx.thread->SetSelectedFrameByIndex (frame_idx); 769 // exe_ctx.frame = exe_ctx.thread->GetSelectedFrame ().get(); 770 // 771 // if (exe_ctx.frame) 772 // { 773 // if (DisplayFrameForExecutionContext (exe_ctx.thread, 774 // exe_ctx.frame, 775 // m_interpreter, 776 // result.GetOutputStream(), 777 // true, 778 // true, 779 // 3, 780 // 3)) 781 // { 782 // result.SetStatus (eReturnStatusSuccessFinishResult); 783 // return result.Succeeded(); 784 // } 785 // } 786 // } 787 // if (frame_idx == UINT32_MAX) 788 // result.AppendErrorWithFormat ("Invalid frame index: %s.\n", frame_idx_cstr); 789 // else 790 // result.AppendErrorWithFormat ("Frame index (%u) out of range.\n", frame_idx); 791 // } 792 // else 793 // { 794 // result.AppendError ("invalid arguments"); 795 // result.AppendErrorWithFormat ("Usage: %s\n", m_cmd_syntax.c_str()); 796 // } 797 // } 798 // else 799 // { 800 // result.AppendError ("no current thread"); 801 // } 802 // result.SetStatus (eReturnStatusFailed); 803 // return false; 804 // } 805 //}; 806 807 808 #pragma mark CommandObjectMultiwordImageSearchPaths 809 810 //------------------------------------------------------------------------- 811 // CommandObjectMultiwordImageSearchPaths 812 //------------------------------------------------------------------------- 813 814 class CommandObjectMultiwordImageSearchPaths : public CommandObjectMultiword 815 { 816 public: 817 818 CommandObjectMultiwordImageSearchPaths (CommandInterpreter &interpreter) : 819 CommandObjectMultiword (interpreter, 820 "target image-search-paths", 821 "A set of commands for operating on debugger target image search paths.", 822 "target image-search-paths <subcommand> [<subcommand-options>]") 823 { 824 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTargetImageSearchPathsAdd (interpreter))); 825 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTargetImageSearchPathsClear (interpreter))); 826 LoadSubCommand ("insert", CommandObjectSP (new CommandObjectTargetImageSearchPathsInsert (interpreter))); 827 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTargetImageSearchPathsList (interpreter))); 828 LoadSubCommand ("query", CommandObjectSP (new CommandObjectTargetImageSearchPathsQuery (interpreter))); 829 } 830 831 ~CommandObjectMultiwordImageSearchPaths() 832 { 833 } 834 }; 835 836 #pragma mark CommandObjectTargetStopHookAdd 837 838 //------------------------------------------------------------------------- 839 // CommandObjectTargetStopHookAdd 840 //------------------------------------------------------------------------- 841 842 class CommandObjectTargetStopHookAdd : public CommandObject 843 { 844 public: 845 846 class CommandOptions : public Options 847 { 848 public: 849 CommandOptions (CommandInterpreter &interpreter) : 850 Options(interpreter), 851 m_line_start(0), 852 m_line_end (UINT_MAX), 853 m_func_name_type_mask (eFunctionNameTypeAuto), 854 m_sym_ctx_specified (false), 855 m_thread_specified (false) 856 { 857 } 858 859 ~CommandOptions () {} 860 861 const OptionDefinition* 862 GetDefinitions () 863 { 864 return g_option_table; 865 } 866 867 virtual Error 868 SetOptionValue (uint32_t option_idx, const char *option_arg) 869 { 870 Error error; 871 char short_option = (char) m_getopt_table[option_idx].val; 872 bool success; 873 874 switch (short_option) 875 { 876 case 'c': 877 m_class_name = option_arg; 878 m_sym_ctx_specified = true; 879 break; 880 881 case 'e': 882 m_line_end = Args::StringToUInt32 (option_arg, UINT_MAX, 0, &success); 883 if (!success) 884 { 885 error.SetErrorStringWithFormat ("Invalid end line number: \"%s\".", option_arg); 886 break; 887 } 888 m_sym_ctx_specified = true; 889 break; 890 891 case 'l': 892 m_line_start = Args::StringToUInt32 (option_arg, 0, 0, &success); 893 if (!success) 894 { 895 error.SetErrorStringWithFormat ("Invalid start line number: \"%s\".", option_arg); 896 break; 897 } 898 m_sym_ctx_specified = true; 899 break; 900 901 case 'n': 902 m_function_name = option_arg; 903 m_func_name_type_mask |= eFunctionNameTypeAuto; 904 m_sym_ctx_specified = true; 905 break; 906 907 case 'f': 908 m_file_name = option_arg; 909 m_sym_ctx_specified = true; 910 break; 911 case 's': 912 m_module_name = option_arg; 913 m_sym_ctx_specified = true; 914 break; 915 case 't' : 916 { 917 m_thread_id = Args::StringToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0); 918 if (m_thread_id == LLDB_INVALID_THREAD_ID) 919 error.SetErrorStringWithFormat ("Invalid thread id string '%s'.\n", option_arg); 920 m_thread_specified = true; 921 } 922 break; 923 case 'T': 924 m_thread_name = option_arg; 925 m_thread_specified = true; 926 break; 927 case 'q': 928 m_queue_name = option_arg; 929 m_thread_specified = true; 930 break; 931 case 'x': 932 { 933 m_thread_index = Args::StringToUInt32(option_arg, UINT32_MAX, 0); 934 if (m_thread_id == UINT32_MAX) 935 error.SetErrorStringWithFormat ("Invalid thread index string '%s'.\n", option_arg); 936 m_thread_specified = true; 937 } 938 break; 939 default: 940 error.SetErrorStringWithFormat ("Unrecognized option %c."); 941 break; 942 } 943 return error; 944 } 945 946 void 947 OptionParsingStarting () 948 { 949 m_class_name.clear(); 950 m_function_name.clear(); 951 m_line_start = 0; 952 m_line_end = UINT_MAX; 953 m_file_name.clear(); 954 m_module_name.clear(); 955 m_func_name_type_mask = eFunctionNameTypeAuto; 956 m_thread_id = LLDB_INVALID_THREAD_ID; 957 m_thread_index = UINT32_MAX; 958 m_thread_name.clear(); 959 m_queue_name.clear(); 960 961 m_sym_ctx_specified = false; 962 m_thread_specified = false; 963 } 964 965 966 static OptionDefinition g_option_table[]; 967 968 std::string m_class_name; 969 std::string m_function_name; 970 uint32_t m_line_start; 971 uint32_t m_line_end; 972 std::string m_file_name; 973 std::string m_module_name; 974 uint32_t m_func_name_type_mask; // A pick from lldb::FunctionNameType. 975 lldb::tid_t m_thread_id; 976 uint32_t m_thread_index; 977 std::string m_thread_name; 978 std::string m_queue_name; 979 bool m_sym_ctx_specified; 980 bool m_thread_specified; 981 982 }; 983 984 Options * 985 GetOptions () 986 { 987 return &m_options; 988 } 989 990 CommandObjectTargetStopHookAdd (CommandInterpreter &interpreter) : 991 CommandObject (interpreter, 992 "target stop-hook add ", 993 "Add a hook to be executed when the target stops.", 994 "target stop-hook add"), 995 m_options (interpreter) 996 { 997 } 998 999 ~CommandObjectTargetStopHookAdd () 1000 { 1001 } 1002 1003 static size_t 1004 ReadCommandsCallbackFunction (void *baton, 1005 InputReader &reader, 1006 lldb::InputReaderAction notification, 1007 const char *bytes, 1008 size_t bytes_len) 1009 { 1010 File &out_file = reader.GetDebugger().GetOutputFile(); 1011 Target::StopHook *new_stop_hook = ((Target::StopHook *) baton); 1012 1013 switch (notification) 1014 { 1015 case eInputReaderActivate: 1016 out_file.Printf ("%s\n", "Enter your stop hook command(s). Type 'DONE' to end."); 1017 if (reader.GetPrompt()) 1018 out_file.Printf ("%s", reader.GetPrompt()); 1019 out_file.Flush(); 1020 break; 1021 1022 case eInputReaderDeactivate: 1023 break; 1024 1025 case eInputReaderReactivate: 1026 if (reader.GetPrompt()) 1027 { 1028 out_file.Printf ("%s", reader.GetPrompt()); 1029 out_file.Flush(); 1030 } 1031 break; 1032 1033 case eInputReaderGotToken: 1034 if (bytes && bytes_len && baton) 1035 { 1036 StringList *commands = new_stop_hook->GetCommandPointer(); 1037 if (commands) 1038 { 1039 commands->AppendString (bytes, bytes_len); 1040 } 1041 } 1042 if (!reader.IsDone() && reader.GetPrompt()) 1043 { 1044 out_file.Printf ("%s", reader.GetPrompt()); 1045 out_file.Flush(); 1046 } 1047 break; 1048 1049 case eInputReaderInterrupt: 1050 { 1051 // Finish, and cancel the stop hook. 1052 new_stop_hook->GetTarget()->RemoveStopHookByID(new_stop_hook->GetID()); 1053 out_file.Printf ("Stop hook cancelled.\n"); 1054 1055 reader.SetIsDone (true); 1056 } 1057 break; 1058 1059 case eInputReaderEndOfFile: 1060 reader.SetIsDone (true); 1061 break; 1062 1063 case eInputReaderDone: 1064 out_file.Printf ("Stop hook #%d added.\n", new_stop_hook->GetID()); 1065 break; 1066 } 1067 1068 return bytes_len; 1069 } 1070 1071 bool 1072 Execute (Args& command, 1073 CommandReturnObject &result) 1074 { 1075 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 1076 if (target) 1077 { 1078 Target::StopHookSP new_hook_sp; 1079 target->AddStopHook (new_hook_sp); 1080 1081 // First step, make the specifier. 1082 std::auto_ptr<SymbolContextSpecifier> specifier_ap; 1083 if (m_options.m_sym_ctx_specified) 1084 { 1085 specifier_ap.reset(new SymbolContextSpecifier(m_interpreter.GetDebugger().GetSelectedTarget())); 1086 1087 if (!m_options.m_module_name.empty()) 1088 { 1089 specifier_ap->AddSpecification (m_options.m_module_name.c_str(), SymbolContextSpecifier::eModuleSpecified); 1090 } 1091 1092 if (!m_options.m_class_name.empty()) 1093 { 1094 specifier_ap->AddSpecification (m_options.m_class_name.c_str(), SymbolContextSpecifier::eClassOrNamespaceSpecified); 1095 } 1096 1097 if (!m_options.m_file_name.empty()) 1098 { 1099 specifier_ap->AddSpecification (m_options.m_file_name.c_str(), SymbolContextSpecifier::eFileSpecified); 1100 } 1101 1102 if (m_options.m_line_start != 0) 1103 { 1104 specifier_ap->AddLineSpecification (m_options.m_line_start, SymbolContextSpecifier::eLineStartSpecified); 1105 } 1106 1107 if (m_options.m_line_end != UINT_MAX) 1108 { 1109 specifier_ap->AddLineSpecification (m_options.m_line_end, SymbolContextSpecifier::eLineEndSpecified); 1110 } 1111 1112 if (!m_options.m_function_name.empty()) 1113 { 1114 specifier_ap->AddSpecification (m_options.m_function_name.c_str(), SymbolContextSpecifier::eFunctionSpecified); 1115 } 1116 } 1117 1118 if (specifier_ap.get()) 1119 new_hook_sp->SetSpecifier (specifier_ap.release()); 1120 1121 // Next see if any of the thread options have been entered: 1122 1123 if (m_options.m_thread_specified) 1124 { 1125 ThreadSpec *thread_spec = new ThreadSpec(); 1126 1127 if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID) 1128 { 1129 thread_spec->SetTID (m_options.m_thread_id); 1130 } 1131 1132 if (m_options.m_thread_index != UINT32_MAX) 1133 thread_spec->SetIndex (m_options.m_thread_index); 1134 1135 if (!m_options.m_thread_name.empty()) 1136 thread_spec->SetName (m_options.m_thread_name.c_str()); 1137 1138 if (!m_options.m_queue_name.empty()) 1139 thread_spec->SetQueueName (m_options.m_queue_name.c_str()); 1140 1141 new_hook_sp->SetThreadSpecifier (thread_spec); 1142 1143 } 1144 // Next gather up the command list, we'll push an input reader and suck the data from that directly into 1145 // the new stop hook's command string. 1146 1147 InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger())); 1148 if (!reader_sp) 1149 { 1150 result.AppendError("out of memory\n"); 1151 result.SetStatus (eReturnStatusFailed); 1152 target->RemoveStopHookByID (new_hook_sp->GetID()); 1153 return false; 1154 } 1155 1156 Error err (reader_sp->Initialize (CommandObjectTargetStopHookAdd::ReadCommandsCallbackFunction, 1157 new_hook_sp.get(), // baton 1158 eInputReaderGranularityLine, // token size, to pass to callback function 1159 "DONE", // end token 1160 "> ", // prompt 1161 true)); // echo input 1162 if (!err.Success()) 1163 { 1164 result.AppendError (err.AsCString()); 1165 result.SetStatus (eReturnStatusFailed); 1166 target->RemoveStopHookByID (new_hook_sp->GetID()); 1167 return false; 1168 } 1169 m_interpreter.GetDebugger().PushInputReader (reader_sp); 1170 1171 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1172 } 1173 else 1174 { 1175 result.AppendError ("invalid target\n"); 1176 result.SetStatus (eReturnStatusFailed); 1177 } 1178 1179 return result.Succeeded(); 1180 } 1181 private: 1182 CommandOptions m_options; 1183 }; 1184 1185 OptionDefinition 1186 CommandObjectTargetStopHookAdd::CommandOptions::g_option_table[] = 1187 { 1188 { LLDB_OPT_SET_ALL, false, "shlib", 's', required_argument, NULL, CommandCompletions::eModuleCompletion, eArgTypeShlibName, 1189 "Set the module within which the stop-hook is to be run."}, 1190 { LLDB_OPT_SET_ALL, false, "thread-index", 'x', required_argument, NULL, NULL, eArgTypeThreadIndex, 1191 "The stop hook is run only for the thread whose index matches this argument."}, 1192 { LLDB_OPT_SET_ALL, false, "thread-id", 't', required_argument, NULL, NULL, eArgTypeThreadID, 1193 "The stop hook is run only for the thread whose TID matches this argument."}, 1194 { LLDB_OPT_SET_ALL, false, "thread-name", 'T', required_argument, NULL, NULL, eArgTypeThreadName, 1195 "The stop hook is run only for the thread whose thread name matches this argument."}, 1196 { LLDB_OPT_SET_ALL, false, "queue-name", 'q', required_argument, NULL, NULL, eArgTypeQueueName, 1197 "The stop hook is run only for threads in the queue whose name is given by this argument."}, 1198 { LLDB_OPT_SET_1, false, "file", 'f', required_argument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, 1199 "Specify the source file within which the stop-hook is to be run." }, 1200 { LLDB_OPT_SET_1, false, "start-line", 'l', required_argument, NULL, 0, eArgTypeLineNum, 1201 "Set the start of the line range for which the stop-hook is to be run."}, 1202 { LLDB_OPT_SET_1, false, "end-line", 'e', required_argument, NULL, 0, eArgTypeLineNum, 1203 "Set the end of the line range for which the stop-hook is to be run."}, 1204 { LLDB_OPT_SET_2, false, "classname", 'c', required_argument, NULL, NULL, eArgTypeClassName, 1205 "Specify the class within which the stop-hook is to be run." }, 1206 { LLDB_OPT_SET_3, false, "name", 'n', required_argument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, 1207 "Set the function name within which the stop hook will be run." }, 1208 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 1209 }; 1210 1211 #pragma mark CommandObjectTargetStopHookDelete 1212 1213 //------------------------------------------------------------------------- 1214 // CommandObjectTargetStopHookDelete 1215 //------------------------------------------------------------------------- 1216 1217 class CommandObjectTargetStopHookDelete : public CommandObject 1218 { 1219 public: 1220 1221 CommandObjectTargetStopHookDelete (CommandInterpreter &interpreter) : 1222 CommandObject (interpreter, 1223 "target stop-hook delete [<id>]", 1224 "Delete a stop-hook.", 1225 "target stop-hook delete") 1226 { 1227 } 1228 1229 ~CommandObjectTargetStopHookDelete () 1230 { 1231 } 1232 1233 bool 1234 Execute (Args& command, 1235 CommandReturnObject &result) 1236 { 1237 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 1238 if (target) 1239 { 1240 // FIXME: see if we can use the breakpoint id style parser? 1241 size_t num_args = command.GetArgumentCount(); 1242 if (num_args == 0) 1243 { 1244 if (!m_interpreter.Confirm ("Delete all stop hooks?", true)) 1245 { 1246 result.SetStatus (eReturnStatusFailed); 1247 return false; 1248 } 1249 else 1250 { 1251 target->RemoveAllStopHooks(); 1252 } 1253 } 1254 else 1255 { 1256 bool success; 1257 for (size_t i = 0; i < num_args; i++) 1258 { 1259 lldb::user_id_t user_id = Args::StringToUInt32 (command.GetArgumentAtIndex(i), 0, 0, &success); 1260 if (!success) 1261 { 1262 result.AppendErrorWithFormat ("invalid stop hook id: \"%s\".\n", command.GetArgumentAtIndex(i)); 1263 result.SetStatus(eReturnStatusFailed); 1264 return false; 1265 } 1266 success = target->RemoveStopHookByID (user_id); 1267 if (!success) 1268 { 1269 result.AppendErrorWithFormat ("unknown stop hook id: \"%s\".\n", command.GetArgumentAtIndex(i)); 1270 result.SetStatus(eReturnStatusFailed); 1271 return false; 1272 } 1273 } 1274 } 1275 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1276 } 1277 else 1278 { 1279 result.AppendError ("invalid target\n"); 1280 result.SetStatus (eReturnStatusFailed); 1281 } 1282 1283 return result.Succeeded(); 1284 } 1285 }; 1286 #pragma mark CommandObjectTargetStopHookEnableDisable 1287 1288 //------------------------------------------------------------------------- 1289 // CommandObjectTargetStopHookEnableDisable 1290 //------------------------------------------------------------------------- 1291 1292 class CommandObjectTargetStopHookEnableDisable : public CommandObject 1293 { 1294 public: 1295 1296 CommandObjectTargetStopHookEnableDisable (CommandInterpreter &interpreter, bool enable, const char *name, const char *help, const char *syntax) : 1297 CommandObject (interpreter, 1298 name, 1299 help, 1300 syntax), 1301 m_enable (enable) 1302 { 1303 } 1304 1305 ~CommandObjectTargetStopHookEnableDisable () 1306 { 1307 } 1308 1309 bool 1310 Execute (Args& command, 1311 CommandReturnObject &result) 1312 { 1313 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 1314 if (target) 1315 { 1316 // FIXME: see if we can use the breakpoint id style parser? 1317 size_t num_args = command.GetArgumentCount(); 1318 bool success; 1319 1320 if (num_args == 0) 1321 { 1322 target->SetAllStopHooksActiveState (m_enable); 1323 } 1324 else 1325 { 1326 for (size_t i = 0; i < num_args; i++) 1327 { 1328 lldb::user_id_t user_id = Args::StringToUInt32 (command.GetArgumentAtIndex(i), 0, 0, &success); 1329 if (!success) 1330 { 1331 result.AppendErrorWithFormat ("invalid stop hook id: \"%s\".\n", command.GetArgumentAtIndex(i)); 1332 result.SetStatus(eReturnStatusFailed); 1333 return false; 1334 } 1335 success = target->SetStopHookActiveStateByID (user_id, m_enable); 1336 if (!success) 1337 { 1338 result.AppendErrorWithFormat ("unknown stop hook id: \"%s\".\n", command.GetArgumentAtIndex(i)); 1339 result.SetStatus(eReturnStatusFailed); 1340 return false; 1341 } 1342 } 1343 } 1344 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1345 } 1346 else 1347 { 1348 result.AppendError ("invalid target\n"); 1349 result.SetStatus (eReturnStatusFailed); 1350 } 1351 return result.Succeeded(); 1352 } 1353 private: 1354 bool m_enable; 1355 }; 1356 1357 #pragma mark CommandObjectTargetStopHookList 1358 1359 //------------------------------------------------------------------------- 1360 // CommandObjectTargetStopHookList 1361 //------------------------------------------------------------------------- 1362 1363 class CommandObjectTargetStopHookList : public CommandObject 1364 { 1365 public: 1366 1367 CommandObjectTargetStopHookList (CommandInterpreter &interpreter) : 1368 CommandObject (interpreter, 1369 "target stop-hook list [<type>]", 1370 "List all stop-hooks.", 1371 "target stop-hook list") 1372 { 1373 } 1374 1375 ~CommandObjectTargetStopHookList () 1376 { 1377 } 1378 1379 bool 1380 Execute (Args& command, 1381 CommandReturnObject &result) 1382 { 1383 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 1384 if (target) 1385 { 1386 bool notify = true; 1387 target->GetImageSearchPathList().Clear(notify); 1388 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1389 } 1390 else 1391 { 1392 result.AppendError ("invalid target\n"); 1393 result.SetStatus (eReturnStatusFailed); 1394 } 1395 1396 size_t num_hooks = target->GetNumStopHooks (); 1397 if (num_hooks == 0) 1398 { 1399 result.GetOutputStream().PutCString ("No stop hooks.\n"); 1400 } 1401 else 1402 { 1403 for (size_t i = 0; i < num_hooks; i++) 1404 { 1405 Target::StopHookSP this_hook = target->GetStopHookAtIndex (i); 1406 if (i > 0) 1407 result.GetOutputStream().PutCString ("\n"); 1408 this_hook->GetDescription (&(result.GetOutputStream()), eDescriptionLevelFull); 1409 } 1410 } 1411 return result.Succeeded(); 1412 } 1413 }; 1414 1415 #pragma mark CommandObjectMultiwordTargetStopHooks 1416 //------------------------------------------------------------------------- 1417 // CommandObjectMultiwordTargetStopHooks 1418 //------------------------------------------------------------------------- 1419 1420 class CommandObjectMultiwordTargetStopHooks : public CommandObjectMultiword 1421 { 1422 public: 1423 1424 CommandObjectMultiwordTargetStopHooks (CommandInterpreter &interpreter) : 1425 CommandObjectMultiword (interpreter, 1426 "target stop-hook", 1427 "A set of commands for operating on debugger target stop-hooks.", 1428 "target stop-hook <subcommand> [<subcommand-options>]") 1429 { 1430 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTargetStopHookAdd (interpreter))); 1431 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTargetStopHookDelete (interpreter))); 1432 LoadSubCommand ("disable", CommandObjectSP (new CommandObjectTargetStopHookEnableDisable (interpreter, 1433 false, 1434 "target stop-hook disable [<id>]", 1435 "Disable a stop-hook.", 1436 "target stop-hook disable"))); 1437 LoadSubCommand ("enable", CommandObjectSP (new CommandObjectTargetStopHookEnableDisable (interpreter, 1438 true, 1439 "target stop-hook enable [<id>]", 1440 "Enable a stop-hook.", 1441 "target stop-hook enable"))); 1442 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTargetStopHookList (interpreter))); 1443 } 1444 1445 ~CommandObjectMultiwordTargetStopHooks() 1446 { 1447 } 1448 }; 1449 1450 1451 1452 #pragma mark CommandObjectMultiwordTarget 1453 1454 //------------------------------------------------------------------------- 1455 // CommandObjectMultiwordTarget 1456 //------------------------------------------------------------------------- 1457 1458 CommandObjectMultiwordTarget::CommandObjectMultiwordTarget (CommandInterpreter &interpreter) : 1459 CommandObjectMultiword (interpreter, 1460 "target", 1461 "A set of commands for operating on debugger targets.", 1462 "target <subcommand> [<subcommand-options>]") 1463 { 1464 1465 LoadSubCommand ("create", CommandObjectSP (new CommandObjectTargetCreate (interpreter))); 1466 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTargetList (interpreter))); 1467 LoadSubCommand ("select", CommandObjectSP (new CommandObjectTargetSelect (interpreter))); 1468 LoadSubCommand ("stop-hook", CommandObjectSP (new CommandObjectMultiwordTargetStopHooks (interpreter))); 1469 LoadSubCommand ("image-search-paths", CommandObjectSP (new CommandObjectMultiwordImageSearchPaths (interpreter))); 1470 } 1471 1472 CommandObjectMultiwordTarget::~CommandObjectMultiwordTarget () 1473 { 1474 } 1475 1476 1477