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