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