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