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