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 859 CommandObjectWatchpointSet::CommandObjectWatchpointSet (CommandInterpreter &interpreter) : 860 CommandObjectMultiword (interpreter, 861 "watchpoint set", 862 "A set of commands for setting a watchpoint.", 863 "watchpoint set <subcommand> [<subcommand-options>]") 864 { 865 866 LoadSubCommand ("variable", CommandObjectSP (new CommandObjectWatchpointSetVariable (interpreter))); 867 LoadSubCommand ("expression", CommandObjectSP (new CommandObjectWatchpointSetExpression (interpreter))); 868 } 869 870 CommandObjectWatchpointSet::~CommandObjectWatchpointSet () 871 { 872 } 873 874 //------------------------------------------------------------------------- 875 // CommandObjectWatchpointSetVariable 876 //------------------------------------------------------------------------- 877 #pragma mark Set 878 879 CommandObjectWatchpointSetVariable::CommandObjectWatchpointSetVariable (CommandInterpreter &interpreter) : 880 CommandObject (interpreter, 881 "watchpoint set variable", 882 "Set a watchpoint on a variable. " 883 "Use the '-w' option to specify the type of watchpoint and " 884 "the '-x' option to specify the byte size to watch for. " 885 "If no '-w' option is specified, it defaults to read_write. " 886 "If no '-x' option is specified, it defaults to the variable's " 887 "byte size. " 888 "Note that hardware resources for watching are often limited.", 889 NULL, 890 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused), 891 m_option_group (interpreter), 892 m_option_watchpoint () 893 { 894 SetHelpLong( 895 "Examples: \n\ 896 \n\ 897 watchpoint set variable -w read_wriate my_global_var \n\ 898 # Watch my_global_var for read/write access, with the region to watch corresponding to the byte size of the data type.\n"); 899 900 CommandArgumentEntry arg; 901 CommandArgumentData var_name_arg; 902 903 // Define the only variant of this arg. 904 var_name_arg.arg_type = eArgTypeVarName; 905 var_name_arg.arg_repetition = eArgRepeatPlain; 906 907 // Push the variant into the argument entry. 908 arg.push_back (var_name_arg); 909 910 // Push the data for the only argument into the m_arguments vector. 911 m_arguments.push_back (arg); 912 913 // Absorb the '-w' and '-x' options into our option group. 914 m_option_group.Append (&m_option_watchpoint, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 915 m_option_group.Finalize(); 916 } 917 918 CommandObjectWatchpointSetVariable::~CommandObjectWatchpointSetVariable () 919 { 920 } 921 922 Options * 923 CommandObjectWatchpointSetVariable::GetOptions () 924 { 925 return &m_option_group; 926 } 927 928 bool 929 CommandObjectWatchpointSetVariable::Execute 930 ( 931 Args& command, 932 CommandReturnObject &result 933 ) 934 { 935 ExecutionContext exe_ctx(m_interpreter.GetExecutionContext()); 936 StackFrame *frame = exe_ctx.GetFramePtr(); 937 if (frame == NULL) 938 { 939 result.AppendError ("you must be stopped in a valid stack frame to set a watchpoint."); 940 result.SetStatus (eReturnStatusFailed); 941 return false; 942 } 943 944 // If no argument is present, issue an error message. There's no way to set a watchpoint. 945 if (command.GetArgumentCount() <= 0) 946 { 947 result.GetErrorStream().Printf("error: required argument missing; specify your program variable to watch for\n"); 948 result.SetStatus(eReturnStatusFailed); 949 return false; 950 } 951 952 // If no '-w' is specified, default to '-w read_write'. 953 if (!m_option_watchpoint.watch_type_specified) 954 { 955 m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchReadWrite; 956 } 957 958 // We passed the sanity check for the command. 959 // Proceed to set the watchpoint now. 960 lldb::addr_t addr = 0; 961 size_t size = 0; 962 963 VariableSP var_sp; 964 ValueObjectSP valobj_sp; 965 Stream &output_stream = result.GetOutputStream(); 966 967 // A simple watch variable gesture allows only one argument. 968 if (command.GetArgumentCount() != 1) { 969 result.GetErrorStream().Printf("error: specify exactly one variable to watch for\n"); 970 result.SetStatus(eReturnStatusFailed); 971 return false; 972 } 973 974 // Things have checked out ok... 975 Error error; 976 uint32_t expr_path_options = StackFrame::eExpressionPathOptionCheckPtrVsMember; 977 valobj_sp = frame->GetValueForVariableExpressionPath (command.GetArgumentAtIndex(0), 978 eNoDynamicValues, 979 expr_path_options, 980 var_sp, 981 error); 982 if (valobj_sp) { 983 AddressType addr_type; 984 addr = valobj_sp->GetAddressOf(false, &addr_type); 985 if (addr_type == eAddressTypeLoad) { 986 // We're in business. 987 // Find out the size of this variable. 988 size = m_option_watchpoint.watch_size == 0 ? valobj_sp->GetByteSize() 989 : m_option_watchpoint.watch_size; 990 } 991 } else { 992 const char *error_cstr = error.AsCString(NULL); 993 if (error_cstr) 994 result.GetErrorStream().Printf("error: %s\n", error_cstr); 995 else 996 result.GetErrorStream().Printf ("error: unable to find any variable expression path that matches '%s'\n", 997 command.GetArgumentAtIndex(0)); 998 return false; 999 } 1000 1001 // Now it's time to create the watchpoint. 1002 uint32_t watch_type = m_option_watchpoint.watch_type; 1003 Watchpoint *wp = exe_ctx.GetTargetRef().CreateWatchpoint(addr, size, watch_type).get(); 1004 if (wp) { 1005 if (var_sp && var_sp->GetDeclaration().GetFile()) { 1006 StreamString ss; 1007 // True to show fullpath for declaration file. 1008 var_sp->GetDeclaration().DumpStopContext(&ss, true); 1009 wp->SetDeclInfo(ss.GetString()); 1010 } 1011 StreamString ss; 1012 output_stream.Printf("Watchpoint created: "); 1013 wp->GetDescription(&output_stream, lldb::eDescriptionLevelFull); 1014 output_stream.EOL(); 1015 result.SetStatus(eReturnStatusSuccessFinishResult); 1016 } else { 1017 result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%llx, size=%lu).\n", 1018 addr, size); 1019 result.SetStatus(eReturnStatusFailed); 1020 } 1021 1022 return result.Succeeded(); 1023 } 1024 1025 //------------------------------------------------------------------------- 1026 // CommandObjectWatchpointSetExpression 1027 //------------------------------------------------------------------------- 1028 #pragma mark Set 1029 1030 CommandObjectWatchpointSetExpression::CommandObjectWatchpointSetExpression (CommandInterpreter &interpreter) : 1031 CommandObject (interpreter, 1032 "watchpoint set expression", 1033 "Set a watchpoint on an address by supplying an expression. " 1034 "Use the '-w' option to specify the type of watchpoint and " 1035 "the '-x' option to specify the byte size to watch for. " 1036 "If no '-w' option is specified, it defaults to read_write. " 1037 "If no '-x' option is specified, it defaults to the target's " 1038 "pointer byte size. " 1039 "Note that hardware resources for watching are often limited.", 1040 NULL, 1041 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused), 1042 m_option_group (interpreter), 1043 m_option_watchpoint () 1044 { 1045 SetHelpLong( 1046 "Examples: \n\ 1047 \n\ 1048 watchpoint set expression -w write -x 1 -- foo + 32\n\ 1049 # Watch write access for the 1-byte region pointed to by the address 'foo + 32'.\n"); 1050 1051 CommandArgumentEntry arg; 1052 CommandArgumentData expression_arg; 1053 1054 // Define the only variant of this arg. 1055 expression_arg.arg_type = eArgTypeExpression; 1056 expression_arg.arg_repetition = eArgRepeatPlain; 1057 1058 // Push the only variant into the argument entry. 1059 arg.push_back (expression_arg); 1060 1061 // Push the data for the only argument into the m_arguments vector. 1062 m_arguments.push_back (arg); 1063 1064 // Absorb the '-w' and '-x' options into our option group. 1065 m_option_group.Append (&m_option_watchpoint, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 1066 m_option_group.Finalize(); 1067 } 1068 1069 CommandObjectWatchpointSetExpression::~CommandObjectWatchpointSetExpression () 1070 { 1071 } 1072 1073 Options * 1074 CommandObjectWatchpointSetExpression::GetOptions () 1075 { 1076 return &m_option_group; 1077 } 1078 1079 #include "llvm/ADT/StringRef.h" 1080 static inline void StripLeadingSpaces(llvm::StringRef &Str) 1081 { 1082 while (!Str.empty() && isspace(Str[0])) 1083 Str = Str.substr(1); 1084 } 1085 static inline llvm::StringRef StripOptionTerminator(llvm::StringRef &Str, bool with_dash_w, bool with_dash_x) 1086 { 1087 llvm::StringRef ExprStr = Str; 1088 1089 // Get rid of the leading spaces first. 1090 StripLeadingSpaces(ExprStr); 1091 1092 // If there's no '-w' and no '-x', we can just return. 1093 if (!with_dash_w && !with_dash_x) 1094 return ExprStr; 1095 1096 // Otherwise, split on the "--" option terminator string, and return the rest of the string. 1097 ExprStr = ExprStr.split("--").second; 1098 StripLeadingSpaces(ExprStr); 1099 return ExprStr; 1100 } 1101 bool 1102 CommandObjectWatchpointSetExpression::ExecuteRawCommandString 1103 ( 1104 const char *raw_command, 1105 CommandReturnObject &result 1106 ) 1107 { 1108 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 1109 ExecutionContext exe_ctx(m_interpreter.GetExecutionContext()); 1110 StackFrame *frame = exe_ctx.GetFramePtr(); 1111 if (frame == NULL) 1112 { 1113 result.AppendError ("you must be stopped in a valid stack frame to set a watchpoint."); 1114 result.SetStatus (eReturnStatusFailed); 1115 return false; 1116 } 1117 1118 Args command(raw_command); 1119 1120 // Process possible options. 1121 if (!ParseOptions (command, result)) 1122 return false; 1123 1124 // If no argument is present, issue an error message. There's no way to set a watchpoint. 1125 if (command.GetArgumentCount() <= 0) 1126 { 1127 result.GetErrorStream().Printf("error: required argument missing; specify an expression to evaulate into the addres to watch for\n"); 1128 result.SetStatus(eReturnStatusFailed); 1129 return false; 1130 } 1131 1132 bool with_dash_w = m_option_watchpoint.watch_type_specified; 1133 bool with_dash_x = (m_option_watchpoint.watch_size != 0); 1134 1135 // If no '-w' is specified, default to '-w read_write'. 1136 if (!with_dash_w) 1137 { 1138 m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchReadWrite; 1139 } 1140 1141 // We passed the sanity check for the command. 1142 // Proceed to set the watchpoint now. 1143 lldb::addr_t addr = 0; 1144 size_t size = 0; 1145 1146 VariableSP var_sp; 1147 ValueObjectSP valobj_sp; 1148 Stream &output_stream = result.GetOutputStream(); 1149 1150 // We will process the raw command string to rid of the '-w', '-x', or '--' 1151 llvm::StringRef raw_expr_str(raw_command); 1152 std::string expr_str = StripOptionTerminator(raw_expr_str, with_dash_w, with_dash_x).str(); 1153 1154 // Sanity check for when the user forgets to terminate the option strings with a '--'. 1155 if ((with_dash_w || with_dash_w) && expr_str.empty()) 1156 { 1157 result.GetErrorStream().Printf("error: did you forget to enter the option terminator string \"--\"?\n"); 1158 result.SetStatus(eReturnStatusFailed); 1159 return false; 1160 } 1161 1162 // Use expression evaluation to arrive at the address to watch. 1163 const bool coerce_to_id = true; 1164 const bool unwind_on_error = true; 1165 const bool keep_in_memory = false; 1166 ExecutionResults expr_result = target->EvaluateExpression (expr_str.c_str(), 1167 frame, 1168 eExecutionPolicyOnlyWhenNeeded, 1169 coerce_to_id, 1170 unwind_on_error, 1171 keep_in_memory, 1172 eNoDynamicValues, 1173 valobj_sp); 1174 if (expr_result != eExecutionCompleted) { 1175 result.GetErrorStream().Printf("error: expression evaluation of address to watch failed\n"); 1176 result.GetErrorStream().Printf("expression evaluated: %s\n", expr_str.c_str()); 1177 result.SetStatus(eReturnStatusFailed); 1178 return false; 1179 } 1180 1181 // Get the address to watch. 1182 addr = valobj_sp->GetValueAsUnsigned(0); 1183 if (!addr) { 1184 result.GetErrorStream().Printf("error: expression did not evaluate to an address\n"); 1185 result.SetStatus(eReturnStatusFailed); 1186 return false; 1187 } 1188 size = with_dash_x ? m_option_watchpoint.watch_size 1189 : target->GetArchitecture().GetAddressByteSize(); 1190 1191 // Now it's time to create the watchpoint. 1192 uint32_t watch_type = m_option_watchpoint.watch_type; 1193 Watchpoint *wp = exe_ctx.GetTargetRef().CreateWatchpoint(addr, size, watch_type).get(); 1194 if (wp) { 1195 if (var_sp && var_sp->GetDeclaration().GetFile()) { 1196 StreamString ss; 1197 // True to show fullpath for declaration file. 1198 var_sp->GetDeclaration().DumpStopContext(&ss, true); 1199 wp->SetDeclInfo(ss.GetString()); 1200 } 1201 StreamString ss; 1202 output_stream.Printf("Watchpoint created: "); 1203 wp->GetDescription(&output_stream, lldb::eDescriptionLevelFull); 1204 output_stream.EOL(); 1205 result.SetStatus(eReturnStatusSuccessFinishResult); 1206 } else { 1207 result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%llx, size=%lu).\n", 1208 addr, size); 1209 result.SetStatus(eReturnStatusFailed); 1210 } 1211 1212 return result.Succeeded(); 1213 } 1214