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