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