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