CommandObjectWatchpoint.cpp revision 712a628dde2f4f786389feecf7e06e59f0853c75
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 26using namespace lldb; 27using namespace lldb_private; 28 29static void 30AddWatchpointDescription(Stream *s, Watchpoint *wp, lldb::DescriptionLevel level) 31{ 32 s->IndentMore(); 33 wp->GetDescription(s, level); 34 s->IndentLess(); 35 s->EOL(); 36} 37 38static bool 39CheckTargetForWatchpointOperations(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. 61static const char* RSA[4] = { "-", "to", "To", "TO" }; 62 63// Return the index to RSA if found; otherwise -1 is returned. 64static int32_t 65WithRSAIndex(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. 77static bool 78VerifyWatchpointIDs(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 146CommandObjectMultiwordWatchpoint::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 176CommandObjectMultiwordWatchpoint::~CommandObjectMultiwordWatchpoint() 177{ 178} 179 180//------------------------------------------------------------------------- 181// CommandObjectWatchpointList::Options 182//------------------------------------------------------------------------- 183#pragma mark List::CommandOptions 184 185CommandObjectWatchpointList::CommandOptions::CommandOptions(CommandInterpreter &interpreter) : 186 Options(interpreter), 187 m_level(lldb::eDescriptionLevelBrief) // Watchpoint List defaults to brief descriptions 188{ 189} 190 191CommandObjectWatchpointList::CommandOptions::~CommandOptions() 192{ 193} 194 195OptionDefinition 196CommandObjectWatchpointList::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 210const OptionDefinition* 211CommandObjectWatchpointList::CommandOptions::GetDefinitions() 212{ 213 return g_option_table; 214} 215 216Error 217CommandObjectWatchpointList::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'.\n", short_option); 235 break; 236 } 237 238 return error; 239} 240 241void 242CommandObjectWatchpointList::CommandOptions::OptionParsingStarting() 243{ 244 m_level = lldb::eDescriptionLevelFull; 245} 246 247//------------------------------------------------------------------------- 248// CommandObjectWatchpointList 249//------------------------------------------------------------------------- 250#pragma mark List 251 252CommandObjectWatchpointList::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 265CommandObjectWatchpointList::~CommandObjectWatchpointList() 266{ 267} 268 269Options * 270CommandObjectWatchpointList::GetOptions() 271{ 272 return &m_options; 273} 274 275bool 276CommandObjectWatchpointList::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 341CommandObjectWatchpointEnable::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 353CommandObjectWatchpointEnable::~CommandObjectWatchpointEnable() 354{ 355} 356 357bool 358CommandObjectWatchpointEnable::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 413CommandObjectWatchpointDisable::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 425CommandObjectWatchpointDisable::~CommandObjectWatchpointDisable() 426{ 427} 428 429bool 430CommandObjectWatchpointDisable::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 491CommandObjectWatchpointDelete::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 503CommandObjectWatchpointDelete::~CommandObjectWatchpointDelete() 504{ 505} 506 507bool 508CommandObjectWatchpointDelete::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 569CommandObjectWatchpointIgnore::CommandOptions::CommandOptions(CommandInterpreter &interpreter) : 570 Options (interpreter), 571 m_ignore_count (0) 572{ 573} 574 575CommandObjectWatchpointIgnore::CommandOptions::~CommandOptions () 576{ 577} 578 579OptionDefinition 580CommandObjectWatchpointIgnore::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 586const OptionDefinition* 587CommandObjectWatchpointIgnore::CommandOptions::GetDefinitions () 588{ 589 return g_option_table; 590} 591 592Error 593CommandObjectWatchpointIgnore::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'.\n", option_arg); 605 } 606 break; 607 default: 608 error.SetErrorStringWithFormat ("Unrecognized option '%c'.\n", short_option); 609 break; 610 } 611 612 return error; 613} 614 615void 616CommandObjectWatchpointIgnore::CommandOptions::OptionParsingStarting () 617{ 618 m_ignore_count = 0; 619} 620 621//------------------------------------------------------------------------- 622// CommandObjectWatchpointIgnore 623//------------------------------------------------------------------------- 624#pragma mark Ignore 625 626CommandObjectWatchpointIgnore::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 639CommandObjectWatchpointIgnore::~CommandObjectWatchpointIgnore() 640{ 641} 642 643Options * 644CommandObjectWatchpointIgnore::GetOptions () 645{ 646 return &m_options; 647} 648 649bool 650CommandObjectWatchpointIgnore::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 704CommandObjectWatchpointModify::CommandOptions::CommandOptions(CommandInterpreter &interpreter) : 705 Options (interpreter), 706 m_condition (), 707 m_condition_passed (false) 708{ 709} 710 711CommandObjectWatchpointModify::CommandOptions::~CommandOptions () 712{ 713} 714 715OptionDefinition 716CommandObjectWatchpointModify::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 722const OptionDefinition* 723CommandObjectWatchpointModify::CommandOptions::GetDefinitions () 724{ 725 return g_option_table; 726} 727 728Error 729CommandObjectWatchpointModify::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'.\n", short_option); 745 break; 746 } 747 748 return error; 749} 750 751void 752CommandObjectWatchpointModify::CommandOptions::OptionParsingStarting () 753{ 754 m_condition.clear(); 755 m_condition_passed = false; 756} 757 758//------------------------------------------------------------------------- 759// CommandObjectWatchpointModify 760//------------------------------------------------------------------------- 761#pragma mark Modify 762 763CommandObjectWatchpointModify::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 778CommandObjectWatchpointModify::~CommandObjectWatchpointModify () 779{ 780} 781 782Options * 783CommandObjectWatchpointModify::GetOptions () 784{ 785 return &m_options; 786} 787 788bool 789CommandObjectWatchpointModify::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