Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:42:44

0001 //===-- StopPointSiteList.h -------------------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLDB_BREAKPOINT_STOPPOINTSITELIST_H
0010 #define LLDB_BREAKPOINT_STOPPOINTSITELIST_H
0011 
0012 #include <functional>
0013 #include <map>
0014 #include <mutex>
0015 
0016 #include <lldb/Breakpoint/BreakpointSite.h>
0017 #include <lldb/Utility/Iterable.h>
0018 #include <lldb/Utility/Stream.h>
0019 
0020 namespace lldb_private {
0021 
0022 template <typename StopPointSite> class StopPointSiteList {
0023   // At present Process directly accesses the map of StopPointSites so it can
0024   // do quick lookups into the map (using GetMap).
0025   // FIXME: Find a better interface for this.
0026   friend class Process;
0027 
0028 public:
0029   using StopPointSiteSP = std::shared_ptr<StopPointSite>;
0030 
0031   /// Add a site to the list.
0032   ///
0033   /// \param[in] site_sp
0034   ///    A shared pointer to a site being added to the list.
0035   ///
0036   /// \return
0037   ///    The ID of the site in the list.
0038   typename StopPointSite::SiteID Add(const StopPointSiteSP &site_sp) {
0039     lldb::addr_t site_load_addr = site_sp->GetLoadAddress();
0040     std::lock_guard<std::recursive_mutex> guard(m_mutex);
0041     // Add site to the list.  However, if the element already exists in
0042     // the list, then we don't add it, and return InvalidSiteID.
0043     bool inserted = m_site_list.try_emplace(site_load_addr, site_sp).second;
0044     return inserted ? site_sp->GetID() : UINT32_MAX;
0045   }
0046 
0047   /// Standard Dump routine, doesn't do anything at present.
0048   /// \param[in] s
0049   ///     Stream into which to dump the description.
0050   void Dump(Stream *s) const {
0051     s->Printf("%p: ", static_cast<const void *>(this));
0052     s->Printf("StopPointSiteList with %u ConstituentSites:\n",
0053               (uint32_t)m_site_list.size());
0054     s->IndentMore();
0055     typename collection::const_iterator pos;
0056     typename collection::const_iterator end = m_site_list.end();
0057     for (pos = m_site_list.begin(); pos != end; ++pos)
0058       pos->second->Dump(s);
0059     s->IndentLess();
0060   }
0061 
0062   /// Returns a shared pointer to the site at address \a addr.
0063   ///
0064   /// \param[in] addr
0065   ///     The address to look for.
0066   ///
0067   /// \result
0068   ///     A shared pointer to the site. Nullptr if no site contains
0069   ///     the address.
0070   StopPointSiteSP FindByAddress(lldb::addr_t addr) {
0071     StopPointSiteSP found_sp;
0072     std::lock_guard<std::recursive_mutex> guard(m_mutex);
0073     typename collection::iterator iter = m_site_list.find(addr);
0074     if (iter != m_site_list.end())
0075       found_sp = iter->second;
0076     return found_sp;
0077   }
0078 
0079   /// Returns a shared pointer to the site with id \a site_id.
0080   ///
0081   /// \param[in] site_id
0082   ///   The site ID to seek for.
0083   ///
0084   /// \result
0085   ///   A shared pointer to the site. Nullptr if no matching site.
0086   StopPointSiteSP FindByID(typename StopPointSite::SiteID site_id) {
0087     std::lock_guard<std::recursive_mutex> guard(m_mutex);
0088     StopPointSiteSP stop_sp;
0089     typename collection::iterator pos = GetIDIterator(site_id);
0090     if (pos != m_site_list.end())
0091       stop_sp = pos->second;
0092 
0093     return stop_sp;
0094   }
0095 
0096   /// Returns a shared pointer to the site with id \a site_id -
0097   /// const version.
0098   ///
0099   /// \param[in] site_id
0100   ///   The site ID to seek for.
0101   ///
0102   /// \result
0103   ///   A shared pointer to the site. Nullptr if no matching site.
0104   const StopPointSiteSP FindByID(typename StopPointSite::SiteID site_id) const {
0105     std::lock_guard<std::recursive_mutex> guard(m_mutex);
0106     StopPointSiteSP stop_sp;
0107     typename collection::const_iterator pos = GetIDConstIterator(site_id);
0108     if (pos != m_site_list.end())
0109       stop_sp = pos->second;
0110 
0111     return stop_sp;
0112   }
0113 
0114   /// Returns the site id to the site at address \a addr.
0115   ///
0116   /// \param[in] addr
0117   ///   The address to match.
0118   ///
0119   /// \result
0120   ///   The ID of the site, or LLDB_INVALID_SITE_ID.
0121   typename StopPointSite::SiteID FindIDByAddress(lldb::addr_t addr) {
0122     if (StopPointSiteSP site = FindByAddress(addr))
0123       return site->GetID();
0124     return UINT32_MAX;
0125   }
0126 
0127   /// Returns whether the BreakpointSite \a site_id has a BreakpointLocation
0128   /// that is part of Breakpoint \a bp_id.
0129   ///
0130   /// NB this is only defined when StopPointSiteList is specialized for
0131   /// BreakpointSite's.
0132   ///
0133   /// \param[in] site_id
0134   ///   The site id to query.
0135   ///
0136   /// \param[in] bp_id
0137   ///   The breakpoint id to look for in \a site_id's BreakpointLocations.
0138   ///
0139   /// \result
0140   ///   True if \a site_id exists in the site list AND \a bp_id
0141   ///   is the breakpoint for one of the BreakpointLocations.
0142   bool StopPointSiteContainsBreakpoint(typename StopPointSite::SiteID,
0143                                        lldb::break_id_t bp_id);
0144 
0145   void ForEach(std::function<void(StopPointSite *)> const &callback) {
0146     std::lock_guard<std::recursive_mutex> guard(m_mutex);
0147     for (auto pair : m_site_list)
0148       callback(pair.second.get());
0149   }
0150 
0151   /// Removes the site given by \a site_id from this list.
0152   ///
0153   /// \param[in] site_id
0154   ///   The site ID to remove.
0155   ///
0156   /// \result
0157   ///   \b true if the site \a site_id was in the list.
0158   bool Remove(typename StopPointSite::SiteID site_id) {
0159     std::lock_guard<std::recursive_mutex> guard(m_mutex);
0160     typename collection::iterator pos = GetIDIterator(site_id); // Predicate
0161     if (pos != m_site_list.end()) {
0162       m_site_list.erase(pos);
0163       return true;
0164     }
0165     return false;
0166   }
0167 
0168   /// Removes the site at address \a addr from this list.
0169   ///
0170   /// \param[in] addr
0171   ///   The address from which to remove a site.
0172   ///
0173   /// \result
0174   ///   \b true if \a addr had a site to remove from the list.
0175   bool RemoveByAddress(lldb::addr_t addr) {
0176     std::lock_guard<std::recursive_mutex> guard(m_mutex);
0177     typename collection::iterator pos = m_site_list.find(addr);
0178     if (pos != m_site_list.end()) {
0179       m_site_list.erase(pos);
0180       return true;
0181     }
0182     return false;
0183   }
0184 
0185   bool FindInRange(lldb::addr_t lower_bound, lldb::addr_t upper_bound,
0186                    StopPointSiteList &bp_site_list) const {
0187     if (lower_bound > upper_bound)
0188       return false;
0189 
0190     std::lock_guard<std::recursive_mutex> guard(m_mutex);
0191     typename collection::const_iterator lower, upper, pos;
0192     lower = m_site_list.lower_bound(lower_bound);
0193     if (lower == m_site_list.end() || (*lower).first >= upper_bound)
0194       return false;
0195 
0196     // This is one tricky bit.  The site might overlap the bottom end of
0197     // the range.  So we grab the site prior to the lower bound, and check
0198     // that that + its byte size isn't in our range.
0199     if (lower != m_site_list.begin()) {
0200       typename collection::const_iterator prev_pos = lower;
0201       prev_pos--;
0202       const StopPointSiteSP &prev_site = (*prev_pos).second;
0203       if (prev_site->GetLoadAddress() + prev_site->GetByteSize() > lower_bound)
0204         bp_site_list.Add(prev_site);
0205     }
0206 
0207     upper = m_site_list.upper_bound(upper_bound);
0208 
0209     for (pos = lower; pos != upper; pos++)
0210       bp_site_list.Add((*pos).second);
0211     return true;
0212   }
0213 
0214   typedef void (*StopPointSiteSPMapFunc)(StopPointSite &site, void *baton);
0215 
0216   /// Enquires of the site on in this list with ID \a site_id
0217   /// whether we should stop for the constituent or not.
0218   ///
0219   /// \param[in] context
0220   ///    This contains the information about this stop.
0221   ///
0222   /// \param[in] site_id
0223   ///    This site ID that we hit.
0224   ///
0225   /// \return
0226   ///    \b true if we should stop, \b false otherwise.
0227   bool ShouldStop(StoppointCallbackContext *context,
0228                   typename StopPointSite::SiteID site_id) {
0229     if (StopPointSiteSP site_sp = FindByID(site_id)) {
0230       // Let the site decide if it should stop here (could not have
0231       // reached it's target hit count yet, or it could have a callback that
0232       // decided it shouldn't stop (shared library loads/unloads).
0233       return site_sp->ShouldStop(context);
0234     }
0235     // We should stop here since this site isn't valid anymore or it
0236     // doesn't exist.
0237     return true;
0238   }
0239 
0240   /// Returns the number of elements in the list.
0241   ///
0242   /// \result
0243   ///   The number of elements.
0244   size_t GetSize() const {
0245     std::lock_guard<std::recursive_mutex> guard(m_mutex);
0246     return m_site_list.size();
0247   }
0248 
0249   bool IsEmpty() const {
0250     std::lock_guard<std::recursive_mutex> guard(m_mutex);
0251     return m_site_list.empty();
0252   }
0253 
0254   std::vector<StopPointSiteSP> Sites() {
0255     std::vector<StopPointSiteSP> sites;
0256     std::lock_guard<std::recursive_mutex> guard(m_mutex);
0257     typename collection::iterator iter = m_site_list.begin();
0258     while (iter != m_site_list.end()) {
0259       sites.push_back(iter->second);
0260       ++iter;
0261     }
0262 
0263     return sites;
0264   }
0265 
0266   void Clear() {
0267     std::lock_guard<std::recursive_mutex> guard(m_mutex);
0268     m_site_list.clear();
0269   }
0270 
0271 protected:
0272   typedef std::map<lldb::addr_t, StopPointSiteSP> collection;
0273 
0274   typename collection::iterator
0275   GetIDIterator(typename StopPointSite::SiteID site_id) {
0276     std::lock_guard<std::recursive_mutex> guard(m_mutex);
0277     auto id_matches =
0278         [site_id](const std::pair<lldb::addr_t, StopPointSiteSP> s) {
0279           return site_id == s.second->GetID();
0280         };
0281     return std::find_if(m_site_list.begin(),
0282                         m_site_list.end(), // Search full range
0283                         id_matches);
0284   }
0285 
0286   typename collection::const_iterator
0287   GetIDConstIterator(typename StopPointSite::SiteID site_id) const {
0288     std::lock_guard<std::recursive_mutex> guard(m_mutex);
0289     auto id_matches =
0290         [site_id](const std::pair<lldb::addr_t, StopPointSiteSP> s) {
0291           return site_id == s.second->GetID();
0292         };
0293     return std::find_if(m_site_list.begin(),
0294                         m_site_list.end(), // Search full range
0295                         id_matches);
0296   }
0297 
0298   mutable std::recursive_mutex m_mutex;
0299   collection m_site_list; // The site list.
0300 };
0301 
0302 } // namespace lldb_private
0303 
0304 #endif // LLDB_BREAKPOINT_STOPPOINTSITELIST_H