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/Core/ValueObject.h" 20 #include "lldb/Core/ValueObjectVariable.h" 21 #include "lldb/Interpreter/CommandInterpreter.h" 22 #include "lldb/Interpreter/CommandReturnObject.h" 23 #include "lldb/Interpreter/CommandCompletions.h" 24 #include "lldb/Symbol/Variable.h" 25 #include "lldb/Symbol/VariableList.h" 26 #include "lldb/Target/Target.h" 27 28 #include <vector> 29 30 using namespace lldb; 31 using namespace lldb_private; 32 33 static void 34 AddWatchpointDescription(Stream *s, Watchpoint *wp, lldb::DescriptionLevel level) 35 { 36 s->IndentMore(); 37 wp->GetDescription(s, level); 38 s->IndentLess(); 39 s->EOL(); 40 } 41 42 static bool 43 CheckTargetForWatchpointOperations(Target *target, CommandReturnObject &result) 44 { 45 if (target == NULL) 46 { 47 result.AppendError ("Invalid target. No existing target or watchpoints."); 48 result.SetStatus (eReturnStatusFailed); 49 return false; 50 } 51 bool process_is_valid = target->GetProcessSP() && target->GetProcessSP()->IsAlive(); 52 if (!process_is_valid) 53 { 54 result.AppendError ("Thre's no process or it is not alive."); 55 result.SetStatus (eReturnStatusFailed); 56 return false; 57 } 58 // Target passes our checks, return true. 59 return true; 60 } 61 62 #include "llvm/ADT/StringRef.h" 63 64 // Equivalent class: {"-", "to", "To", "TO"} of range specifier array. 65 static const char* RSA[4] = { "-", "to", "To", "TO" }; 66 67 // Return the index to RSA if found; otherwise -1 is returned. 68 static int32_t 69 WithRSAIndex(llvm::StringRef &Arg) 70 { 71 72 uint32_t i; 73 for (i = 0; i < 4; ++i) 74 if (Arg.find(RSA[i]) != llvm::StringRef::npos) 75 return i; 76 return -1; 77 } 78 79 // Return true if wp_ids is successfully populated with the watch ids. 80 // False otherwise. 81 static bool 82 VerifyWatchpointIDs(Args &args, std::vector<uint32_t> &wp_ids) 83 { 84 // Pre-condition: args.GetArgumentCount() > 0. 85 assert(args.GetArgumentCount() > 0); 86 87 llvm::StringRef Minus("-"); 88 std::vector<llvm::StringRef> StrRefArgs; 89 std::pair<llvm::StringRef, llvm::StringRef> Pair; 90 size_t i; 91 int32_t idx; 92 // Go through the argments and make a canonical form of arg list containing 93 // only numbers with possible "-" in between. 94 for (i = 0; i < args.GetArgumentCount(); ++i) { 95 llvm::StringRef Arg(args.GetArgumentAtIndex(i)); 96 if ((idx = WithRSAIndex(Arg)) == -1) { 97 StrRefArgs.push_back(Arg); 98 continue; 99 } 100 // The Arg contains the range specifier, split it, then. 101 Pair = Arg.split(RSA[idx]); 102 if (!Pair.first.empty()) 103 StrRefArgs.push_back(Pair.first); 104 StrRefArgs.push_back(Minus); 105 if (!Pair.second.empty()) 106 StrRefArgs.push_back(Pair.second); 107 } 108 // Now process the canonical list and fill in the vector of uint32_t's. 109 // If there is any error, return false and the client should ignore wp_ids. 110 uint32_t beg, end, id; 111 size_t size = StrRefArgs.size(); 112 bool in_range = false; 113 for (i = 0; i < size; ++i) { 114 llvm::StringRef Arg = StrRefArgs[i]; 115 if (in_range) { 116 // Look for the 'end' of the range. Note StringRef::getAsInteger() 117 // returns true to signify error while parsing. 118 if (Arg.getAsInteger(0, end)) 119 return false; 120 // Found a range! Now append the elements. 121 for (id = beg; id <= end; ++id) 122 wp_ids.push_back(id); 123 in_range = false; 124 continue; 125 } 126 if (i < (size - 1) && StrRefArgs[i+1] == Minus) { 127 if (Arg.getAsInteger(0, beg)) 128 return false; 129 // Turn on the in_range flag, we are looking for end of range next. 130 ++i; in_range = true; 131 continue; 132 } 133 // Otherwise, we have a simple ID. Just append it. 134 if (Arg.getAsInteger(0, beg)) 135 return false; 136 wp_ids.push_back(beg); 137 } 138 // It is an error if after the loop, we're still in_range. 139 if (in_range) 140 return false; 141 142 return true; // Success! 143 } 144 145 //------------------------------------------------------------------------- 146 // CommandObjectMultiwordWatchpoint 147 //------------------------------------------------------------------------- 148 #pragma mark MultiwordWatchpoint 149 150 CommandObjectMultiwordWatchpoint::CommandObjectMultiwordWatchpoint(CommandInterpreter &interpreter) : 151 CommandObjectMultiword (interpreter, 152 "watchpoint", 153 "A set of commands for operating on watchpoints.", 154 "watchpoint <command> [<command-options>]") 155 { 156 bool status; 157 158 CommandObjectSP list_command_object (new CommandObjectWatchpointList (interpreter)); 159 CommandObjectSP enable_command_object (new CommandObjectWatchpointEnable (interpreter)); 160 CommandObjectSP disable_command_object (new CommandObjectWatchpointDisable (interpreter)); 161 CommandObjectSP delete_command_object (new CommandObjectWatchpointDelete (interpreter)); 162 CommandObjectSP ignore_command_object (new CommandObjectWatchpointIgnore (interpreter)); 163 CommandObjectSP modify_command_object (new CommandObjectWatchpointModify (interpreter)); 164 CommandObjectSP set_command_object (new CommandObjectWatchpointSet (interpreter)); 165 166 list_command_object->SetCommandName ("watchpoint list"); 167 enable_command_object->SetCommandName("watchpoint enable"); 168 disable_command_object->SetCommandName("watchpoint disable"); 169 delete_command_object->SetCommandName("watchpoint delete"); 170 ignore_command_object->SetCommandName("watchpoint ignore"); 171 modify_command_object->SetCommandName("watchpoint modify"); 172 set_command_object->SetCommandName("watchpoint set"); 173 174 status = LoadSubCommand ("list", list_command_object); 175 status = LoadSubCommand ("enable", enable_command_object); 176 status = LoadSubCommand ("disable", disable_command_object); 177 status = LoadSubCommand ("delete", delete_command_object); 178 status = LoadSubCommand ("ignore", ignore_command_object); 179 status = LoadSubCommand ("modify", modify_command_object); 180 status = LoadSubCommand ("set", set_command_object); 181 } 182 183 CommandObjectMultiwordWatchpoint::~CommandObjectMultiwordWatchpoint() 184 { 185 } 186 187 //------------------------------------------------------------------------- 188 // CommandObjectWatchpointList::Options 189 //------------------------------------------------------------------------- 190 #pragma mark List::CommandOptions 191 192 CommandObjectWatchpointList::CommandOptions::CommandOptions(CommandInterpreter &interpreter) : 193 Options(interpreter), 194 m_level(lldb::eDescriptionLevelBrief) // Watchpoint List defaults to brief descriptions 195 { 196 } 197 198 CommandObjectWatchpointList::CommandOptions::~CommandOptions() 199 { 200 } 201 202 OptionDefinition 203 CommandObjectWatchpointList::CommandOptions::g_option_table[] = 204 { 205 { LLDB_OPT_SET_1, false, "brief", 'b', no_argument, NULL, 0, eArgTypeNone, 206 "Give a brief description of the watchpoint (no location info)."}, 207 208 { LLDB_OPT_SET_2, false, "full", 'f', no_argument, NULL, 0, eArgTypeNone, 209 "Give a full description of the watchpoint and its locations."}, 210 211 { LLDB_OPT_SET_3, false, "verbose", 'v', no_argument, NULL, 0, eArgTypeNone, 212 "Explain everything we know about the watchpoint (for debugging debugger bugs)." }, 213 214 { 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL } 215 }; 216 217 const OptionDefinition* 218 CommandObjectWatchpointList::CommandOptions::GetDefinitions() 219 { 220 return g_option_table; 221 } 222 223 Error 224 CommandObjectWatchpointList::CommandOptions::SetOptionValue(uint32_t option_idx, const char *option_arg) 225 { 226 Error error; 227 char short_option = (char) m_getopt_table[option_idx].val; 228 229 switch (short_option) 230 { 231 case 'b': 232 m_level = lldb::eDescriptionLevelBrief; 233 break; 234 case 'f': 235 m_level = lldb::eDescriptionLevelFull; 236 break; 237 case 'v': 238 m_level = lldb::eDescriptionLevelVerbose; 239 break; 240 default: 241 error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); 242 break; 243 } 244 245 return error; 246 } 247 248 void 249 CommandObjectWatchpointList::CommandOptions::OptionParsingStarting() 250 { 251 m_level = lldb::eDescriptionLevelFull; 252 } 253 254 //------------------------------------------------------------------------- 255 // CommandObjectWatchpointList 256 //------------------------------------------------------------------------- 257 #pragma mark List 258 259 CommandObjectWatchpointList::CommandObjectWatchpointList(CommandInterpreter &interpreter) : 260 CommandObject(interpreter, 261 "watchpoint list", 262 "List all watchpoints at configurable levels of detail.", 263 NULL), 264 m_options(interpreter) 265 { 266 CommandArgumentEntry arg; 267 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); 268 // Add the entry for the first argument for this command to the object's arguments vector. 269 m_arguments.push_back(arg); 270 } 271 272 CommandObjectWatchpointList::~CommandObjectWatchpointList() 273 { 274 } 275 276 Options * 277 CommandObjectWatchpointList::GetOptions() 278 { 279 return &m_options; 280 } 281 282 bool 283 CommandObjectWatchpointList::Execute(Args& args, CommandReturnObject &result) 284 { 285 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 286 if (target == NULL) 287 { 288 result.AppendError ("Invalid target. No current target or watchpoints."); 289 result.SetStatus (eReturnStatusSuccessFinishNoResult); 290 return true; 291 } 292 293 const WatchpointList &watchpoints = target->GetWatchpointList(); 294 Mutex::Locker locker; 295 target->GetWatchpointList().GetListMutex(locker); 296 297 size_t num_watchpoints = watchpoints.GetSize(); 298 299 if (num_watchpoints == 0) 300 { 301 result.AppendMessage("No watchpoints currently set."); 302 result.SetStatus(eReturnStatusSuccessFinishNoResult); 303 return true; 304 } 305 306 Stream &output_stream = result.GetOutputStream(); 307 308 if (args.GetArgumentCount() == 0) 309 { 310 // No watchpoint selected; show info about all currently set watchpoints. 311 result.AppendMessage ("Current watchpoints:"); 312 for (size_t i = 0; i < num_watchpoints; ++i) 313 { 314 Watchpoint *wp = watchpoints.GetByIndex(i).get(); 315 AddWatchpointDescription(&output_stream, wp, m_options.m_level); 316 } 317 result.SetStatus(eReturnStatusSuccessFinishNoResult); 318 } 319 else 320 { 321 // Particular watchpoints selected; enable them. 322 std::vector<uint32_t> wp_ids; 323 if (!VerifyWatchpointIDs(args, wp_ids)) 324 { 325 result.AppendError("Invalid watchpoints specification."); 326 result.SetStatus(eReturnStatusFailed); 327 return false; 328 } 329 330 const size_t size = wp_ids.size(); 331 for (size_t i = 0; i < size; ++i) 332 { 333 Watchpoint *wp = watchpoints.FindByID(wp_ids[i]).get(); 334 if (wp) 335 AddWatchpointDescription(&output_stream, wp, m_options.m_level); 336 result.SetStatus(eReturnStatusSuccessFinishNoResult); 337 } 338 } 339 340 return result.Succeeded(); 341 } 342 343 //------------------------------------------------------------------------- 344 // CommandObjectWatchpointEnable 345 //------------------------------------------------------------------------- 346 #pragma mark Enable 347 348 CommandObjectWatchpointEnable::CommandObjectWatchpointEnable(CommandInterpreter &interpreter) : 349 CommandObject(interpreter, 350 "enable", 351 "Enable the specified disabled watchpoint(s). If no watchpoints are specified, enable all of them.", 352 NULL) 353 { 354 CommandArgumentEntry arg; 355 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); 356 // Add the entry for the first argument for this command to the object's arguments vector. 357 m_arguments.push_back(arg); 358 } 359 360 CommandObjectWatchpointEnable::~CommandObjectWatchpointEnable() 361 { 362 } 363 364 bool 365 CommandObjectWatchpointEnable::Execute(Args& args, CommandReturnObject &result) 366 { 367 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 368 if (!CheckTargetForWatchpointOperations(target, result)) 369 return false; 370 371 Mutex::Locker locker; 372 target->GetWatchpointList().GetListMutex(locker); 373 374 const WatchpointList &watchpoints = target->GetWatchpointList(); 375 376 size_t num_watchpoints = watchpoints.GetSize(); 377 378 if (num_watchpoints == 0) 379 { 380 result.AppendError("No watchpoints exist to be enabled."); 381 result.SetStatus(eReturnStatusFailed); 382 return false; 383 } 384 385 if (args.GetArgumentCount() == 0) 386 { 387 // No watchpoint selected; enable all currently set watchpoints. 388 target->EnableAllWatchpoints(); 389 result.AppendMessageWithFormat("All watchpoints enabled. (%lu watchpoints)\n", num_watchpoints); 390 result.SetStatus(eReturnStatusSuccessFinishNoResult); 391 } 392 else 393 { 394 // Particular watchpoints selected; enable them. 395 std::vector<uint32_t> wp_ids; 396 if (!VerifyWatchpointIDs(args, wp_ids)) 397 { 398 result.AppendError("Invalid watchpoints specification."); 399 result.SetStatus(eReturnStatusFailed); 400 return false; 401 } 402 403 int count = 0; 404 const size_t size = wp_ids.size(); 405 for (size_t i = 0; i < size; ++i) 406 if (target->EnableWatchpointByID(wp_ids[i])) 407 ++count; 408 result.AppendMessageWithFormat("%d watchpoints enabled.\n", count); 409 result.SetStatus(eReturnStatusSuccessFinishNoResult); 410 } 411 412 return result.Succeeded(); 413 } 414 415 //------------------------------------------------------------------------- 416 // CommandObjectWatchpointDisable 417 //------------------------------------------------------------------------- 418 #pragma mark Disable 419 420 CommandObjectWatchpointDisable::CommandObjectWatchpointDisable(CommandInterpreter &interpreter) : 421 CommandObject(interpreter, 422 "watchpoint disable", 423 "Disable the specified watchpoint(s) without removing it/them. If no watchpoints are specified, disable them all.", 424 NULL) 425 { 426 CommandArgumentEntry arg; 427 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); 428 // Add the entry for the first argument for this command to the object's arguments vector. 429 m_arguments.push_back(arg); 430 } 431 432 CommandObjectWatchpointDisable::~CommandObjectWatchpointDisable() 433 { 434 } 435 436 bool 437 CommandObjectWatchpointDisable::Execute(Args& args, CommandReturnObject &result) 438 { 439 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 440 if (!CheckTargetForWatchpointOperations(target, result)) 441 return false; 442 443 Mutex::Locker locker; 444 target->GetWatchpointList().GetListMutex(locker); 445 446 const WatchpointList &watchpoints = target->GetWatchpointList(); 447 size_t num_watchpoints = watchpoints.GetSize(); 448 449 if (num_watchpoints == 0) 450 { 451 result.AppendError("No watchpoints exist to be disabled."); 452 result.SetStatus(eReturnStatusFailed); 453 return false; 454 } 455 456 if (args.GetArgumentCount() == 0) 457 { 458 // No watchpoint selected; disable all currently set watchpoints. 459 if (target->DisableAllWatchpoints()) 460 { 461 result.AppendMessageWithFormat("All watchpoints disabled. (%lu watchpoints)\n", num_watchpoints); 462 result.SetStatus(eReturnStatusSuccessFinishNoResult); 463 } 464 else 465 { 466 result.AppendError("Disable all watchpoints failed\n"); 467 result.SetStatus(eReturnStatusFailed); 468 } 469 } 470 else 471 { 472 // Particular watchpoints selected; disable them. 473 std::vector<uint32_t> wp_ids; 474 if (!VerifyWatchpointIDs(args, wp_ids)) 475 { 476 result.AppendError("Invalid watchpoints specification."); 477 result.SetStatus(eReturnStatusFailed); 478 return false; 479 } 480 481 int count = 0; 482 const size_t size = wp_ids.size(); 483 for (size_t i = 0; i < size; ++i) 484 if (target->DisableWatchpointByID(wp_ids[i])) 485 ++count; 486 result.AppendMessageWithFormat("%d watchpoints disabled.\n", count); 487 result.SetStatus(eReturnStatusSuccessFinishNoResult); 488 } 489 490 return result.Succeeded(); 491 } 492 493 //------------------------------------------------------------------------- 494 // CommandObjectWatchpointDelete 495 //------------------------------------------------------------------------- 496 #pragma mark Delete 497 498 CommandObjectWatchpointDelete::CommandObjectWatchpointDelete(CommandInterpreter &interpreter) : 499 CommandObject(interpreter, 500 "watchpoint delete", 501 "Delete the specified watchpoint(s). If no watchpoints are specified, delete them all.", 502 NULL) 503 { 504 CommandArgumentEntry arg; 505 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); 506 // Add the entry for the first argument for this command to the object's arguments vector. 507 m_arguments.push_back(arg); 508 } 509 510 CommandObjectWatchpointDelete::~CommandObjectWatchpointDelete() 511 { 512 } 513 514 bool 515 CommandObjectWatchpointDelete::Execute(Args& args, CommandReturnObject &result) 516 { 517 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 518 if (!CheckTargetForWatchpointOperations(target, result)) 519 return false; 520 521 Mutex::Locker locker; 522 target->GetWatchpointList().GetListMutex(locker); 523 524 const WatchpointList &watchpoints = target->GetWatchpointList(); 525 526 size_t num_watchpoints = watchpoints.GetSize(); 527 528 if (num_watchpoints == 0) 529 { 530 result.AppendError("No watchpoints exist to be deleted."); 531 result.SetStatus(eReturnStatusFailed); 532 return false; 533 } 534 535 if (args.GetArgumentCount() == 0) 536 { 537 if (!m_interpreter.Confirm("About to delete all watchpoints, do you want to do that?", true)) 538 { 539 result.AppendMessage("Operation cancelled..."); 540 } 541 else 542 { 543 target->RemoveAllWatchpoints(); 544 result.AppendMessageWithFormat("All watchpoints removed. (%lu watchpoints)\n", num_watchpoints); 545 } 546 result.SetStatus (eReturnStatusSuccessFinishNoResult); 547 } 548 else 549 { 550 // Particular watchpoints selected; delete them. 551 std::vector<uint32_t> wp_ids; 552 if (!VerifyWatchpointIDs(args, wp_ids)) 553 { 554 result.AppendError("Invalid watchpoints specification."); 555 result.SetStatus(eReturnStatusFailed); 556 return false; 557 } 558 559 int count = 0; 560 const size_t size = wp_ids.size(); 561 for (size_t i = 0; i < size; ++i) 562 if (target->RemoveWatchpointByID(wp_ids[i])) 563 ++count; 564 result.AppendMessageWithFormat("%d watchpoints deleted.\n",count); 565 result.SetStatus (eReturnStatusSuccessFinishNoResult); 566 } 567 568 return result.Succeeded(); 569 } 570 571 //------------------------------------------------------------------------- 572 // CommandObjectWatchpointIgnore::CommandOptions 573 //------------------------------------------------------------------------- 574 #pragma mark Ignore::CommandOptions 575 576 CommandObjectWatchpointIgnore::CommandOptions::CommandOptions(CommandInterpreter &interpreter) : 577 Options (interpreter), 578 m_ignore_count (0) 579 { 580 } 581 582 CommandObjectWatchpointIgnore::CommandOptions::~CommandOptions () 583 { 584 } 585 586 OptionDefinition 587 CommandObjectWatchpointIgnore::CommandOptions::g_option_table[] = 588 { 589 { LLDB_OPT_SET_ALL, true, "ignore-count", 'i', required_argument, NULL, NULL, eArgTypeCount, "Set the number of times this watchpoint is skipped before stopping." }, 590 { 0, false, NULL, 0 , 0, NULL, 0, eArgTypeNone, NULL } 591 }; 592 593 const OptionDefinition* 594 CommandObjectWatchpointIgnore::CommandOptions::GetDefinitions () 595 { 596 return g_option_table; 597 } 598 599 Error 600 CommandObjectWatchpointIgnore::CommandOptions::SetOptionValue (uint32_t option_idx, const char *option_arg) 601 { 602 Error error; 603 char short_option = (char) m_getopt_table[option_idx].val; 604 605 switch (short_option) 606 { 607 case 'i': 608 { 609 m_ignore_count = Args::StringToUInt32(option_arg, UINT32_MAX, 0); 610 if (m_ignore_count == UINT32_MAX) 611 error.SetErrorStringWithFormat ("invalid ignore count '%s'", option_arg); 612 } 613 break; 614 default: 615 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 616 break; 617 } 618 619 return error; 620 } 621 622 void 623 CommandObjectWatchpointIgnore::CommandOptions::OptionParsingStarting () 624 { 625 m_ignore_count = 0; 626 } 627 628 //------------------------------------------------------------------------- 629 // CommandObjectWatchpointIgnore 630 //------------------------------------------------------------------------- 631 #pragma mark Ignore 632 633 CommandObjectWatchpointIgnore::CommandObjectWatchpointIgnore(CommandInterpreter &interpreter) : 634 CommandObject(interpreter, 635 "watchpoint ignore", 636 "Set ignore count on the specified watchpoint(s). If no watchpoints are specified, set them all.", 637 NULL), 638 m_options (interpreter) 639 { 640 CommandArgumentEntry arg; 641 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); 642 // Add the entry for the first argument for this command to the object's arguments vector. 643 m_arguments.push_back(arg); 644 } 645 646 CommandObjectWatchpointIgnore::~CommandObjectWatchpointIgnore() 647 { 648 } 649 650 Options * 651 CommandObjectWatchpointIgnore::GetOptions () 652 { 653 return &m_options; 654 } 655 656 bool 657 CommandObjectWatchpointIgnore::Execute(Args& args, CommandReturnObject &result) 658 { 659 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 660 if (!CheckTargetForWatchpointOperations(target, result)) 661 return false; 662 663 Mutex::Locker locker; 664 target->GetWatchpointList().GetListMutex(locker); 665 666 const WatchpointList &watchpoints = target->GetWatchpointList(); 667 668 size_t num_watchpoints = watchpoints.GetSize(); 669 670 if (num_watchpoints == 0) 671 { 672 result.AppendError("No watchpoints exist to be ignored."); 673 result.SetStatus(eReturnStatusFailed); 674 return false; 675 } 676 677 if (args.GetArgumentCount() == 0) 678 { 679 target->IgnoreAllWatchpoints(m_options.m_ignore_count); 680 result.AppendMessageWithFormat("All watchpoints ignored. (%lu watchpoints)\n", num_watchpoints); 681 result.SetStatus (eReturnStatusSuccessFinishNoResult); 682 } 683 else 684 { 685 // Particular watchpoints selected; ignore them. 686 std::vector<uint32_t> wp_ids; 687 if (!VerifyWatchpointIDs(args, wp_ids)) 688 { 689 result.AppendError("Invalid watchpoints specification."); 690 result.SetStatus(eReturnStatusFailed); 691 return false; 692 } 693 694 int count = 0; 695 const size_t size = wp_ids.size(); 696 for (size_t i = 0; i < size; ++i) 697 if (target->IgnoreWatchpointByID(wp_ids[i], m_options.m_ignore_count)) 698 ++count; 699 result.AppendMessageWithFormat("%d watchpoints ignored.\n",count); 700 result.SetStatus (eReturnStatusSuccessFinishNoResult); 701 } 702 703 return result.Succeeded(); 704 } 705 706 //------------------------------------------------------------------------- 707 // CommandObjectWatchpointModify::CommandOptions 708 //------------------------------------------------------------------------- 709 #pragma mark Modify::CommandOptions 710 711 CommandObjectWatchpointModify::CommandOptions::CommandOptions(CommandInterpreter &interpreter) : 712 Options (interpreter), 713 m_condition (), 714 m_condition_passed (false) 715 { 716 } 717 718 CommandObjectWatchpointModify::CommandOptions::~CommandOptions () 719 { 720 } 721 722 OptionDefinition 723 CommandObjectWatchpointModify::CommandOptions::g_option_table[] = 724 { 725 { LLDB_OPT_SET_ALL, false, "condition", 'c', required_argument, NULL, NULL, eArgTypeExpression, "The watchpoint stops only if this condition expression evaluates to true."}, 726 { 0, false, NULL, 0 , 0, NULL, 0, eArgTypeNone, NULL } 727 }; 728 729 const OptionDefinition* 730 CommandObjectWatchpointModify::CommandOptions::GetDefinitions () 731 { 732 return g_option_table; 733 } 734 735 Error 736 CommandObjectWatchpointModify::CommandOptions::SetOptionValue (uint32_t option_idx, const char *option_arg) 737 { 738 Error error; 739 char short_option = (char) m_getopt_table[option_idx].val; 740 741 switch (short_option) 742 { 743 case 'c': 744 if (option_arg != NULL) 745 m_condition.assign (option_arg); 746 else 747 m_condition.clear(); 748 m_condition_passed = true; 749 break; 750 default: 751 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 752 break; 753 } 754 755 return error; 756 } 757 758 void 759 CommandObjectWatchpointModify::CommandOptions::OptionParsingStarting () 760 { 761 m_condition.clear(); 762 m_condition_passed = false; 763 } 764 765 //------------------------------------------------------------------------- 766 // CommandObjectWatchpointModify 767 //------------------------------------------------------------------------- 768 #pragma mark Modify 769 770 CommandObjectWatchpointModify::CommandObjectWatchpointModify (CommandInterpreter &interpreter) : 771 CommandObject (interpreter, 772 "watchpoint modify", 773 "Modify the options on a watchpoint or set of watchpoints in the executable. " 774 "If no watchpoint is specified, act on the last created watchpoint. " 775 "Passing an empty argument clears the modification.", 776 NULL), 777 m_options (interpreter) 778 { 779 CommandArgumentEntry arg; 780 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); 781 // Add the entry for the first argument for this command to the object's arguments vector. 782 m_arguments.push_back (arg); 783 } 784 785 CommandObjectWatchpointModify::~CommandObjectWatchpointModify () 786 { 787 } 788 789 Options * 790 CommandObjectWatchpointModify::GetOptions () 791 { 792 return &m_options; 793 } 794 795 bool 796 CommandObjectWatchpointModify::Execute 797 ( 798 Args& args, 799 CommandReturnObject &result 800 ) 801 { 802 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 803 if (!CheckTargetForWatchpointOperations(target, result)) 804 return false; 805 806 Mutex::Locker locker; 807 target->GetWatchpointList().GetListMutex(locker); 808 809 const WatchpointList &watchpoints = target->GetWatchpointList(); 810 811 size_t num_watchpoints = watchpoints.GetSize(); 812 813 if (num_watchpoints == 0) 814 { 815 result.AppendError("No watchpoints exist to be modified."); 816 result.SetStatus(eReturnStatusFailed); 817 return false; 818 } 819 820 if (args.GetArgumentCount() == 0) 821 { 822 WatchpointSP wp_sp = target->GetLastCreatedWatchpoint(); 823 wp_sp->SetCondition(m_options.m_condition.c_str()); 824 result.SetStatus (eReturnStatusSuccessFinishNoResult); 825 } 826 else 827 { 828 // Particular watchpoints selected; set condition on them. 829 std::vector<uint32_t> wp_ids; 830 if (!VerifyWatchpointIDs(args, wp_ids)) 831 { 832 result.AppendError("Invalid watchpoints specification."); 833 result.SetStatus(eReturnStatusFailed); 834 return false; 835 } 836 837 int count = 0; 838 const size_t size = wp_ids.size(); 839 for (size_t i = 0; i < size; ++i) 840 { 841 WatchpointSP wp_sp = watchpoints.FindByID(wp_ids[i]); 842 if (wp_sp) 843 { 844 wp_sp->SetCondition(m_options.m_condition.c_str()); 845 ++count; 846 } 847 } 848 result.AppendMessageWithFormat("%d watchpoints modified.\n",count); 849 result.SetStatus (eReturnStatusSuccessFinishNoResult); 850 } 851 852 return result.Succeeded(); 853 } 854 855 //------------------------------------------------------------------------- 856 // CommandObjectWatchpointSet 857 //------------------------------------------------------------------------- 858 #pragma mark Set 859 860 CommandObjectWatchpointSet::CommandObjectWatchpointSet (CommandInterpreter &interpreter) : 861 CommandObject (interpreter, 862 "watchpoint set", 863 "Set a watchpoint. " 864 "You can choose to watch a variable in scope with just the '-w' option. " 865 "If you use the '-x' option to specify the byte size, it is implied " 866 "that the remaining string is evaluated as an expression with the result " 867 "interpreted as an address to watch for, i.e., the pointee is watched. " 868 "If no '-w' option is specified, it defaults to read_write. " 869 "Note that hardware resources for watching are often limited.", 870 NULL, 871 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused), 872 m_option_group (interpreter), 873 m_option_watchpoint() 874 { 875 SetHelpLong( 876 "Examples: \n\ 877 \n\ 878 watchpoint set -w read_wriate my_global_var \n\ 879 # Watch my_global_var for read/write access.\n\ 880 \n\ 881 watchpoint set -w write -x 1 foo + 32\n\ 882 # Watch write access for the 1-byte region pointed to by the address 'foo + 32'.\n"); 883 884 CommandArgumentEntry arg; 885 CommandArgumentData var_name_arg, expression_arg; 886 887 // Define the first variant of this arg. 888 var_name_arg.arg_type = eArgTypeVarName; 889 var_name_arg.arg_repetition = eArgRepeatPlain; 890 891 // Define the second variant of this arg. 892 expression_arg.arg_type = eArgTypeExpression; 893 expression_arg.arg_repetition = eArgRepeatPlain; 894 895 // Push the two variants into the argument entry. 896 arg.push_back (var_name_arg); 897 arg.push_back (expression_arg); 898 899 // Push the data for the first argument into the m_arguments vector. 900 m_arguments.push_back (arg); 901 902 m_option_group.Append (&m_option_watchpoint, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 903 m_option_group.Finalize(); 904 } 905 906 CommandObjectWatchpointSet::~CommandObjectWatchpointSet () 907 { 908 } 909 910 Options * 911 CommandObjectWatchpointSet::GetOptions () 912 { 913 return &m_option_group; 914 } 915 916 bool 917 CommandObjectWatchpointSet::Execute 918 ( 919 Args& command, 920 CommandReturnObject &result 921 ) 922 { 923 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 924 ExecutionContext exe_ctx(m_interpreter.GetExecutionContext()); 925 StackFrame *frame = exe_ctx.GetFramePtr(); 926 if (frame == NULL) 927 { 928 result.AppendError ("you must be stopped in a valid stack frame to set a watchpoint."); 929 result.SetStatus (eReturnStatusFailed); 930 return false; 931 } 932 933 // Be careful about the stack frame, if any summary formatter runs code, it might clear the StackFrameList 934 // for the thread. So hold onto a shared pointer to the frame so it stays alive. 935 bool get_file_globals = true; 936 VariableList *variable_list = frame->GetVariableList (get_file_globals); 937 938 bool watch_address = (m_option_watchpoint.watch_size > 0); 939 940 // If no '-w' is specified, default to '-w read_write'. 941 if (!m_option_watchpoint.watch_variable) 942 { 943 m_option_watchpoint.watch_variable = true; 944 m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchReadWrite; 945 } 946 // It's possible to specify an address to watch for with the '-x' option. 947 if (!variable_list && !watch_address) 948 { 949 result.GetErrorStream().Printf("error: no variables found, did you forget to use '-x' option to watch an address?\n"); 950 result.SetStatus(eReturnStatusFailed); 951 return false; 952 } 953 // If thre's no argument, it is an error. 954 if (command.GetArgumentCount() <= 0) 955 { 956 result.GetErrorStream().Printf("error: specify your target variable (no '-x') or expression (with '-x') to watch for\n"); 957 result.SetStatus(eReturnStatusFailed); 958 return false; 959 } 960 961 // We passed the sanity check for the options. 962 // Proceed to set the watchpoint now. 963 lldb::addr_t addr = 0; 964 size_t size = 0; 965 966 VariableSP var_sp; 967 ValueObjectSP valobj_sp; 968 Stream &output_stream = result.GetOutputStream(); 969 970 if (watch_address) { 971 std::string expr_str; 972 command.GetQuotedCommandString(expr_str); 973 const bool coerce_to_id = true; 974 const bool unwind_on_error = true; 975 const bool keep_in_memory = false; 976 ExecutionResults expr_result = target->EvaluateExpression (expr_str.c_str(), 977 frame, 978 eExecutionPolicyOnlyWhenNeeded, 979 coerce_to_id, 980 unwind_on_error, 981 keep_in_memory, 982 eNoDynamicValues, 983 valobj_sp); 984 if (expr_result != eExecutionCompleted) { 985 result.GetErrorStream().Printf("error: expression evaluation of address to watch failed\n"); 986 result.SetStatus(eReturnStatusFailed); 987 } 988 989 // Get the address to watch. 990 addr = valobj_sp->GetValueAsUnsigned(0); 991 if (!addr) { 992 result.GetErrorStream().Printf("error: expression did not evaluate to an address\n"); 993 result.SetStatus(eReturnStatusFailed); 994 return false; 995 } 996 size = m_option_watchpoint.watch_size; 997 } else { 998 // A simple watch variable gesture allows only one argument. 999 if (m_option_watchpoint.watch_size == 0 && command.GetArgumentCount() != 1) { 1000 result.GetErrorStream().Printf("error: specify exactly one variable with the '-w' option, i.e., no '-x'\n"); 1001 result.SetStatus(eReturnStatusFailed); 1002 return false; 1003 } 1004 1005 // Things have checked out ok... 1006 Error error; 1007 uint32_t expr_path_options = StackFrame::eExpressionPathOptionCheckPtrVsMember; 1008 valobj_sp = frame->GetValueForVariableExpressionPath (command.GetArgumentAtIndex(0), 1009 eNoDynamicValues, 1010 expr_path_options, 1011 var_sp, 1012 error); 1013 if (valobj_sp) { 1014 AddressType addr_type; 1015 addr = valobj_sp->GetAddressOf(false, &addr_type); 1016 if (addr_type == eAddressTypeLoad) { 1017 // We're in business. 1018 // Find out the size of this variable. 1019 size = valobj_sp->GetByteSize(); 1020 } 1021 } else { 1022 const char *error_cstr = error.AsCString(NULL); 1023 if (error_cstr) 1024 result.GetErrorStream().Printf("error: %s\n", error_cstr); 1025 else 1026 result.GetErrorStream().Printf ("error: unable to find any variable expression path that matches '%s'\n", 1027 command.GetArgumentAtIndex(0)); 1028 return false; 1029 } 1030 } 1031 1032 // Now it's time to create the watchpoint. 1033 uint32_t watch_type = m_option_watchpoint.watch_type; 1034 Watchpoint *wp = exe_ctx.GetTargetRef().CreateWatchpoint(addr, size, watch_type).get(); 1035 if (wp) { 1036 if (var_sp && var_sp->GetDeclaration().GetFile()) { 1037 StreamString ss; 1038 // True to show fullpath for declaration file. 1039 var_sp->GetDeclaration().DumpStopContext(&ss, true); 1040 wp->SetDeclInfo(ss.GetString()); 1041 } 1042 StreamString ss; 1043 output_stream.Printf("Watchpoint created: "); 1044 wp->GetDescription(&output_stream, lldb::eDescriptionLevelFull); 1045 output_stream.EOL(); 1046 result.SetStatus(eReturnStatusSuccessFinishResult); 1047 } else { 1048 result.AppendErrorWithFormat("Watchpoint creation failed.\n"); 1049 result.SetStatus(eReturnStatusFailed); 1050 } 1051 1052 return result.Succeeded(); 1053 } 1054