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