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