BreakpointLocation::ShouldStop. That worked but wasn't really right, since there's nothing to guarantee that won't get called more than once. So this change moves that responsibility to the StopInfoBreakpoint directly, and then it uses the BreakpointSite to actually do the bumping. Also fix a test case that was assuming if you had many threads running some code with a breakpoint in it, the hit count when you stopped would always be 1. Many of the threads could have hit it at the same time... <rdar://problem/18577603> llvm-svn: 220358
200 lines
5.5 KiB
C++
200 lines
5.5 KiB
C++
//===-- BreakpointLocationCollection.cpp ------------------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
// C Includes
|
|
// C++ Includes
|
|
// Other libraries and framework includes
|
|
// Project includes
|
|
#include "lldb/Breakpoint/BreakpointLocationCollection.h"
|
|
#include "lldb/Core/ModuleList.h"
|
|
#include "lldb/Breakpoint/Breakpoint.h"
|
|
#include "lldb/Breakpoint/BreakpointLocation.h"
|
|
#include "lldb/Target/Thread.h"
|
|
#include "lldb/Target/ThreadSpec.h"
|
|
|
|
using namespace lldb;
|
|
using namespace lldb_private;
|
|
|
|
//----------------------------------------------------------------------
|
|
// BreakpointLocationCollection constructor
|
|
//----------------------------------------------------------------------
|
|
BreakpointLocationCollection::BreakpointLocationCollection() :
|
|
m_break_loc_collection()
|
|
{
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// Destructor
|
|
//----------------------------------------------------------------------
|
|
BreakpointLocationCollection::~BreakpointLocationCollection()
|
|
{
|
|
}
|
|
|
|
void
|
|
BreakpointLocationCollection::Add(const BreakpointLocationSP &bp_loc)
|
|
{
|
|
BreakpointLocationSP old_bp_loc = FindByIDPair (bp_loc->GetBreakpoint().GetID(), bp_loc->GetID());
|
|
if (!old_bp_loc.get())
|
|
m_break_loc_collection.push_back(bp_loc);
|
|
}
|
|
|
|
bool
|
|
BreakpointLocationCollection::Remove (lldb::break_id_t bp_id, lldb::break_id_t bp_loc_id)
|
|
{
|
|
collection::iterator pos = GetIDPairIterator(bp_id, bp_loc_id); // Predicate
|
|
if (pos != m_break_loc_collection.end())
|
|
{
|
|
m_break_loc_collection.erase(pos);
|
|
return true;
|
|
}
|
|
return false;
|
|
|
|
}
|
|
|
|
class BreakpointIDPairMatches
|
|
{
|
|
public:
|
|
BreakpointIDPairMatches (lldb::break_id_t break_id, lldb::break_id_t break_loc_id) :
|
|
m_break_id(break_id),
|
|
m_break_loc_id (break_loc_id)
|
|
{
|
|
}
|
|
|
|
bool operator() (const BreakpointLocationSP &bp_loc) const
|
|
{
|
|
return m_break_id == bp_loc->GetBreakpoint().GetID()
|
|
&& m_break_loc_id == bp_loc->GetID();
|
|
}
|
|
|
|
private:
|
|
const lldb::break_id_t m_break_id;
|
|
const lldb::break_id_t m_break_loc_id;
|
|
};
|
|
|
|
BreakpointLocationCollection::collection::iterator
|
|
BreakpointLocationCollection::GetIDPairIterator (lldb::break_id_t break_id, lldb::break_id_t break_loc_id)
|
|
{
|
|
return std::find_if(m_break_loc_collection.begin(), m_break_loc_collection.end(), // Search full range
|
|
BreakpointIDPairMatches(break_id, break_loc_id)); // Predicate
|
|
}
|
|
|
|
BreakpointLocationCollection::collection::const_iterator
|
|
BreakpointLocationCollection::GetIDPairConstIterator (lldb::break_id_t break_id, lldb::break_id_t break_loc_id) const
|
|
{
|
|
return std::find_if(m_break_loc_collection.begin(), m_break_loc_collection.end(), // Search full range
|
|
BreakpointIDPairMatches(break_id, break_loc_id)); // Predicate
|
|
}
|
|
|
|
BreakpointLocationSP
|
|
BreakpointLocationCollection::FindByIDPair (lldb::break_id_t break_id, lldb::break_id_t break_loc_id)
|
|
{
|
|
BreakpointLocationSP stop_sp;
|
|
collection::iterator pos = GetIDPairIterator(break_id, break_loc_id);
|
|
if (pos != m_break_loc_collection.end())
|
|
stop_sp = *pos;
|
|
|
|
return stop_sp;
|
|
}
|
|
|
|
const BreakpointLocationSP
|
|
BreakpointLocationCollection::FindByIDPair (lldb::break_id_t break_id, lldb::break_id_t break_loc_id) const
|
|
{
|
|
BreakpointLocationSP stop_sp;
|
|
collection::const_iterator pos = GetIDPairConstIterator(break_id, break_loc_id);
|
|
if (pos != m_break_loc_collection.end())
|
|
stop_sp = *pos;
|
|
|
|
return stop_sp;
|
|
}
|
|
|
|
BreakpointLocationSP
|
|
BreakpointLocationCollection::GetByIndex (size_t i)
|
|
{
|
|
BreakpointLocationSP stop_sp;
|
|
if (i < m_break_loc_collection.size())
|
|
stop_sp = m_break_loc_collection[i];
|
|
|
|
return stop_sp;
|
|
}
|
|
|
|
const BreakpointLocationSP
|
|
BreakpointLocationCollection::GetByIndex (size_t i) const
|
|
{
|
|
BreakpointLocationSP stop_sp;
|
|
if (i < m_break_loc_collection.size())
|
|
stop_sp = m_break_loc_collection[i];
|
|
|
|
return stop_sp;
|
|
}
|
|
|
|
bool
|
|
BreakpointLocationCollection::ShouldStop (StoppointCallbackContext *context)
|
|
{
|
|
bool shouldStop = false;
|
|
const size_t count = GetSize();
|
|
for (size_t i = 0; i < count; i++)
|
|
{
|
|
if (GetByIndex(i)->ShouldStop(context))
|
|
shouldStop = true;
|
|
}
|
|
return shouldStop;
|
|
}
|
|
|
|
bool
|
|
BreakpointLocationCollection::ValidForThisThread (Thread *thread)
|
|
{
|
|
collection::iterator pos,
|
|
begin = m_break_loc_collection.begin(),
|
|
end = m_break_loc_collection.end();
|
|
|
|
for (pos = begin; pos != end; ++pos)
|
|
{
|
|
if ((*pos)->ValidForThisThread (thread))
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
BreakpointLocationCollection::IsInternal () const
|
|
{
|
|
collection::const_iterator pos,
|
|
begin = m_break_loc_collection.begin(),
|
|
end = m_break_loc_collection.end();
|
|
|
|
bool is_internal = true;
|
|
|
|
for (pos = begin; pos != end; ++pos)
|
|
{
|
|
if (!(*pos)->GetBreakpoint().IsInternal ())
|
|
{
|
|
is_internal = false;
|
|
break;
|
|
}
|
|
}
|
|
return is_internal;
|
|
}
|
|
|
|
void
|
|
BreakpointLocationCollection::GetDescription (Stream *s, lldb::DescriptionLevel level)
|
|
{
|
|
collection::iterator pos,
|
|
begin = m_break_loc_collection.begin(),
|
|
end = m_break_loc_collection.end();
|
|
|
|
for (pos = begin; pos != end; ++pos)
|
|
{
|
|
if (pos != begin)
|
|
s->PutChar(' ');
|
|
(*pos)->GetDescription(s, level);
|
|
}
|
|
}
|
|
|