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 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused), 938 m_option_group (interpreter), 939 m_option_watchpoint () 940 { 941 SetHelpLong( 942 "Examples: \n\ 943 \n\ 944 watchpoint set variable -w read_wriate my_global_var \n\ 945 # Watch my_global_var for read/write access, with the region to watch corresponding to the byte size of the data type.\n"); 946 947 CommandArgumentEntry arg; 948 CommandArgumentData var_name_arg; 949 950 // Define the only variant of this arg. 951 var_name_arg.arg_type = eArgTypeVarName; 952 var_name_arg.arg_repetition = eArgRepeatPlain; 953 954 // Push the variant into the argument entry. 955 arg.push_back (var_name_arg); 956 957 // Push the data for the only argument into the m_arguments vector. 958 m_arguments.push_back (arg); 959 960 // Absorb the '-w' and '-x' options into our option group. 961 m_option_group.Append (&m_option_watchpoint, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 962 m_option_group.Finalize(); 963 } 964 965 virtual 966 ~CommandObjectWatchpointSetVariable () {} 967 968 virtual Options * 969 GetOptions () 970 { 971 return &m_option_group; 972 } 973 974 protected: 975 static uint32_t GetVariableCallback (void *baton, 976 const char *name, 977 VariableList &variable_list) 978 { 979 Target *target = static_cast<Target *>(baton); 980 if (target) 981 { 982 return target->GetImages().FindGlobalVariables (ConstString(name), 983 true, 984 UINT32_MAX, 985 variable_list); 986 } 987 return 0; 988 } 989 990 virtual bool 991 DoExecute (Args& command, 992 CommandReturnObject &result) 993 { 994 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 995 ExecutionContext exe_ctx(m_interpreter.GetExecutionContext()); 996 StackFrame *frame = exe_ctx.GetFramePtr(); 997 if (frame == NULL) 998 { 999 result.AppendError ("you must be stopped in a valid stack frame to set a watchpoint."); 1000 result.SetStatus (eReturnStatusFailed); 1001 return false; 1002 } 1003 1004 // If no argument is present, issue an error message. There's no way to set a watchpoint. 1005 if (command.GetArgumentCount() <= 0) 1006 { 1007 result.GetErrorStream().Printf("error: required argument missing; specify your program variable to watch for\n"); 1008 result.SetStatus(eReturnStatusFailed); 1009 return false; 1010 } 1011 1012 // If no '-w' is specified, default to '-w write'. 1013 if (!m_option_watchpoint.watch_type_specified) 1014 { 1015 m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchWrite; 1016 } 1017 1018 // We passed the sanity check for the command. 1019 // Proceed to set the watchpoint now. 1020 lldb::addr_t addr = 0; 1021 size_t size = 0; 1022 1023 VariableSP var_sp; 1024 ValueObjectSP valobj_sp; 1025 Stream &output_stream = result.GetOutputStream(); 1026 1027 // A simple watch variable gesture allows only one argument. 1028 if (command.GetArgumentCount() != 1) { 1029 result.GetErrorStream().Printf("error: specify exactly one variable to watch for\n"); 1030 result.SetStatus(eReturnStatusFailed); 1031 return false; 1032 } 1033 1034 // Things have checked out ok... 1035 Error error; 1036 uint32_t expr_path_options = StackFrame::eExpressionPathOptionCheckPtrVsMember | 1037 StackFrame::eExpressionPathOptionsAllowDirectIVarAccess; 1038 valobj_sp = frame->GetValueForVariableExpressionPath (command.GetArgumentAtIndex(0), 1039 eNoDynamicValues, 1040 expr_path_options, 1041 var_sp, 1042 error); 1043 1044 if (!valobj_sp) { 1045 // Not in the frame; let's check the globals. 1046 1047 VariableList variable_list; 1048 ValueObjectList valobj_list; 1049 1050 Error error (Variable::GetValuesForVariableExpressionPath (command.GetArgumentAtIndex(0), 1051 exe_ctx.GetBestExecutionContextScope(), 1052 GetVariableCallback, 1053 target, 1054 variable_list, 1055 valobj_list)); 1056 1057 if (valobj_list.GetSize()) 1058 valobj_sp = valobj_list.GetValueObjectAtIndex(0); 1059 } 1060 1061 ClangASTType type; 1062 1063 if (valobj_sp) { 1064 AddressType addr_type; 1065 addr = valobj_sp->GetAddressOf(false, &addr_type); 1066 if (addr_type == eAddressTypeLoad) { 1067 // We're in business. 1068 // Find out the size of this variable. 1069 size = m_option_watchpoint.watch_size == 0 ? valobj_sp->GetByteSize() 1070 : m_option_watchpoint.watch_size; 1071 } 1072 type.SetClangType(valobj_sp->GetClangAST(), valobj_sp->GetClangType()); 1073 } else { 1074 const char *error_cstr = error.AsCString(NULL); 1075 if (error_cstr) 1076 result.GetErrorStream().Printf("error: %s\n", error_cstr); 1077 else 1078 result.GetErrorStream().Printf ("error: unable to find any variable expression path that matches '%s'\n", 1079 command.GetArgumentAtIndex(0)); 1080 return false; 1081 } 1082 1083 // Now it's time to create the watchpoint. 1084 uint32_t watch_type = m_option_watchpoint.watch_type; 1085 error.Clear(); 1086 Watchpoint *wp = target->CreateWatchpoint(addr, size, &type, watch_type, error).get(); 1087 if (wp) { 1088 wp->SetWatchSpec(command.GetArgumentAtIndex(0)); 1089 wp->SetWatchVariable(true); 1090 if (var_sp && var_sp->GetDeclaration().GetFile()) { 1091 StreamString ss; 1092 // True to show fullpath for declaration file. 1093 var_sp->GetDeclaration().DumpStopContext(&ss, true); 1094 wp->SetDeclInfo(ss.GetString()); 1095 } 1096 output_stream.Printf("Watchpoint created: "); 1097 wp->GetDescription(&output_stream, lldb::eDescriptionLevelFull); 1098 output_stream.EOL(); 1099 result.SetStatus(eReturnStatusSuccessFinishResult); 1100 } else { 1101 result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%" PRIx64 ", size=%lu, variable expression='%s').\n", 1102 addr, size, command.GetArgumentAtIndex(0)); 1103 if (error.AsCString(NULL)) 1104 result.AppendError(error.AsCString()); 1105 result.SetStatus(eReturnStatusFailed); 1106 } 1107 1108 return result.Succeeded(); 1109 } 1110 1111 private: 1112 OptionGroupOptions m_option_group; 1113 OptionGroupWatchpoint m_option_watchpoint; 1114 }; 1115 1116 //------------------------------------------------------------------------- 1117 // CommandObjectWatchpointSetExpression 1118 //------------------------------------------------------------------------- 1119 #pragma mark Set 1120 1121 class CommandObjectWatchpointSetExpression : public CommandObjectRaw 1122 { 1123 public: 1124 1125 CommandObjectWatchpointSetExpression (CommandInterpreter &interpreter) : 1126 CommandObjectRaw (interpreter, 1127 "watchpoint set expression", 1128 "Set a watchpoint on an address by supplying an expression. " 1129 "Use the '-w' option to specify the type of watchpoint and " 1130 "the '-x' option to specify the byte size to watch for. " 1131 "If no '-w' option is specified, it defaults to write. " 1132 "If no '-x' option is specified, it defaults to the target's " 1133 "pointer byte size. " 1134 "Note that there are limited hardware resources for watchpoints. " 1135 "If watchpoint setting fails, consider disable/delete existing ones " 1136 "to free up resources.", 1137 NULL, 1138 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused), 1139 m_option_group (interpreter), 1140 m_option_watchpoint () 1141 { 1142 SetHelpLong( 1143 "Examples: \n\ 1144 \n\ 1145 watchpoint set expression -w write -x 1 -- foo + 32\n\ 1146 # Watch write access for the 1-byte region pointed to by the address 'foo + 32'.\n"); 1147 1148 CommandArgumentEntry arg; 1149 CommandArgumentData expression_arg; 1150 1151 // Define the only variant of this arg. 1152 expression_arg.arg_type = eArgTypeExpression; 1153 expression_arg.arg_repetition = eArgRepeatPlain; 1154 1155 // Push the only variant into the argument entry. 1156 arg.push_back (expression_arg); 1157 1158 // Push the data for the only argument into the m_arguments vector. 1159 m_arguments.push_back (arg); 1160 1161 // Absorb the '-w' and '-x' options into our option group. 1162 m_option_group.Append (&m_option_watchpoint, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 1163 m_option_group.Finalize(); 1164 } 1165 1166 1167 virtual 1168 ~CommandObjectWatchpointSetExpression () {} 1169 1170 // Overrides base class's behavior where WantsCompletion = !WantsRawCommandString. 1171 virtual bool 1172 WantsCompletion() { return true; } 1173 1174 virtual Options * 1175 GetOptions () 1176 { 1177 return &m_option_group; 1178 } 1179 1180 protected: 1181 virtual bool 1182 DoExecute (const char *raw_command, CommandReturnObject &result) 1183 { 1184 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 1185 ExecutionContext exe_ctx(m_interpreter.GetExecutionContext()); 1186 StackFrame *frame = exe_ctx.GetFramePtr(); 1187 if (frame == NULL) 1188 { 1189 result.AppendError ("you must be stopped in a valid stack frame to set a watchpoint."); 1190 result.SetStatus (eReturnStatusFailed); 1191 return false; 1192 } 1193 1194 Args command(raw_command); 1195 1196 // Process possible options. 1197 if (!ParseOptions (command, result)) 1198 return false; 1199 1200 // If no argument is present, issue an error message. There's no way to set a watchpoint. 1201 if (command.GetArgumentCount() <= 0) 1202 { 1203 result.GetErrorStream().Printf("error: required argument missing; specify an expression to evaulate into the addres to watch for\n"); 1204 result.SetStatus(eReturnStatusFailed); 1205 return false; 1206 } 1207 1208 bool with_dash_w = m_option_watchpoint.watch_type_specified; 1209 bool with_dash_x = (m_option_watchpoint.watch_size != 0); 1210 1211 // If no '-w' is specified, default to '-w write'. 1212 if (!with_dash_w) 1213 { 1214 m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchWrite; 1215 } 1216 1217 // We passed the sanity check for the command. 1218 // Proceed to set the watchpoint now. 1219 lldb::addr_t addr = 0; 1220 size_t size = 0; 1221 1222 VariableSP var_sp; 1223 ValueObjectSP valobj_sp; 1224 Stream &output_stream = result.GetOutputStream(); 1225 1226 // We will process the raw command string to rid of the '-w', '-x', or '--' 1227 llvm::StringRef raw_expr_str(raw_command); 1228 std::string expr_str = StripOptionTerminator(raw_expr_str, with_dash_w, with_dash_x).str(); 1229 1230 // Sanity check for when the user forgets to terminate the option strings with a '--'. 1231 if ((with_dash_w || with_dash_w) && expr_str.empty()) 1232 { 1233 result.GetErrorStream().Printf("error: did you forget to enter the option terminator string \"--\"?\n"); 1234 result.SetStatus(eReturnStatusFailed); 1235 return false; 1236 } 1237 1238 // Use expression evaluation to arrive at the address to watch. 1239 EvaluateExpressionOptions options; 1240 options.SetCoerceToId(false) 1241 .SetUnwindOnError(true) 1242 .SetKeepInMemory(false) 1243 .SetRunOthers(true) 1244 .SetTimeoutUsec(0); 1245 1246 ExecutionResults expr_result = target->EvaluateExpression (expr_str.c_str(), 1247 frame, 1248 valobj_sp, 1249 options); 1250 if (expr_result != eExecutionCompleted) { 1251 result.GetErrorStream().Printf("error: expression evaluation of address to watch failed\n"); 1252 result.GetErrorStream().Printf("expression evaluated: %s\n", expr_str.c_str()); 1253 result.SetStatus(eReturnStatusFailed); 1254 return false; 1255 } 1256 1257 // Get the address to watch. 1258 bool success = false; 1259 addr = valobj_sp->GetValueAsUnsigned(0, &success); 1260 if (!success) { 1261 result.GetErrorStream().Printf("error: expression did not evaluate to an address\n"); 1262 result.SetStatus(eReturnStatusFailed); 1263 return false; 1264 } 1265 size = with_dash_x ? m_option_watchpoint.watch_size 1266 : target->GetArchitecture().GetAddressByteSize(); 1267 1268 // Now it's time to create the watchpoint. 1269 uint32_t watch_type = m_option_watchpoint.watch_type; 1270 1271 // Fetch the type from the value object, the type of the watched object is the pointee type 1272 /// of the expression, so convert to that if we found a valid type. 1273 ClangASTType type(valobj_sp->GetClangAST(), valobj_sp->GetClangType()); 1274 if (type.IsValid()) 1275 type.SetClangType(type.GetASTContext(), type.GetPointeeType()); 1276 1277 Error error; 1278 Watchpoint *wp = target->CreateWatchpoint(addr, size, &type, watch_type, error).get(); 1279 if (wp) { 1280 if (var_sp && var_sp->GetDeclaration().GetFile()) { 1281 StreamString ss; 1282 // True to show fullpath for declaration file. 1283 var_sp->GetDeclaration().DumpStopContext(&ss, true); 1284 wp->SetDeclInfo(ss.GetString()); 1285 } 1286 output_stream.Printf("Watchpoint created: "); 1287 wp->GetDescription(&output_stream, lldb::eDescriptionLevelFull); 1288 output_stream.EOL(); 1289 result.SetStatus(eReturnStatusSuccessFinishResult); 1290 } else { 1291 result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%" PRIx64 ", size=%lu).\n", 1292 addr, size); 1293 if (error.AsCString(NULL)) 1294 result.AppendError(error.AsCString()); 1295 result.SetStatus(eReturnStatusFailed); 1296 } 1297 1298 return result.Succeeded(); 1299 } 1300 1301 private: 1302 OptionGroupOptions m_option_group; 1303 OptionGroupWatchpoint m_option_watchpoint; 1304 }; 1305 1306 //------------------------------------------------------------------------- 1307 // CommandObjectWatchpointSet 1308 //------------------------------------------------------------------------- 1309 #pragma mark Set 1310 1311 class CommandObjectWatchpointSet : public CommandObjectMultiword 1312 { 1313 public: 1314 1315 CommandObjectWatchpointSet (CommandInterpreter &interpreter) : 1316 CommandObjectMultiword (interpreter, 1317 "watchpoint set", 1318 "A set of commands for setting a watchpoint.", 1319 "watchpoint set <subcommand> [<subcommand-options>]") 1320 { 1321 1322 LoadSubCommand ("variable", CommandObjectSP (new CommandObjectWatchpointSetVariable (interpreter))); 1323 LoadSubCommand ("expression", CommandObjectSP (new CommandObjectWatchpointSetExpression (interpreter))); 1324 } 1325 1326 1327 virtual 1328 ~CommandObjectWatchpointSet () {} 1329 1330 }; 1331 1332 //------------------------------------------------------------------------- 1333 // CommandObjectMultiwordWatchpoint 1334 //------------------------------------------------------------------------- 1335 #pragma mark MultiwordWatchpoint 1336 1337 CommandObjectMultiwordWatchpoint::CommandObjectMultiwordWatchpoint(CommandInterpreter &interpreter) : 1338 CommandObjectMultiword (interpreter, 1339 "watchpoint", 1340 "A set of commands for operating on watchpoints.", 1341 "watchpoint <command> [<command-options>]") 1342 { 1343 CommandObjectSP list_command_object (new CommandObjectWatchpointList (interpreter)); 1344 CommandObjectSP enable_command_object (new CommandObjectWatchpointEnable (interpreter)); 1345 CommandObjectSP disable_command_object (new CommandObjectWatchpointDisable (interpreter)); 1346 CommandObjectSP delete_command_object (new CommandObjectWatchpointDelete (interpreter)); 1347 CommandObjectSP ignore_command_object (new CommandObjectWatchpointIgnore (interpreter)); 1348 CommandObjectSP command_command_object (new CommandObjectWatchpointCommand (interpreter)); 1349 CommandObjectSP modify_command_object (new CommandObjectWatchpointModify (interpreter)); 1350 CommandObjectSP set_command_object (new CommandObjectWatchpointSet (interpreter)); 1351 1352 list_command_object->SetCommandName ("watchpoint list"); 1353 enable_command_object->SetCommandName("watchpoint enable"); 1354 disable_command_object->SetCommandName("watchpoint disable"); 1355 delete_command_object->SetCommandName("watchpoint delete"); 1356 ignore_command_object->SetCommandName("watchpoint ignore"); 1357 command_command_object->SetCommandName ("watchpoint command"); 1358 modify_command_object->SetCommandName("watchpoint modify"); 1359 set_command_object->SetCommandName("watchpoint set"); 1360 1361 LoadSubCommand ("list", list_command_object); 1362 LoadSubCommand ("enable", enable_command_object); 1363 LoadSubCommand ("disable", disable_command_object); 1364 LoadSubCommand ("delete", delete_command_object); 1365 LoadSubCommand ("ignore", ignore_command_object); 1366 LoadSubCommand ("command", command_command_object); 1367 LoadSubCommand ("modify", modify_command_object); 1368 LoadSubCommand ("set", set_command_object); 1369 } 1370 1371 CommandObjectMultiwordWatchpoint::~CommandObjectMultiwordWatchpoint() 1372 { 1373 } 1374 1375