brintos

brintos / llvm-project-archived public Read only

0
0
Text · 44.4 KiB · 201d8d2 Raw
1270 lines · cpp
1//===-- Breakpoint.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 "llvm/Support/Casting.h"10 11#include "lldb/Breakpoint/Breakpoint.h"12#include "lldb/Breakpoint/BreakpointLocation.h"13#include "lldb/Breakpoint/BreakpointLocationCollection.h"14#include "lldb/Breakpoint/BreakpointPrecondition.h"15#include "lldb/Breakpoint/BreakpointResolver.h"16#include "lldb/Breakpoint/BreakpointResolverFileLine.h"17#include "lldb/Core/Address.h"18#include "lldb/Core/Debugger.h"19#include "lldb/Core/Module.h"20#include "lldb/Core/ModuleList.h"21#include "lldb/Core/SearchFilter.h"22#include "lldb/Core/Section.h"23#include "lldb/Symbol/CompileUnit.h"24#include "lldb/Symbol/Function.h"25#include "lldb/Symbol/Symbol.h"26#include "lldb/Symbol/SymbolContext.h"27#include "lldb/Target/SectionLoadList.h"28#include "lldb/Target/Target.h"29#include "lldb/Target/ThreadSpec.h"30#include "lldb/Utility/AnsiTerminal.h"31#include "lldb/Utility/LLDBLog.h"32#include "lldb/Utility/Log.h"33#include "lldb/Utility/Stream.h"34#include "lldb/Utility/StreamString.h"35 36#include <memory>37 38using namespace lldb;39using namespace lldb_private;40using namespace llvm;41 42const char *Breakpoint::g_option_names[static_cast<uint32_t>(43    Breakpoint::OptionNames::LastOptionName)]{"Names", "Hardware"};44 45// Breakpoint constructor46Breakpoint::Breakpoint(Target &target, SearchFilterSP &filter_sp,47                       BreakpointResolverSP &resolver_sp, bool hardware,48                       bool resolve_indirect_symbols)49    : m_hardware(hardware), m_target(target), m_filter_sp(filter_sp),50      m_resolver_sp(resolver_sp), m_options(true), m_locations(*this),51      m_resolve_indirect_symbols(resolve_indirect_symbols), m_hit_counter() {}52 53Breakpoint::Breakpoint(Target &new_target, const Breakpoint &source_bp)54    : m_hardware(source_bp.m_hardware), m_target(new_target),55      m_name_list(source_bp.m_name_list), m_options(source_bp.m_options),56      m_locations(*this),57      m_resolve_indirect_symbols(source_bp.m_resolve_indirect_symbols),58      m_hit_counter() {}59 60// Destructor61Breakpoint::~Breakpoint() {62  for (BreakpointLocationSP location_sp : m_locations.BreakpointLocations())63    location_sp->SetInvalid();64  for (BreakpointLocationSP location_sp :65       m_facade_locations.BreakpointLocations())66    location_sp->SetInvalid();67}68 69BreakpointSP Breakpoint::CopyFromBreakpoint(TargetSP new_target,70                                            const Breakpoint &bp_to_copy_from) {71  if (!new_target)72    return BreakpointSP();73 74  BreakpointSP bp(new Breakpoint(*new_target, bp_to_copy_from));75  // Now go through and copy the filter & resolver:76  bp->m_resolver_sp = bp_to_copy_from.m_resolver_sp->CopyForBreakpoint(bp);77  bp->m_filter_sp = bp_to_copy_from.m_filter_sp->CreateCopy(new_target);78  return bp;79}80 81// Serialization82StructuredData::ObjectSP Breakpoint::SerializeToStructuredData() {83  // Serialize the resolver:84  StructuredData::DictionarySP breakpoint_dict_sp(85      new StructuredData::Dictionary());86  StructuredData::DictionarySP breakpoint_contents_sp(87      new StructuredData::Dictionary());88 89  if (!m_name_list.empty()) {90    StructuredData::ArraySP names_array_sp(new StructuredData::Array());91    for (auto name : m_name_list) {92      names_array_sp->AddItem(std::make_shared<StructuredData::String>(name));93    }94    breakpoint_contents_sp->AddItem(Breakpoint::GetKey(OptionNames::Names),95                                    names_array_sp);96  }97 98  breakpoint_contents_sp->AddBooleanItem(99      Breakpoint::GetKey(OptionNames::Hardware), m_hardware);100 101  StructuredData::ObjectSP resolver_dict_sp(102      m_resolver_sp->SerializeToStructuredData());103  if (!resolver_dict_sp)104    return StructuredData::ObjectSP();105 106  breakpoint_contents_sp->AddItem(BreakpointResolver::GetSerializationKey(),107                                  resolver_dict_sp);108 109  StructuredData::ObjectSP filter_dict_sp(110      m_filter_sp->SerializeToStructuredData());111  if (!filter_dict_sp)112    return StructuredData::ObjectSP();113 114  breakpoint_contents_sp->AddItem(SearchFilter::GetSerializationKey(),115                                  filter_dict_sp);116 117  StructuredData::ObjectSP options_dict_sp(118      m_options.SerializeToStructuredData());119  if (!options_dict_sp)120    return StructuredData::ObjectSP();121 122  breakpoint_contents_sp->AddItem(BreakpointOptions::GetSerializationKey(),123                                  options_dict_sp);124 125  breakpoint_dict_sp->AddItem(GetSerializationKey(), breakpoint_contents_sp);126  return breakpoint_dict_sp;127}128 129lldb::BreakpointSP Breakpoint::CreateFromStructuredData(130    TargetSP target_sp, StructuredData::ObjectSP &object_data, Status &error) {131  BreakpointSP result_sp;132  if (!target_sp)133    return result_sp;134 135  StructuredData::Dictionary *breakpoint_dict = object_data->GetAsDictionary();136 137  if (!breakpoint_dict || !breakpoint_dict->IsValid()) {138    error = Status::FromErrorString(139        "Can't deserialize from an invalid data object.");140    return result_sp;141  }142 143  StructuredData::Dictionary *resolver_dict;144  bool success = breakpoint_dict->GetValueForKeyAsDictionary(145      BreakpointResolver::GetSerializationKey(), resolver_dict);146  if (!success) {147    error = Status::FromErrorString(148        "Breakpoint data missing toplevel resolver key");149    return result_sp;150  }151 152  Status create_error;153  BreakpointResolverSP resolver_sp =154      BreakpointResolver::CreateFromStructuredData(*resolver_dict,155                                                   create_error);156  if (create_error.Fail()) {157    error = Status::FromErrorStringWithFormatv(158        "Error creating breakpoint resolver from data: {0}.", create_error);159    return result_sp;160  }161 162  StructuredData::Dictionary *filter_dict;163  success = breakpoint_dict->GetValueForKeyAsDictionary(164      SearchFilter::GetSerializationKey(), filter_dict);165  SearchFilterSP filter_sp;166  if (!success)167    filter_sp =168        std::make_shared<SearchFilterForUnconstrainedSearches>(target_sp);169  else {170    filter_sp = SearchFilter::CreateFromStructuredData(target_sp, *filter_dict,171                                                       create_error);172    if (create_error.Fail()) {173      error = Status::FromErrorStringWithFormat(174          "Error creating breakpoint filter from data: %s.",175          create_error.AsCString());176      return result_sp;177    }178  }179 180  std::unique_ptr<BreakpointOptions> options_up;181  StructuredData::Dictionary *options_dict;182  Target &target = *target_sp;183  success = breakpoint_dict->GetValueForKeyAsDictionary(184      BreakpointOptions::GetSerializationKey(), options_dict);185  if (success) {186    options_up = BreakpointOptions::CreateFromStructuredData(187        target, *options_dict, create_error);188    if (create_error.Fail()) {189      error = Status::FromErrorStringWithFormat(190          "Error creating breakpoint options from data: %s.",191          create_error.AsCString());192      return result_sp;193    }194  }195 196  bool hardware = false;197  success = breakpoint_dict->GetValueForKeyAsBoolean(198      Breakpoint::GetKey(OptionNames::Hardware), hardware);199 200  result_sp =201      target.CreateBreakpoint(filter_sp, resolver_sp, false, hardware, true);202 203  if (result_sp && options_up) {204    result_sp->m_options = *options_up;205  }206 207  StructuredData::Array *names_array;208  success = breakpoint_dict->GetValueForKeyAsArray(209      Breakpoint::GetKey(OptionNames::Names), names_array);210  if (success && names_array) {211    size_t num_names = names_array->GetSize();212    for (size_t i = 0; i < num_names; i++) {213      if (std::optional<llvm::StringRef> maybe_name =214              names_array->GetItemAtIndexAsString(i))215        target.AddNameToBreakpoint(result_sp, *maybe_name, error);216    }217  }218 219  return result_sp;220}221 222bool Breakpoint::SerializedBreakpointMatchesNames(223    StructuredData::ObjectSP &bkpt_object_sp, std::vector<std::string> &names) {224  if (!bkpt_object_sp)225    return false;226 227  StructuredData::Dictionary *bkpt_dict = bkpt_object_sp->GetAsDictionary();228  if (!bkpt_dict)229    return false;230 231  if (names.empty())232    return true;233 234  StructuredData::Array *names_array;235 236  bool success =237      bkpt_dict->GetValueForKeyAsArray(GetKey(OptionNames::Names), names_array);238  // If there are no names, it can't match these names;239  if (!success)240    return false;241 242  size_t num_names = names_array->GetSize();243 244  for (size_t i = 0; i < num_names; i++) {245    std::optional<llvm::StringRef> maybe_name =246        names_array->GetItemAtIndexAsString(i);247    if (maybe_name && llvm::is_contained(names, *maybe_name))248      return true;249  }250  return false;251}252 253const lldb::TargetSP Breakpoint::GetTargetSP() {254  return m_target.shared_from_this();255}256 257bool Breakpoint::IsInternal() const { return LLDB_BREAK_ID_IS_INTERNAL(m_bid); }258 259llvm::Error Breakpoint::SetIsHardware(bool is_hardware) {260  if (is_hardware == m_hardware)261    return llvm::Error::success();262 263  Log *log = GetLog(LLDBLog::Breakpoints);264 265  // Disable all non-hardware breakpoint locations.266  std::vector<BreakpointLocationSP> locations;267  for (BreakpointLocationSP location_sp : m_locations.BreakpointLocations()) {268    if (!location_sp || !location_sp->IsEnabled())269      continue;270 271    lldb::BreakpointSiteSP breakpoint_site_sp =272        location_sp->GetBreakpointSite();273    if (!breakpoint_site_sp ||274        breakpoint_site_sp->GetType() == BreakpointSite::eHardware)275      continue;276 277    locations.push_back(location_sp);278    if (llvm::Error error = location_sp->SetEnabled(false))279      LLDB_LOG_ERROR(log, std::move(error),280                     "Failed to disable breakpoint location: {0}");281  }282 283  // Toggle the hardware mode.284  m_hardware = is_hardware;285 286  // Re-enable all breakpoint locations.287  size_t num_failures = 0;288  for (BreakpointLocationSP location_sp : locations) {289    if (llvm::Error error = location_sp->SetEnabled(true)) {290      LLDB_LOG_ERROR(log, std::move(error),291                     "Failed to re-enable breakpoint location: {0}");292      num_failures++;293    }294  }295 296  if (num_failures != 0)297    return llvm::createStringError(298        "%ull out of %ull breakpoint locations left disabled because they "299        "couldn't be converted to hardware",300        num_failures, locations.size());301 302  return llvm::Error::success();303}304 305BreakpointLocationSP Breakpoint::AddLocation(const Address &addr,306                                             bool *new_location) {307  return m_locations.AddLocation(addr, m_resolve_indirect_symbols,308                                 new_location);309}310 311BreakpointLocationSP Breakpoint::AddFacadeLocation() {312  size_t next_id = m_facade_locations.GetSize() + 1;313  BreakpointLocationSP break_loc_sp =314      std::make_shared<BreakpointLocation>(next_id, *this);315  break_loc_sp->m_is_facade = true;316  m_facade_locations.Add(break_loc_sp);317  return break_loc_sp;318}319 320BreakpointLocationSP321Breakpoint::GetFacadeLocationByID(lldb::break_id_t loc_id) {322  return m_facade_locations.GetByIndex(loc_id - 1);323}324 325BreakpointLocationSP Breakpoint::FindLocationByAddress(const Address &addr) {326  return m_locations.FindByAddress(addr);327}328 329break_id_t Breakpoint::FindLocationIDByAddress(const Address &addr) {330  return m_locations.FindIDByAddress(addr);331}332 333BreakpointLocationSP Breakpoint::FindLocationByID(break_id_t bp_loc_id,334                                                  bool use_facade) {335  if (use_facade && m_facade_locations.GetSize())336    return GetFacadeLocationByID(bp_loc_id);337  return m_locations.FindByID(bp_loc_id);338}339 340BreakpointLocationSP Breakpoint::GetLocationAtIndex(size_t index,341                                                    bool use_facade) {342  if (use_facade && m_facade_locations.GetSize() > 0)343    return m_facade_locations.GetByIndex(index);344  return m_locations.GetByIndex(index);345}346 347void Breakpoint::RemoveInvalidLocations(const ArchSpec &arch) {348  // FIXME: Should we ask the scripted resolver whether any of its facade349  // locations are invalid?350  m_locations.RemoveInvalidLocations(arch);351}352 353// For each of the overall options we need to decide how they propagate to the354// location options.  This will determine the precedence of options on the355// breakpoint vs. its locations.356 357// Disable at the breakpoint level should override the location settings. That358// way you can conveniently turn off a whole breakpoint without messing up the359// individual settings.360 361void Breakpoint::SetEnabled(bool enable) {362  if (enable == m_options.IsEnabled())363    return;364 365  m_options.SetEnabled(enable);366  if (enable)367    m_locations.ResolveAllBreakpointSites();368  else369    m_locations.ClearAllBreakpointSites();370 371  SendBreakpointChangedEvent(enable ? eBreakpointEventTypeEnabled372                                    : eBreakpointEventTypeDisabled);373}374 375bool Breakpoint::IsEnabled() { return m_options.IsEnabled(); }376 377void Breakpoint::SetIgnoreCount(uint32_t n) {378  if (m_options.GetIgnoreCount() == n)379    return;380 381  m_options.SetIgnoreCount(n);382  SendBreakpointChangedEvent(eBreakpointEventTypeIgnoreChanged);383}384 385void Breakpoint::DecrementIgnoreCount() {386  uint32_t ignore = m_options.GetIgnoreCount();387  if (ignore != 0)388    m_options.SetIgnoreCount(ignore - 1);389}390 391uint32_t Breakpoint::GetIgnoreCount() const {392  return m_options.GetIgnoreCount();393}394 395uint32_t Breakpoint::GetHitCount() const { return m_hit_counter.GetValue(); }396 397void Breakpoint::ResetHitCount() {398  m_hit_counter.Reset();399  m_locations.ResetHitCount();400}401 402bool Breakpoint::IsOneShot() const { return m_options.IsOneShot(); }403 404void Breakpoint::SetOneShot(bool one_shot) { m_options.SetOneShot(one_shot); }405 406bool Breakpoint::IsAutoContinue() const { return m_options.IsAutoContinue(); }407 408void Breakpoint::SetAutoContinue(bool auto_continue) {409  m_options.SetAutoContinue(auto_continue);410}411 412void Breakpoint::SetThreadID(lldb::tid_t thread_id) {413  if (m_options.GetThreadSpec()->GetTID() == thread_id)414    return;415 416  m_options.GetThreadSpec()->SetTID(thread_id);417  SendBreakpointChangedEvent(eBreakpointEventTypeThreadChanged);418}419 420lldb::tid_t Breakpoint::GetThreadID() const {421  if (m_options.GetThreadSpecNoCreate() == nullptr)422    return LLDB_INVALID_THREAD_ID;423  return m_options.GetThreadSpecNoCreate()->GetTID();424}425 426void Breakpoint::SetThreadIndex(uint32_t index) {427  if (m_options.GetThreadSpec()->GetIndex() == index)428    return;429 430  m_options.GetThreadSpec()->SetIndex(index);431  SendBreakpointChangedEvent(eBreakpointEventTypeThreadChanged);432}433 434uint32_t Breakpoint::GetThreadIndex() const {435  if (m_options.GetThreadSpecNoCreate() == nullptr)436    return 0;437  return m_options.GetThreadSpecNoCreate()->GetIndex();438}439 440void Breakpoint::SetThreadName(const char *thread_name) {441  if (m_options.GetThreadSpec()->GetName() != nullptr &&442      ::strcmp(m_options.GetThreadSpec()->GetName(), thread_name) == 0)443    return;444 445  m_options.GetThreadSpec()->SetName(thread_name);446  SendBreakpointChangedEvent(eBreakpointEventTypeThreadChanged);447}448 449const char *Breakpoint::GetThreadName() const {450  if (m_options.GetThreadSpecNoCreate() == nullptr)451    return nullptr;452  return m_options.GetThreadSpecNoCreate()->GetName();453}454 455void Breakpoint::SetQueueName(const char *queue_name) {456  if (m_options.GetThreadSpec()->GetQueueName() != nullptr &&457      ::strcmp(m_options.GetThreadSpec()->GetQueueName(), queue_name) == 0)458    return;459 460  m_options.GetThreadSpec()->SetQueueName(queue_name);461  SendBreakpointChangedEvent(eBreakpointEventTypeThreadChanged);462}463 464const char *Breakpoint::GetQueueName() const {465  if (m_options.GetThreadSpecNoCreate() == nullptr)466    return nullptr;467  return m_options.GetThreadSpecNoCreate()->GetQueueName();468}469 470void Breakpoint::SetCondition(StopCondition condition) {471  m_options.SetCondition(std::move(condition));472  SendBreakpointChangedEvent(eBreakpointEventTypeConditionChanged);473}474 475const StopCondition &Breakpoint::GetCondition() const {476  return m_options.GetCondition();477}478 479// This function is used when "baton" doesn't need to be freed480void Breakpoint::SetCallback(BreakpointHitCallback callback, void *baton,481                             bool is_synchronous) {482  // The default "Baton" class will keep a copy of "baton" and won't free or483  // delete it when it goes out of scope.484  m_options.SetCallback(callback, std::make_shared<UntypedBaton>(baton),485                        is_synchronous);486 487  SendBreakpointChangedEvent(eBreakpointEventTypeCommandChanged);488}489 490// This function is used when a baton needs to be freed and therefore is491// contained in a "Baton" subclass.492void Breakpoint::SetCallback(BreakpointHitCallback callback,493                             const BatonSP &callback_baton_sp,494                             bool is_synchronous) {495  m_options.SetCallback(callback, callback_baton_sp, is_synchronous);496}497 498void Breakpoint::ClearCallback() { m_options.ClearCallback(); }499 500bool Breakpoint::InvokeCallback(StoppointCallbackContext *context,501                                break_id_t bp_loc_id) {502  return m_options.InvokeCallback(context, GetID(), bp_loc_id);503}504 505BreakpointOptions &Breakpoint::GetOptions() { return m_options; }506 507const BreakpointOptions &Breakpoint::GetOptions() const { return m_options; }508 509void Breakpoint::ResolveBreakpoint() {510  if (m_resolver_sp) {511    ElapsedTime elapsed(m_resolve_time);512    m_resolver_sp->ResolveBreakpoint(*m_filter_sp);513  }514}515 516void Breakpoint::ResolveBreakpointInModules(517    ModuleList &module_list, BreakpointLocationCollection &new_locations) {518  ElapsedTime elapsed(m_resolve_time);519  m_locations.StartRecordingNewLocations(new_locations);520 521  m_resolver_sp->ResolveBreakpointInModules(*m_filter_sp, module_list);522 523  m_locations.StopRecordingNewLocations();524}525 526void Breakpoint::ResolveBreakpointInModules(ModuleList &module_list,527                                            bool send_event) {528  if (m_resolver_sp) {529    // If this is not an internal breakpoint, set up to record the new530    // locations, then dispatch an event with the new locations.531    if (!IsInternal() && send_event) {532      std::shared_ptr<BreakpointEventData> new_locations_event =533          std::make_shared<BreakpointEventData>(534              eBreakpointEventTypeLocationsAdded, shared_from_this());535      ResolveBreakpointInModules(536          module_list, new_locations_event->GetBreakpointLocationCollection());537      if (new_locations_event->GetBreakpointLocationCollection().GetSize() != 0)538        SendBreakpointChangedEvent(new_locations_event);539    } else {540      ElapsedTime elapsed(m_resolve_time);541      m_resolver_sp->ResolveBreakpointInModules(*m_filter_sp, module_list);542    }543  }544}545 546void Breakpoint::ClearAllBreakpointSites() {547  m_locations.ClearAllBreakpointSites();548}549 550// ModulesChanged: Pass in a list of new modules, and551 552void Breakpoint::ModulesChanged(ModuleList &module_list, bool load,553                                bool delete_locations) {554  Log *log = GetLog(LLDBLog::Breakpoints);555  LLDB_LOGF(log,556            "Breakpoint::ModulesChanged: num_modules: %zu load: %i "557            "delete_locations: %i\n",558            module_list.GetSize(), load, delete_locations);559 560  if (load) {561    // The logic for handling new modules is:562    // 1) If the filter rejects this module, then skip it. 2) Run through the563    // current location list and if there are any locations564    //    for that module, we mark the module as "seen" and we don't try to565    //    re-resolve566    //    breakpoint locations for that module.567    //    However, we do add breakpoint sites to these locations if needed.568    // 3) If we don't see this module in our breakpoint location list, call569    // ResolveInModules.570 571    ModuleList new_modules; // We'll stuff the "unseen" modules in this list,572                            // and then resolve573    // them after the locations pass.  Have to do it this way because resolving574    // breakpoints will add new locations potentially.575 576    for (ModuleSP module_sp : module_list.Modules()) {577      bool seen = false;578      if (!m_filter_sp->ModulePasses(module_sp))579        continue;580 581      BreakpointLocationCollection locations_with_no_section;582      for (BreakpointLocationSP break_loc_sp :583           m_locations.BreakpointLocations()) {584 585        // If the section for this location was deleted, that means it's Module586        // has gone away but somebody forgot to tell us. Let's clean it up587        // here.588        Address section_addr(break_loc_sp->GetAddress());589        if (section_addr.SectionWasDeleted()) {590          locations_with_no_section.Add(break_loc_sp);591          continue;592        }593 594        if (!break_loc_sp->IsEnabled())595          continue;596 597        SectionSP section_sp(section_addr.GetSection());598 599        // If we don't have a Section, that means this location is a raw600        // address that we haven't resolved to a section yet.  So we'll have to601        // look in all the new modules to resolve this location. Otherwise, if602        // it was set in this module, re-resolve it here.603        if (section_sp && section_sp->GetModule() == module_sp) {604          if (!seen)605            seen = true;606 607          if (llvm::Error error = break_loc_sp->ResolveBreakpointSite()) {608            LLDB_LOG_ERROR(log, std::move(error),609                           "could not set breakpoint site for "610                           "breakpoint location {1} of breakpoint {2}: {0}",611                           break_loc_sp->GetID(), GetID());612          }613        }614      }615 616      size_t num_to_delete = locations_with_no_section.GetSize();617 618      for (size_t i = 0; i < num_to_delete; i++)619        m_locations.RemoveLocation(locations_with_no_section.GetByIndex(i));620 621      if (!seen)622        new_modules.AppendIfNeeded(module_sp);623    }624 625    if (new_modules.GetSize() > 0) {626      ResolveBreakpointInModules(new_modules);627    }628  } else {629    // Go through the currently set locations and if any have breakpoints in630    // the module list, then remove their breakpoint sites, and their locations631    // if asked to.632 633    std::shared_ptr<BreakpointEventData> removed_locations_event;634    if (!IsInternal())635      removed_locations_event = std::make_shared<BreakpointEventData>(636          eBreakpointEventTypeLocationsRemoved, shared_from_this());637 638    for (ModuleSP module_sp : module_list.Modules()) {639      if (m_filter_sp->ModulePasses(module_sp)) {640        size_t loc_idx = 0;641        size_t num_locations = m_locations.GetSize();642        BreakpointLocationCollection locations_to_remove;643        for (loc_idx = 0; loc_idx < num_locations; loc_idx++) {644          BreakpointLocationSP break_loc_sp(m_locations.GetByIndex(loc_idx));645          SectionSP section_sp(break_loc_sp->GetAddress().GetSection());646          if (section_sp && section_sp->GetModule() == module_sp) {647            // Remove this breakpoint since the shared library is unloaded, but648            // keep the breakpoint location around so we always get complete649            // hit count and breakpoint lifetime info650            if (llvm::Error error = break_loc_sp->ClearBreakpointSite())651              LLDB_LOG_ERROR(log, std::move(error),652                             "Failed to clear breakpoint locations on library "653                             "unload: {0}");654            if (removed_locations_event) {655              removed_locations_event->GetBreakpointLocationCollection().Add(656                  break_loc_sp);657            }658            if (delete_locations)659              locations_to_remove.Add(break_loc_sp);660          }661        }662 663        if (delete_locations) {664          size_t num_locations_to_remove = locations_to_remove.GetSize();665          for (loc_idx = 0; loc_idx < num_locations_to_remove; loc_idx++)666            m_locations.RemoveLocation(locations_to_remove.GetByIndex(loc_idx));667        }668      }669    }670    SendBreakpointChangedEvent(removed_locations_event);671  }672}673 674static bool SymbolContextsMightBeEquivalent(SymbolContext &old_sc,675                                            SymbolContext &new_sc) {676  bool equivalent_scs = false;677 678  if (old_sc.module_sp.get() == new_sc.module_sp.get()) {679    // If these come from the same module, we can directly compare the680    // pointers:681    if (old_sc.comp_unit && new_sc.comp_unit &&682        (old_sc.comp_unit == new_sc.comp_unit)) {683      if (old_sc.function && new_sc.function &&684          (old_sc.function == new_sc.function)) {685        equivalent_scs = true;686      }687    } else if (old_sc.symbol && new_sc.symbol &&688               (old_sc.symbol == new_sc.symbol)) {689      equivalent_scs = true;690    }691  } else {692    // Otherwise we will compare by name...693    if (old_sc.comp_unit && new_sc.comp_unit) {694      if (old_sc.comp_unit->GetPrimaryFile() ==695          new_sc.comp_unit->GetPrimaryFile()) {696        // Now check the functions:697        if (old_sc.function && new_sc.function &&698            (old_sc.function->GetName() == new_sc.function->GetName())) {699          equivalent_scs = true;700        }701      }702    } else if (old_sc.symbol && new_sc.symbol) {703      if (Mangled::Compare(old_sc.symbol->GetMangled(),704                           new_sc.symbol->GetMangled()) == 0) {705        equivalent_scs = true;706      }707    }708  }709  return equivalent_scs;710}711 712void Breakpoint::ModuleReplaced(ModuleSP old_module_sp,713                                ModuleSP new_module_sp) {714  Log *log = GetLog(LLDBLog::Breakpoints);715  LLDB_LOGF(log, "Breakpoint::ModulesReplaced for %s\n",716            old_module_sp->GetSpecificationDescription().c_str());717  // First find all the locations that are in the old module718 719  BreakpointLocationCollection old_break_locs;720  for (BreakpointLocationSP break_loc_sp : m_locations.BreakpointLocations()) {721    SectionSP section_sp = break_loc_sp->GetAddress().GetSection();722    if (section_sp && section_sp->GetModule() == old_module_sp) {723      old_break_locs.Add(break_loc_sp);724    }725  }726 727  size_t num_old_locations = old_break_locs.GetSize();728 729  if (num_old_locations == 0) {730    // There were no locations in the old module, so we just need to check if731    // there were any in the new module.732    ModuleList temp_list;733    temp_list.Append(new_module_sp);734    ResolveBreakpointInModules(temp_list);735  } else {736    // First search the new module for locations. Then compare this with the737    // old list, copy over locations that "look the same" Then delete the old738    // locations. Finally remember to post the creation event.739    //740    // Two locations are the same if they have the same comp unit & function741    // (by name) and there are the same number of locations in the old function742    // as in the new one.743 744    ModuleList temp_list;745    temp_list.Append(new_module_sp);746    BreakpointLocationCollection new_break_locs;747    ResolveBreakpointInModules(temp_list, new_break_locs);748    BreakpointLocationCollection locations_to_remove;749    BreakpointLocationCollection locations_to_announce;750 751    size_t num_new_locations = new_break_locs.GetSize();752 753    if (num_new_locations > 0) {754      // Break out the case of one location -> one location since that's the755      // most common one, and there's no need to build up the structures needed756      // for the merge in that case.757      if (num_new_locations == 1 && num_old_locations == 1) {758        bool equivalent_locations = false;759        SymbolContext old_sc, new_sc;760        // The only way the old and new location can be equivalent is if they761        // have the same amount of information:762        BreakpointLocationSP old_loc_sp = old_break_locs.GetByIndex(0);763        BreakpointLocationSP new_loc_sp = new_break_locs.GetByIndex(0);764 765        if (old_loc_sp->GetAddress().CalculateSymbolContext(&old_sc) ==766            new_loc_sp->GetAddress().CalculateSymbolContext(&new_sc)) {767          equivalent_locations =768              SymbolContextsMightBeEquivalent(old_sc, new_sc);769        }770 771        if (equivalent_locations) {772          m_locations.SwapLocation(old_loc_sp, new_loc_sp);773        } else {774          locations_to_remove.Add(old_loc_sp);775          locations_to_announce.Add(new_loc_sp);776        }777      } else {778        // We don't want to have to keep computing the SymbolContexts for these779        // addresses over and over, so lets get them up front:780 781        typedef std::map<lldb::break_id_t, SymbolContext> IDToSCMap;782        IDToSCMap old_sc_map;783        for (size_t idx = 0; idx < num_old_locations; idx++) {784          SymbolContext sc;785          BreakpointLocationSP bp_loc_sp = old_break_locs.GetByIndex(idx);786          lldb::break_id_t loc_id = bp_loc_sp->GetID();787          bp_loc_sp->GetAddress().CalculateSymbolContext(&old_sc_map[loc_id]);788        }789 790        std::map<lldb::break_id_t, SymbolContext> new_sc_map;791        for (size_t idx = 0; idx < num_new_locations; idx++) {792          SymbolContext sc;793          BreakpointLocationSP bp_loc_sp = new_break_locs.GetByIndex(idx);794          lldb::break_id_t loc_id = bp_loc_sp->GetID();795          bp_loc_sp->GetAddress().CalculateSymbolContext(&new_sc_map[loc_id]);796        }797        // Take an element from the old Symbol Contexts798        while (old_sc_map.size() > 0) {799          lldb::break_id_t old_id = old_sc_map.begin()->first;800          SymbolContext &old_sc = old_sc_map.begin()->second;801 802          // Count the number of entries equivalent to this SC for the old803          // list:804          std::vector<lldb::break_id_t> old_id_vec;805          old_id_vec.push_back(old_id);806 807          IDToSCMap::iterator tmp_iter;808          for (tmp_iter = ++old_sc_map.begin(); tmp_iter != old_sc_map.end();809               tmp_iter++) {810            if (SymbolContextsMightBeEquivalent(old_sc, tmp_iter->second))811              old_id_vec.push_back(tmp_iter->first);812          }813 814          // Now find all the equivalent locations in the new list.815          std::vector<lldb::break_id_t> new_id_vec;816          for (tmp_iter = new_sc_map.begin(); tmp_iter != new_sc_map.end();817               tmp_iter++) {818            if (SymbolContextsMightBeEquivalent(old_sc, tmp_iter->second))819              new_id_vec.push_back(tmp_iter->first);820          }821 822          // Alright, if we have the same number of potentially equivalent823          // locations in the old and new modules, we'll just map them one to824          // one in ascending ID order (assuming the resolver's order would825          // match the equivalent ones. Otherwise, we'll dump all the old ones,826          // and just take the new ones, erasing the elements from both maps as827          // we go.828 829          if (old_id_vec.size() == new_id_vec.size()) {830            llvm::sort(old_id_vec);831            llvm::sort(new_id_vec);832            size_t num_elements = old_id_vec.size();833            for (size_t idx = 0; idx < num_elements; idx++) {834              BreakpointLocationSP old_loc_sp =835                  old_break_locs.FindByIDPair(GetID(), old_id_vec[idx]);836              BreakpointLocationSP new_loc_sp =837                  new_break_locs.FindByIDPair(GetID(), new_id_vec[idx]);838              m_locations.SwapLocation(old_loc_sp, new_loc_sp);839              old_sc_map.erase(old_id_vec[idx]);840              new_sc_map.erase(new_id_vec[idx]);841            }842          } else {843            for (lldb::break_id_t old_id : old_id_vec) {844              locations_to_remove.Add(845                  old_break_locs.FindByIDPair(GetID(), old_id));846              old_sc_map.erase(old_id);847            }848            for (lldb::break_id_t new_id : new_id_vec) {849              locations_to_announce.Add(850                  new_break_locs.FindByIDPair(GetID(), new_id));851              new_sc_map.erase(new_id);852            }853          }854        }855      }856    }857 858    // Now remove the remaining old locations, and cons up a removed locations859    // event. Note, we don't put the new locations that were swapped with an860    // old location on the locations_to_remove list, so we don't need to worry861    // about telling the world about removing a location we didn't tell them862    // about adding.863 864    std::shared_ptr<BreakpointEventData> removed_locations_event;865    if (!IsInternal())866      removed_locations_event = std::make_shared<BreakpointEventData>(867          eBreakpointEventTypeLocationsRemoved, shared_from_this());868 869    for (BreakpointLocationSP loc_sp :870         locations_to_remove.BreakpointLocations()) {871      m_locations.RemoveLocation(loc_sp);872      if (removed_locations_event)873        removed_locations_event->GetBreakpointLocationCollection().Add(loc_sp);874    }875    SendBreakpointChangedEvent(removed_locations_event);876 877    // And announce the new ones.878 879    if (!IsInternal()) {880      std::shared_ptr<BreakpointEventData> added_locations_event =881          std::make_shared<BreakpointEventData>(882              eBreakpointEventTypeLocationsAdded, shared_from_this());883      for (BreakpointLocationSP loc_sp :884           locations_to_announce.BreakpointLocations())885        added_locations_event->GetBreakpointLocationCollection().Add(loc_sp);886 887      SendBreakpointChangedEvent(added_locations_event);888    }889    m_locations.Compact();890  }891}892 893void Breakpoint::Dump(Stream *) {}894 895size_t Breakpoint::GetNumResolvedLocations(bool use_facade) const {896  // Return the number of breakpoints that are actually resolved and set down897  // in the inferior process.898  // All facade locations are considered to be resolved:899  if (use_facade) {900    size_t num_facade_locs = m_facade_locations.GetSize();901    if (num_facade_locs)902      return num_facade_locs;903  }904  return m_locations.GetNumResolvedLocations();905}906 907bool Breakpoint::HasResolvedLocations() const {908  return GetNumResolvedLocations() > 0;909}910 911size_t Breakpoint::GetNumLocations(bool use_facade) const {912  if (use_facade) {913    size_t num_facade_locs = m_facade_locations.GetSize();914    if (num_facade_locs > 0)915      return num_facade_locs;916  }917  return m_locations.GetSize();918}919 920void Breakpoint::AddName(llvm::StringRef new_name) {921  m_name_list.insert(new_name.str());922}923 924void Breakpoint::GetDescription(Stream *s, lldb::DescriptionLevel level,925                                bool show_locations) {926  assert(s != nullptr);927 928  const bool dim_breakpoint_description =929      !IsEnabled() && s->AsRawOstream().colors_enabled();930  if (dim_breakpoint_description)931    s->Printf("%s", ansi::FormatAnsiTerminalCodes(932                        GetTarget().GetDebugger().GetDisabledAnsiPrefix())933                        .c_str());934 935  if (!m_kind_description.empty()) {936    if (level == eDescriptionLevelBrief) {937      s->PutCString(GetBreakpointKind());938      return;939    }940    s->Printf("Kind: %s\n", GetBreakpointKind());941  }942 943  bool show_both_types = level == eDescriptionLevelVerbose &&944                         HasFacadeLocations() && show_locations;945  uint8_t display_mask = eDisplayFacade;946  if (show_both_types)947    display_mask |= eDisplayHeader;948 949  GetDescriptionForType(s, level, display_mask, show_locations);950 951  if (show_both_types) {952    display_mask = eDisplayReal | eDisplayHeader;953    GetDescriptionForType(s, level, display_mask, show_locations);954  }955  // Reset the colors back to normal if they were previously greyed out.956  if (dim_breakpoint_description)957    s->Printf("%s", ansi::FormatAnsiTerminalCodes(958                        GetTarget().GetDebugger().GetDisabledAnsiSuffix())959                        .c_str());960}961 962void Breakpoint::GetDescriptionForType(Stream *s, lldb::DescriptionLevel level,963                                       uint8_t display_type,964                                       bool show_locations) {965  bool use_facade = (display_type & eDisplayFacade) != 0;966  const size_t num_locations = GetNumLocations(use_facade);967  const size_t num_resolved_locations = GetNumResolvedLocations(use_facade);968 969  // They just made the breakpoint, they don't need to be told HOW they made970  // it... Also, we'll print the breakpoint number differently depending on971  // whether there is 1 or more locations.972  if (level != eDescriptionLevelInitial) {973    s->Printf("%i: ", GetID());974    GetResolverDescription(s);975    GetFilterDescription(s);976  }977 978  switch (level) {979  case lldb::eDescriptionLevelBrief:980  case lldb::eDescriptionLevelFull:981    if (num_locations > 0) {982      s->Printf(", locations = %" PRIu64, (uint64_t)num_locations);983      if (num_resolved_locations > 0)984        s->Printf(", resolved = %" PRIu64 ", hit count = %d",985                  (uint64_t)num_resolved_locations, GetHitCount());986    } else {987      // Don't print the pending notification for exception resolvers since we988      // don't generally know how to set them until the target is run.989      if (m_resolver_sp->getResolverID() !=990          BreakpointResolver::ExceptionResolver)991        s->Printf(", locations = 0 (pending)");992    }993 994    m_options.GetDescription(s, level);995 996    if (m_precondition_sp)997      m_precondition_sp->GetDescription(*s, level);998 999    if (level == lldb::eDescriptionLevelFull) {1000      if (!m_name_list.empty()) {1001        s->EOL();1002        s->Indent();1003        s->Printf("Names:");1004        s->EOL();1005        s->IndentMore();1006        for (const std::string &name : m_name_list) {1007          s->Indent();1008          s->Printf("%s\n", name.c_str());1009        }1010        s->IndentLess();1011      }1012      s->IndentLess();1013      s->EOL();1014    }1015    break;1016 1017  case lldb::eDescriptionLevelInitial:1018    s->Printf("Breakpoint %i: ", GetID());1019    if (num_locations == 0) {1020      s->Printf("no locations (pending).");1021    } else if (num_locations == 1 && !show_locations) {1022      // There is only one location, so we'll just print that location1023      // information.1024      GetLocationAtIndex(0, use_facade)->GetDescription(s, level);1025    } else {1026      s->Printf("%" PRIu64 " locations.", static_cast<uint64_t>(num_locations));1027    }1028    s->EOL();1029    break;1030 1031  case lldb::eDescriptionLevelVerbose:1032    // Verbose mode does a debug dump of the breakpoint1033    Dump(s);1034    s->EOL();1035    // s->Indent();1036    m_options.GetDescription(s, level);1037    break;1038 1039  default:1040    break;1041  }1042 1043  // The brief description is just the location name (1.2 or whatever).  That's1044  // pointless to show in the breakpoint's description, so suppress it.1045  if (show_locations && level != lldb::eDescriptionLevelBrief) {1046    if ((display_type & eDisplayHeader) != 0) {1047      if ((display_type & eDisplayFacade) != 0)1048        s->Printf("Facade locations:\n");1049      else1050        s->Printf("Implementation Locations\n");1051    }1052    s->IndentMore();1053    for (size_t i = 0; i < num_locations; ++i) {1054      BreakpointLocation *loc = GetLocationAtIndex(i, use_facade).get();1055      loc->GetDescription(s, level);1056      s->EOL();1057    }1058    s->IndentLess();1059  }1060}1061 1062void Breakpoint::GetResolverDescription(Stream *s) {1063  if (m_resolver_sp)1064    m_resolver_sp->GetDescription(s);1065}1066 1067bool Breakpoint::GetMatchingFileLine(ConstString filename, uint32_t line_number,1068                                     BreakpointLocationCollection &loc_coll) {1069  // TODO: To be correct, this method needs to fill the breakpoint location1070  // collection1071  //       with the location IDs which match the filename and line_number.1072  //1073 1074  if (m_resolver_sp) {1075    BreakpointResolverFileLine *resolverFileLine =1076        dyn_cast<BreakpointResolverFileLine>(m_resolver_sp.get());1077 1078    // TODO: Handle SourceLocationSpec column information1079    if (resolverFileLine &&1080        resolverFileLine->m_location_spec.GetFileSpec().GetFilename() ==1081            filename &&1082        resolverFileLine->m_location_spec.GetLine() == line_number) {1083      return true;1084    }1085  }1086  return false;1087}1088 1089void Breakpoint::GetFilterDescription(Stream *s) {1090  m_filter_sp->GetDescription(s);1091}1092 1093bool Breakpoint::EvaluatePrecondition(StoppointCallbackContext &context) {1094  if (!m_precondition_sp)1095    return true;1096 1097  return m_precondition_sp->EvaluatePrecondition(context);1098}1099 1100void Breakpoint::SendBreakpointChangedEvent(1101    lldb::BreakpointEventType event_kind) {1102  if (!IsInternal())1103    GetTarget().NotifyBreakpointChanged(*this, event_kind);1104}1105 1106void Breakpoint::SendBreakpointChangedEvent(1107    const lldb::EventDataSP &breakpoint_data_sp) {1108  if (!breakpoint_data_sp)1109    return;1110 1111  if (!IsInternal())1112    GetTarget().NotifyBreakpointChanged(*this, breakpoint_data_sp);1113}1114 1115const char *Breakpoint::BreakpointEventTypeAsCString(BreakpointEventType type) {1116  switch (type) {1117  case eBreakpointEventTypeInvalidType:1118    return "invalid";1119  case eBreakpointEventTypeAdded:1120    return "breakpoint added";1121  case eBreakpointEventTypeRemoved:1122    return "breakpoint removed";1123  case eBreakpointEventTypeLocationsAdded:1124    return "locations added";1125  case eBreakpointEventTypeLocationsRemoved:1126    return "locations removed";1127  case eBreakpointEventTypeLocationsResolved:1128    return "locations resolved";1129  case eBreakpointEventTypeEnabled:1130    return "breakpoint enabled";1131  case eBreakpointEventTypeDisabled:1132    return "breakpoint disabled";1133  case eBreakpointEventTypeCommandChanged:1134    return "command changed";1135  case eBreakpointEventTypeConditionChanged:1136    return "condition changed";1137  case eBreakpointEventTypeIgnoreChanged:1138    return "ignore count changed";1139  case eBreakpointEventTypeThreadChanged:1140    return "thread changed";1141  case eBreakpointEventTypeAutoContinueChanged:1142    return "autocontinue changed";1143  };1144  llvm_unreachable("Fully covered switch above!");1145}1146 1147Log *Breakpoint::BreakpointEventData::GetLogChannel() {1148  return GetLog(LLDBLog::Breakpoints);1149}1150 1151Breakpoint::BreakpointEventData::BreakpointEventData(1152    BreakpointEventType sub_type, const BreakpointSP &new_breakpoint_sp)1153    : m_breakpoint_event(sub_type), m_new_breakpoint_sp(new_breakpoint_sp) {}1154 1155Breakpoint::BreakpointEventData::~BreakpointEventData() = default;1156 1157llvm::StringRef Breakpoint::BreakpointEventData::GetFlavorString() {1158  return "Breakpoint::BreakpointEventData";1159}1160 1161llvm::StringRef Breakpoint::BreakpointEventData::GetFlavor() const {1162  return BreakpointEventData::GetFlavorString();1163}1164 1165BreakpointSP Breakpoint::BreakpointEventData::GetBreakpoint() const {1166  return m_new_breakpoint_sp;1167}1168 1169BreakpointEventType1170Breakpoint::BreakpointEventData::GetBreakpointEventType() const {1171  return m_breakpoint_event;1172}1173 1174void Breakpoint::BreakpointEventData::Dump(Stream *s) const {1175  if (!s)1176    return;1177  BreakpointEventType event_type = GetBreakpointEventType();1178  break_id_t bkpt_id = GetBreakpoint()->GetID();1179  s->Format("bkpt: {0} type: {1}", bkpt_id,1180            BreakpointEventTypeAsCString(event_type));1181}1182 1183const Breakpoint::BreakpointEventData *1184Breakpoint::BreakpointEventData::GetEventDataFromEvent(const Event *event) {1185  if (event) {1186    const EventData *event_data = event->GetData();1187    if (event_data &&1188        event_data->GetFlavor() == BreakpointEventData::GetFlavorString())1189      return static_cast<const BreakpointEventData *>(event->GetData());1190  }1191  return nullptr;1192}1193 1194BreakpointEventType1195Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent(1196    const EventSP &event_sp) {1197  const BreakpointEventData *data = GetEventDataFromEvent(event_sp.get());1198 1199  if (data == nullptr)1200    return eBreakpointEventTypeInvalidType;1201  return data->GetBreakpointEventType();1202}1203 1204BreakpointSP Breakpoint::BreakpointEventData::GetBreakpointFromEvent(1205    const EventSP &event_sp) {1206  BreakpointSP bp_sp;1207 1208  const BreakpointEventData *data = GetEventDataFromEvent(event_sp.get());1209  if (data)1210    bp_sp = data->m_new_breakpoint_sp;1211 1212  return bp_sp;1213}1214 1215size_t Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent(1216    const EventSP &event_sp) {1217  const BreakpointEventData *data = GetEventDataFromEvent(event_sp.get());1218  if (data)1219    return data->m_locations.GetSize();1220 1221  return 0;1222}1223 1224lldb::BreakpointLocationSP1225Breakpoint::BreakpointEventData::GetBreakpointLocationAtIndexFromEvent(1226    const lldb::EventSP &event_sp, uint32_t bp_loc_idx) {1227  lldb::BreakpointLocationSP bp_loc_sp;1228 1229  const BreakpointEventData *data = GetEventDataFromEvent(event_sp.get());1230  if (data) {1231    bp_loc_sp = data->m_locations.GetByIndex(bp_loc_idx);1232  }1233 1234  return bp_loc_sp;1235}1236 1237json::Value Breakpoint::GetStatistics() {1238  json::Object bp;1239  bp.try_emplace("id", GetID());1240  bp.try_emplace("resolveTime", m_resolve_time.get().count());1241  bp.try_emplace("numLocations", (int64_t)GetNumLocations());1242  bp.try_emplace("numResolvedLocations", (int64_t)GetNumResolvedLocations());1243  bp.try_emplace("hitCount", (int64_t)GetHitCount());1244  bp.try_emplace("internal", IsInternal());1245  if (!m_kind_description.empty())1246    bp.try_emplace("kindDescription", m_kind_description);1247  // Put the full structured data for reproducing this breakpoint in a key/value1248  // pair named "details". This allows the breakpoint's details to be visible1249  // in the stats in case we need to reproduce a breakpoint that has long1250  // resolve times1251  StructuredData::ObjectSP bp_data_sp = SerializeToStructuredData();1252  if (bp_data_sp) {1253    std::string buffer;1254    llvm::raw_string_ostream ss(buffer);1255    json::OStream json_os(ss);1256    bp_data_sp->Serialize(json_os);1257    if (auto expected_value = llvm::json::parse(buffer)) {1258      bp.try_emplace("details", std::move(*expected_value));1259    } else {1260      std::string details_error = toString(expected_value.takeError());1261      json::Object details;1262      details.try_emplace("error", details_error);1263      bp.try_emplace("details", std::move(details));1264    }1265  }1266  return json::Value(std::move(bp));1267}1268 1269void Breakpoint::ResetStatistics() { m_resolve_time.reset(); }1270