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