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