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 void 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; 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; 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 265 private: 266 CommandOptions m_options; 267 }; 268 269 // CommandObjectWatchpointEnable 270 #pragma mark Enable 271 272 class CommandObjectWatchpointEnable : public CommandObjectParsed { 273 public: 274 CommandObjectWatchpointEnable(CommandInterpreter &interpreter) 275 : CommandObjectParsed(interpreter, "enable", 276 "Enable the specified disabled watchpoint(s). If " 277 "no watchpoints are specified, enable all of them.", 278 nullptr, eCommandRequiresTarget) { 279 CommandArgumentEntry arg; 280 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, 281 eArgTypeWatchpointIDRange); 282 // Add the entry for the first argument for this command to the object's 283 // arguments vector. 284 m_arguments.push_back(arg); 285 } 286 287 ~CommandObjectWatchpointEnable() override = default; 288 289 void 290 HandleArgumentCompletion(CompletionRequest &request, 291 OptionElementVector &opt_element_vector) override { 292 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( 293 GetCommandInterpreter(), lldb::eWatchpointIDCompletion, request, 294 nullptr); 295 } 296 297 protected: 298 void DoExecute(Args &command, CommandReturnObject &result) override { 299 Target *target = &GetSelectedTarget(); 300 if (!CheckTargetForWatchpointOperations(target, result)) 301 return; 302 303 std::unique_lock<std::recursive_mutex> lock; 304 target->GetWatchpointList().GetListMutex(lock); 305 306 const WatchpointList &watchpoints = target->GetWatchpointList(); 307 308 size_t num_watchpoints = watchpoints.GetSize(); 309 310 if (num_watchpoints == 0) { 311 result.AppendError("No watchpoints exist to be enabled."); 312 return; 313 } 314 315 if (command.GetArgumentCount() == 0) { 316 // No watchpoint selected; enable all currently set watchpoints. 317 target->EnableAllWatchpoints(); 318 result.AppendMessageWithFormat("All watchpoints enabled. (%" PRIu64 319 " watchpoints)\n", 320 (uint64_t)num_watchpoints); 321 result.SetStatus(eReturnStatusSuccessFinishNoResult); 322 } else { 323 // Particular watchpoints selected; enable them. 324 std::vector<uint32_t> wp_ids; 325 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs( 326 target, command, wp_ids)) { 327 result.AppendError("Invalid watchpoints specification."); 328 return; 329 } 330 331 int count = 0; 332 const size_t size = wp_ids.size(); 333 for (size_t i = 0; i < size; ++i) 334 if (target->EnableWatchpointByID(wp_ids[i])) 335 ++count; 336 result.AppendMessageWithFormat("%d watchpoints enabled.\n", count); 337 result.SetStatus(eReturnStatusSuccessFinishNoResult); 338 } 339 } 340 }; 341 342 // CommandObjectWatchpointDisable 343 #pragma mark Disable 344 345 class CommandObjectWatchpointDisable : public CommandObjectParsed { 346 public: 347 CommandObjectWatchpointDisable(CommandInterpreter &interpreter) 348 : CommandObjectParsed(interpreter, "watchpoint disable", 349 "Disable the specified watchpoint(s) without " 350 "removing it/them. If no watchpoints are " 351 "specified, disable them all.", 352 nullptr, eCommandRequiresTarget) { 353 CommandArgumentEntry arg; 354 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, 355 eArgTypeWatchpointIDRange); 356 // Add the entry for the first argument for this command to the object's 357 // arguments vector. 358 m_arguments.push_back(arg); 359 } 360 361 ~CommandObjectWatchpointDisable() override = default; 362 363 void 364 HandleArgumentCompletion(CompletionRequest &request, 365 OptionElementVector &opt_element_vector) override { 366 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( 367 GetCommandInterpreter(), lldb::eWatchpointIDCompletion, request, 368 nullptr); 369 } 370 371 protected: 372 void DoExecute(Args &command, CommandReturnObject &result) override { 373 Target *target = &GetSelectedTarget(); 374 if (!CheckTargetForWatchpointOperations(target, result)) 375 return; 376 377 std::unique_lock<std::recursive_mutex> lock; 378 target->GetWatchpointList().GetListMutex(lock); 379 380 const WatchpointList &watchpoints = target->GetWatchpointList(); 381 size_t num_watchpoints = watchpoints.GetSize(); 382 383 if (num_watchpoints == 0) { 384 result.AppendError("No watchpoints exist to be disabled."); 385 return; 386 } 387 388 if (command.GetArgumentCount() == 0) { 389 // No watchpoint selected; disable all currently set watchpoints. 390 if (target->DisableAllWatchpoints()) { 391 result.AppendMessageWithFormat("All watchpoints disabled. (%" PRIu64 392 " watchpoints)\n", 393 (uint64_t)num_watchpoints); 394 result.SetStatus(eReturnStatusSuccessFinishNoResult); 395 } else { 396 result.AppendError("Disable all watchpoints failed\n"); 397 } 398 } else { 399 // Particular watchpoints selected; disable them. 400 std::vector<uint32_t> wp_ids; 401 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs( 402 target, command, wp_ids)) { 403 result.AppendError("Invalid watchpoints specification."); 404 return; 405 } 406 407 int count = 0; 408 const size_t size = wp_ids.size(); 409 for (size_t i = 0; i < size; ++i) 410 if (target->DisableWatchpointByID(wp_ids[i])) 411 ++count; 412 result.AppendMessageWithFormat("%d watchpoints disabled.\n", count); 413 result.SetStatus(eReturnStatusSuccessFinishNoResult); 414 } 415 } 416 }; 417 418 // CommandObjectWatchpointDelete 419 #define LLDB_OPTIONS_watchpoint_delete 420 #include "CommandOptions.inc" 421 422 // CommandObjectWatchpointDelete 423 #pragma mark Delete 424 425 class CommandObjectWatchpointDelete : public CommandObjectParsed { 426 public: 427 CommandObjectWatchpointDelete(CommandInterpreter &interpreter) 428 : CommandObjectParsed(interpreter, "watchpoint delete", 429 "Delete the specified watchpoint(s). If no " 430 "watchpoints are specified, delete them all.", 431 nullptr, eCommandRequiresTarget) { 432 CommandArgumentEntry arg; 433 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, 434 eArgTypeWatchpointIDRange); 435 // Add the entry for the first argument for this command to the object's 436 // arguments vector. 437 m_arguments.push_back(arg); 438 } 439 440 ~CommandObjectWatchpointDelete() override = default; 441 442 void 443 HandleArgumentCompletion(CompletionRequest &request, 444 OptionElementVector &opt_element_vector) override { 445 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( 446 GetCommandInterpreter(), lldb::eWatchpointIDCompletion, request, 447 nullptr); 448 } 449 450 Options *GetOptions() override { return &m_options; } 451 452 class CommandOptions : public Options { 453 public: 454 CommandOptions() = default; 455 456 ~CommandOptions() override = default; 457 458 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 459 ExecutionContext *execution_context) override { 460 const int short_option = m_getopt_table[option_idx].val; 461 462 switch (short_option) { 463 case 'f': 464 m_force = true; 465 break; 466 default: 467 llvm_unreachable("Unimplemented option"); 468 } 469 470 return {}; 471 } 472 473 void OptionParsingStarting(ExecutionContext *execution_context) override { 474 m_force = false; 475 } 476 477 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 478 return llvm::ArrayRef(g_watchpoint_delete_options); 479 } 480 481 // Instance variables to hold the values for command options. 482 bool m_force = false; 483 }; 484 485 protected: 486 void DoExecute(Args &command, CommandReturnObject &result) override { 487 Target *target = &GetSelectedTarget(); 488 if (!CheckTargetForWatchpointOperations(target, result)) 489 return; 490 491 std::unique_lock<std::recursive_mutex> lock; 492 target->GetWatchpointList().GetListMutex(lock); 493 494 const WatchpointList &watchpoints = target->GetWatchpointList(); 495 496 size_t num_watchpoints = watchpoints.GetSize(); 497 498 if (num_watchpoints == 0) { 499 result.AppendError("No watchpoints exist to be deleted."); 500 return; 501 } 502 503 if (command.empty()) { 504 if (!m_options.m_force && 505 !m_interpreter.Confirm( 506 "About to delete all watchpoints, do you want to do that?", 507 true)) { 508 result.AppendMessage("Operation cancelled..."); 509 } else { 510 target->RemoveAllWatchpoints(); 511 result.AppendMessageWithFormat("All watchpoints removed. (%" PRIu64 512 " watchpoints)\n", 513 (uint64_t)num_watchpoints); 514 } 515 result.SetStatus(eReturnStatusSuccessFinishNoResult); 516 return; 517 } 518 519 // Particular watchpoints selected; delete them. 520 std::vector<uint32_t> wp_ids; 521 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs(target, command, 522 wp_ids)) { 523 result.AppendError("Invalid watchpoints specification."); 524 return; 525 } 526 527 int count = 0; 528 const size_t size = wp_ids.size(); 529 for (size_t i = 0; i < size; ++i) 530 if (target->RemoveWatchpointByID(wp_ids[i])) 531 ++count; 532 result.AppendMessageWithFormat("%d watchpoints deleted.\n", count); 533 result.SetStatus(eReturnStatusSuccessFinishNoResult); 534 } 535 536 private: 537 CommandOptions m_options; 538 }; 539 540 // CommandObjectWatchpointIgnore 541 542 #pragma mark Ignore::CommandOptions 543 #define LLDB_OPTIONS_watchpoint_ignore 544 #include "CommandOptions.inc" 545 546 class CommandObjectWatchpointIgnore : public CommandObjectParsed { 547 public: 548 CommandObjectWatchpointIgnore(CommandInterpreter &interpreter) 549 : CommandObjectParsed(interpreter, "watchpoint ignore", 550 "Set ignore count on the specified watchpoint(s). " 551 "If no watchpoints are specified, set them all.", 552 nullptr, eCommandRequiresTarget) { 553 CommandArgumentEntry arg; 554 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, 555 eArgTypeWatchpointIDRange); 556 // Add the entry for the first argument for this command to the object's 557 // arguments vector. 558 m_arguments.push_back(arg); 559 } 560 561 ~CommandObjectWatchpointIgnore() override = default; 562 563 void 564 HandleArgumentCompletion(CompletionRequest &request, 565 OptionElementVector &opt_element_vector) override { 566 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( 567 GetCommandInterpreter(), lldb::eWatchpointIDCompletion, request, 568 nullptr); 569 } 570 571 Options *GetOptions() override { return &m_options; } 572 573 class CommandOptions : public Options { 574 public: 575 CommandOptions() = default; 576 577 ~CommandOptions() override = default; 578 579 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 580 ExecutionContext *execution_context) override { 581 Status error; 582 const int short_option = m_getopt_table[option_idx].val; 583 584 switch (short_option) { 585 case 'i': 586 if (option_arg.getAsInteger(0, m_ignore_count)) 587 error.SetErrorStringWithFormat("invalid ignore count '%s'", 588 option_arg.str().c_str()); 589 break; 590 default: 591 llvm_unreachable("Unimplemented option"); 592 } 593 594 return error; 595 } 596 597 void OptionParsingStarting(ExecutionContext *execution_context) override { 598 m_ignore_count = 0; 599 } 600 601 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 602 return llvm::ArrayRef(g_watchpoint_ignore_options); 603 } 604 605 // Instance variables to hold the values for command options. 606 607 uint32_t m_ignore_count = 0; 608 }; 609 610 protected: 611 void DoExecute(Args &command, CommandReturnObject &result) override { 612 Target *target = &GetSelectedTarget(); 613 if (!CheckTargetForWatchpointOperations(target, result)) 614 return; 615 616 std::unique_lock<std::recursive_mutex> lock; 617 target->GetWatchpointList().GetListMutex(lock); 618 619 const WatchpointList &watchpoints = target->GetWatchpointList(); 620 621 size_t num_watchpoints = watchpoints.GetSize(); 622 623 if (num_watchpoints == 0) { 624 result.AppendError("No watchpoints exist to be ignored."); 625 return; 626 } 627 628 if (command.GetArgumentCount() == 0) { 629 target->IgnoreAllWatchpoints(m_options.m_ignore_count); 630 result.AppendMessageWithFormat("All watchpoints ignored. (%" PRIu64 631 " watchpoints)\n", 632 (uint64_t)num_watchpoints); 633 result.SetStatus(eReturnStatusSuccessFinishNoResult); 634 } else { 635 // Particular watchpoints selected; ignore them. 636 std::vector<uint32_t> wp_ids; 637 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs( 638 target, command, wp_ids)) { 639 result.AppendError("Invalid watchpoints specification."); 640 return; 641 } 642 643 int count = 0; 644 const size_t size = wp_ids.size(); 645 for (size_t i = 0; i < size; ++i) 646 if (target->IgnoreWatchpointByID(wp_ids[i], m_options.m_ignore_count)) 647 ++count; 648 result.AppendMessageWithFormat("%d watchpoints ignored.\n", count); 649 result.SetStatus(eReturnStatusSuccessFinishNoResult); 650 } 651 } 652 653 private: 654 CommandOptions m_options; 655 }; 656 657 // CommandObjectWatchpointModify 658 659 #pragma mark Modify::CommandOptions 660 #define LLDB_OPTIONS_watchpoint_modify 661 #include "CommandOptions.inc" 662 663 #pragma mark Modify 664 665 class CommandObjectWatchpointModify : public CommandObjectParsed { 666 public: 667 CommandObjectWatchpointModify(CommandInterpreter &interpreter) 668 : CommandObjectParsed( 669 interpreter, "watchpoint modify", 670 "Modify the options on a watchpoint or set of watchpoints in the " 671 "executable. " 672 "If no watchpoint is specified, act on the last created " 673 "watchpoint. " 674 "Passing an empty argument clears the modification.", 675 nullptr, eCommandRequiresTarget) { 676 CommandArgumentEntry arg; 677 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, 678 eArgTypeWatchpointIDRange); 679 // Add the entry for the first argument for this command to the object's 680 // arguments vector. 681 m_arguments.push_back(arg); 682 } 683 684 ~CommandObjectWatchpointModify() override = default; 685 686 void 687 HandleArgumentCompletion(CompletionRequest &request, 688 OptionElementVector &opt_element_vector) override { 689 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( 690 GetCommandInterpreter(), lldb::eWatchpointIDCompletion, request, 691 nullptr); 692 } 693 694 Options *GetOptions() override { return &m_options; } 695 696 class CommandOptions : public Options { 697 public: 698 CommandOptions() = default; 699 700 ~CommandOptions() override = default; 701 702 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 703 ExecutionContext *execution_context) override { 704 Status error; 705 const int short_option = m_getopt_table[option_idx].val; 706 707 switch (short_option) { 708 case 'c': 709 m_condition = std::string(option_arg); 710 m_condition_passed = true; 711 break; 712 default: 713 llvm_unreachable("Unimplemented option"); 714 } 715 716 return error; 717 } 718 719 void OptionParsingStarting(ExecutionContext *execution_context) override { 720 m_condition.clear(); 721 m_condition_passed = false; 722 } 723 724 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 725 return llvm::ArrayRef(g_watchpoint_modify_options); 726 } 727 728 // Instance variables to hold the values for command options. 729 730 std::string m_condition; 731 bool m_condition_passed = false; 732 }; 733 734 protected: 735 void DoExecute(Args &command, CommandReturnObject &result) override { 736 Target *target = &GetSelectedTarget(); 737 if (!CheckTargetForWatchpointOperations(target, result)) 738 return; 739 740 std::unique_lock<std::recursive_mutex> lock; 741 target->GetWatchpointList().GetListMutex(lock); 742 743 const WatchpointList &watchpoints = target->GetWatchpointList(); 744 745 size_t num_watchpoints = watchpoints.GetSize(); 746 747 if (num_watchpoints == 0) { 748 result.AppendError("No watchpoints exist to be modified."); 749 return; 750 } 751 752 if (command.GetArgumentCount() == 0) { 753 WatchpointSP watch_sp = target->GetLastCreatedWatchpoint(); 754 watch_sp->SetCondition(m_options.m_condition.c_str()); 755 result.SetStatus(eReturnStatusSuccessFinishNoResult); 756 } else { 757 // Particular watchpoints selected; set condition on them. 758 std::vector<uint32_t> wp_ids; 759 if (!CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs( 760 target, command, wp_ids)) { 761 result.AppendError("Invalid watchpoints specification."); 762 return; 763 } 764 765 int count = 0; 766 const size_t size = wp_ids.size(); 767 for (size_t i = 0; i < size; ++i) { 768 WatchpointSP watch_sp = watchpoints.FindByID(wp_ids[i]); 769 if (watch_sp) { 770 watch_sp->SetCondition(m_options.m_condition.c_str()); 771 ++count; 772 } 773 } 774 result.AppendMessageWithFormat("%d watchpoints modified.\n", count); 775 result.SetStatus(eReturnStatusSuccessFinishNoResult); 776 } 777 } 778 779 private: 780 CommandOptions m_options; 781 }; 782 783 // CommandObjectWatchpointSetVariable 784 #pragma mark SetVariable 785 786 class CommandObjectWatchpointSetVariable : public CommandObjectParsed { 787 public: 788 CommandObjectWatchpointSetVariable(CommandInterpreter &interpreter) 789 : CommandObjectParsed( 790 interpreter, "watchpoint set variable", 791 "Set a watchpoint on a variable. " 792 "Use the '-w' option to specify the type of watchpoint and " 793 "the '-s' option to specify the byte size to watch for. " 794 "If no '-w' option is specified, it defaults to modify. " 795 "If no '-s' option is specified, it defaults to the variable's " 796 "byte size. " 797 "Note that there are limited hardware resources for watchpoints. " 798 "If watchpoint setting fails, consider disable/delete existing " 799 "ones " 800 "to free up resources.", 801 nullptr, 802 eCommandRequiresFrame | eCommandTryTargetAPILock | 803 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) { 804 SetHelpLong( 805 R"( 806 Examples: 807 808 (lldb) watchpoint set variable -w read_write my_global_var 809 810 )" 811 " Watches my_global_var for read/write access, with the region to watch \ 812 corresponding to the byte size of the data type."); 813 814 CommandArgumentEntry arg; 815 CommandArgumentData var_name_arg; 816 817 // Define the only variant of this arg. 818 var_name_arg.arg_type = eArgTypeVarName; 819 var_name_arg.arg_repetition = eArgRepeatPlain; 820 821 // Push the variant into the argument entry. 822 arg.push_back(var_name_arg); 823 824 // Push the data for the only argument into the m_arguments vector. 825 m_arguments.push_back(arg); 826 827 // Absorb the '-w' and '-s' options into our option group. 828 m_option_group.Append(&m_option_watchpoint, LLDB_OPT_SET_1, LLDB_OPT_SET_1); 829 m_option_group.Finalize(); 830 } 831 832 ~CommandObjectWatchpointSetVariable() override = default; 833 834 void 835 HandleArgumentCompletion(CompletionRequest &request, 836 OptionElementVector &opt_element_vector) override { 837 if (request.GetCursorIndex() != 0) 838 return; 839 lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks( 840 GetCommandInterpreter(), lldb::eVariablePathCompletion, request, 841 nullptr); 842 } 843 844 Options *GetOptions() override { return &m_option_group; } 845 846 protected: 847 static size_t GetVariableCallback(void *baton, const char *name, 848 VariableList &variable_list) { 849 size_t old_size = variable_list.GetSize(); 850 Target *target = static_cast<Target *>(baton); 851 if (target) 852 target->GetImages().FindGlobalVariables(ConstString(name), UINT32_MAX, 853 variable_list); 854 return variable_list.GetSize() - old_size; 855 } 856 857 void DoExecute(Args &command, CommandReturnObject &result) override { 858 Target *target = GetDebugger().GetSelectedTarget().get(); 859 StackFrame *frame = m_exe_ctx.GetFramePtr(); 860 861 // If no argument is present, issue an error message. There's no way to 862 // set a watchpoint. 863 if (command.GetArgumentCount() <= 0) { 864 result.AppendError("required argument missing; " 865 "specify your program variable to watch for"); 866 return; 867 } 868 869 // If no '-w' is specified, default to '-w modify'. 870 if (!m_option_watchpoint.watch_type_specified) { 871 m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchModify; 872 } 873 874 // We passed the sanity check for the command. Proceed to set the 875 // watchpoint now. 876 lldb::addr_t addr = 0; 877 size_t size = 0; 878 879 VariableSP var_sp; 880 ValueObjectSP valobj_sp; 881 Stream &output_stream = result.GetOutputStream(); 882 883 // A simple watch variable gesture allows only one argument. 884 if (command.GetArgumentCount() != 1) { 885 result.AppendError("specify exactly one variable to watch for"); 886 return; 887 } 888 889 // Things have checked out ok... 890 Status error; 891 uint32_t expr_path_options = 892 StackFrame::eExpressionPathOptionCheckPtrVsMember | 893 StackFrame::eExpressionPathOptionsAllowDirectIVarAccess; 894 valobj_sp = frame->GetValueForVariableExpressionPath( 895 command.GetArgumentAtIndex(0), eNoDynamicValues, expr_path_options, 896 var_sp, error); 897 898 if (!valobj_sp) { 899 // Not in the frame; let's check the globals. 900 901 VariableList variable_list; 902 ValueObjectList valobj_list; 903 904 Status error(Variable::GetValuesForVariableExpressionPath( 905 command.GetArgumentAtIndex(0), 906 m_exe_ctx.GetBestExecutionContextScope(), GetVariableCallback, target, 907 variable_list, valobj_list)); 908 909 if (valobj_list.GetSize()) 910 valobj_sp = valobj_list.GetValueObjectAtIndex(0); 911 } 912 913 CompilerType compiler_type; 914 915 if (valobj_sp) { 916 AddressType addr_type; 917 addr = valobj_sp->GetAddressOf(false, &addr_type); 918 if (addr_type == eAddressTypeLoad) { 919 // We're in business. 920 // Find out the size of this variable. 921 size = m_option_watchpoint.watch_size.GetCurrentValue() == 0 922 ? valobj_sp->GetByteSize().value_or(0) 923 : m_option_watchpoint.watch_size.GetCurrentValue(); 924 } 925 compiler_type = valobj_sp->GetCompilerType(); 926 } else { 927 const char *error_cstr = error.AsCString(nullptr); 928 if (error_cstr) 929 result.AppendError(error_cstr); 930 else 931 result.AppendErrorWithFormat("unable to find any variable " 932 "expression path that matches '%s'", 933 command.GetArgumentAtIndex(0)); 934 return; 935 } 936 937 // Now it's time to create the watchpoint. 938 uint32_t watch_type = 0; 939 switch (m_option_watchpoint.watch_type) { 940 case OptionGroupWatchpoint::eWatchModify: 941 watch_type |= LLDB_WATCH_TYPE_MODIFY; 942 break; 943 case OptionGroupWatchpoint::eWatchRead: 944 watch_type |= LLDB_WATCH_TYPE_READ; 945 break; 946 case OptionGroupWatchpoint::eWatchReadWrite: 947 watch_type |= LLDB_WATCH_TYPE_READ | LLDB_WATCH_TYPE_WRITE; 948 break; 949 case OptionGroupWatchpoint::eWatchWrite: 950 watch_type |= LLDB_WATCH_TYPE_WRITE; 951 break; 952 case OptionGroupWatchpoint::eWatchInvalid: 953 break; 954 }; 955 956 error.Clear(); 957 WatchpointSP watch_sp = 958 target->CreateWatchpoint(addr, size, &compiler_type, watch_type, error); 959 if (!watch_sp) { 960 result.AppendErrorWithFormat( 961 "Watchpoint creation failed (addr=0x%" PRIx64 ", size=%" PRIu64 962 ", variable expression='%s').\n", 963 addr, static_cast<uint64_t>(size), command.GetArgumentAtIndex(0)); 964 if (const char *error_message = error.AsCString(nullptr)) 965 result.AppendError(error_message); 966 return; 967 } 968 969 watch_sp->SetWatchSpec(command.GetArgumentAtIndex(0)); 970 watch_sp->SetWatchVariable(true); 971 if (var_sp) { 972 if (var_sp->GetDeclaration().GetFile()) { 973 StreamString ss; 974 // True to show fullpath for declaration file. 975 var_sp->GetDeclaration().DumpStopContext(&ss, true); 976 watch_sp->SetDeclInfo(std::string(ss.GetString())); 977 } 978 if (var_sp->GetScope() == eValueTypeVariableLocal) 979 watch_sp->SetupVariableWatchpointDisabler(m_exe_ctx.GetFrameSP()); 980 } 981 output_stream.Printf("Watchpoint created: "); 982 watch_sp->GetDescription(&output_stream, lldb::eDescriptionLevelFull); 983 output_stream.EOL(); 984 result.SetStatus(eReturnStatusSuccessFinishResult); 985 } 986 987 private: 988 OptionGroupOptions m_option_group; 989 OptionGroupWatchpoint m_option_watchpoint; 990 }; 991 992 // CommandObjectWatchpointSetExpression 993 #pragma mark Set 994 995 class CommandObjectWatchpointSetExpression : public CommandObjectRaw { 996 public: 997 CommandObjectWatchpointSetExpression(CommandInterpreter &interpreter) 998 : CommandObjectRaw( 999 interpreter, "watchpoint set expression", 1000 "Set a watchpoint on an address by supplying an expression. " 1001 "Use the '-l' option to specify the language of the expression. " 1002 "Use the '-w' option to specify the type of watchpoint and " 1003 "the '-s' option to specify the byte size to watch for. " 1004 "If no '-w' option is specified, it defaults to modify. " 1005 "If no '-s' option is specified, it defaults to the target's " 1006 "pointer byte size. " 1007 "Note that there are limited hardware resources for watchpoints. " 1008 "If watchpoint setting fails, consider disable/delete existing " 1009 "ones " 1010 "to free up resources.", 1011 "", 1012 eCommandRequiresFrame | eCommandTryTargetAPILock | 1013 eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) { 1014 SetHelpLong( 1015 R"( 1016 Examples: 1017 1018 (lldb) watchpoint set expression -w modify -s 1 -- foo + 32 1019 1020 Watches write access for the 1-byte region pointed to by the address 'foo + 32')"); 1021 1022 CommandArgumentEntry arg; 1023 CommandArgumentData expression_arg; 1024 1025 // Define the only variant of this arg. 1026 expression_arg.arg_type = eArgTypeExpression; 1027 expression_arg.arg_repetition = eArgRepeatPlain; 1028 1029 // Push the only variant into the argument entry. 1030 arg.push_back(expression_arg); 1031 1032 // Push the data for the only argument into the m_arguments vector. 1033 m_arguments.push_back(arg); 1034 1035 // Absorb the '-w' and '-s' options into our option group. 1036 m_option_group.Append(&m_option_watchpoint, LLDB_OPT_SET_ALL, 1037 LLDB_OPT_SET_1); 1038 m_option_group.Finalize(); 1039 } 1040 1041 ~CommandObjectWatchpointSetExpression() override = default; 1042 1043 // Overrides base class's behavior where WantsCompletion = 1044 // !WantsRawCommandString. 1045 bool WantsCompletion() override { return true; } 1046 1047 Options *GetOptions() override { return &m_option_group; } 1048 1049 protected: 1050 void DoExecute(llvm::StringRef raw_command, 1051 CommandReturnObject &result) override { 1052 auto exe_ctx = GetCommandInterpreter().GetExecutionContext(); 1053 m_option_group.NotifyOptionParsingStarting( 1054 &exe_ctx); // This is a raw command, so notify the option group 1055 1056 Target *target = GetDebugger().GetSelectedTarget().get(); 1057 StackFrame *frame = m_exe_ctx.GetFramePtr(); 1058 1059 OptionsWithRaw args(raw_command); 1060 1061 llvm::StringRef expr = args.GetRawPart(); 1062 1063 if (args.HasArgs()) 1064 if (!ParseOptionsAndNotify(args.GetArgs(), result, m_option_group, 1065 exe_ctx)) 1066 return; 1067 1068 // If no argument is present, issue an error message. There's no way to 1069 // set a watchpoint. 1070 if (raw_command.trim().empty()) { 1071 result.AppendError("required argument missing; specify an expression " 1072 "to evaluate into the address to watch for"); 1073 return; 1074 } 1075 1076 // If no '-w' is specified, default to '-w write'. 1077 if (!m_option_watchpoint.watch_type_specified) { 1078 m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchModify; 1079 } 1080 1081 // We passed the sanity check for the command. Proceed to set the 1082 // watchpoint now. 1083 lldb::addr_t addr = 0; 1084 size_t size = 0; 1085 1086 ValueObjectSP valobj_sp; 1087 1088 // Use expression evaluation to arrive at the address to watch. 1089 EvaluateExpressionOptions options; 1090 options.SetCoerceToId(false); 1091 options.SetUnwindOnError(true); 1092 options.SetKeepInMemory(false); 1093 options.SetTryAllThreads(true); 1094 options.SetTimeout(std::nullopt); 1095 if (m_option_watchpoint.language_type != eLanguageTypeUnknown) 1096 options.SetLanguage(m_option_watchpoint.language_type); 1097 1098 ExpressionResults expr_result = 1099 target->EvaluateExpression(expr, frame, valobj_sp, options); 1100 if (expr_result != eExpressionCompleted) { 1101 result.AppendError("expression evaluation of address to watch failed"); 1102 result.AppendErrorWithFormat("expression evaluated: \n%s", expr.data()); 1103 if (valobj_sp && !valobj_sp->GetError().Success()) 1104 result.AppendError(valobj_sp->GetError().AsCString()); 1105 return; 1106 } 1107 1108 // Get the address to watch. 1109 bool success = false; 1110 addr = valobj_sp->GetValueAsUnsigned(0, &success); 1111 if (!success) { 1112 result.AppendError("expression did not evaluate to an address"); 1113 return; 1114 } 1115 1116 if (m_option_watchpoint.watch_size.GetCurrentValue() != 0) 1117 size = m_option_watchpoint.watch_size.GetCurrentValue(); 1118 else 1119 size = target->GetArchitecture().GetAddressByteSize(); 1120 1121 // Now it's time to create the watchpoint. 1122 uint32_t watch_type; 1123 switch (m_option_watchpoint.watch_type) { 1124 case OptionGroupWatchpoint::eWatchRead: 1125 watch_type = LLDB_WATCH_TYPE_READ; 1126 break; 1127 case OptionGroupWatchpoint::eWatchWrite: 1128 watch_type = LLDB_WATCH_TYPE_WRITE; 1129 break; 1130 case OptionGroupWatchpoint::eWatchModify: 1131 watch_type = LLDB_WATCH_TYPE_MODIFY; 1132 break; 1133 case OptionGroupWatchpoint::eWatchReadWrite: 1134 watch_type = LLDB_WATCH_TYPE_READ | LLDB_WATCH_TYPE_WRITE; 1135 break; 1136 default: 1137 watch_type = LLDB_WATCH_TYPE_MODIFY; 1138 } 1139 1140 // Fetch the type from the value object, the type of the watched object is 1141 // the pointee type 1142 /// of the expression, so convert to that if we found a valid type. 1143 CompilerType compiler_type(valobj_sp->GetCompilerType()); 1144 1145 Status error; 1146 WatchpointSP watch_sp = 1147 target->CreateWatchpoint(addr, size, &compiler_type, watch_type, error); 1148 if (watch_sp) { 1149 watch_sp->SetWatchSpec(std::string(expr)); 1150 Stream &output_stream = result.GetOutputStream(); 1151 output_stream.Printf("Watchpoint created: "); 1152 watch_sp->GetDescription(&output_stream, lldb::eDescriptionLevelFull); 1153 output_stream.EOL(); 1154 result.SetStatus(eReturnStatusSuccessFinishResult); 1155 } else { 1156 result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%" PRIx64 1157 ", size=%" PRIu64 ").\n", 1158 addr, (uint64_t)size); 1159 if (error.AsCString(nullptr)) 1160 result.AppendError(error.AsCString()); 1161 } 1162 } 1163 1164 private: 1165 OptionGroupOptions m_option_group; 1166 OptionGroupWatchpoint m_option_watchpoint; 1167 }; 1168 1169 // CommandObjectWatchpointSet 1170 #pragma mark Set 1171 1172 class CommandObjectWatchpointSet : public CommandObjectMultiword { 1173 public: 1174 CommandObjectWatchpointSet(CommandInterpreter &interpreter) 1175 : CommandObjectMultiword( 1176 interpreter, "watchpoint set", "Commands for setting a watchpoint.", 1177 "watchpoint set <subcommand> [<subcommand-options>]") { 1178 1179 LoadSubCommand( 1180 "variable", 1181 CommandObjectSP(new CommandObjectWatchpointSetVariable(interpreter))); 1182 LoadSubCommand( 1183 "expression", 1184 CommandObjectSP(new CommandObjectWatchpointSetExpression(interpreter))); 1185 } 1186 1187 ~CommandObjectWatchpointSet() override = default; 1188 }; 1189 1190 // CommandObjectMultiwordWatchpoint 1191 #pragma mark MultiwordWatchpoint 1192 1193 CommandObjectMultiwordWatchpoint::CommandObjectMultiwordWatchpoint( 1194 CommandInterpreter &interpreter) 1195 : CommandObjectMultiword(interpreter, "watchpoint", 1196 "Commands for operating on watchpoints.", 1197 "watchpoint <subcommand> [<command-options>]") { 1198 CommandObjectSP list_command_object( 1199 new CommandObjectWatchpointList(interpreter)); 1200 CommandObjectSP enable_command_object( 1201 new CommandObjectWatchpointEnable(interpreter)); 1202 CommandObjectSP disable_command_object( 1203 new CommandObjectWatchpointDisable(interpreter)); 1204 CommandObjectSP delete_command_object( 1205 new CommandObjectWatchpointDelete(interpreter)); 1206 CommandObjectSP ignore_command_object( 1207 new CommandObjectWatchpointIgnore(interpreter)); 1208 CommandObjectSP command_command_object( 1209 new CommandObjectWatchpointCommand(interpreter)); 1210 CommandObjectSP modify_command_object( 1211 new CommandObjectWatchpointModify(interpreter)); 1212 CommandObjectSP set_command_object( 1213 new CommandObjectWatchpointSet(interpreter)); 1214 1215 list_command_object->SetCommandName("watchpoint list"); 1216 enable_command_object->SetCommandName("watchpoint enable"); 1217 disable_command_object->SetCommandName("watchpoint disable"); 1218 delete_command_object->SetCommandName("watchpoint delete"); 1219 ignore_command_object->SetCommandName("watchpoint ignore"); 1220 command_command_object->SetCommandName("watchpoint command"); 1221 modify_command_object->SetCommandName("watchpoint modify"); 1222 set_command_object->SetCommandName("watchpoint set"); 1223 1224 LoadSubCommand("list", list_command_object); 1225 LoadSubCommand("enable", enable_command_object); 1226 LoadSubCommand("disable", disable_command_object); 1227 LoadSubCommand("delete", delete_command_object); 1228 LoadSubCommand("ignore", ignore_command_object); 1229 LoadSubCommand("command", command_command_object); 1230 LoadSubCommand("modify", modify_command_object); 1231 LoadSubCommand("set", set_command_object); 1232 } 1233 1234 CommandObjectMultiwordWatchpoint::~CommandObjectMultiwordWatchpoint() = default; 1235