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 StackFrame::eExpressionPathOptionsAllowDirectIVarAccess; 1020 valobj_sp = frame->GetValueForVariableExpressionPath (command.GetArgumentAtIndex(0), 1021 eNoDynamicValues, 1022 expr_path_options, 1023 var_sp, 1024 error); 1025 if (valobj_sp) { 1026 AddressType addr_type; 1027 addr = valobj_sp->GetAddressOf(false, &addr_type); 1028 if (addr_type == eAddressTypeLoad) { 1029 // We're in business. 1030 // Find out the size of this variable. 1031 size = m_option_watchpoint.watch_size == 0 ? valobj_sp->GetByteSize() 1032 : m_option_watchpoint.watch_size; 1033 } 1034 } else { 1035 const char *error_cstr = error.AsCString(NULL); 1036 if (error_cstr) 1037 result.GetErrorStream().Printf("error: %s\n", error_cstr); 1038 else 1039 result.GetErrorStream().Printf ("error: unable to find any variable expression path that matches '%s'\n", 1040 command.GetArgumentAtIndex(0)); 1041 return false; 1042 } 1043 1044 // Now it's time to create the watchpoint. 1045 uint32_t watch_type = m_option_watchpoint.watch_type; 1046 error.Clear(); 1047 Watchpoint *wp = target->CreateWatchpoint(addr, size, watch_type, error).get(); 1048 if (wp) { 1049 if (var_sp && var_sp->GetDeclaration().GetFile()) { 1050 StreamString ss; 1051 // True to show fullpath for declaration file. 1052 var_sp->GetDeclaration().DumpStopContext(&ss, true); 1053 wp->SetDeclInfo(ss.GetString()); 1054 } 1055 StreamString ss; 1056 output_stream.Printf("Watchpoint created: "); 1057 wp->GetDescription(&output_stream, lldb::eDescriptionLevelFull); 1058 output_stream.EOL(); 1059 result.SetStatus(eReturnStatusSuccessFinishResult); 1060 } else { 1061 result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%llx, size=%lu).\n", 1062 addr, size); 1063 if (error.AsCString(NULL)) 1064 result.AppendError(error.AsCString()); 1065 result.SetStatus(eReturnStatusFailed); 1066 } 1067 1068 return result.Succeeded(); 1069 } 1070 1071 private: 1072 OptionGroupOptions m_option_group; 1073 OptionGroupWatchpoint m_option_watchpoint; 1074 }; 1075 1076 //------------------------------------------------------------------------- 1077 // CommandObjectWatchpointSetExpression 1078 //------------------------------------------------------------------------- 1079 #pragma mark Set 1080 1081 class CommandObjectWatchpointSetExpression : public CommandObjectRaw 1082 { 1083 public: 1084 1085 CommandObjectWatchpointSetExpression (CommandInterpreter &interpreter) : 1086 CommandObjectRaw (interpreter, 1087 "watchpoint set expression", 1088 "Set a watchpoint on an address by supplying an expression. " 1089 "Use the '-w' option to specify the type of watchpoint and " 1090 "the '-x' option to specify the byte size to watch for. " 1091 "If no '-w' option is specified, it defaults to write. " 1092 "If no '-x' option is specified, it defaults to the target's " 1093 "pointer byte size. " 1094 "Note that there are limited hardware resources for watchpoints. " 1095 "If watchpoint setting fails, consider disable/delete existing ones " 1096 "to free up resources.", 1097 NULL, 1098 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused), 1099 m_option_group (interpreter), 1100 m_option_watchpoint () 1101 { 1102 SetHelpLong( 1103 "Examples: \n\ 1104 \n\ 1105 watchpoint set expression -w write -x 1 -- foo + 32\n\ 1106 # Watch write access for the 1-byte region pointed to by the address 'foo + 32'.\n"); 1107 1108 CommandArgumentEntry arg; 1109 CommandArgumentData expression_arg; 1110 1111 // Define the only variant of this arg. 1112 expression_arg.arg_type = eArgTypeExpression; 1113 expression_arg.arg_repetition = eArgRepeatPlain; 1114 1115 // Push the only variant into the argument entry. 1116 arg.push_back (expression_arg); 1117 1118 // Push the data for the only argument into the m_arguments vector. 1119 m_arguments.push_back (arg); 1120 1121 // Absorb the '-w' and '-x' options into our option group. 1122 m_option_group.Append (&m_option_watchpoint, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 1123 m_option_group.Finalize(); 1124 } 1125 1126 1127 virtual 1128 ~CommandObjectWatchpointSetExpression () {} 1129 1130 // Overrides base class's behavior where WantsCompletion = !WantsRawCommandString. 1131 virtual bool 1132 WantsCompletion() { return true; } 1133 1134 virtual Options * 1135 GetOptions () 1136 { 1137 return &m_option_group; 1138 } 1139 1140 protected: 1141 virtual bool 1142 DoExecute (const char *raw_command, CommandReturnObject &result) 1143 { 1144 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 1145 ExecutionContext exe_ctx(m_interpreter.GetExecutionContext()); 1146 StackFrame *frame = exe_ctx.GetFramePtr(); 1147 if (frame == NULL) 1148 { 1149 result.AppendError ("you must be stopped in a valid stack frame to set a watchpoint."); 1150 result.SetStatus (eReturnStatusFailed); 1151 return false; 1152 } 1153 1154 Args command(raw_command); 1155 1156 // Process possible options. 1157 if (!ParseOptions (command, result)) 1158 return false; 1159 1160 // If no argument is present, issue an error message. There's no way to set a watchpoint. 1161 if (command.GetArgumentCount() <= 0) 1162 { 1163 result.GetErrorStream().Printf("error: required argument missing; specify an expression to evaulate into the addres to watch for\n"); 1164 result.SetStatus(eReturnStatusFailed); 1165 return false; 1166 } 1167 1168 bool with_dash_w = m_option_watchpoint.watch_type_specified; 1169 bool with_dash_x = (m_option_watchpoint.watch_size != 0); 1170 1171 // If no '-w' is specified, default to '-w write'. 1172 if (!with_dash_w) 1173 { 1174 m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchWrite; 1175 } 1176 1177 // We passed the sanity check for the command. 1178 // Proceed to set the watchpoint now. 1179 lldb::addr_t addr = 0; 1180 size_t size = 0; 1181 1182 VariableSP var_sp; 1183 ValueObjectSP valobj_sp; 1184 Stream &output_stream = result.GetOutputStream(); 1185 1186 // We will process the raw command string to rid of the '-w', '-x', or '--' 1187 llvm::StringRef raw_expr_str(raw_command); 1188 std::string expr_str = StripOptionTerminator(raw_expr_str, with_dash_w, with_dash_x).str(); 1189 1190 // Sanity check for when the user forgets to terminate the option strings with a '--'. 1191 if ((with_dash_w || with_dash_w) && expr_str.empty()) 1192 { 1193 result.GetErrorStream().Printf("error: did you forget to enter the option terminator string \"--\"?\n"); 1194 result.SetStatus(eReturnStatusFailed); 1195 return false; 1196 } 1197 1198 // Use expression evaluation to arrive at the address to watch. 1199 const bool coerce_to_id = true; 1200 const bool unwind_on_error = true; 1201 const bool keep_in_memory = false; 1202 ExecutionResults expr_result = target->EvaluateExpression (expr_str.c_str(), 1203 frame, 1204 eExecutionPolicyOnlyWhenNeeded, 1205 coerce_to_id, 1206 unwind_on_error, 1207 keep_in_memory, 1208 eNoDynamicValues, 1209 valobj_sp, 1210 0 /* no timeout */); 1211 if (expr_result != eExecutionCompleted) { 1212 result.GetErrorStream().Printf("error: expression evaluation of address to watch failed\n"); 1213 result.GetErrorStream().Printf("expression evaluated: %s\n", expr_str.c_str()); 1214 result.SetStatus(eReturnStatusFailed); 1215 return false; 1216 } 1217 1218 // Get the address to watch. 1219 bool success = false; 1220 addr = valobj_sp->GetValueAsUnsigned(0, &success); 1221 if (!success) { 1222 result.GetErrorStream().Printf("error: expression did not evaluate to an address\n"); 1223 result.SetStatus(eReturnStatusFailed); 1224 return false; 1225 } 1226 size = with_dash_x ? m_option_watchpoint.watch_size 1227 : target->GetArchitecture().GetAddressByteSize(); 1228 1229 // Now it's time to create the watchpoint. 1230 uint32_t watch_type = m_option_watchpoint.watch_type; 1231 Error error; 1232 Watchpoint *wp = target->CreateWatchpoint(addr, size, watch_type, error).get(); 1233 if (wp) { 1234 if (var_sp && var_sp->GetDeclaration().GetFile()) { 1235 StreamString ss; 1236 // True to show fullpath for declaration file. 1237 var_sp->GetDeclaration().DumpStopContext(&ss, true); 1238 wp->SetDeclInfo(ss.GetString()); 1239 } 1240 StreamString ss; 1241 output_stream.Printf("Watchpoint created: "); 1242 wp->GetDescription(&output_stream, lldb::eDescriptionLevelFull); 1243 output_stream.EOL(); 1244 result.SetStatus(eReturnStatusSuccessFinishResult); 1245 } else { 1246 result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%llx, size=%lu).\n", 1247 addr, size); 1248 if (error.AsCString(NULL)) 1249 result.AppendError(error.AsCString()); 1250 result.SetStatus(eReturnStatusFailed); 1251 } 1252 1253 return result.Succeeded(); 1254 } 1255 1256 private: 1257 OptionGroupOptions m_option_group; 1258 OptionGroupWatchpoint m_option_watchpoint; 1259 }; 1260 1261 //------------------------------------------------------------------------- 1262 // CommandObjectWatchpointSet 1263 //------------------------------------------------------------------------- 1264 #pragma mark Set 1265 1266 class CommandObjectWatchpointSet : public CommandObjectMultiword 1267 { 1268 public: 1269 1270 CommandObjectWatchpointSet (CommandInterpreter &interpreter) : 1271 CommandObjectMultiword (interpreter, 1272 "watchpoint set", 1273 "A set of commands for setting a watchpoint.", 1274 "watchpoint set <subcommand> [<subcommand-options>]") 1275 { 1276 1277 LoadSubCommand ("variable", CommandObjectSP (new CommandObjectWatchpointSetVariable (interpreter))); 1278 LoadSubCommand ("expression", CommandObjectSP (new CommandObjectWatchpointSetExpression (interpreter))); 1279 } 1280 1281 1282 virtual 1283 ~CommandObjectWatchpointSet () {} 1284 1285 }; 1286 1287 //------------------------------------------------------------------------- 1288 // CommandObjectMultiwordWatchpoint 1289 //------------------------------------------------------------------------- 1290 #pragma mark MultiwordWatchpoint 1291 1292 CommandObjectMultiwordWatchpoint::CommandObjectMultiwordWatchpoint(CommandInterpreter &interpreter) : 1293 CommandObjectMultiword (interpreter, 1294 "watchpoint", 1295 "A set of commands for operating on watchpoints.", 1296 "watchpoint <command> [<command-options>]") 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 LoadSubCommand ("list", list_command_object); 1315 LoadSubCommand ("enable", enable_command_object); 1316 LoadSubCommand ("disable", disable_command_object); 1317 LoadSubCommand ("delete", delete_command_object); 1318 LoadSubCommand ("ignore", ignore_command_object); 1319 LoadSubCommand ("modify", modify_command_object); 1320 LoadSubCommand ("set", set_command_object); 1321 } 1322 1323 CommandObjectMultiwordWatchpoint::~CommandObjectMultiwordWatchpoint() 1324 { 1325 } 1326 1327