2010-06-09 00:52:24 +08:00
|
|
|
//===-- BreakpointList.cpp --------------------------------------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "lldb/Breakpoint/BreakpointList.h"
|
|
|
|
|
2010-07-24 07:33:17 +08:00
|
|
|
#include "lldb/Target/Target.h"
|
2010-06-09 00:52:24 +08:00
|
|
|
|
|
|
|
using namespace lldb;
|
|
|
|
using namespace lldb_private;
|
|
|
|
|
2016-05-19 13:13:57 +08:00
|
|
|
BreakpointList::BreakpointList(bool is_internal)
|
2016-09-07 04:57:50 +08:00
|
|
|
: m_mutex(), m_breakpoints(), m_next_break_id(0),
|
|
|
|
m_is_internal(is_internal) {}
|
|
|
|
|
|
|
|
BreakpointList::~BreakpointList() {}
|
|
|
|
|
|
|
|
break_id_t BreakpointList::Add(BreakpointSP &bp_sp, bool notify) {
|
|
|
|
std::lock_guard<std::recursive_mutex> guard(m_mutex);
|
|
|
|
// Internal breakpoint IDs are negative, normal ones are positive
|
|
|
|
bp_sp->SetID(m_is_internal ? --m_next_break_id : ++m_next_break_id);
|
|
|
|
|
|
|
|
m_breakpoints.push_back(bp_sp);
|
|
|
|
if (notify) {
|
|
|
|
if (bp_sp->GetTarget().EventTypeHasListeners(
|
|
|
|
Target::eBroadcastBitBreakpointChanged))
|
|
|
|
bp_sp->GetTarget().BroadcastEvent(Target::eBroadcastBitBreakpointChanged,
|
|
|
|
new Breakpoint::BreakpointEventData(
|
|
|
|
eBreakpointEventTypeAdded, bp_sp));
|
|
|
|
}
|
|
|
|
return bp_sp->GetID();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool BreakpointList::Remove(break_id_t break_id, bool notify) {
|
|
|
|
std::lock_guard<std::recursive_mutex> guard(m_mutex);
|
|
|
|
bp_collection::iterator pos = GetBreakpointIDIterator(break_id); // Predicate
|
|
|
|
if (pos != m_breakpoints.end()) {
|
|
|
|
BreakpointSP bp_sp(*pos);
|
|
|
|
m_breakpoints.erase(pos);
|
|
|
|
if (notify) {
|
|
|
|
if (bp_sp->GetTarget().EventTypeHasListeners(
|
|
|
|
Target::eBroadcastBitBreakpointChanged))
|
|
|
|
bp_sp->GetTarget().BroadcastEvent(
|
|
|
|
Target::eBroadcastBitBreakpointChanged,
|
|
|
|
new Breakpoint::BreakpointEventData(eBreakpointEventTypeRemoved,
|
|
|
|
bp_sp));
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
void BreakpointList::RemoveInvalidLocations(const ArchSpec &arch) {
|
|
|
|
std::lock_guard<std::recursive_mutex> guard(m_mutex);
|
|
|
|
for (const auto &bp_sp : m_breakpoints)
|
|
|
|
bp_sp->RemoveInvalidLocations(arch);
|
2013-11-09 08:03:31 +08:00
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
void BreakpointList::SetEnabledAll(bool enabled) {
|
|
|
|
std::lock_guard<std::recursive_mutex> guard(m_mutex);
|
|
|
|
for (const auto &bp_sp : m_breakpoints)
|
|
|
|
bp_sp->SetEnabled(enabled);
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
2017-09-15 04:22:49 +08:00
|
|
|
void BreakpointList::SetEnabledAllowed(bool enabled) {
|
|
|
|
std::lock_guard<std::recursive_mutex> guard(m_mutex);
|
|
|
|
for (const auto &bp_sp : m_breakpoints)
|
|
|
|
if (bp_sp->AllowDisable())
|
|
|
|
bp_sp->SetEnabled(enabled);
|
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
void BreakpointList::RemoveAll(bool notify) {
|
|
|
|
std::lock_guard<std::recursive_mutex> guard(m_mutex);
|
|
|
|
ClearAllBreakpointSites();
|
2010-06-09 00:52:24 +08:00
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
if (notify) {
|
|
|
|
bp_collection::iterator pos, end = m_breakpoints.end();
|
|
|
|
for (pos = m_breakpoints.begin(); pos != end; ++pos) {
|
|
|
|
if ((*pos)->GetTarget().EventTypeHasListeners(
|
|
|
|
Target::eBroadcastBitBreakpointChanged)) {
|
|
|
|
(*pos)->GetTarget().BroadcastEvent(
|
|
|
|
Target::eBroadcastBitBreakpointChanged,
|
|
|
|
new Breakpoint::BreakpointEventData(eBreakpointEventTypeRemoved,
|
|
|
|
*pos));
|
|
|
|
}
|
2010-07-24 07:33:17 +08:00
|
|
|
}
|
2016-09-07 04:57:50 +08:00
|
|
|
}
|
|
|
|
m_breakpoints.erase(m_breakpoints.begin(), m_breakpoints.end());
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
2017-09-15 04:22:49 +08:00
|
|
|
void BreakpointList::RemoveAllowed(bool notify) {
|
|
|
|
std::lock_guard<std::recursive_mutex> guard(m_mutex);
|
2018-04-17 06:26:21 +08:00
|
|
|
|
2017-09-15 04:22:49 +08:00
|
|
|
bp_collection::iterator pos, end = m_breakpoints.end();
|
|
|
|
if (notify) {
|
|
|
|
for (pos = m_breakpoints.begin(); pos != end; ++pos) {
|
|
|
|
if(!(*pos)->AllowDelete())
|
|
|
|
continue;
|
|
|
|
if ((*pos)->GetTarget().EventTypeHasListeners(
|
|
|
|
Target::eBroadcastBitBreakpointChanged)) {
|
|
|
|
(*pos)->GetTarget().BroadcastEvent(
|
|
|
|
Target::eBroadcastBitBreakpointChanged,
|
|
|
|
new Breakpoint::BreakpointEventData(eBreakpointEventTypeRemoved,
|
|
|
|
*pos));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pos = m_breakpoints.begin();
|
|
|
|
while ( pos != end) {
|
2018-04-17 06:26:21 +08:00
|
|
|
auto bp = *pos;
|
|
|
|
if (bp->AllowDelete()) {
|
|
|
|
bp->ClearAllBreakpointSites();
|
|
|
|
pos = m_breakpoints.erase(pos);
|
|
|
|
} else
|
|
|
|
pos++;
|
2017-09-15 04:22:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
class BreakpointIDMatches {
|
2010-06-09 00:52:24 +08:00
|
|
|
public:
|
2016-09-07 04:57:50 +08:00
|
|
|
BreakpointIDMatches(break_id_t break_id) : m_break_id(break_id) {}
|
2010-06-09 00:52:24 +08:00
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
bool operator()(const BreakpointSP &bp) const {
|
|
|
|
return m_break_id == bp->GetID();
|
|
|
|
}
|
2010-06-09 00:52:24 +08:00
|
|
|
|
|
|
|
private:
|
2016-09-07 04:57:50 +08:00
|
|
|
const break_id_t m_break_id;
|
2010-06-09 00:52:24 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
BreakpointList::bp_collection::iterator
|
2016-09-07 04:57:50 +08:00
|
|
|
BreakpointList::GetBreakpointIDIterator(break_id_t break_id) {
|
|
|
|
return std::find_if(m_breakpoints.begin(),
|
|
|
|
m_breakpoints.end(), // Search full range
|
|
|
|
BreakpointIDMatches(break_id)); // Predicate
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
BreakpointList::bp_collection::const_iterator
|
2016-09-07 04:57:50 +08:00
|
|
|
BreakpointList::GetBreakpointIDConstIterator(break_id_t break_id) const {
|
|
|
|
return std::find_if(m_breakpoints.begin(),
|
|
|
|
m_breakpoints.end(), // Search full range
|
|
|
|
BreakpointIDMatches(break_id)); // Predicate
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
BreakpointSP BreakpointList::FindBreakpointByID(break_id_t break_id) {
|
|
|
|
std::lock_guard<std::recursive_mutex> guard(m_mutex);
|
|
|
|
BreakpointSP stop_sp;
|
|
|
|
bp_collection::iterator pos = GetBreakpointIDIterator(break_id);
|
|
|
|
if (pos != m_breakpoints.end())
|
|
|
|
stop_sp = *pos;
|
2010-06-09 00:52:24 +08:00
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
return stop_sp;
|
2010-06-09 00:52:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
const BreakpointSP
|
2016-09-07 04:57:50 +08:00
|
|
|
BreakpointList::FindBreakpointByID(break_id_t break_id) const {
|
|
|
|
std::lock_guard<std::recursive_mutex> guard(m_mutex);
|
|
|
|
BreakpointSP stop_sp;
|
|
|
|
bp_collection::const_iterator pos = GetBreakpointIDConstIterator(break_id);
|
|
|
|
if (pos != m_breakpoints.end())
|
|
|
|
stop_sp = *pos;
|
|
|
|
|
|
|
|
return stop_sp;
|
|
|
|
}
|
|
|
|
|
2016-09-21 09:21:19 +08:00
|
|
|
bool BreakpointList::FindBreakpointsByName(const char *name,
|
|
|
|
BreakpointList &matching_bps) {
|
2017-05-12 12:51:55 +08:00
|
|
|
Status error;
|
2016-09-21 09:21:19 +08:00
|
|
|
if (!name)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!BreakpointID::StringIsBreakpointName(llvm::StringRef(name), error))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
for (BreakpointSP bkpt_sp : Breakpoints()) {
|
|
|
|
if (bkpt_sp->MatchesName(name)) {
|
|
|
|
matching_bps.Add(bkpt_sp, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2016-09-07 04:57:50 +08:00
|
|
|
void BreakpointList::Dump(Stream *s) const {
|
|
|
|
std::lock_guard<std::recursive_mutex> guard(m_mutex);
|
|
|
|
s->Printf("%p: ", static_cast<const void *>(this));
|
|
|
|
s->Indent();
|
|
|
|
s->Printf("BreakpointList with %u Breakpoints:\n",
|
|
|
|
(uint32_t)m_breakpoints.size());
|
|
|
|
s->IndentMore();
|
|
|
|
for (const auto &bp_sp : m_breakpoints)
|
|
|
|
bp_sp->Dump(s);
|
|
|
|
s->IndentLess();
|
|
|
|
}
|
|
|
|
|
|
|
|
BreakpointSP BreakpointList::GetBreakpointAtIndex(size_t i) {
|
|
|
|
std::lock_guard<std::recursive_mutex> guard(m_mutex);
|
|
|
|
BreakpointSP stop_sp;
|
|
|
|
bp_collection::iterator end = m_breakpoints.end();
|
|
|
|
bp_collection::iterator pos;
|
|
|
|
size_t curr_i = 0;
|
|
|
|
for (pos = m_breakpoints.begin(), curr_i = 0; pos != end; ++pos, ++curr_i) {
|
|
|
|
if (curr_i == i)
|
|
|
|
stop_sp = *pos;
|
|
|
|
}
|
|
|
|
return stop_sp;
|
|
|
|
}
|
|
|
|
|
|
|
|
const BreakpointSP BreakpointList::GetBreakpointAtIndex(size_t i) const {
|
|
|
|
std::lock_guard<std::recursive_mutex> guard(m_mutex);
|
|
|
|
BreakpointSP stop_sp;
|
|
|
|
bp_collection::const_iterator end = m_breakpoints.end();
|
|
|
|
bp_collection::const_iterator pos;
|
|
|
|
size_t curr_i = 0;
|
|
|
|
for (pos = m_breakpoints.begin(), curr_i = 0; pos != end; ++pos, ++curr_i) {
|
|
|
|
if (curr_i == i)
|
|
|
|
stop_sp = *pos;
|
|
|
|
}
|
|
|
|
return stop_sp;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BreakpointList::UpdateBreakpoints(ModuleList &module_list, bool added,
|
|
|
|
bool delete_locations) {
|
|
|
|
std::lock_guard<std::recursive_mutex> guard(m_mutex);
|
|
|
|
for (const auto &bp_sp : m_breakpoints)
|
|
|
|
bp_sp->ModulesChanged(module_list, added, delete_locations);
|
|
|
|
}
|
|
|
|
|
|
|
|
void BreakpointList::UpdateBreakpointsWhenModuleIsReplaced(
|
|
|
|
ModuleSP old_module_sp, ModuleSP new_module_sp) {
|
|
|
|
std::lock_guard<std::recursive_mutex> guard(m_mutex);
|
|
|
|
for (const auto &bp_sp : m_breakpoints)
|
|
|
|
bp_sp->ModuleReplaced(old_module_sp, new_module_sp);
|
|
|
|
}
|
|
|
|
|
|
|
|
void BreakpointList::ClearAllBreakpointSites() {
|
|
|
|
std::lock_guard<std::recursive_mutex> guard(m_mutex);
|
|
|
|
for (const auto &bp_sp : m_breakpoints)
|
|
|
|
bp_sp->ClearAllBreakpointSites();
|
|
|
|
}
|
|
|
|
|
|
|
|
void BreakpointList::GetListMutex(
|
|
|
|
std::unique_lock<std::recursive_mutex> &lock) {
|
|
|
|
lock = std::unique_lock<std::recursive_mutex>(m_mutex);
|
2010-06-16 10:00:15 +08:00
|
|
|
}
|