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