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