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