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/WatchpointLocation.h" 17 #include "lldb/Breakpoint/WatchpointLocationList.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, WatchpointLocation *wp_loc, lldb::DescriptionLevel level) 31 { 32 s->IndentMore(); 33 wp_loc->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 160 list_command_object->SetCommandName ("watchpoint list"); 161 enable_command_object->SetCommandName("watchpoint enable"); 162 disable_command_object->SetCommandName("watchpoint disable"); 163 delete_command_object->SetCommandName("watchpoint delete"); 164 ignore_command_object->SetCommandName("watchpoint ignore"); 165 166 status = LoadSubCommand ("list", list_command_object); 167 status = LoadSubCommand ("enable", enable_command_object); 168 status = LoadSubCommand ("disable", disable_command_object); 169 status = LoadSubCommand ("delete", delete_command_object); 170 status = LoadSubCommand ("ignore", ignore_command_object); 171 } 172 173 CommandObjectMultiwordWatchpoint::~CommandObjectMultiwordWatchpoint() 174 { 175 } 176 177 //------------------------------------------------------------------------- 178 // CommandObjectWatchpointList::Options 179 //------------------------------------------------------------------------- 180 #pragma mark List::CommandOptions 181 182 CommandObjectWatchpointList::CommandOptions::CommandOptions(CommandInterpreter &interpreter) : 183 Options(interpreter), 184 m_level(lldb::eDescriptionLevelBrief) // Watchpoint List defaults to brief descriptions 185 { 186 } 187 188 CommandObjectWatchpointList::CommandOptions::~CommandOptions() 189 { 190 } 191 192 OptionDefinition 193 CommandObjectWatchpointList::CommandOptions::g_option_table[] = 194 { 195 { LLDB_OPT_SET_1, false, "brief", 'b', no_argument, NULL, 0, eArgTypeNone, 196 "Give a brief description of the watchpoint (no location info)."}, 197 198 { LLDB_OPT_SET_2, false, "full", 'f', no_argument, NULL, 0, eArgTypeNone, 199 "Give a full description of the watchpoint and its locations."}, 200 201 { LLDB_OPT_SET_3, false, "verbose", 'v', no_argument, NULL, 0, eArgTypeNone, 202 "Explain everything we know about the watchpoint (for debugging debugger bugs)." }, 203 204 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 205 }; 206 207 const OptionDefinition* 208 CommandObjectWatchpointList::CommandOptions::GetDefinitions() 209 { 210 return g_option_table; 211 } 212 213 Error 214 CommandObjectWatchpointList::CommandOptions::SetOptionValue(uint32_t option_idx, const char *option_arg) 215 { 216 Error error; 217 char short_option = (char) m_getopt_table[option_idx].val; 218 219 switch (short_option) 220 { 221 case 'b': 222 m_level = lldb::eDescriptionLevelBrief; 223 break; 224 case 'f': 225 m_level = lldb::eDescriptionLevelFull; 226 break; 227 case 'v': 228 m_level = lldb::eDescriptionLevelVerbose; 229 break; 230 default: 231 error.SetErrorStringWithFormat("Unrecognized option '%c'.\n", short_option); 232 break; 233 } 234 235 return error; 236 } 237 238 void 239 CommandObjectWatchpointList::CommandOptions::OptionParsingStarting() 240 { 241 m_level = lldb::eDescriptionLevelFull; 242 } 243 244 //------------------------------------------------------------------------- 245 // CommandObjectWatchpointList 246 //------------------------------------------------------------------------- 247 #pragma mark List 248 249 CommandObjectWatchpointList::CommandObjectWatchpointList(CommandInterpreter &interpreter) : 250 CommandObject(interpreter, 251 "watchpoint list", 252 "List all watchpoints at configurable levels of detail.", 253 NULL), 254 m_options(interpreter) 255 { 256 CommandArgumentEntry arg; 257 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); 258 // Add the entry for the first argument for this command to the object's arguments vector. 259 m_arguments.push_back(arg); 260 } 261 262 CommandObjectWatchpointList::~CommandObjectWatchpointList() 263 { 264 } 265 266 Options * 267 CommandObjectWatchpointList::GetOptions() 268 { 269 return &m_options; 270 } 271 272 bool 273 CommandObjectWatchpointList::Execute(Args& args, CommandReturnObject &result) 274 { 275 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 276 if (target == NULL) 277 { 278 result.AppendError ("Invalid target. No current target or watchpoints."); 279 result.SetStatus (eReturnStatusSuccessFinishNoResult); 280 return true; 281 } 282 283 const WatchpointLocationList &watchpoints = target->GetWatchpointLocationList(); 284 Mutex::Locker locker; 285 target->GetWatchpointLocationList().GetListMutex(locker); 286 287 size_t num_watchpoints = watchpoints.GetSize(); 288 289 if (num_watchpoints == 0) 290 { 291 result.AppendMessage("No watchpoints currently set."); 292 result.SetStatus(eReturnStatusSuccessFinishNoResult); 293 return true; 294 } 295 296 Stream &output_stream = result.GetOutputStream(); 297 298 if (args.GetArgumentCount() == 0) 299 { 300 // No watchpoint selected; show info about all currently set watchpoints. 301 result.AppendMessage ("Current watchpoints:"); 302 for (size_t i = 0; i < num_watchpoints; ++i) 303 { 304 WatchpointLocation *wp_loc = watchpoints.GetByIndex(i).get(); 305 AddWatchpointDescription(&output_stream, wp_loc, m_options.m_level); 306 } 307 result.SetStatus(eReturnStatusSuccessFinishNoResult); 308 } 309 else 310 { 311 // Particular watchpoints selected; enable them. 312 std::vector<uint32_t> wp_ids; 313 if (!VerifyWatchpointIDs(args, wp_ids)) 314 { 315 result.AppendError("Invalid watchpoints specification."); 316 result.SetStatus(eReturnStatusFailed); 317 return false; 318 } 319 320 const size_t size = wp_ids.size(); 321 for (size_t i = 0; i < size; ++i) 322 { 323 WatchpointLocation *wp_loc = watchpoints.FindByID(wp_ids[i]).get(); 324 if (wp_loc) 325 AddWatchpointDescription(&output_stream, wp_loc, m_options.m_level); 326 result.SetStatus(eReturnStatusSuccessFinishNoResult); 327 } 328 } 329 330 return result.Succeeded(); 331 } 332 333 //------------------------------------------------------------------------- 334 // CommandObjectWatchpointEnable 335 //------------------------------------------------------------------------- 336 #pragma mark Enable 337 338 CommandObjectWatchpointEnable::CommandObjectWatchpointEnable(CommandInterpreter &interpreter) : 339 CommandObject(interpreter, 340 "enable", 341 "Enable the specified disabled watchpoint(s). If no watchpoints are specified, enable all of them.", 342 NULL) 343 { 344 CommandArgumentEntry arg; 345 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); 346 // Add the entry for the first argument for this command to the object's arguments vector. 347 m_arguments.push_back(arg); 348 } 349 350 CommandObjectWatchpointEnable::~CommandObjectWatchpointEnable() 351 { 352 } 353 354 bool 355 CommandObjectWatchpointEnable::Execute(Args& args, CommandReturnObject &result) 356 { 357 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 358 if (!CheckTargetForWatchpointOperations(target, result)) 359 return false; 360 361 Mutex::Locker locker; 362 target->GetWatchpointLocationList().GetListMutex(locker); 363 364 const WatchpointLocationList &watchpoints = target->GetWatchpointLocationList(); 365 366 size_t num_watchpoints = watchpoints.GetSize(); 367 368 if (num_watchpoints == 0) 369 { 370 result.AppendError("No watchpoints exist to be enabled."); 371 result.SetStatus(eReturnStatusFailed); 372 return false; 373 } 374 375 if (args.GetArgumentCount() == 0) 376 { 377 // No watchpoint selected; enable all currently set watchpoints. 378 target->EnableAllWatchpointLocations(); 379 result.AppendMessageWithFormat("All watchpoints enabled. (%lu watchpoints)\n", num_watchpoints); 380 result.SetStatus(eReturnStatusSuccessFinishNoResult); 381 } 382 else 383 { 384 // Particular watchpoints selected; enable them. 385 std::vector<uint32_t> wp_ids; 386 if (!VerifyWatchpointIDs(args, wp_ids)) 387 { 388 result.AppendError("Invalid watchpoints specification."); 389 result.SetStatus(eReturnStatusFailed); 390 return false; 391 } 392 393 int count = 0; 394 const size_t size = wp_ids.size(); 395 for (size_t i = 0; i < size; ++i) 396 if (target->EnableWatchpointLocationByID(wp_ids[i])) 397 ++count; 398 result.AppendMessageWithFormat("%d watchpoints enabled.\n", count); 399 result.SetStatus(eReturnStatusSuccessFinishNoResult); 400 } 401 402 return result.Succeeded(); 403 } 404 405 //------------------------------------------------------------------------- 406 // CommandObjectWatchpointDisable 407 //------------------------------------------------------------------------- 408 #pragma mark Disable 409 410 CommandObjectWatchpointDisable::CommandObjectWatchpointDisable(CommandInterpreter &interpreter) : 411 CommandObject(interpreter, 412 "watchpoint disable", 413 "Disable the specified watchpoint(s) without removing it/them. If no watchpoints are specified, disable them all.", 414 NULL) 415 { 416 CommandArgumentEntry arg; 417 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); 418 // Add the entry for the first argument for this command to the object's arguments vector. 419 m_arguments.push_back(arg); 420 } 421 422 CommandObjectWatchpointDisable::~CommandObjectWatchpointDisable() 423 { 424 } 425 426 bool 427 CommandObjectWatchpointDisable::Execute(Args& args, CommandReturnObject &result) 428 { 429 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 430 if (!CheckTargetForWatchpointOperations(target, result)) 431 return false; 432 433 Mutex::Locker locker; 434 target->GetWatchpointLocationList().GetListMutex(locker); 435 436 const WatchpointLocationList &watchpoints = target->GetWatchpointLocationList(); 437 size_t num_watchpoints = watchpoints.GetSize(); 438 439 if (num_watchpoints == 0) 440 { 441 result.AppendError("No watchpoints exist to be disabled."); 442 result.SetStatus(eReturnStatusFailed); 443 return false; 444 } 445 446 if (args.GetArgumentCount() == 0) 447 { 448 // No watchpoint selected; disable all currently set watchpoints. 449 if (target->DisableAllWatchpointLocations()) 450 { 451 result.AppendMessageWithFormat("All watchpoints disabled. (%lu watchpoints)\n", num_watchpoints); 452 result.SetStatus(eReturnStatusSuccessFinishNoResult); 453 } 454 else 455 { 456 result.AppendError("Disable all watchpoints failed\n"); 457 result.SetStatus(eReturnStatusFailed); 458 } 459 } 460 else 461 { 462 // Particular watchpoints selected; disable them. 463 std::vector<uint32_t> wp_ids; 464 if (!VerifyWatchpointIDs(args, wp_ids)) 465 { 466 result.AppendError("Invalid watchpoints specification."); 467 result.SetStatus(eReturnStatusFailed); 468 return false; 469 } 470 471 int count = 0; 472 const size_t size = wp_ids.size(); 473 for (size_t i = 0; i < size; ++i) 474 if (target->DisableWatchpointLocationByID(wp_ids[i])) 475 ++count; 476 result.AppendMessageWithFormat("%d watchpoints disabled.\n", count); 477 result.SetStatus(eReturnStatusSuccessFinishNoResult); 478 } 479 480 return result.Succeeded(); 481 } 482 483 //------------------------------------------------------------------------- 484 // CommandObjectWatchpointDelete 485 //------------------------------------------------------------------------- 486 #pragma mark Delete 487 488 CommandObjectWatchpointDelete::CommandObjectWatchpointDelete(CommandInterpreter &interpreter) : 489 CommandObject(interpreter, 490 "watchpoint delete", 491 "Delete the specified watchpoint(s). If no watchpoints are specified, delete them all.", 492 NULL) 493 { 494 CommandArgumentEntry arg; 495 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); 496 // Add the entry for the first argument for this command to the object's arguments vector. 497 m_arguments.push_back(arg); 498 } 499 500 CommandObjectWatchpointDelete::~CommandObjectWatchpointDelete() 501 { 502 } 503 504 bool 505 CommandObjectWatchpointDelete::Execute(Args& args, CommandReturnObject &result) 506 { 507 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 508 if (!CheckTargetForWatchpointOperations(target, result)) 509 return false; 510 511 Mutex::Locker locker; 512 target->GetWatchpointLocationList().GetListMutex(locker); 513 514 const WatchpointLocationList &watchpoints = target->GetWatchpointLocationList(); 515 516 size_t num_watchpoints = watchpoints.GetSize(); 517 518 if (num_watchpoints == 0) 519 { 520 result.AppendError("No watchpoints exist to be deleted."); 521 result.SetStatus(eReturnStatusFailed); 522 return false; 523 } 524 525 if (args.GetArgumentCount() == 0) 526 { 527 if (!m_interpreter.Confirm("About to delete all watchpoints, do you want to do that?", true)) 528 { 529 result.AppendMessage("Operation cancelled..."); 530 } 531 else 532 { 533 target->RemoveAllWatchpointLocations(); 534 result.AppendMessageWithFormat("All watchpoints removed. (%lu watchpoints)\n", num_watchpoints); 535 } 536 result.SetStatus (eReturnStatusSuccessFinishNoResult); 537 } 538 else 539 { 540 // Particular watchpoints selected; delete them. 541 std::vector<uint32_t> wp_ids; 542 if (!VerifyWatchpointIDs(args, wp_ids)) 543 { 544 result.AppendError("Invalid watchpoints specification."); 545 result.SetStatus(eReturnStatusFailed); 546 return false; 547 } 548 549 int count = 0; 550 const size_t size = wp_ids.size(); 551 for (size_t i = 0; i < size; ++i) 552 if (target->RemoveWatchpointLocationByID(wp_ids[i])) 553 ++count; 554 result.AppendMessageWithFormat("%d watchpoints deleted.\n",count); 555 result.SetStatus (eReturnStatusSuccessFinishNoResult); 556 } 557 558 return result.Succeeded(); 559 } 560 561 //------------------------------------------------------------------------- 562 // CommandObjectWatchpointIgnore::CommandOptions 563 //------------------------------------------------------------------------- 564 #pragma mark Ignore::CommandOptions 565 566 CommandObjectWatchpointIgnore::CommandOptions::CommandOptions(CommandInterpreter &interpreter) : 567 Options (interpreter), 568 m_ignore_count (0) 569 { 570 } 571 572 CommandObjectWatchpointIgnore::CommandOptions::~CommandOptions () 573 { 574 } 575 576 OptionDefinition 577 CommandObjectWatchpointIgnore::CommandOptions::g_option_table[] = 578 { 579 { LLDB_OPT_SET_ALL, true, "ignore-count", 'i', required_argument, NULL, NULL, eArgTypeCount, "Set the number of times this watchpoint is skipped before stopping." }, 580 { 0, false, NULL, 0 , 0, NULL, 0, eArgTypeNone, NULL } 581 }; 582 583 const OptionDefinition* 584 CommandObjectWatchpointIgnore::CommandOptions::GetDefinitions () 585 { 586 return g_option_table; 587 } 588 589 Error 590 CommandObjectWatchpointIgnore::CommandOptions::SetOptionValue (uint32_t option_idx, const char *option_arg) 591 { 592 Error error; 593 char short_option = (char) m_getopt_table[option_idx].val; 594 595 switch (short_option) 596 { 597 case 'i': 598 { 599 m_ignore_count = Args::StringToUInt32(option_arg, UINT32_MAX, 0); 600 if (m_ignore_count == UINT32_MAX) 601 error.SetErrorStringWithFormat ("Invalid ignore count '%s'.\n", option_arg); 602 } 603 break; 604 default: 605 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option); 606 break; 607 } 608 609 return error; 610 } 611 612 void 613 CommandObjectWatchpointIgnore::CommandOptions::OptionParsingStarting () 614 { 615 m_ignore_count = 0; 616 } 617 618 //------------------------------------------------------------------------- 619 // CommandObjectWatchpointIgnore 620 //------------------------------------------------------------------------- 621 #pragma mark Ignore 622 623 CommandObjectWatchpointIgnore::CommandObjectWatchpointIgnore(CommandInterpreter &interpreter) : 624 CommandObject(interpreter, 625 "watchpoint ignore", 626 "Set ignore count on the specified watchpoint(s). If no watchpoints are specified, set them all.", 627 NULL), 628 m_options (interpreter) 629 { 630 CommandArgumentEntry arg; 631 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); 632 // Add the entry for the first argument for this command to the object's arguments vector. 633 m_arguments.push_back(arg); 634 } 635 636 CommandObjectWatchpointIgnore::~CommandObjectWatchpointIgnore() 637 { 638 } 639 640 Options * 641 CommandObjectWatchpointIgnore::GetOptions () 642 { 643 return &m_options; 644 } 645 646 bool 647 CommandObjectWatchpointIgnore::Execute(Args& args, CommandReturnObject &result) 648 { 649 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 650 if (!CheckTargetForWatchpointOperations(target, result)) 651 return false; 652 653 Mutex::Locker locker; 654 target->GetWatchpointLocationList().GetListMutex(locker); 655 656 const WatchpointLocationList &watchpoints = target->GetWatchpointLocationList(); 657 658 size_t num_watchpoints = watchpoints.GetSize(); 659 660 if (num_watchpoints == 0) 661 { 662 result.AppendError("No watchpoints exist to be ignored."); 663 result.SetStatus(eReturnStatusFailed); 664 return false; 665 } 666 667 if (args.GetArgumentCount() == 0) 668 { 669 target->IgnoreAllWatchpointLocations(m_options.m_ignore_count); 670 result.AppendMessageWithFormat("All watchpoints ignored. (%lu watchpoints)\n", num_watchpoints); 671 result.SetStatus (eReturnStatusSuccessFinishNoResult); 672 } 673 else 674 { 675 // Particular watchpoints selected; ignore them. 676 std::vector<uint32_t> wp_ids; 677 if (!VerifyWatchpointIDs(args, wp_ids)) 678 { 679 result.AppendError("Invalid watchpoints specification."); 680 result.SetStatus(eReturnStatusFailed); 681 return false; 682 } 683 684 int count = 0; 685 const size_t size = wp_ids.size(); 686 for (size_t i = 0; i < size; ++i) 687 if (target->IgnoreWatchpointLocationByID(wp_ids[i], m_options.m_ignore_count)) 688 ++count; 689 result.AppendMessageWithFormat("%d watchpoints ignored.\n",count); 690 result.SetStatus (eReturnStatusSuccessFinishNoResult); 691 } 692 693 return result.Succeeded(); 694 } 695 696