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