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