brintos

brintos / llvm-project-archived public Read only

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