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