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