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