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