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 = llvm::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 (!regexp.IsValid()) { 686 char err_str[1024]; 687 regexp.GetErrorAsCString(err_str, sizeof(err_str)); 688 result.AppendErrorWithFormat( 689 "Function name regular expression could not be compiled: \"%s\"", 690 err_str); 691 result.SetStatus(eReturnStatusFailed); 692 return false; 693 } 694 695 bp_sp = target->CreateFuncRegexBreakpoint(&(m_options.m_modules), 696 &(m_options.m_filenames), 697 regexp, 698 m_options.m_language, 699 m_options.m_skip_prologue, 700 internal, 701 m_options.m_hardware); 702 } 703 break; 704 case eSetTypeSourceRegexp: // Breakpoint by regexp on source text. 705 { 706 const size_t num_files = m_options.m_filenames.GetSize(); 707 708 if (num_files == 0 && !m_options.m_all_files) { 709 FileSpec file; 710 if (!GetDefaultFile(target, file, result)) { 711 result.AppendError( 712 "No files provided and could not find default file."); 713 result.SetStatus(eReturnStatusFailed); 714 return false; 715 } else { 716 m_options.m_filenames.Append(file); 717 } 718 } 719 720 RegularExpression regexp(m_options.m_source_text_regexp); 721 if (!regexp.IsValid()) { 722 char err_str[1024]; 723 regexp.GetErrorAsCString(err_str, sizeof(err_str)); 724 result.AppendErrorWithFormat( 725 "Source text regular expression could not be compiled: \"%s\"", 726 err_str); 727 result.SetStatus(eReturnStatusFailed); 728 return false; 729 } 730 bp_sp = 731 target->CreateSourceRegexBreakpoint(&(m_options.m_modules), 732 &(m_options.m_filenames), 733 m_options 734 .m_source_regex_func_names, 735 regexp, 736 internal, 737 m_options.m_hardware, 738 m_options.m_move_to_nearest_code); 739 } break; 740 case eSetTypeException: { 741 Status precond_error; 742 bp_sp = target->CreateExceptionBreakpoint(m_options.m_exception_language, 743 m_options.m_catch_bp, 744 m_options.m_throw_bp, 745 internal, 746 &m_options 747 .m_exception_extra_args, 748 &precond_error); 749 if (precond_error.Fail()) { 750 result.AppendErrorWithFormat( 751 "Error setting extra exception arguments: %s", 752 precond_error.AsCString()); 753 target->RemoveBreakpointByID(bp_sp->GetID()); 754 result.SetStatus(eReturnStatusFailed); 755 return false; 756 } 757 } break; 758 case eSetTypeScripted: { 759 760 Status error; 761 bp_sp = target->CreateScriptedBreakpoint(m_options.m_python_class, 762 &(m_options.m_modules), 763 &(m_options.m_filenames), 764 false, 765 m_options.m_hardware, 766 m_options.m_extra_args_sp, 767 &error); 768 if (error.Fail()) { 769 result.AppendErrorWithFormat( 770 "Error setting extra exception arguments: %s", 771 error.AsCString()); 772 target->RemoveBreakpointByID(bp_sp->GetID()); 773 result.SetStatus(eReturnStatusFailed); 774 return false; 775 } 776 } break; 777 default: 778 break; 779 } 780 781 // Now set the various options that were passed in: 782 if (bp_sp) { 783 bp_sp->GetOptions()->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions()); 784 785 if (!m_options.m_breakpoint_names.empty()) { 786 Status name_error; 787 for (auto name : m_options.m_breakpoint_names) { 788 target->AddNameToBreakpoint(bp_sp, name.c_str(), name_error); 789 if (name_error.Fail()) { 790 result.AppendErrorWithFormat("Invalid breakpoint name: %s", 791 name.c_str()); 792 target->RemoveBreakpointByID(bp_sp->GetID()); 793 result.SetStatus(eReturnStatusFailed); 794 return false; 795 } 796 } 797 } 798 } 799 800 if (bp_sp) { 801 Stream &output_stream = result.GetOutputStream(); 802 const bool show_locations = false; 803 bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, 804 show_locations); 805 if (target == GetDebugger().GetDummyTarget()) 806 output_stream.Printf("Breakpoint set in dummy target, will get copied " 807 "into future targets.\n"); 808 else { 809 // Don't print out this warning for exception breakpoints. They can 810 // get set before the target is set, but we won't know how to actually 811 // set the breakpoint till we run. 812 if (bp_sp->GetNumLocations() == 0 && break_type != eSetTypeException) { 813 output_stream.Printf("WARNING: Unable to resolve breakpoint to any " 814 "actual locations.\n"); 815 } 816 } 817 result.SetStatus(eReturnStatusSuccessFinishResult); 818 } else if (!bp_sp) { 819 result.AppendError("Breakpoint creation failed: No breakpoint created."); 820 result.SetStatus(eReturnStatusFailed); 821 } 822 823 return result.Succeeded(); 824 } 825 826 private: 827 bool GetDefaultFile(Target *target, FileSpec &file, 828 CommandReturnObject &result) { 829 uint32_t default_line; 830 // First use the Source Manager's default file. Then use the current stack 831 // frame's file. 832 if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line)) { 833 StackFrame *cur_frame = m_exe_ctx.GetFramePtr(); 834 if (cur_frame == nullptr) { 835 result.AppendError( 836 "No selected frame to use to find the default file."); 837 result.SetStatus(eReturnStatusFailed); 838 return false; 839 } else if (!cur_frame->HasDebugInformation()) { 840 result.AppendError("Cannot use the selected frame to find the default " 841 "file, it has no debug info."); 842 result.SetStatus(eReturnStatusFailed); 843 return false; 844 } else { 845 const SymbolContext &sc = 846 cur_frame->GetSymbolContext(eSymbolContextLineEntry); 847 if (sc.line_entry.file) { 848 file = sc.line_entry.file; 849 } else { 850 result.AppendError("Can't find the file for the selected frame to " 851 "use as the default file."); 852 result.SetStatus(eReturnStatusFailed); 853 return false; 854 } 855 } 856 } 857 return true; 858 } 859 860 BreakpointOptionGroup m_bp_opts; 861 BreakpointDummyOptionGroup m_dummy_options; 862 CommandOptions m_options; 863 OptionGroupOptions m_all_options; 864 }; 865 866 // CommandObjectBreakpointModify 867 #pragma mark Modify 868 869 class CommandObjectBreakpointModify : public CommandObjectParsed { 870 public: 871 CommandObjectBreakpointModify(CommandInterpreter &interpreter) 872 : CommandObjectParsed(interpreter, "breakpoint modify", 873 "Modify the options on a breakpoint or set of " 874 "breakpoints in the executable. " 875 "If no breakpoint is specified, acts on the last " 876 "created breakpoint. " 877 "With the exception of -e, -d and -i, passing an " 878 "empty argument clears the modification.", 879 nullptr), 880 m_options() { 881 CommandArgumentEntry arg; 882 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 883 eArgTypeBreakpointIDRange); 884 // Add the entry for the first argument for this command to the object's 885 // arguments vector. 886 m_arguments.push_back(arg); 887 888 m_options.Append(&m_bp_opts, 889 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3, 890 LLDB_OPT_SET_ALL); 891 m_options.Append(&m_dummy_opts, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 892 m_options.Finalize(); 893 } 894 895 ~CommandObjectBreakpointModify() override = default; 896 897 Options *GetOptions() override { return &m_options; } 898 899 protected: 900 bool DoExecute(Args &command, CommandReturnObject &result) override { 901 Target *target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy); 902 if (target == nullptr) { 903 result.AppendError("Invalid target. No existing target or breakpoints."); 904 result.SetStatus(eReturnStatusFailed); 905 return false; 906 } 907 908 std::unique_lock<std::recursive_mutex> lock; 909 target->GetBreakpointList().GetListMutex(lock); 910 911 BreakpointIDList valid_bp_ids; 912 913 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 914 command, target, result, &valid_bp_ids, 915 BreakpointName::Permissions::PermissionKinds::disablePerm); 916 917 if (result.Succeeded()) { 918 const size_t count = valid_bp_ids.GetSize(); 919 for (size_t i = 0; i < count; ++i) { 920 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 921 922 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 923 Breakpoint *bp = 924 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 925 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 926 BreakpointLocation *location = 927 bp->FindLocationByID(cur_bp_id.GetLocationID()).get(); 928 if (location) 929 location->GetLocationOptions() 930 ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions()); 931 } else { 932 bp->GetOptions() 933 ->CopyOverSetOptions(m_bp_opts.GetBreakpointOptions()); 934 } 935 } 936 } 937 } 938 939 return result.Succeeded(); 940 } 941 942 private: 943 BreakpointOptionGroup m_bp_opts; 944 BreakpointDummyOptionGroup m_dummy_opts; 945 OptionGroupOptions m_options; 946 }; 947 948 // CommandObjectBreakpointEnable 949 #pragma mark Enable 950 951 class CommandObjectBreakpointEnable : public CommandObjectParsed { 952 public: 953 CommandObjectBreakpointEnable(CommandInterpreter &interpreter) 954 : CommandObjectParsed(interpreter, "enable", 955 "Enable the specified disabled breakpoint(s). If " 956 "no breakpoints are specified, enable all of them.", 957 nullptr) { 958 CommandArgumentEntry arg; 959 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 960 eArgTypeBreakpointIDRange); 961 // Add the entry for the first argument for this command to the object's 962 // arguments vector. 963 m_arguments.push_back(arg); 964 } 965 966 ~CommandObjectBreakpointEnable() override = default; 967 968 protected: 969 bool DoExecute(Args &command, CommandReturnObject &result) override { 970 Target *target = GetSelectedOrDummyTarget(); 971 if (target == nullptr) { 972 result.AppendError("Invalid target. No existing target or breakpoints."); 973 result.SetStatus(eReturnStatusFailed); 974 return false; 975 } 976 977 std::unique_lock<std::recursive_mutex> lock; 978 target->GetBreakpointList().GetListMutex(lock); 979 980 const BreakpointList &breakpoints = target->GetBreakpointList(); 981 982 size_t num_breakpoints = breakpoints.GetSize(); 983 984 if (num_breakpoints == 0) { 985 result.AppendError("No breakpoints exist to be enabled."); 986 result.SetStatus(eReturnStatusFailed); 987 return false; 988 } 989 990 if (command.empty()) { 991 // No breakpoint selected; enable all currently set breakpoints. 992 target->EnableAllowedBreakpoints(); 993 result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64 994 " breakpoints)\n", 995 (uint64_t)num_breakpoints); 996 result.SetStatus(eReturnStatusSuccessFinishNoResult); 997 } else { 998 // Particular breakpoint selected; enable that breakpoint. 999 BreakpointIDList valid_bp_ids; 1000 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1001 command, target, result, &valid_bp_ids, 1002 BreakpointName::Permissions::PermissionKinds::disablePerm); 1003 1004 if (result.Succeeded()) { 1005 int enable_count = 0; 1006 int loc_count = 0; 1007 const size_t count = valid_bp_ids.GetSize(); 1008 for (size_t i = 0; i < count; ++i) { 1009 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 1010 1011 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1012 Breakpoint *breakpoint = 1013 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1014 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1015 BreakpointLocation *location = 1016 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1017 if (location) { 1018 location->SetEnabled(true); 1019 ++loc_count; 1020 } 1021 } else { 1022 breakpoint->SetEnabled(true); 1023 ++enable_count; 1024 } 1025 } 1026 } 1027 result.AppendMessageWithFormat("%d breakpoints enabled.\n", 1028 enable_count + loc_count); 1029 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1030 } 1031 } 1032 1033 return result.Succeeded(); 1034 } 1035 }; 1036 1037 // CommandObjectBreakpointDisable 1038 #pragma mark Disable 1039 1040 class CommandObjectBreakpointDisable : public CommandObjectParsed { 1041 public: 1042 CommandObjectBreakpointDisable(CommandInterpreter &interpreter) 1043 : CommandObjectParsed( 1044 interpreter, "breakpoint disable", 1045 "Disable the specified breakpoint(s) without deleting " 1046 "them. If none are specified, disable all " 1047 "breakpoints.", 1048 nullptr) { 1049 SetHelpLong( 1050 "Disable the specified breakpoint(s) without deleting them. \ 1051 If none are specified, disable all breakpoints." 1052 R"( 1053 1054 )" 1055 "Note: disabling a breakpoint will cause none of its locations to be hit \ 1056 regardless of whether individual locations are enabled or disabled. After the sequence:" 1057 R"( 1058 1059 (lldb) break disable 1 1060 (lldb) break enable 1.1 1061 1062 execution will NOT stop at location 1.1. To achieve that, type: 1063 1064 (lldb) break disable 1.* 1065 (lldb) break enable 1.1 1066 1067 )" 1068 "The first command disables all locations for breakpoint 1, \ 1069 the second re-enables the first location."); 1070 1071 CommandArgumentEntry arg; 1072 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 1073 eArgTypeBreakpointIDRange); 1074 // Add the entry for the first argument for this command to the object's 1075 // arguments vector. 1076 m_arguments.push_back(arg); 1077 } 1078 1079 ~CommandObjectBreakpointDisable() override = default; 1080 1081 protected: 1082 bool DoExecute(Args &command, CommandReturnObject &result) override { 1083 Target *target = GetSelectedOrDummyTarget(); 1084 if (target == nullptr) { 1085 result.AppendError("Invalid target. No existing target or breakpoints."); 1086 result.SetStatus(eReturnStatusFailed); 1087 return false; 1088 } 1089 1090 std::unique_lock<std::recursive_mutex> lock; 1091 target->GetBreakpointList().GetListMutex(lock); 1092 1093 const BreakpointList &breakpoints = target->GetBreakpointList(); 1094 size_t num_breakpoints = breakpoints.GetSize(); 1095 1096 if (num_breakpoints == 0) { 1097 result.AppendError("No breakpoints exist to be disabled."); 1098 result.SetStatus(eReturnStatusFailed); 1099 return false; 1100 } 1101 1102 if (command.empty()) { 1103 // No breakpoint selected; disable all currently set breakpoints. 1104 target->DisableAllowedBreakpoints(); 1105 result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64 1106 " breakpoints)\n", 1107 (uint64_t)num_breakpoints); 1108 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1109 } else { 1110 // Particular breakpoint selected; disable that breakpoint. 1111 BreakpointIDList valid_bp_ids; 1112 1113 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1114 command, target, result, &valid_bp_ids, 1115 BreakpointName::Permissions::PermissionKinds::disablePerm); 1116 1117 if (result.Succeeded()) { 1118 int disable_count = 0; 1119 int loc_count = 0; 1120 const size_t count = valid_bp_ids.GetSize(); 1121 for (size_t i = 0; i < count; ++i) { 1122 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 1123 1124 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1125 Breakpoint *breakpoint = 1126 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1127 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1128 BreakpointLocation *location = 1129 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1130 if (location) { 1131 location->SetEnabled(false); 1132 ++loc_count; 1133 } 1134 } else { 1135 breakpoint->SetEnabled(false); 1136 ++disable_count; 1137 } 1138 } 1139 } 1140 result.AppendMessageWithFormat("%d breakpoints disabled.\n", 1141 disable_count + loc_count); 1142 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1143 } 1144 } 1145 1146 return result.Succeeded(); 1147 } 1148 }; 1149 1150 // CommandObjectBreakpointList 1151 1152 #pragma mark List::CommandOptions 1153 #define LLDB_OPTIONS_breakpoint_list 1154 #include "CommandOptions.inc" 1155 1156 #pragma mark List 1157 1158 class CommandObjectBreakpointList : public CommandObjectParsed { 1159 public: 1160 CommandObjectBreakpointList(CommandInterpreter &interpreter) 1161 : CommandObjectParsed( 1162 interpreter, "breakpoint list", 1163 "List some or all breakpoints at configurable levels of detail.", 1164 nullptr), 1165 m_options() { 1166 CommandArgumentEntry arg; 1167 CommandArgumentData bp_id_arg; 1168 1169 // Define the first (and only) variant of this arg. 1170 bp_id_arg.arg_type = eArgTypeBreakpointID; 1171 bp_id_arg.arg_repetition = eArgRepeatOptional; 1172 1173 // There is only one variant this argument could be; put it into the 1174 // argument entry. 1175 arg.push_back(bp_id_arg); 1176 1177 // Push the data for the first argument into the m_arguments vector. 1178 m_arguments.push_back(arg); 1179 } 1180 1181 ~CommandObjectBreakpointList() override = default; 1182 1183 Options *GetOptions() override { return &m_options; } 1184 1185 class CommandOptions : public Options { 1186 public: 1187 CommandOptions() 1188 : Options(), m_level(lldb::eDescriptionLevelBrief), m_use_dummy(false) { 1189 } 1190 1191 ~CommandOptions() override = default; 1192 1193 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1194 ExecutionContext *execution_context) override { 1195 Status error; 1196 const int short_option = m_getopt_table[option_idx].val; 1197 1198 switch (short_option) { 1199 case 'b': 1200 m_level = lldb::eDescriptionLevelBrief; 1201 break; 1202 case 'D': 1203 m_use_dummy = true; 1204 break; 1205 case 'f': 1206 m_level = lldb::eDescriptionLevelFull; 1207 break; 1208 case 'v': 1209 m_level = lldb::eDescriptionLevelVerbose; 1210 break; 1211 case 'i': 1212 m_internal = true; 1213 break; 1214 default: 1215 error.SetErrorStringWithFormat("unrecognized option '%c'", 1216 short_option); 1217 break; 1218 } 1219 1220 return error; 1221 } 1222 1223 void OptionParsingStarting(ExecutionContext *execution_context) override { 1224 m_level = lldb::eDescriptionLevelFull; 1225 m_internal = false; 1226 m_use_dummy = false; 1227 } 1228 1229 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1230 return llvm::makeArrayRef(g_breakpoint_list_options); 1231 } 1232 1233 // Instance variables to hold the values for command options. 1234 1235 lldb::DescriptionLevel m_level; 1236 1237 bool m_internal; 1238 bool m_use_dummy; 1239 }; 1240 1241 protected: 1242 bool DoExecute(Args &command, CommandReturnObject &result) override { 1243 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 1244 1245 if (target == nullptr) { 1246 result.AppendError("Invalid target. No current target or breakpoints."); 1247 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1248 return true; 1249 } 1250 1251 const BreakpointList &breakpoints = 1252 target->GetBreakpointList(m_options.m_internal); 1253 std::unique_lock<std::recursive_mutex> lock; 1254 target->GetBreakpointList(m_options.m_internal).GetListMutex(lock); 1255 1256 size_t num_breakpoints = breakpoints.GetSize(); 1257 1258 if (num_breakpoints == 0) { 1259 result.AppendMessage("No breakpoints currently set."); 1260 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1261 return true; 1262 } 1263 1264 Stream &output_stream = result.GetOutputStream(); 1265 1266 if (command.empty()) { 1267 // No breakpoint selected; show info about all currently set breakpoints. 1268 result.AppendMessage("Current breakpoints:"); 1269 for (size_t i = 0; i < num_breakpoints; ++i) { 1270 Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(i).get(); 1271 if (breakpoint->AllowList()) 1272 AddBreakpointDescription(&output_stream, breakpoint, 1273 m_options.m_level); 1274 } 1275 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1276 } else { 1277 // Particular breakpoints selected; show info about that breakpoint. 1278 BreakpointIDList valid_bp_ids; 1279 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1280 command, target, result, &valid_bp_ids, 1281 BreakpointName::Permissions::PermissionKinds::listPerm); 1282 1283 if (result.Succeeded()) { 1284 for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) { 1285 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 1286 Breakpoint *breakpoint = 1287 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1288 AddBreakpointDescription(&output_stream, breakpoint, 1289 m_options.m_level); 1290 } 1291 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1292 } else { 1293 result.AppendError("Invalid breakpoint ID."); 1294 result.SetStatus(eReturnStatusFailed); 1295 } 1296 } 1297 1298 return result.Succeeded(); 1299 } 1300 1301 private: 1302 CommandOptions m_options; 1303 }; 1304 1305 // CommandObjectBreakpointClear 1306 #pragma mark Clear::CommandOptions 1307 1308 #define LLDB_OPTIONS_breakpoint_clear 1309 #include "CommandOptions.inc" 1310 1311 #pragma mark Clear 1312 1313 class CommandObjectBreakpointClear : public CommandObjectParsed { 1314 public: 1315 enum BreakpointClearType { eClearTypeInvalid, eClearTypeFileAndLine }; 1316 1317 CommandObjectBreakpointClear(CommandInterpreter &interpreter) 1318 : CommandObjectParsed(interpreter, "breakpoint clear", 1319 "Delete or disable breakpoints matching the " 1320 "specified source file and line.", 1321 "breakpoint clear <cmd-options>"), 1322 m_options() {} 1323 1324 ~CommandObjectBreakpointClear() override = default; 1325 1326 Options *GetOptions() override { return &m_options; } 1327 1328 class CommandOptions : public Options { 1329 public: 1330 CommandOptions() : Options(), m_filename(), m_line_num(0) {} 1331 1332 ~CommandOptions() override = default; 1333 1334 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1335 ExecutionContext *execution_context) override { 1336 Status error; 1337 const int short_option = m_getopt_table[option_idx].val; 1338 1339 switch (short_option) { 1340 case 'f': 1341 m_filename.assign(option_arg); 1342 break; 1343 1344 case 'l': 1345 option_arg.getAsInteger(0, m_line_num); 1346 break; 1347 1348 default: 1349 error.SetErrorStringWithFormat("unrecognized option '%c'", 1350 short_option); 1351 break; 1352 } 1353 1354 return error; 1355 } 1356 1357 void OptionParsingStarting(ExecutionContext *execution_context) override { 1358 m_filename.clear(); 1359 m_line_num = 0; 1360 } 1361 1362 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1363 return llvm::makeArrayRef(g_breakpoint_clear_options); 1364 } 1365 1366 // Instance variables to hold the values for command options. 1367 1368 std::string m_filename; 1369 uint32_t m_line_num; 1370 }; 1371 1372 protected: 1373 bool DoExecute(Args &command, CommandReturnObject &result) override { 1374 Target *target = GetSelectedOrDummyTarget(); 1375 if (target == nullptr) { 1376 result.AppendError("Invalid target. No existing target or breakpoints."); 1377 result.SetStatus(eReturnStatusFailed); 1378 return false; 1379 } 1380 1381 // The following are the various types of breakpoints that could be 1382 // cleared: 1383 // 1). -f -l (clearing breakpoint by source location) 1384 1385 BreakpointClearType break_type = eClearTypeInvalid; 1386 1387 if (m_options.m_line_num != 0) 1388 break_type = eClearTypeFileAndLine; 1389 1390 std::unique_lock<std::recursive_mutex> lock; 1391 target->GetBreakpointList().GetListMutex(lock); 1392 1393 BreakpointList &breakpoints = target->GetBreakpointList(); 1394 size_t num_breakpoints = breakpoints.GetSize(); 1395 1396 // Early return if there's no breakpoint at all. 1397 if (num_breakpoints == 0) { 1398 result.AppendError("Breakpoint clear: No breakpoint cleared."); 1399 result.SetStatus(eReturnStatusFailed); 1400 return result.Succeeded(); 1401 } 1402 1403 // Find matching breakpoints and delete them. 1404 1405 // First create a copy of all the IDs. 1406 std::vector<break_id_t> BreakIDs; 1407 for (size_t i = 0; i < num_breakpoints; ++i) 1408 BreakIDs.push_back(breakpoints.GetBreakpointAtIndex(i)->GetID()); 1409 1410 int num_cleared = 0; 1411 StreamString ss; 1412 switch (break_type) { 1413 case eClearTypeFileAndLine: // Breakpoint by source position 1414 { 1415 const ConstString filename(m_options.m_filename.c_str()); 1416 BreakpointLocationCollection loc_coll; 1417 1418 for (size_t i = 0; i < num_breakpoints; ++i) { 1419 Breakpoint *bp = breakpoints.FindBreakpointByID(BreakIDs[i]).get(); 1420 1421 if (bp->GetMatchingFileLine(filename, m_options.m_line_num, loc_coll)) { 1422 // If the collection size is 0, it's a full match and we can just 1423 // remove the breakpoint. 1424 if (loc_coll.GetSize() == 0) { 1425 bp->GetDescription(&ss, lldb::eDescriptionLevelBrief); 1426 ss.EOL(); 1427 target->RemoveBreakpointByID(bp->GetID()); 1428 ++num_cleared; 1429 } 1430 } 1431 } 1432 } break; 1433 1434 default: 1435 break; 1436 } 1437 1438 if (num_cleared > 0) { 1439 Stream &output_stream = result.GetOutputStream(); 1440 output_stream.Printf("%d breakpoints cleared:\n", num_cleared); 1441 output_stream << ss.GetString(); 1442 output_stream.EOL(); 1443 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1444 } else { 1445 result.AppendError("Breakpoint clear: No breakpoint cleared."); 1446 result.SetStatus(eReturnStatusFailed); 1447 } 1448 1449 return result.Succeeded(); 1450 } 1451 1452 private: 1453 CommandOptions m_options; 1454 }; 1455 1456 // CommandObjectBreakpointDelete 1457 #define LLDB_OPTIONS_breakpoint_delete 1458 #include "CommandOptions.inc" 1459 1460 #pragma mark Delete 1461 1462 class CommandObjectBreakpointDelete : public CommandObjectParsed { 1463 public: 1464 CommandObjectBreakpointDelete(CommandInterpreter &interpreter) 1465 : CommandObjectParsed(interpreter, "breakpoint delete", 1466 "Delete the specified breakpoint(s). If no " 1467 "breakpoints are specified, delete them all.", 1468 nullptr), 1469 m_options() { 1470 CommandArgumentEntry arg; 1471 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 1472 eArgTypeBreakpointIDRange); 1473 // Add the entry for the first argument for this command to the object's 1474 // arguments vector. 1475 m_arguments.push_back(arg); 1476 } 1477 1478 ~CommandObjectBreakpointDelete() override = default; 1479 1480 Options *GetOptions() override { return &m_options; } 1481 1482 class CommandOptions : public Options { 1483 public: 1484 CommandOptions() : Options(), m_use_dummy(false), m_force(false) {} 1485 1486 ~CommandOptions() override = default; 1487 1488 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1489 ExecutionContext *execution_context) override { 1490 Status error; 1491 const int short_option = m_getopt_table[option_idx].val; 1492 1493 switch (short_option) { 1494 case 'f': 1495 m_force = true; 1496 break; 1497 1498 case 'D': 1499 m_use_dummy = true; 1500 break; 1501 1502 default: 1503 error.SetErrorStringWithFormat("unrecognized option '%c'", 1504 short_option); 1505 break; 1506 } 1507 1508 return error; 1509 } 1510 1511 void OptionParsingStarting(ExecutionContext *execution_context) override { 1512 m_use_dummy = false; 1513 m_force = false; 1514 } 1515 1516 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1517 return llvm::makeArrayRef(g_breakpoint_delete_options); 1518 } 1519 1520 // Instance variables to hold the values for command options. 1521 bool m_use_dummy; 1522 bool m_force; 1523 }; 1524 1525 protected: 1526 bool DoExecute(Args &command, CommandReturnObject &result) override { 1527 Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); 1528 1529 if (target == nullptr) { 1530 result.AppendError("Invalid target. No existing target or breakpoints."); 1531 result.SetStatus(eReturnStatusFailed); 1532 return false; 1533 } 1534 1535 std::unique_lock<std::recursive_mutex> lock; 1536 target->GetBreakpointList().GetListMutex(lock); 1537 1538 const BreakpointList &breakpoints = target->GetBreakpointList(); 1539 1540 size_t num_breakpoints = breakpoints.GetSize(); 1541 1542 if (num_breakpoints == 0) { 1543 result.AppendError("No breakpoints exist to be deleted."); 1544 result.SetStatus(eReturnStatusFailed); 1545 return false; 1546 } 1547 1548 if (command.empty()) { 1549 if (!m_options.m_force && 1550 !m_interpreter.Confirm( 1551 "About to delete all breakpoints, do you want to do that?", 1552 true)) { 1553 result.AppendMessage("Operation cancelled..."); 1554 } else { 1555 target->RemoveAllowedBreakpoints(); 1556 result.AppendMessageWithFormat( 1557 "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n", 1558 (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : ""); 1559 } 1560 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1561 } else { 1562 // Particular breakpoint selected; disable that breakpoint. 1563 BreakpointIDList valid_bp_ids; 1564 CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( 1565 command, target, result, &valid_bp_ids, 1566 BreakpointName::Permissions::PermissionKinds::deletePerm); 1567 1568 if (result.Succeeded()) { 1569 int delete_count = 0; 1570 int disable_count = 0; 1571 const size_t count = valid_bp_ids.GetSize(); 1572 for (size_t i = 0; i < count; ++i) { 1573 BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); 1574 1575 if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { 1576 if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { 1577 Breakpoint *breakpoint = 1578 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 1579 BreakpointLocation *location = 1580 breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); 1581 // It makes no sense to try to delete individual locations, so we 1582 // disable them instead. 1583 if (location) { 1584 location->SetEnabled(false); 1585 ++disable_count; 1586 } 1587 } else { 1588 target->RemoveBreakpointByID(cur_bp_id.GetBreakpointID()); 1589 ++delete_count; 1590 } 1591 } 1592 } 1593 result.AppendMessageWithFormat( 1594 "%d breakpoints deleted; %d breakpoint locations disabled.\n", 1595 delete_count, disable_count); 1596 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1597 } 1598 } 1599 return result.Succeeded(); 1600 } 1601 1602 private: 1603 CommandOptions m_options; 1604 }; 1605 1606 // CommandObjectBreakpointName 1607 #define LLDB_OPTIONS_breakpoint_name 1608 #include "CommandOptions.inc" 1609 1610 class BreakpointNameOptionGroup : public OptionGroup { 1611 public: 1612 BreakpointNameOptionGroup() 1613 : OptionGroup(), m_breakpoint(LLDB_INVALID_BREAK_ID), m_use_dummy(false) { 1614 } 1615 1616 ~BreakpointNameOptionGroup() override = default; 1617 1618 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1619 return llvm::makeArrayRef(g_breakpoint_name_options); 1620 } 1621 1622 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1623 ExecutionContext *execution_context) override { 1624 Status error; 1625 const int short_option = g_breakpoint_name_options[option_idx].short_option; 1626 1627 switch (short_option) { 1628 case 'N': 1629 if (BreakpointID::StringIsBreakpointName(option_arg, error) && 1630 error.Success()) 1631 m_name.SetValueFromString(option_arg); 1632 break; 1633 case 'B': 1634 if (m_breakpoint.SetValueFromString(option_arg).Fail()) 1635 error.SetErrorStringWithFormat( 1636 "unrecognized value \"%s\" for breakpoint", 1637 option_arg.str().c_str()); 1638 break; 1639 case 'D': 1640 if (m_use_dummy.SetValueFromString(option_arg).Fail()) 1641 error.SetErrorStringWithFormat( 1642 "unrecognized value \"%s\" for use-dummy", 1643 option_arg.str().c_str()); 1644 break; 1645 case 'H': 1646 m_help_string.SetValueFromString(option_arg); 1647 break; 1648 1649 default: 1650 error.SetErrorStringWithFormat("unrecognized short option '%c'", 1651 short_option); 1652 break; 1653 } 1654 return error; 1655 } 1656 1657 void OptionParsingStarting(ExecutionContext *execution_context) override { 1658 m_name.Clear(); 1659 m_breakpoint.Clear(); 1660 m_use_dummy.Clear(); 1661 m_use_dummy.SetDefaultValue(false); 1662 m_help_string.Clear(); 1663 } 1664 1665 OptionValueString m_name; 1666 OptionValueUInt64 m_breakpoint; 1667 OptionValueBoolean m_use_dummy; 1668 OptionValueString m_help_string; 1669 }; 1670 1671 #define LLDB_OPTIONS_breakpoint_access 1672 #include "CommandOptions.inc" 1673 1674 class BreakpointAccessOptionGroup : public OptionGroup { 1675 public: 1676 BreakpointAccessOptionGroup() : OptionGroup() {} 1677 1678 ~BreakpointAccessOptionGroup() override = default; 1679 1680 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1681 return llvm::makeArrayRef(g_breakpoint_access_options); 1682 } 1683 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1684 ExecutionContext *execution_context) override { 1685 Status error; 1686 const int short_option 1687 = g_breakpoint_access_options[option_idx].short_option; 1688 1689 switch (short_option) { 1690 case 'L': { 1691 bool value, success; 1692 value = OptionArgParser::ToBoolean(option_arg, false, &success); 1693 if (success) { 1694 m_permissions.SetAllowList(value); 1695 } else 1696 error.SetErrorStringWithFormat( 1697 "invalid boolean value '%s' passed for -L option", 1698 option_arg.str().c_str()); 1699 } break; 1700 case 'A': { 1701 bool value, success; 1702 value = OptionArgParser::ToBoolean(option_arg, false, &success); 1703 if (success) { 1704 m_permissions.SetAllowDisable(value); 1705 } else 1706 error.SetErrorStringWithFormat( 1707 "invalid boolean value '%s' passed for -L option", 1708 option_arg.str().c_str()); 1709 } break; 1710 case 'D': { 1711 bool value, success; 1712 value = OptionArgParser::ToBoolean(option_arg, false, &success); 1713 if (success) { 1714 m_permissions.SetAllowDelete(value); 1715 } else 1716 error.SetErrorStringWithFormat( 1717 "invalid boolean value '%s' passed for -L option", 1718 option_arg.str().c_str()); 1719 } break; 1720 1721 } 1722 1723 return error; 1724 } 1725 1726 void OptionParsingStarting(ExecutionContext *execution_context) override { 1727 } 1728 1729 const BreakpointName::Permissions &GetPermissions() const 1730 { 1731 return m_permissions; 1732 } 1733 BreakpointName::Permissions m_permissions; 1734 }; 1735 1736 class CommandObjectBreakpointNameConfigure : public CommandObjectParsed { 1737 public: 1738 CommandObjectBreakpointNameConfigure(CommandInterpreter &interpreter) 1739 : CommandObjectParsed( 1740 interpreter, "configure", "Configure the options for the breakpoint" 1741 " name provided. " 1742 "If you provide a breakpoint id, the options will be copied from " 1743 "the breakpoint, otherwise only the options specified will be set " 1744 "on the name.", 1745 "breakpoint name configure <command-options> " 1746 "<breakpoint-name-list>"), 1747 m_bp_opts(), m_option_group() { 1748 // Create the first variant for the first (and only) argument for this 1749 // command. 1750 CommandArgumentEntry arg1; 1751 CommandArgumentData id_arg; 1752 id_arg.arg_type = eArgTypeBreakpointName; 1753 id_arg.arg_repetition = eArgRepeatOptional; 1754 arg1.push_back(id_arg); 1755 m_arguments.push_back(arg1); 1756 1757 m_option_group.Append(&m_bp_opts, 1758 LLDB_OPT_SET_ALL, 1759 LLDB_OPT_SET_1); 1760 m_option_group.Append(&m_access_options, 1761 LLDB_OPT_SET_ALL, 1762 LLDB_OPT_SET_ALL); 1763 m_option_group.Append(&m_bp_id, 1764 LLDB_OPT_SET_2|LLDB_OPT_SET_4, 1765 LLDB_OPT_SET_ALL); 1766 m_option_group.Finalize(); 1767 } 1768 1769 ~CommandObjectBreakpointNameConfigure() override = default; 1770 1771 Options *GetOptions() override { return &m_option_group; } 1772 1773 protected: 1774 bool DoExecute(Args &command, CommandReturnObject &result) override { 1775 1776 const size_t argc = command.GetArgumentCount(); 1777 if (argc == 0) { 1778 result.AppendError("No names provided."); 1779 result.SetStatus(eReturnStatusFailed); 1780 return false; 1781 } 1782 1783 Target *target = 1784 GetSelectedOrDummyTarget(false); 1785 1786 if (target == nullptr) { 1787 result.AppendError("Invalid target. No existing target or breakpoints."); 1788 result.SetStatus(eReturnStatusFailed); 1789 return false; 1790 } 1791 1792 std::unique_lock<std::recursive_mutex> lock; 1793 target->GetBreakpointList().GetListMutex(lock); 1794 1795 // Make a pass through first to see that all the names are legal. 1796 for (auto &entry : command.entries()) { 1797 Status error; 1798 if (!BreakpointID::StringIsBreakpointName(entry.ref, error)) 1799 { 1800 result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s", 1801 entry.c_str(), error.AsCString()); 1802 result.SetStatus(eReturnStatusFailed); 1803 return false; 1804 } 1805 } 1806 // Now configure them, we already pre-checked the names so we don't need to 1807 // check the error: 1808 BreakpointSP bp_sp; 1809 if (m_bp_id.m_breakpoint.OptionWasSet()) 1810 { 1811 lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value(); 1812 bp_sp = target->GetBreakpointByID(bp_id); 1813 if (!bp_sp) 1814 { 1815 result.AppendErrorWithFormatv("Could not find specified breakpoint {0}", 1816 bp_id); 1817 result.SetStatus(eReturnStatusFailed); 1818 return false; 1819 } 1820 } 1821 1822 Status error; 1823 for (auto &entry : command.entries()) { 1824 ConstString name(entry.c_str()); 1825 BreakpointName *bp_name = target->FindBreakpointName(name, true, error); 1826 if (!bp_name) 1827 continue; 1828 if (m_bp_id.m_help_string.OptionWasSet()) 1829 bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str()); 1830 1831 if (bp_sp) 1832 target->ConfigureBreakpointName(*bp_name, 1833 *bp_sp->GetOptions(), 1834 m_access_options.GetPermissions()); 1835 else 1836 target->ConfigureBreakpointName(*bp_name, 1837 m_bp_opts.GetBreakpointOptions(), 1838 m_access_options.GetPermissions()); 1839 } 1840 return true; 1841 } 1842 1843 private: 1844 BreakpointNameOptionGroup m_bp_id; // Only using the id part of this. 1845 BreakpointOptionGroup m_bp_opts; 1846 BreakpointAccessOptionGroup m_access_options; 1847 OptionGroupOptions m_option_group; 1848 }; 1849 1850 class CommandObjectBreakpointNameAdd : public CommandObjectParsed { 1851 public: 1852 CommandObjectBreakpointNameAdd(CommandInterpreter &interpreter) 1853 : CommandObjectParsed( 1854 interpreter, "add", "Add a name to the breakpoints provided.", 1855 "breakpoint name add <command-options> <breakpoint-id-list>"), 1856 m_name_options(), m_option_group() { 1857 // Create the first variant for the first (and only) argument for this 1858 // command. 1859 CommandArgumentEntry arg1; 1860 CommandArgumentData id_arg; 1861 id_arg.arg_type = eArgTypeBreakpointID; 1862 id_arg.arg_repetition = eArgRepeatOptional; 1863 arg1.push_back(id_arg); 1864 m_arguments.push_back(arg1); 1865 1866 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 1867 m_option_group.Finalize(); 1868 } 1869 1870 ~CommandObjectBreakpointNameAdd() override = default; 1871 1872 Options *GetOptions() override { return &m_option_group; } 1873 1874 protected: 1875 bool DoExecute(Args &command, CommandReturnObject &result) override { 1876 if (!m_name_options.m_name.OptionWasSet()) { 1877 result.SetError("No name option provided."); 1878 return false; 1879 } 1880 1881 Target *target = 1882 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 1883 1884 if (target == nullptr) { 1885 result.AppendError("Invalid target. No existing target or breakpoints."); 1886 result.SetStatus(eReturnStatusFailed); 1887 return false; 1888 } 1889 1890 std::unique_lock<std::recursive_mutex> lock; 1891 target->GetBreakpointList().GetListMutex(lock); 1892 1893 const BreakpointList &breakpoints = target->GetBreakpointList(); 1894 1895 size_t num_breakpoints = breakpoints.GetSize(); 1896 if (num_breakpoints == 0) { 1897 result.SetError("No breakpoints, cannot add names."); 1898 result.SetStatus(eReturnStatusFailed); 1899 return false; 1900 } 1901 1902 // Particular breakpoint selected; disable that breakpoint. 1903 BreakpointIDList valid_bp_ids; 1904 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 1905 command, target, result, &valid_bp_ids, 1906 BreakpointName::Permissions::PermissionKinds::listPerm); 1907 1908 if (result.Succeeded()) { 1909 if (valid_bp_ids.GetSize() == 0) { 1910 result.SetError("No breakpoints specified, cannot add names."); 1911 result.SetStatus(eReturnStatusFailed); 1912 return false; 1913 } 1914 size_t num_valid_ids = valid_bp_ids.GetSize(); 1915 const char *bp_name = m_name_options.m_name.GetCurrentValue(); 1916 Status error; // This error reports illegal names, but we've already 1917 // checked that, so we don't need to check it again here. 1918 for (size_t index = 0; index < num_valid_ids; index++) { 1919 lldb::break_id_t bp_id = 1920 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); 1921 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); 1922 target->AddNameToBreakpoint(bp_sp, bp_name, error); 1923 } 1924 } 1925 1926 return true; 1927 } 1928 1929 private: 1930 BreakpointNameOptionGroup m_name_options; 1931 OptionGroupOptions m_option_group; 1932 }; 1933 1934 class CommandObjectBreakpointNameDelete : public CommandObjectParsed { 1935 public: 1936 CommandObjectBreakpointNameDelete(CommandInterpreter &interpreter) 1937 : CommandObjectParsed( 1938 interpreter, "delete", 1939 "Delete a name from the breakpoints provided.", 1940 "breakpoint name delete <command-options> <breakpoint-id-list>"), 1941 m_name_options(), m_option_group() { 1942 // Create the first variant for the first (and only) argument for this 1943 // command. 1944 CommandArgumentEntry arg1; 1945 CommandArgumentData id_arg; 1946 id_arg.arg_type = eArgTypeBreakpointID; 1947 id_arg.arg_repetition = eArgRepeatOptional; 1948 arg1.push_back(id_arg); 1949 m_arguments.push_back(arg1); 1950 1951 m_option_group.Append(&m_name_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); 1952 m_option_group.Finalize(); 1953 } 1954 1955 ~CommandObjectBreakpointNameDelete() override = default; 1956 1957 Options *GetOptions() override { return &m_option_group; } 1958 1959 protected: 1960 bool DoExecute(Args &command, CommandReturnObject &result) override { 1961 if (!m_name_options.m_name.OptionWasSet()) { 1962 result.SetError("No name option provided."); 1963 return false; 1964 } 1965 1966 Target *target = 1967 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 1968 1969 if (target == nullptr) { 1970 result.AppendError("Invalid target. No existing target or breakpoints."); 1971 result.SetStatus(eReturnStatusFailed); 1972 return false; 1973 } 1974 1975 std::unique_lock<std::recursive_mutex> lock; 1976 target->GetBreakpointList().GetListMutex(lock); 1977 1978 const BreakpointList &breakpoints = target->GetBreakpointList(); 1979 1980 size_t num_breakpoints = breakpoints.GetSize(); 1981 if (num_breakpoints == 0) { 1982 result.SetError("No breakpoints, cannot delete names."); 1983 result.SetStatus(eReturnStatusFailed); 1984 return false; 1985 } 1986 1987 // Particular breakpoint selected; disable that breakpoint. 1988 BreakpointIDList valid_bp_ids; 1989 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 1990 command, target, result, &valid_bp_ids, 1991 BreakpointName::Permissions::PermissionKinds::deletePerm); 1992 1993 if (result.Succeeded()) { 1994 if (valid_bp_ids.GetSize() == 0) { 1995 result.SetError("No breakpoints specified, cannot delete names."); 1996 result.SetStatus(eReturnStatusFailed); 1997 return false; 1998 } 1999 ConstString bp_name(m_name_options.m_name.GetCurrentValue()); 2000 size_t num_valid_ids = valid_bp_ids.GetSize(); 2001 for (size_t index = 0; index < num_valid_ids; index++) { 2002 lldb::break_id_t bp_id = 2003 valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); 2004 BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); 2005 target->RemoveNameFromBreakpoint(bp_sp, bp_name); 2006 } 2007 } 2008 2009 return true; 2010 } 2011 2012 private: 2013 BreakpointNameOptionGroup m_name_options; 2014 OptionGroupOptions m_option_group; 2015 }; 2016 2017 class CommandObjectBreakpointNameList : public CommandObjectParsed { 2018 public: 2019 CommandObjectBreakpointNameList(CommandInterpreter &interpreter) 2020 : CommandObjectParsed(interpreter, "list", 2021 "List either the names for a breakpoint or info " 2022 "about a given name. With no arguments, lists all " 2023 "names", 2024 "breakpoint name list <command-options>"), 2025 m_name_options(), m_option_group() { 2026 m_option_group.Append(&m_name_options, LLDB_OPT_SET_3, LLDB_OPT_SET_ALL); 2027 m_option_group.Finalize(); 2028 } 2029 2030 ~CommandObjectBreakpointNameList() override = default; 2031 2032 Options *GetOptions() override { return &m_option_group; } 2033 2034 protected: 2035 bool DoExecute(Args &command, CommandReturnObject &result) override { 2036 Target *target = 2037 GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); 2038 2039 if (target == nullptr) { 2040 result.AppendError("Invalid target. No existing target or breakpoints."); 2041 result.SetStatus(eReturnStatusFailed); 2042 return false; 2043 } 2044 2045 2046 std::vector<std::string> name_list; 2047 if (command.empty()) { 2048 target->GetBreakpointNames(name_list); 2049 } else { 2050 for (const Args::ArgEntry &arg : command) 2051 { 2052 name_list.push_back(arg.c_str()); 2053 } 2054 } 2055 2056 if (name_list.empty()) { 2057 result.AppendMessage("No breakpoint names found."); 2058 } else { 2059 for (const std::string &name_str : name_list) { 2060 const char *name = name_str.c_str(); 2061 // First print out the options for the name: 2062 Status error; 2063 BreakpointName *bp_name = target->FindBreakpointName(ConstString(name), 2064 false, 2065 error); 2066 if (bp_name) 2067 { 2068 StreamString s; 2069 result.AppendMessageWithFormat("Name: %s\n", name); 2070 if (bp_name->GetDescription(&s, eDescriptionLevelFull)) 2071 { 2072 result.AppendMessage(s.GetString()); 2073 } 2074 2075 std::unique_lock<std::recursive_mutex> lock; 2076 target->GetBreakpointList().GetListMutex(lock); 2077 2078 BreakpointList &breakpoints = target->GetBreakpointList(); 2079 bool any_set = false; 2080 for (BreakpointSP bp_sp : breakpoints.Breakpoints()) { 2081 if (bp_sp->MatchesName(name)) { 2082 StreamString s; 2083 any_set = true; 2084 bp_sp->GetDescription(&s, eDescriptionLevelBrief); 2085 s.EOL(); 2086 result.AppendMessage(s.GetString()); 2087 } 2088 } 2089 if (!any_set) 2090 result.AppendMessage("No breakpoints using this name."); 2091 } else { 2092 result.AppendMessageWithFormat("Name: %s not found.\n", name); 2093 } 2094 } 2095 } 2096 return true; 2097 } 2098 2099 private: 2100 BreakpointNameOptionGroup m_name_options; 2101 OptionGroupOptions m_option_group; 2102 }; 2103 2104 // CommandObjectBreakpointName 2105 class CommandObjectBreakpointName : public CommandObjectMultiword { 2106 public: 2107 CommandObjectBreakpointName(CommandInterpreter &interpreter) 2108 : CommandObjectMultiword( 2109 interpreter, "name", "Commands to manage name tags for breakpoints", 2110 "breakpoint name <subcommand> [<command-options>]") { 2111 CommandObjectSP add_command_object( 2112 new CommandObjectBreakpointNameAdd(interpreter)); 2113 CommandObjectSP delete_command_object( 2114 new CommandObjectBreakpointNameDelete(interpreter)); 2115 CommandObjectSP list_command_object( 2116 new CommandObjectBreakpointNameList(interpreter)); 2117 CommandObjectSP configure_command_object( 2118 new CommandObjectBreakpointNameConfigure(interpreter)); 2119 2120 LoadSubCommand("add", add_command_object); 2121 LoadSubCommand("delete", delete_command_object); 2122 LoadSubCommand("list", list_command_object); 2123 LoadSubCommand("configure", configure_command_object); 2124 } 2125 2126 ~CommandObjectBreakpointName() override = default; 2127 }; 2128 2129 // CommandObjectBreakpointRead 2130 #pragma mark Read::CommandOptions 2131 #define LLDB_OPTIONS_breakpoint_read 2132 #include "CommandOptions.inc" 2133 2134 #pragma mark Read 2135 2136 class CommandObjectBreakpointRead : public CommandObjectParsed { 2137 public: 2138 CommandObjectBreakpointRead(CommandInterpreter &interpreter) 2139 : CommandObjectParsed(interpreter, "breakpoint read", 2140 "Read and set the breakpoints previously saved to " 2141 "a file with \"breakpoint write\". ", 2142 nullptr), 2143 m_options() { 2144 CommandArgumentEntry arg; 2145 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 2146 eArgTypeBreakpointIDRange); 2147 // Add the entry for the first argument for this command to the object's 2148 // arguments vector. 2149 m_arguments.push_back(arg); 2150 } 2151 2152 ~CommandObjectBreakpointRead() override = default; 2153 2154 Options *GetOptions() override { return &m_options; } 2155 2156 class CommandOptions : public Options { 2157 public: 2158 CommandOptions() : Options() {} 2159 2160 ~CommandOptions() override = default; 2161 2162 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2163 ExecutionContext *execution_context) override { 2164 Status error; 2165 const int short_option = m_getopt_table[option_idx].val; 2166 2167 switch (short_option) { 2168 case 'f': 2169 m_filename.assign(option_arg); 2170 break; 2171 case 'N': { 2172 Status name_error; 2173 if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(option_arg), 2174 name_error)) { 2175 error.SetErrorStringWithFormat("Invalid breakpoint name: %s", 2176 name_error.AsCString()); 2177 } 2178 m_names.push_back(option_arg); 2179 break; 2180 } 2181 default: 2182 error.SetErrorStringWithFormat("unrecognized option '%c'", 2183 short_option); 2184 break; 2185 } 2186 2187 return error; 2188 } 2189 2190 void OptionParsingStarting(ExecutionContext *execution_context) override { 2191 m_filename.clear(); 2192 m_names.clear(); 2193 } 2194 2195 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 2196 return llvm::makeArrayRef(g_breakpoint_read_options); 2197 } 2198 2199 // Instance variables to hold the values for command options. 2200 2201 std::string m_filename; 2202 std::vector<std::string> m_names; 2203 }; 2204 2205 protected: 2206 bool DoExecute(Args &command, CommandReturnObject &result) override { 2207 Target *target = GetSelectedOrDummyTarget(); 2208 if (target == nullptr) { 2209 result.AppendError("Invalid target. No existing target or breakpoints."); 2210 result.SetStatus(eReturnStatusFailed); 2211 return false; 2212 } 2213 2214 std::unique_lock<std::recursive_mutex> lock; 2215 target->GetBreakpointList().GetListMutex(lock); 2216 2217 FileSpec input_spec(m_options.m_filename); 2218 FileSystem::Instance().Resolve(input_spec); 2219 BreakpointIDList new_bps; 2220 Status error = target->CreateBreakpointsFromFile( 2221 input_spec, m_options.m_names, new_bps); 2222 2223 if (!error.Success()) { 2224 result.AppendError(error.AsCString()); 2225 result.SetStatus(eReturnStatusFailed); 2226 return false; 2227 } 2228 2229 Stream &output_stream = result.GetOutputStream(); 2230 2231 size_t num_breakpoints = new_bps.GetSize(); 2232 if (num_breakpoints == 0) { 2233 result.AppendMessage("No breakpoints added."); 2234 } else { 2235 // No breakpoint selected; show info about all currently set breakpoints. 2236 result.AppendMessage("New breakpoints:"); 2237 for (size_t i = 0; i < num_breakpoints; ++i) { 2238 BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i); 2239 Breakpoint *bp = target->GetBreakpointList() 2240 .FindBreakpointByID(bp_id.GetBreakpointID()) 2241 .get(); 2242 if (bp) 2243 bp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, 2244 false); 2245 } 2246 } 2247 return result.Succeeded(); 2248 } 2249 2250 private: 2251 CommandOptions m_options; 2252 }; 2253 2254 // CommandObjectBreakpointWrite 2255 #pragma mark Write::CommandOptions 2256 #define LLDB_OPTIONS_breakpoint_write 2257 #include "CommandOptions.inc" 2258 2259 #pragma mark Write 2260 class CommandObjectBreakpointWrite : public CommandObjectParsed { 2261 public: 2262 CommandObjectBreakpointWrite(CommandInterpreter &interpreter) 2263 : CommandObjectParsed(interpreter, "breakpoint write", 2264 "Write the breakpoints listed to a file that can " 2265 "be read in with \"breakpoint read\". " 2266 "If given no arguments, writes all breakpoints.", 2267 nullptr), 2268 m_options() { 2269 CommandArgumentEntry arg; 2270 CommandObject::AddIDsArgumentData(arg, eArgTypeBreakpointID, 2271 eArgTypeBreakpointIDRange); 2272 // Add the entry for the first argument for this command to the object's 2273 // arguments vector. 2274 m_arguments.push_back(arg); 2275 } 2276 2277 ~CommandObjectBreakpointWrite() override = default; 2278 2279 Options *GetOptions() override { return &m_options; } 2280 2281 class CommandOptions : public Options { 2282 public: 2283 CommandOptions() : Options() {} 2284 2285 ~CommandOptions() override = default; 2286 2287 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 2288 ExecutionContext *execution_context) override { 2289 Status error; 2290 const int short_option = m_getopt_table[option_idx].val; 2291 2292 switch (short_option) { 2293 case 'f': 2294 m_filename.assign(option_arg); 2295 break; 2296 case 'a': 2297 m_append = true; 2298 break; 2299 default: 2300 error.SetErrorStringWithFormat("unrecognized option '%c'", 2301 short_option); 2302 break; 2303 } 2304 2305 return error; 2306 } 2307 2308 void OptionParsingStarting(ExecutionContext *execution_context) override { 2309 m_filename.clear(); 2310 m_append = false; 2311 } 2312 2313 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 2314 return llvm::makeArrayRef(g_breakpoint_write_options); 2315 } 2316 2317 // Instance variables to hold the values for command options. 2318 2319 std::string m_filename; 2320 bool m_append = false; 2321 }; 2322 2323 protected: 2324 bool DoExecute(Args &command, CommandReturnObject &result) override { 2325 Target *target = GetSelectedOrDummyTarget(); 2326 if (target == nullptr) { 2327 result.AppendError("Invalid target. No existing target or breakpoints."); 2328 result.SetStatus(eReturnStatusFailed); 2329 return false; 2330 } 2331 2332 std::unique_lock<std::recursive_mutex> lock; 2333 target->GetBreakpointList().GetListMutex(lock); 2334 2335 BreakpointIDList valid_bp_ids; 2336 if (!command.empty()) { 2337 CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( 2338 command, target, result, &valid_bp_ids, 2339 BreakpointName::Permissions::PermissionKinds::listPerm); 2340 2341 if (!result.Succeeded()) { 2342 result.SetStatus(eReturnStatusFailed); 2343 return false; 2344 } 2345 } 2346 FileSpec file_spec(m_options.m_filename); 2347 FileSystem::Instance().Resolve(file_spec); 2348 Status error = target->SerializeBreakpointsToFile(file_spec, valid_bp_ids, 2349 m_options.m_append); 2350 if (!error.Success()) { 2351 result.AppendErrorWithFormat("error serializing breakpoints: %s.", 2352 error.AsCString()); 2353 result.SetStatus(eReturnStatusFailed); 2354 } 2355 return result.Succeeded(); 2356 } 2357 2358 private: 2359 CommandOptions m_options; 2360 }; 2361 2362 // CommandObjectMultiwordBreakpoint 2363 #pragma mark MultiwordBreakpoint 2364 2365 CommandObjectMultiwordBreakpoint::CommandObjectMultiwordBreakpoint( 2366 CommandInterpreter &interpreter) 2367 : CommandObjectMultiword( 2368 interpreter, "breakpoint", 2369 "Commands for operating on breakpoints (see 'help b' for shorthand.)", 2370 "breakpoint <subcommand> [<command-options>]") { 2371 CommandObjectSP list_command_object( 2372 new CommandObjectBreakpointList(interpreter)); 2373 CommandObjectSP enable_command_object( 2374 new CommandObjectBreakpointEnable(interpreter)); 2375 CommandObjectSP disable_command_object( 2376 new CommandObjectBreakpointDisable(interpreter)); 2377 CommandObjectSP clear_command_object( 2378 new CommandObjectBreakpointClear(interpreter)); 2379 CommandObjectSP delete_command_object( 2380 new CommandObjectBreakpointDelete(interpreter)); 2381 CommandObjectSP set_command_object( 2382 new CommandObjectBreakpointSet(interpreter)); 2383 CommandObjectSP command_command_object( 2384 new CommandObjectBreakpointCommand(interpreter)); 2385 CommandObjectSP modify_command_object( 2386 new CommandObjectBreakpointModify(interpreter)); 2387 CommandObjectSP name_command_object( 2388 new CommandObjectBreakpointName(interpreter)); 2389 CommandObjectSP write_command_object( 2390 new CommandObjectBreakpointWrite(interpreter)); 2391 CommandObjectSP read_command_object( 2392 new CommandObjectBreakpointRead(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 write_command_object->SetCommandName("breakpoint write"); 2404 read_command_object->SetCommandName("breakpoint read"); 2405 2406 LoadSubCommand("list", list_command_object); 2407 LoadSubCommand("enable", enable_command_object); 2408 LoadSubCommand("disable", disable_command_object); 2409 LoadSubCommand("clear", clear_command_object); 2410 LoadSubCommand("delete", delete_command_object); 2411 LoadSubCommand("set", set_command_object); 2412 LoadSubCommand("command", command_command_object); 2413 LoadSubCommand("modify", modify_command_object); 2414 LoadSubCommand("name", name_command_object); 2415 LoadSubCommand("write", write_command_object); 2416 LoadSubCommand("read", read_command_object); 2417 } 2418 2419 CommandObjectMultiwordBreakpoint::~CommandObjectMultiwordBreakpoint() = default; 2420 2421 void CommandObjectMultiwordBreakpoint::VerifyIDs(Args &args, Target *target, 2422 bool allow_locations, 2423 CommandReturnObject &result, 2424 BreakpointIDList *valid_ids, 2425 BreakpointName::Permissions 2426 ::PermissionKinds 2427 purpose) { 2428 // args can be strings representing 1). integers (for breakpoint ids) 2429 // 2). the full breakpoint & location 2430 // canonical representation 2431 // 3). the word "to" or a hyphen, 2432 // representing a range (in which case there 2433 // had *better* be an entry both before & 2434 // after of one of the first two types. 2435 // 4). A breakpoint name 2436 // If args is empty, we will use the last created breakpoint (if there is 2437 // one.) 2438 2439 Args temp_args; 2440 2441 if (args.empty()) { 2442 if (target->GetLastCreatedBreakpoint()) { 2443 valid_ids->AddBreakpointID(BreakpointID( 2444 target->GetLastCreatedBreakpoint()->GetID(), LLDB_INVALID_BREAK_ID)); 2445 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2446 } else { 2447 result.AppendError( 2448 "No breakpoint specified and no last created breakpoint."); 2449 result.SetStatus(eReturnStatusFailed); 2450 } 2451 return; 2452 } 2453 2454 // Create a new Args variable to use; copy any non-breakpoint-id-ranges stuff 2455 // directly from the old ARGS to the new TEMP_ARGS. Do not copy breakpoint 2456 // id range strings over; instead generate a list of strings for all the 2457 // breakpoint ids in the range, and shove all of those breakpoint id strings 2458 // into TEMP_ARGS. 2459 2460 BreakpointIDList::FindAndReplaceIDRanges(args, target, allow_locations, 2461 purpose, result, temp_args); 2462 2463 // NOW, convert the list of breakpoint id strings in TEMP_ARGS into an actual 2464 // BreakpointIDList: 2465 2466 valid_ids->InsertStringArray(temp_args.GetArgumentArrayRef(), result); 2467 2468 // At this point, all of the breakpoint ids that the user passed in have 2469 // been converted to breakpoint IDs and put into valid_ids. 2470 2471 if (result.Succeeded()) { 2472 // Now that we've converted everything from args into a list of breakpoint 2473 // ids, go through our tentative list of breakpoint id's and verify that 2474 // they correspond to valid/currently set breakpoints. 2475 2476 const size_t count = valid_ids->GetSize(); 2477 for (size_t i = 0; i < count; ++i) { 2478 BreakpointID cur_bp_id = valid_ids->GetBreakpointIDAtIndex(i); 2479 Breakpoint *breakpoint = 2480 target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); 2481 if (breakpoint != nullptr) { 2482 const size_t num_locations = breakpoint->GetNumLocations(); 2483 if (static_cast<size_t>(cur_bp_id.GetLocationID()) > num_locations) { 2484 StreamString id_str; 2485 BreakpointID::GetCanonicalReference( 2486 &id_str, cur_bp_id.GetBreakpointID(), cur_bp_id.GetLocationID()); 2487 i = valid_ids->GetSize() + 1; 2488 result.AppendErrorWithFormat( 2489 "'%s' is not a currently valid breakpoint/location id.\n", 2490 id_str.GetData()); 2491 result.SetStatus(eReturnStatusFailed); 2492 } 2493 } else { 2494 i = valid_ids->GetSize() + 1; 2495 result.AppendErrorWithFormat( 2496 "'%d' is not a currently valid breakpoint ID.\n", 2497 cur_bp_id.GetBreakpointID()); 2498 result.SetStatus(eReturnStatusFailed); 2499 } 2500 } 2501 } 2502 } 2503