1 //===-- CommandObjectWatchpoint.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 "lldb/lldb-python.h" 11 12 #include "CommandObjectWatchpoint.h" 13 #include "CommandObjectWatchpointCommand.h" 14 15 // C Includes 16 // C++ Includes 17 // Other libraries and framework includes 18 // Project includes 19 #include "lldb/Breakpoint/Watchpoint.h" 20 #include "lldb/Breakpoint/WatchpointList.h" 21 #include "lldb/Core/StreamString.h" 22 #include "lldb/Core/ValueObject.h" 23 #include "lldb/Core/ValueObjectVariable.h" 24 #include "lldb/Interpreter/CommandInterpreter.h" 25 #include "lldb/Interpreter/CommandReturnObject.h" 26 #include "lldb/Interpreter/CommandCompletions.h" 27 #include "lldb/Symbol/Variable.h" 28 #include "lldb/Symbol/VariableList.h" 29 #include "lldb/Target/Target.h" 30 31 #include <vector> 32 33 using namespace lldb; 34 using namespace lldb_private; 35 36 static void 37 AddWatchpointDescription(Stream *s, Watchpoint *wp, lldb::DescriptionLevel level) 38 { 39 s->IndentMore(); 40 wp->GetDescription(s, level); 41 s->IndentLess(); 42 s->EOL(); 43 } 44 45 static bool 46 CheckTargetForWatchpointOperations(Target *target, CommandReturnObject &result) 47 { 48 if (target == NULL) 49 { 50 result.AppendError ("Invalid target. No existing target or watchpoints."); 51 result.SetStatus (eReturnStatusFailed); 52 return false; 53 } 54 bool process_is_valid = target->GetProcessSP() && target->GetProcessSP()->IsAlive(); 55 if (!process_is_valid) 56 { 57 result.AppendError ("Thre's no process or it is not alive."); 58 result.SetStatus (eReturnStatusFailed); 59 return false; 60 } 61 // Target passes our checks, return true. 62 return true; 63 } 64 65 // FIXME: This doesn't seem to be the right place for this functionality. 66 #include "llvm/ADT/StringRef.h" 67 static inline void StripLeadingSpaces(llvm::StringRef &Str) 68 { 69 while (!Str.empty() && isspace(Str[0])) 70 Str = Str.substr(1); 71 } 72 73 // Equivalent class: {"-", "to", "To", "TO"} of range specifier array. 74 static const char* RSA[4] = { "-", "to", "To", "TO" }; 75 76 // Return the index to RSA if found; otherwise -1 is returned. 77 static int32_t 78 WithRSAIndex(llvm::StringRef &Arg) 79 { 80 81 uint32_t i; 82 for (i = 0; i < 4; ++i) 83 if (Arg.find(RSA[i]) != llvm::StringRef::npos) 84 return i; 85 return -1; 86 } 87 88 // Return true if wp_ids is successfully populated with the watch ids. 89 // False otherwise. 90 bool 91 CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(Target *target, Args &args, std::vector<uint32_t> &wp_ids) 92 { 93 // Pre-condition: args.GetArgumentCount() > 0. 94 if (args.GetArgumentCount() == 0) 95 { 96 if (target == NULL) 97 return false; 98 WatchpointSP watch_sp = target->GetLastCreatedWatchpoint(); 99 if (watch_sp) 100 { 101 wp_ids.push_back(watch_sp->GetID()); 102 return true; 103 } 104 else 105 return false; 106 } 107 108 llvm::StringRef Minus("-"); 109 std::vector<llvm::StringRef> StrRefArgs; 110 std::pair<llvm::StringRef, llvm::StringRef> Pair; 111 size_t i; 112 int32_t idx; 113 // Go through the argments and make a canonical form of arg list containing 114 // only numbers with possible "-" in between. 115 for (i = 0; i < args.GetArgumentCount(); ++i) { 116 llvm::StringRef Arg(args.GetArgumentAtIndex(i)); 117 if ((idx = WithRSAIndex(Arg)) == -1) { 118 StrRefArgs.push_back(Arg); 119 continue; 120 } 121 // The Arg contains the range specifier, split it, then. 122 Pair = Arg.split(RSA[idx]); 123 if (!Pair.first.empty()) 124 StrRefArgs.push_back(Pair.first); 125 StrRefArgs.push_back(Minus); 126 if (!Pair.second.empty()) 127 StrRefArgs.push_back(Pair.second); 128 } 129 // Now process the canonical list and fill in the vector of uint32_t's. 130 // If there is any error, return false and the client should ignore wp_ids. 131 uint32_t beg, end, id; 132 size_t size = StrRefArgs.size(); 133 bool in_range = false; 134 for (i = 0; i < size; ++i) { 135 llvm::StringRef Arg = StrRefArgs[i]; 136 if (in_range) { 137 // Look for the 'end' of the range. Note StringRef::getAsInteger() 138 // returns true to signify error while parsing. 139 if (Arg.getAsInteger(0, end)) 140 return false; 141 // Found a range! Now append the elements. 142 for (id = beg; id <= end; ++id) 143 wp_ids.push_back(id); 144 in_range = false; 145 continue; 146 } 147 if (i < (size - 1) && StrRefArgs[i+1] == Minus) { 148 if (Arg.getAsInteger(0, beg)) 149 return false; 150 // Turn on the in_range flag, we are looking for end of range next. 151 ++i; in_range = true; 152 continue; 153 } 154 // Otherwise, we have a simple ID. Just append it. 155 if (Arg.getAsInteger(0, beg)) 156 return false; 157 wp_ids.push_back(beg); 158 } 159 // It is an error if after the loop, we're still in_range. 160 if (in_range) 161 return false; 162 163 return true; // Success! 164 } 165 166 //------------------------------------------------------------------------- 167 // CommandObjectWatchpointList 168 //------------------------------------------------------------------------- 169 #pragma mark List 170 171 class CommandObjectWatchpointList : public CommandObjectParsed 172 { 173 public: 174 CommandObjectWatchpointList (CommandInterpreter &interpreter) : 175 CommandObjectParsed (interpreter, 176 "watchpoint list", 177 "List all watchpoints at configurable levels of detail.", 178 NULL), 179 m_options(interpreter) 180 { 181 CommandArgumentEntry arg; 182 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); 183 // Add the entry for the first argument for this command to the object's arguments vector. 184 m_arguments.push_back(arg); 185 } 186 187 virtual 188 ~CommandObjectWatchpointList () {} 189 190 virtual Options * 191 GetOptions () 192 { 193 return &m_options; 194 } 195 196 class CommandOptions : public Options 197 { 198 public: 199 200 CommandOptions (CommandInterpreter &interpreter) : 201 Options(interpreter), 202 m_level(lldb::eDescriptionLevelBrief) // Watchpoint List defaults to brief descriptions 203 { 204 } 205 206 virtual 207 ~CommandOptions () {} 208 209 virtual Error 210 SetOptionValue (uint32_t option_idx, const char *option_arg) 211 { 212 Error error; 213 const int short_option = m_getopt_table[option_idx].val; 214 215 switch (short_option) 216 { 217 case 'b': 218 m_level = lldb::eDescriptionLevelBrief; 219 break; 220 case 'f': 221 m_level = lldb::eDescriptionLevelFull; 222 break; 223 case 'v': 224 m_level = lldb::eDescriptionLevelVerbose; 225 break; 226 default: 227 error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); 228 break; 229 } 230 231 return error; 232 } 233 234 void 235 OptionParsingStarting () 236 { 237 m_level = lldb::eDescriptionLevelFull; 238 } 239 240 const OptionDefinition * 241 GetDefinitions () 242 { 243 return g_option_table; 244 } 245 246 247 // Options table: Required for subclasses of Options. 248 249 static OptionDefinition g_option_table[]; 250 251 // Instance variables to hold the values for command options. 252 253 lldb::DescriptionLevel m_level; 254 }; 255 256 protected: 257 virtual bool 258 DoExecute (Args& command, CommandReturnObject &result) 259 { 260 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 261 if (target == NULL) 262 { 263 result.AppendError ("Invalid target. No current target or watchpoints."); 264 result.SetStatus (eReturnStatusSuccessFinishNoResult); 265 return true; 266 } 267 268 if (target->GetProcessSP() && target->GetProcessSP()->IsAlive()) 269 { 270 uint32_t num_supported_hardware_watchpoints; 271 Error error = target->GetProcessSP()->GetWatchpointSupportInfo(num_supported_hardware_watchpoints); 272 if (error.Success()) 273 result.AppendMessageWithFormat("Number of supported hardware watchpoints: %u\n", 274 num_supported_hardware_watchpoints); 275 } 276 277 const WatchpointList &watchpoints = target->GetWatchpointList(); 278 Mutex::Locker locker; 279 target->GetWatchpointList().GetListMutex(locker); 280 281 size_t num_watchpoints = watchpoints.GetSize(); 282 283 if (num_watchpoints == 0) 284 { 285 result.AppendMessage("No watchpoints currently set."); 286 result.SetStatus(eReturnStatusSuccessFinishNoResult); 287 return true; 288 } 289 290 Stream &output_stream = result.GetOutputStream(); 291 292 if (command.GetArgumentCount() == 0) 293 { 294 // No watchpoint selected; show info about all currently set watchpoints. 295 result.AppendMessage ("Current watchpoints:"); 296 for (size_t i = 0; i < num_watchpoints; ++i) 297 { 298 Watchpoint *wp = watchpoints.GetByIndex(i).get(); 299 AddWatchpointDescription(&output_stream, wp, m_options.m_level); 300 } 301 result.SetStatus(eReturnStatusSuccessFinishNoResult); 302 } 303 else 304 { 305 // Particular watchpoints selected; enable them. 306 std::vector<uint32_t> wp_ids; 307 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, wp_ids)) 308 { 309 result.AppendError("Invalid watchpoints specification."); 310 result.SetStatus(eReturnStatusFailed); 311 return false; 312 } 313 314 const size_t size = wp_ids.size(); 315 for (size_t i = 0; i < size; ++i) 316 { 317 Watchpoint *wp = watchpoints.FindByID(wp_ids[i]).get(); 318 if (wp) 319 AddWatchpointDescription(&output_stream, wp, m_options.m_level); 320 result.SetStatus(eReturnStatusSuccessFinishNoResult); 321 } 322 } 323 324 return result.Succeeded(); 325 } 326 327 private: 328 CommandOptions m_options; 329 }; 330 331 //------------------------------------------------------------------------- 332 // CommandObjectWatchpointList::Options 333 //------------------------------------------------------------------------- 334 #pragma mark List::CommandOptions 335 OptionDefinition 336 CommandObjectWatchpointList::CommandOptions::g_option_table[] = 337 { 338 { LLDB_OPT_SET_1, false, "brief", 'b', no_argument, NULL, 0, eArgTypeNone, 339 "Give a brief description of the watchpoint (no location info)."}, 340 341 { LLDB_OPT_SET_2, false, "full", 'f', no_argument, NULL, 0, eArgTypeNone, 342 "Give a full description of the watchpoint and its locations."}, 343 344 { LLDB_OPT_SET_3, false, "verbose", 'v', no_argument, NULL, 0, eArgTypeNone, 345 "Explain everything we know about the watchpoint (for debugging debugger bugs)." }, 346 347 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 348 }; 349 350 //------------------------------------------------------------------------- 351 // CommandObjectWatchpointEnable 352 //------------------------------------------------------------------------- 353 #pragma mark Enable 354 355 class CommandObjectWatchpointEnable : public CommandObjectParsed 356 { 357 public: 358 CommandObjectWatchpointEnable (CommandInterpreter &interpreter) : 359 CommandObjectParsed (interpreter, 360 "enable", 361 "Enable the specified disabled watchpoint(s). If no watchpoints are specified, enable all of them.", 362 NULL) 363 { 364 CommandArgumentEntry arg; 365 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); 366 // Add the entry for the first argument for this command to the object's arguments vector. 367 m_arguments.push_back(arg); 368 } 369 370 virtual 371 ~CommandObjectWatchpointEnable () {} 372 373 protected: 374 virtual bool 375 DoExecute (Args& command, 376 CommandReturnObject &result) 377 { 378 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 379 if (!CheckTargetForWatchpointOperations(target, result)) 380 return false; 381 382 Mutex::Locker locker; 383 target->GetWatchpointList().GetListMutex(locker); 384 385 const WatchpointList &watchpoints = target->GetWatchpointList(); 386 387 size_t num_watchpoints = watchpoints.GetSize(); 388 389 if (num_watchpoints == 0) 390 { 391 result.AppendError("No watchpoints exist to be enabled."); 392 result.SetStatus(eReturnStatusFailed); 393 return false; 394 } 395 396 if (command.GetArgumentCount() == 0) 397 { 398 // No watchpoint selected; enable all currently set watchpoints. 399 target->EnableAllWatchpoints(); 400 result.AppendMessageWithFormat("All watchpoints enabled. (%lu watchpoints)\n", num_watchpoints); 401 result.SetStatus(eReturnStatusSuccessFinishNoResult); 402 } 403 else 404 { 405 // Particular watchpoints selected; enable them. 406 std::vector<uint32_t> wp_ids; 407 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, wp_ids)) 408 { 409 result.AppendError("Invalid watchpoints specification."); 410 result.SetStatus(eReturnStatusFailed); 411 return false; 412 } 413 414 int count = 0; 415 const size_t size = wp_ids.size(); 416 for (size_t i = 0; i < size; ++i) 417 if (target->EnableWatchpointByID(wp_ids[i])) 418 ++count; 419 result.AppendMessageWithFormat("%d watchpoints enabled.\n", count); 420 result.SetStatus(eReturnStatusSuccessFinishNoResult); 421 } 422 423 return result.Succeeded(); 424 } 425 426 private: 427 }; 428 429 //------------------------------------------------------------------------- 430 // CommandObjectWatchpointDisable 431 //------------------------------------------------------------------------- 432 #pragma mark Disable 433 434 class CommandObjectWatchpointDisable : public CommandObjectParsed 435 { 436 public: 437 CommandObjectWatchpointDisable (CommandInterpreter &interpreter) : 438 CommandObjectParsed (interpreter, 439 "watchpoint disable", 440 "Disable the specified watchpoint(s) without removing it/them. If no watchpoints are specified, disable them all.", 441 NULL) 442 { 443 CommandArgumentEntry arg; 444 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); 445 // Add the entry for the first argument for this command to the object's arguments vector. 446 m_arguments.push_back(arg); 447 } 448 449 450 virtual 451 ~CommandObjectWatchpointDisable () {} 452 453 protected: 454 virtual bool 455 DoExecute (Args& command, CommandReturnObject &result) 456 { 457 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 458 if (!CheckTargetForWatchpointOperations(target, result)) 459 return false; 460 461 Mutex::Locker locker; 462 target->GetWatchpointList().GetListMutex(locker); 463 464 const WatchpointList &watchpoints = target->GetWatchpointList(); 465 size_t num_watchpoints = watchpoints.GetSize(); 466 467 if (num_watchpoints == 0) 468 { 469 result.AppendError("No watchpoints exist to be disabled."); 470 result.SetStatus(eReturnStatusFailed); 471 return false; 472 } 473 474 if (command.GetArgumentCount() == 0) 475 { 476 // No watchpoint selected; disable all currently set watchpoints. 477 if (target->DisableAllWatchpoints()) 478 { 479 result.AppendMessageWithFormat("All watchpoints disabled. (%lu watchpoints)\n", num_watchpoints); 480 result.SetStatus(eReturnStatusSuccessFinishNoResult); 481 } 482 else 483 { 484 result.AppendError("Disable all watchpoints failed\n"); 485 result.SetStatus(eReturnStatusFailed); 486 } 487 } 488 else 489 { 490 // Particular watchpoints selected; disable them. 491 std::vector<uint32_t> wp_ids; 492 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, wp_ids)) 493 { 494 result.AppendError("Invalid watchpoints specification."); 495 result.SetStatus(eReturnStatusFailed); 496 return false; 497 } 498 499 int count = 0; 500 const size_t size = wp_ids.size(); 501 for (size_t i = 0; i < size; ++i) 502 if (target->DisableWatchpointByID(wp_ids[i])) 503 ++count; 504 result.AppendMessageWithFormat("%d watchpoints disabled.\n", count); 505 result.SetStatus(eReturnStatusSuccessFinishNoResult); 506 } 507 508 return result.Succeeded(); 509 } 510 511 }; 512 513 //------------------------------------------------------------------------- 514 // CommandObjectWatchpointDelete 515 //------------------------------------------------------------------------- 516 #pragma mark Delete 517 518 class CommandObjectWatchpointDelete : public CommandObjectParsed 519 { 520 public: 521 CommandObjectWatchpointDelete (CommandInterpreter &interpreter) : 522 CommandObjectParsed(interpreter, 523 "watchpoint delete", 524 "Delete the specified watchpoint(s). If no watchpoints are specified, delete them all.", 525 NULL) 526 { 527 CommandArgumentEntry arg; 528 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); 529 // Add the entry for the first argument for this command to the object's arguments vector. 530 m_arguments.push_back(arg); 531 } 532 533 virtual 534 ~CommandObjectWatchpointDelete () {} 535 536 protected: 537 virtual bool 538 DoExecute (Args& command, CommandReturnObject &result) 539 { 540 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 541 if (!CheckTargetForWatchpointOperations(target, result)) 542 return false; 543 544 Mutex::Locker locker; 545 target->GetWatchpointList().GetListMutex(locker); 546 547 const WatchpointList &watchpoints = target->GetWatchpointList(); 548 549 size_t num_watchpoints = watchpoints.GetSize(); 550 551 if (num_watchpoints == 0) 552 { 553 result.AppendError("No watchpoints exist to be deleted."); 554 result.SetStatus(eReturnStatusFailed); 555 return false; 556 } 557 558 if (command.GetArgumentCount() == 0) 559 { 560 if (!m_interpreter.Confirm("About to delete all watchpoints, do you want to do that?", true)) 561 { 562 result.AppendMessage("Operation cancelled..."); 563 } 564 else 565 { 566 target->RemoveAllWatchpoints(); 567 result.AppendMessageWithFormat("All watchpoints removed. (%lu watchpoints)\n", num_watchpoints); 568 } 569 result.SetStatus (eReturnStatusSuccessFinishNoResult); 570 } 571 else 572 { 573 // Particular watchpoints selected; delete them. 574 std::vector<uint32_t> wp_ids; 575 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, wp_ids)) 576 { 577 result.AppendError("Invalid watchpoints specification."); 578 result.SetStatus(eReturnStatusFailed); 579 return false; 580 } 581 582 int count = 0; 583 const size_t size = wp_ids.size(); 584 for (size_t i = 0; i < size; ++i) 585 if (target->RemoveWatchpointByID(wp_ids[i])) 586 ++count; 587 result.AppendMessageWithFormat("%d watchpoints deleted.\n",count); 588 result.SetStatus (eReturnStatusSuccessFinishNoResult); 589 } 590 591 return result.Succeeded(); 592 } 593 594 }; 595 596 //------------------------------------------------------------------------- 597 // CommandObjectWatchpointIgnore 598 //------------------------------------------------------------------------- 599 600 class CommandObjectWatchpointIgnore : public CommandObjectParsed 601 { 602 public: 603 CommandObjectWatchpointIgnore (CommandInterpreter &interpreter) : 604 CommandObjectParsed (interpreter, 605 "watchpoint ignore", 606 "Set ignore count on the specified watchpoint(s). If no watchpoints are specified, set them all.", 607 NULL), 608 m_options (interpreter) 609 { 610 CommandArgumentEntry arg; 611 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); 612 // Add the entry for the first argument for this command to the object's arguments vector. 613 m_arguments.push_back(arg); 614 } 615 616 virtual 617 ~CommandObjectWatchpointIgnore () {} 618 619 virtual Options * 620 GetOptions () 621 { 622 return &m_options; 623 } 624 625 class CommandOptions : public Options 626 { 627 public: 628 629 CommandOptions (CommandInterpreter &interpreter) : 630 Options (interpreter), 631 m_ignore_count (0) 632 { 633 } 634 635 virtual 636 ~CommandOptions () {} 637 638 virtual Error 639 SetOptionValue (uint32_t option_idx, const char *option_arg) 640 { 641 Error error; 642 const int short_option = m_getopt_table[option_idx].val; 643 644 switch (short_option) 645 { 646 case 'i': 647 { 648 m_ignore_count = Args::StringToUInt32(option_arg, UINT32_MAX, 0); 649 if (m_ignore_count == UINT32_MAX) 650 error.SetErrorStringWithFormat ("invalid ignore count '%s'", option_arg); 651 } 652 break; 653 default: 654 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 655 break; 656 } 657 658 return error; 659 } 660 661 void 662 OptionParsingStarting () 663 { 664 m_ignore_count = 0; 665 } 666 667 const OptionDefinition * 668 GetDefinitions () 669 { 670 return g_option_table; 671 } 672 673 674 // Options table: Required for subclasses of Options. 675 676 static OptionDefinition g_option_table[]; 677 678 // Instance variables to hold the values for command options. 679 680 uint32_t m_ignore_count; 681 }; 682 683 protected: 684 virtual bool 685 DoExecute (Args& command, 686 CommandReturnObject &result) 687 { 688 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 689 if (!CheckTargetForWatchpointOperations(target, result)) 690 return false; 691 692 Mutex::Locker locker; 693 target->GetWatchpointList().GetListMutex(locker); 694 695 const WatchpointList &watchpoints = target->GetWatchpointList(); 696 697 size_t num_watchpoints = watchpoints.GetSize(); 698 699 if (num_watchpoints == 0) 700 { 701 result.AppendError("No watchpoints exist to be ignored."); 702 result.SetStatus(eReturnStatusFailed); 703 return false; 704 } 705 706 if (command.GetArgumentCount() == 0) 707 { 708 target->IgnoreAllWatchpoints(m_options.m_ignore_count); 709 result.AppendMessageWithFormat("All watchpoints ignored. (%lu watchpoints)\n", num_watchpoints); 710 result.SetStatus (eReturnStatusSuccessFinishNoResult); 711 } 712 else 713 { 714 // Particular watchpoints selected; ignore them. 715 std::vector<uint32_t> wp_ids; 716 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, wp_ids)) 717 { 718 result.AppendError("Invalid watchpoints specification."); 719 result.SetStatus(eReturnStatusFailed); 720 return false; 721 } 722 723 int count = 0; 724 const size_t size = wp_ids.size(); 725 for (size_t i = 0; i < size; ++i) 726 if (target->IgnoreWatchpointByID(wp_ids[i], m_options.m_ignore_count)) 727 ++count; 728 result.AppendMessageWithFormat("%d watchpoints ignored.\n",count); 729 result.SetStatus (eReturnStatusSuccessFinishNoResult); 730 } 731 732 return result.Succeeded(); 733 } 734 735 private: 736 CommandOptions m_options; 737 }; 738 739 #pragma mark Ignore::CommandOptions 740 OptionDefinition 741 CommandObjectWatchpointIgnore::CommandOptions::g_option_table[] = 742 { 743 { LLDB_OPT_SET_ALL, true, "ignore-count", 'i', required_argument, NULL, 0, eArgTypeCount, "Set the number of times this watchpoint is skipped before stopping." }, 744 { 0, false, NULL, 0 , 0, NULL, 0, eArgTypeNone, NULL } 745 }; 746 747 748 //------------------------------------------------------------------------- 749 // CommandObjectWatchpointModify 750 //------------------------------------------------------------------------- 751 #pragma mark Modify 752 753 class CommandObjectWatchpointModify : public CommandObjectParsed 754 { 755 public: 756 757 CommandObjectWatchpointModify (CommandInterpreter &interpreter) : 758 CommandObjectParsed (interpreter, 759 "watchpoint modify", 760 "Modify the options on a watchpoint or set of watchpoints in the executable. " 761 "If no watchpoint is specified, act on the last created watchpoint. " 762 "Passing an empty argument clears the modification.", 763 NULL), 764 m_options (interpreter) 765 { 766 CommandArgumentEntry arg; 767 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); 768 // Add the entry for the first argument for this command to the object's arguments vector. 769 m_arguments.push_back (arg); 770 } 771 772 virtual 773 ~CommandObjectWatchpointModify () {} 774 775 virtual Options * 776 GetOptions () 777 { 778 return &m_options; 779 } 780 781 class CommandOptions : public Options 782 { 783 public: 784 785 CommandOptions (CommandInterpreter &interpreter) : 786 Options (interpreter), 787 m_condition (), 788 m_condition_passed (false) 789 { 790 } 791 792 virtual 793 ~CommandOptions () {} 794 795 virtual Error 796 SetOptionValue (uint32_t option_idx, const char *option_arg) 797 { 798 Error error; 799 const int short_option = m_getopt_table[option_idx].val; 800 801 switch (short_option) 802 { 803 case 'c': 804 if (option_arg != NULL) 805 m_condition.assign (option_arg); 806 else 807 m_condition.clear(); 808 m_condition_passed = true; 809 break; 810 default: 811 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 812 break; 813 } 814 815 return error; 816 } 817 818 void 819 OptionParsingStarting () 820 { 821 m_condition.clear(); 822 m_condition_passed = false; 823 } 824 825 const OptionDefinition* 826 GetDefinitions () 827 { 828 return g_option_table; 829 } 830 831 // Options table: Required for subclasses of Options. 832 833 static OptionDefinition g_option_table[]; 834 835 // Instance variables to hold the values for command options. 836 837 std::string m_condition; 838 bool m_condition_passed; 839 }; 840 841 protected: 842 virtual bool 843 DoExecute (Args& command, CommandReturnObject &result) 844 { 845 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 846 if (!CheckTargetForWatchpointOperations(target, result)) 847 return false; 848 849 Mutex::Locker locker; 850 target->GetWatchpointList().GetListMutex(locker); 851 852 const WatchpointList &watchpoints = target->GetWatchpointList(); 853 854 size_t num_watchpoints = watchpoints.GetSize(); 855 856 if (num_watchpoints == 0) 857 { 858 result.AppendError("No watchpoints exist to be modified."); 859 result.SetStatus(eReturnStatusFailed); 860 return false; 861 } 862 863 if (command.GetArgumentCount() == 0) 864 { 865 WatchpointSP wp_sp = target->GetLastCreatedWatchpoint(); 866 wp_sp->SetCondition(m_options.m_condition.c_str()); 867 result.SetStatus (eReturnStatusSuccessFinishNoResult); 868 } 869 else 870 { 871 // Particular watchpoints selected; set condition on them. 872 std::vector<uint32_t> wp_ids; 873 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, wp_ids)) 874 { 875 result.AppendError("Invalid watchpoints specification."); 876 result.SetStatus(eReturnStatusFailed); 877 return false; 878 } 879 880 int count = 0; 881 const size_t size = wp_ids.size(); 882 for (size_t i = 0; i < size; ++i) 883 { 884 WatchpointSP wp_sp = watchpoints.FindByID(wp_ids[i]); 885 if (wp_sp) 886 { 887 wp_sp->SetCondition(m_options.m_condition.c_str()); 888 ++count; 889 } 890 } 891 result.AppendMessageWithFormat("%d watchpoints modified.\n",count); 892 result.SetStatus (eReturnStatusSuccessFinishNoResult); 893 } 894 895 return result.Succeeded(); 896 } 897 898 private: 899 CommandOptions m_options; 900 }; 901 902 #pragma mark Modify::CommandOptions 903 OptionDefinition 904 CommandObjectWatchpointModify::CommandOptions::g_option_table[] = 905 { 906 { LLDB_OPT_SET_ALL, false, "condition", 'c', required_argument, NULL, 0, eArgTypeExpression, "The watchpoint stops only if this condition expression evaluates to true."}, 907 { 0, false, NULL, 0 , 0, NULL, 0, eArgTypeNone, NULL } 908 }; 909 910 //------------------------------------------------------------------------- 911 // CommandObjectWatchpointSetVariable 912 //------------------------------------------------------------------------- 913 #pragma mark SetVariable 914 915 class CommandObjectWatchpointSetVariable : public CommandObjectParsed 916 { 917 public: 918 919 CommandObjectWatchpointSetVariable (CommandInterpreter &interpreter) : 920 CommandObjectParsed (interpreter, 921 "watchpoint set variable", 922 "Set a watchpoint on a variable. " 923 "Use the '-w' option to specify the type of watchpoint and " 924 "the '-x' option to specify the byte size to watch for. " 925 "If no '-w' option is specified, it defaults to write. " 926 "If no '-x' option is specified, it defaults to the variable's " 927 "byte size. " 928 "Note that there are limited hardware resources for watchpoints. " 929 "If watchpoint setting fails, consider disable/delete existing ones " 930 "to free up resources.", 931 NULL, 932 eFlagRequiresFrame | 933 eFlagTryTargetAPILock | 934 eFlagProcessMustBeLaunched | 935 eFlagProcessMustBePaused ), 936 m_option_group (interpreter), 937 m_option_watchpoint () 938 { 939 SetHelpLong( 940 "Examples: \n\ 941 \n\ 942 watchpoint set variable -w read_wriate my_global_var \n\ 943 # Watch my_global_var for read/write access, with the region to watch corresponding to the byte size of the data type.\n"); 944 945 CommandArgumentEntry arg; 946 CommandArgumentData var_name_arg; 947 948 // Define the only variant of this arg. 949 var_name_arg.arg_type = eArgTypeVarName; 950 var_name_arg.arg_repetition = eArgRepeatPlain; 951 952 // Push the variant into the argument entry. 953 arg.push_back (var_name_arg); 954 955 // Push the data for the only argument into the m_arguments vector. 956 m_arguments.push_back (arg); 957 958 // Absorb the '-w' and '-x' options into our option group. 959 m_option_group.Append (&m_option_watchpoint, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 960 m_option_group.Finalize(); 961 } 962 963 virtual 964 ~CommandObjectWatchpointSetVariable () {} 965 966 virtual Options * 967 GetOptions () 968 { 969 return &m_option_group; 970 } 971 972 protected: 973 static size_t GetVariableCallback (void *baton, 974 const char *name, 975 VariableList &variable_list) 976 { 977 Target *target = static_cast<Target *>(baton); 978 if (target) 979 { 980 return target->GetImages().FindGlobalVariables (ConstString(name), 981 true, 982 UINT32_MAX, 983 variable_list); 984 } 985 return 0; 986 } 987 988 virtual bool 989 DoExecute (Args& command, CommandReturnObject &result) 990 { 991 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 992 StackFrame *frame = m_exe_ctx.GetFramePtr(); 993 994 // If no argument is present, issue an error message. There's no way to set a watchpoint. 995 if (command.GetArgumentCount() <= 0) 996 { 997 result.GetErrorStream().Printf("error: required argument missing; specify your program variable to watch for\n"); 998 result.SetStatus(eReturnStatusFailed); 999 return false; 1000 } 1001 1002 // If no '-w' is specified, default to '-w write'. 1003 if (!m_option_watchpoint.watch_type_specified) 1004 { 1005 m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchWrite; 1006 } 1007 1008 // We passed the sanity check for the command. 1009 // Proceed to set the watchpoint now. 1010 lldb::addr_t addr = 0; 1011 size_t size = 0; 1012 1013 VariableSP var_sp; 1014 ValueObjectSP valobj_sp; 1015 Stream &output_stream = result.GetOutputStream(); 1016 1017 // A simple watch variable gesture allows only one argument. 1018 if (command.GetArgumentCount() != 1) 1019 { 1020 result.GetErrorStream().Printf("error: specify exactly one variable to watch for\n"); 1021 result.SetStatus(eReturnStatusFailed); 1022 return false; 1023 } 1024 1025 // Things have checked out ok... 1026 Error error; 1027 uint32_t expr_path_options = StackFrame::eExpressionPathOptionCheckPtrVsMember | 1028 StackFrame::eExpressionPathOptionsAllowDirectIVarAccess; 1029 valobj_sp = frame->GetValueForVariableExpressionPath (command.GetArgumentAtIndex(0), 1030 eNoDynamicValues, 1031 expr_path_options, 1032 var_sp, 1033 error); 1034 1035 if (!valobj_sp) 1036 { 1037 // Not in the frame; let's check the globals. 1038 1039 VariableList variable_list; 1040 ValueObjectList valobj_list; 1041 1042 Error error (Variable::GetValuesForVariableExpressionPath (command.GetArgumentAtIndex(0), 1043 m_exe_ctx.GetBestExecutionContextScope(), 1044 GetVariableCallback, 1045 target, 1046 variable_list, 1047 valobj_list)); 1048 1049 if (valobj_list.GetSize()) 1050 valobj_sp = valobj_list.GetValueObjectAtIndex(0); 1051 } 1052 1053 ClangASTType clang_type; 1054 1055 if (valobj_sp) 1056 { 1057 AddressType addr_type; 1058 addr = valobj_sp->GetAddressOf(false, &addr_type); 1059 if (addr_type == eAddressTypeLoad) 1060 { 1061 // We're in business. 1062 // Find out the size of this variable. 1063 size = m_option_watchpoint.watch_size == 0 ? valobj_sp->GetByteSize() 1064 : m_option_watchpoint.watch_size; 1065 } 1066 clang_type = valobj_sp->GetClangType(); 1067 } 1068 else 1069 { 1070 const char *error_cstr = error.AsCString(NULL); 1071 if (error_cstr) 1072 result.GetErrorStream().Printf("error: %s\n", error_cstr); 1073 else 1074 result.GetErrorStream().Printf ("error: unable to find any variable expression path that matches '%s'\n", 1075 command.GetArgumentAtIndex(0)); 1076 return false; 1077 } 1078 1079 // Now it's time to create the watchpoint. 1080 uint32_t watch_type = m_option_watchpoint.watch_type; 1081 1082 error.Clear(); 1083 Watchpoint *wp = target->CreateWatchpoint(addr, size, &clang_type, watch_type, error).get(); 1084 if (wp) 1085 { 1086 wp->SetWatchSpec(command.GetArgumentAtIndex(0)); 1087 wp->SetWatchVariable(true); 1088 if (var_sp && var_sp->GetDeclaration().GetFile()) 1089 { 1090 StreamString ss; 1091 // True to show fullpath for declaration file. 1092 var_sp->GetDeclaration().DumpStopContext(&ss, true); 1093 wp->SetDeclInfo(ss.GetString()); 1094 } 1095 output_stream.Printf("Watchpoint created: "); 1096 wp->GetDescription(&output_stream, lldb::eDescriptionLevelFull); 1097 output_stream.EOL(); 1098 result.SetStatus(eReturnStatusSuccessFinishResult); 1099 } 1100 else 1101 { 1102 result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%" PRIx64 ", size=%lu, variable expression='%s').\n", 1103 addr, size, command.GetArgumentAtIndex(0)); 1104 if (error.AsCString(NULL)) 1105 result.AppendError(error.AsCString()); 1106 result.SetStatus(eReturnStatusFailed); 1107 } 1108 1109 return result.Succeeded(); 1110 } 1111 1112 private: 1113 OptionGroupOptions m_option_group; 1114 OptionGroupWatchpoint m_option_watchpoint; 1115 }; 1116 1117 //------------------------------------------------------------------------- 1118 // CommandObjectWatchpointSetExpression 1119 //------------------------------------------------------------------------- 1120 #pragma mark Set 1121 1122 class CommandObjectWatchpointSetExpression : public CommandObjectRaw 1123 { 1124 public: 1125 1126 CommandObjectWatchpointSetExpression (CommandInterpreter &interpreter) : 1127 CommandObjectRaw (interpreter, 1128 "watchpoint set expression", 1129 "Set a watchpoint on an address by supplying an expression. " 1130 "Use the '-w' option to specify the type of watchpoint and " 1131 "the '-x' option to specify the byte size to watch for. " 1132 "If no '-w' option is specified, it defaults to write. " 1133 "If no '-x' option is specified, it defaults to the target's " 1134 "pointer byte size. " 1135 "Note that there are limited hardware resources for watchpoints. " 1136 "If watchpoint setting fails, consider disable/delete existing ones " 1137 "to free up resources.", 1138 NULL, 1139 eFlagRequiresFrame | 1140 eFlagTryTargetAPILock | 1141 eFlagProcessMustBeLaunched | 1142 eFlagProcessMustBePaused ), 1143 m_option_group (interpreter), 1144 m_option_watchpoint () 1145 { 1146 SetHelpLong( 1147 "Examples: \n\ 1148 \n\ 1149 watchpoint set expression -w write -x 1 -- foo + 32\n\ 1150 # Watch write access for the 1-byte region pointed to by the address 'foo + 32'.\n"); 1151 1152 CommandArgumentEntry arg; 1153 CommandArgumentData expression_arg; 1154 1155 // Define the only variant of this arg. 1156 expression_arg.arg_type = eArgTypeExpression; 1157 expression_arg.arg_repetition = eArgRepeatPlain; 1158 1159 // Push the only variant into the argument entry. 1160 arg.push_back (expression_arg); 1161 1162 // Push the data for the only argument into the m_arguments vector. 1163 m_arguments.push_back (arg); 1164 1165 // Absorb the '-w' and '-x' options into our option group. 1166 m_option_group.Append (&m_option_watchpoint, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 1167 m_option_group.Finalize(); 1168 } 1169 1170 1171 virtual 1172 ~CommandObjectWatchpointSetExpression () {} 1173 1174 // Overrides base class's behavior where WantsCompletion = !WantsRawCommandString. 1175 virtual bool 1176 WantsCompletion() { return true; } 1177 1178 virtual Options * 1179 GetOptions () 1180 { 1181 return &m_option_group; 1182 } 1183 1184 protected: 1185 virtual bool 1186 DoExecute (const char *raw_command, CommandReturnObject &result) 1187 { 1188 m_option_group.NotifyOptionParsingStarting(); // This is a raw command, so notify the option group 1189 1190 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 1191 StackFrame *frame = m_exe_ctx.GetFramePtr(); 1192 1193 Args command(raw_command); 1194 const char *expr = NULL; 1195 if (raw_command[0] == '-') 1196 { 1197 // We have some options and these options MUST end with --. 1198 const char *end_options = NULL; 1199 const char *s = raw_command; 1200 while (s && s[0]) 1201 { 1202 end_options = ::strstr (s, "--"); 1203 if (end_options) 1204 { 1205 end_options += 2; // Get past the "--" 1206 if (::isspace (end_options[0])) 1207 { 1208 expr = end_options; 1209 while (::isspace (*expr)) 1210 ++expr; 1211 break; 1212 } 1213 } 1214 s = end_options; 1215 } 1216 1217 if (end_options) 1218 { 1219 Args args (raw_command, end_options - raw_command); 1220 if (!ParseOptions (args, result)) 1221 return false; 1222 1223 Error error (m_option_group.NotifyOptionParsingFinished()); 1224 if (error.Fail()) 1225 { 1226 result.AppendError (error.AsCString()); 1227 result.SetStatus (eReturnStatusFailed); 1228 return false; 1229 } 1230 } 1231 } 1232 1233 if (expr == NULL) 1234 expr = raw_command; 1235 1236 // If no argument is present, issue an error message. There's no way to set a watchpoint. 1237 if (command.GetArgumentCount() == 0) 1238 { 1239 result.GetErrorStream().Printf("error: required argument missing; specify an expression to evaulate into the address to watch for\n"); 1240 result.SetStatus(eReturnStatusFailed); 1241 return false; 1242 } 1243 1244 // If no '-w' is specified, default to '-w write'. 1245 if (!m_option_watchpoint.watch_type_specified) 1246 { 1247 m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchWrite; 1248 } 1249 1250 // We passed the sanity check for the command. 1251 // Proceed to set the watchpoint now. 1252 lldb::addr_t addr = 0; 1253 size_t size = 0; 1254 1255 ValueObjectSP valobj_sp; 1256 1257 // Use expression evaluation to arrive at the address to watch. 1258 EvaluateExpressionOptions options; 1259 options.SetCoerceToId(false) 1260 .SetUnwindOnError(true) 1261 .SetKeepInMemory(false) 1262 .SetRunOthers(true) 1263 .SetTimeoutUsec(0); 1264 1265 ExecutionResults expr_result = target->EvaluateExpression (expr, 1266 frame, 1267 valobj_sp, 1268 options); 1269 if (expr_result != eExecutionCompleted) 1270 { 1271 result.GetErrorStream().Printf("error: expression evaluation of address to watch failed\n"); 1272 result.GetErrorStream().Printf("expression evaluated: %s\n", expr); 1273 result.SetStatus(eReturnStatusFailed); 1274 return false; 1275 } 1276 1277 // Get the address to watch. 1278 bool success = false; 1279 addr = valobj_sp->GetValueAsUnsigned(0, &success); 1280 if (!success) 1281 { 1282 result.GetErrorStream().Printf("error: expression did not evaluate to an address\n"); 1283 result.SetStatus(eReturnStatusFailed); 1284 return false; 1285 } 1286 1287 if (m_option_watchpoint.watch_size != 0) 1288 size = m_option_watchpoint.watch_size; 1289 else 1290 size = target->GetArchitecture().GetAddressByteSize(); 1291 1292 // Now it's time to create the watchpoint. 1293 uint32_t watch_type = m_option_watchpoint.watch_type; 1294 1295 // Fetch the type from the value object, the type of the watched object is the pointee type 1296 /// of the expression, so convert to that if we found a valid type. 1297 ClangASTType clang_type(valobj_sp->GetClangType()); 1298 1299 Error error; 1300 Watchpoint *wp = target->CreateWatchpoint(addr, size, &clang_type, watch_type, error).get(); 1301 if (wp) 1302 { 1303 Stream &output_stream = result.GetOutputStream(); 1304 output_stream.Printf("Watchpoint created: "); 1305 wp->GetDescription(&output_stream, lldb::eDescriptionLevelFull); 1306 output_stream.EOL(); 1307 result.SetStatus(eReturnStatusSuccessFinishResult); 1308 } 1309 else 1310 { 1311 result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%" PRIx64 ", size=%lu).\n", 1312 addr, size); 1313 if (error.AsCString(NULL)) 1314 result.AppendError(error.AsCString()); 1315 result.SetStatus(eReturnStatusFailed); 1316 } 1317 1318 return result.Succeeded(); 1319 } 1320 1321 private: 1322 OptionGroupOptions m_option_group; 1323 OptionGroupWatchpoint m_option_watchpoint; 1324 }; 1325 1326 //------------------------------------------------------------------------- 1327 // CommandObjectWatchpointSet 1328 //------------------------------------------------------------------------- 1329 #pragma mark Set 1330 1331 class CommandObjectWatchpointSet : public CommandObjectMultiword 1332 { 1333 public: 1334 1335 CommandObjectWatchpointSet (CommandInterpreter &interpreter) : 1336 CommandObjectMultiword (interpreter, 1337 "watchpoint set", 1338 "A set of commands for setting a watchpoint.", 1339 "watchpoint set <subcommand> [<subcommand-options>]") 1340 { 1341 1342 LoadSubCommand ("variable", CommandObjectSP (new CommandObjectWatchpointSetVariable (interpreter))); 1343 LoadSubCommand ("expression", CommandObjectSP (new CommandObjectWatchpointSetExpression (interpreter))); 1344 } 1345 1346 1347 virtual 1348 ~CommandObjectWatchpointSet () {} 1349 1350 }; 1351 1352 //------------------------------------------------------------------------- 1353 // CommandObjectMultiwordWatchpoint 1354 //------------------------------------------------------------------------- 1355 #pragma mark MultiwordWatchpoint 1356 1357 CommandObjectMultiwordWatchpoint::CommandObjectMultiwordWatchpoint(CommandInterpreter &interpreter) : 1358 CommandObjectMultiword (interpreter, 1359 "watchpoint", 1360 "A set of commands for operating on watchpoints.", 1361 "watchpoint <command> [<command-options>]") 1362 { 1363 CommandObjectSP list_command_object (new CommandObjectWatchpointList (interpreter)); 1364 CommandObjectSP enable_command_object (new CommandObjectWatchpointEnable (interpreter)); 1365 CommandObjectSP disable_command_object (new CommandObjectWatchpointDisable (interpreter)); 1366 CommandObjectSP delete_command_object (new CommandObjectWatchpointDelete (interpreter)); 1367 CommandObjectSP ignore_command_object (new CommandObjectWatchpointIgnore (interpreter)); 1368 CommandObjectSP command_command_object (new CommandObjectWatchpointCommand (interpreter)); 1369 CommandObjectSP modify_command_object (new CommandObjectWatchpointModify (interpreter)); 1370 CommandObjectSP set_command_object (new CommandObjectWatchpointSet (interpreter)); 1371 1372 list_command_object->SetCommandName ("watchpoint list"); 1373 enable_command_object->SetCommandName("watchpoint enable"); 1374 disable_command_object->SetCommandName("watchpoint disable"); 1375 delete_command_object->SetCommandName("watchpoint delete"); 1376 ignore_command_object->SetCommandName("watchpoint ignore"); 1377 command_command_object->SetCommandName ("watchpoint command"); 1378 modify_command_object->SetCommandName("watchpoint modify"); 1379 set_command_object->SetCommandName("watchpoint set"); 1380 1381 LoadSubCommand ("list", list_command_object); 1382 LoadSubCommand ("enable", enable_command_object); 1383 LoadSubCommand ("disable", disable_command_object); 1384 LoadSubCommand ("delete", delete_command_object); 1385 LoadSubCommand ("ignore", ignore_command_object); 1386 LoadSubCommand ("command", command_command_object); 1387 LoadSubCommand ("modify", modify_command_object); 1388 LoadSubCommand ("set", set_command_object); 1389 } 1390 1391 CommandObjectMultiwordWatchpoint::~CommandObjectMultiwordWatchpoint() 1392 { 1393 } 1394 1395