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