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