1 //===-- CommandObjectWatchpoint.cpp -----------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "CommandObjectWatchpoint.h" 11 12 // C Includes 13 // C++ Includes 14 // Other libraries and framework includes 15 // Project includes 16 #include "lldb/Breakpoint/Watchpoint.h" 17 #include "lldb/Breakpoint/WatchpointList.h" 18 #include "lldb/Core/StreamString.h" 19 #include "lldb/Interpreter/CommandInterpreter.h" 20 #include "lldb/Interpreter/CommandReturnObject.h" 21 #include "lldb/Target/Target.h" 22 #include "lldb/Interpreter/CommandCompletions.h" 23 24 #include <vector> 25 26 using namespace lldb; 27 using namespace lldb_private; 28 29 static void 30 AddWatchpointDescription(Stream *s, Watchpoint *wp, lldb::DescriptionLevel level) 31 { 32 s->IndentMore(); 33 wp->GetDescription(s, level); 34 s->IndentLess(); 35 s->EOL(); 36 } 37 38 static bool 39 CheckTargetForWatchpointOperations(Target *target, CommandReturnObject &result) 40 { 41 if (target == NULL) 42 { 43 result.AppendError ("Invalid target. No existing target or watchpoints."); 44 result.SetStatus (eReturnStatusFailed); 45 return false; 46 } 47 bool process_is_valid = target->GetProcessSP() && target->GetProcessSP()->IsAlive(); 48 if (!process_is_valid) 49 { 50 result.AppendError ("Thre's no process or it is not alive."); 51 result.SetStatus (eReturnStatusFailed); 52 return false; 53 } 54 // Target passes our checks, return true. 55 return true; 56 } 57 58 #include "llvm/ADT/StringRef.h" 59 60 // Equivalent class: {"-", "to", "To", "TO"} of range specifier array. 61 static const char* RSA[4] = { "-", "to", "To", "TO" }; 62 63 // Return the index to RSA if found; otherwise -1 is returned. 64 static int32_t 65 WithRSAIndex(llvm::StringRef &Arg) 66 { 67 68 uint32_t i; 69 for (i = 0; i < 4; ++i) 70 if (Arg.find(RSA[i]) != llvm::StringRef::npos) 71 return i; 72 return -1; 73 } 74 75 // Return true if wp_ids is successfully populated with the watch ids. 76 // False otherwise. 77 static bool 78 VerifyWatchpointIDs(Args &args, std::vector<uint32_t> &wp_ids) 79 { 80 // Pre-condition: args.GetArgumentCount() > 0. 81 assert(args.GetArgumentCount() > 0); 82 83 llvm::StringRef Minus("-"); 84 std::vector<llvm::StringRef> StrRefArgs; 85 std::pair<llvm::StringRef, llvm::StringRef> Pair; 86 size_t i; 87 int32_t idx; 88 // Go through the argments and make a canonical form of arg list containing 89 // only numbers with possible "-" in between. 90 for (i = 0; i < args.GetArgumentCount(); ++i) { 91 llvm::StringRef Arg(args.GetArgumentAtIndex(i)); 92 if ((idx = WithRSAIndex(Arg)) == -1) { 93 StrRefArgs.push_back(Arg); 94 continue; 95 } 96 // The Arg contains the range specifier, split it, then. 97 Pair = Arg.split(RSA[idx]); 98 if (!Pair.first.empty()) 99 StrRefArgs.push_back(Pair.first); 100 StrRefArgs.push_back(Minus); 101 if (!Pair.second.empty()) 102 StrRefArgs.push_back(Pair.second); 103 } 104 // Now process the canonical list and fill in the vector of uint32_t's. 105 // If 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; in_range = true; 127 continue; 128 } 129 // Otherwise, we have a simple ID. Just append it. 130 if (Arg.getAsInteger(0, beg)) 131 return false; 132 wp_ids.push_back(beg); 133 } 134 // It is an error if after the loop, we're still in_range. 135 if (in_range) 136 return false; 137 138 return true; // Success! 139 } 140 141 //------------------------------------------------------------------------- 142 // CommandObjectMultiwordWatchpoint 143 //------------------------------------------------------------------------- 144 #pragma mark MultiwordWatchpoint 145 146 CommandObjectMultiwordWatchpoint::CommandObjectMultiwordWatchpoint(CommandInterpreter &interpreter) : 147 CommandObjectMultiword (interpreter, 148 "watchpoint", 149 "A set of commands for operating on watchpoints.", 150 "watchpoint <command> [<command-options>]") 151 { 152 bool status; 153 154 CommandObjectSP list_command_object (new CommandObjectWatchpointList (interpreter)); 155 CommandObjectSP enable_command_object (new CommandObjectWatchpointEnable (interpreter)); 156 CommandObjectSP disable_command_object (new CommandObjectWatchpointDisable (interpreter)); 157 CommandObjectSP delete_command_object (new CommandObjectWatchpointDelete (interpreter)); 158 CommandObjectSP ignore_command_object (new CommandObjectWatchpointIgnore (interpreter)); 159 CommandObjectSP modify_command_object (new CommandObjectWatchpointModify (interpreter)); 160 161 list_command_object->SetCommandName ("watchpoint list"); 162 enable_command_object->SetCommandName("watchpoint enable"); 163 disable_command_object->SetCommandName("watchpoint disable"); 164 delete_command_object->SetCommandName("watchpoint delete"); 165 ignore_command_object->SetCommandName("watchpoint ignore"); 166 modify_command_object->SetCommandName("watchpoint modify"); 167 168 status = LoadSubCommand ("list", list_command_object); 169 status = LoadSubCommand ("enable", enable_command_object); 170 status = LoadSubCommand ("disable", disable_command_object); 171 status = LoadSubCommand ("delete", delete_command_object); 172 status = LoadSubCommand ("ignore", ignore_command_object); 173 status = LoadSubCommand ("modify", modify_command_object); 174 } 175 176 CommandObjectMultiwordWatchpoint::~CommandObjectMultiwordWatchpoint() 177 { 178 } 179 180 //------------------------------------------------------------------------- 181 // CommandObjectWatchpointList::Options 182 //------------------------------------------------------------------------- 183 #pragma mark List::CommandOptions 184 185 CommandObjectWatchpointList::CommandOptions::CommandOptions(CommandInterpreter &interpreter) : 186 Options(interpreter), 187 m_level(lldb::eDescriptionLevelBrief) // Watchpoint List defaults to brief descriptions 188 { 189 } 190 191 CommandObjectWatchpointList::CommandOptions::~CommandOptions() 192 { 193 } 194 195 OptionDefinition 196 CommandObjectWatchpointList::CommandOptions::g_option_table[] = 197 { 198 { LLDB_OPT_SET_1, false, "brief", 'b', no_argument, NULL, 0, eArgTypeNone, 199 "Give a brief description of the watchpoint (no location info)."}, 200 201 { LLDB_OPT_SET_2, false, "full", 'f', no_argument, NULL, 0, eArgTypeNone, 202 "Give a full description of the watchpoint and its locations."}, 203 204 { LLDB_OPT_SET_3, false, "verbose", 'v', no_argument, NULL, 0, eArgTypeNone, 205 "Explain everything we know about the watchpoint (for debugging debugger bugs)." }, 206 207 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 208 }; 209 210 const OptionDefinition* 211 CommandObjectWatchpointList::CommandOptions::GetDefinitions() 212 { 213 return g_option_table; 214 } 215 216 Error 217 CommandObjectWatchpointList::CommandOptions::SetOptionValue(uint32_t option_idx, const char *option_arg) 218 { 219 Error error; 220 char short_option = (char) m_getopt_table[option_idx].val; 221 222 switch (short_option) 223 { 224 case 'b': 225 m_level = lldb::eDescriptionLevelBrief; 226 break; 227 case 'f': 228 m_level = lldb::eDescriptionLevelFull; 229 break; 230 case 'v': 231 m_level = lldb::eDescriptionLevelVerbose; 232 break; 233 default: 234 error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); 235 break; 236 } 237 238 return error; 239 } 240 241 void 242 CommandObjectWatchpointList::CommandOptions::OptionParsingStarting() 243 { 244 m_level = lldb::eDescriptionLevelFull; 245 } 246 247 //------------------------------------------------------------------------- 248 // CommandObjectWatchpointList 249 //------------------------------------------------------------------------- 250 #pragma mark List 251 252 CommandObjectWatchpointList::CommandObjectWatchpointList(CommandInterpreter &interpreter) : 253 CommandObject(interpreter, 254 "watchpoint list", 255 "List all watchpoints at configurable levels of detail.", 256 NULL), 257 m_options(interpreter) 258 { 259 CommandArgumentEntry arg; 260 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); 261 // Add the entry for the first argument for this command to the object's arguments vector. 262 m_arguments.push_back(arg); 263 } 264 265 CommandObjectWatchpointList::~CommandObjectWatchpointList() 266 { 267 } 268 269 Options * 270 CommandObjectWatchpointList::GetOptions() 271 { 272 return &m_options; 273 } 274 275 bool 276 CommandObjectWatchpointList::Execute(Args& args, CommandReturnObject &result) 277 { 278 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 279 if (target == NULL) 280 { 281 result.AppendError ("Invalid target. No current target or watchpoints."); 282 result.SetStatus (eReturnStatusSuccessFinishNoResult); 283 return true; 284 } 285 286 const WatchpointList &watchpoints = target->GetWatchpointList(); 287 Mutex::Locker locker; 288 target->GetWatchpointList().GetListMutex(locker); 289 290 size_t num_watchpoints = watchpoints.GetSize(); 291 292 if (num_watchpoints == 0) 293 { 294 result.AppendMessage("No watchpoints currently set."); 295 result.SetStatus(eReturnStatusSuccessFinishNoResult); 296 return true; 297 } 298 299 Stream &output_stream = result.GetOutputStream(); 300 301 if (args.GetArgumentCount() == 0) 302 { 303 // No watchpoint selected; show info about all currently set watchpoints. 304 result.AppendMessage ("Current watchpoints:"); 305 for (size_t i = 0; i < num_watchpoints; ++i) 306 { 307 Watchpoint *wp = watchpoints.GetByIndex(i).get(); 308 AddWatchpointDescription(&output_stream, wp, m_options.m_level); 309 } 310 result.SetStatus(eReturnStatusSuccessFinishNoResult); 311 } 312 else 313 { 314 // Particular watchpoints selected; enable them. 315 std::vector<uint32_t> wp_ids; 316 if (!VerifyWatchpointIDs(args, wp_ids)) 317 { 318 result.AppendError("Invalid watchpoints specification."); 319 result.SetStatus(eReturnStatusFailed); 320 return false; 321 } 322 323 const size_t size = wp_ids.size(); 324 for (size_t i = 0; i < size; ++i) 325 { 326 Watchpoint *wp = watchpoints.FindByID(wp_ids[i]).get(); 327 if (wp) 328 AddWatchpointDescription(&output_stream, wp, m_options.m_level); 329 result.SetStatus(eReturnStatusSuccessFinishNoResult); 330 } 331 } 332 333 return result.Succeeded(); 334 } 335 336 //------------------------------------------------------------------------- 337 // CommandObjectWatchpointEnable 338 //------------------------------------------------------------------------- 339 #pragma mark Enable 340 341 CommandObjectWatchpointEnable::CommandObjectWatchpointEnable(CommandInterpreter &interpreter) : 342 CommandObject(interpreter, 343 "enable", 344 "Enable the specified disabled watchpoint(s). If no watchpoints are specified, enable all of them.", 345 NULL) 346 { 347 CommandArgumentEntry arg; 348 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); 349 // Add the entry for the first argument for this command to the object's arguments vector. 350 m_arguments.push_back(arg); 351 } 352 353 CommandObjectWatchpointEnable::~CommandObjectWatchpointEnable() 354 { 355 } 356 357 bool 358 CommandObjectWatchpointEnable::Execute(Args& args, CommandReturnObject &result) 359 { 360 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 361 if (!CheckTargetForWatchpointOperations(target, result)) 362 return false; 363 364 Mutex::Locker locker; 365 target->GetWatchpointList().GetListMutex(locker); 366 367 const WatchpointList &watchpoints = target->GetWatchpointList(); 368 369 size_t num_watchpoints = watchpoints.GetSize(); 370 371 if (num_watchpoints == 0) 372 { 373 result.AppendError("No watchpoints exist to be enabled."); 374 result.SetStatus(eReturnStatusFailed); 375 return false; 376 } 377 378 if (args.GetArgumentCount() == 0) 379 { 380 // No watchpoint selected; enable all currently set watchpoints. 381 target->EnableAllWatchpoints(); 382 result.AppendMessageWithFormat("All watchpoints enabled. (%lu watchpoints)\n", num_watchpoints); 383 result.SetStatus(eReturnStatusSuccessFinishNoResult); 384 } 385 else 386 { 387 // Particular watchpoints selected; enable them. 388 std::vector<uint32_t> wp_ids; 389 if (!VerifyWatchpointIDs(args, wp_ids)) 390 { 391 result.AppendError("Invalid watchpoints specification."); 392 result.SetStatus(eReturnStatusFailed); 393 return false; 394 } 395 396 int count = 0; 397 const size_t size = wp_ids.size(); 398 for (size_t i = 0; i < size; ++i) 399 if (target->EnableWatchpointByID(wp_ids[i])) 400 ++count; 401 result.AppendMessageWithFormat("%d watchpoints enabled.\n", count); 402 result.SetStatus(eReturnStatusSuccessFinishNoResult); 403 } 404 405 return result.Succeeded(); 406 } 407 408 //------------------------------------------------------------------------- 409 // CommandObjectWatchpointDisable 410 //------------------------------------------------------------------------- 411 #pragma mark Disable 412 413 CommandObjectWatchpointDisable::CommandObjectWatchpointDisable(CommandInterpreter &interpreter) : 414 CommandObject(interpreter, 415 "watchpoint disable", 416 "Disable the specified watchpoint(s) without removing it/them. If no watchpoints are specified, disable them all.", 417 NULL) 418 { 419 CommandArgumentEntry arg; 420 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); 421 // Add the entry for the first argument for this command to the object's arguments vector. 422 m_arguments.push_back(arg); 423 } 424 425 CommandObjectWatchpointDisable::~CommandObjectWatchpointDisable() 426 { 427 } 428 429 bool 430 CommandObjectWatchpointDisable::Execute(Args& args, CommandReturnObject &result) 431 { 432 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 433 if (!CheckTargetForWatchpointOperations(target, result)) 434 return false; 435 436 Mutex::Locker locker; 437 target->GetWatchpointList().GetListMutex(locker); 438 439 const WatchpointList &watchpoints = target->GetWatchpointList(); 440 size_t num_watchpoints = watchpoints.GetSize(); 441 442 if (num_watchpoints == 0) 443 { 444 result.AppendError("No watchpoints exist to be disabled."); 445 result.SetStatus(eReturnStatusFailed); 446 return false; 447 } 448 449 if (args.GetArgumentCount() == 0) 450 { 451 // No watchpoint selected; disable all currently set watchpoints. 452 if (target->DisableAllWatchpoints()) 453 { 454 result.AppendMessageWithFormat("All watchpoints disabled. (%lu watchpoints)\n", num_watchpoints); 455 result.SetStatus(eReturnStatusSuccessFinishNoResult); 456 } 457 else 458 { 459 result.AppendError("Disable all watchpoints failed\n"); 460 result.SetStatus(eReturnStatusFailed); 461 } 462 } 463 else 464 { 465 // Particular watchpoints selected; disable them. 466 std::vector<uint32_t> wp_ids; 467 if (!VerifyWatchpointIDs(args, wp_ids)) 468 { 469 result.AppendError("Invalid watchpoints specification."); 470 result.SetStatus(eReturnStatusFailed); 471 return false; 472 } 473 474 int count = 0; 475 const size_t size = wp_ids.size(); 476 for (size_t i = 0; i < size; ++i) 477 if (target->DisableWatchpointByID(wp_ids[i])) 478 ++count; 479 result.AppendMessageWithFormat("%d watchpoints disabled.\n", count); 480 result.SetStatus(eReturnStatusSuccessFinishNoResult); 481 } 482 483 return result.Succeeded(); 484 } 485 486 //------------------------------------------------------------------------- 487 // CommandObjectWatchpointDelete 488 //------------------------------------------------------------------------- 489 #pragma mark Delete 490 491 CommandObjectWatchpointDelete::CommandObjectWatchpointDelete(CommandInterpreter &interpreter) : 492 CommandObject(interpreter, 493 "watchpoint delete", 494 "Delete the specified watchpoint(s). If no watchpoints are specified, delete them all.", 495 NULL) 496 { 497 CommandArgumentEntry arg; 498 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); 499 // Add the entry for the first argument for this command to the object's arguments vector. 500 m_arguments.push_back(arg); 501 } 502 503 CommandObjectWatchpointDelete::~CommandObjectWatchpointDelete() 504 { 505 } 506 507 bool 508 CommandObjectWatchpointDelete::Execute(Args& args, CommandReturnObject &result) 509 { 510 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 511 if (!CheckTargetForWatchpointOperations(target, result)) 512 return false; 513 514 Mutex::Locker locker; 515 target->GetWatchpointList().GetListMutex(locker); 516 517 const WatchpointList &watchpoints = target->GetWatchpointList(); 518 519 size_t num_watchpoints = watchpoints.GetSize(); 520 521 if (num_watchpoints == 0) 522 { 523 result.AppendError("No watchpoints exist to be deleted."); 524 result.SetStatus(eReturnStatusFailed); 525 return false; 526 } 527 528 if (args.GetArgumentCount() == 0) 529 { 530 if (!m_interpreter.Confirm("About to delete all watchpoints, do you want to do that?", true)) 531 { 532 result.AppendMessage("Operation cancelled..."); 533 } 534 else 535 { 536 target->RemoveAllWatchpoints(); 537 result.AppendMessageWithFormat("All watchpoints removed. (%lu watchpoints)\n", num_watchpoints); 538 } 539 result.SetStatus (eReturnStatusSuccessFinishNoResult); 540 } 541 else 542 { 543 // Particular watchpoints selected; delete them. 544 std::vector<uint32_t> wp_ids; 545 if (!VerifyWatchpointIDs(args, wp_ids)) 546 { 547 result.AppendError("Invalid watchpoints specification."); 548 result.SetStatus(eReturnStatusFailed); 549 return false; 550 } 551 552 int count = 0; 553 const size_t size = wp_ids.size(); 554 for (size_t i = 0; i < size; ++i) 555 if (target->RemoveWatchpointByID(wp_ids[i])) 556 ++count; 557 result.AppendMessageWithFormat("%d watchpoints deleted.\n",count); 558 result.SetStatus (eReturnStatusSuccessFinishNoResult); 559 } 560 561 return result.Succeeded(); 562 } 563 564 //------------------------------------------------------------------------- 565 // CommandObjectWatchpointIgnore::CommandOptions 566 //------------------------------------------------------------------------- 567 #pragma mark Ignore::CommandOptions 568 569 CommandObjectWatchpointIgnore::CommandOptions::CommandOptions(CommandInterpreter &interpreter) : 570 Options (interpreter), 571 m_ignore_count (0) 572 { 573 } 574 575 CommandObjectWatchpointIgnore::CommandOptions::~CommandOptions () 576 { 577 } 578 579 OptionDefinition 580 CommandObjectWatchpointIgnore::CommandOptions::g_option_table[] = 581 { 582 { LLDB_OPT_SET_ALL, true, "ignore-count", 'i', required_argument, NULL, NULL, eArgTypeCount, "Set the number of times this watchpoint is skipped before stopping." }, 583 { 0, false, NULL, 0 , 0, NULL, 0, eArgTypeNone, NULL } 584 }; 585 586 const OptionDefinition* 587 CommandObjectWatchpointIgnore::CommandOptions::GetDefinitions () 588 { 589 return g_option_table; 590 } 591 592 Error 593 CommandObjectWatchpointIgnore::CommandOptions::SetOptionValue (uint32_t option_idx, const char *option_arg) 594 { 595 Error error; 596 char short_option = (char) m_getopt_table[option_idx].val; 597 598 switch (short_option) 599 { 600 case 'i': 601 { 602 m_ignore_count = Args::StringToUInt32(option_arg, UINT32_MAX, 0); 603 if (m_ignore_count == UINT32_MAX) 604 error.SetErrorStringWithFormat ("invalid ignore count '%s'", option_arg); 605 } 606 break; 607 default: 608 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 609 break; 610 } 611 612 return error; 613 } 614 615 void 616 CommandObjectWatchpointIgnore::CommandOptions::OptionParsingStarting () 617 { 618 m_ignore_count = 0; 619 } 620 621 //------------------------------------------------------------------------- 622 // CommandObjectWatchpointIgnore 623 //------------------------------------------------------------------------- 624 #pragma mark Ignore 625 626 CommandObjectWatchpointIgnore::CommandObjectWatchpointIgnore(CommandInterpreter &interpreter) : 627 CommandObject(interpreter, 628 "watchpoint ignore", 629 "Set ignore count on the specified watchpoint(s). If no watchpoints are specified, set them all.", 630 NULL), 631 m_options (interpreter) 632 { 633 CommandArgumentEntry arg; 634 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); 635 // Add the entry for the first argument for this command to the object's arguments vector. 636 m_arguments.push_back(arg); 637 } 638 639 CommandObjectWatchpointIgnore::~CommandObjectWatchpointIgnore() 640 { 641 } 642 643 Options * 644 CommandObjectWatchpointIgnore::GetOptions () 645 { 646 return &m_options; 647 } 648 649 bool 650 CommandObjectWatchpointIgnore::Execute(Args& args, CommandReturnObject &result) 651 { 652 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 653 if (!CheckTargetForWatchpointOperations(target, result)) 654 return false; 655 656 Mutex::Locker locker; 657 target->GetWatchpointList().GetListMutex(locker); 658 659 const WatchpointList &watchpoints = target->GetWatchpointList(); 660 661 size_t num_watchpoints = watchpoints.GetSize(); 662 663 if (num_watchpoints == 0) 664 { 665 result.AppendError("No watchpoints exist to be ignored."); 666 result.SetStatus(eReturnStatusFailed); 667 return false; 668 } 669 670 if (args.GetArgumentCount() == 0) 671 { 672 target->IgnoreAllWatchpoints(m_options.m_ignore_count); 673 result.AppendMessageWithFormat("All watchpoints ignored. (%lu watchpoints)\n", num_watchpoints); 674 result.SetStatus (eReturnStatusSuccessFinishNoResult); 675 } 676 else 677 { 678 // Particular watchpoints selected; ignore them. 679 std::vector<uint32_t> wp_ids; 680 if (!VerifyWatchpointIDs(args, wp_ids)) 681 { 682 result.AppendError("Invalid watchpoints specification."); 683 result.SetStatus(eReturnStatusFailed); 684 return false; 685 } 686 687 int count = 0; 688 const size_t size = wp_ids.size(); 689 for (size_t i = 0; i < size; ++i) 690 if (target->IgnoreWatchpointByID(wp_ids[i], m_options.m_ignore_count)) 691 ++count; 692 result.AppendMessageWithFormat("%d watchpoints ignored.\n",count); 693 result.SetStatus (eReturnStatusSuccessFinishNoResult); 694 } 695 696 return result.Succeeded(); 697 } 698 699 //------------------------------------------------------------------------- 700 // CommandObjectWatchpointModify::CommandOptions 701 //------------------------------------------------------------------------- 702 #pragma mark Modify::CommandOptions 703 704 CommandObjectWatchpointModify::CommandOptions::CommandOptions(CommandInterpreter &interpreter) : 705 Options (interpreter), 706 m_condition (), 707 m_condition_passed (false) 708 { 709 } 710 711 CommandObjectWatchpointModify::CommandOptions::~CommandOptions () 712 { 713 } 714 715 OptionDefinition 716 CommandObjectWatchpointModify::CommandOptions::g_option_table[] = 717 { 718 { LLDB_OPT_SET_ALL, false, "condition", 'c', required_argument, NULL, NULL, eArgTypeExpression, "The watchpoint stops only if this condition expression evaluates to true."}, 719 { 0, false, NULL, 0 , 0, NULL, 0, eArgTypeNone, NULL } 720 }; 721 722 const OptionDefinition* 723 CommandObjectWatchpointModify::CommandOptions::GetDefinitions () 724 { 725 return g_option_table; 726 } 727 728 Error 729 CommandObjectWatchpointModify::CommandOptions::SetOptionValue (uint32_t option_idx, const char *option_arg) 730 { 731 Error error; 732 char short_option = (char) m_getopt_table[option_idx].val; 733 734 switch (short_option) 735 { 736 case 'c': 737 if (option_arg != NULL) 738 m_condition.assign (option_arg); 739 else 740 m_condition.clear(); 741 m_condition_passed = true; 742 break; 743 default: 744 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 745 break; 746 } 747 748 return error; 749 } 750 751 void 752 CommandObjectWatchpointModify::CommandOptions::OptionParsingStarting () 753 { 754 m_condition.clear(); 755 m_condition_passed = false; 756 } 757 758 //------------------------------------------------------------------------- 759 // CommandObjectWatchpointModify 760 //------------------------------------------------------------------------- 761 #pragma mark Modify 762 763 CommandObjectWatchpointModify::CommandObjectWatchpointModify (CommandInterpreter &interpreter) : 764 CommandObject (interpreter, 765 "watchpoint modify", 766 "Modify the options on a watchpoint or set of watchpoints in the executable. " 767 "If no watchpoint is specified, act on the last created watchpoint. " 768 "Passing an empty argument clears the modification.", 769 NULL), 770 m_options (interpreter) 771 { 772 CommandArgumentEntry arg; 773 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); 774 // Add the entry for the first argument for this command to the object's arguments vector. 775 m_arguments.push_back (arg); 776 } 777 778 CommandObjectWatchpointModify::~CommandObjectWatchpointModify () 779 { 780 } 781 782 Options * 783 CommandObjectWatchpointModify::GetOptions () 784 { 785 return &m_options; 786 } 787 788 bool 789 CommandObjectWatchpointModify::Execute 790 ( 791 Args& args, 792 CommandReturnObject &result 793 ) 794 { 795 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 796 if (!CheckTargetForWatchpointOperations(target, result)) 797 return false; 798 799 Mutex::Locker locker; 800 target->GetWatchpointList().GetListMutex(locker); 801 802 const WatchpointList &watchpoints = target->GetWatchpointList(); 803 804 size_t num_watchpoints = watchpoints.GetSize(); 805 806 if (num_watchpoints == 0) 807 { 808 result.AppendError("No watchpoints exist to be modified."); 809 result.SetStatus(eReturnStatusFailed); 810 return false; 811 } 812 813 if (args.GetArgumentCount() == 0) 814 { 815 WatchpointSP wp_sp = target->GetLastCreatedWatchpoint(); 816 wp_sp->SetCondition(m_options.m_condition.c_str()); 817 result.SetStatus (eReturnStatusSuccessFinishNoResult); 818 } 819 else 820 { 821 // Particular watchpoints selected; set condition on them. 822 std::vector<uint32_t> wp_ids; 823 if (!VerifyWatchpointIDs(args, wp_ids)) 824 { 825 result.AppendError("Invalid watchpoints specification."); 826 result.SetStatus(eReturnStatusFailed); 827 return false; 828 } 829 830 int count = 0; 831 const size_t size = wp_ids.size(); 832 for (size_t i = 0; i < size; ++i) 833 { 834 WatchpointSP wp_sp = watchpoints.FindByID(wp_ids[i]); 835 if (wp_sp) 836 { 837 wp_sp->SetCondition(m_options.m_condition.c_str()); 838 ++count; 839 } 840 } 841 result.AppendMessageWithFormat("%d watchpoints modified.\n",count); 842 result.SetStatus (eReturnStatusSuccessFinishNoResult); 843 } 844 845 return result.Succeeded(); 846 } 847