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