brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.4 KiB · 8c46b39 Raw
295 lines · cpp
1//===-- BreakpointIDList.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 "lldb/lldb-enumerations.h"10#include "lldb/Breakpoint/BreakpointIDList.h"11 12#include "lldb/Breakpoint/Breakpoint.h"13#include "lldb/Breakpoint/BreakpointLocation.h"14#include "lldb/Target/Target.h"15#include "lldb/Utility/Args.h"16#include "lldb/Utility/StreamString.h"17 18#include "llvm/ADT/STLExtras.h"19#include "llvm/ADT/StringRef.h"20 21using namespace lldb;22using namespace lldb_private;23 24// class BreakpointIDList25 26BreakpointIDList::BreakpointIDList() : m_breakpoint_ids() {}27 28BreakpointIDList::~BreakpointIDList() = default;29 30size_t BreakpointIDList::GetSize() const { return m_breakpoint_ids.size(); }31 32BreakpointID BreakpointIDList::GetBreakpointIDAtIndex(size_t index) const {33  return ((index < m_breakpoint_ids.size()) ? m_breakpoint_ids[index]34                                            : BreakpointID());35}36 37bool BreakpointIDList::RemoveBreakpointIDAtIndex(size_t index) {38  if (index >= m_breakpoint_ids.size())39    return false;40 41  m_breakpoint_ids.erase(m_breakpoint_ids.begin() + index);42  return true;43}44 45void BreakpointIDList::Clear() { m_breakpoint_ids.clear(); }46 47bool BreakpointIDList::AddBreakpointID(BreakpointID bp_id) {48  m_breakpoint_ids.push_back(bp_id);49 50  return true; // We don't do any verification in this function, so always51               // return true.52}53 54bool BreakpointIDList::Contains(BreakpointID bp_id) const {55  return llvm::is_contained(m_breakpoint_ids, bp_id);56}57 58//  This function takes OLD_ARGS, which is usually the result of breaking the59//  command string arguments into60//  an array of space-separated strings, and searches through the arguments for61//  any breakpoint ID range specifiers.62//  Any string in the array that is not part of an ID range specifier is copied63//  directly into NEW_ARGS.  If any64//  ID range specifiers are found, the range is interpreted and a list of65//  canonical breakpoint IDs corresponding to66//  all the current breakpoints and locations in the range are added to67//  NEW_ARGS.  When this function is done,68//  NEW_ARGS should be a copy of OLD_ARGS, with and ID range specifiers replaced69//  by the members of the range.70 71llvm::Error BreakpointIDList::FindAndReplaceIDRanges(72    Args &old_args, Target *target, bool allow_locations,73    BreakpointName::Permissions ::PermissionKinds purpose, Args &new_args) {74  llvm::StringRef range_from;75  llvm::StringRef range_to;76  llvm::StringRef current_arg;77  std::set<std::string> names_found;78 79  for (size_t i = 0; i < old_args.size(); ++i) {80    bool is_range = false;81 82    current_arg = old_args[i].ref();83    if (!allow_locations && current_arg.contains('.')) {84      new_args.Clear();85      return llvm::createStringError(86          llvm::inconvertibleErrorCode(),87          "Breakpoint locations not allowed, saw location: %s.",88          current_arg.str().c_str());89    }90 91    Status error;92 93    std::tie(range_from, range_to) =94        BreakpointIDList::SplitIDRangeExpression(current_arg);95    if (!range_from.empty() && !range_to.empty()) {96      is_range = true;97    } else if (BreakpointID::StringIsBreakpointName(current_arg, error)) {98      if (!error.Success()) {99        new_args.Clear();100        return llvm::createStringError(llvm::inconvertibleErrorCode(),101                                       error.AsCString());102      }103      names_found.insert(std::string(current_arg));104    } else if ((i + 2 < old_args.size()) &&105               BreakpointID::IsRangeIdentifier(old_args[i + 1].ref()) &&106               BreakpointID::IsValidIDExpression(current_arg) &&107               BreakpointID::IsValidIDExpression(old_args[i + 2].ref())) {108      range_from = current_arg;109      range_to = old_args[i + 2].ref();110      is_range = true;111      i = i + 2;112    } else {113      // See if user has specified id.*114      llvm::StringRef tmp_str = old_args[i].ref();115      auto [prefix, suffix] = tmp_str.split('.');116      if (suffix == "*" && BreakpointID::IsValidIDExpression(prefix)) {117 118        BreakpointSP breakpoint_sp;119        auto bp_id = BreakpointID::ParseCanonicalReference(prefix);120        if (bp_id)121          breakpoint_sp = target->GetBreakpointByID(bp_id->GetBreakpointID());122        if (!breakpoint_sp) {123          new_args.Clear();124          return llvm::createStringError(llvm::inconvertibleErrorCode(),125                                         "'%d' is not a valid breakpoint ID.\n",126                                         bp_id->GetBreakpointID());127        }128        const size_t num_locations = breakpoint_sp->GetNumLocations();129        for (size_t j = 0; j < num_locations; ++j) {130          BreakpointLocation *bp_loc =131              breakpoint_sp->GetLocationAtIndex(j).get();132          StreamString canonical_id_str;133          BreakpointID::GetCanonicalReference(134              &canonical_id_str, bp_id->GetBreakpointID(), bp_loc->GetID());135          new_args.AppendArgument(canonical_id_str.GetString());136        }137      }138    }139 140    if (!is_range) {141      new_args.AppendArgument(current_arg);142      continue;143    }144 145    auto start_bp = BreakpointID::ParseCanonicalReference(range_from);146    auto end_bp = BreakpointID::ParseCanonicalReference(range_to);147 148    if (!start_bp ||149        !target->GetBreakpointByID(start_bp->GetBreakpointID())) {150      new_args.Clear();151      return llvm::createStringError(llvm::inconvertibleErrorCode(),152                                     "'%s' is not a valid breakpoint ID.\n",153                                     range_from.str().c_str());154    }155 156    if (!end_bp ||157        !target->GetBreakpointByID(end_bp->GetBreakpointID())) {158      new_args.Clear();159      return llvm::createStringError(llvm::inconvertibleErrorCode(),160                                     "'%s' is not a valid breakpoint ID.\n",161                                     range_to.str().c_str());162    }163    break_id_t start_bp_id = start_bp->GetBreakpointID();164    break_id_t start_loc_id = start_bp->GetLocationID();165    break_id_t end_bp_id = end_bp->GetBreakpointID();166    break_id_t end_loc_id = end_bp->GetLocationID();167    if (((start_loc_id == LLDB_INVALID_BREAK_ID) &&168            (end_loc_id != LLDB_INVALID_BREAK_ID)) ||169        ((start_loc_id != LLDB_INVALID_BREAK_ID) &&170         (end_loc_id == LLDB_INVALID_BREAK_ID))) {171      new_args.Clear();172      return llvm::createStringError(llvm::inconvertibleErrorCode(),173                                     "Invalid breakpoint id range:  Either "174                                     "both ends of range must specify"175                                     " a breakpoint location, or neither can "176                                     "specify a breakpoint location.");177    }178 179    // We have valid range starting & ending breakpoint IDs.  Go through all180    // the breakpoints in the target and find all the breakpoints that fit into181    // this range, and add them to new_args.182 183    // Next check to see if we have location id's.  If so, make sure the184    // start_bp_id and end_bp_id are for the same breakpoint; otherwise we have185    // an illegal range: breakpoint id ranges that specify bp locations are NOT186    // allowed to cross major bp id numbers.187 188    if ((start_loc_id != LLDB_INVALID_BREAK_ID) ||189        (end_loc_id != LLDB_INVALID_BREAK_ID)) {190      if (start_bp_id != end_bp_id) {191        new_args.Clear();192        return llvm::createStringError(193            llvm::inconvertibleErrorCode(),194            "Invalid range: Ranges that specify particular breakpoint "195            "locations"196            " must be within the same major breakpoint; you specified two"197            " different major breakpoints, %d and %d.\n",198            start_bp_id, end_bp_id);199      }200    }201 202    const BreakpointList &breakpoints = target->GetBreakpointList();203    const size_t num_breakpoints = breakpoints.GetSize();204    for (size_t j = 0; j < num_breakpoints; ++j) {205      Breakpoint *breakpoint = breakpoints.GetBreakpointAtIndex(j).get();206      break_id_t cur_bp_id = breakpoint->GetID();207 208      if ((cur_bp_id < start_bp_id) || (cur_bp_id > end_bp_id))209        continue;210 211      const size_t num_locations = breakpoint->GetNumLocations();212 213      if ((cur_bp_id == start_bp_id) &&214          (start_loc_id != LLDB_INVALID_BREAK_ID)) {215        for (size_t k = 0; k < num_locations; ++k) {216          BreakpointLocation *bp_loc = breakpoint->GetLocationAtIndex(k).get();217          if ((bp_loc->GetID() >= start_loc_id) &&218              (bp_loc->GetID() <= end_loc_id)) {219            StreamString canonical_id_str;220            BreakpointID::GetCanonicalReference(&canonical_id_str, cur_bp_id,221                                                bp_loc->GetID());222            new_args.AppendArgument(canonical_id_str.GetString());223          }224        }225      } else if ((cur_bp_id == end_bp_id) &&226                 (end_loc_id != LLDB_INVALID_BREAK_ID)) {227        for (size_t k = 0; k < num_locations; ++k) {228          BreakpointLocation *bp_loc = breakpoint->GetLocationAtIndex(k).get();229          if (bp_loc->GetID() <= end_loc_id) {230            StreamString canonical_id_str;231            BreakpointID::GetCanonicalReference(&canonical_id_str, cur_bp_id,232                                                bp_loc->GetID());233            new_args.AppendArgument(canonical_id_str.GetString());234          }235        }236      } else {237        StreamString canonical_id_str;238        BreakpointID::GetCanonicalReference(&canonical_id_str, cur_bp_id,239                                            LLDB_INVALID_BREAK_ID);240        new_args.AppendArgument(canonical_id_str.GetString());241      }242    }243  }244 245  // Okay, now see if we found any names, and if we did, add them:246  if (target && !names_found.empty()) {247    Status error;248    // Remove any names that aren't visible for this purpose:249    auto iter = names_found.begin();250    while (iter != names_found.end()) {251      BreakpointName *bp_name = target->FindBreakpointName(ConstString(*iter),252                                                           true,253                                                           error);254      if (bp_name && !bp_name->GetPermission(purpose))255        iter = names_found.erase(iter);256      else257        iter++;258    }259 260    if (!names_found.empty()) {261      for (BreakpointSP bkpt_sp : target->GetBreakpointList().Breakpoints()) {262        for (const std::string &name : names_found) {263          if (bkpt_sp->MatchesName(name.c_str())) {264            StreamString canonical_id_str;265            BreakpointID::GetCanonicalReference(266                &canonical_id_str, bkpt_sp->GetID(), LLDB_INVALID_BREAK_ID);267            new_args.AppendArgument(canonical_id_str.GetString());268          }269        }270      }271    }272  }273  return llvm::Error::success();274}275 276std::pair<llvm::StringRef, llvm::StringRef>277BreakpointIDList::SplitIDRangeExpression(llvm::StringRef in_string) {278  for (auto specifier_str : BreakpointID::GetRangeSpecifiers()) {279    size_t idx = in_string.find(specifier_str);280    if (idx == llvm::StringRef::npos)281      continue;282    llvm::StringRef right1 = in_string.drop_front(idx);283 284    llvm::StringRef from = in_string.take_front(idx);285    llvm::StringRef to = right1.drop_front(specifier_str.size());286 287    if (BreakpointID::IsValidIDExpression(from) &&288        BreakpointID::IsValidIDExpression(to)) {289      return std::make_pair(from, to);290    }291  }292 293  return std::pair<llvm::StringRef, llvm::StringRef>();294}295