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