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