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