1 //===-- CommandObjectBreakpoint.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 // C Includes 11 // C++ Includes 12 #include <vector> 13 14 // Other libraries and framework includes 15 // Project includes 16 #include "CommandObjectBreakpoint.h" 17 #include "CommandObjectBreakpointCommand.h" 18 #include "lldb/Breakpoint/Breakpoint.h" 19 #include "lldb/Breakpoint/BreakpointIDList.h" 20 #include "lldb/Breakpoint/BreakpointLocation.h" 21 #include "lldb/Host/StringConvert.h" 22 #include "lldb/Interpreter/Options.h" 23 #include "lldb/Interpreter/OptionValueBoolean.h" 24 #include "lldb/Interpreter/OptionValueString.h" 25 #include "lldb/Interpreter/OptionValueUInt64.h" 26 #include "lldb/Core/RegularExpression.h" 27 #include "lldb/Core/StreamString.h" 28 #include "lldb/Interpreter/CommandInterpreter.h" 29 #include "lldb/Interpreter/CommandReturnObject.h" 30 #include "lldb/Target/Language.h" 31 #include "lldb/Target/Target.h" 32 #include "lldb/Interpreter/CommandCompletions.h" 33 #include "lldb/Target/StackFrame.h" 34 #include "lldb/Target/Thread.h" 35 #include "lldb/Target/ThreadSpec.h" 36 37 using namespace lldb; 38 using namespace lldb_private; 39 40 static void 41 AddBreakpointDescription (Stream *s, Breakpoint *bp, lldb::DescriptionLevel level) 42 { 43 s->IndentMore(); 44 bp->GetDescription (s, level, true); 45 s->IndentLess(); 46 s->EOL(); 47 } 48 49 //------------------------------------------------------------------------- 50 // CommandObjectBreakpointSet 51 //------------------------------------------------------------------------- 52 53 class CommandObjectBreakpointSet : public CommandObjectParsed 54 { 55 public: 56 typedef enum BreakpointSetType 57 { 58 eSetTypeInvalid, 59 eSetTypeFileAndLine, 60 eSetTypeAddress, 61 eSetTypeFunctionName, 62 eSetTypeFunctionRegexp, 63 eSetTypeSourceRegexp, 64 eSetTypeException 65 } BreakpointSetType; 66 67 CommandObjectBreakpointSet (CommandInterpreter &interpreter) : 68 CommandObjectParsed (interpreter, 69 "breakpoint set", 70 "Sets a breakpoint or set of breakpoints in the executable.", 71 "breakpoint set <cmd-options>"), 72 m_options () 73 { 74 } 75 76 ~CommandObjectBreakpointSet() override = default; 77 78 Options * 79 GetOptions () override 80 { 81 return &m_options; 82 } 83 84 class CommandOptions : public Options 85 { 86 public: 87 CommandOptions () : 88 Options (), 89 m_condition (), 90 m_filenames (), 91 m_line_num (0), 92 m_column (0), 93 m_func_names (), 94 m_func_name_type_mask (eFunctionNameTypeNone), 95 m_func_regexp (), 96 m_source_text_regexp(), 97 m_modules (), 98 m_load_addr(), 99 m_ignore_count (0), 100 m_thread_id(LLDB_INVALID_THREAD_ID), 101 m_thread_index (UINT32_MAX), 102 m_thread_name(), 103 m_queue_name(), 104 m_catch_bp (false), 105 m_throw_bp (true), 106 m_hardware (false), 107 m_exception_language (eLanguageTypeUnknown), 108 m_language (lldb::eLanguageTypeUnknown), 109 m_skip_prologue (eLazyBoolCalculate), 110 m_one_shot (false), 111 m_all_files (false), 112 m_move_to_nearest_code (eLazyBoolCalculate) 113 { 114 } 115 116 ~CommandOptions() override = default; 117 118 Error 119 SetOptionValue (uint32_t option_idx, const char *option_arg, 120 ExecutionContext *execution_context) override 121 { 122 Error error; 123 const int short_option = m_getopt_table[option_idx].val; 124 125 switch (short_option) 126 { 127 case 'a': 128 { 129 m_load_addr = 130 Args::StringToAddress(execution_context, option_arg, 131 LLDB_INVALID_ADDRESS, &error); 132 } 133 break; 134 135 case 'A': 136 m_all_files = true; 137 break; 138 139 case 'b': 140 m_func_names.push_back (option_arg); 141 m_func_name_type_mask |= eFunctionNameTypeBase; 142 break; 143 144 case 'C': 145 { 146 bool success; 147 m_column = StringConvert::ToUInt32 (option_arg, 0, 0, &success); 148 if (!success) 149 error.SetErrorStringWithFormat("invalid column number: %s", option_arg); 150 break; 151 } 152 153 case 'c': 154 m_condition.assign(option_arg); 155 break; 156 157 case 'D': 158 m_use_dummy = true; 159 break; 160 161 case 'E': 162 { 163 LanguageType language = Language::GetLanguageTypeFromString (option_arg); 164 165 switch (language) 166 { 167 case eLanguageTypeC89: 168 case eLanguageTypeC: 169 case eLanguageTypeC99: 170 case eLanguageTypeC11: 171 m_exception_language = eLanguageTypeC; 172 break; 173 case eLanguageTypeC_plus_plus: 174 case eLanguageTypeC_plus_plus_03: 175 case eLanguageTypeC_plus_plus_11: 176 case eLanguageTypeC_plus_plus_14: 177 m_exception_language = eLanguageTypeC_plus_plus; 178 break; 179 case eLanguageTypeObjC: 180 m_exception_language = eLanguageTypeObjC; 181 break; 182 case eLanguageTypeObjC_plus_plus: 183 error.SetErrorStringWithFormat ("Set exception breakpoints separately for c++ and objective-c"); 184 break; 185 case eLanguageTypeUnknown: 186 error.SetErrorStringWithFormat ("Unknown language type: '%s' for exception breakpoint", option_arg); 187 break; 188 default: 189 error.SetErrorStringWithFormat ("Unsupported language type: '%s' for exception breakpoint", option_arg); 190 } 191 } 192 break; 193 194 case 'f': 195 m_filenames.AppendIfUnique (FileSpec(option_arg, false)); 196 break; 197 198 case 'F': 199 m_func_names.push_back (option_arg); 200 m_func_name_type_mask |= eFunctionNameTypeFull; 201 break; 202 203 case 'h': 204 { 205 bool success; 206 m_catch_bp = Args::StringToBoolean (option_arg, true, &success); 207 if (!success) 208 error.SetErrorStringWithFormat ("Invalid boolean value for on-catch option: '%s'", option_arg); 209 } 210 break; 211 212 case 'H': 213 m_hardware = true; 214 break; 215 216 case 'i': 217 m_ignore_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); 218 if (m_ignore_count == UINT32_MAX) 219 error.SetErrorStringWithFormat ("invalid ignore count '%s'", option_arg); 220 break; 221 222 case 'K': 223 { 224 bool success; 225 bool value; 226 value = Args::StringToBoolean (option_arg, true, &success); 227 if (value) 228 m_skip_prologue = eLazyBoolYes; 229 else 230 m_skip_prologue = eLazyBoolNo; 231 232 if (!success) 233 error.SetErrorStringWithFormat ("Invalid boolean value for skip prologue option: '%s'", option_arg); 234 } 235 break; 236 237 case 'l': 238 { 239 bool success; 240 m_line_num = StringConvert::ToUInt32 (option_arg, 0, 0, &success); 241 if (!success) 242 error.SetErrorStringWithFormat ("invalid line number: %s.", option_arg); 243 break; 244 } 245 246 case 'L': 247 m_language = Language::GetLanguageTypeFromString (option_arg); 248 if (m_language == eLanguageTypeUnknown) 249 error.SetErrorStringWithFormat ("Unknown language type: '%s' for breakpoint", option_arg); 250 break; 251 252 case 'm': 253 { 254 bool success; 255 bool value; 256 value = Args::StringToBoolean (option_arg, true, &success); 257 if (value) 258 m_move_to_nearest_code = eLazyBoolYes; 259 else 260 m_move_to_nearest_code = eLazyBoolNo; 261 262 if (!success) 263 error.SetErrorStringWithFormat ("Invalid boolean value for move-to-nearest-code option: '%s'", option_arg); 264 break; 265 } 266 267 case 'M': 268 m_func_names.push_back (option_arg); 269 m_func_name_type_mask |= eFunctionNameTypeMethod; 270 break; 271 272 case 'n': 273 m_func_names.push_back (option_arg); 274 m_func_name_type_mask |= eFunctionNameTypeAuto; 275 break; 276 277 case 'N': 278 if (BreakpointID::StringIsBreakpointName(option_arg, error)) 279 m_breakpoint_names.push_back (option_arg); 280 break; 281 282 case 'R': 283 { 284 lldb::addr_t tmp_offset_addr; 285 tmp_offset_addr = 286 Args::StringToAddress(execution_context, option_arg, 287 0, &error); 288 if (error.Success()) 289 m_offset_addr = tmp_offset_addr; 290 } 291 break; 292 293 case 'o': 294 m_one_shot = true; 295 break; 296 297 case 'O': 298 m_exception_extra_args.AppendArgument ("-O"); 299 m_exception_extra_args.AppendArgument (option_arg); 300 break; 301 302 case 'p': 303 m_source_text_regexp.assign (option_arg); 304 break; 305 306 case 'q': 307 m_queue_name.assign (option_arg); 308 break; 309 310 case 'r': 311 m_func_regexp.assign (option_arg); 312 break; 313 314 case 's': 315 m_modules.AppendIfUnique (FileSpec (option_arg, false)); 316 break; 317 318 case 'S': 319 m_func_names.push_back (option_arg); 320 m_func_name_type_mask |= eFunctionNameTypeSelector; 321 break; 322 323 case 't' : 324 m_thread_id = StringConvert::ToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0); 325 if (m_thread_id == LLDB_INVALID_THREAD_ID) 326 error.SetErrorStringWithFormat ("invalid thread id string '%s'", option_arg); 327 break; 328 329 case 'T': 330 m_thread_name.assign (option_arg); 331 break; 332 333 case 'w': 334 { 335 bool success; 336 m_throw_bp = Args::StringToBoolean (option_arg, true, &success); 337 if (!success) 338 error.SetErrorStringWithFormat ("Invalid boolean value for on-throw option: '%s'", option_arg); 339 } 340 break; 341 342 case 'x': 343 m_thread_index = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); 344 if (m_thread_id == UINT32_MAX) 345 error.SetErrorStringWithFormat ("invalid thread index string '%s'", option_arg); 346 break; 347 348 case 'X': 349 m_source_regex_func_names.insert(option_arg); 350 break; 351 352 default: 353 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 354 break; 355 } 356 357 return error; 358 } 359 360 void 361 OptionParsingStarting (ExecutionContext *execution_context) override 362 { 363 m_condition.clear(); 364 m_filenames.Clear(); 365 m_line_num = 0; 366 m_column = 0; 367 m_func_names.clear(); 368 m_func_name_type_mask = eFunctionNameTypeNone; 369 m_func_regexp.clear(); 370 m_source_text_regexp.clear(); 371 m_modules.Clear(); 372 m_load_addr = LLDB_INVALID_ADDRESS; 373 m_offset_addr = 0; 374 m_ignore_count = 0; 375 m_thread_id = LLDB_INVALID_THREAD_ID; 376 m_thread_index = UINT32_MAX; 377 m_thread_name.clear(); 378 m_queue_name.clear(); 379 m_catch_bp = false; 380 m_throw_bp = true; 381 m_hardware = false; 382 m_exception_language = eLanguageTypeUnknown; 383 m_language = lldb::eLanguageTypeUnknown; 384 m_skip_prologue = eLazyBoolCalculate; 385 m_one_shot = false; 386 m_use_dummy = false; 387 m_breakpoint_names.clear(); 388 m_all_files = false; 389 m_exception_extra_args.Clear(); 390 m_move_to_nearest_code = eLazyBoolCalculate; 391 m_source_regex_func_names.clear(); 392 } 393 394 const OptionDefinition* 395 GetDefinitions () override 396 { 397 return g_option_table; 398 } 399 400 // Options table: Required for subclasses of Options. 401 402 static OptionDefinition g_option_table[]; 403 404 // Instance variables to hold the values for command options. 405 406 std::string m_condition; 407 FileSpecList m_filenames; 408 uint32_t m_line_num; 409 uint32_t m_column; 410 std::vector<std::string> m_func_names; 411 std::vector<std::string> m_breakpoint_names; 412 uint32_t m_func_name_type_mask; 413 std::string m_func_regexp; 414 std::string m_source_text_regexp; 415 FileSpecList m_modules; 416 lldb::addr_t m_load_addr; 417 lldb::addr_t m_offset_addr; 418 uint32_t m_ignore_count; 419 lldb::tid_t m_thread_id; 420 uint32_t m_thread_index; 421 std::string m_thread_name; 422 std::string m_queue_name; 423 bool m_catch_bp; 424 bool m_throw_bp; 425 bool m_hardware; // Request to use hardware breakpoints 426 lldb::LanguageType m_exception_language; 427 lldb::LanguageType m_language; 428 LazyBool m_skip_prologue; 429 bool m_one_shot; 430 bool m_use_dummy; 431 bool m_all_files; 432 Args m_exception_extra_args; 433 LazyBool m_move_to_nearest_code; 434 std::unordered_set<std::string> m_source_regex_func_names; 435 }; 436 437 protected: 438 bool 439 DoExecute (Args& command, 440 CommandReturnObject &result) override 441 { 442 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 443 444 if (target == nullptr) 445 { 446 result.AppendError ("Invalid target. Must set target before setting breakpoints (see 'target create' command)."); 447 result.SetStatus (eReturnStatusFailed); 448 return false; 449 } 450 451 // The following are the various types of breakpoints that could be set: 452 // 1). -f -l -p [-s -g] (setting breakpoint by source location) 453 // 2). -a [-s -g] (setting breakpoint by address) 454 // 3). -n [-s -g] (setting breakpoint by function name) 455 // 4). -r [-s -g] (setting breakpoint by function name regular expression) 456 // 5). -p -f (setting a breakpoint by comparing a reg-exp to source text) 457 // 6). -E [-w -h] (setting a breakpoint for exceptions for a given language.) 458 459 BreakpointSetType break_type = eSetTypeInvalid; 460 461 if (m_options.m_line_num != 0) 462 break_type = eSetTypeFileAndLine; 463 else if (m_options.m_load_addr != LLDB_INVALID_ADDRESS) 464 break_type = eSetTypeAddress; 465 else if (!m_options.m_func_names.empty()) 466 break_type = eSetTypeFunctionName; 467 else if (!m_options.m_func_regexp.empty()) 468 break_type = eSetTypeFunctionRegexp; 469 else if (!m_options.m_source_text_regexp.empty()) 470 break_type = eSetTypeSourceRegexp; 471 else if (m_options.m_exception_language != eLanguageTypeUnknown) 472 break_type = eSetTypeException; 473 474 Breakpoint *bp = nullptr; 475 FileSpec module_spec; 476 const bool internal = false; 477 478 // If the user didn't specify skip-prologue, having an offset should turn that off. 479 if (m_options.m_offset_addr != 0 && m_options.m_skip_prologue == eLazyBoolCalculate) 480 m_options.m_skip_prologue = eLazyBoolNo; 481 482 switch (break_type) 483 { 484 case eSetTypeFileAndLine: // Breakpoint by source position 485 { 486 FileSpec file; 487 const size_t num_files = m_options.m_filenames.GetSize(); 488 if (num_files == 0) 489 { 490 if (!GetDefaultFile (target, file, result)) 491 { 492 result.AppendError("No file supplied and no default file available."); 493 result.SetStatus (eReturnStatusFailed); 494 return false; 495 } 496 } 497 else if (num_files > 1) 498 { 499 result.AppendError("Only one file at a time is allowed for file and line breakpoints."); 500 result.SetStatus (eReturnStatusFailed); 501 return false; 502 } 503 else 504 file = m_options.m_filenames.GetFileSpecAtIndex(0); 505 506 // Only check for inline functions if 507 LazyBool check_inlines = eLazyBoolCalculate; 508 509 bp = target->CreateBreakpoint (&(m_options.m_modules), 510 file, 511 m_options.m_line_num, 512 m_options.m_offset_addr, 513 check_inlines, 514 m_options.m_skip_prologue, 515 internal, 516 m_options.m_hardware, 517 m_options.m_move_to_nearest_code).get(); 518 } 519 break; 520 521 case eSetTypeAddress: // Breakpoint by address 522 { 523 // If a shared library has been specified, make an lldb_private::Address with the library, and 524 // use that. That way the address breakpoint will track the load location of the library. 525 size_t num_modules_specified = m_options.m_modules.GetSize(); 526 if (num_modules_specified == 1) 527 { 528 const FileSpec *file_spec = m_options.m_modules.GetFileSpecPointerAtIndex(0); 529 bp = target->CreateAddressInModuleBreakpoint (m_options.m_load_addr, 530 internal, 531 file_spec, 532 m_options.m_hardware).get(); 533 } 534 else if (num_modules_specified == 0) 535 { 536 bp = target->CreateBreakpoint (m_options.m_load_addr, 537 internal, 538 m_options.m_hardware).get(); 539 } 540 else 541 { 542 result.AppendError("Only one shared library can be specified for address breakpoints."); 543 result.SetStatus(eReturnStatusFailed); 544 return false; 545 } 546 break; 547 } 548 case eSetTypeFunctionName: // Breakpoint by function name 549 { 550 uint32_t name_type_mask = m_options.m_func_name_type_mask; 551 552 if (name_type_mask == 0) 553 name_type_mask = eFunctionNameTypeAuto; 554 555 bp = target->CreateBreakpoint (&(m_options.m_modules), 556 &(m_options.m_filenames), 557 m_options.m_func_names, 558 name_type_mask, 559 m_options.m_language, 560 m_options.m_offset_addr, 561 m_options.m_skip_prologue, 562 internal, 563 m_options.m_hardware).get(); 564 } 565 break; 566 567 case eSetTypeFunctionRegexp: // Breakpoint by regular expression function name 568 { 569 RegularExpression regexp(m_options.m_func_regexp.c_str()); 570 if (!regexp.IsValid()) 571 { 572 char err_str[1024]; 573 regexp.GetErrorAsCString(err_str, sizeof(err_str)); 574 result.AppendErrorWithFormat("Function name regular expression could not be compiled: \"%s\"", 575 err_str); 576 result.SetStatus (eReturnStatusFailed); 577 return false; 578 } 579 580 bp = target->CreateFuncRegexBreakpoint (&(m_options.m_modules), 581 &(m_options.m_filenames), 582 regexp, 583 m_options.m_language, 584 m_options.m_skip_prologue, 585 internal, 586 m_options.m_hardware).get(); 587 } 588 break; 589 case eSetTypeSourceRegexp: // Breakpoint by regexp on source text. 590 { 591 const size_t num_files = m_options.m_filenames.GetSize(); 592 593 if (num_files == 0 && !m_options.m_all_files) 594 { 595 FileSpec file; 596 if (!GetDefaultFile (target, file, result)) 597 { 598 result.AppendError ("No files provided and could not find default file."); 599 result.SetStatus (eReturnStatusFailed); 600 return false; 601 } 602 else 603 { 604 m_options.m_filenames.Append (file); 605 } 606 } 607 608 RegularExpression regexp(m_options.m_source_text_regexp.c_str()); 609 if (!regexp.IsValid()) 610 { 611 char err_str[1024]; 612 regexp.GetErrorAsCString(err_str, sizeof(err_str)); 613 result.AppendErrorWithFormat("Source text regular expression could not be compiled: \"%s\"", 614 err_str); 615 result.SetStatus (eReturnStatusFailed); 616 return false; 617 } 618 bp = target->CreateSourceRegexBreakpoint (&(m_options.m_modules), 619 &(m_options.m_filenames), 620 m_options.m_source_regex_func_names, 621 regexp, 622 internal, 623 m_options.m_hardware, 624 m_options.m_move_to_nearest_code).get(); 625 } 626 break; 627 case eSetTypeException: 628 { 629 Error precond_error; 630 bp = target->CreateExceptionBreakpoint (m_options.m_exception_language, 631 m_options.m_catch_bp, 632 m_options.m_throw_bp, 633 internal, 634 &m_options.m_exception_extra_args, 635 &precond_error).get(); 636 if (precond_error.Fail()) 637 { 638 result.AppendErrorWithFormat("Error setting extra exception arguments: %s", 639 precond_error.AsCString()); 640 target->RemoveBreakpointByID(bp->GetID()); 641 result.SetStatus(eReturnStatusFailed); 642 return false; 643 } 644 } 645 break; 646 default: 647 break; 648 } 649 650 // Now set the various options that were passed in: 651 if (bp) 652 { 653 if (m_options.m_thread_id != LLDB_INVALID_THREAD_ID) 654 bp->SetThreadID (m_options.m_thread_id); 655 656 if (m_options.m_thread_index != UINT32_MAX) 657 bp->GetOptions()->GetThreadSpec()->SetIndex(m_options.m_thread_index); 658 659 if (!m_options.m_thread_name.empty()) 660 bp->GetOptions()->GetThreadSpec()->SetName(m_options.m_thread_name.c_str()); 661 662 if (!m_options.m_queue_name.empty()) 663 bp->GetOptions()->GetThreadSpec()->SetQueueName(m_options.m_queue_name.c_str()); 664 665 if (m_options.m_ignore_count != 0) 666 bp->GetOptions()->SetIgnoreCount(m_options.m_ignore_count); 667 668 if (!m_options.m_condition.empty()) 669 bp->GetOptions()->SetCondition(m_options.m_condition.c_str()); 670 671 if (!m_options.m_breakpoint_names.empty()) 672 { 673 Error error; // We don't need to check the error here, since the option parser checked it... 674 for (auto name : m_options.m_breakpoint_names) 675 bp->AddName(name.c_str(), error); 676 } 677 678 bp->SetOneShot (m_options.m_one_shot); 679 } 680 681 if (bp) 682 { 683 Stream &output_stream = result.GetOutputStream(); 684 const bool show_locations = false; 685 bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, show_locations); 686 if (target == m_interpreter.GetDebugger().GetDummyTarget()) 687 output_stream.Printf ("Breakpoint set in dummy target, will get copied into future targets.\n"); 688 else 689 { 690 // Don't print out this warning for exception breakpoints. They can get set before the target 691 // is set, but we won't know how to actually set the breakpoint till we run. 692 if (bp->GetNumLocations() == 0 && break_type != eSetTypeException) 693 { 694 output_stream.Printf ("WARNING: Unable to resolve breakpoint to any actual locations.\n"); 695 } 696 } 697 result.SetStatus (eReturnStatusSuccessFinishResult); 698 } 699 else if (!bp) 700 { 701 result.AppendError ("Breakpoint creation failed: No breakpoint created."); 702 result.SetStatus (eReturnStatusFailed); 703 } 704 705 return result.Succeeded(); 706 } 707 708 private: 709 bool 710 GetDefaultFile (Target *target, FileSpec &file, CommandReturnObject &result) 711 { 712 uint32_t default_line; 713 // First use the Source Manager's default file. 714 // Then use the current stack frame's file. 715 if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line)) 716 { 717 StackFrame *cur_frame = m_exe_ctx.GetFramePtr(); 718 if (cur_frame == nullptr) 719 { 720 result.AppendError ("No selected frame to use to find the default file."); 721 result.SetStatus (eReturnStatusFailed); 722 return false; 723 } 724 else if (!cur_frame->HasDebugInformation()) 725 { 726 result.AppendError ("Cannot use the selected frame to find the default file, it has no debug info."); 727 result.SetStatus (eReturnStatusFailed); 728 return false; 729 } 730 else 731 { 732 const SymbolContext &sc = cur_frame->GetSymbolContext (eSymbolContextLineEntry); 733 if (sc.line_entry.file) 734 { 735 file = sc.line_entry.file; 736 } 737 else 738 { 739 result.AppendError ("Can't find the file for the selected frame to use as the default file."); 740 result.SetStatus (eReturnStatusFailed); 741 return false; 742 } 743 } 744 } 745 return true; 746 } 747 748 CommandOptions m_options; 749 }; 750 751 // If an additional option set beyond LLDB_OPTION_SET_10 is added, make sure to 752 // update the numbers passed to LLDB_OPT_SET_FROM_TO(...) appropriately. 753 #define LLDB_OPT_FILE ( LLDB_OPT_SET_FROM_TO(1, 9) & ~LLDB_OPT_SET_2 ) 754 #define LLDB_OPT_NOT_10 ( LLDB_OPT_SET_FROM_TO(1, 10) & ~LLDB_OPT_SET_10 ) 755 #define LLDB_OPT_SKIP_PROLOGUE ( LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3,8) ) 756 #define LLDB_OPT_OFFSET_APPLIES (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3,8) ) 757 #define LLDB_OPT_MOVE_TO_NEAREST_CODE ( LLDB_OPT_SET_1 | LLDB_OPT_SET_9 ) 758 #define LLDB_OPT_EXPR_LANGUAGE ( LLDB_OPT_SET_FROM_TO(3, 8) ) 759 760 OptionDefinition 761 CommandObjectBreakpointSet::CommandOptions::g_option_table[] = 762 { 763 { LLDB_OPT_NOT_10, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eModuleCompletion, eArgTypeShlibName, 764 "Set the breakpoint only in this shared library. " 765 "Can repeat this option multiple times to specify multiple shared libraries."}, 766 767 { LLDB_OPT_SET_ALL, false, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, 768 "Set the number of times this breakpoint is skipped before stopping." }, 769 770 { LLDB_OPT_SET_ALL, false, "one-shot", 'o', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, 771 "The breakpoint is deleted the first time it causes a stop." }, 772 773 { LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression, 774 "The breakpoint stops only if this condition expression evaluates to true."}, 775 776 { LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadIndex, 777 "The breakpoint stops only for the thread whose indeX matches this argument."}, 778 779 { LLDB_OPT_SET_ALL, false, "thread-id", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadID, 780 "The breakpoint stops only for the thread whose TID matches this argument."}, 781 782 { LLDB_OPT_SET_ALL, false, "thread-name", 'T', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadName, 783 "The breakpoint stops only for the thread whose thread name matches this argument."}, 784 785 { LLDB_OPT_SET_ALL, false, "hardware", 'H', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, 786 "Require the breakpoint to use hardware breakpoints."}, 787 788 { LLDB_OPT_SET_ALL, false, "queue-name", 'q', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeQueueName, 789 "The breakpoint stops only for threads in the queue whose name is given by this argument."}, 790 791 { LLDB_OPT_FILE, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, 792 "Specifies the source file in which to set this breakpoint. " 793 "Note, by default lldb only looks for files that are #included if they use the standard include file extensions. " 794 "To set breakpoints on .c/.cpp/.m/.mm files that are #included, set target.inline-breakpoint-strategy" 795 " to \"always\"."}, 796 797 { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, 798 "Specifies the line number on which to set this breakpoint."}, 799 800 // Comment out this option for the moment, as we don't actually use it, but will in the future. 801 // This way users won't see it, but the infrastructure is left in place. 802 // { 0, false, "column", 'C', OptionParser::eRequiredArgument, nullptr, "<column>", 803 // "Set the breakpoint by source location at this particular column."}, 804 805 { LLDB_OPT_SET_2, true, "address", 'a', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddressOrExpression, 806 "Set the breakpoint at the specified address. " 807 "If the address maps uniquely to a particular " 808 "binary, then the address will be converted to a \"file\" address, so that the breakpoint will track that binary+offset no matter where " 809 "the binary eventually loads. " 810 "Alternately, if you also specify the module - with the -s option - then the address will be treated as " 811 "a file address in that module, and resolved accordingly. Again, this will allow lldb to track that offset on " 812 "subsequent reloads. The module need not have been loaded at the time you specify this breakpoint, and will " 813 "get resolved when the module is loaded."}, 814 815 { LLDB_OPT_SET_3, true, "name", 'n', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, 816 "Set the breakpoint by function name. Can be repeated multiple times to make one breakpoint for multiple names" }, 817 818 { LLDB_OPT_SET_9, false, "source-regexp-function", 'X', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, 819 "When used with '-p' limits the source regex to source contained in the named functions. Can be repeated multiple times." }, 820 821 { LLDB_OPT_SET_4, true, "fullname", 'F', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFullName, 822 "Set the breakpoint by fully qualified function names. For C++ this means namespaces and all arguments, and " 823 "for Objective C this means a full function prototype with class and selector. " 824 "Can be repeated multiple times to make one breakpoint for multiple names." }, 825 826 { LLDB_OPT_SET_5, true, "selector", 'S', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeSelector, 827 "Set the breakpoint by ObjC selector name. Can be repeated multiple times to make one breakpoint for multiple Selectors." }, 828 829 { LLDB_OPT_SET_6, true, "method", 'M', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeMethod, 830 "Set the breakpoint by C++ method names. Can be repeated multiple times to make one breakpoint for multiple methods." }, 831 832 { LLDB_OPT_SET_7, true, "func-regex", 'r', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeRegularExpression, 833 "Set the breakpoint by function name, evaluating a regular-expression to find the function name(s)." }, 834 835 { LLDB_OPT_SET_8, true, "basename", 'b', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, 836 "Set the breakpoint by function basename (C++ namespaces and arguments will be ignored). " 837 "Can be repeated multiple times to make one breakpoint for multiple symbols." }, 838 839 { LLDB_OPT_SET_9, true, "source-pattern-regexp", 'p', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeRegularExpression, 840 "Set the breakpoint by specifying a regular expression which is matched against the source text in a source file or files " 841 "specified with the -f option. The -f option can be specified more than once. " 842 "If no source files are specified, uses the current \"default source file\". " 843 "If you want to match against all source files, pass the \"--all-files\" option." }, 844 845 { LLDB_OPT_SET_9, false, "all-files", 'A', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, 846 "All files are searched for source pattern matches." }, 847 848 { LLDB_OPT_SET_10, true, "language-exception", 'E', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, 849 "Set the breakpoint on exceptions thrown by the specified language (without options, on throw but not catch.)" }, 850 851 { LLDB_OPT_SET_10, false, "on-throw", 'w', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, 852 "Set the breakpoint on exception throW." }, 853 854 { LLDB_OPT_SET_10, false, "on-catch", 'h', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, 855 "Set the breakpoint on exception catcH." }, 856 857 // Don't add this option till it actually does something useful... 858 // { LLDB_OPT_SET_10, false, "exception-typename", 'O', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeTypeName, 859 // "The breakpoint will only stop if an exception Object of this type is thrown. Can be repeated multiple times to stop for multiple object types" }, 860 861 { LLDB_OPT_EXPR_LANGUAGE, false, "language", 'L', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage, 862 "Specifies the Language to use when interpreting the breakpoint's expression (note: currently only implemented for setting breakpoints on identifiers). If not set the target.language setting is used." }, 863 864 { LLDB_OPT_SKIP_PROLOGUE, false, "skip-prologue", 'K', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, 865 "sKip the prologue if the breakpoint is at the beginning of a function. If not set the target.skip-prologue setting is used." }, 866 867 { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, 868 "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, 869 870 { LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, 871 "Adds this to the list of names for this breakpoint."}, 872 873 { LLDB_OPT_OFFSET_APPLIES, false, "address-slide", 'R', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeAddress, 874 "Add the specified offset to whatever address(es) the breakpoint resolves to. " 875 "At present this applies the offset directly as given, and doesn't try to align it to instruction boundaries."}, 876 877 { LLDB_OPT_MOVE_TO_NEAREST_CODE, false, "move-to-nearest-code", 'm', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, 878 "Move breakpoints to nearest code. If not set the target.move-to-nearest-code setting is used." }, 879 880 { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 881 }; 882 883 //------------------------------------------------------------------------- 884 // CommandObjectBreakpointModify 885 //------------------------------------------------------------------------- 886 #pragma mark Modify 887 888 class CommandObjectBreakpointModify : public CommandObjectParsed 889 { 890 public: 891 CommandObjectBreakpointModify (CommandInterpreter &interpreter) : 892 CommandObjectParsed(interpreter, 893 "breakpoint modify", 894 "Modify the options on a breakpoint or set of breakpoints in the executable. " 895 "If no breakpoint is specified, acts on the last created breakpoint. " 896 "With the exception of -e, -d and -i, passing an empty argument clears the modification.", 897 nullptr), 898 m_options () 899 { 900 CommandArgumentEntry arg; 901 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, eArgTypeBreakpointIDRange); 902 // Add the entry for the first argument for this command to the object's arguments vector. 903 m_arguments.push_back (arg); 904 } 905 906 ~CommandObjectBreakpointModify() override = default; 907 908 Options * 909 GetOptions () override 910 { 911 return &m_options; 912 } 913 914 class CommandOptions : public Options 915 { 916 public: 917 CommandOptions () : 918 Options (), 919 m_ignore_count (0), 920 m_thread_id(LLDB_INVALID_THREAD_ID), 921 m_thread_id_passed(false), 922 m_thread_index (UINT32_MAX), 923 m_thread_index_passed(false), 924 m_thread_name(), 925 m_queue_name(), 926 m_condition (), 927 m_one_shot (false), 928 m_enable_passed (false), 929 m_enable_value (false), 930 m_name_passed (false), 931 m_queue_passed (false), 932 m_condition_passed (false), 933 m_one_shot_passed (false), 934 m_use_dummy (false) 935 { 936 } 937 938 ~CommandOptions() override = default; 939 940 Error 941 SetOptionValue (uint32_t option_idx, const char *option_arg, 942 ExecutionContext *execution_context) override 943 { 944 Error error; 945 const int short_option = m_getopt_table[option_idx].val; 946 947 switch (short_option) 948 { 949 case 'c': 950 if (option_arg != nullptr) 951 m_condition.assign (option_arg); 952 else 953 m_condition.clear(); 954 m_condition_passed = true; 955 break; 956 case 'd': 957 m_enable_passed = true; 958 m_enable_value = false; 959 break; 960 case 'D': 961 m_use_dummy = true; 962 break; 963 case 'e': 964 m_enable_passed = true; 965 m_enable_value = true; 966 break; 967 case 'i': 968 m_ignore_count = StringConvert::ToUInt32(option_arg, UINT32_MAX, 0); 969 if (m_ignore_count == UINT32_MAX) 970 error.SetErrorStringWithFormat ("invalid ignore count '%s'", option_arg); 971 break; 972 case 'o': 973 { 974 bool value, success; 975 value = Args::StringToBoolean(option_arg, false, &success); 976 if (success) 977 { 978 m_one_shot_passed = true; 979 m_one_shot = value; 980 } 981 else 982 error.SetErrorStringWithFormat("invalid boolean value '%s' passed for -o option", option_arg); 983 } 984 break; 985 case 't' : 986 if (option_arg[0] == '\0') 987 { 988 m_thread_id = LLDB_INVALID_THREAD_ID; 989 m_thread_id_passed = true; 990 } 991 else 992 { 993 m_thread_id = StringConvert::ToUInt64(option_arg, LLDB_INVALID_THREAD_ID, 0); 994 if (m_thread_id == LLDB_INVALID_THREAD_ID) 995 error.SetErrorStringWithFormat ("invalid thread id string '%s'", option_arg); 996 else 997 m_thread_id_passed = true; 998 } 999 break; 1000 case 'T': 1001 if (option_arg != nullptr) 1002 m_thread_name.assign (option_arg); 1003 else 1004 m_thread_name.clear(); 1005 m_name_passed = true; 1006 break; 1007 case 'q': 1008 if (option_arg != nullptr) 1009 m_queue_name.assign (option_arg); 1010 else 1011 m_queue_name.clear(); 1012 m_queue_passed = true; 1013 break; 1014 case 'x': 1015 if (option_arg[0] == '\n') 1016 { 1017 m_thread_index = UINT32_MAX; 1018 m_thread_index_passed = true; 1019 } 1020 else 1021 { 1022 m_thread_index = StringConvert::ToUInt32 (option_arg, UINT32_MAX, 0); 1023 if (m_thread_id == UINT32_MAX) 1024 error.SetErrorStringWithFormat ("invalid thread index string '%s'", option_arg); 1025 else 1026 m_thread_index_passed = true; 1027 } 1028 break; 1029 default: 1030 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 1031 break; 1032 } 1033 1034 return error; 1035 } 1036 1037 void 1038 OptionParsingStarting (ExecutionContext *execution_context) override 1039 { 1040 m_ignore_count = 0; 1041 m_thread_id = LLDB_INVALID_THREAD_ID; 1042 m_thread_id_passed = false; 1043 m_thread_index = UINT32_MAX; 1044 m_thread_index_passed = false; 1045 m_thread_name.clear(); 1046 m_queue_name.clear(); 1047 m_condition.clear(); 1048 m_one_shot = false; 1049 m_enable_passed = false; 1050 m_queue_passed = false; 1051 m_name_passed = false; 1052 m_condition_passed = false; 1053 m_one_shot_passed = false; 1054 m_use_dummy = false; 1055 } 1056 1057 const OptionDefinition* 1058 GetDefinitions () override 1059 { 1060 return g_option_table; 1061 } 1062 1063 // Options table: Required for subclasses of Options. 1064 1065 static OptionDefinition g_option_table[]; 1066 1067 // Instance variables to hold the values for command options. 1068 1069 uint32_t m_ignore_count; 1070 lldb::tid_t m_thread_id; 1071 bool m_thread_id_passed; 1072 uint32_t m_thread_index; 1073 bool m_thread_index_passed; 1074 std::string m_thread_name; 1075 std::string m_queue_name; 1076 std::string m_condition; 1077 bool m_one_shot; 1078 bool m_enable_passed; 1079 bool m_enable_value; 1080 bool m_name_passed; 1081 bool m_queue_passed; 1082 bool m_condition_passed; 1083 bool m_one_shot_passed; 1084 bool m_use_dummy; 1085 }; 1086 1087 protected: 1088 bool 1089 DoExecute (Args& command, CommandReturnObject &result) override 1090 { 1091 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 1092 if (target == nullptr) 1093 { 1094 result.AppendError ("Invalid target. No existing target or breakpoints."); 1095 result.SetStatus (eReturnStatusFailed); 1096 return false; 1097 } 1098 1099 std::unique_lock<std::recursive_mutex> lock; 1100 target->GetBreakpointList().GetListMutex(lock); 1101 1102 BreakpointIDList valid_bp_ids; 1103 1104 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids); 1105 1106 if (result.Succeeded()) 1107 { 1108 const size_t count = valid_bp_ids.GetSize(); 1109 for (size_t i = 0; i < count; ++i) 1110 { 1111 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i); 1112 1113 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) 1114 { 1115 Breakpoint *bp = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get(); 1116 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) 1117 { 1118 BreakpointLocation *location = bp->FindLocationByID (cur_bp_id.GetLocationID()).get(); 1119 if (location) 1120 { 1121 if (m_options.m_thread_id_passed) 1122 location->SetThreadID (m_options.m_thread_id); 1123 1124 if (m_options.m_thread_index_passed) 1125 location->SetThreadIndex(m_options.m_thread_index); 1126 1127 if (m_options.m_name_passed) 1128 location->SetThreadName(m_options.m_thread_name.c_str()); 1129 1130 if (m_options.m_queue_passed) 1131 location->SetQueueName(m_options.m_queue_name.c_str()); 1132 1133 if (m_options.m_ignore_count != 0) 1134 location->SetIgnoreCount(m_options.m_ignore_count); 1135 1136 if (m_options.m_enable_passed) 1137 location->SetEnabled (m_options.m_enable_value); 1138 1139 if (m_options.m_condition_passed) 1140 location->SetCondition (m_options.m_condition.c_str()); 1141 } 1142 } 1143 else 1144 { 1145 if (m_options.m_thread_id_passed) 1146 bp->SetThreadID (m_options.m_thread_id); 1147 1148 if (m_options.m_thread_index_passed) 1149 bp->SetThreadIndex(m_options.m_thread_index); 1150 1151 if (m_options.m_name_passed) 1152 bp->SetThreadName(m_options.m_thread_name.c_str()); 1153 1154 if (m_options.m_queue_passed) 1155 bp->SetQueueName(m_options.m_queue_name.c_str()); 1156 1157 if (m_options.m_ignore_count != 0) 1158 bp->SetIgnoreCount(m_options.m_ignore_count); 1159 1160 if (m_options.m_enable_passed) 1161 bp->SetEnabled (m_options.m_enable_value); 1162 1163 if (m_options.m_condition_passed) 1164 bp->SetCondition (m_options.m_condition.c_str()); 1165 } 1166 } 1167 } 1168 } 1169 1170 return result.Succeeded(); 1171 } 1172 1173 private: 1174 CommandOptions m_options; 1175 }; 1176 1177 #pragma mark Modify::CommandOptions 1178 OptionDefinition 1179 CommandObjectBreakpointModify::CommandOptions::g_option_table[] = 1180 { 1181 { LLDB_OPT_SET_ALL, false, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." }, 1182 { LLDB_OPT_SET_ALL, false, "one-shot", 'o', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean, "The breakpoint is deleted the first time it stop causes a stop." }, 1183 { LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose index matches this argument."}, 1184 { LLDB_OPT_SET_ALL, false, "thread-id", 't', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument."}, 1185 { LLDB_OPT_SET_ALL, false, "thread-name", 'T', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this argument."}, 1186 { LLDB_OPT_SET_ALL, false, "queue-name", 'q', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeQueueName, "The breakpoint stops only for threads in the queue whose name is given by this argument."}, 1187 { LLDB_OPT_SET_ALL, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true."}, 1188 { LLDB_OPT_SET_1, false, "enable", 'e', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Enable the breakpoint."}, 1189 { LLDB_OPT_SET_2, false, "disable", 'd', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Disable the breakpoint."}, 1190 { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, 1191 1192 { 0, false, nullptr, 0 , 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 1193 }; 1194 1195 //------------------------------------------------------------------------- 1196 // CommandObjectBreakpointEnable 1197 //------------------------------------------------------------------------- 1198 #pragma mark Enable 1199 1200 class CommandObjectBreakpointEnable : public CommandObjectParsed 1201 { 1202 public: 1203 CommandObjectBreakpointEnable (CommandInterpreter &interpreter) : 1204 CommandObjectParsed(interpreter, 1205 "enable", 1206 "Enable the specified disabled breakpoint(s). If no breakpoints are specified, enable all of them.", 1207 nullptr) 1208 { 1209 CommandArgumentEntry arg; 1210 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, eArgTypeBreakpointIDRange); 1211 // Add the entry for the first argument for this command to the object's arguments vector. 1212 m_arguments.push_back (arg); 1213 } 1214 1215 ~CommandObjectBreakpointEnable() override = default; 1216 1217 protected: 1218 bool 1219 DoExecute (Args& command, CommandReturnObject &result) override 1220 { 1221 Target *target = GetSelectedOrDummyTarget(); 1222 if (target == nullptr) 1223 { 1224 result.AppendError ("Invalid target. No existing target or breakpoints."); 1225 result.SetStatus (eReturnStatusFailed); 1226 return false; 1227 } 1228 1229 std::unique_lock<std::recursive_mutex> lock; 1230 target->GetBreakpointList().GetListMutex(lock); 1231 1232 const BreakpointList &breakpoints = target->GetBreakpointList(); 1233 1234 size_t num_breakpoints = breakpoints.GetSize(); 1235 1236 if (num_breakpoints == 0) 1237 { 1238 result.AppendError ("No breakpoints exist to be enabled."); 1239 result.SetStatus (eReturnStatusFailed); 1240 return false; 1241 } 1242 1243 if (command.GetArgumentCount() == 0) 1244 { 1245 // No breakpoint selected; enable all currently set breakpoints. 1246 target->EnableAllBreakpoints (); 1247 result.AppendMessageWithFormat ("All breakpoints enabled. (%" PRIu64 " breakpoints)\n", (uint64_t)num_breakpoints); 1248 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1249 } 1250 else 1251 { 1252 // Particular breakpoint selected; enable that breakpoint. 1253 BreakpointIDList valid_bp_ids; 1254 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids); 1255 1256 if (result.Succeeded()) 1257 { 1258 int enable_count = 0; 1259 int loc_count = 0; 1260 const size_t count = valid_bp_ids.GetSize(); 1261 for (size_t i = 0; i < count; ++i) 1262 { 1263 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i); 1264 1265 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) 1266 { 1267 Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get(); 1268 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) 1269 { 1270 BreakpointLocation *location = breakpoint->FindLocationByID (cur_bp_id.GetLocationID()).get(); 1271 if (location) 1272 { 1273 location->SetEnabled (true); 1274 ++loc_count; 1275 } 1276 } 1277 else 1278 { 1279 breakpoint->SetEnabled (true); 1280 ++enable_count; 1281 } 1282 } 1283 } 1284 result.AppendMessageWithFormat ("%d breakpoints enabled.\n", enable_count + loc_count); 1285 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1286 } 1287 } 1288 1289 return result.Succeeded(); 1290 } 1291 }; 1292 1293 //------------------------------------------------------------------------- 1294 // CommandObjectBreakpointDisable 1295 //------------------------------------------------------------------------- 1296 #pragma mark Disable 1297 1298 class CommandObjectBreakpointDisable : public CommandObjectParsed 1299 { 1300 public: 1301 CommandObjectBreakpointDisable(CommandInterpreter &interpreter) 1302 : CommandObjectParsed(interpreter, "breakpoint disable", "Disable the specified breakpoint(s) without deleting " 1303 "them. If none are specified, disable all " 1304 "breakpoints.", 1305 nullptr) 1306 { 1307 SetHelpLong("Disable the specified breakpoint(s) without deleting them. \ 1308 If none are specified, disable all breakpoints." 1309 R"( 1310 1311 )" 1312 "Note: disabling a breakpoint will cause none of its locations to be hit \ 1313 regardless of whether individual locations are enabled or disabled. After the sequence:" 1314 R"( 1315 1316 (lldb) break disable 1 1317 (lldb) break enable 1.1 1318 1319 execution will NOT stop at location 1.1. To achieve that, type: 1320 1321 (lldb) break disable 1.* 1322 (lldb) break enable 1.1 1323 1324 )" 1325 "The first command disables all locations for breakpoint 1, \ 1326 the second re-enables the first location."); 1327 1328 CommandArgumentEntry arg; 1329 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, eArgTypeBreakpointIDRange); 1330 // Add the entry for the first argument for this command to the object's arguments vector. 1331 m_arguments.push_back (arg); 1332 } 1333 1334 ~CommandObjectBreakpointDisable() override = default; 1335 1336 protected: 1337 bool 1338 DoExecute (Args& command, CommandReturnObject &result) override 1339 { 1340 Target *target = GetSelectedOrDummyTarget(); 1341 if (target == nullptr) 1342 { 1343 result.AppendError ("Invalid target. No existing target or breakpoints."); 1344 result.SetStatus (eReturnStatusFailed); 1345 return false; 1346 } 1347 1348 std::unique_lock<std::recursive_mutex> lock; 1349 target->GetBreakpointList().GetListMutex(lock); 1350 1351 const BreakpointList &breakpoints = target->GetBreakpointList(); 1352 size_t num_breakpoints = breakpoints.GetSize(); 1353 1354 if (num_breakpoints == 0) 1355 { 1356 result.AppendError ("No breakpoints exist to be disabled."); 1357 result.SetStatus (eReturnStatusFailed); 1358 return false; 1359 } 1360 1361 if (command.GetArgumentCount() == 0) 1362 { 1363 // No breakpoint selected; disable all currently set breakpoints. 1364 target->DisableAllBreakpoints (); 1365 result.AppendMessageWithFormat ("All breakpoints disabled. (%" PRIu64 " breakpoints)\n", (uint64_t)num_breakpoints); 1366 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1367 } 1368 else 1369 { 1370 // Particular breakpoint selected; disable that breakpoint. 1371 BreakpointIDList valid_bp_ids; 1372 1373 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids); 1374 1375 if (result.Succeeded()) 1376 { 1377 int disable_count = 0; 1378 int loc_count = 0; 1379 const size_t count = valid_bp_ids.GetSize(); 1380 for (size_t i = 0; i < count; ++i) 1381 { 1382 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i); 1383 1384 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) 1385 { 1386 Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get(); 1387 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) 1388 { 1389 BreakpointLocation *location = breakpoint->FindLocationByID (cur_bp_id.GetLocationID()).get(); 1390 if (location) 1391 { 1392 location->SetEnabled (false); 1393 ++loc_count; 1394 } 1395 } 1396 else 1397 { 1398 breakpoint->SetEnabled (false); 1399 ++disable_count; 1400 } 1401 } 1402 } 1403 result.AppendMessageWithFormat ("%d breakpoints disabled.\n", disable_count + loc_count); 1404 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1405 } 1406 } 1407 1408 return result.Succeeded(); 1409 } 1410 }; 1411 1412 //------------------------------------------------------------------------- 1413 // CommandObjectBreakpointList 1414 //------------------------------------------------------------------------- 1415 #pragma mark List 1416 1417 class CommandObjectBreakpointList : public CommandObjectParsed 1418 { 1419 public: 1420 CommandObjectBreakpointList (CommandInterpreter &interpreter) : 1421 CommandObjectParsed(interpreter, 1422 "breakpoint list", 1423 "List some or all breakpoints at configurable levels of detail.", 1424 nullptr), 1425 m_options () 1426 { 1427 CommandArgumentEntry arg; 1428 CommandArgumentData bp_id_arg; 1429 1430 // Define the first (and only) variant of this arg. 1431 bp_id_arg.arg_type = eArgTypeBreakpointID; 1432 bp_id_arg.arg_repetition = eArgRepeatOptional; 1433 1434 // There is only one variant this argument could be; put it into the argument entry. 1435 arg.push_back (bp_id_arg); 1436 1437 // Push the data for the first argument into the m_arguments vector. 1438 m_arguments.push_back (arg); 1439 } 1440 1441 ~CommandObjectBreakpointList() override = default; 1442 1443 Options * 1444 GetOptions () override 1445 { 1446 return &m_options; 1447 } 1448 1449 class CommandOptions : public Options 1450 { 1451 public: 1452 CommandOptions () : 1453 Options (), 1454 m_level (lldb::eDescriptionLevelBrief), 1455 m_use_dummy(false) 1456 { 1457 } 1458 1459 ~CommandOptions() override = default; 1460 1461 Error 1462 SetOptionValue (uint32_t option_idx, const char *option_arg, 1463 ExecutionContext *execution_context) override 1464 { 1465 Error error; 1466 const int short_option = m_getopt_table[option_idx].val; 1467 1468 switch (short_option) 1469 { 1470 case 'b': 1471 m_level = lldb::eDescriptionLevelBrief; 1472 break; 1473 case 'D': 1474 m_use_dummy = true; 1475 break; 1476 case 'f': 1477 m_level = lldb::eDescriptionLevelFull; 1478 break; 1479 case 'v': 1480 m_level = lldb::eDescriptionLevelVerbose; 1481 break; 1482 case 'i': 1483 m_internal = true; 1484 break; 1485 default: 1486 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 1487 break; 1488 } 1489 1490 return error; 1491 } 1492 1493 void 1494 OptionParsingStarting (ExecutionContext *execution_context) override 1495 { 1496 m_level = lldb::eDescriptionLevelFull; 1497 m_internal = false; 1498 m_use_dummy = false; 1499 } 1500 1501 const OptionDefinition * 1502 GetDefinitions () override 1503 { 1504 return g_option_table; 1505 } 1506 1507 // Options table: Required for subclasses of Options. 1508 1509 static OptionDefinition g_option_table[]; 1510 1511 // Instance variables to hold the values for command options. 1512 1513 lldb::DescriptionLevel m_level; 1514 1515 bool m_internal; 1516 bool m_use_dummy; 1517 }; 1518 1519 protected: 1520 bool 1521 DoExecute (Args& command, CommandReturnObject &result) override 1522 { 1523 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 1524 1525 if (target == nullptr) 1526 { 1527 result.AppendError ("Invalid target. No current target or breakpoints."); 1528 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1529 return true; 1530 } 1531 1532 const BreakpointList &breakpoints = target->GetBreakpointList(m_options.m_internal); 1533 std::unique_lock<std::recursive_mutex> lock; 1534 target->GetBreakpointList(m_options.m_internal).GetListMutex(lock); 1535 1536 size_t num_breakpoints = breakpoints.GetSize(); 1537 1538 if (num_breakpoints == 0) 1539 { 1540 result.AppendMessage ("No breakpoints currently set."); 1541 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1542 return true; 1543 } 1544 1545 Stream &output_stream = result.GetOutputStream(); 1546 1547 if (command.GetArgumentCount() == 0) 1548 { 1549 // No breakpoint selected; show info about all currently set breakpoints. 1550 result.AppendMessage ("Current breakpoints:"); 1551 for (size_t i = 0; i < num_breakpoints; ++i) 1552 { 1553 Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex (i).get(); 1554 AddBreakpointDescription (&output_stream, breakpoint, m_options.m_level); 1555 } 1556 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1557 } 1558 else 1559 { 1560 // Particular breakpoints selected; show info about that breakpoint. 1561 BreakpointIDList valid_bp_ids; 1562 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids); 1563 1564 if (result.Succeeded()) 1565 { 1566 for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) 1567 { 1568 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i); 1569 Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get(); 1570 AddBreakpointDescription (&output_stream, breakpoint, m_options.m_level); 1571 } 1572 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1573 } 1574 else 1575 { 1576 result.AppendError("Invalid breakpoint ID."); 1577 result.SetStatus (eReturnStatusFailed); 1578 } 1579 } 1580 1581 return result.Succeeded(); 1582 } 1583 1584 private: 1585 CommandOptions m_options; 1586 }; 1587 1588 #pragma mark List::CommandOptions 1589 OptionDefinition 1590 CommandObjectBreakpointList::CommandOptions::g_option_table[] = 1591 { 1592 { LLDB_OPT_SET_ALL, false, "internal", 'i', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, 1593 "Show debugger internal breakpoints" }, 1594 1595 { LLDB_OPT_SET_1, false, "brief", 'b', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, 1596 "Give a brief description of the breakpoint (no location info)."}, 1597 1598 // FIXME: We need to add an "internal" command, and then add this sort of thing to it. 1599 // But I need to see it for now, and don't want to wait. 1600 { LLDB_OPT_SET_2, false, "full", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, 1601 "Give a full description of the breakpoint and its locations."}, 1602 1603 { LLDB_OPT_SET_3, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, 1604 "Explain everything we know about the breakpoint (for debugging debugger bugs)." }, 1605 1606 { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, 1607 "List Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, 1608 1609 { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 1610 }; 1611 1612 //------------------------------------------------------------------------- 1613 // CommandObjectBreakpointClear 1614 //------------------------------------------------------------------------- 1615 #pragma mark Clear 1616 1617 class CommandObjectBreakpointClear : public CommandObjectParsed 1618 { 1619 public: 1620 typedef enum BreakpointClearType 1621 { 1622 eClearTypeInvalid, 1623 eClearTypeFileAndLine 1624 } BreakpointClearType; 1625 1626 CommandObjectBreakpointClear(CommandInterpreter &interpreter) 1627 : CommandObjectParsed(interpreter, "breakpoint clear", 1628 "Delete or disable breakpoints matching the specified source file and line.", 1629 "breakpoint clear <cmd-options>"), 1630 m_options() 1631 { 1632 } 1633 1634 ~CommandObjectBreakpointClear() override = default; 1635 1636 Options * 1637 GetOptions () override 1638 { 1639 return &m_options; 1640 } 1641 1642 class CommandOptions : public Options 1643 { 1644 public: 1645 CommandOptions () : 1646 Options (), 1647 m_filename (), 1648 m_line_num (0) 1649 { 1650 } 1651 1652 ~CommandOptions() override = default; 1653 1654 Error 1655 SetOptionValue (uint32_t option_idx, const char *option_arg, 1656 ExecutionContext *execution_context) override 1657 { 1658 Error error; 1659 const int short_option = m_getopt_table[option_idx].val; 1660 1661 switch (short_option) 1662 { 1663 case 'f': 1664 m_filename.assign (option_arg); 1665 break; 1666 1667 case 'l': 1668 m_line_num = StringConvert::ToUInt32 (option_arg, 0); 1669 break; 1670 1671 default: 1672 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 1673 break; 1674 } 1675 1676 return error; 1677 } 1678 1679 void 1680 OptionParsingStarting (ExecutionContext *execution_context) override 1681 { 1682 m_filename.clear(); 1683 m_line_num = 0; 1684 } 1685 1686 const OptionDefinition* 1687 GetDefinitions () override 1688 { 1689 return g_option_table; 1690 } 1691 1692 // Options table: Required for subclasses of Options. 1693 1694 static OptionDefinition g_option_table[]; 1695 1696 // Instance variables to hold the values for command options. 1697 1698 std::string m_filename; 1699 uint32_t m_line_num; 1700 1701 }; 1702 1703 protected: 1704 bool 1705 DoExecute (Args& command, CommandReturnObject &result) override 1706 { 1707 Target *target = GetSelectedOrDummyTarget(); 1708 if (target == nullptr) 1709 { 1710 result.AppendError ("Invalid target. No existing target or breakpoints."); 1711 result.SetStatus (eReturnStatusFailed); 1712 return false; 1713 } 1714 1715 // The following are the various types of breakpoints that could be cleared: 1716 // 1). -f -l (clearing breakpoint by source location) 1717 1718 BreakpointClearType break_type = eClearTypeInvalid; 1719 1720 if (m_options.m_line_num != 0) 1721 break_type = eClearTypeFileAndLine; 1722 1723 std::unique_lock<std::recursive_mutex> lock; 1724 target->GetBreakpointList().GetListMutex(lock); 1725 1726 BreakpointList &breakpoints = target->GetBreakpointList(); 1727 size_t num_breakpoints = breakpoints.GetSize(); 1728 1729 // Early return if there's no breakpoint at all. 1730 if (num_breakpoints == 0) 1731 { 1732 result.AppendError ("Breakpoint clear: No breakpoint cleared."); 1733 result.SetStatus (eReturnStatusFailed); 1734 return result.Succeeded(); 1735 } 1736 1737 // Find matching breakpoints and delete them. 1738 1739 // First create a copy of all the IDs. 1740 std::vector<break_id_t> BreakIDs; 1741 for (size_t i = 0; i < num_breakpoints; ++i) 1742 BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID()); 1743 1744 int num_cleared = 0; 1745 StreamString ss; 1746 switch (break_type) 1747 { 1748 case eClearTypeFileAndLine: // Breakpoint by source position 1749 { 1750 const ConstString filename(m_options.m_filename.c_str()); 1751 BreakpointLocationCollection loc_coll; 1752 1753 for (size_t i = 0; i < num_breakpoints; ++i) 1754 { 1755 Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get(); 1756 1757 if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) 1758 { 1759 // If the collection size is 0, it's a full match and we can just remove the breakpoint. 1760 if (loc_coll.GetSize() == 0) 1761 { 1762 bp->GetDescription(&ss, lldb::eDescriptionLevelBrief); 1763 ss.EOL(); 1764 target->RemoveBreakpointByID (bp->GetID()); 1765 ++num_cleared; 1766 } 1767 } 1768 } 1769 } 1770 break; 1771 1772 default: 1773 break; 1774 } 1775 1776 if (num_cleared > 0) 1777 { 1778 Stream &output_stream = result.GetOutputStream(); 1779 output_stream.Printf ("%d breakpoints cleared:\n", num_cleared); 1780 output_stream << ss.GetData(); 1781 output_stream.EOL(); 1782 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1783 } 1784 else 1785 { 1786 result.AppendError ("Breakpoint clear: No breakpoint cleared."); 1787 result.SetStatus (eReturnStatusFailed); 1788 } 1789 1790 return result.Succeeded(); 1791 } 1792 1793 private: 1794 CommandOptions m_options; 1795 }; 1796 1797 #pragma mark Clear::CommandOptions 1798 1799 OptionDefinition 1800 CommandObjectBreakpointClear::CommandOptions::g_option_table[] = 1801 { 1802 { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, nullptr, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, 1803 "Specify the breakpoint by source location in this particular file."}, 1804 1805 { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLineNum, 1806 "Specify the breakpoint by source location at this particular line."}, 1807 1808 { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 1809 }; 1810 1811 //------------------------------------------------------------------------- 1812 // CommandObjectBreakpointDelete 1813 //------------------------------------------------------------------------- 1814 #pragma mark Delete 1815 1816 class CommandObjectBreakpointDelete : public CommandObjectParsed 1817 { 1818 public: 1819 CommandObjectBreakpointDelete (CommandInterpreter &interpreter) : 1820 CommandObjectParsed(interpreter, 1821 "breakpoint delete", 1822 "Delete the specified breakpoint(s). If no breakpoints are specified, delete them all.", 1823 nullptr), 1824 m_options() 1825 { 1826 CommandArgumentEntry arg; 1827 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, eArgTypeBreakpointIDRange); 1828 // Add the entry for the first argument for this command to the object's arguments vector. 1829 m_arguments.push_back (arg); 1830 } 1831 1832 ~CommandObjectBreakpointDelete() override = default; 1833 1834 Options * 1835 GetOptions () override 1836 { 1837 return &m_options; 1838 } 1839 1840 class CommandOptions : public Options 1841 { 1842 public: 1843 CommandOptions () : 1844 Options (), 1845 m_use_dummy (false), 1846 m_force (false) 1847 { 1848 } 1849 1850 ~CommandOptions() override = default; 1851 1852 Error 1853 SetOptionValue (uint32_t option_idx, const char *option_arg, 1854 ExecutionContext *execution_context) override 1855 { 1856 Error error; 1857 const int short_option = m_getopt_table[option_idx].val; 1858 1859 switch (short_option) 1860 { 1861 case 'f': 1862 m_force = true; 1863 break; 1864 1865 case 'D': 1866 m_use_dummy = true; 1867 break; 1868 1869 default: 1870 error.SetErrorStringWithFormat ("unrecognized option '%c'", short_option); 1871 break; 1872 } 1873 1874 return error; 1875 } 1876 1877 void 1878 OptionParsingStarting (ExecutionContext *execution_context) override 1879 { 1880 m_use_dummy = false; 1881 m_force = false; 1882 } 1883 1884 const OptionDefinition* 1885 GetDefinitions () override 1886 { 1887 return g_option_table; 1888 } 1889 1890 // Options table: Required for subclasses of Options. 1891 1892 static OptionDefinition g_option_table[]; 1893 1894 // Instance variables to hold the values for command options. 1895 bool m_use_dummy; 1896 bool m_force; 1897 }; 1898 1899 protected: 1900 bool 1901 DoExecute (Args& command, CommandReturnObject &result) override 1902 { 1903 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 1904 1905 if (target == nullptr) 1906 { 1907 result.AppendError ("Invalid target. No existing target or breakpoints."); 1908 result.SetStatus (eReturnStatusFailed); 1909 return false; 1910 } 1911 1912 std::unique_lock<std::recursive_mutex> lock; 1913 target->GetBreakpointList().GetListMutex(lock); 1914 1915 const BreakpointList &breakpoints = target->GetBreakpointList(); 1916 1917 size_t num_breakpoints = breakpoints.GetSize(); 1918 1919 if (num_breakpoints == 0) 1920 { 1921 result.AppendError ("No breakpoints exist to be deleted."); 1922 result.SetStatus (eReturnStatusFailed); 1923 return false; 1924 } 1925 1926 if (command.GetArgumentCount() == 0) 1927 { 1928 if (!m_options.m_force && !m_interpreter.Confirm ("About to delete all breakpoints, do you want to do that?", true)) 1929 { 1930 result.AppendMessage("Operation cancelled..."); 1931 } 1932 else 1933 { 1934 target->RemoveAllBreakpoints (); 1935 result.AppendMessageWithFormat ("All breakpoints removed. (%" PRIu64 " breakpoint%s)\n", (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : ""); 1936 } 1937 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1938 } 1939 else 1940 { 1941 // Particular breakpoint selected; disable that breakpoint. 1942 BreakpointIDList valid_bp_ids; 1943 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs (command, target, result, &valid_bp_ids); 1944 1945 if (result.Succeeded()) 1946 { 1947 int delete_count = 0; 1948 int disable_count = 0; 1949 const size_t count = valid_bp_ids.GetSize(); 1950 for (size_t i = 0; i < count; ++i) 1951 { 1952 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex (i); 1953 1954 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) 1955 { 1956 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) 1957 { 1958 Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get(); 1959 BreakpointLocation *location = breakpoint->FindLocationByID (cur_bp_id.GetLocationID()).get(); 1960 // It makes no sense to try to delete individual locations, so we disable them instead. 1961 if (location) 1962 { 1963 location->SetEnabled (false); 1964 ++disable_count; 1965 } 1966 } 1967 else 1968 { 1969 target->RemoveBreakpointByID (cur_bp_id.GetBreakpointID()); 1970 ++delete_count; 1971 } 1972 } 1973 } 1974 result.AppendMessageWithFormat ("%d breakpoints deleted; %d breakpoint locations disabled.\n", 1975 delete_count, disable_count); 1976 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1977 } 1978 } 1979 return result.Succeeded(); 1980 } 1981 1982 private: 1983 CommandOptions m_options; 1984 }; 1985 1986 OptionDefinition 1987 CommandObjectBreakpointDelete::CommandOptions::g_option_table[] = 1988 { 1989 { LLDB_OPT_SET_1, false, "force", 'f', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, 1990 "Delete all breakpoints without querying for confirmation."}, 1991 1992 { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, 1993 "Delete Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, 1994 1995 { 0, false, nullptr, 0, 0, nullptr, nullptr, 0, eArgTypeNone, nullptr } 1996 }; 1997 1998 //------------------------------------------------------------------------- 1999 // CommandObjectBreakpointName 2000 //------------------------------------------------------------------------- 2001 2002 static OptionDefinition g_breakpoint_name_options[] = { 2003 {LLDB_OPT_SET_1, false, "name", 'N', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBreakpointName, 2004 "Specifies a breakpoint name to use."}, 2005 {LLDB_OPT_SET_2, false, "breakpoint-id", 'B', OptionParser::eRequiredArgument, nullptr, nullptr, 0, 2006 eArgTypeBreakpointID, "Specify a breakpoint ID to use."}, 2007 {LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, nullptr, 0, eArgTypeNone, 2008 "Operate on Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, 2009 }; 2010 class BreakpointNameOptionGroup : public OptionGroup 2011 { 2012 public: 2013 BreakpointNameOptionGroup() : 2014 OptionGroup(), 2015 m_breakpoint(LLDB_INVALID_BREAK_ID), 2016 m_use_dummy (false) 2017 { 2018 } 2019 2020 ~BreakpointNameOptionGroup() override = default; 2021 2022 uint32_t 2023 GetNumDefinitions () override 2024 { 2025 return sizeof (g_breakpoint_name_options) / sizeof (OptionDefinition); 2026 } 2027 2028 const OptionDefinition* 2029 GetDefinitions () override 2030 { 2031 return g_breakpoint_name_options; 2032 } 2033 2034 Error 2035 SetOptionValue (uint32_t option_idx, 2036 const char *option_value, 2037 ExecutionContext *execution_context) override 2038 { 2039 Error error; 2040 const int short_option = g_breakpoint_name_options[option_idx].short_option; 2041 2042 switch (short_option) 2043 { 2044 case 'N': 2045 if (BreakpointID::StringIsBreakpointName(option_value, error) && error.Success()) 2046 m_name.SetValueFromString(option_value); 2047 break; 2048 2049 case 'B': 2050 if (m_breakpoint.SetValueFromString(option_value).Fail()) 2051 error.SetErrorStringWithFormat ("unrecognized value \"%s\" for breakpoint", option_value); 2052 break; 2053 case 'D': 2054 if (m_use_dummy.SetValueFromString(option_value).Fail()) 2055 error.SetErrorStringWithFormat ("unrecognized value \"%s\" for use-dummy", option_value); 2056 break; 2057 2058 default: 2059 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); 2060 break; 2061 } 2062 return error; 2063 } 2064 2065 void 2066 OptionParsingStarting (ExecutionContext *execution_context) override 2067 { 2068 m_name.Clear(); 2069 m_breakpoint.Clear(); 2070 m_use_dummy.Clear(); 2071 m_use_dummy.SetDefaultValue(false); 2072 } 2073 2074 OptionValueString m_name; 2075 OptionValueUInt64 m_breakpoint; 2076 OptionValueBoolean m_use_dummy; 2077 }; 2078 2079 class CommandObjectBreakpointNameAdd : public CommandObjectParsed 2080 { 2081 public: 2082 CommandObjectBreakpointNameAdd (CommandInterpreter &interpreter) : 2083 CommandObjectParsed (interpreter, 2084 "add", 2085 "Add a name to the breakpoints provided.", 2086 "breakpoint name add <command-options> <breakpoint-id-list>"), 2087 m_name_options(), 2088 m_option_group() 2089 { 2090 // Create the first variant for the first (and only) argument for this command. 2091 CommandArgumentEntry arg1; 2092 CommandArgumentData id_arg; 2093 id_arg.arg_type = eArgTypeBreakpointID; 2094 id_arg.arg_repetition = eArgRepeatOptional; 2095 arg1.push_back(id_arg); 2096 m_arguments.push_back (arg1); 2097 2098 m_option_group.Append (&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 2099 m_option_group.Finalize(); 2100 } 2101 2102 ~CommandObjectBreakpointNameAdd() override = default; 2103 2104 Options * 2105 GetOptions() override 2106 { 2107 return &m_option_group; 2108 } 2109 2110 protected: 2111 bool 2112 DoExecute (Args& command, CommandReturnObject &result) override 2113 { 2114 if (!m_name_options.m_name.OptionWasSet()) 2115 { 2116 result.SetError("No name option provided."); 2117 return false; 2118 } 2119 2120 Target *target = GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 2121 2122 if (target == nullptr) 2123 { 2124 result.AppendError ("Invalid target. No existing target or breakpoints."); 2125 result.SetStatus (eReturnStatusFailed); 2126 return false; 2127 } 2128 2129 std::unique_lock<std::recursive_mutex> lock; 2130 target->GetBreakpointList().GetListMutex(lock); 2131 2132 const BreakpointList &breakpoints = target->GetBreakpointList(); 2133 2134 size_t num_breakpoints = breakpoints.GetSize(); 2135 if (num_breakpoints == 0) 2136 { 2137 result.SetError("No breakpoints, cannot add names."); 2138 result.SetStatus (eReturnStatusFailed); 2139 return false; 2140 } 2141 2142 // Particular breakpoint selected; disable that breakpoint. 2143 BreakpointIDList valid_bp_ids; 2144 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids); 2145 2146 if (result.Succeeded()) 2147 { 2148 if (valid_bp_ids.GetSize() == 0) 2149 { 2150 result.SetError("No breakpoints specified, cannot add names."); 2151 result.SetStatus (eReturnStatusFailed); 2152 return false; 2153 } 2154 size_t num_valid_ids = valid_bp_ids.GetSize(); 2155 for (size_t index = 0; index < num_valid_ids; index++) 2156 { 2157 lldb::break_id_t bp_id = valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); 2158 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); 2159 Error error; // We don't need to check the error here, since the option parser checked it... 2160 bp_sp->AddName(m_name_options.m_name.GetCurrentValue(), error); 2161 } 2162 } 2163 2164 return true; 2165 } 2166 2167 private: 2168 BreakpointNameOptionGroup m_name_options; 2169 OptionGroupOptions m_option_group; 2170 }; 2171 2172 class CommandObjectBreakpointNameDelete : public CommandObjectParsed 2173 { 2174 public: 2175 CommandObjectBreakpointNameDelete (CommandInterpreter &interpreter) : 2176 CommandObjectParsed (interpreter, 2177 "delete", 2178 "Delete a name from the breakpoints provided.", 2179 "breakpoint name delete <command-options> <breakpoint-id-list>"), 2180 m_name_options(), 2181 m_option_group() 2182 { 2183 // Create the first variant for the first (and only) argument for this command. 2184 CommandArgumentEntry arg1; 2185 CommandArgumentData id_arg; 2186 id_arg.arg_type = eArgTypeBreakpointID; 2187 id_arg.arg_repetition = eArgRepeatOptional; 2188 arg1.push_back(id_arg); 2189 m_arguments.push_back (arg1); 2190 2191 m_option_group.Append (&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 2192 m_option_group.Finalize(); 2193 } 2194 2195 ~CommandObjectBreakpointNameDelete() override = default; 2196 2197 Options * 2198 GetOptions() override 2199 { 2200 return &m_option_group; 2201 } 2202 2203 protected: 2204 bool 2205 DoExecute (Args& command, CommandReturnObject &result) override 2206 { 2207 if (!m_name_options.m_name.OptionWasSet()) 2208 { 2209 result.SetError("No name option provided."); 2210 return false; 2211 } 2212 2213 Target *target = GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 2214 2215 if (target == nullptr) 2216 { 2217 result.AppendError ("Invalid target. No existing target or breakpoints."); 2218 result.SetStatus (eReturnStatusFailed); 2219 return false; 2220 } 2221 2222 std::unique_lock<std::recursive_mutex> lock; 2223 target->GetBreakpointList().GetListMutex(lock); 2224 2225 const BreakpointList &breakpoints = target->GetBreakpointList(); 2226 2227 size_t num_breakpoints = breakpoints.GetSize(); 2228 if (num_breakpoints == 0) 2229 { 2230 result.SetError("No breakpoints, cannot delete names."); 2231 result.SetStatus (eReturnStatusFailed); 2232 return false; 2233 } 2234 2235 // Particular breakpoint selected; disable that breakpoint. 2236 BreakpointIDList valid_bp_ids; 2237 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs (command, target, result, &valid_bp_ids); 2238 2239 if (result.Succeeded()) 2240 { 2241 if (valid_bp_ids.GetSize() == 0) 2242 { 2243 result.SetError("No breakpoints specified, cannot delete names."); 2244 result.SetStatus (eReturnStatusFailed); 2245 return false; 2246 } 2247 size_t num_valid_ids = valid_bp_ids.GetSize(); 2248 for (size_t index = 0; index < num_valid_ids; index++) 2249 { 2250 lldb::break_id_t bp_id = valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); 2251 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); 2252 bp_sp->RemoveName(m_name_options.m_name.GetCurrentValue()); 2253 } 2254 } 2255 2256 return true; 2257 } 2258 2259 private: 2260 BreakpointNameOptionGroup m_name_options; 2261 OptionGroupOptions m_option_group; 2262 }; 2263 2264 class CommandObjectBreakpointNameList : public CommandObjectParsed 2265 { 2266 public: 2267 CommandObjectBreakpointNameList (CommandInterpreter &interpreter) : 2268 CommandObjectParsed (interpreter, 2269 "list", 2270 "List either the names for a breakpoint or the breakpoints for a given name.", 2271 "breakpoint name list <command-options>"), 2272 m_name_options(), 2273 m_option_group() 2274 { 2275 m_option_group.Append (&m_name_options); 2276 m_option_group.Finalize(); 2277 } 2278 2279 ~CommandObjectBreakpointNameList() override = default; 2280 2281 Options * 2282 GetOptions() override 2283 { 2284 return &m_option_group; 2285 } 2286 2287 protected: 2288 bool 2289 DoExecute (Args& command, CommandReturnObject &result) override 2290 { 2291 Target *target = GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 2292 2293 if (target == nullptr) 2294 { 2295 result.AppendError ("Invalid target. No existing target or breakpoints."); 2296 result.SetStatus (eReturnStatusFailed); 2297 return false; 2298 } 2299 2300 if (m_name_options.m_name.OptionWasSet()) 2301 { 2302 const char *name = m_name_options.m_name.GetCurrentValue(); 2303 std::unique_lock<std::recursive_mutex> lock; 2304 target->GetBreakpointList().GetListMutex(lock); 2305 2306 BreakpointList &breakpoints = target->GetBreakpointList(); 2307 for (BreakpointSP bp_sp : breakpoints.Breakpoints()) 2308 { 2309 if (bp_sp->MatchesName(name)) 2310 { 2311 StreamString s; 2312 bp_sp->GetDescription(&s, eDescriptionLevelBrief); 2313 s.EOL(); 2314 result.AppendMessage(s.GetData()); 2315 } 2316 } 2317 2318 } 2319 else if (m_name_options.m_breakpoint.OptionWasSet()) 2320 { 2321 BreakpointSP bp_sp = target->GetBreakpointList().FindBreakpointByID(m_name_options.m_breakpoint.GetCurrentValue()); 2322 if (bp_sp) 2323 { 2324 std::vector<std::string> names; 2325 bp_sp->GetNames (names); 2326 result.AppendMessage ("Names:"); 2327 for (auto name : names) 2328 result.AppendMessageWithFormat (" %s\n", name.c_str()); 2329 } 2330 else 2331 { 2332 result.AppendErrorWithFormat ("Could not find breakpoint %" PRId64 ".\n", 2333 m_name_options.m_breakpoint.GetCurrentValue()); 2334 result.SetStatus (eReturnStatusFailed); 2335 return false; 2336 } 2337 } 2338 else 2339 { 2340 result.SetError ("Must specify -N or -B option to list."); 2341 result.SetStatus (eReturnStatusFailed); 2342 return false; 2343 } 2344 return true; 2345 } 2346 2347 private: 2348 BreakpointNameOptionGroup m_name_options; 2349 OptionGroupOptions m_option_group; 2350 }; 2351 2352 //------------------------------------------------------------------------- 2353 // CommandObjectMultiwordBreakpoint 2354 //------------------------------------------------------------------------- 2355 class CommandObjectBreakpointName : public CommandObjectMultiword 2356 { 2357 public: 2358 CommandObjectBreakpointName(CommandInterpreter &interpreter) 2359 : CommandObjectMultiword(interpreter, "name", "Commands to manage name tags for breakpoints", 2360 "breakpoint name <subcommand> [<command-options>]") 2361 { 2362 CommandObjectSP add_command_object (new CommandObjectBreakpointNameAdd (interpreter)); 2363 CommandObjectSP delete_command_object (new CommandObjectBreakpointNameDelete (interpreter)); 2364 CommandObjectSP list_command_object (new CommandObjectBreakpointNameList (interpreter)); 2365 2366 LoadSubCommand ("add", add_command_object); 2367 LoadSubCommand ("delete", delete_command_object); 2368 LoadSubCommand ("list", list_command_object); 2369 } 2370 2371 ~CommandObjectBreakpointName() override = default; 2372 }; 2373 2374 //------------------------------------------------------------------------- 2375 // CommandObjectMultiwordBreakpoint 2376 //------------------------------------------------------------------------- 2377 #pragma mark MultiwordBreakpoint 2378 2379 CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint(CommandInterpreter &interpreter) 2380 : CommandObjectMultiword(interpreter, "breakpoint", 2381 "Commands for operating on breakpoints (see 'help b' for shorthand.)", 2382 "breakpoint <subcommand> [<command-options>]") 2383 { 2384 CommandObjectSP list_command_object (new CommandObjectBreakpointList (interpreter)); 2385 CommandObjectSP enable_command_object (new CommandObjectBreakpointEnable (interpreter)); 2386 CommandObjectSP disable_command_object (new CommandObjectBreakpointDisable (interpreter)); 2387 CommandObjectSP clear_command_object (new CommandObjectBreakpointClear (interpreter)); 2388 CommandObjectSP delete_command_object (new CommandObjectBreakpointDelete (interpreter)); 2389 CommandObjectSP set_command_object (new CommandObjectBreakpointSet (interpreter)); 2390 CommandObjectSP command_command_object (new CommandObjectBreakpointCommand (interpreter)); 2391 CommandObjectSP modify_command_object (new CommandObjectBreakpointModify(interpreter)); 2392 CommandObjectSP name_command_object (new CommandObjectBreakpointName(interpreter)); 2393 2394 list_command_object->SetCommandName ("breakpoint list"); 2395 enable_command_object->SetCommandName("breakpoint enable"); 2396 disable_command_object->SetCommandName("breakpoint disable"); 2397 clear_command_object->SetCommandName("breakpoint clear"); 2398 delete_command_object->SetCommandName("breakpoint delete"); 2399 set_command_object->SetCommandName("breakpoint set"); 2400 command_command_object->SetCommandName ("breakpoint command"); 2401 modify_command_object->SetCommandName ("breakpoint modify"); 2402 name_command_object->SetCommandName ("breakpoint name"); 2403 2404 LoadSubCommand ("list", list_command_object); 2405 LoadSubCommand ("enable", enable_command_object); 2406 LoadSubCommand ("disable", disable_command_object); 2407 LoadSubCommand ("clear", clear_command_object); 2408 LoadSubCommand ("delete", delete_command_object); 2409 LoadSubCommand ("set", set_command_object); 2410 LoadSubCommand ("command", command_command_object); 2411 LoadSubCommand ("modify", modify_command_object); 2412 LoadSubCommand ("name", name_command_object); 2413 } 2414 2415 CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default; 2416 2417 void 2418 CommandObjectMultiwordBreakpoint::VerifyIDs (Args &args, 2419 Target *target, 2420 bool allow_locations, 2421 CommandReturnObject &result, 2422 BreakpointIDList *valid_ids) 2423 { 2424 // args can be strings representing 1). integers (for breakpoint ids) 2425 // 2). the full breakpoint & location canonical representation 2426 // 3). the word "to" or a hyphen, representing a range (in which case there 2427 // had *better* be an entry both before & after of one of the first two types. 2428 // 4). A breakpoint name 2429 // If args is empty, we will use the last created breakpoint (if there is one.) 2430 2431 Args temp_args; 2432 2433 if (args.GetArgumentCount() == 0) 2434 { 2435 if (target->GetLastCreatedBreakpoint()) 2436 { 2437 valid_ids->AddBreakpointID (BreakpointID(target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID)); 2438 result.SetStatus (eReturnStatusSuccessFinishNoResult); 2439 } 2440 else 2441 { 2442 result.AppendError("No breakpoint specified and no last created breakpoint."); 2443 result.SetStatus (eReturnStatusFailed); 2444 } 2445 return; 2446 } 2447 2448 // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff directly from the old ARGS to 2449 // the new TEMP_ARGS. Do not copy breakpoint id range strings over; instead generate a list of strings for 2450 // all the breakpoint ids in the range, and shove all of those breakpoint id strings into TEMP_ARGS. 2451 2452 BreakpointIDList::FindAndReplaceIDRanges (args, target, allow_locations, result, temp_args); 2453 2454 // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual BreakpointIDList: 2455 2456 valid_ids->InsertStringArray (temp_args.GetConstArgumentVector(), temp_args.GetArgumentCount(), result); 2457 2458 // At this point, all of the breakpoint ids that the user passed in have been converted to breakpoint IDs 2459 // and put into valid_ids. 2460 2461 if (result.Succeeded()) 2462 { 2463 // Now that we've converted everything from args into a list of breakpoint ids, go through our tentative list 2464 // of breakpoint id's and verify that they correspond to valid/currently set breakpoints. 2465 2466 const size_t count = valid_ids->GetSize(); 2467 for (size_t i = 0; i < count; ++i) 2468 { 2469 BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex (i); 2470 Breakpoint *breakpoint = target->GetBreakpointByID (cur_bp_id.GetBreakpointID()).get(); 2471 if (breakpoint != nullptr) 2472 { 2473 const size_t num_locations = breakpoint->GetNumLocations(); 2474 if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) 2475 { 2476 StreamString id_str; 2477 BreakpointID::GetCanonicalReference (&id_str, 2478 cur_bp_id.GetBreakpointID(), 2479 cur_bp_id.GetLocationID()); 2480 i = valid_ids->GetSize() + 1; 2481 result.AppendErrorWithFormat ("'%s' is not a currently valid breakpoint/location id.\n", 2482 id_str.GetData()); 2483 result.SetStatus (eReturnStatusFailed); 2484 } 2485 } 2486 else 2487 { 2488 i = valid_ids->GetSize() + 1; 2489 result.AppendErrorWithFormat("'%d' is not a currently valid breakpoint ID.\n", 2490 cur_bp_id.GetBreakpointID()); 2491 result.SetStatus (eReturnStatusFailed); 2492 } 2493 } 2494 } 2495 } 2496