Files
clang-r547379/include/lldb/Breakpoint/StopPointSiteList.h
Ryan Prichard 6024e5c395 Update prebuilt Clang to r547379 (20.0.0).
clang 20.0.0 (based on r547379) from build 12806354.

Bug: http://b/379133546
Test: N/A
Change-Id: I2eb8938af55d809de674be63cb30cf27e801862b

Upstream-Commit: ad834e67b1105d15ef907f6255d4c96e8e733f57
2025-11-26 14:59:46 -05:00

311 lines
9.9 KiB
C++

//===-- StopPointSiteList.h -------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLDB_BREAKPOINT_STOPPOINTSITELIST_H
#define LLDB_BREAKPOINT_STOPPOINTSITELIST_H
#include <functional>
#include <map>
#include <mutex>
#include <lldb/Breakpoint/BreakpointSite.h>
#include <lldb/Utility/Iterable.h>
#include <lldb/Utility/Stream.h>
namespace lldb_private {
template <typename StopPointSite> class StopPointSiteList {
// At present Process directly accesses the map of StopPointSites so it can
// do quick lookups into the map (using GetMap).
// FIXME: Find a better interface for this.
friend class Process;
public:
using StopPointSiteSP = std::shared_ptr<StopPointSite>;
/// Add a site to the list.
///
/// \param[in] site_sp
/// A shared pointer to a site being added to the list.
///
/// \return
/// The ID of the site in the list.
typename StopPointSite::SiteID Add(const StopPointSiteSP &site_sp) {
lldb::addr_t site_load_addr = site_sp->GetLoadAddress();
std::lock_guard<std::recursive_mutex> guard(m_mutex);
typename collection::iterator iter = m_site_list.find(site_load_addr);
// Add site to the list. However, if the element already exists in
// the list, then we don't add it, and return InvalidSiteID.
if (iter == m_site_list.end()) {
m_site_list[site_load_addr] = site_sp;
return site_sp->GetID();
} else {
return UINT32_MAX;
}
}
/// Standard Dump routine, doesn't do anything at present.
/// \param[in] s
/// Stream into which to dump the description.
void Dump(Stream *s) const {
s->Printf("%p: ", static_cast<const void *>(this));
s->Printf("StopPointSiteList with %u ConstituentSites:\n",
(uint32_t)m_site_list.size());
s->IndentMore();
typename collection::const_iterator pos;
typename collection::const_iterator end = m_site_list.end();
for (pos = m_site_list.begin(); pos != end; ++pos)
pos->second->Dump(s);
s->IndentLess();
}
/// Returns a shared pointer to the site at address \a addr.
///
/// \param[in] addr
/// The address to look for.
///
/// \result
/// A shared pointer to the site. Nullptr if no site contains
/// the address.
StopPointSiteSP FindByAddress(lldb::addr_t addr) {
StopPointSiteSP found_sp;
std::lock_guard<std::recursive_mutex> guard(m_mutex);
typename collection::iterator iter = m_site_list.find(addr);
if (iter != m_site_list.end())
found_sp = iter->second;
return found_sp;
}
/// Returns a shared pointer to the site with id \a site_id.
///
/// \param[in] site_id
/// The site ID to seek for.
///
/// \result
/// A shared pointer to the site. Nullptr if no matching site.
StopPointSiteSP FindByID(typename StopPointSite::SiteID site_id) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
StopPointSiteSP stop_sp;
typename collection::iterator pos = GetIDIterator(site_id);
if (pos != m_site_list.end())
stop_sp = pos->second;
return stop_sp;
}
/// Returns a shared pointer to the site with id \a site_id -
/// const version.
///
/// \param[in] site_id
/// The site ID to seek for.
///
/// \result
/// A shared pointer to the site. Nullptr if no matching site.
const StopPointSiteSP FindByID(typename StopPointSite::SiteID site_id) const {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
StopPointSiteSP stop_sp;
typename collection::const_iterator pos = GetIDConstIterator(site_id);
if (pos != m_site_list.end())
stop_sp = pos->second;
return stop_sp;
}
/// Returns the site id to the site at address \a addr.
///
/// \param[in] addr
/// The address to match.
///
/// \result
/// The ID of the site, or LLDB_INVALID_SITE_ID.
typename StopPointSite::SiteID FindIDByAddress(lldb::addr_t addr) {
if (StopPointSiteSP site = FindByAddress(addr))
return site->GetID();
return UINT32_MAX;
}
/// Returns whether the BreakpointSite \a site_id has a BreakpointLocation
/// that is part of Breakpoint \a bp_id.
///
/// NB this is only defined when StopPointSiteList is specialized for
/// BreakpointSite's.
///
/// \param[in] site_id
/// The site id to query.
///
/// \param[in] bp_id
/// The breakpoint id to look for in \a site_id's BreakpointLocations.
///
/// \result
/// True if \a site_id exists in the site list AND \a bp_id
/// is the breakpoint for one of the BreakpointLocations.
bool StopPointSiteContainsBreakpoint(typename StopPointSite::SiteID,
lldb::break_id_t bp_id);
void ForEach(std::function<void(StopPointSite *)> const &callback) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
for (auto pair : m_site_list)
callback(pair.second.get());
}
/// Removes the site given by \a site_id from this list.
///
/// \param[in] site_id
/// The site ID to remove.
///
/// \result
/// \b true if the site \a site_id was in the list.
bool Remove(typename StopPointSite::SiteID site_id) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
typename collection::iterator pos = GetIDIterator(site_id); // Predicate
if (pos != m_site_list.end()) {
m_site_list.erase(pos);
return true;
}
return false;
}
/// Removes the site at address \a addr from this list.
///
/// \param[in] addr
/// The address from which to remove a site.
///
/// \result
/// \b true if \a addr had a site to remove from the list.
bool RemoveByAddress(lldb::addr_t addr) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
typename collection::iterator pos = m_site_list.find(addr);
if (pos != m_site_list.end()) {
m_site_list.erase(pos);
return true;
}
return false;
}
bool FindInRange(lldb::addr_t lower_bound, lldb::addr_t upper_bound,
StopPointSiteList &bp_site_list) const {
if (lower_bound > upper_bound)
return false;
std::lock_guard<std::recursive_mutex> guard(m_mutex);
typename collection::const_iterator lower, upper, pos;
lower = m_site_list.lower_bound(lower_bound);
if (lower == m_site_list.end() || (*lower).first >= upper_bound)
return false;
// This is one tricky bit. The site might overlap the bottom end of
// the range. So we grab the site prior to the lower bound, and check
// that that + its byte size isn't in our range.
if (lower != m_site_list.begin()) {
typename collection::const_iterator prev_pos = lower;
prev_pos--;
const StopPointSiteSP &prev_site = (*prev_pos).second;
if (prev_site->GetLoadAddress() + prev_site->GetByteSize() > lower_bound)
bp_site_list.Add(prev_site);
}
upper = m_site_list.upper_bound(upper_bound);
for (pos = lower; pos != upper; pos++)
bp_site_list.Add((*pos).second);
return true;
}
typedef void (*StopPointSiteSPMapFunc)(StopPointSite &site, void *baton);
/// Enquires of the site on in this list with ID \a site_id
/// whether we should stop for the constituent or not.
///
/// \param[in] context
/// This contains the information about this stop.
///
/// \param[in] site_id
/// This site ID that we hit.
///
/// \return
/// \b true if we should stop, \b false otherwise.
bool ShouldStop(StoppointCallbackContext *context,
typename StopPointSite::SiteID site_id) {
if (StopPointSiteSP site_sp = FindByID(site_id)) {
// Let the site decide if it should stop here (could not have
// reached it's target hit count yet, or it could have a callback that
// decided it shouldn't stop (shared library loads/unloads).
return site_sp->ShouldStop(context);
}
// We should stop here since this site isn't valid anymore or it
// doesn't exist.
return true;
}
/// Returns the number of elements in the list.
///
/// \result
/// The number of elements.
size_t GetSize() const {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
return m_site_list.size();
}
bool IsEmpty() const {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
return m_site_list.empty();
}
std::vector<StopPointSiteSP> Sites() {
std::vector<StopPointSiteSP> sites;
std::lock_guard<std::recursive_mutex> guard(m_mutex);
typename collection::iterator iter = m_site_list.begin();
while (iter != m_site_list.end()) {
sites.push_back(iter->second);
++iter;
}
return sites;
}
void Clear() {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
m_site_list.clear();
}
protected:
typedef std::map<lldb::addr_t, StopPointSiteSP> collection;
typename collection::iterator
GetIDIterator(typename StopPointSite::SiteID site_id) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
auto id_matches =
[site_id](const std::pair<lldb::addr_t, StopPointSiteSP> s) {
return site_id == s.second->GetID();
};
return std::find_if(m_site_list.begin(),
m_site_list.end(), // Search full range
id_matches);
}
typename collection::const_iterator
GetIDConstIterator(typename StopPointSite::SiteID site_id) const {
std::lock_guard<std::recursive_mutex> guard(m_mutex);
auto id_matches =
[site_id](const std::pair<lldb::addr_t, StopPointSiteSP> s) {
return site_id == s.second->GetID();
};
return std::find_if(m_site_list.begin(),
m_site_list.end(), // Search full range
id_matches);
}
mutable std::recursive_mutex m_mutex;
collection m_site_list; // The site list.
};
} // namespace lldb_private
#endif // LLDB_BREAKPOINT_STOPPOINTSITELIST_H