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 if (target->GetProcessSP() && target->GetProcessSP()->IsAlive()) 294 { 295 uint32_t num_supported_hardware_watchpoints; 296 Error error = target->GetProcessSP()->GetWatchpointSupportInfo(num_supported_hardware_watchpoints); 297 if (error.Success()) 298 result.AppendMessageWithFormat("Number of supported hardware watchpoints: %u\n", 299 num_supported_hardware_watchpoints); 300 } 301 302 const WatchpointList &watchpoints = target->GetWatchpointList(); 303 Mutex::Locker locker; 304 target->GetWatchpointList().GetListMutex(locker); 305 306 size_t num_watchpoints = watchpoints.GetSize(); 307 308 if (num_watchpoints == 0) 309 { 310 result.AppendMessage("No watchpoints currently set."); 311 result.SetStatus(eReturnStatusSuccessFinishNoResult); 312 return true; 313 } 314 315 Stream &output_stream = result.GetOutputStream(); 316 317 if (args.GetArgumentCount() == 0) 318 { 319 // No watchpoint selected; show info about all currently set watchpoints. 320 result.AppendMessage ("Current watchpoints:"); 321 for (size_t i = 0; i < num_watchpoints; ++i) 322 { 323 Watchpoint *wp = watchpoints.GetByIndex(i).get(); 324 AddWatchpointDescription(&output_stream, wp, m_options.m_level); 325 } 326 result.SetStatus(eReturnStatusSuccessFinishNoResult); 327 } 328 else 329 { 330 // Particular watchpoints selected; enable them. 331 std::vector<uint32_t> wp_ids; 332 if (!VerifyWatchpointIDs(args, wp_ids)) 333 { 334 result.AppendError("Invalid watchpoints specification."); 335 result.SetStatus(eReturnStatusFailed); 336 return false; 337 } 338 339 const size_t size = wp_ids.size(); 340 for (size_t i = 0; i < size; ++i) 341 { 342 Watchpoint *wp = watchpoints.FindByID(wp_ids[i]).get(); 343 if (wp) 344 AddWatchpointDescription(&output_stream, wp, m_options.m_level); 345 result.SetStatus(eReturnStatusSuccessFinishNoResult); 346 } 347 } 348 349 return result.Succeeded(); 350 } 351 352 //------------------------------------------------------------------------- 353 // CommandObjectWatchpointEnable 354 //------------------------------------------------------------------------- 355 #pragma mark Enable 356 357 CommandObjectWatchpointEnable::CommandObjectWatchpointEnable(CommandInterpreter &interpreter) : 358 CommandObject(interpreter, 359 "enable", 360 "Enable the specified disabled watchpoint(s). If no watchpoints are specified, enable all of them.", 361 NULL) 362 { 363 CommandArgumentEntry arg; 364 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); 365 // Add the entry for the first argument for this command to the object's arguments vector. 366 m_arguments.push_back(arg); 367 } 368 369 CommandObjectWatchpointEnable::~CommandObjectWatchpointEnable() 370 { 371 } 372 373 bool 374 CommandObjectWatchpointEnable::Execute(Args& args, CommandReturnObject &result) 375 { 376 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 377 if (!CheckTargetForWatchpointOperations(target, result)) 378 return false; 379 380 Mutex::Locker locker; 381 target->GetWatchpointList().GetListMutex(locker); 382 383 const WatchpointList &watchpoints = target->GetWatchpointList(); 384 385 size_t num_watchpoints = watchpoints.GetSize(); 386 387 if (num_watchpoints == 0) 388 { 389 result.AppendError("No watchpoints exist to be enabled."); 390 result.SetStatus(eReturnStatusFailed); 391 return false; 392 } 393 394 if (args.GetArgumentCount() == 0) 395 { 396 // No watchpoint selected; enable all currently set watchpoints. 397 target->EnableAllWatchpoints(); 398 result.AppendMessageWithFormat("All watchpoints enabled. (%lu watchpoints)\n", num_watchpoints); 399 result.SetStatus(eReturnStatusSuccessFinishNoResult); 400 } 401 else 402 { 403 // Particular watchpoints selected; enable them. 404 std::vector<uint32_t> wp_ids; 405 if (!VerifyWatchpointIDs(args, wp_ids)) 406 { 407 result.AppendError("Invalid watchpoints specification."); 408 result.SetStatus(eReturnStatusFailed); 409 return false; 410 } 411 412 int count = 0; 413 const size_t size = wp_ids.size(); 414 for (size_t i = 0; i < size; ++i) 415 if (target->EnableWatchpointByID(wp_ids[i])) 416 ++count; 417 result.AppendMessageWithFormat("%d watchpoints enabled.\n", count); 418 result.SetStatus(eReturnStatusSuccessFinishNoResult); 419 } 420 421 return result.Succeeded(); 422 } 423 424 //------------------------------------------------------------------------- 425 // CommandObjectWatchpointDisable 426 //------------------------------------------------------------------------- 427 #pragma mark Disable 428 429 CommandObjectWatchpointDisable::CommandObjectWatchpointDisable(CommandInterpreter &interpreter) : 430 CommandObject(interpreter, 431 "watchpoint disable", 432 "Disable the specified watchpoint(s) without removing it/them. If no watchpoints are specified, disable them all.", 433 NULL) 434 { 435 CommandArgumentEntry arg; 436 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); 437 // Add the entry for the first argument for this command to the object's arguments vector. 438 m_arguments.push_back(arg); 439 } 440 441 CommandObjectWatchpointDisable::~CommandObjectWatchpointDisable() 442 { 443 } 444 445 bool 446 CommandObjectWatchpointDisable::Execute(Args& args, CommandReturnObject &result) 447 { 448 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 449 if (!CheckTargetForWatchpointOperations(target, result)) 450 return false; 451 452 Mutex::Locker locker; 453 target->GetWatchpointList().GetListMutex(locker); 454 455 const WatchpointList &watchpoints = target->GetWatchpointList(); 456 size_t num_watchpoints = watchpoints.GetSize(); 457 458 if (num_watchpoints == 0) 459 { 460 result.AppendError("No watchpoints exist to be disabled."); 461 result.SetStatus(eReturnStatusFailed); 462 return false; 463 } 464 465 if (args.GetArgumentCount() == 0) 466 { 467 // No watchpoint selected; disable all currently set watchpoints. 468 if (target->DisableAllWatchpoints()) 469 { 470 result.AppendMessageWithFormat("All watchpoints disabled. (%lu watchpoints)\n", num_watchpoints); 471 result.SetStatus(eReturnStatusSuccessFinishNoResult); 472 } 473 else 474 { 475 result.AppendError("Disable all watchpoints failed\n"); 476 result.SetStatus(eReturnStatusFailed); 477 } 478 } 479 else 480 { 481 // Particular watchpoints selected; disable them. 482 std::vector<uint32_t> wp_ids; 483 if (!VerifyWatchpointIDs(args, wp_ids)) 484 { 485 result.AppendError("Invalid watchpoints specification."); 486 result.SetStatus(eReturnStatusFailed); 487 return false; 488 } 489 490 int count = 0; 491 const size_t size = wp_ids.size(); 492 for (size_t i = 0; i < size; ++i) 493 if (target->DisableWatchpointByID(wp_ids[i])) 494 ++count; 495 result.AppendMessageWithFormat("%d watchpoints disabled.\n", count); 496 result.SetStatus(eReturnStatusSuccessFinishNoResult); 497 } 498 499 return result.Succeeded(); 500 } 501 502 //------------------------------------------------------------------------- 503 // CommandObjectWatchpointDelete 504 //------------------------------------------------------------------------- 505 #pragma mark Delete 506 507 CommandObjectWatchpointDelete::CommandObjectWatchpointDelete(CommandInterpreter &interpreter) : 508 CommandObject(interpreter, 509 "watchpoint delete", 510 "Delete the specified watchpoint(s). If no watchpoints are specified, delete them all.", 511 NULL) 512 { 513 CommandArgumentEntry arg; 514 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); 515 // Add the entry for the first argument for this command to the object's arguments vector. 516 m_arguments.push_back(arg); 517 } 518 519 CommandObjectWatchpointDelete::~CommandObjectWatchpointDelete() 520 { 521 } 522 523 bool 524 CommandObjectWatchpointDelete::Execute(Args& args, CommandReturnObject &result) 525 { 526 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 527 if (!CheckTargetForWatchpointOperations(target, result)) 528 return false; 529 530 Mutex::Locker locker; 531 target->GetWatchpointList().GetListMutex(locker); 532 533 const WatchpointList &watchpoints = target->GetWatchpointList(); 534 535 size_t num_watchpoints = watchpoints.GetSize(); 536 537 if (num_watchpoints == 0) 538 { 539 result.AppendError("No watchpoints exist to be deleted."); 540 result.SetStatus(eReturnStatusFailed); 541 return false; 542 } 543 544 if (args.GetArgumentCount() == 0) 545 { 546 if (!m_interpreter.Confirm("About to delete all watchpoints, do you want to do that?", true)) 547 { 548 result.AppendMessage("Operation cancelled..."); 549 } 550 else 551 { 552 target->RemoveAllWatchpoints(); 553 result.AppendMessageWithFormat("All watchpoints removed. (%lu watchpoints)\n", num_watchpoints); 554 } 555 result.SetStatus (eReturnStatusSuccessFinishNoResult); 556 } 557 else 558 { 559 // Particular watchpoints selected; delete them. 560 std::vector<uint32_t> wp_ids; 561 if (!VerifyWatchpointIDs(args, wp_ids)) 562 { 563 result.AppendError("Invalid watchpoints specification."); 564 result.SetStatus(eReturnStatusFailed); 565 return false; 566 } 567 568 int count = 0; 569 const size_t size = wp_ids.size(); 570 for (size_t i = 0; i < size; ++i) 571 if (target->RemoveWatchpointByID(wp_ids[i])) 572 ++count; 573 result.AppendMessageWithFormat("%d watchpoints deleted.\n",count); 574 result.SetStatus (eReturnStatusSuccessFinishNoResult); 575 } 576 577 return result.Succeeded(); 578 } 579 580 //------------------------------------------------------------------------- 581 // CommandObjectWatchpointIgnore::CommandOptions 582 //------------------------------------------------------------------------- 583 #pragma mark Ignore::CommandOptions 584 585 CommandObjectWatchpointIgnore::CommandOptions::CommandOptions(CommandInterpreter &interpreter) : 586 Options (interpreter), 587 m_ignore_count (0) 588 { 589 } 590 591 CommandObjectWatchpointIgnore::CommandOptions::~CommandOptions () 592 { 593 } 594 595 OptionDefinition 596 CommandObjectWatchpointIgnore::CommandOptions::g_option_table[] = 597 { 598 { LLDB_OPT_SET_ALL, true, "ignore-count", 'i', required_argument, NULL, NULL, eArgTypeCount, "Set the number of times this watchpoint is skipped before stopping." }, 599 { 0, false, NULL, 0 , 0, NULL, 0, eArgTypeNone, NULL } 600 }; 601 602 const OptionDefinition* 603 CommandObjectWatchpointIgnore::CommandOptions::GetDefinitions () 604 { 605 return g_option_table; 606 } 607 608 Error 609 CommandObjectWatchpointIgnore::CommandOptions::SetOptionValue (uint32_t option_idx, const char *option_arg) 610 { 611 Error error; 612 char short_option = (char) m_getopt_table[option_idx].val; 613 614 switch (short_option) 615 { 616 case 'i': 617 { 618 m_ignore_count = Args::StringToUInt32(option_arg, UINT32_MAX, 0); 619 if (m_ignore_count == UINT32_MAX) 620 error.SetErrorStringWithFormat ("invalid ignore count '%s'", option_arg); 621 } 622 break; 623 default: 624 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 625 break; 626 } 627 628 return error; 629 } 630 631 void 632 CommandObjectWatchpointIgnore::CommandOptions::OptionParsingStarting () 633 { 634 m_ignore_count = 0; 635 } 636 637 //------------------------------------------------------------------------- 638 // CommandObjectWatchpointIgnore 639 //------------------------------------------------------------------------- 640 #pragma mark Ignore 641 642 CommandObjectWatchpointIgnore::CommandObjectWatchpointIgnore(CommandInterpreter &interpreter) : 643 CommandObject(interpreter, 644 "watchpoint ignore", 645 "Set ignore count on the specified watchpoint(s). If no watchpoints are specified, set them all.", 646 NULL), 647 m_options (interpreter) 648 { 649 CommandArgumentEntry arg; 650 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); 651 // Add the entry for the first argument for this command to the object's arguments vector. 652 m_arguments.push_back(arg); 653 } 654 655 CommandObjectWatchpointIgnore::~CommandObjectWatchpointIgnore() 656 { 657 } 658 659 Options * 660 CommandObjectWatchpointIgnore::GetOptions () 661 { 662 return &m_options; 663 } 664 665 bool 666 CommandObjectWatchpointIgnore::Execute(Args& args, CommandReturnObject &result) 667 { 668 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 669 if (!CheckTargetForWatchpointOperations(target, result)) 670 return false; 671 672 Mutex::Locker locker; 673 target->GetWatchpointList().GetListMutex(locker); 674 675 const WatchpointList &watchpoints = target->GetWatchpointList(); 676 677 size_t num_watchpoints = watchpoints.GetSize(); 678 679 if (num_watchpoints == 0) 680 { 681 result.AppendError("No watchpoints exist to be ignored."); 682 result.SetStatus(eReturnStatusFailed); 683 return false; 684 } 685 686 if (args.GetArgumentCount() == 0) 687 { 688 target->IgnoreAllWatchpoints(m_options.m_ignore_count); 689 result.AppendMessageWithFormat("All watchpoints ignored. (%lu watchpoints)\n", num_watchpoints); 690 result.SetStatus (eReturnStatusSuccessFinishNoResult); 691 } 692 else 693 { 694 // Particular watchpoints selected; ignore them. 695 std::vector<uint32_t> wp_ids; 696 if (!VerifyWatchpointIDs(args, wp_ids)) 697 { 698 result.AppendError("Invalid watchpoints specification."); 699 result.SetStatus(eReturnStatusFailed); 700 return false; 701 } 702 703 int count = 0; 704 const size_t size = wp_ids.size(); 705 for (size_t i = 0; i < size; ++i) 706 if (target->IgnoreWatchpointByID(wp_ids[i], m_options.m_ignore_count)) 707 ++count; 708 result.AppendMessageWithFormat("%d watchpoints ignored.\n",count); 709 result.SetStatus (eReturnStatusSuccessFinishNoResult); 710 } 711 712 return result.Succeeded(); 713 } 714 715 //------------------------------------------------------------------------- 716 // CommandObjectWatchpointModify::CommandOptions 717 //------------------------------------------------------------------------- 718 #pragma mark Modify::CommandOptions 719 720 CommandObjectWatchpointModify::CommandOptions::CommandOptions(CommandInterpreter &interpreter) : 721 Options (interpreter), 722 m_condition (), 723 m_condition_passed (false) 724 { 725 } 726 727 CommandObjectWatchpointModify::CommandOptions::~CommandOptions () 728 { 729 } 730 731 OptionDefinition 732 CommandObjectWatchpointModify::CommandOptions::g_option_table[] = 733 { 734 { LLDB_OPT_SET_ALL, false, "condition", 'c', required_argument, NULL, NULL, eArgTypeExpression, "The watchpoint stops only if this condition expression evaluates to true."}, 735 { 0, false, NULL, 0 , 0, NULL, 0, eArgTypeNone, NULL } 736 }; 737 738 const OptionDefinition* 739 CommandObjectWatchpointModify::CommandOptions::GetDefinitions () 740 { 741 return g_option_table; 742 } 743 744 Error 745 CommandObjectWatchpointModify::CommandOptions::SetOptionValue (uint32_t option_idx, const char *option_arg) 746 { 747 Error error; 748 char short_option = (char) m_getopt_table[option_idx].val; 749 750 switch (short_option) 751 { 752 case 'c': 753 if (option_arg != NULL) 754 m_condition.assign (option_arg); 755 else 756 m_condition.clear(); 757 m_condition_passed = true; 758 break; 759 default: 760 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 761 break; 762 } 763 764 return error; 765 } 766 767 void 768 CommandObjectWatchpointModify::CommandOptions::OptionParsingStarting () 769 { 770 m_condition.clear(); 771 m_condition_passed = false; 772 } 773 774 //------------------------------------------------------------------------- 775 // CommandObjectWatchpointModify 776 //------------------------------------------------------------------------- 777 #pragma mark Modify 778 779 CommandObjectWatchpointModify::CommandObjectWatchpointModify (CommandInterpreter &interpreter) : 780 CommandObject (interpreter, 781 "watchpoint modify", 782 "Modify the options on a watchpoint or set of watchpoints in the executable. " 783 "If no watchpoint is specified, act on the last created watchpoint. " 784 "Passing an empty argument clears the modification.", 785 NULL), 786 m_options (interpreter) 787 { 788 CommandArgumentEntry arg; 789 CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); 790 // Add the entry for the first argument for this command to the object's arguments vector. 791 m_arguments.push_back (arg); 792 } 793 794 CommandObjectWatchpointModify::~CommandObjectWatchpointModify () 795 { 796 } 797 798 Options * 799 CommandObjectWatchpointModify::GetOptions () 800 { 801 return &m_options; 802 } 803 804 bool 805 CommandObjectWatchpointModify::Execute 806 ( 807 Args& args, 808 CommandReturnObject &result 809 ) 810 { 811 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 812 if (!CheckTargetForWatchpointOperations(target, result)) 813 return false; 814 815 Mutex::Locker locker; 816 target->GetWatchpointList().GetListMutex(locker); 817 818 const WatchpointList &watchpoints = target->GetWatchpointList(); 819 820 size_t num_watchpoints = watchpoints.GetSize(); 821 822 if (num_watchpoints == 0) 823 { 824 result.AppendError("No watchpoints exist to be modified."); 825 result.SetStatus(eReturnStatusFailed); 826 return false; 827 } 828 829 if (args.GetArgumentCount() == 0) 830 { 831 WatchpointSP wp_sp = target->GetLastCreatedWatchpoint(); 832 wp_sp->SetCondition(m_options.m_condition.c_str()); 833 result.SetStatus (eReturnStatusSuccessFinishNoResult); 834 } 835 else 836 { 837 // Particular watchpoints selected; set condition on them. 838 std::vector<uint32_t> wp_ids; 839 if (!VerifyWatchpointIDs(args, wp_ids)) 840 { 841 result.AppendError("Invalid watchpoints specification."); 842 result.SetStatus(eReturnStatusFailed); 843 return false; 844 } 845 846 int count = 0; 847 const size_t size = wp_ids.size(); 848 for (size_t i = 0; i < size; ++i) 849 { 850 WatchpointSP wp_sp = watchpoints.FindByID(wp_ids[i]); 851 if (wp_sp) 852 { 853 wp_sp->SetCondition(m_options.m_condition.c_str()); 854 ++count; 855 } 856 } 857 result.AppendMessageWithFormat("%d watchpoints modified.\n",count); 858 result.SetStatus (eReturnStatusSuccessFinishNoResult); 859 } 860 861 return result.Succeeded(); 862 } 863 864 //------------------------------------------------------------------------- 865 // CommandObjectWatchpointSet 866 //------------------------------------------------------------------------- 867 868 CommandObjectWatchpointSet::CommandObjectWatchpointSet (CommandInterpreter &interpreter) : 869 CommandObjectMultiword (interpreter, 870 "watchpoint set", 871 "A set of commands for setting a watchpoint.", 872 "watchpoint set <subcommand> [<subcommand-options>]") 873 { 874 875 LoadSubCommand ("variable", CommandObjectSP (new CommandObjectWatchpointSetVariable (interpreter))); 876 LoadSubCommand ("expression", CommandObjectSP (new CommandObjectWatchpointSetExpression (interpreter))); 877 } 878 879 CommandObjectWatchpointSet::~CommandObjectWatchpointSet () 880 { 881 } 882 883 //------------------------------------------------------------------------- 884 // CommandObjectWatchpointSetVariable 885 //------------------------------------------------------------------------- 886 #pragma mark Set 887 888 CommandObjectWatchpointSetVariable::CommandObjectWatchpointSetVariable (CommandInterpreter &interpreter) : 889 CommandObject (interpreter, 890 "watchpoint set variable", 891 "Set a watchpoint on a variable. " 892 "Use the '-w' option to specify the type of watchpoint and " 893 "the '-x' option to specify the byte size to watch for. " 894 "If no '-w' option is specified, it defaults to read_write. " 895 "If no '-x' option is specified, it defaults to the variable's " 896 "byte size. " 897 "Note that there are limited hardware resources for watchpoints. " 898 "If watchpoint setting fails, consider disable/delete existing ones " 899 "to free up resources.", 900 NULL, 901 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused), 902 m_option_group (interpreter), 903 m_option_watchpoint () 904 { 905 SetHelpLong( 906 "Examples: \n\ 907 \n\ 908 watchpoint set variable -w read_wriate my_global_var \n\ 909 # Watch my_global_var for read/write access, with the region to watch corresponding to the byte size of the data type.\n"); 910 911 CommandArgumentEntry arg; 912 CommandArgumentData var_name_arg; 913 914 // Define the only variant of this arg. 915 var_name_arg.arg_type = eArgTypeVarName; 916 var_name_arg.arg_repetition = eArgRepeatPlain; 917 918 // Push the variant into the argument entry. 919 arg.push_back (var_name_arg); 920 921 // Push the data for the only argument into the m_arguments vector. 922 m_arguments.push_back (arg); 923 924 // Absorb the '-w' and '-x' options into our option group. 925 m_option_group.Append (&m_option_watchpoint, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 926 m_option_group.Finalize(); 927 } 928 929 CommandObjectWatchpointSetVariable::~CommandObjectWatchpointSetVariable () 930 { 931 } 932 933 Options * 934 CommandObjectWatchpointSetVariable::GetOptions () 935 { 936 return &m_option_group; 937 } 938 939 bool 940 CommandObjectWatchpointSetVariable::Execute 941 ( 942 Args& command, 943 CommandReturnObject &result 944 ) 945 { 946 ExecutionContext exe_ctx(m_interpreter.GetExecutionContext()); 947 StackFrame *frame = exe_ctx.GetFramePtr(); 948 if (frame == NULL) 949 { 950 result.AppendError ("you must be stopped in a valid stack frame to set a watchpoint."); 951 result.SetStatus (eReturnStatusFailed); 952 return false; 953 } 954 955 // If no argument is present, issue an error message. There's no way to set a watchpoint. 956 if (command.GetArgumentCount() <= 0) 957 { 958 result.GetErrorStream().Printf("error: required argument missing; specify your program variable to watch for\n"); 959 result.SetStatus(eReturnStatusFailed); 960 return false; 961 } 962 963 // If no '-w' is specified, default to '-w read_write'. 964 if (!m_option_watchpoint.watch_type_specified) 965 { 966 m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchReadWrite; 967 } 968 969 // We passed the sanity check for the command. 970 // Proceed to set the watchpoint now. 971 lldb::addr_t addr = 0; 972 size_t size = 0; 973 974 VariableSP var_sp; 975 ValueObjectSP valobj_sp; 976 Stream &output_stream = result.GetOutputStream(); 977 978 // A simple watch variable gesture allows only one argument. 979 if (command.GetArgumentCount() != 1) { 980 result.GetErrorStream().Printf("error: specify exactly one variable to watch for\n"); 981 result.SetStatus(eReturnStatusFailed); 982 return false; 983 } 984 985 // Things have checked out ok... 986 Error error; 987 uint32_t expr_path_options = StackFrame::eExpressionPathOptionCheckPtrVsMember; 988 valobj_sp = frame->GetValueForVariableExpressionPath (command.GetArgumentAtIndex(0), 989 eNoDynamicValues, 990 expr_path_options, 991 var_sp, 992 error); 993 if (valobj_sp) { 994 AddressType addr_type; 995 addr = valobj_sp->GetAddressOf(false, &addr_type); 996 if (addr_type == eAddressTypeLoad) { 997 // We're in business. 998 // Find out the size of this variable. 999 size = m_option_watchpoint.watch_size == 0 ? valobj_sp->GetByteSize() 1000 : m_option_watchpoint.watch_size; 1001 } 1002 } else { 1003 const char *error_cstr = error.AsCString(NULL); 1004 if (error_cstr) 1005 result.GetErrorStream().Printf("error: %s\n", error_cstr); 1006 else 1007 result.GetErrorStream().Printf ("error: unable to find any variable expression path that matches '%s'\n", 1008 command.GetArgumentAtIndex(0)); 1009 return false; 1010 } 1011 1012 // Now it's time to create the watchpoint. 1013 uint32_t watch_type = m_option_watchpoint.watch_type; 1014 Watchpoint *wp = exe_ctx.GetTargetRef().CreateWatchpoint(addr, size, watch_type).get(); 1015 if (wp) { 1016 if (var_sp && var_sp->GetDeclaration().GetFile()) { 1017 StreamString ss; 1018 // True to show fullpath for declaration file. 1019 var_sp->GetDeclaration().DumpStopContext(&ss, true); 1020 wp->SetDeclInfo(ss.GetString()); 1021 } 1022 StreamString ss; 1023 output_stream.Printf("Watchpoint created: "); 1024 wp->GetDescription(&output_stream, lldb::eDescriptionLevelFull); 1025 output_stream.EOL(); 1026 result.SetStatus(eReturnStatusSuccessFinishResult); 1027 } else { 1028 result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%llx, size=%lu).\n", 1029 addr, size); 1030 result.SetStatus(eReturnStatusFailed); 1031 } 1032 1033 return result.Succeeded(); 1034 } 1035 1036 //------------------------------------------------------------------------- 1037 // CommandObjectWatchpointSetExpression 1038 //------------------------------------------------------------------------- 1039 #pragma mark Set 1040 1041 CommandObjectWatchpointSetExpression::CommandObjectWatchpointSetExpression (CommandInterpreter &interpreter) : 1042 CommandObject (interpreter, 1043 "watchpoint set expression", 1044 "Set a watchpoint on an address by supplying an expression. " 1045 "Use the '-w' option to specify the type of watchpoint and " 1046 "the '-x' option to specify the byte size to watch for. " 1047 "If no '-w' option is specified, it defaults to read_write. " 1048 "If no '-x' option is specified, it defaults to the target's " 1049 "pointer byte size. " 1050 "Note that there are limited hardware resources for watchpoints. " 1051 "If watchpoint setting fails, consider disable/delete existing ones " 1052 "to free up resources.", 1053 NULL, 1054 eFlagProcessMustBeLaunched | eFlagProcessMustBePaused), 1055 m_option_group (interpreter), 1056 m_option_watchpoint () 1057 { 1058 SetHelpLong( 1059 "Examples: \n\ 1060 \n\ 1061 watchpoint set expression -w write -x 1 -- foo + 32\n\ 1062 # Watch write access for the 1-byte region pointed to by the address 'foo + 32'.\n"); 1063 1064 CommandArgumentEntry arg; 1065 CommandArgumentData expression_arg; 1066 1067 // Define the only variant of this arg. 1068 expression_arg.arg_type = eArgTypeExpression; 1069 expression_arg.arg_repetition = eArgRepeatPlain; 1070 1071 // Push the only variant into the argument entry. 1072 arg.push_back (expression_arg); 1073 1074 // Push the data for the only argument into the m_arguments vector. 1075 m_arguments.push_back (arg); 1076 1077 // Absorb the '-w' and '-x' options into our option group. 1078 m_option_group.Append (&m_option_watchpoint, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1); 1079 m_option_group.Finalize(); 1080 } 1081 1082 CommandObjectWatchpointSetExpression::~CommandObjectWatchpointSetExpression () 1083 { 1084 } 1085 1086 Options * 1087 CommandObjectWatchpointSetExpression::GetOptions () 1088 { 1089 return &m_option_group; 1090 } 1091 1092 #include "llvm/ADT/StringRef.h" 1093 static inline void StripLeadingSpaces(llvm::StringRef &Str) 1094 { 1095 while (!Str.empty() && isspace(Str[0])) 1096 Str = Str.substr(1); 1097 } 1098 static inline llvm::StringRef StripOptionTerminator(llvm::StringRef &Str, bool with_dash_w, bool with_dash_x) 1099 { 1100 llvm::StringRef ExprStr = Str; 1101 1102 // Get rid of the leading spaces first. 1103 StripLeadingSpaces(ExprStr); 1104 1105 // If there's no '-w' and no '-x', we can just return. 1106 if (!with_dash_w && !with_dash_x) 1107 return ExprStr; 1108 1109 // Otherwise, split on the "--" option terminator string, and return the rest of the string. 1110 ExprStr = ExprStr.split("--").second; 1111 StripLeadingSpaces(ExprStr); 1112 return ExprStr; 1113 } 1114 bool 1115 CommandObjectWatchpointSetExpression::ExecuteRawCommandString 1116 ( 1117 const char *raw_command, 1118 CommandReturnObject &result 1119 ) 1120 { 1121 Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get(); 1122 ExecutionContext exe_ctx(m_interpreter.GetExecutionContext()); 1123 StackFrame *frame = exe_ctx.GetFramePtr(); 1124 if (frame == NULL) 1125 { 1126 result.AppendError ("you must be stopped in a valid stack frame to set a watchpoint."); 1127 result.SetStatus (eReturnStatusFailed); 1128 return false; 1129 } 1130 1131 Args command(raw_command); 1132 1133 // Process possible options. 1134 if (!ParseOptions (command, result)) 1135 return false; 1136 1137 // If no argument is present, issue an error message. There's no way to set a watchpoint. 1138 if (command.GetArgumentCount() <= 0) 1139 { 1140 result.GetErrorStream().Printf("error: required argument missing; specify an expression to evaulate into the addres to watch for\n"); 1141 result.SetStatus(eReturnStatusFailed); 1142 return false; 1143 } 1144 1145 bool with_dash_w = m_option_watchpoint.watch_type_specified; 1146 bool with_dash_x = (m_option_watchpoint.watch_size != 0); 1147 1148 // If no '-w' is specified, default to '-w read_write'. 1149 if (!with_dash_w) 1150 { 1151 m_option_watchpoint.watch_type = OptionGroupWatchpoint::eWatchReadWrite; 1152 } 1153 1154 // We passed the sanity check for the command. 1155 // Proceed to set the watchpoint now. 1156 lldb::addr_t addr = 0; 1157 size_t size = 0; 1158 1159 VariableSP var_sp; 1160 ValueObjectSP valobj_sp; 1161 Stream &output_stream = result.GetOutputStream(); 1162 1163 // We will process the raw command string to rid of the '-w', '-x', or '--' 1164 llvm::StringRef raw_expr_str(raw_command); 1165 std::string expr_str = StripOptionTerminator(raw_expr_str, with_dash_w, with_dash_x).str(); 1166 1167 // Sanity check for when the user forgets to terminate the option strings with a '--'. 1168 if ((with_dash_w || with_dash_w) && expr_str.empty()) 1169 { 1170 result.GetErrorStream().Printf("error: did you forget to enter the option terminator string \"--\"?\n"); 1171 result.SetStatus(eReturnStatusFailed); 1172 return false; 1173 } 1174 1175 // Use expression evaluation to arrive at the address to watch. 1176 const bool coerce_to_id = true; 1177 const bool unwind_on_error = true; 1178 const bool keep_in_memory = false; 1179 ExecutionResults expr_result = target->EvaluateExpression (expr_str.c_str(), 1180 frame, 1181 eExecutionPolicyOnlyWhenNeeded, 1182 coerce_to_id, 1183 unwind_on_error, 1184 keep_in_memory, 1185 eNoDynamicValues, 1186 valobj_sp); 1187 if (expr_result != eExecutionCompleted) { 1188 result.GetErrorStream().Printf("error: expression evaluation of address to watch failed\n"); 1189 result.GetErrorStream().Printf("expression evaluated: %s\n", expr_str.c_str()); 1190 result.SetStatus(eReturnStatusFailed); 1191 return false; 1192 } 1193 1194 // Get the address to watch. 1195 addr = valobj_sp->GetValueAsUnsigned(0); 1196 if (!addr) { 1197 result.GetErrorStream().Printf("error: expression did not evaluate to an address\n"); 1198 result.SetStatus(eReturnStatusFailed); 1199 return false; 1200 } 1201 size = with_dash_x ? m_option_watchpoint.watch_size 1202 : target->GetArchitecture().GetAddressByteSize(); 1203 1204 // Now it's time to create the watchpoint. 1205 uint32_t watch_type = m_option_watchpoint.watch_type; 1206 Watchpoint *wp = exe_ctx.GetTargetRef().CreateWatchpoint(addr, size, watch_type).get(); 1207 if (wp) { 1208 if (var_sp && var_sp->GetDeclaration().GetFile()) { 1209 StreamString ss; 1210 // True to show fullpath for declaration file. 1211 var_sp->GetDeclaration().DumpStopContext(&ss, true); 1212 wp->SetDeclInfo(ss.GetString()); 1213 } 1214 StreamString ss; 1215 output_stream.Printf("Watchpoint created: "); 1216 wp->GetDescription(&output_stream, lldb::eDescriptionLevelFull); 1217 output_stream.EOL(); 1218 result.SetStatus(eReturnStatusSuccessFinishResult); 1219 } else { 1220 result.AppendErrorWithFormat("Watchpoint creation failed (addr=0x%llx, size=%lu).\n", 1221 addr, size); 1222 result.SetStatus(eReturnStatusFailed); 1223 } 1224 1225 return result.Succeeded(); 1226 } 1227