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/Timer.h" 22 #include "lldb/Interpreter/CommandInterpreter.h" 23 #include "lldb/Interpreter/CommandReturnObject.h" 24 #include "lldb/Target/Process.h" 25 #include "lldb/Target/StackFrame.h" 26 #include "lldb/Target/Thread.h" 27 #include "lldb/Target/ThreadSpec.h" 28 29 using namespace lldb; 30 using namespace lldb_private; 31 32 #pragma mark CommandObjectTargetImageSearchPaths 33 34 class CommandObjectTargetImageSearchPathsAdd : public CommandObject 35 { 36 public: 37 38 CommandObjectTargetImageSearchPathsAdd (CommandInterpreter &interpreter) : 39 CommandObject (interpreter, 40 "target image-search-paths add", 41 "Add new image search paths substitution pairs to the current target.", 42 NULL) 43 { 44 CommandArgumentEntry arg; 45 CommandArgumentData old_prefix_arg; 46 CommandArgumentData new_prefix_arg; 47 48 // Define the first variant of this arg pair. 49 old_prefix_arg.arg_type = eArgTypeOldPathPrefix; 50 old_prefix_arg.arg_repetition = eArgRepeatPairPlus; 51 52 // Define the first variant of this arg pair. 53 new_prefix_arg.arg_type = eArgTypeNewPathPrefix; 54 new_prefix_arg.arg_repetition = eArgRepeatPairPlus; 55 56 // There are two required arguments that must always occur together, i.e. an argument "pair". Because they 57 // must always occur together, they are treated as two variants of one argument rather than two independent 58 // arguments. Push them both into the first argument position for m_arguments... 59 60 arg.push_back (old_prefix_arg); 61 arg.push_back (new_prefix_arg); 62 63 m_arguments.push_back (arg); 64 } 65 66 ~CommandObjectTargetImageSearchPathsAdd () 67 { 68 } 69 70 bool 71 Execute (Args& command, 72 CommandReturnObject &result) 73 { 74 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 75 if (target) 76 { 77 uint32_t argc = command.GetArgumentCount(); 78 if (argc & 1) 79 { 80 result.AppendError ("add requires an even number of arguments"); 81 result.SetStatus (eReturnStatusFailed); 82 } 83 else 84 { 85 for (uint32_t i=0; i<argc; i+=2) 86 { 87 const char *from = command.GetArgumentAtIndex(i); 88 const char *to = command.GetArgumentAtIndex(i+1); 89 90 if (from[0] && to[0]) 91 { 92 bool last_pair = ((argc - i) == 2); 93 target->GetImageSearchPathList().Append (ConstString(from), 94 ConstString(to), 95 last_pair); // Notify if this is the last pair 96 result.SetStatus (eReturnStatusSuccessFinishNoResult); 97 } 98 else 99 { 100 if (from[0]) 101 result.AppendError ("<path-prefix> can't be empty"); 102 else 103 result.AppendError ("<new-path-prefix> can't be empty"); 104 result.SetStatus (eReturnStatusFailed); 105 } 106 } 107 } 108 } 109 else 110 { 111 result.AppendError ("invalid target"); 112 result.SetStatus (eReturnStatusFailed); 113 } 114 return result.Succeeded(); 115 } 116 }; 117 118 class CommandObjectTargetImageSearchPathsClear : public CommandObject 119 { 120 public: 121 122 CommandObjectTargetImageSearchPathsClear (CommandInterpreter &interpreter) : 123 CommandObject (interpreter, 124 "target image-search-paths clear", 125 "Clear all current image search path substitution pairs from the current target.", 126 "target image-search-paths clear") 127 { 128 } 129 130 ~CommandObjectTargetImageSearchPathsClear () 131 { 132 } 133 134 bool 135 Execute (Args& command, 136 CommandReturnObject &result) 137 { 138 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 139 if (target) 140 { 141 bool notify = true; 142 target->GetImageSearchPathList().Clear(notify); 143 result.SetStatus (eReturnStatusSuccessFinishNoResult); 144 } 145 else 146 { 147 result.AppendError ("invalid target"); 148 result.SetStatus (eReturnStatusFailed); 149 } 150 return result.Succeeded(); 151 } 152 }; 153 154 class CommandObjectTargetImageSearchPathsInsert : public CommandObject 155 { 156 public: 157 158 CommandObjectTargetImageSearchPathsInsert (CommandInterpreter &interpreter) : 159 CommandObject (interpreter, 160 "target image-search-paths insert", 161 "Insert a new image search path substitution pair into the current target at the specified index.", 162 NULL) 163 { 164 CommandArgumentEntry arg1; 165 CommandArgumentEntry arg2; 166 CommandArgumentData index_arg; 167 CommandArgumentData old_prefix_arg; 168 CommandArgumentData new_prefix_arg; 169 170 // Define the first and only variant of this arg. 171 index_arg.arg_type = eArgTypeIndex; 172 index_arg.arg_repetition = eArgRepeatPlain; 173 174 // Put the one and only variant into the first arg for m_arguments: 175 arg1.push_back (index_arg); 176 177 // Define the first variant of this arg pair. 178 old_prefix_arg.arg_type = eArgTypeOldPathPrefix; 179 old_prefix_arg.arg_repetition = eArgRepeatPairPlus; 180 181 // Define the first variant of this arg pair. 182 new_prefix_arg.arg_type = eArgTypeNewPathPrefix; 183 new_prefix_arg.arg_repetition = eArgRepeatPairPlus; 184 185 // There are two required arguments that must always occur together, i.e. an argument "pair". Because they 186 // must always occur together, they are treated as two variants of one argument rather than two independent 187 // arguments. Push them both into the same argument position for m_arguments... 188 189 arg2.push_back (old_prefix_arg); 190 arg2.push_back (new_prefix_arg); 191 192 // Add arguments to m_arguments. 193 m_arguments.push_back (arg1); 194 m_arguments.push_back (arg2); 195 } 196 197 ~CommandObjectTargetImageSearchPathsInsert () 198 { 199 } 200 201 bool 202 Execute (Args& command, 203 CommandReturnObject &result) 204 { 205 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 206 if (target) 207 { 208 uint32_t argc = command.GetArgumentCount(); 209 // check for at least 3 arguments and an odd nubmer of parameters 210 if (argc >= 3 && argc & 1) 211 { 212 bool success = false; 213 214 uint32_t insert_idx = Args::StringToUInt32(command.GetArgumentAtIndex(0), UINT32_MAX, 0, &success); 215 216 if (!success) 217 { 218 result.AppendErrorWithFormat("<index> parameter is not an integer: '%s'.\n", command.GetArgumentAtIndex(0)); 219 result.SetStatus (eReturnStatusFailed); 220 return result.Succeeded(); 221 } 222 223 // shift off the index 224 command.Shift(); 225 argc = command.GetArgumentCount(); 226 227 for (uint32_t i=0; i<argc; i+=2, ++insert_idx) 228 { 229 const char *from = command.GetArgumentAtIndex(i); 230 const char *to = command.GetArgumentAtIndex(i+1); 231 232 if (from[0] && to[0]) 233 { 234 bool last_pair = ((argc - i) == 2); 235 target->GetImageSearchPathList().Insert (ConstString(from), 236 ConstString(to), 237 insert_idx, 238 last_pair); 239 result.SetStatus (eReturnStatusSuccessFinishNoResult); 240 } 241 else 242 { 243 if (from[0]) 244 result.AppendError ("<path-prefix> can't be empty"); 245 else 246 result.AppendError ("<new-path-prefix> can't be empty"); 247 result.SetStatus (eReturnStatusFailed); 248 return false; 249 } 250 } 251 } 252 else 253 { 254 result.AppendError ("insert requires at least three arguments"); 255 result.SetStatus (eReturnStatusFailed); 256 return result.Succeeded(); 257 } 258 259 } 260 else 261 { 262 result.AppendError ("invalid target"); 263 result.SetStatus (eReturnStatusFailed); 264 } 265 return result.Succeeded(); 266 } 267 }; 268 269 class CommandObjectTargetImageSearchPathsList : public CommandObject 270 { 271 public: 272 273 CommandObjectTargetImageSearchPathsList (CommandInterpreter &interpreter) : 274 CommandObject (interpreter, 275 "target image-search-paths list", 276 "List all current image search path substitution pairs in the current target.", 277 "target image-search-paths list") 278 { 279 } 280 281 ~CommandObjectTargetImageSearchPathsList () 282 { 283 } 284 285 bool 286 Execute (Args& command, 287 CommandReturnObject &result) 288 { 289 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 290 if (target) 291 { 292 if (command.GetArgumentCount() != 0) 293 { 294 result.AppendError ("list takes no arguments"); 295 result.SetStatus (eReturnStatusFailed); 296 return result.Succeeded(); 297 } 298 299 target->GetImageSearchPathList().Dump(&result.GetOutputStream()); 300 result.SetStatus (eReturnStatusSuccessFinishResult); 301 } 302 else 303 { 304 result.AppendError ("invalid target"); 305 result.SetStatus (eReturnStatusFailed); 306 } 307 return result.Succeeded(); 308 } 309 }; 310 311 class CommandObjectTargetImageSearchPathsQuery : public CommandObject 312 { 313 public: 314 315 CommandObjectTargetImageSearchPathsQuery (CommandInterpreter &interpreter) : 316 CommandObject (interpreter, 317 "target image-search-paths query", 318 "Transform a path using the first applicable image search path.", 319 NULL) 320 { 321 CommandArgumentEntry arg; 322 CommandArgumentData path_arg; 323 324 // Define the first (and only) variant of this arg. 325 path_arg.arg_type = eArgTypePath; 326 path_arg.arg_repetition = eArgRepeatPlain; 327 328 // There is only one variant this argument could be; put it into the argument entry. 329 arg.push_back (path_arg); 330 331 // Push the data for the first argument into the m_arguments vector. 332 m_arguments.push_back (arg); 333 } 334 335 ~CommandObjectTargetImageSearchPathsQuery () 336 { 337 } 338 339 bool 340 Execute (Args& command, 341 CommandReturnObject &result) 342 { 343 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 344 if (target) 345 { 346 if (command.GetArgumentCount() != 1) 347 { 348 result.AppendError ("query requires one argument"); 349 result.SetStatus (eReturnStatusFailed); 350 return result.Succeeded(); 351 } 352 353 ConstString orig(command.GetArgumentAtIndex(0)); 354 ConstString transformed; 355 if (target->GetImageSearchPathList().RemapPath(orig, transformed)) 356 result.GetOutputStream().Printf("%s\n", transformed.GetCString()); 357 else 358 result.GetOutputStream().Printf("%s\n", orig.GetCString()); 359 360 result.SetStatus (eReturnStatusSuccessFinishResult); 361 } 362 else 363 { 364 result.AppendError ("invalid target"); 365 result.SetStatus (eReturnStatusFailed); 366 } 367 return result.Succeeded(); 368 } 369 }; 370 371 // TODO: implement the target select later when we start doing multiple targets 372 //#pragma mark CommandObjectTargetSelect 373 // 374 ////------------------------------------------------------------------------- 375 //// CommandObjectTargetSelect 376 ////------------------------------------------------------------------------- 377 // 378 //class CommandObjectTargetSelect : public CommandObject 379 //{ 380 //public: 381 // 382 // CommandObjectTargetSelect () : 383 // CommandObject (interpreter, 384 // frame select", 385 // "Select the current frame by index in the current thread.", 386 // "frame select <frame-index>") 387 // { 388 // } 389 // 390 // ~CommandObjectTargetSelect () 391 // { 392 // } 393 // 394 // bool 395 // Execute (Args& command, 396 // Debugger *context, 397 // CommandInterpreter &m_interpreter, 398 // CommandReturnObject &result) 399 // { 400 // ExecutionContext exe_ctx (context->GetExecutionContext()); 401 // if (exe_ctx.thread) 402 // { 403 // if (command.GetArgumentCount() == 1) 404 // { 405 // const char *frame_idx_cstr = command.GetArgumentAtIndex(0); 406 // 407 // const uint32_t num_frames = exe_ctx.thread->GetStackFrameCount(); 408 // const uint32_t frame_idx = Args::StringToUInt32 (frame_idx_cstr, UINT32_MAX, 0); 409 // if (frame_idx < num_frames) 410 // { 411 // exe_ctx.thread->SetSelectedFrameByIndex (frame_idx); 412 // exe_ctx.frame = exe_ctx.thread->GetSelectedFrame ().get(); 413 // 414 // if (exe_ctx.frame) 415 // { 416 // if (DisplayFrameForExecutionContext (exe_ctx.thread, 417 // exe_ctx.frame, 418 // m_interpreter, 419 // result.GetOutputStream(), 420 // true, 421 // true, 422 // 3, 423 // 3)) 424 // { 425 // result.SetStatus (eReturnStatusSuccessFinishResult); 426 // return result.Succeeded(); 427 // } 428 // } 429 // } 430 // if (frame_idx == UINT32_MAX) 431 // result.AppendErrorWithFormat ("Invalid frame index: %s.\n", frame_idx_cstr); 432 // else 433 // result.AppendErrorWithFormat ("Frame index (%u) out of range.\n", frame_idx); 434 // } 435 // else 436 // { 437 // result.AppendError ("invalid arguments"); 438 // result.AppendErrorWithFormat ("Usage: %s\n", m_cmd_syntax.c_str()); 439 // } 440 // } 441 // else 442 // { 443 // result.AppendError ("no current thread"); 444 // } 445 // result.SetStatus (eReturnStatusFailed); 446 // return false; 447 // } 448 //}; 449 450 451 #pragma mark CommandObjectMultiwordImageSearchPaths 452 453 //------------------------------------------------------------------------- 454 // CommandObjectMultiwordImageSearchPaths 455 //------------------------------------------------------------------------- 456 457 class CommandObjectMultiwordImageSearchPaths : public CommandObjectMultiword 458 { 459 public: 460 461 CommandObjectMultiwordImageSearchPaths (CommandInterpreter &interpreter) : 462 CommandObjectMultiword (interpreter, 463 "target image-search-paths", 464 "A set of commands for operating on debugger target image search paths.", 465 "target image-search-paths <subcommand> [<subcommand-options>]") 466 { 467 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTargetImageSearchPathsAdd (interpreter))); 468 LoadSubCommand ("clear", CommandObjectSP (new CommandObjectTargetImageSearchPathsClear (interpreter))); 469 LoadSubCommand ("insert", CommandObjectSP (new CommandObjectTargetImageSearchPathsInsert (interpreter))); 470 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTargetImageSearchPathsList (interpreter))); 471 LoadSubCommand ("query", CommandObjectSP (new CommandObjectTargetImageSearchPathsQuery (interpreter))); 472 } 473 474 ~CommandObjectMultiwordImageSearchPaths() 475 { 476 } 477 }; 478 479 #pragma mark CommandObjectTargetStopHookAdd 480 481 //------------------------------------------------------------------------- 482 // CommandObjectTargetStopHookAdd 483 //------------------------------------------------------------------------- 484 485 class CommandObjectTargetStopHookAdd : public CommandObject 486 { 487 public: 488 489 class CommandOptions : public Options 490 { 491 public: 492 CommandOptions () : 493 Options(), 494 m_line_start(0), 495 m_line_end (UINT_MAX), 496 m_func_name_type_mask (eFunctionNameTypeAuto), 497 m_sym_ctx_specified (false), 498 m_thread_specified (false) 499 { 500 } 501 502 ~CommandOptions () {} 503 504 const lldb::OptionDefinition* 505 GetDefinitions () 506 { 507 return g_option_table; 508 } 509 510 virtual Error 511 SetOptionValue (int option_idx, const char *option_arg) 512 { 513 Error error; 514 char short_option = (char) m_getopt_table[option_idx].val; 515 bool success; 516 517 switch (short_option) 518 { 519 case 'c': 520 m_class_name = option_arg; 521 m_sym_ctx_specified = true; 522 break; 523 524 case 'e': 525 m_line_end = Args::StringToUInt32 (option_arg, UINT_MAX, 0, &success); 526 if (!success) 527 { 528 error.SetErrorStringWithFormat ("Invalid end line number: \"%s\".", option_arg); 529 break; 530 } 531 m_sym_ctx_specified = true; 532 break; 533 534 case 'l': 535 m_line_start = Args::StringToUInt32 (option_arg, 0, 0, &success); 536 if (!success) 537 { 538 error.SetErrorStringWithFormat ("Invalid start line number: \"%s\".", option_arg); 539 break; 540 } 541 m_sym_ctx_specified = true; 542 break; 543 544 case 'n': 545 m_function_name = option_arg; 546 m_func_name_type_mask |= eFunctionNameTypeAuto; 547 m_sym_ctx_specified = true; 548 break; 549 550 case 'f': 551 m_file_name = option_arg; 552 m_sym_ctx_specified = true; 553 break; 554 case 's': 555 m_module_name = option_arg; 556 m_sym_ctx_specified = true; 557 break; 558 case 't' : 559 { 560 m_thread_id = Args::StringToUInt64(optarg, LLDB_INVALID_THREAD_ID, 0); 561 if (m_thread_id == LLDB_INVALID_THREAD_ID) 562 error.SetErrorStringWithFormat ("Invalid thread id string '%s'.\n", optarg); 563 m_thread_specified = true; 564 } 565 break; 566 case 'T': 567 m_thread_name = option_arg; 568 m_thread_specified = true; 569 break; 570 case 'q': 571 m_queue_name = option_arg; 572 m_thread_specified = true; 573 break; 574 case 'x': 575 { 576 m_thread_index = Args::StringToUInt32(optarg, UINT32_MAX, 0); 577 if (m_thread_id == UINT32_MAX) 578 error.SetErrorStringWithFormat ("Invalid thread index string '%s'.\n", optarg); 579 m_thread_specified = true; 580 } 581 break; 582 default: 583 error.SetErrorStringWithFormat ("Unrecognized option %c."); 584 break; 585 } 586 return error; 587 } 588 589 void 590 ResetOptionValues () 591 { 592 m_class_name.clear(); 593 m_function_name.clear(); 594 m_line_start = 0; 595 m_line_end = UINT_MAX; 596 m_file_name.clear(); 597 m_module_name.clear(); 598 m_func_name_type_mask = eFunctionNameTypeAuto; 599 m_thread_id = LLDB_INVALID_THREAD_ID; 600 m_thread_index = UINT32_MAX; 601 m_thread_name.clear(); 602 m_queue_name.clear(); 603 604 m_sym_ctx_specified = false; 605 m_thread_specified = false; 606 } 607 608 609 static lldb::OptionDefinition g_option_table[]; 610 611 std::string m_class_name; 612 std::string m_function_name; 613 uint32_t m_line_start; 614 uint32_t m_line_end; 615 std::string m_file_name; 616 std::string m_module_name; 617 uint32_t m_func_name_type_mask; // A pick from lldb::FunctionNameType. 618 lldb::tid_t m_thread_id; 619 uint32_t m_thread_index; 620 std::string m_thread_name; 621 std::string m_queue_name; 622 bool m_sym_ctx_specified; 623 bool m_thread_specified; 624 625 }; 626 627 Options * 628 GetOptions () 629 { 630 return &m_options; 631 } 632 633 CommandObjectTargetStopHookAdd (CommandInterpreter &interpreter) : 634 CommandObject (interpreter, 635 "target stop-hook add ", 636 "Add a hook to be executed when the target stops.", 637 "target stop-hook add") 638 { 639 } 640 641 ~CommandObjectTargetStopHookAdd () 642 { 643 } 644 645 static size_t 646 ReadCommandsCallbackFunction (void *baton, 647 InputReader &reader, 648 lldb::InputReaderAction notification, 649 const char *bytes, 650 size_t bytes_len) 651 { 652 File &out_file = reader.GetDebugger().GetOutputFile(); 653 Target::StopHook *new_stop_hook = ((Target::StopHook *) baton); 654 655 switch (notification) 656 { 657 case eInputReaderActivate: 658 out_file.Printf ("%s\n", "Enter your stop hook command(s). Type 'DONE' to end."); 659 if (reader.GetPrompt()) 660 out_file.Printf ("%s", reader.GetPrompt()); 661 out_file.Flush(); 662 break; 663 664 case eInputReaderDeactivate: 665 break; 666 667 case eInputReaderReactivate: 668 if (reader.GetPrompt()) 669 { 670 out_file.Printf ("%s", reader.GetPrompt()); 671 out_file.Flush(); 672 } 673 break; 674 675 case eInputReaderGotToken: 676 if (bytes && bytes_len && baton) 677 { 678 StringList *commands = new_stop_hook->GetCommandPointer(); 679 if (commands) 680 { 681 commands->AppendString (bytes, bytes_len); 682 } 683 } 684 if (!reader.IsDone() && reader.GetPrompt()) 685 { 686 out_file.Printf ("%s", reader.GetPrompt()); 687 out_file.Flush(); 688 } 689 break; 690 691 case eInputReaderInterrupt: 692 { 693 // Finish, and cancel the stop hook. 694 new_stop_hook->GetTarget()->RemoveStopHookByID(new_stop_hook->GetID()); 695 out_file.Printf ("Stop hook cancelled.\n"); 696 697 reader.SetIsDone (true); 698 } 699 break; 700 701 case eInputReaderEndOfFile: 702 reader.SetIsDone (true); 703 break; 704 705 case eInputReaderDone: 706 out_file.Printf ("Stop hook #%d added.\n", new_stop_hook->GetID()); 707 break; 708 } 709 710 return bytes_len; 711 } 712 713 bool 714 Execute (Args& command, 715 CommandReturnObject &result) 716 { 717 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 718 if (target) 719 { 720 Target::StopHookSP new_hook_sp; 721 target->AddStopHook (new_hook_sp); 722 723 // First step, make the specifier. 724 std::auto_ptr<SymbolContextSpecifier> specifier_ap; 725 if (m_options.m_sym_ctx_specified) 726 { 727 specifier_ap.reset(new SymbolContextSpecifier(m_interpreter.GetDebugger().GetSelectedTarget())); 728 729 if (!m_options.m_module_name.empty()) 730 { 731 specifier_ap->AddSpecification (m_options.m_module_name.c_str(), SymbolContextSpecifier::eModuleSpecified); 732 } 733 734 if (!m_options.m_class_name.empty()) 735 { 736 specifier_ap->AddSpecification (m_options.m_class_name.c_str(), SymbolContextSpecifier::eClassOrNamespaceSpecified); 737 } 738 739 if (!m_options.m_file_name.empty()) 740 { 741 specifier_ap->AddSpecification (m_options.m_file_name.c_str(), SymbolContextSpecifier::eFileSpecified); 742 } 743 744 if (m_options.m_line_start != 0) 745 { 746 specifier_ap->AddLineSpecification (m_options.m_line_start, SymbolContextSpecifier::eLineStartSpecified); 747 } 748 749 if (m_options.m_line_end != UINT_MAX) 750 { 751 specifier_ap->AddLineSpecification (m_options.m_line_end, SymbolContextSpecifier::eLineEndSpecified); 752 } 753 754 if (!m_options.m_function_name.empty()) 755 { 756 specifier_ap->AddSpecification (m_options.m_function_name.c_str(), SymbolContextSpecifier::eFunctionSpecified); 757 } 758 } 759 760 if (specifier_ap.get()) 761 new_hook_sp->SetSpecifier (specifier_ap.release()); 762 763 // Next see if any of the thread options have been entered: 764 765 if (m_options.m_thread_specified) 766 { 767 ThreadSpec *thread_spec = new ThreadSpec(); 768 769 if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID) 770 { 771 thread_spec->SetTID (m_options.m_thread_id); 772 } 773 774 if (m_options.m_thread_index != UINT32_MAX) 775 thread_spec->SetIndex (m_options.m_thread_index); 776 777 if (!m_options.m_thread_name.empty()) 778 thread_spec->SetName (m_options.m_thread_name.c_str()); 779 780 if (!m_options.m_queue_name.empty()) 781 thread_spec->SetQueueName (m_options.m_queue_name.c_str()); 782 783 new_hook_sp->SetThreadSpecifier (thread_spec); 784 785 } 786 // Next gather up the command list, we'll push an input reader and suck the data from that directly into 787 // the new stop hook's command string. 788 789 InputReaderSP reader_sp (new InputReader(m_interpreter.GetDebugger())); 790 if (!reader_sp) 791 { 792 result.AppendError("out of memory"); 793 result.SetStatus (eReturnStatusFailed); 794 target->RemoveStopHookByID (new_hook_sp->GetID()); 795 return false; 796 } 797 798 Error err (reader_sp->Initialize (CommandObjectTargetStopHookAdd::ReadCommandsCallbackFunction, 799 new_hook_sp.get(), // baton 800 eInputReaderGranularityLine, // token size, to pass to callback function 801 "DONE", // end token 802 "> ", // prompt 803 true)); // echo input 804 if (!err.Success()) 805 { 806 result.AppendError (err.AsCString()); 807 result.SetStatus (eReturnStatusFailed); 808 target->RemoveStopHookByID (new_hook_sp->GetID()); 809 return false; 810 } 811 m_interpreter.GetDebugger().PushInputReader (reader_sp); 812 813 result.SetStatus (eReturnStatusSuccessFinishNoResult); 814 } 815 else 816 { 817 result.AppendError ("invalid target"); 818 result.SetStatus (eReturnStatusFailed); 819 } 820 821 return result.Succeeded(); 822 } 823 private: 824 CommandOptions m_options; 825 }; 826 827 lldb::OptionDefinition 828 CommandObjectTargetStopHookAdd::CommandOptions::g_option_table[] = 829 { 830 { LLDB_OPT_SET_ALL, false, "shlib", 's', required_argument, NULL, CommandCompletions::eModuleCompletion, eArgTypeShlibName, 831 "Set the module within which the stop-hook is to be run."}, 832 { LLDB_OPT_SET_ALL, false, "thread-index", 'x', required_argument, NULL, NULL, eArgTypeThreadIndex, 833 "The stop hook is run only for the thread whose index matches this argument."}, 834 { LLDB_OPT_SET_ALL, false, "thread-id", 't', required_argument, NULL, NULL, eArgTypeThreadID, 835 "The stop hook is run only for the thread whose TID matches this argument."}, 836 { LLDB_OPT_SET_ALL, false, "thread-name", 'T', required_argument, NULL, NULL, eArgTypeThreadName, 837 "The stop hook is run only for the thread whose thread name matches this argument."}, 838 { LLDB_OPT_SET_ALL, false, "queue-name", 'q', required_argument, NULL, NULL, eArgTypeQueueName, 839 "The stop hook is run only for threads in the queue whose name is given by this argument."}, 840 { LLDB_OPT_SET_1, false, "file", 'f', required_argument, NULL, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, 841 "Specify the source file within which the stop-hook is to be run." }, 842 { LLDB_OPT_SET_1, false, "start-line", 'l', required_argument, NULL, 0, eArgTypeLineNum, 843 "Set the start of the line range for which the stop-hook is to be run."}, 844 { LLDB_OPT_SET_1, false, "end-line", 'e', required_argument, NULL, 0, eArgTypeLineNum, 845 "Set the end of the line range for which the stop-hook is to be run."}, 846 { LLDB_OPT_SET_2, false, "classname", 'c', required_argument, NULL, NULL, eArgTypeClassName, 847 "Specify the class within which the stop-hook is to be run." }, 848 { LLDB_OPT_SET_3, false, "name", 'n', required_argument, NULL, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, 849 "Set the function name within which the stop hook will be run." }, 850 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 851 }; 852 853 #pragma mark CommandObjectTargetStopHookDelete 854 855 //------------------------------------------------------------------------- 856 // CommandObjectTargetStopHookDelete 857 //------------------------------------------------------------------------- 858 859 class CommandObjectTargetStopHookDelete : public CommandObject 860 { 861 public: 862 863 CommandObjectTargetStopHookDelete (CommandInterpreter &interpreter) : 864 CommandObject (interpreter, 865 "target stop-hook delete [<id>]", 866 "Delete a stop-hook.", 867 "target stop-hook delete") 868 { 869 } 870 871 ~CommandObjectTargetStopHookDelete () 872 { 873 } 874 875 bool 876 Execute (Args& command, 877 CommandReturnObject &result) 878 { 879 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 880 if (target) 881 { 882 // FIXME: see if we can use the breakpoint id style parser? 883 size_t num_args = command.GetArgumentCount(); 884 if (num_args == 0) 885 { 886 if (!m_interpreter.Confirm ("Delete all stop hooks?", true)) 887 { 888 result.SetStatus (eReturnStatusFailed); 889 return false; 890 } 891 else 892 { 893 target->RemoveAllStopHooks(); 894 } 895 } 896 else 897 { 898 bool success; 899 for (size_t i = 0; i < num_args; i++) 900 { 901 lldb::user_id_t user_id = Args::StringToUInt32 (command.GetArgumentAtIndex(i), 0, 0, &success); 902 if (!success) 903 { 904 result.AppendErrorWithFormat ("invalid stop hook id: \"%s\".", command.GetArgumentAtIndex(i)); 905 result.SetStatus(eReturnStatusFailed); 906 return false; 907 } 908 success = target->RemoveStopHookByID (user_id); 909 if (!success) 910 { 911 result.AppendErrorWithFormat ("unknown stop hook id: \"%s\".", command.GetArgumentAtIndex(i)); 912 result.SetStatus(eReturnStatusFailed); 913 return false; 914 } 915 } 916 } 917 result.SetStatus (eReturnStatusSuccessFinishNoResult); 918 } 919 else 920 { 921 result.AppendError ("invalid target"); 922 result.SetStatus (eReturnStatusFailed); 923 } 924 925 return result.Succeeded(); 926 } 927 }; 928 #pragma mark CommandObjectTargetStopHookEnableDisable 929 930 //------------------------------------------------------------------------- 931 // CommandObjectTargetStopHookEnableDisable 932 //------------------------------------------------------------------------- 933 934 class CommandObjectTargetStopHookEnableDisable : public CommandObject 935 { 936 public: 937 938 CommandObjectTargetStopHookEnableDisable (CommandInterpreter &interpreter, bool enable, const char *name, const char *help, const char *syntax) : 939 CommandObject (interpreter, 940 name, 941 help, 942 syntax), 943 m_enable (enable) 944 { 945 } 946 947 ~CommandObjectTargetStopHookEnableDisable () 948 { 949 } 950 951 bool 952 Execute (Args& command, 953 CommandReturnObject &result) 954 { 955 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 956 if (target) 957 { 958 // FIXME: see if we can use the breakpoint id style parser? 959 size_t num_args = command.GetArgumentCount(); 960 bool success; 961 962 if (num_args == 0) 963 { 964 target->SetAllStopHooksActiveState (m_enable); 965 } 966 else 967 { 968 for (size_t i = 0; i < num_args; i++) 969 { 970 lldb::user_id_t user_id = Args::StringToUInt32 (command.GetArgumentAtIndex(i), 0, 0, &success); 971 if (!success) 972 { 973 result.AppendErrorWithFormat ("invalid stop hook id: \"%s\".", command.GetArgumentAtIndex(i)); 974 result.SetStatus(eReturnStatusFailed); 975 return false; 976 } 977 success = target->SetStopHookActiveStateByID (user_id, m_enable); 978 if (!success) 979 { 980 result.AppendErrorWithFormat ("unknown stop hook id: \"%s\".", command.GetArgumentAtIndex(i)); 981 result.SetStatus(eReturnStatusFailed); 982 return false; 983 } 984 } 985 } 986 result.SetStatus (eReturnStatusSuccessFinishNoResult); 987 } 988 else 989 { 990 result.AppendError ("invalid target"); 991 result.SetStatus (eReturnStatusFailed); 992 } 993 return result.Succeeded(); 994 } 995 private: 996 bool m_enable; 997 }; 998 999 #pragma mark CommandObjectTargetStopHookList 1000 1001 //------------------------------------------------------------------------- 1002 // CommandObjectTargetStopHookList 1003 //------------------------------------------------------------------------- 1004 1005 class CommandObjectTargetStopHookList : public CommandObject 1006 { 1007 public: 1008 1009 CommandObjectTargetStopHookList (CommandInterpreter &interpreter) : 1010 CommandObject (interpreter, 1011 "target stop-hook list [<type>]", 1012 "List all stop-hooks.", 1013 "target stop-hook list") 1014 { 1015 } 1016 1017 ~CommandObjectTargetStopHookList () 1018 { 1019 } 1020 1021 bool 1022 Execute (Args& command, 1023 CommandReturnObject &result) 1024 { 1025 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 1026 if (target) 1027 { 1028 bool notify = true; 1029 target->GetImageSearchPathList().Clear(notify); 1030 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1031 } 1032 else 1033 { 1034 result.AppendError ("invalid target"); 1035 result.SetStatus (eReturnStatusFailed); 1036 } 1037 1038 size_t num_hooks = target->GetNumStopHooks (); 1039 if (num_hooks == 0) 1040 { 1041 result.GetOutputStream().PutCString ("No stop hooks.\n"); 1042 } 1043 else 1044 { 1045 for (size_t i = 0; i < num_hooks; i++) 1046 { 1047 Target::StopHookSP this_hook = target->GetStopHookAtIndex (i); 1048 if (i > 0) 1049 result.GetOutputStream().PutCString ("\n"); 1050 this_hook->GetDescription (&(result.GetOutputStream()), eDescriptionLevelFull); 1051 } 1052 } 1053 return result.Succeeded(); 1054 } 1055 }; 1056 1057 #pragma mark CommandObjectMultiwordTargetStopHooks 1058 //------------------------------------------------------------------------- 1059 // CommandObjectMultiwordTargetStopHooks 1060 //------------------------------------------------------------------------- 1061 1062 class CommandObjectMultiwordTargetStopHooks : public CommandObjectMultiword 1063 { 1064 public: 1065 1066 CommandObjectMultiwordTargetStopHooks (CommandInterpreter &interpreter) : 1067 CommandObjectMultiword (interpreter, 1068 "target stop-hook", 1069 "A set of commands for operating on debugger target stop-hooks.", 1070 "target stop-hook <subcommand> [<subcommand-options>]") 1071 { 1072 LoadSubCommand ("add", CommandObjectSP (new CommandObjectTargetStopHookAdd (interpreter))); 1073 LoadSubCommand ("delete", CommandObjectSP (new CommandObjectTargetStopHookDelete (interpreter))); 1074 LoadSubCommand ("disable", CommandObjectSP (new CommandObjectTargetStopHookEnableDisable (interpreter, 1075 false, 1076 "target stop-hook disable [<id>]", 1077 "Disable a stop-hook.", 1078 "target stop-hook disable"))); 1079 LoadSubCommand ("enable", CommandObjectSP (new CommandObjectTargetStopHookEnableDisable (interpreter, 1080 true, 1081 "target stop-hook enable [<id>]", 1082 "Enable a stop-hook.", 1083 "target stop-hook enable"))); 1084 LoadSubCommand ("list", CommandObjectSP (new CommandObjectTargetStopHookList (interpreter))); 1085 } 1086 1087 ~CommandObjectMultiwordTargetStopHooks() 1088 { 1089 } 1090 }; 1091 1092 1093 1094 #pragma mark CommandObjectMultiwordTarget 1095 1096 //------------------------------------------------------------------------- 1097 // CommandObjectMultiwordTarget 1098 //------------------------------------------------------------------------- 1099 1100 CommandObjectMultiwordTarget::CommandObjectMultiwordTarget (CommandInterpreter &interpreter) : 1101 CommandObjectMultiword (interpreter, 1102 "target", 1103 "A set of commands for operating on debugger targets.", 1104 "target <subcommand> [<subcommand-options>]") 1105 { 1106 LoadSubCommand ("image-search-paths", CommandObjectSP (new CommandObjectMultiwordImageSearchPaths (interpreter))); 1107 LoadSubCommand ("stop-hook", CommandObjectSP (new CommandObjectMultiwordTargetStopHooks (interpreter))); 1108 } 1109 1110 CommandObjectMultiwordTarget::~CommandObjectMultiwordTarget () 1111 { 1112 } 1113 1114