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/Section.h" 22 #include "lldb/Core/State.h" 23 #include "lldb/Core/Timer.h" 24 #include "lldb/Interpreter/CommandInterpreter.h" 25 #include "lldb/Interpreter/CommandReturnObject.h" 26 #include "lldb/Interpreter/Options.h" 27 #include "lldb/Interpreter/OptionGroupArchitecture.h" 28 #include "lldb/Interpreter/OptionGroupFile.h" 29 #include "lldb/Interpreter/OptionGroupPlatform.h" 30 #include "lldb/Interpreter/OptionGroupUInt64.h" 31 #include "lldb/Interpreter/OptionGroupUUID.h" 32 #include "lldb/Symbol/LineTable.h" 33 #include "lldb/Symbol/ObjectFile.h" 34 #include "lldb/Symbol/SymbolFile.h" 35 #include "lldb/Symbol/SymbolVendor.h" 36 #include "lldb/Target/Process.h" 37 #include "lldb/Target/StackFrame.h" 38 #include "lldb/Target/Thread.h" 39 #include "lldb/Target/ThreadSpec.h" 40 41 using namespace lldb; 42 using namespace lldb_private; 43 44 45 46 static void 47 DumpTargetInfo (uint32_t target_idx, Target *target, const char *prefix_cstr, bool show_stopped_process_status, Stream &strm) 48 { 49 const ArchSpec &target_arch = target->GetArchitecture(); 50 51 ModuleSP exe_module_sp (target->GetExecutableModule ()); 52 char exe_path[PATH_MAX]; 53 bool exe_valid = false; 54 if (exe_module_sp) 55 exe_valid = exe_module_sp->GetFileSpec().GetPath (exe_path, sizeof(exe_path)); 56 57 if (!exe_valid) 58 ::strcpy (exe_path, "<none>"); 59 60 strm.Printf ("%starget #%u: %s", prefix_cstr ? prefix_cstr : "", target_idx, exe_path); 61 62 uint32_t properties = 0; 63 if (target_arch.IsValid()) 64 { 65 strm.Printf ("%sarch=%s", properties++ > 0 ? ", " : " ( ", target_arch.GetTriple().str().c_str()); 66 properties++; 67 } 68 PlatformSP platform_sp (target->GetPlatform()); 69 if (platform_sp) 70 strm.Printf ("%splatform=%s", properties++ > 0 ? ", " : " ( ", platform_sp->GetName()); 71 72 ProcessSP process_sp (target->GetProcessSP()); 73 bool show_process_status = false; 74 if (process_sp) 75 { 76 lldb::pid_t pid = process_sp->GetID(); 77 StateType state = process_sp->GetState(); 78 if (show_stopped_process_status) 79 show_process_status = StateIsStoppedState(state); 80 const char *state_cstr = StateAsCString (state); 81 if (pid != LLDB_INVALID_PROCESS_ID) 82 strm.Printf ("%spid=%i", properties++ > 0 ? ", " : " ( ", pid); 83 strm.Printf ("%sstate=%s", properties++ > 0 ? ", " : " ( ", state_cstr); 84 } 85 if (properties > 0) 86 strm.PutCString (" )\n"); 87 else 88 strm.EOL(); 89 if (show_process_status) 90 { 91 const bool only_threads_with_stop_reason = true; 92 const uint32_t start_frame = 0; 93 const uint32_t num_frames = 1; 94 const uint32_t num_frames_with_source = 1; 95 process_sp->GetStatus (strm); 96 process_sp->GetThreadStatus (strm, 97 only_threads_with_stop_reason, 98 start_frame, 99 num_frames, 100 num_frames_with_source); 101 102 } 103 } 104 105 static uint32_t 106 DumpTargetList (TargetList &target_list, bool show_stopped_process_status, Stream &strm) 107 { 108 const uint32_t num_targets = target_list.GetNumTargets(); 109 if (num_targets) 110 { 111 TargetSP selected_target_sp (target_list.GetSelectedTarget()); 112 strm.PutCString ("Current targets:\n"); 113 for (uint32_t i=0; i<num_targets; ++i) 114 { 115 TargetSP target_sp (target_list.GetTargetAtIndex (i)); 116 if (target_sp) 117 { 118 bool is_selected = target_sp.get() == selected_target_sp.get(); 119 DumpTargetInfo (i, 120 target_sp.get(), 121 is_selected ? "* " : " ", 122 show_stopped_process_status, 123 strm); 124 } 125 } 126 } 127 return num_targets; 128 } 129 #pragma mark CommandObjectTargetCreate 130 131 //------------------------------------------------------------------------- 132 // "target create" 133 //------------------------------------------------------------------------- 134 135 class CommandObjectTargetCreate : public CommandObject 136 { 137 public: 138 CommandObjectTargetCreate(CommandInterpreter &interpreter) : 139 CommandObject (interpreter, 140 "target create", 141 "Create a target using the argument as the main executable.", 142 NULL), 143 m_option_group (interpreter), 144 m_file_options (), 145 m_platform_options(true) // Do include the "--platform" option in the platform settings by passing true 146 { 147 CommandArgumentEntry arg; 148 CommandArgumentData file_arg; 149 150 // Define the first (and only) variant of this arg. 151 file_arg.arg_type = eArgTypeFilename; 152 file_arg.arg_repetition = eArgRepeatPlain; 153 154 // There is only one variant this argument could be; put it into the argument entry. 155 arg.push_back (file_arg); 156 157 // Push the data for the first argument into the m_arguments vector. 158 m_arguments.push_back (arg); 159 160 m_option_group.Append (&m_file_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 161 m_option_group.Append (&m_platform_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 162 m_option_group.Finalize(); 163 } 164 165 ~CommandObjectTargetCreate () 166 { 167 } 168 169 Options * 170 GetOptions () 171 { 172 return &m_option_group; 173 } 174 175 bool 176 Execute (Args& command, CommandReturnObject &result) 177 { 178 const int argc = command.GetArgumentCount(); 179 if (argc == 1) 180 { 181 const char *file_path = command.GetArgumentAtIndex(0); 182 Timer scoped_timer(__PRETTY_FUNCTION__, "(lldb) target create '%s'", file_path); 183 FileSpec file_spec (file_path, true); 184 185 bool select = true; 186 PlatformSP platform_sp; 187 188 Error error; 189 190 if (m_platform_options.PlatformWasSpecified ()) 191 { 192 platform_sp = m_platform_options.CreatePlatformWithOptions(m_interpreter, select, error); 193 if (!platform_sp) 194 { 195 result.AppendError(error.AsCString()); 196 result.SetStatus (eReturnStatusFailed); 197 return false; 198 } 199 } 200 ArchSpec file_arch; 201 202 const char *arch_cstr = m_file_options.GetArchitectureName(); 203 if (arch_cstr) 204 { 205 if (!platform_sp) 206 platform_sp = m_interpreter.GetDebugger().GetPlatformList().GetSelectedPlatform(); 207 if (!m_file_options.GetArchitecture(platform_sp.get(), file_arch)) 208 { 209 result.AppendErrorWithFormat("invalid architecture '%s'\n", arch_cstr); 210 result.SetStatus (eReturnStatusFailed); 211 return false; 212 } 213 } 214 215 if (! file_spec.Exists() && !file_spec.ResolveExecutableLocation()) 216 { 217 result.AppendErrorWithFormat ("File '%s' does not exist.\n", file_path); 218 result.SetStatus (eReturnStatusFailed); 219 return false; 220 } 221 222 TargetSP target_sp; 223 Debugger &debugger = m_interpreter.GetDebugger(); 224 error = debugger.GetTargetList().CreateTarget (debugger, file_spec, file_arch, true, target_sp); 225 226 if (target_sp) 227 { 228 debugger.GetTargetList().SetSelectedTarget(target_sp.get()); 229 result.AppendMessageWithFormat ("Current executable set to '%s' (%s).\n", file_path, target_sp->GetArchitecture().GetArchitectureName()); 230 result.SetStatus (eReturnStatusSuccessFinishNoResult); 231 } 232 else 233 { 234 result.AppendError(error.AsCString()); 235 result.SetStatus (eReturnStatusFailed); 236 } 237 } 238 else 239 { 240 result.AppendErrorWithFormat("'%s' takes exactly one executable path argument.\n", m_cmd_name.c_str()); 241 result.SetStatus (eReturnStatusFailed); 242 } 243 return result.Succeeded(); 244 245 } 246 247 int 248 HandleArgumentCompletion (Args &input, 249 int &cursor_index, 250 int &cursor_char_position, 251 OptionElementVector &opt_element_vector, 252 int match_start_point, 253 int max_return_elements, 254 bool &word_complete, 255 StringList &matches) 256 { 257 std::string completion_str (input.GetArgumentAtIndex(cursor_index)); 258 completion_str.erase (cursor_char_position); 259 260 CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter, 261 CommandCompletions::eDiskFileCompletion, 262 completion_str.c_str(), 263 match_start_point, 264 max_return_elements, 265 NULL, 266 word_complete, 267 matches); 268 return matches.GetSize(); 269 } 270 private: 271 OptionGroupOptions m_option_group; 272 OptionGroupArchitecture m_file_options; 273 OptionGroupPlatform m_platform_options; 274 275 }; 276 277 #pragma mark CommandObjectTargetList 278 279 //---------------------------------------------------------------------- 280 // "target list" 281 //---------------------------------------------------------------------- 282 283 class CommandObjectTargetList : public CommandObject 284 { 285 public: 286 CommandObjectTargetList (CommandInterpreter &interpreter) : 287 CommandObject (interpreter, 288 "target list", 289 "List all current targets in the current debug session.", 290 NULL, 291 0) 292 { 293 } 294 295 virtual 296 ~CommandObjectTargetList () 297 { 298 } 299 300 virtual bool 301 Execute (Args& args, CommandReturnObject &result) 302 { 303 if (args.GetArgumentCount() == 0) 304 { 305 Stream &strm = result.GetOutputStream(); 306 307 bool show_stopped_process_status = false; 308 if (DumpTargetList (m_interpreter.GetDebugger().GetTargetList(), show_stopped_process_status, strm) == 0) 309 { 310 strm.PutCString ("No targets.\n"); 311 } 312 result.SetStatus (eReturnStatusSuccessFinishResult); 313 } 314 else 315 { 316 result.AppendError ("the 'target list' command takes no arguments\n"); 317 result.SetStatus (eReturnStatusFailed); 318 } 319 return result.Succeeded(); 320 } 321 }; 322 323 324 #pragma mark CommandObjectTargetSelect 325 326 //---------------------------------------------------------------------- 327 // "target select" 328 //---------------------------------------------------------------------- 329 330 class CommandObjectTargetSelect : public CommandObject 331 { 332 public: 333 CommandObjectTargetSelect (CommandInterpreter &interpreter) : 334 CommandObject (interpreter, 335 "target select", 336 "Select a target as the current target by target index.", 337 NULL, 338 0) 339 { 340 } 341 342 virtual 343 ~CommandObjectTargetSelect () 344 { 345 } 346 347 virtual bool 348 Execute (Args& args, CommandReturnObject &result) 349 { 350 if (args.GetArgumentCount() == 1) 351 { 352 bool success = false; 353 const char *target_idx_arg = args.GetArgumentAtIndex(0); 354 uint32_t target_idx = Args::StringToUInt32 (target_idx_arg, UINT32_MAX, 0, &success); 355 if (success) 356 { 357 TargetList &target_list = m_interpreter.GetDebugger().GetTargetList(); 358 const uint32_t num_targets = target_list.GetNumTargets(); 359 if (target_idx < num_targets) 360 { 361 TargetSP target_sp (target_list.GetTargetAtIndex (target_idx)); 362 if (target_sp) 363 { 364 Stream &strm = result.GetOutputStream(); 365 target_list.SetSelectedTarget (target_sp.get()); 366 bool show_stopped_process_status = false; 367 DumpTargetList (target_list, show_stopped_process_status, strm); 368 result.SetStatus (eReturnStatusSuccessFinishResult); 369 } 370 else 371 { 372 result.AppendErrorWithFormat ("target #%u is NULL in target list\n", target_idx); 373 result.SetStatus (eReturnStatusFailed); 374 } 375 } 376 else 377 { 378 result.AppendErrorWithFormat ("index %u is out of range, valid target indexes are 0 - %u\n", 379 target_idx, 380 num_targets - 1); 381 result.SetStatus (eReturnStatusFailed); 382 } 383 } 384 else 385 { 386 result.AppendErrorWithFormat("invalid index string value '%s'\n", target_idx_arg); 387 result.SetStatus (eReturnStatusFailed); 388 } 389 } 390 else 391 { 392 result.AppendError ("'target select' takes a single argument: a target index\n"); 393 result.SetStatus (eReturnStatusFailed); 394 } 395 return result.Succeeded(); 396 } 397 }; 398 399 400 #pragma mark CommandObjectTargetModulesSearchPathsAdd 401 402 class CommandObjectTargetModulesSearchPathsAdd : public CommandObject 403 { 404 public: 405 406 CommandObjectTargetModulesSearchPathsAdd (CommandInterpreter &interpreter) : 407 CommandObject (interpreter, 408 "target modules search-paths add", 409 "Add new image search paths substitution pairs to the current target.", 410 NULL) 411 { 412 CommandArgumentEntry arg; 413 CommandArgumentData old_prefix_arg; 414 CommandArgumentData new_prefix_arg; 415 416 // Define the first variant of this arg pair. 417 old_prefix_arg.arg_type = eArgTypeOldPathPrefix; 418 old_prefix_arg.arg_repetition = eArgRepeatPairPlus; 419 420 // Define the first variant of this arg pair. 421 new_prefix_arg.arg_type = eArgTypeNewPathPrefix; 422 new_prefix_arg.arg_repetition = eArgRepeatPairPlus; 423 424 // There are two required arguments that must always occur together, i.e. an argument "pair". Because they 425 // must always occur together, they are treated as two variants of one argument rather than two independent 426 // arguments. Push them both into the first argument position for m_arguments... 427 428 arg.push_back (old_prefix_arg); 429 arg.push_back (new_prefix_arg); 430 431 m_arguments.push_back (arg); 432 } 433 434 ~CommandObjectTargetModulesSearchPathsAdd () 435 { 436 } 437 438 bool 439 Execute (Args& command, 440 CommandReturnObject &result) 441 { 442 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 443 if (target) 444 { 445 uint32_t argc = command.GetArgumentCount(); 446 if (argc & 1) 447 { 448 result.AppendError ("add requires an even number of arguments\n"); 449 result.SetStatus (eReturnStatusFailed); 450 } 451 else 452 { 453 for (uint32_t i=0; i<argc; i+=2) 454 { 455 const char *from = command.GetArgumentAtIndex(i); 456 const char *to = command.GetArgumentAtIndex(i+1); 457 458 if (from[0] && to[0]) 459 { 460 bool last_pair = ((argc - i) == 2); 461 target->GetImageSearchPathList().Append (ConstString(from), 462 ConstString(to), 463 last_pair); // Notify if this is the last pair 464 result.SetStatus (eReturnStatusSuccessFinishNoResult); 465 } 466 else 467 { 468 if (from[0]) 469 result.AppendError ("<path-prefix> can't be empty\n"); 470 else 471 result.AppendError ("<new-path-prefix> can't be empty\n"); 472 result.SetStatus (eReturnStatusFailed); 473 } 474 } 475 } 476 } 477 else 478 { 479 result.AppendError ("invalid target\n"); 480 result.SetStatus (eReturnStatusFailed); 481 } 482 return result.Succeeded(); 483 } 484 }; 485 486 #pragma mark CommandObjectTargetModulesSearchPathsClear 487 488 class CommandObjectTargetModulesSearchPathsClear : public CommandObject 489 { 490 public: 491 492 CommandObjectTargetModulesSearchPathsClear (CommandInterpreter &interpreter) : 493 CommandObject (interpreter, 494 "target modules search-paths clear", 495 "Clear all current image search path substitution pairs from the current target.", 496 "target modules search-paths clear") 497 { 498 } 499 500 ~CommandObjectTargetModulesSearchPathsClear () 501 { 502 } 503 504 bool 505 Execute (Args& command, 506 CommandReturnObject &result) 507 { 508 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 509 if (target) 510 { 511 bool notify = true; 512 target->GetImageSearchPathList().Clear(notify); 513 result.SetStatus (eReturnStatusSuccessFinishNoResult); 514 } 515 else 516 { 517 result.AppendError ("invalid target\n"); 518 result.SetStatus (eReturnStatusFailed); 519 } 520 return result.Succeeded(); 521 } 522 }; 523 524 #pragma mark CommandObjectTargetModulesSearchPathsInsert 525 526 class CommandObjectTargetModulesSearchPathsInsert : public CommandObject 527 { 528 public: 529 530 CommandObjectTargetModulesSearchPathsInsert (CommandInterpreter &interpreter) : 531 CommandObject (interpreter, 532 "target modules search-paths insert", 533 "Insert a new image search path substitution pair into the current target at the specified index.", 534 NULL) 535 { 536 CommandArgumentEntry arg1; 537 CommandArgumentEntry arg2; 538 CommandArgumentData index_arg; 539 CommandArgumentData old_prefix_arg; 540 CommandArgumentData new_prefix_arg; 541 542 // Define the first and only variant of this arg. 543 index_arg.arg_type = eArgTypeIndex; 544 index_arg.arg_repetition = eArgRepeatPlain; 545 546 // Put the one and only variant into the first arg for m_arguments: 547 arg1.push_back (index_arg); 548 549 // Define the first variant of this arg pair. 550 old_prefix_arg.arg_type = eArgTypeOldPathPrefix; 551 old_prefix_arg.arg_repetition = eArgRepeatPairPlus; 552 553 // Define the first variant of this arg pair. 554 new_prefix_arg.arg_type = eArgTypeNewPathPrefix; 555 new_prefix_arg.arg_repetition = eArgRepeatPairPlus; 556 557 // There are two required arguments that must always occur together, i.e. an argument "pair". Because they 558 // must always occur together, they are treated as two variants of one argument rather than two independent 559 // arguments. Push them both into the same argument position for m_arguments... 560 561 arg2.push_back (old_prefix_arg); 562 arg2.push_back (new_prefix_arg); 563 564 // Add arguments to m_arguments. 565 m_arguments.push_back (arg1); 566 m_arguments.push_back (arg2); 567 } 568 569 ~CommandObjectTargetModulesSearchPathsInsert () 570 { 571 } 572 573 bool 574 Execute (Args& command, 575 CommandReturnObject &result) 576 { 577 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 578 if (target) 579 { 580 uint32_t argc = command.GetArgumentCount(); 581 // check for at least 3 arguments and an odd nubmer of parameters 582 if (argc >= 3 && argc & 1) 583 { 584 bool success = false; 585 586 uint32_t insert_idx = Args::StringToUInt32(command.GetArgumentAtIndex(0), UINT32_MAX, 0, &success); 587 588 if (!success) 589 { 590 result.AppendErrorWithFormat("<index> parameter is not an integer: '%s'.\n", command.GetArgumentAtIndex(0)); 591 result.SetStatus (eReturnStatusFailed); 592 return result.Succeeded(); 593 } 594 595 // shift off the index 596 command.Shift(); 597 argc = command.GetArgumentCount(); 598 599 for (uint32_t i=0; i<argc; i+=2, ++insert_idx) 600 { 601 const char *from = command.GetArgumentAtIndex(i); 602 const char *to = command.GetArgumentAtIndex(i+1); 603 604 if (from[0] && to[0]) 605 { 606 bool last_pair = ((argc - i) == 2); 607 target->GetImageSearchPathList().Insert (ConstString(from), 608 ConstString(to), 609 insert_idx, 610 last_pair); 611 result.SetStatus (eReturnStatusSuccessFinishNoResult); 612 } 613 else 614 { 615 if (from[0]) 616 result.AppendError ("<path-prefix> can't be empty\n"); 617 else 618 result.AppendError ("<new-path-prefix> can't be empty\n"); 619 result.SetStatus (eReturnStatusFailed); 620 return false; 621 } 622 } 623 } 624 else 625 { 626 result.AppendError ("insert requires at least three arguments\n"); 627 result.SetStatus (eReturnStatusFailed); 628 return result.Succeeded(); 629 } 630 631 } 632 else 633 { 634 result.AppendError ("invalid target\n"); 635 result.SetStatus (eReturnStatusFailed); 636 } 637 return result.Succeeded(); 638 } 639 }; 640 641 642 #pragma mark CommandObjectTargetModulesSearchPathsList 643 644 645 class CommandObjectTargetModulesSearchPathsList : public CommandObject 646 { 647 public: 648 649 CommandObjectTargetModulesSearchPathsList (CommandInterpreter &interpreter) : 650 CommandObject (interpreter, 651 "target modules search-paths list", 652 "List all current image search path substitution pairs in the current target.", 653 "target modules search-paths list") 654 { 655 } 656 657 ~CommandObjectTargetModulesSearchPathsList () 658 { 659 } 660 661 bool 662 Execute (Args& command, 663 CommandReturnObject &result) 664 { 665 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 666 if (target) 667 { 668 if (command.GetArgumentCount() != 0) 669 { 670 result.AppendError ("list takes no arguments\n"); 671 result.SetStatus (eReturnStatusFailed); 672 return result.Succeeded(); 673 } 674 675 target->GetImageSearchPathList().Dump(&result.GetOutputStream()); 676 result.SetStatus (eReturnStatusSuccessFinishResult); 677 } 678 else 679 { 680 result.AppendError ("invalid target\n"); 681 result.SetStatus (eReturnStatusFailed); 682 } 683 return result.Succeeded(); 684 } 685 }; 686 687 #pragma mark CommandObjectTargetModulesSearchPathsQuery 688 689 class CommandObjectTargetModulesSearchPathsQuery : public CommandObject 690 { 691 public: 692 693 CommandObjectTargetModulesSearchPathsQuery (CommandInterpreter &interpreter) : 694 CommandObject (interpreter, 695 "target modules search-paths query", 696 "Transform a path using the first applicable image search path.", 697 NULL) 698 { 699 CommandArgumentEntry arg; 700 CommandArgumentData path_arg; 701 702 // Define the first (and only) variant of this arg. 703 path_arg.arg_type = eArgTypePath; 704 path_arg.arg_repetition = eArgRepeatPlain; 705 706 // There is only one variant this argument could be; put it into the argument entry. 707 arg.push_back (path_arg); 708 709 // Push the data for the first argument into the m_arguments vector. 710 m_arguments.push_back (arg); 711 } 712 713 ~CommandObjectTargetModulesSearchPathsQuery () 714 { 715 } 716 717 bool 718 Execute (Args& command, 719 CommandReturnObject &result) 720 { 721 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 722 if (target) 723 { 724 if (command.GetArgumentCount() != 1) 725 { 726 result.AppendError ("query requires one argument\n"); 727 result.SetStatus (eReturnStatusFailed); 728 return result.Succeeded(); 729 } 730 731 ConstString orig(command.GetArgumentAtIndex(0)); 732 ConstString transformed; 733 if (target->GetImageSearchPathList().RemapPath(orig, transformed)) 734 result.GetOutputStream().Printf("%s\n", transformed.GetCString()); 735 else 736 result.GetOutputStream().Printf("%s\n", orig.GetCString()); 737 738 result.SetStatus (eReturnStatusSuccessFinishResult); 739 } 740 else 741 { 742 result.AppendError ("invalid target\n"); 743 result.SetStatus (eReturnStatusFailed); 744 } 745 return result.Succeeded(); 746 } 747 }; 748 749 //---------------------------------------------------------------------- 750 // Static Helper functions 751 //---------------------------------------------------------------------- 752 static void 753 DumpModuleArchitecture (Stream &strm, Module *module, bool full_triple, uint32_t width) 754 { 755 if (module) 756 { 757 const char *arch_cstr; 758 if (full_triple) 759 arch_cstr = module->GetArchitecture().GetTriple().str().c_str(); 760 else 761 arch_cstr = module->GetArchitecture().GetArchitectureName(); 762 if (width) 763 strm.Printf("%-*s", width, arch_cstr); 764 else 765 strm.PutCString(arch_cstr); 766 } 767 } 768 769 static void 770 DumpModuleUUID (Stream &strm, Module *module) 771 { 772 module->GetUUID().Dump (&strm); 773 } 774 775 static uint32_t 776 DumpCompileUnitLineTable 777 ( 778 CommandInterpreter &interpreter, 779 Stream &strm, 780 Module *module, 781 const FileSpec &file_spec, 782 bool load_addresses 783 ) 784 { 785 uint32_t num_matches = 0; 786 if (module) 787 { 788 SymbolContextList sc_list; 789 num_matches = module->ResolveSymbolContextsForFileSpec (file_spec, 790 0, 791 false, 792 eSymbolContextCompUnit, 793 sc_list); 794 795 for (uint32_t i=0; i<num_matches; ++i) 796 { 797 SymbolContext sc; 798 if (sc_list.GetContextAtIndex(i, sc)) 799 { 800 if (i > 0) 801 strm << "\n\n"; 802 803 strm << "Line table for " << *static_cast<FileSpec*> (sc.comp_unit) << " in `" 804 << module->GetFileSpec().GetFilename() << "\n"; 805 LineTable *line_table = sc.comp_unit->GetLineTable(); 806 if (line_table) 807 line_table->GetDescription (&strm, 808 interpreter.GetExecutionContext().target, 809 lldb::eDescriptionLevelBrief); 810 else 811 strm << "No line table"; 812 } 813 } 814 } 815 return num_matches; 816 } 817 818 static void 819 DumpFullpath (Stream &strm, const FileSpec *file_spec_ptr, uint32_t width) 820 { 821 if (file_spec_ptr) 822 { 823 if (width > 0) 824 { 825 char fullpath[PATH_MAX]; 826 if (file_spec_ptr->GetPath(fullpath, sizeof(fullpath))) 827 { 828 strm.Printf("%-*s", width, fullpath); 829 return; 830 } 831 } 832 else 833 { 834 file_spec_ptr->Dump(&strm); 835 return; 836 } 837 } 838 // Keep the width spacing correct if things go wrong... 839 if (width > 0) 840 strm.Printf("%-*s", width, ""); 841 } 842 843 static void 844 DumpDirectory (Stream &strm, const FileSpec *file_spec_ptr, uint32_t width) 845 { 846 if (file_spec_ptr) 847 { 848 if (width > 0) 849 strm.Printf("%-*s", width, file_spec_ptr->GetDirectory().AsCString("")); 850 else 851 file_spec_ptr->GetDirectory().Dump(&strm); 852 return; 853 } 854 // Keep the width spacing correct if things go wrong... 855 if (width > 0) 856 strm.Printf("%-*s", width, ""); 857 } 858 859 static void 860 DumpBasename (Stream &strm, const FileSpec *file_spec_ptr, uint32_t width) 861 { 862 if (file_spec_ptr) 863 { 864 if (width > 0) 865 strm.Printf("%-*s", width, file_spec_ptr->GetFilename().AsCString("")); 866 else 867 file_spec_ptr->GetFilename().Dump(&strm); 868 return; 869 } 870 // Keep the width spacing correct if things go wrong... 871 if (width > 0) 872 strm.Printf("%-*s", width, ""); 873 } 874 875 876 static void 877 DumpModuleSymtab (CommandInterpreter &interpreter, Stream &strm, Module *module, SortOrder sort_order) 878 { 879 if (module) 880 { 881 ObjectFile *objfile = module->GetObjectFile (); 882 if (objfile) 883 { 884 Symtab *symtab = objfile->GetSymtab(); 885 if (symtab) 886 symtab->Dump(&strm, interpreter.GetExecutionContext().target, sort_order); 887 } 888 } 889 } 890 891 static void 892 DumpModuleSections (CommandInterpreter &interpreter, Stream &strm, Module *module) 893 { 894 if (module) 895 { 896 ObjectFile *objfile = module->GetObjectFile (); 897 if (objfile) 898 { 899 SectionList *section_list = objfile->GetSectionList(); 900 if (section_list) 901 { 902 strm.PutCString ("Sections for '"); 903 strm << module->GetFileSpec(); 904 if (module->GetObjectName()) 905 strm << '(' << module->GetObjectName() << ')'; 906 strm.Printf ("' (%s):\n", module->GetArchitecture().GetArchitectureName()); 907 strm.IndentMore(); 908 section_list->Dump(&strm, interpreter.GetExecutionContext().target, true, UINT32_MAX); 909 strm.IndentLess(); 910 } 911 } 912 } 913 } 914 915 static bool 916 DumpModuleSymbolVendor (Stream &strm, Module *module) 917 { 918 if (module) 919 { 920 SymbolVendor *symbol_vendor = module->GetSymbolVendor(true); 921 if (symbol_vendor) 922 { 923 symbol_vendor->Dump(&strm); 924 return true; 925 } 926 } 927 return false; 928 } 929 930 static bool 931 LookupAddressInModule 932 ( 933 CommandInterpreter &interpreter, 934 Stream &strm, 935 Module *module, 936 uint32_t resolve_mask, 937 lldb::addr_t raw_addr, 938 lldb::addr_t offset, 939 bool verbose 940 ) 941 { 942 if (module) 943 { 944 lldb::addr_t addr = raw_addr - offset; 945 Address so_addr; 946 SymbolContext sc; 947 Target *target = interpreter.GetExecutionContext().target; 948 if (target && !target->GetSectionLoadList().IsEmpty()) 949 { 950 if (!target->GetSectionLoadList().ResolveLoadAddress (addr, so_addr)) 951 return false; 952 else if (so_addr.GetModule() != module) 953 return false; 954 } 955 else 956 { 957 if (!module->ResolveFileAddress (addr, so_addr)) 958 return false; 959 } 960 961 // If an offset was given, print out the address we ended up looking up 962 if (offset) 963 strm.Printf("File Address: 0x%llx\n", addr); 964 965 ExecutionContextScope *exe_scope = interpreter.GetExecutionContext().GetBestExecutionContextScope(); 966 strm.IndentMore(); 967 strm.Indent (" Address: "); 968 so_addr.Dump (&strm, exe_scope, Address::DumpStyleSectionNameOffset); 969 strm.EOL(); 970 strm.Indent (" Summary: "); 971 const uint32_t save_indent = strm.GetIndentLevel (); 972 strm.SetIndentLevel (save_indent + 11); 973 so_addr.Dump (&strm, exe_scope, Address::DumpStyleResolvedDescription); 974 strm.SetIndentLevel (save_indent); 975 strm.EOL(); 976 // Print out detailed address information when verbose is enabled 977 if (verbose) 978 { 979 if (so_addr.Dump (&strm, exe_scope, Address::DumpStyleDetailedSymbolContext)) 980 strm.EOL(); 981 } 982 strm.IndentLess(); 983 return true; 984 } 985 986 return false; 987 } 988 989 static uint32_t 990 LookupSymbolInModule (CommandInterpreter &interpreter, Stream &strm, Module *module, const char *name, bool name_is_regex) 991 { 992 if (module) 993 { 994 SymbolContext sc; 995 996 ObjectFile *objfile = module->GetObjectFile (); 997 if (objfile) 998 { 999 Symtab *symtab = objfile->GetSymtab(); 1000 if (symtab) 1001 { 1002 uint32_t i; 1003 std::vector<uint32_t> match_indexes; 1004 ConstString symbol_name (name); 1005 uint32_t num_matches = 0; 1006 if (name_is_regex) 1007 { 1008 RegularExpression name_regexp(name); 1009 num_matches = symtab->AppendSymbolIndexesMatchingRegExAndType (name_regexp, 1010 eSymbolTypeAny, 1011 match_indexes); 1012 } 1013 else 1014 { 1015 num_matches = symtab->AppendSymbolIndexesWithName (symbol_name, match_indexes); 1016 } 1017 1018 1019 if (num_matches > 0) 1020 { 1021 strm.Indent (); 1022 strm.Printf("%u symbols match %s'%s' in ", num_matches, 1023 name_is_regex ? "the regular expression " : "", name); 1024 DumpFullpath (strm, &module->GetFileSpec(), 0); 1025 strm.PutCString(":\n"); 1026 strm.IndentMore (); 1027 Symtab::DumpSymbolHeader (&strm); 1028 for (i=0; i < num_matches; ++i) 1029 { 1030 Symbol *symbol = symtab->SymbolAtIndex(match_indexes[i]); 1031 strm.Indent (); 1032 symbol->Dump (&strm, interpreter.GetExecutionContext().target, i); 1033 } 1034 strm.IndentLess (); 1035 return num_matches; 1036 } 1037 } 1038 } 1039 } 1040 return 0; 1041 } 1042 1043 1044 static void 1045 DumpSymbolContextList (CommandInterpreter &interpreter, Stream &strm, SymbolContextList &sc_list, bool prepend_addr, bool verbose) 1046 { 1047 strm.IndentMore (); 1048 uint32_t i; 1049 const uint32_t num_matches = sc_list.GetSize(); 1050 1051 for (i=0; i<num_matches; ++i) 1052 { 1053 SymbolContext sc; 1054 if (sc_list.GetContextAtIndex(i, sc)) 1055 { 1056 strm.Indent(); 1057 ExecutionContextScope *exe_scope = interpreter.GetExecutionContext().GetBestExecutionContextScope (); 1058 1059 if (prepend_addr) 1060 { 1061 if (sc.line_entry.range.GetBaseAddress().IsValid()) 1062 { 1063 sc.line_entry.range.GetBaseAddress().Dump (&strm, 1064 exe_scope, 1065 Address::DumpStyleLoadAddress, 1066 Address::DumpStyleModuleWithFileAddress); 1067 strm.PutCString(" in "); 1068 } 1069 } 1070 sc.DumpStopContext(&strm, 1071 exe_scope, 1072 sc.line_entry.range.GetBaseAddress(), 1073 true, 1074 true, 1075 false); 1076 strm.EOL(); 1077 if (verbose) 1078 { 1079 if (sc.line_entry.range.GetBaseAddress().IsValid()) 1080 { 1081 if (sc.line_entry.range.GetBaseAddress().Dump (&strm, 1082 exe_scope, 1083 Address::DumpStyleDetailedSymbolContext)) 1084 strm.PutCString("\n\n"); 1085 } 1086 else if (sc.function->GetAddressRange().GetBaseAddress().IsValid()) 1087 { 1088 if (sc.function->GetAddressRange().GetBaseAddress().Dump (&strm, 1089 exe_scope, 1090 Address::DumpStyleDetailedSymbolContext)) 1091 strm.PutCString("\n\n"); 1092 } 1093 } 1094 } 1095 } 1096 strm.IndentLess (); 1097 } 1098 1099 static uint32_t 1100 LookupFunctionInModule (CommandInterpreter &interpreter, Stream &strm, Module *module, const char *name, bool name_is_regex, bool verbose) 1101 { 1102 if (module && name && name[0]) 1103 { 1104 SymbolContextList sc_list; 1105 const bool include_symbols = false; 1106 const bool append = true; 1107 uint32_t num_matches = 0; 1108 if (name_is_regex) 1109 { 1110 RegularExpression function_name_regex (name); 1111 num_matches = module->FindFunctions (function_name_regex, 1112 include_symbols, 1113 append, 1114 sc_list); 1115 } 1116 else 1117 { 1118 ConstString function_name (name); 1119 num_matches = module->FindFunctions (function_name, 1120 eFunctionNameTypeBase | eFunctionNameTypeFull | eFunctionNameTypeMethod | eFunctionNameTypeSelector, 1121 include_symbols, 1122 append, 1123 sc_list); 1124 } 1125 1126 if (num_matches) 1127 { 1128 strm.Indent (); 1129 strm.Printf("%u match%s found in ", num_matches, num_matches > 1 ? "es" : ""); 1130 DumpFullpath (strm, &module->GetFileSpec(), 0); 1131 strm.PutCString(":\n"); 1132 DumpSymbolContextList (interpreter, strm, sc_list, true, verbose); 1133 } 1134 return num_matches; 1135 } 1136 return 0; 1137 } 1138 1139 static uint32_t 1140 LookupTypeInModule 1141 ( 1142 CommandInterpreter &interpreter, 1143 Stream &strm, 1144 Module *module, 1145 const char *name_cstr, 1146 bool name_is_regex 1147 ) 1148 { 1149 if (module && name_cstr && name_cstr[0]) 1150 { 1151 SymbolContextList sc_list; 1152 1153 SymbolVendor *symbol_vendor = module->GetSymbolVendor(); 1154 if (symbol_vendor) 1155 { 1156 TypeList type_list; 1157 uint32_t num_matches = 0; 1158 SymbolContext sc; 1159 // if (name_is_regex) 1160 // { 1161 // RegularExpression name_regex (name_cstr); 1162 // num_matches = symbol_vendor->FindFunctions(sc, name_regex, true, UINT32_MAX, type_list); 1163 // } 1164 // else 1165 // { 1166 ConstString name(name_cstr); 1167 num_matches = symbol_vendor->FindTypes(sc, name, true, UINT32_MAX, type_list); 1168 // } 1169 1170 if (num_matches) 1171 { 1172 strm.Indent (); 1173 strm.Printf("%u match%s found in ", num_matches, num_matches > 1 ? "es" : ""); 1174 DumpFullpath (strm, &module->GetFileSpec(), 0); 1175 strm.PutCString(":\n"); 1176 const uint32_t num_types = type_list.GetSize(); 1177 for (uint32_t i=0; i<num_types; ++i) 1178 { 1179 TypeSP type_sp (type_list.GetTypeAtIndex(i)); 1180 if (type_sp) 1181 { 1182 // Resolve the clang type so that any forward references 1183 // to types that haven't yet been parsed will get parsed. 1184 type_sp->GetClangFullType (); 1185 type_sp->GetDescription (&strm, eDescriptionLevelFull, true); 1186 } 1187 strm.EOL(); 1188 } 1189 } 1190 return num_matches; 1191 } 1192 } 1193 return 0; 1194 } 1195 1196 static uint32_t 1197 LookupFileAndLineInModule (CommandInterpreter &interpreter, 1198 Stream &strm, 1199 Module *module, 1200 const FileSpec &file_spec, 1201 uint32_t line, 1202 bool check_inlines, 1203 bool verbose) 1204 { 1205 if (module && file_spec) 1206 { 1207 SymbolContextList sc_list; 1208 const uint32_t num_matches = module->ResolveSymbolContextsForFileSpec(file_spec, line, check_inlines, 1209 eSymbolContextEverything, sc_list); 1210 if (num_matches > 0) 1211 { 1212 strm.Indent (); 1213 strm.Printf("%u match%s found in ", num_matches, num_matches > 1 ? "es" : ""); 1214 strm << file_spec; 1215 if (line > 0) 1216 strm.Printf (":%u", line); 1217 strm << " in "; 1218 DumpFullpath (strm, &module->GetFileSpec(), 0); 1219 strm.PutCString(":\n"); 1220 DumpSymbolContextList (interpreter, strm, sc_list, true, verbose); 1221 return num_matches; 1222 } 1223 } 1224 return 0; 1225 1226 } 1227 1228 #pragma mark CommandObjectTargetModulesModuleAutoComplete 1229 1230 //---------------------------------------------------------------------- 1231 // A base command object class that can auto complete with module file 1232 // paths 1233 //---------------------------------------------------------------------- 1234 1235 class CommandObjectTargetModulesModuleAutoComplete : public CommandObject 1236 { 1237 public: 1238 1239 CommandObjectTargetModulesModuleAutoComplete (CommandInterpreter &interpreter, 1240 const char *name, 1241 const char *help, 1242 const char *syntax) : 1243 CommandObject (interpreter, name, help, syntax) 1244 { 1245 CommandArgumentEntry arg; 1246 CommandArgumentData file_arg; 1247 1248 // Define the first (and only) variant of this arg. 1249 file_arg.arg_type = eArgTypeFilename; 1250 file_arg.arg_repetition = eArgRepeatStar; 1251 1252 // There is only one variant this argument could be; put it into the argument entry. 1253 arg.push_back (file_arg); 1254 1255 // Push the data for the first argument into the m_arguments vector. 1256 m_arguments.push_back (arg); 1257 } 1258 1259 virtual 1260 ~CommandObjectTargetModulesModuleAutoComplete () 1261 { 1262 } 1263 1264 virtual int 1265 HandleArgumentCompletion (Args &input, 1266 int &cursor_index, 1267 int &cursor_char_position, 1268 OptionElementVector &opt_element_vector, 1269 int match_start_point, 1270 int max_return_elements, 1271 bool &word_complete, 1272 StringList &matches) 1273 { 1274 // Arguments are the standard module completer. 1275 std::string completion_str (input.GetArgumentAtIndex(cursor_index)); 1276 completion_str.erase (cursor_char_position); 1277 1278 CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter, 1279 CommandCompletions::eModuleCompletion, 1280 completion_str.c_str(), 1281 match_start_point, 1282 max_return_elements, 1283 NULL, 1284 word_complete, 1285 matches); 1286 return matches.GetSize(); 1287 } 1288 }; 1289 1290 #pragma mark CommandObjectTargetModulesSourceFileAutoComplete 1291 1292 //---------------------------------------------------------------------- 1293 // A base command object class that can auto complete with module source 1294 // file paths 1295 //---------------------------------------------------------------------- 1296 1297 class CommandObjectTargetModulesSourceFileAutoComplete : public CommandObject 1298 { 1299 public: 1300 1301 CommandObjectTargetModulesSourceFileAutoComplete (CommandInterpreter &interpreter, 1302 const char *name, 1303 const char *help, 1304 const char *syntax) : 1305 CommandObject (interpreter, name, help, syntax) 1306 { 1307 CommandArgumentEntry arg; 1308 CommandArgumentData source_file_arg; 1309 1310 // Define the first (and only) variant of this arg. 1311 source_file_arg.arg_type = eArgTypeSourceFile; 1312 source_file_arg.arg_repetition = eArgRepeatPlus; 1313 1314 // There is only one variant this argument could be; put it into the argument entry. 1315 arg.push_back (source_file_arg); 1316 1317 // Push the data for the first argument into the m_arguments vector. 1318 m_arguments.push_back (arg); 1319 } 1320 1321 virtual 1322 ~CommandObjectTargetModulesSourceFileAutoComplete () 1323 { 1324 } 1325 1326 virtual int 1327 HandleArgumentCompletion (Args &input, 1328 int &cursor_index, 1329 int &cursor_char_position, 1330 OptionElementVector &opt_element_vector, 1331 int match_start_point, 1332 int max_return_elements, 1333 bool &word_complete, 1334 StringList &matches) 1335 { 1336 // Arguments are the standard source file completer. 1337 std::string completion_str (input.GetArgumentAtIndex(cursor_index)); 1338 completion_str.erase (cursor_char_position); 1339 1340 CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter, 1341 CommandCompletions::eSourceFileCompletion, 1342 completion_str.c_str(), 1343 match_start_point, 1344 max_return_elements, 1345 NULL, 1346 word_complete, 1347 matches); 1348 return matches.GetSize(); 1349 } 1350 }; 1351 1352 1353 #pragma mark CommandObjectTargetModulesDumpSymtab 1354 1355 1356 class CommandObjectTargetModulesDumpSymtab : public CommandObjectTargetModulesModuleAutoComplete 1357 { 1358 public: 1359 CommandObjectTargetModulesDumpSymtab (CommandInterpreter &interpreter) : 1360 CommandObjectTargetModulesModuleAutoComplete (interpreter, 1361 "target modules dump symtab", 1362 "Dump the symbol table from one or more target modules.", 1363 NULL), 1364 m_options (interpreter) 1365 { 1366 } 1367 1368 virtual 1369 ~CommandObjectTargetModulesDumpSymtab () 1370 { 1371 } 1372 1373 virtual bool 1374 Execute (Args& command, 1375 CommandReturnObject &result) 1376 { 1377 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 1378 if (target == NULL) 1379 { 1380 result.AppendError ("invalid target, create a debug target using the 'target create' command"); 1381 result.SetStatus (eReturnStatusFailed); 1382 return false; 1383 } 1384 else 1385 { 1386 uint32_t num_dumped = 0; 1387 1388 uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); 1389 result.GetOutputStream().SetAddressByteSize(addr_byte_size); 1390 result.GetErrorStream().SetAddressByteSize(addr_byte_size); 1391 1392 if (command.GetArgumentCount() == 0) 1393 { 1394 // Dump all sections for all modules images 1395 const uint32_t num_modules = target->GetImages().GetSize(); 1396 if (num_modules > 0) 1397 { 1398 result.GetOutputStream().Printf("Dumping symbol table for %u modules.\n", num_modules); 1399 for (uint32_t image_idx = 0; image_idx<num_modules; ++image_idx) 1400 { 1401 if (num_dumped > 0) 1402 { 1403 result.GetOutputStream().EOL(); 1404 result.GetOutputStream().EOL(); 1405 } 1406 num_dumped++; 1407 DumpModuleSymtab (m_interpreter, result.GetOutputStream(), target->GetImages().GetModulePointerAtIndex(image_idx), m_options.m_sort_order); 1408 } 1409 } 1410 else 1411 { 1412 result.AppendError ("the target has no associated executable images"); 1413 result.SetStatus (eReturnStatusFailed); 1414 return false; 1415 } 1416 } 1417 else 1418 { 1419 // Dump specified images (by basename or fullpath) 1420 const char *arg_cstr; 1421 for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx) 1422 { 1423 FileSpec image_file(arg_cstr, false); 1424 ModuleList matching_modules; 1425 size_t num_matching_modules = target->GetImages().FindModules(&image_file, NULL, NULL, NULL, matching_modules); 1426 1427 // Not found in our module list for our target, check the main 1428 // shared module list in case it is a extra file used somewhere 1429 // else 1430 if (num_matching_modules == 0) 1431 num_matching_modules = ModuleList::FindSharedModules (image_file, 1432 target->GetArchitecture(), 1433 NULL, 1434 NULL, 1435 matching_modules); 1436 1437 if (num_matching_modules > 0) 1438 { 1439 for (size_t i=0; i<num_matching_modules; ++i) 1440 { 1441 Module *image_module = matching_modules.GetModulePointerAtIndex(i); 1442 if (image_module) 1443 { 1444 if (num_dumped > 0) 1445 { 1446 result.GetOutputStream().EOL(); 1447 result.GetOutputStream().EOL(); 1448 } 1449 num_dumped++; 1450 DumpModuleSymtab (m_interpreter, result.GetOutputStream(), image_module, m_options.m_sort_order); 1451 } 1452 } 1453 } 1454 else 1455 result.AppendWarningWithFormat("Unable to find an image that matches '%s'.\n", arg_cstr); 1456 } 1457 } 1458 1459 if (num_dumped > 0) 1460 result.SetStatus (eReturnStatusSuccessFinishResult); 1461 else 1462 { 1463 result.AppendError ("no matching executable images found"); 1464 result.SetStatus (eReturnStatusFailed); 1465 } 1466 } 1467 return result.Succeeded(); 1468 } 1469 1470 virtual Options * 1471 GetOptions () 1472 { 1473 return &m_options; 1474 } 1475 1476 class CommandOptions : public Options 1477 { 1478 public: 1479 1480 CommandOptions (CommandInterpreter &interpreter) : 1481 Options(interpreter), 1482 m_sort_order (eSortOrderNone) 1483 { 1484 } 1485 1486 virtual 1487 ~CommandOptions () 1488 { 1489 } 1490 1491 virtual Error 1492 SetOptionValue (uint32_t option_idx, const char *option_arg) 1493 { 1494 Error error; 1495 char short_option = (char) m_getopt_table[option_idx].val; 1496 1497 switch (short_option) 1498 { 1499 case 's': 1500 { 1501 bool found_one = false; 1502 m_sort_order = (SortOrder) Args::StringToOptionEnum (option_arg, 1503 g_option_table[option_idx].enum_values, 1504 eSortOrderNone, 1505 &found_one); 1506 if (!found_one) 1507 error.SetErrorStringWithFormat("Invalid enumeration value '%s' for option '%c'.\n", 1508 option_arg, 1509 short_option); 1510 } 1511 break; 1512 1513 default: 1514 error.SetErrorStringWithFormat("Invalid short option character '%c'.\n", short_option); 1515 break; 1516 1517 } 1518 return error; 1519 } 1520 1521 void 1522 OptionParsingStarting () 1523 { 1524 m_sort_order = eSortOrderNone; 1525 } 1526 1527 const OptionDefinition* 1528 GetDefinitions () 1529 { 1530 return g_option_table; 1531 } 1532 1533 // Options table: Required for subclasses of Options. 1534 static OptionDefinition g_option_table[]; 1535 1536 SortOrder m_sort_order; 1537 }; 1538 1539 protected: 1540 1541 CommandOptions m_options; 1542 }; 1543 1544 static OptionEnumValueElement 1545 g_sort_option_enumeration[4] = 1546 { 1547 { eSortOrderNone, "none", "No sorting, use the original symbol table order."}, 1548 { eSortOrderByAddress, "address", "Sort output by symbol address."}, 1549 { eSortOrderByName, "name", "Sort output by symbol name."}, 1550 { 0, NULL, NULL } 1551 }; 1552 1553 1554 OptionDefinition 1555 CommandObjectTargetModulesDumpSymtab::CommandOptions::g_option_table[] = 1556 { 1557 { LLDB_OPT_SET_1, false, "sort", 's', required_argument, g_sort_option_enumeration, 0, eArgTypeSortOrder, "Supply a sort order when dumping the symbol table."}, 1558 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 1559 }; 1560 1561 #pragma mark CommandObjectTargetModulesDumpSections 1562 1563 //---------------------------------------------------------------------- 1564 // Image section dumping command 1565 //---------------------------------------------------------------------- 1566 1567 class CommandObjectTargetModulesDumpSections : public CommandObjectTargetModulesModuleAutoComplete 1568 { 1569 public: 1570 CommandObjectTargetModulesDumpSections (CommandInterpreter &interpreter) : 1571 CommandObjectTargetModulesModuleAutoComplete (interpreter, 1572 "target modules dump sections", 1573 "Dump the sections from one or more target modules.", 1574 //"target modules dump sections [<file1> ...]") 1575 NULL) 1576 { 1577 } 1578 1579 virtual 1580 ~CommandObjectTargetModulesDumpSections () 1581 { 1582 } 1583 1584 virtual bool 1585 Execute (Args& command, 1586 CommandReturnObject &result) 1587 { 1588 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 1589 if (target == NULL) 1590 { 1591 result.AppendError ("invalid target, create a debug target using the 'target create' command"); 1592 result.SetStatus (eReturnStatusFailed); 1593 return false; 1594 } 1595 else 1596 { 1597 uint32_t num_dumped = 0; 1598 1599 uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); 1600 result.GetOutputStream().SetAddressByteSize(addr_byte_size); 1601 result.GetErrorStream().SetAddressByteSize(addr_byte_size); 1602 1603 if (command.GetArgumentCount() == 0) 1604 { 1605 // Dump all sections for all modules images 1606 const uint32_t num_modules = target->GetImages().GetSize(); 1607 if (num_modules > 0) 1608 { 1609 result.GetOutputStream().Printf("Dumping sections for %u modules.\n", num_modules); 1610 for (uint32_t image_idx = 0; image_idx<num_modules; ++image_idx) 1611 { 1612 num_dumped++; 1613 DumpModuleSections (m_interpreter, result.GetOutputStream(), target->GetImages().GetModulePointerAtIndex(image_idx)); 1614 } 1615 } 1616 else 1617 { 1618 result.AppendError ("the target has no associated executable images"); 1619 result.SetStatus (eReturnStatusFailed); 1620 return false; 1621 } 1622 } 1623 else 1624 { 1625 // Dump specified images (by basename or fullpath) 1626 const char *arg_cstr; 1627 for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx) 1628 { 1629 FileSpec image_file(arg_cstr, false); 1630 ModuleList matching_modules; 1631 size_t num_matching_modules = target->GetImages().FindModules(&image_file, NULL, NULL, NULL, matching_modules); 1632 1633 // Not found in our module list for our target, check the main 1634 // shared module list in case it is a extra file used somewhere 1635 // else 1636 if (num_matching_modules == 0) 1637 num_matching_modules = ModuleList::FindSharedModules (image_file, 1638 target->GetArchitecture(), 1639 NULL, 1640 NULL, 1641 matching_modules); 1642 1643 if (num_matching_modules > 0) 1644 { 1645 for (size_t i=0; i<num_matching_modules; ++i) 1646 { 1647 Module * image_module = matching_modules.GetModulePointerAtIndex(i); 1648 if (image_module) 1649 { 1650 num_dumped++; 1651 DumpModuleSections (m_interpreter, result.GetOutputStream(), image_module); 1652 } 1653 } 1654 } 1655 else 1656 result.AppendWarningWithFormat("Unable to find an image that matches '%s'.\n", arg_cstr); 1657 } 1658 } 1659 1660 if (num_dumped > 0) 1661 result.SetStatus (eReturnStatusSuccessFinishResult); 1662 else 1663 { 1664 result.AppendError ("no matching executable images found"); 1665 result.SetStatus (eReturnStatusFailed); 1666 } 1667 } 1668 return result.Succeeded(); 1669 } 1670 }; 1671 1672 1673 #pragma mark CommandObjectTargetModulesDumpSymfile 1674 1675 //---------------------------------------------------------------------- 1676 // Image debug symbol dumping command 1677 //---------------------------------------------------------------------- 1678 1679 class CommandObjectTargetModulesDumpSymfile : public CommandObjectTargetModulesModuleAutoComplete 1680 { 1681 public: 1682 CommandObjectTargetModulesDumpSymfile (CommandInterpreter &interpreter) : 1683 CommandObjectTargetModulesModuleAutoComplete (interpreter, 1684 "target modules dump symfile", 1685 "Dump the debug symbol file for one or more target modules.", 1686 //"target modules dump symfile [<file1> ...]") 1687 NULL) 1688 { 1689 } 1690 1691 virtual 1692 ~CommandObjectTargetModulesDumpSymfile () 1693 { 1694 } 1695 1696 virtual bool 1697 Execute (Args& command, 1698 CommandReturnObject &result) 1699 { 1700 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 1701 if (target == NULL) 1702 { 1703 result.AppendError ("invalid target, create a debug target using the 'target create' command"); 1704 result.SetStatus (eReturnStatusFailed); 1705 return false; 1706 } 1707 else 1708 { 1709 uint32_t num_dumped = 0; 1710 1711 uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); 1712 result.GetOutputStream().SetAddressByteSize(addr_byte_size); 1713 result.GetErrorStream().SetAddressByteSize(addr_byte_size); 1714 1715 if (command.GetArgumentCount() == 0) 1716 { 1717 // Dump all sections for all modules images 1718 const uint32_t num_modules = target->GetImages().GetSize(); 1719 if (num_modules > 0) 1720 { 1721 result.GetOutputStream().Printf("Dumping debug symbols for %u modules.\n", num_modules); 1722 for (uint32_t image_idx = 0; image_idx<num_modules; ++image_idx) 1723 { 1724 if (DumpModuleSymbolVendor (result.GetOutputStream(), target->GetImages().GetModulePointerAtIndex(image_idx))) 1725 num_dumped++; 1726 } 1727 } 1728 else 1729 { 1730 result.AppendError ("the target has no associated executable images"); 1731 result.SetStatus (eReturnStatusFailed); 1732 return false; 1733 } 1734 } 1735 else 1736 { 1737 // Dump specified images (by basename or fullpath) 1738 const char *arg_cstr; 1739 for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx) 1740 { 1741 FileSpec image_file(arg_cstr, false); 1742 ModuleList matching_modules; 1743 size_t num_matching_modules = target->GetImages().FindModules(&image_file, NULL, NULL, NULL, matching_modules); 1744 1745 // Not found in our module list for our target, check the main 1746 // shared module list in case it is a extra file used somewhere 1747 // else 1748 if (num_matching_modules == 0) 1749 num_matching_modules = ModuleList::FindSharedModules (image_file, 1750 target->GetArchitecture(), 1751 NULL, 1752 NULL, 1753 matching_modules); 1754 1755 if (num_matching_modules > 0) 1756 { 1757 for (size_t i=0; i<num_matching_modules; ++i) 1758 { 1759 Module * image_module = matching_modules.GetModulePointerAtIndex(i); 1760 if (image_module) 1761 { 1762 if (DumpModuleSymbolVendor (result.GetOutputStream(), image_module)) 1763 num_dumped++; 1764 } 1765 } 1766 } 1767 else 1768 result.AppendWarningWithFormat("Unable to find an image that matches '%s'.\n", arg_cstr); 1769 } 1770 } 1771 1772 if (num_dumped > 0) 1773 result.SetStatus (eReturnStatusSuccessFinishResult); 1774 else 1775 { 1776 result.AppendError ("no matching executable images found"); 1777 result.SetStatus (eReturnStatusFailed); 1778 } 1779 } 1780 return result.Succeeded(); 1781 } 1782 }; 1783 1784 1785 #pragma mark CommandObjectTargetModulesDumpLineTable 1786 1787 //---------------------------------------------------------------------- 1788 // Image debug line table dumping command 1789 //---------------------------------------------------------------------- 1790 1791 class CommandObjectTargetModulesDumpLineTable : public CommandObjectTargetModulesSourceFileAutoComplete 1792 { 1793 public: 1794 CommandObjectTargetModulesDumpLineTable (CommandInterpreter &interpreter) : 1795 CommandObjectTargetModulesSourceFileAutoComplete (interpreter, 1796 "target modules dump line-table", 1797 "Dump the debug symbol file for one or more target modules.", 1798 NULL) 1799 { 1800 } 1801 1802 virtual 1803 ~CommandObjectTargetModulesDumpLineTable () 1804 { 1805 } 1806 1807 virtual bool 1808 Execute (Args& command, 1809 CommandReturnObject &result) 1810 { 1811 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 1812 if (target == NULL) 1813 { 1814 result.AppendError ("invalid target, create a debug target using the 'target create' command"); 1815 result.SetStatus (eReturnStatusFailed); 1816 return false; 1817 } 1818 else 1819 { 1820 ExecutionContext exe_ctx(m_interpreter.GetExecutionContext()); 1821 uint32_t total_num_dumped = 0; 1822 1823 uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); 1824 result.GetOutputStream().SetAddressByteSize(addr_byte_size); 1825 result.GetErrorStream().SetAddressByteSize(addr_byte_size); 1826 1827 if (command.GetArgumentCount() == 0) 1828 { 1829 result.AppendErrorWithFormat ("\nSyntax: %s\n", m_cmd_syntax.c_str()); 1830 result.SetStatus (eReturnStatusFailed); 1831 } 1832 else 1833 { 1834 // Dump specified images (by basename or fullpath) 1835 const char *arg_cstr; 1836 for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx) 1837 { 1838 FileSpec file_spec(arg_cstr, false); 1839 const uint32_t num_modules = target->GetImages().GetSize(); 1840 if (num_modules > 0) 1841 { 1842 uint32_t num_dumped = 0; 1843 for (uint32_t i = 0; i<num_modules; ++i) 1844 { 1845 if (DumpCompileUnitLineTable (m_interpreter, 1846 result.GetOutputStream(), 1847 target->GetImages().GetModulePointerAtIndex(i), 1848 file_spec, 1849 exe_ctx.process != NULL && exe_ctx.process->IsAlive())) 1850 num_dumped++; 1851 } 1852 if (num_dumped == 0) 1853 result.AppendWarningWithFormat ("No source filenames matched '%s'.\n", arg_cstr); 1854 else 1855 total_num_dumped += num_dumped; 1856 } 1857 } 1858 } 1859 1860 if (total_num_dumped > 0) 1861 result.SetStatus (eReturnStatusSuccessFinishResult); 1862 else 1863 { 1864 result.AppendError ("no source filenames matched any command arguments"); 1865 result.SetStatus (eReturnStatusFailed); 1866 } 1867 } 1868 return result.Succeeded(); 1869 } 1870 }; 1871 1872 1873 #pragma mark CommandObjectTargetModulesDump 1874 1875 //---------------------------------------------------------------------- 1876 // Dump multi-word command for target modules 1877 //---------------------------------------------------------------------- 1878 1879 class CommandObjectTargetModulesDump : public CommandObjectMultiword 1880 { 1881 public: 1882 1883 //------------------------------------------------------------------ 1884 // Constructors and Destructors 1885 //------------------------------------------------------------------ 1886 CommandObjectTargetModulesDump(CommandInterpreter &interpreter) : 1887 CommandObjectMultiword (interpreter, 1888 "target modules dump", 1889 "A set of commands for dumping information about one or more target modules.", 1890 "target modules dump [symtab|sections|symfile|line-table] [<file1> <file2> ...]") 1891 { 1892 LoadSubCommand ("symtab", CommandObjectSP (new CommandObjectTargetModulesDumpSymtab (interpreter))); 1893 LoadSubCommand ("sections", CommandObjectSP (new CommandObjectTargetModulesDumpSections (interpreter))); 1894 LoadSubCommand ("symfile", CommandObjectSP (new CommandObjectTargetModulesDumpSymfile (interpreter))); 1895 LoadSubCommand ("line-table", CommandObjectSP (new CommandObjectTargetModulesDumpLineTable (interpreter))); 1896 } 1897 1898 virtual 1899 ~CommandObjectTargetModulesDump() 1900 { 1901 } 1902 }; 1903 1904 class CommandObjectTargetModulesAdd : public CommandObject 1905 { 1906 public: 1907 CommandObjectTargetModulesAdd (CommandInterpreter &interpreter) : 1908 CommandObject (interpreter, 1909 "target modules add", 1910 "Add a new module to the current target's modules.", 1911 "target modules add [<module>]") 1912 { 1913 } 1914 1915 virtual 1916 ~CommandObjectTargetModulesAdd () 1917 { 1918 } 1919 1920 virtual bool 1921 Execute (Args& args, 1922 CommandReturnObject &result) 1923 { 1924 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 1925 if (target == NULL) 1926 { 1927 result.AppendError ("invalid target, create a debug target using the 'target create' command"); 1928 result.SetStatus (eReturnStatusFailed); 1929 return false; 1930 } 1931 else 1932 { 1933 const size_t argc = args.GetArgumentCount(); 1934 if (argc == 0) 1935 { 1936 result.AppendError ("one or more executable image paths must be specified"); 1937 result.SetStatus (eReturnStatusFailed); 1938 return false; 1939 } 1940 else 1941 { 1942 for (size_t i=0; i<argc; ++i) 1943 { 1944 const char *path = args.GetArgumentAtIndex(i); 1945 if (path) 1946 { 1947 FileSpec file_spec(path, true); 1948 ArchSpec arch; 1949 if (file_spec.Exists()) 1950 { 1951 ModuleSP module_sp (target->GetSharedModule(file_spec, arch)); 1952 if (!module_sp) 1953 { 1954 result.AppendError ("one or more executable image paths must be specified"); 1955 result.SetStatus (eReturnStatusFailed); 1956 return false; 1957 } 1958 } 1959 else 1960 { 1961 char resolved_path[PATH_MAX]; 1962 result.SetStatus (eReturnStatusFailed); 1963 if (file_spec.GetPath (resolved_path, sizeof(resolved_path))) 1964 { 1965 if (strcmp (resolved_path, path) != 0) 1966 { 1967 result.AppendErrorWithFormat ("invalid module path '%s' with resolved path '%s'\n", path, resolved_path); 1968 break; 1969 } 1970 } 1971 result.AppendErrorWithFormat ("invalid module path '%s'\n", path); 1972 break; 1973 } 1974 } 1975 } 1976 } 1977 } 1978 return result.Succeeded(); 1979 } 1980 1981 int 1982 HandleArgumentCompletion (Args &input, 1983 int &cursor_index, 1984 int &cursor_char_position, 1985 OptionElementVector &opt_element_vector, 1986 int match_start_point, 1987 int max_return_elements, 1988 bool &word_complete, 1989 StringList &matches) 1990 { 1991 std::string completion_str (input.GetArgumentAtIndex(cursor_index)); 1992 completion_str.erase (cursor_char_position); 1993 1994 CommandCompletions::InvokeCommonCompletionCallbacks (m_interpreter, 1995 CommandCompletions::eDiskFileCompletion, 1996 completion_str.c_str(), 1997 match_start_point, 1998 max_return_elements, 1999 NULL, 2000 word_complete, 2001 matches); 2002 return matches.GetSize(); 2003 } 2004 2005 }; 2006 2007 class CommandObjectTargetModulesLoad : public CommandObjectTargetModulesModuleAutoComplete 2008 { 2009 public: 2010 CommandObjectTargetModulesLoad (CommandInterpreter &interpreter) : 2011 CommandObjectTargetModulesModuleAutoComplete (interpreter, 2012 "target modules load", 2013 "Set the load addresses for one or more sections in a target module.", 2014 "target modules load [--file <module> --uuid <uuid>] <sect-name> <address> [<sect-name> <address> ....]"), 2015 m_option_group (interpreter), 2016 m_file_option (LLDB_OPT_SET_1, false, "file", 'f', 0, eArgTypePath, "Fullpath or basename for module to load."), 2017 m_slide_option(LLDB_OPT_SET_1, false, "slide", 's', 0, eArgTypeOffset, "Set the load address for all sections to be the virtual address in the file plus the offset.", 0) 2018 { 2019 m_option_group.Append (&m_uuid_option_group, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 2020 m_option_group.Append (&m_file_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 2021 m_option_group.Append (&m_slide_option, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 2022 m_option_group.Finalize(); 2023 } 2024 2025 virtual 2026 ~CommandObjectTargetModulesLoad () 2027 { 2028 } 2029 2030 virtual bool 2031 Execute (Args& args, 2032 CommandReturnObject &result) 2033 { 2034 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 2035 if (target == NULL) 2036 { 2037 result.AppendError ("invalid target, create a debug target using the 'target create' command"); 2038 result.SetStatus (eReturnStatusFailed); 2039 return false; 2040 } 2041 else 2042 { 2043 const size_t argc = args.GetArgumentCount(); 2044 const FileSpec *file_ptr = NULL; 2045 const UUID *uuid_ptr = NULL; 2046 if (m_file_option.GetOptionValue().OptionWasSet()) 2047 file_ptr = &m_file_option.GetOptionValue().GetCurrentValue(); 2048 2049 if (m_uuid_option_group.GetOptionValue().OptionWasSet()) 2050 uuid_ptr = &m_uuid_option_group.GetOptionValue().GetCurrentValue(); 2051 2052 if (file_ptr || uuid_ptr) 2053 { 2054 2055 ModuleList matching_modules; 2056 const size_t num_matches = target->GetImages().FindModules (file_ptr, // File spec to match (can be NULL to match by UUID only) 2057 NULL, // Architecture 2058 uuid_ptr, // UUID to match (can be NULL to not match on UUID) 2059 NULL, // Object name 2060 matching_modules); 2061 2062 char path[PATH_MAX]; 2063 if (num_matches == 1) 2064 { 2065 Module *module = matching_modules.GetModulePointerAtIndex(0); 2066 if (module) 2067 { 2068 ObjectFile *objfile = module->GetObjectFile(); 2069 if (objfile) 2070 { 2071 SectionList *section_list = objfile->GetSectionList(); 2072 if (section_list) 2073 { 2074 if (argc == 0) 2075 { 2076 if (m_slide_option.GetOptionValue().OptionWasSet()) 2077 { 2078 Module *module = matching_modules.GetModulePointerAtIndex(0); 2079 if (module) 2080 { 2081 ObjectFile *objfile = module->GetObjectFile(); 2082 if (objfile) 2083 { 2084 SectionList *section_list = objfile->GetSectionList(); 2085 if (section_list) 2086 { 2087 const size_t num_sections = section_list->GetSize(); 2088 const addr_t slide = m_slide_option.GetOptionValue().GetCurrentValue(); 2089 for (size_t sect_idx = 0; sect_idx < num_sections; ++sect_idx) 2090 { 2091 SectionSP section_sp (section_list->GetSectionAtIndex(sect_idx)); 2092 if (section_sp) 2093 target->GetSectionLoadList().SetSectionLoadAddress (section_sp.get(), section_sp->GetFileAddress() + slide); 2094 } 2095 } 2096 } 2097 } 2098 } 2099 else 2100 { 2101 result.AppendError ("one or more section name + load address pair must be specified"); 2102 result.SetStatus (eReturnStatusFailed); 2103 return false; 2104 } 2105 } 2106 else 2107 { 2108 if (m_slide_option.GetOptionValue().OptionWasSet()) 2109 { 2110 result.AppendError ("The \"--slide <offset>\" option can't be used in conjunction with setting section load addresses.\n"); 2111 result.SetStatus (eReturnStatusFailed); 2112 return false; 2113 } 2114 2115 for (size_t i=0; i<argc; i += 2) 2116 { 2117 const char *sect_name = args.GetArgumentAtIndex(i); 2118 const char *load_addr_cstr = args.GetArgumentAtIndex(i+1); 2119 if (sect_name && load_addr_cstr) 2120 { 2121 ConstString const_sect_name(sect_name); 2122 bool success = false; 2123 addr_t load_addr = Args::StringToUInt64(load_addr_cstr, LLDB_INVALID_ADDRESS, 0, &success); 2124 if (success) 2125 { 2126 SectionSP section_sp (section_list->FindSectionByName(const_sect_name)); 2127 if (section_sp) 2128 { 2129 target->GetSectionLoadList().SetSectionLoadAddress (section_sp.get(), load_addr); 2130 result.AppendMessageWithFormat("section '%s' loaded at 0x%llx\n", sect_name, load_addr); 2131 } 2132 else 2133 { 2134 result.AppendErrorWithFormat ("no section found that matches the section name '%s'\n", sect_name); 2135 result.SetStatus (eReturnStatusFailed); 2136 break; 2137 } 2138 } 2139 else 2140 { 2141 result.AppendErrorWithFormat ("invalid load address string '%s'\n", load_addr_cstr); 2142 result.SetStatus (eReturnStatusFailed); 2143 break; 2144 } 2145 } 2146 else 2147 { 2148 if (sect_name) 2149 result.AppendError ("section names must be followed by a load address.\n"); 2150 else 2151 result.AppendError ("one or more section name + load address pair must be specified.\n"); 2152 result.SetStatus (eReturnStatusFailed); 2153 break; 2154 } 2155 } 2156 } 2157 } 2158 else 2159 { 2160 module->GetFileSpec().GetPath (path, sizeof(path)); 2161 result.AppendErrorWithFormat ("no sections in object file '%s'\n", path); 2162 result.SetStatus (eReturnStatusFailed); 2163 } 2164 } 2165 else 2166 { 2167 module->GetFileSpec().GetPath (path, sizeof(path)); 2168 result.AppendErrorWithFormat ("no object file for module '%s'\n", path); 2169 result.SetStatus (eReturnStatusFailed); 2170 } 2171 } 2172 else 2173 { 2174 module->GetFileSpec().GetPath (path, sizeof(path)); 2175 result.AppendErrorWithFormat ("invalid module '%s'.\n", path); 2176 result.SetStatus (eReturnStatusFailed); 2177 } 2178 } 2179 else 2180 { 2181 char uuid_cstr[64]; 2182 if (file_ptr) 2183 file_ptr->GetPath (path, sizeof(path)); 2184 else 2185 path[0] = '\0'; 2186 2187 if (uuid_ptr) 2188 uuid_ptr->GetAsCString(uuid_cstr, sizeof(uuid_cstr)); 2189 else 2190 uuid_cstr[0] = '\0'; 2191 if (num_matches > 1) 2192 { 2193 result.AppendErrorWithFormat ("multiple modules match%s%s%s%s:\n", 2194 path[0] ? " file=" : "", 2195 path, 2196 uuid_cstr[0] ? " uuid=" : "", 2197 uuid_cstr); 2198 for (size_t i=0; i<num_matches; ++i) 2199 { 2200 if (matching_modules.GetModulePointerAtIndex(i)->GetFileSpec().GetPath (path, sizeof(path))) 2201 result.AppendMessageWithFormat("%s\n", path); 2202 } 2203 } 2204 else 2205 { 2206 result.AppendErrorWithFormat ("no modules were found that match%s%s%s%s.\n", 2207 path[0] ? " file=" : "", 2208 path, 2209 uuid_cstr[0] ? " uuid=" : "", 2210 uuid_cstr); 2211 } 2212 result.SetStatus (eReturnStatusFailed); 2213 } 2214 } 2215 else 2216 { 2217 result.AppendError ("either the \"--file <module>\" or the \"--uuid <uuid>\" option must be specified.\n"); 2218 result.SetStatus (eReturnStatusFailed); 2219 return false; 2220 } 2221 } 2222 return result.Succeeded(); 2223 } 2224 2225 virtual Options * 2226 GetOptions () 2227 { 2228 return &m_option_group; 2229 } 2230 2231 protected: 2232 OptionGroupOptions m_option_group; 2233 OptionGroupUUID m_uuid_option_group; 2234 OptionGroupFile m_file_option; 2235 OptionGroupUInt64 m_slide_option; 2236 }; 2237 2238 //---------------------------------------------------------------------- 2239 // List images with associated information 2240 //---------------------------------------------------------------------- 2241 class CommandObjectTargetModulesList : public CommandObject 2242 { 2243 public: 2244 2245 class CommandOptions : public Options 2246 { 2247 public: 2248 2249 CommandOptions (CommandInterpreter &interpreter) : 2250 Options(interpreter), 2251 m_format_array() 2252 { 2253 } 2254 2255 virtual 2256 ~CommandOptions () 2257 { 2258 } 2259 2260 virtual Error 2261 SetOptionValue (uint32_t option_idx, const char *option_arg) 2262 { 2263 char short_option = (char) m_getopt_table[option_idx].val; 2264 uint32_t width = 0; 2265 if (option_arg) 2266 width = strtoul (option_arg, NULL, 0); 2267 m_format_array.push_back(std::make_pair(short_option, width)); 2268 Error error; 2269 return error; 2270 } 2271 2272 void 2273 OptionParsingStarting () 2274 { 2275 m_format_array.clear(); 2276 } 2277 2278 const OptionDefinition* 2279 GetDefinitions () 2280 { 2281 return g_option_table; 2282 } 2283 2284 // Options table: Required for subclasses of Options. 2285 2286 static OptionDefinition g_option_table[]; 2287 2288 // Instance variables to hold the values for command options. 2289 typedef std::vector< std::pair<char, uint32_t> > FormatWidthCollection; 2290 FormatWidthCollection m_format_array; 2291 }; 2292 2293 CommandObjectTargetModulesList (CommandInterpreter &interpreter) : 2294 CommandObject (interpreter, 2295 "target modules list", 2296 "List current executable and dependent shared library images.", 2297 "target modules list [<cmd-options>]"), 2298 m_options (interpreter) 2299 { 2300 } 2301 2302 virtual 2303 ~CommandObjectTargetModulesList () 2304 { 2305 } 2306 2307 virtual 2308 Options * 2309 GetOptions () 2310 { 2311 return &m_options; 2312 } 2313 2314 virtual bool 2315 Execute (Args& command, 2316 CommandReturnObject &result) 2317 { 2318 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 2319 if (target == NULL) 2320 { 2321 result.AppendError ("invalid target, create a debug target using the 'target create' command"); 2322 result.SetStatus (eReturnStatusFailed); 2323 return false; 2324 } 2325 else 2326 { 2327 uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); 2328 result.GetOutputStream().SetAddressByteSize(addr_byte_size); 2329 result.GetErrorStream().SetAddressByteSize(addr_byte_size); 2330 // Dump all sections for all modules images 2331 const uint32_t num_modules = target->GetImages().GetSize(); 2332 if (num_modules > 0) 2333 { 2334 Stream &strm = result.GetOutputStream(); 2335 2336 for (uint32_t image_idx = 0; image_idx<num_modules; ++image_idx) 2337 { 2338 Module *module = target->GetImages().GetModulePointerAtIndex(image_idx); 2339 strm.Printf("[%3u] ", image_idx); 2340 2341 bool dump_object_name = false; 2342 if (m_options.m_format_array.empty()) 2343 { 2344 DumpFullpath(strm, &module->GetFileSpec(), 0); 2345 dump_object_name = true; 2346 } 2347 else 2348 { 2349 const size_t num_entries = m_options.m_format_array.size(); 2350 for (size_t i=0; i<num_entries; ++i) 2351 { 2352 if (i > 0) 2353 strm.PutChar(' '); 2354 char format_char = m_options.m_format_array[i].first; 2355 uint32_t width = m_options.m_format_array[i].second; 2356 switch (format_char) 2357 { 2358 case 'a': 2359 DumpModuleArchitecture (strm, module, false, width); 2360 break; 2361 2362 case 't': 2363 DumpModuleArchitecture (strm, module, true, width); 2364 break; 2365 2366 case 'f': 2367 DumpFullpath (strm, &module->GetFileSpec(), width); 2368 dump_object_name = true; 2369 break; 2370 2371 case 'd': 2372 DumpDirectory (strm, &module->GetFileSpec(), width); 2373 break; 2374 2375 case 'b': 2376 DumpBasename (strm, &module->GetFileSpec(), width); 2377 dump_object_name = true; 2378 break; 2379 2380 case 's': 2381 case 'S': 2382 { 2383 SymbolVendor *symbol_vendor = module->GetSymbolVendor(); 2384 if (symbol_vendor) 2385 { 2386 SymbolFile *symbol_file = symbol_vendor->GetSymbolFile(); 2387 if (symbol_file) 2388 { 2389 if (format_char == 'S') 2390 DumpBasename(strm, &symbol_file->GetObjectFile()->GetFileSpec(), width); 2391 else 2392 DumpFullpath (strm, &symbol_file->GetObjectFile()->GetFileSpec(), width); 2393 dump_object_name = true; 2394 break; 2395 } 2396 } 2397 strm.Printf("%.*s", width, "<NONE>"); 2398 } 2399 break; 2400 2401 case 'u': 2402 DumpModuleUUID(strm, module); 2403 break; 2404 2405 default: 2406 break; 2407 } 2408 2409 } 2410 } 2411 if (dump_object_name) 2412 { 2413 const char *object_name = module->GetObjectName().GetCString(); 2414 if (object_name) 2415 strm.Printf ("(%s)", object_name); 2416 } 2417 strm.EOL(); 2418 } 2419 result.SetStatus (eReturnStatusSuccessFinishResult); 2420 } 2421 else 2422 { 2423 result.AppendError ("the target has no associated executable images"); 2424 result.SetStatus (eReturnStatusFailed); 2425 return false; 2426 } 2427 } 2428 return result.Succeeded(); 2429 } 2430 protected: 2431 2432 CommandOptions m_options; 2433 }; 2434 2435 OptionDefinition 2436 CommandObjectTargetModulesList::CommandOptions::g_option_table[] = 2437 { 2438 { LLDB_OPT_SET_1, false, "arch", 'a', optional_argument, NULL, 0, eArgTypeWidth, "Display the architecture when listing images."}, 2439 { LLDB_OPT_SET_1, false, "triple", 't', optional_argument, NULL, 0, eArgTypeWidth, "Display the triple when listing images."}, 2440 { LLDB_OPT_SET_1, false, "uuid", 'u', no_argument, NULL, 0, eArgTypeNone, "Display the UUID when listing images."}, 2441 { LLDB_OPT_SET_1, false, "fullpath", 'f', optional_argument, NULL, 0, eArgTypeWidth, "Display the fullpath to the image object file."}, 2442 { LLDB_OPT_SET_1, false, "directory", 'd', optional_argument, NULL, 0, eArgTypeWidth, "Display the directory with optional width for the image object file."}, 2443 { LLDB_OPT_SET_1, false, "basename", 'b', optional_argument, NULL, 0, eArgTypeWidth, "Display the basename with optional width for the image object file."}, 2444 { LLDB_OPT_SET_1, false, "symfile", 's', optional_argument, NULL, 0, eArgTypeWidth, "Display the fullpath to the image symbol file with optional width."}, 2445 { LLDB_OPT_SET_1, false, "symfile-basename", 'S', optional_argument, NULL, 0, eArgTypeWidth, "Display the basename to the image symbol file with optional width."}, 2446 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 2447 }; 2448 2449 2450 2451 //---------------------------------------------------------------------- 2452 // Lookup information in images 2453 //---------------------------------------------------------------------- 2454 class CommandObjectTargetModulesLookup : public CommandObject 2455 { 2456 public: 2457 2458 enum 2459 { 2460 eLookupTypeInvalid = -1, 2461 eLookupTypeAddress = 0, 2462 eLookupTypeSymbol, 2463 eLookupTypeFileLine, // Line is optional 2464 eLookupTypeFunction, 2465 eLookupTypeType, 2466 kNumLookupTypes 2467 }; 2468 2469 class CommandOptions : public Options 2470 { 2471 public: 2472 2473 CommandOptions (CommandInterpreter &interpreter) : 2474 Options(interpreter) 2475 { 2476 OptionParsingStarting(); 2477 } 2478 2479 virtual 2480 ~CommandOptions () 2481 { 2482 } 2483 2484 virtual Error 2485 SetOptionValue (uint32_t option_idx, const char *option_arg) 2486 { 2487 Error error; 2488 2489 char short_option = (char) m_getopt_table[option_idx].val; 2490 2491 switch (short_option) 2492 { 2493 case 'a': 2494 m_type = eLookupTypeAddress; 2495 m_addr = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS); 2496 if (m_addr == LLDB_INVALID_ADDRESS) 2497 error.SetErrorStringWithFormat ("Invalid address string '%s'.\n", option_arg); 2498 break; 2499 2500 case 'o': 2501 m_offset = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS); 2502 if (m_offset == LLDB_INVALID_ADDRESS) 2503 error.SetErrorStringWithFormat ("Invalid offset string '%s'.\n", option_arg); 2504 break; 2505 2506 case 's': 2507 m_str = option_arg; 2508 m_type = eLookupTypeSymbol; 2509 break; 2510 2511 case 'f': 2512 m_file.SetFile (option_arg, false); 2513 m_type = eLookupTypeFileLine; 2514 break; 2515 2516 case 'i': 2517 m_check_inlines = false; 2518 break; 2519 2520 case 'l': 2521 m_line_number = Args::StringToUInt32(option_arg, UINT32_MAX); 2522 if (m_line_number == UINT32_MAX) 2523 error.SetErrorStringWithFormat ("Invalid line number string '%s'.\n", option_arg); 2524 else if (m_line_number == 0) 2525 error.SetErrorString ("Zero is an invalid line number."); 2526 m_type = eLookupTypeFileLine; 2527 break; 2528 2529 case 'n': 2530 m_str = option_arg; 2531 m_type = eLookupTypeFunction; 2532 break; 2533 2534 case 't': 2535 m_str = option_arg; 2536 m_type = eLookupTypeType; 2537 break; 2538 2539 case 'v': 2540 m_verbose = 1; 2541 break; 2542 2543 case 'r': 2544 m_use_regex = true; 2545 break; 2546 } 2547 2548 return error; 2549 } 2550 2551 void 2552 OptionParsingStarting () 2553 { 2554 m_type = eLookupTypeInvalid; 2555 m_str.clear(); 2556 m_file.Clear(); 2557 m_addr = LLDB_INVALID_ADDRESS; 2558 m_offset = 0; 2559 m_line_number = 0; 2560 m_use_regex = false; 2561 m_check_inlines = true; 2562 m_verbose = false; 2563 } 2564 2565 const OptionDefinition* 2566 GetDefinitions () 2567 { 2568 return g_option_table; 2569 } 2570 2571 // Options table: Required for subclasses of Options. 2572 2573 static OptionDefinition g_option_table[]; 2574 int m_type; // Should be a eLookupTypeXXX enum after parsing options 2575 std::string m_str; // Holds name lookup 2576 FileSpec m_file; // Files for file lookups 2577 lldb::addr_t m_addr; // Holds the address to lookup 2578 lldb::addr_t m_offset; // Subtract this offset from m_addr before doing lookups. 2579 uint32_t m_line_number; // Line number for file+line lookups 2580 bool m_use_regex; // Name lookups in m_str are regular expressions. 2581 bool m_check_inlines;// Check for inline entries when looking up by file/line. 2582 bool m_verbose; // Enable verbose lookup info 2583 2584 }; 2585 2586 CommandObjectTargetModulesLookup (CommandInterpreter &interpreter) : 2587 CommandObject (interpreter, 2588 "target modules lookup", 2589 "Look up information within executable and dependent shared library images.", 2590 NULL), 2591 m_options (interpreter) 2592 { 2593 CommandArgumentEntry arg; 2594 CommandArgumentData file_arg; 2595 2596 // Define the first (and only) variant of this arg. 2597 file_arg.arg_type = eArgTypeFilename; 2598 file_arg.arg_repetition = eArgRepeatStar; 2599 2600 // There is only one variant this argument could be; put it into the argument entry. 2601 arg.push_back (file_arg); 2602 2603 // Push the data for the first argument into the m_arguments vector. 2604 m_arguments.push_back (arg); 2605 } 2606 2607 virtual 2608 ~CommandObjectTargetModulesLookup () 2609 { 2610 } 2611 2612 virtual Options * 2613 GetOptions () 2614 { 2615 return &m_options; 2616 } 2617 2618 2619 bool 2620 LookupInModule (CommandInterpreter &interpreter, Module *module, CommandReturnObject &result, bool &syntax_error) 2621 { 2622 switch (m_options.m_type) 2623 { 2624 case eLookupTypeAddress: 2625 if (m_options.m_addr != LLDB_INVALID_ADDRESS) 2626 { 2627 if (LookupAddressInModule (m_interpreter, 2628 result.GetOutputStream(), 2629 module, 2630 eSymbolContextEverything, 2631 m_options.m_addr, 2632 m_options.m_offset, 2633 m_options.m_verbose)) 2634 { 2635 result.SetStatus(eReturnStatusSuccessFinishResult); 2636 return true; 2637 } 2638 } 2639 break; 2640 2641 case eLookupTypeSymbol: 2642 if (!m_options.m_str.empty()) 2643 { 2644 if (LookupSymbolInModule (m_interpreter, result.GetOutputStream(), module, m_options.m_str.c_str(), m_options.m_use_regex)) 2645 { 2646 result.SetStatus(eReturnStatusSuccessFinishResult); 2647 return true; 2648 } 2649 } 2650 break; 2651 2652 case eLookupTypeFileLine: 2653 if (m_options.m_file) 2654 { 2655 2656 if (LookupFileAndLineInModule (m_interpreter, 2657 result.GetOutputStream(), 2658 module, 2659 m_options.m_file, 2660 m_options.m_line_number, 2661 m_options.m_check_inlines, 2662 m_options.m_verbose)) 2663 { 2664 result.SetStatus(eReturnStatusSuccessFinishResult); 2665 return true; 2666 } 2667 } 2668 break; 2669 2670 case eLookupTypeFunction: 2671 if (!m_options.m_str.empty()) 2672 { 2673 if (LookupFunctionInModule (m_interpreter, 2674 result.GetOutputStream(), 2675 module, 2676 m_options.m_str.c_str(), 2677 m_options.m_use_regex, 2678 m_options.m_verbose)) 2679 { 2680 result.SetStatus(eReturnStatusSuccessFinishResult); 2681 return true; 2682 } 2683 } 2684 break; 2685 2686 case eLookupTypeType: 2687 if (!m_options.m_str.empty()) 2688 { 2689 if (LookupTypeInModule (m_interpreter, 2690 result.GetOutputStream(), 2691 module, 2692 m_options.m_str.c_str(), 2693 m_options.m_use_regex)) 2694 { 2695 result.SetStatus(eReturnStatusSuccessFinishResult); 2696 return true; 2697 } 2698 } 2699 break; 2700 2701 default: 2702 m_options.GenerateOptionUsage (result.GetErrorStream(), this); 2703 syntax_error = true; 2704 break; 2705 } 2706 2707 result.SetStatus (eReturnStatusFailed); 2708 return false; 2709 } 2710 2711 virtual bool 2712 Execute (Args& command, 2713 CommandReturnObject &result) 2714 { 2715 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 2716 if (target == NULL) 2717 { 2718 result.AppendError ("invalid target, create a debug target using the 'target create' command"); 2719 result.SetStatus (eReturnStatusFailed); 2720 return false; 2721 } 2722 else 2723 { 2724 bool syntax_error = false; 2725 uint32_t i; 2726 uint32_t num_successful_lookups = 0; 2727 uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); 2728 result.GetOutputStream().SetAddressByteSize(addr_byte_size); 2729 result.GetErrorStream().SetAddressByteSize(addr_byte_size); 2730 // Dump all sections for all modules images 2731 2732 if (command.GetArgumentCount() == 0) 2733 { 2734 // Dump all sections for all modules images 2735 const uint32_t num_modules = target->GetImages().GetSize(); 2736 if (num_modules > 0) 2737 { 2738 for (i = 0; i<num_modules && syntax_error == false; ++i) 2739 { 2740 if (LookupInModule (m_interpreter, target->GetImages().GetModulePointerAtIndex(i), result, syntax_error)) 2741 { 2742 result.GetOutputStream().EOL(); 2743 num_successful_lookups++; 2744 } 2745 } 2746 } 2747 else 2748 { 2749 result.AppendError ("the target has no associated executable images"); 2750 result.SetStatus (eReturnStatusFailed); 2751 return false; 2752 } 2753 } 2754 else 2755 { 2756 // Dump specified images (by basename or fullpath) 2757 const char *arg_cstr; 2758 for (i = 0; (arg_cstr = command.GetArgumentAtIndex(i)) != NULL && syntax_error == false; ++i) 2759 { 2760 FileSpec image_file(arg_cstr, false); 2761 ModuleList matching_modules; 2762 size_t num_matching_modules = target->GetImages().FindModules(&image_file, NULL, NULL, NULL, matching_modules); 2763 2764 // Not found in our module list for our target, check the main 2765 // shared module list in case it is a extra file used somewhere 2766 // else 2767 if (num_matching_modules == 0) 2768 num_matching_modules = ModuleList::FindSharedModules (image_file, 2769 target->GetArchitecture(), 2770 NULL, 2771 NULL, 2772 matching_modules); 2773 2774 if (num_matching_modules > 0) 2775 { 2776 for (size_t j=0; j<num_matching_modules; ++j) 2777 { 2778 Module * image_module = matching_modules.GetModulePointerAtIndex(j); 2779 if (image_module) 2780 { 2781 if (LookupInModule (m_interpreter, image_module, result, syntax_error)) 2782 { 2783 result.GetOutputStream().EOL(); 2784 num_successful_lookups++; 2785 } 2786 } 2787 } 2788 } 2789 else 2790 result.AppendWarningWithFormat("Unable to find an image that matches '%s'.\n", arg_cstr); 2791 } 2792 } 2793 2794 if (num_successful_lookups > 0) 2795 result.SetStatus (eReturnStatusSuccessFinishResult); 2796 else 2797 result.SetStatus (eReturnStatusFailed); 2798 } 2799 return result.Succeeded(); 2800 } 2801 protected: 2802 2803 CommandOptions m_options; 2804 }; 2805 2806 OptionDefinition 2807 CommandObjectTargetModulesLookup::CommandOptions::g_option_table[] = 2808 { 2809 { LLDB_OPT_SET_1, true, "address", 'a', required_argument, NULL, 0, eArgTypeAddress, "Lookup an address in one or more target modules."}, 2810 { LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "When looking up an address subtract <offset> from any addresses before doing the lookup."}, 2811 { LLDB_OPT_SET_2, true, "symbol", 's', required_argument, NULL, 0, eArgTypeSymbol, "Lookup a symbol by name in the symbol tables in one or more target modules."}, 2812 { LLDB_OPT_SET_2, false, "regex", 'r', no_argument, NULL, 0, eArgTypeNone, "The <name> argument for name lookups are regular expressions."}, 2813 { LLDB_OPT_SET_3, true, "file", 'f', required_argument, NULL, 0, eArgTypeFilename, "Lookup a file by fullpath or basename in one or more target modules."}, 2814 { LLDB_OPT_SET_3, false, "line", 'l', required_argument, NULL, 0, eArgTypeLineNum, "Lookup a line number in a file (must be used in conjunction with --file)."}, 2815 { LLDB_OPT_SET_3, false, "no-inlines", 'i', no_argument, NULL, 0, eArgTypeNone, "Check inline line entries (must be used in conjunction with --file)."}, 2816 { LLDB_OPT_SET_4, true, "function", 'n', required_argument, NULL, 0, eArgTypeFunctionName, "Lookup a function by name in the debug symbols in one or more target modules."}, 2817 { LLDB_OPT_SET_5, true, "type", 't', required_argument, NULL, 0, eArgTypeName, "Lookup a type by name in the debug symbols in one or more target modules."}, 2818 { LLDB_OPT_SET_ALL, false, "verbose", 'v', no_argument, NULL, 0, eArgTypeNone, "Enable verbose lookup information."}, 2819 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 2820 }; 2821 2822 2823 #pragma mark CommandObjectMultiwordImageSearchPaths 2824 2825 //------------------------------------------------------------------------- 2826 // CommandObjectMultiwordImageSearchPaths 2827 //------------------------------------------------------------------------- 2828 2829 class CommandObjectTargetModulesImageSearchPaths : public CommandObjectMultiword 2830 { 2831 public: 2832 2833 CommandObjectTargetModulesImageSearchPaths (CommandInterpreter &interpreter) : 2834 CommandObjectMultiword (interpreter, 2835 "target modules search-paths", 2836 "A set of commands for operating on debugger target image search paths.", 2837 "target modules search-paths <subcommand> [<subcommand-options>]") 2838 { 2839 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTargetModulesSearchPathsAdd (interpreter))); 2840 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTargetModulesSearchPathsClear (interpreter))); 2841 LoadSubCommand ("insert", CommandObjectSP (new CommandObjectTargetModulesSearchPathsInsert (interpreter))); 2842 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTargetModulesSearchPathsList (interpreter))); 2843 LoadSubCommand ("query", CommandObjectSP (new CommandObjectTargetModulesSearchPathsQuery (interpreter))); 2844 } 2845 2846 ~CommandObjectTargetModulesImageSearchPaths() 2847 { 2848 } 2849 }; 2850 2851 2852 2853 #pragma mark CommandObjectTargetModules 2854 2855 //------------------------------------------------------------------------- 2856 // CommandObjectTargetModules 2857 //------------------------------------------------------------------------- 2858 2859 class CommandObjectTargetModules : public CommandObjectMultiword 2860 { 2861 public: 2862 //------------------------------------------------------------------ 2863 // Constructors and Destructors 2864 //------------------------------------------------------------------ 2865 CommandObjectTargetModules(CommandInterpreter &interpreter) : 2866 CommandObjectMultiword (interpreter, 2867 "target modules", 2868 "A set of commands for accessing information for one or more target modules.", 2869 "target modules <sub-command> ...") 2870 { 2871 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTargetModulesAdd (interpreter))); 2872 LoadSubCommand ("load", CommandObjectSP (new CommandObjectTargetModulesLoad (interpreter))); 2873 //LoadSubCommand ("unload", CommandObjectSP (new CommandObjectTargetModulesUnload (interpreter))); 2874 LoadSubCommand ("dump", CommandObjectSP (new CommandObjectTargetModulesDump (interpreter))); 2875 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTargetModulesList (interpreter))); 2876 LoadSubCommand ("lookup", CommandObjectSP (new CommandObjectTargetModulesLookup (interpreter))); 2877 LoadSubCommand ("search-paths", CommandObjectSP (new CommandObjectTargetModulesImageSearchPaths (interpreter))); 2878 2879 } 2880 virtual 2881 ~CommandObjectTargetModules() 2882 { 2883 } 2884 2885 private: 2886 //------------------------------------------------------------------ 2887 // For CommandObjectTargetModules only 2888 //------------------------------------------------------------------ 2889 DISALLOW_COPY_AND_ASSIGN (CommandObjectTargetModules); 2890 }; 2891 2892 2893 #pragma mark CommandObjectTargetStopHookAdd 2894 2895 //------------------------------------------------------------------------- 2896 // CommandObjectTargetStopHookAdd 2897 //------------------------------------------------------------------------- 2898 2899 class CommandObjectTargetStopHookAdd : public CommandObject 2900 { 2901 public: 2902 2903 class CommandOptions : public Options 2904 { 2905 public: 2906 CommandOptions (CommandInterpreter &interpreter) : 2907 Options(interpreter), 2908 m_line_start(0), 2909 m_line_end (UINT_MAX), 2910 m_func_name_type_mask (eFunctionNameTypeAuto), 2911 m_sym_ctx_specified (false), 2912 m_thread_specified (false), 2913 m_use_one_liner (false), 2914 m_one_liner() 2915 { 2916 } 2917 2918 ~CommandOptions () {} 2919 2920 const OptionDefinition* 2921 GetDefinitions () 2922 { 2923 return g_option_table; 2924 } 2925 2926 virtual Error 2927 SetOptionValue (uint32_t option_idx, const char *option_arg) 2928 { 2929 Error error; 2930 char short_option = (char) m_getopt_table[option_idx].val; 2931 bool success; 2932 2933 switch (short_option) 2934 { 2935 case 'c': 2936 m_class_name = option_arg; 2937 m_sym_ctx_specified = true; 2938 break; 2939 2940 case 'e': 2941 m_line_end = Args::StringToUInt32 (option_arg, UINT_MAX, 0, &success); 2942 if (!success) 2943 { 2944 error.SetErrorStringWithFormat ("Invalid end line number: \"%s\".", option_arg); 2945 break; 2946 } 2947 m_sym_ctx_specified = true; 2948 break; 2949 2950 case 'l': 2951 m_line_start = Args::StringToUInt32 (option_arg, 0, 0, &success); 2952 if (!success) 2953 { 2954 error.SetErrorStringWithFormat ("Invalid start line number: \"%s\".", option_arg); 2955 break; 2956 } 2957 m_sym_ctx_specified = true; 2958 break; 2959 2960 case 'n': 2961 m_function_name = option_arg; 2962 m_func_name_type_mask |= eFunctionNameTypeAuto; 2963 m_sym_ctx_specified = true; 2964 break; 2965 2966 case 'f': 2967 m_file_name = option_arg; 2968 m_sym_ctx_specified = true; 2969 break; 2970 case 's': 2971 m_module_name = option_arg; 2972 m_sym_ctx_specified = true; 2973 break; 2974 case 't' : 2975 { 2976 m_thread_id = Args::StringToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0); 2977 if (m_thread_id == LLDB_INVALID_THREAD_ID) 2978 error.SetErrorStringWithFormat ("Invalid thread id string '%s'.\n", option_arg); 2979 m_thread_specified = true; 2980 } 2981 break; 2982 case 'T': 2983 m_thread_name = option_arg; 2984 m_thread_specified = true; 2985 break; 2986 case 'q': 2987 m_queue_name = option_arg; 2988 m_thread_specified = true; 2989 break; 2990 case 'x': 2991 { 2992 m_thread_index = Args::StringToUInt32(option_arg, UINT32_MAX, 0); 2993 if (m_thread_id == UINT32_MAX) 2994 error.SetErrorStringWithFormat ("Invalid thread index string '%s'.\n", option_arg); 2995 m_thread_specified = true; 2996 } 2997 break; 2998 case 'o': 2999 m_use_one_liner = true; 3000 m_one_liner = option_arg; 3001 break; 3002 default: 3003 error.SetErrorStringWithFormat ("Unrecognized option %c."); 3004 break; 3005 } 3006 return error; 3007 } 3008 3009 void 3010 OptionParsingStarting () 3011 { 3012 m_class_name.clear(); 3013 m_function_name.clear(); 3014 m_line_start = 0; 3015 m_line_end = UINT_MAX; 3016 m_file_name.clear(); 3017 m_module_name.clear(); 3018 m_func_name_type_mask = eFunctionNameTypeAuto; 3019 m_thread_id = LLDB_INVALID_THREAD_ID; 3020 m_thread_index = UINT32_MAX; 3021 m_thread_name.clear(); 3022 m_queue_name.clear(); 3023 3024 m_sym_ctx_specified = false; 3025 m_thread_specified = false; 3026 3027 m_use_one_liner = false; 3028 m_one_liner.clear(); 3029 } 3030 3031 3032 static OptionDefinition g_option_table[]; 3033 3034 std::string m_class_name; 3035 std::string m_function_name; 3036 uint32_t m_line_start; 3037 uint32_t m_line_end; 3038 std::string m_file_name; 3039 std::string m_module_name; 3040 uint32_t m_func_name_type_mask; // A pick from lldb::FunctionNameType. 3041 lldb::tid_t m_thread_id; 3042 uint32_t m_thread_index; 3043 std::string m_thread_name; 3044 std::string m_queue_name; 3045 bool m_sym_ctx_specified; 3046 bool m_thread_specified; 3047 // Instance variables to hold the values for one_liner options. 3048 bool m_use_one_liner; 3049 std::string m_one_liner; 3050 }; 3051 3052 Options * 3053 GetOptions () 3054 { 3055 return &m_options; 3056 } 3057 3058 CommandObjectTargetStopHookAdd (CommandInterpreter &interpreter) : 3059 CommandObject (interpreter, 3060 "target stop-hook add ", 3061 "Add a hook to be executed when the target stops.", 3062 "target stop-hook add"), 3063 m_options (interpreter) 3064 { 3065 } 3066 3067 ~CommandObjectTargetStopHookAdd () 3068 { 3069 } 3070 3071 static size_t 3072 ReadCommandsCallbackFunction (void *baton, 3073 InputReader &reader, 3074 lldb::InputReaderAction notification, 3075 const char *bytes, 3076 size_t bytes_len) 3077 { 3078 File &out_file = reader.GetDebugger().GetOutputFile(); 3079 Target::StopHook *new_stop_hook = ((Target::StopHook *) baton); 3080 static bool got_interrupted; 3081 3082 switch (notification) 3083 { 3084 case eInputReaderActivate: 3085 out_file.Printf ("%s\n", "Enter your stop hook command(s). Type 'DONE' to end."); 3086 if (reader.GetPrompt()) 3087 out_file.Printf ("%s", reader.GetPrompt()); 3088 out_file.Flush(); 3089 got_interrupted = false; 3090 break; 3091 3092 case eInputReaderDeactivate: 3093 break; 3094 3095 case eInputReaderReactivate: 3096 if (reader.GetPrompt()) 3097 { 3098 out_file.Printf ("%s", reader.GetPrompt()); 3099 out_file.Flush(); 3100 } 3101 got_interrupted = false; 3102 break; 3103 3104 case eInputReaderAsynchronousOutputWritten: 3105 break; 3106 3107 case eInputReaderGotToken: 3108 if (bytes && bytes_len && baton) 3109 { 3110 StringList *commands = new_stop_hook->GetCommandPointer(); 3111 if (commands) 3112 { 3113 commands->AppendString (bytes, bytes_len); 3114 } 3115 } 3116 if (!reader.IsDone() && reader.GetPrompt()) 3117 { 3118 out_file.Printf ("%s", reader.GetPrompt()); 3119 out_file.Flush(); 3120 } 3121 break; 3122 3123 case eInputReaderInterrupt: 3124 { 3125 // Finish, and cancel the stop hook. 3126 new_stop_hook->GetTarget()->RemoveStopHookByID(new_stop_hook->GetID()); 3127 out_file.Printf ("Stop hook cancelled.\n"); 3128 3129 reader.SetIsDone (true); 3130 } 3131 got_interrupted = true; 3132 break; 3133 3134 case eInputReaderEndOfFile: 3135 reader.SetIsDone (true); 3136 break; 3137 3138 case eInputReaderDone: 3139 if (!got_interrupted) 3140 out_file.Printf ("Stop hook #%d added.\n", new_stop_hook->GetID()); 3141 break; 3142 } 3143 3144 return bytes_len; 3145 } 3146 3147 bool 3148 Execute (Args& command, 3149 CommandReturnObject &result) 3150 { 3151 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 3152 if (target) 3153 { 3154 Target::StopHookSP new_hook_sp; 3155 target->AddStopHook (new_hook_sp); 3156 3157 // First step, make the specifier. 3158 std::auto_ptr<SymbolContextSpecifier> specifier_ap; 3159 if (m_options.m_sym_ctx_specified) 3160 { 3161 specifier_ap.reset(new SymbolContextSpecifier(m_interpreter.GetDebugger().GetSelectedTarget())); 3162 3163 if (!m_options.m_module_name.empty()) 3164 { 3165 specifier_ap->AddSpecification (m_options.m_module_name.c_str(), SymbolContextSpecifier::eModuleSpecified); 3166 } 3167 3168 if (!m_options.m_class_name.empty()) 3169 { 3170 specifier_ap->AddSpecification (m_options.m_class_name.c_str(), SymbolContextSpecifier::eClassOrNamespaceSpecified); 3171 } 3172 3173 if (!m_options.m_file_name.empty()) 3174 { 3175 specifier_ap->AddSpecification (m_options.m_file_name.c_str(), SymbolContextSpecifier::eFileSpecified); 3176 } 3177 3178 if (m_options.m_line_start != 0) 3179 { 3180 specifier_ap->AddLineSpecification (m_options.m_line_start, SymbolContextSpecifier::eLineStartSpecified); 3181 } 3182 3183 if (m_options.m_line_end != UINT_MAX) 3184 { 3185 specifier_ap->AddLineSpecification (m_options.m_line_end, SymbolContextSpecifier::eLineEndSpecified); 3186 } 3187 3188 if (!m_options.m_function_name.empty()) 3189 { 3190 specifier_ap->AddSpecification (m_options.m_function_name.c_str(), SymbolContextSpecifier::eFunctionSpecified); 3191 } 3192 } 3193 3194 if (specifier_ap.get()) 3195 new_hook_sp->SetSpecifier (specifier_ap.release()); 3196 3197 // Next see if any of the thread options have been entered: 3198 3199 if (m_options.m_thread_specified) 3200 { 3201 ThreadSpec *thread_spec = new ThreadSpec(); 3202 3203 if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID) 3204 { 3205 thread_spec->SetTID (m_options.m_thread_id); 3206 } 3207 3208 if (m_options.m_thread_index != UINT32_MAX) 3209 thread_spec->SetIndex (m_options.m_thread_index); 3210 3211 if (!m_options.m_thread_name.empty()) 3212 thread_spec->SetName (m_options.m_thread_name.c_str()); 3213 3214 if (!m_options.m_queue_name.empty()) 3215 thread_spec->SetQueueName (m_options.m_queue_name.c_str()); 3216 3217 new_hook_sp->SetThreadSpecifier (thread_spec); 3218 3219 } 3220 if (m_options.m_use_one_liner) 3221 { 3222 // Use one-liner. 3223 new_hook_sp->GetCommandPointer()->AppendString (m_options.m_one_liner.c_str()); 3224 result.AppendMessageWithFormat("Stop hook #%d added.\n", new_hook_sp->GetID()); 3225 } 3226 else 3227 { 3228 // Otherwise gather up the command list, we'll push an input reader and suck the data from that directly into 3229 // the new stop hook's command string. 3230 InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger())); 3231 if (!reader_sp) 3232 { 3233 result.AppendError("out of memory\n"); 3234 result.SetStatus (eReturnStatusFailed); 3235 target->RemoveStopHookByID (new_hook_sp->GetID()); 3236 return false; 3237 } 3238 3239 Error err (reader_sp->Initialize (CommandObjectTargetStopHookAdd::ReadCommandsCallbackFunction, 3240 new_hook_sp.get(), // baton 3241 eInputReaderGranularityLine, // token size, to pass to callback function 3242 "DONE", // end token 3243 "> ", // prompt 3244 true)); // echo input 3245 if (!err.Success()) 3246 { 3247 result.AppendError (err.AsCString()); 3248 result.SetStatus (eReturnStatusFailed); 3249 target->RemoveStopHookByID (new_hook_sp->GetID()); 3250 return false; 3251 } 3252 m_interpreter.GetDebugger().PushInputReader (reader_sp); 3253 } 3254 result.SetStatus (eReturnStatusSuccessFinishNoResult); 3255 } 3256 else 3257 { 3258 result.AppendError ("invalid target\n"); 3259 result.SetStatus (eReturnStatusFailed); 3260 } 3261 3262 return result.Succeeded(); 3263 } 3264 private: 3265 CommandOptions m_options; 3266 }; 3267 3268 OptionDefinition 3269 CommandObjectTargetStopHookAdd::CommandOptions::g_option_table[] = 3270 { 3271 { LLDB_OPT_SET_ALL, false, "one-liner", 'o', required_argument, NULL, NULL, eArgTypeOneLiner, 3272 "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." }, 3273 { LLDB_OPT_SET_ALL, false, "shlib", 's', required_argument, NULL, CommandCompletions::eModuleCompletion, eArgTypeShlibName, 3274 "Set the module within which the stop-hook is to be run."}, 3275 { LLDB_OPT_SET_ALL, false, "thread-index", 'x', required_argument, NULL, NULL, eArgTypeThreadIndex, 3276 "The stop hook is run only for the thread whose index matches this argument."}, 3277 { LLDB_OPT_SET_ALL, false, "thread-id", 't', required_argument, NULL, NULL, eArgTypeThreadID, 3278 "The stop hook is run only for the thread whose TID matches this argument."}, 3279 { LLDB_OPT_SET_ALL, false, "thread-name", 'T', required_argument, NULL, NULL, eArgTypeThreadName, 3280 "The stop hook is run only for the thread whose thread name matches this argument."}, 3281 { LLDB_OPT_SET_ALL, false, "queue-name", 'q', required_argument, NULL, NULL, eArgTypeQueueName, 3282 "The stop hook is run only for threads in the queue whose name is given by this argument."}, 3283 { LLDB_OPT_SET_1, false, "file", 'f', required_argument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, 3284 "Specify the source file within which the stop-hook is to be run." }, 3285 { LLDB_OPT_SET_1, false, "start-line", 'l', required_argument, NULL, 0, eArgTypeLineNum, 3286 "Set the start of the line range for which the stop-hook is to be run."}, 3287 { LLDB_OPT_SET_1, false, "end-line", 'e', required_argument, NULL, 0, eArgTypeLineNum, 3288 "Set the end of the line range for which the stop-hook is to be run."}, 3289 { LLDB_OPT_SET_2, false, "classname", 'c', required_argument, NULL, NULL, eArgTypeClassName, 3290 "Specify the class within which the stop-hook is to be run." }, 3291 { LLDB_OPT_SET_3, false, "name", 'n', required_argument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, 3292 "Set the function name within which the stop hook will be run." }, 3293 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 3294 }; 3295 3296 #pragma mark CommandObjectTargetStopHookDelete 3297 3298 //------------------------------------------------------------------------- 3299 // CommandObjectTargetStopHookDelete 3300 //------------------------------------------------------------------------- 3301 3302 class CommandObjectTargetStopHookDelete : public CommandObject 3303 { 3304 public: 3305 3306 CommandObjectTargetStopHookDelete (CommandInterpreter &interpreter) : 3307 CommandObject (interpreter, 3308 "target stop-hook delete [<id>]", 3309 "Delete a stop-hook.", 3310 "target stop-hook delete") 3311 { 3312 } 3313 3314 ~CommandObjectTargetStopHookDelete () 3315 { 3316 } 3317 3318 bool 3319 Execute (Args& command, 3320 CommandReturnObject &result) 3321 { 3322 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 3323 if (target) 3324 { 3325 // FIXME: see if we can use the breakpoint id style parser? 3326 size_t num_args = command.GetArgumentCount(); 3327 if (num_args == 0) 3328 { 3329 if (!m_interpreter.Confirm ("Delete all stop hooks?", true)) 3330 { 3331 result.SetStatus (eReturnStatusFailed); 3332 return false; 3333 } 3334 else 3335 { 3336 target->RemoveAllStopHooks(); 3337 } 3338 } 3339 else 3340 { 3341 bool success; 3342 for (size_t i = 0; i < num_args; i++) 3343 { 3344 lldb::user_id_t user_id = Args::StringToUInt32 (command.GetArgumentAtIndex(i), 0, 0, &success); 3345 if (!success) 3346 { 3347 result.AppendErrorWithFormat ("invalid stop hook id: \"%s\".\n", command.GetArgumentAtIndex(i)); 3348 result.SetStatus(eReturnStatusFailed); 3349 return false; 3350 } 3351 success = target->RemoveStopHookByID (user_id); 3352 if (!success) 3353 { 3354 result.AppendErrorWithFormat ("unknown stop hook id: \"%s\".\n", command.GetArgumentAtIndex(i)); 3355 result.SetStatus(eReturnStatusFailed); 3356 return false; 3357 } 3358 } 3359 } 3360 result.SetStatus (eReturnStatusSuccessFinishNoResult); 3361 } 3362 else 3363 { 3364 result.AppendError ("invalid target\n"); 3365 result.SetStatus (eReturnStatusFailed); 3366 } 3367 3368 return result.Succeeded(); 3369 } 3370 }; 3371 #pragma mark CommandObjectTargetStopHookEnableDisable 3372 3373 //------------------------------------------------------------------------- 3374 // CommandObjectTargetStopHookEnableDisable 3375 //------------------------------------------------------------------------- 3376 3377 class CommandObjectTargetStopHookEnableDisable : public CommandObject 3378 { 3379 public: 3380 3381 CommandObjectTargetStopHookEnableDisable (CommandInterpreter &interpreter, bool enable, const char *name, const char *help, const char *syntax) : 3382 CommandObject (interpreter, 3383 name, 3384 help, 3385 syntax), 3386 m_enable (enable) 3387 { 3388 } 3389 3390 ~CommandObjectTargetStopHookEnableDisable () 3391 { 3392 } 3393 3394 bool 3395 Execute (Args& command, 3396 CommandReturnObject &result) 3397 { 3398 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 3399 if (target) 3400 { 3401 // FIXME: see if we can use the breakpoint id style parser? 3402 size_t num_args = command.GetArgumentCount(); 3403 bool success; 3404 3405 if (num_args == 0) 3406 { 3407 target->SetAllStopHooksActiveState (m_enable); 3408 } 3409 else 3410 { 3411 for (size_t i = 0; i < num_args; i++) 3412 { 3413 lldb::user_id_t user_id = Args::StringToUInt32 (command.GetArgumentAtIndex(i), 0, 0, &success); 3414 if (!success) 3415 { 3416 result.AppendErrorWithFormat ("invalid stop hook id: \"%s\".\n", command.GetArgumentAtIndex(i)); 3417 result.SetStatus(eReturnStatusFailed); 3418 return false; 3419 } 3420 success = target->SetStopHookActiveStateByID (user_id, m_enable); 3421 if (!success) 3422 { 3423 result.AppendErrorWithFormat ("unknown stop hook id: \"%s\".\n", command.GetArgumentAtIndex(i)); 3424 result.SetStatus(eReturnStatusFailed); 3425 return false; 3426 } 3427 } 3428 } 3429 result.SetStatus (eReturnStatusSuccessFinishNoResult); 3430 } 3431 else 3432 { 3433 result.AppendError ("invalid target\n"); 3434 result.SetStatus (eReturnStatusFailed); 3435 } 3436 return result.Succeeded(); 3437 } 3438 private: 3439 bool m_enable; 3440 }; 3441 3442 #pragma mark CommandObjectTargetStopHookList 3443 3444 //------------------------------------------------------------------------- 3445 // CommandObjectTargetStopHookList 3446 //------------------------------------------------------------------------- 3447 3448 class CommandObjectTargetStopHookList : public CommandObject 3449 { 3450 public: 3451 3452 CommandObjectTargetStopHookList (CommandInterpreter &interpreter) : 3453 CommandObject (interpreter, 3454 "target stop-hook list [<type>]", 3455 "List all stop-hooks.", 3456 "target stop-hook list") 3457 { 3458 } 3459 3460 ~CommandObjectTargetStopHookList () 3461 { 3462 } 3463 3464 bool 3465 Execute (Args& command, 3466 CommandReturnObject &result) 3467 { 3468 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 3469 if (target) 3470 { 3471 bool notify = true; 3472 target->GetImageSearchPathList().Clear(notify); 3473 result.SetStatus (eReturnStatusSuccessFinishNoResult); 3474 } 3475 else 3476 { 3477 result.AppendError ("invalid target\n"); 3478 result.SetStatus (eReturnStatusFailed); 3479 } 3480 3481 size_t num_hooks = target->GetNumStopHooks (); 3482 if (num_hooks == 0) 3483 { 3484 result.GetOutputStream().PutCString ("No stop hooks.\n"); 3485 } 3486 else 3487 { 3488 for (size_t i = 0; i < num_hooks; i++) 3489 { 3490 Target::StopHookSP this_hook = target->GetStopHookAtIndex (i); 3491 if (i > 0) 3492 result.GetOutputStream().PutCString ("\n"); 3493 this_hook->GetDescription (&(result.GetOutputStream()), eDescriptionLevelFull); 3494 } 3495 } 3496 return result.Succeeded(); 3497 } 3498 }; 3499 3500 #pragma mark CommandObjectMultiwordTargetStopHooks 3501 //------------------------------------------------------------------------- 3502 // CommandObjectMultiwordTargetStopHooks 3503 //------------------------------------------------------------------------- 3504 3505 class CommandObjectMultiwordTargetStopHooks : public CommandObjectMultiword 3506 { 3507 public: 3508 3509 CommandObjectMultiwordTargetStopHooks (CommandInterpreter &interpreter) : 3510 CommandObjectMultiword (interpreter, 3511 "target stop-hook", 3512 "A set of commands for operating on debugger target stop-hooks.", 3513 "target stop-hook <subcommand> [<subcommand-options>]") 3514 { 3515 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTargetStopHookAdd (interpreter))); 3516 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTargetStopHookDelete (interpreter))); 3517 LoadSubCommand ("disable", CommandObjectSP (new CommandObjectTargetStopHookEnableDisable (interpreter, 3518 false, 3519 "target stop-hook disable [<id>]", 3520 "Disable a stop-hook.", 3521 "target stop-hook disable"))); 3522 LoadSubCommand ("enable", CommandObjectSP (new CommandObjectTargetStopHookEnableDisable (interpreter, 3523 true, 3524 "target stop-hook enable [<id>]", 3525 "Enable a stop-hook.", 3526 "target stop-hook enable"))); 3527 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTargetStopHookList (interpreter))); 3528 } 3529 3530 ~CommandObjectMultiwordTargetStopHooks() 3531 { 3532 } 3533 }; 3534 3535 3536 3537 #pragma mark CommandObjectMultiwordTarget 3538 3539 //------------------------------------------------------------------------- 3540 // CommandObjectMultiwordTarget 3541 //------------------------------------------------------------------------- 3542 3543 CommandObjectMultiwordTarget::CommandObjectMultiwordTarget (CommandInterpreter &interpreter) : 3544 CommandObjectMultiword (interpreter, 3545 "target", 3546 "A set of commands for operating on debugger targets.", 3547 "target <subcommand> [<subcommand-options>]") 3548 { 3549 3550 LoadSubCommand ("create", CommandObjectSP (new CommandObjectTargetCreate (interpreter))); 3551 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTargetList (interpreter))); 3552 LoadSubCommand ("select", CommandObjectSP (new CommandObjectTargetSelect (interpreter))); 3553 LoadSubCommand ("stop-hook", CommandObjectSP (new CommandObjectMultiwordTargetStopHooks (interpreter))); 3554 LoadSubCommand ("modules", CommandObjectSP (new CommandObjectTargetModules (interpreter))); 3555 } 3556 3557 CommandObjectMultiwordTarget::~CommandObjectMultiwordTarget () 3558 { 3559 } 3560 3561 3562