Make the Watchpoint IDs unique per target, not across targets as before.

Now Each newly created target has its Watchpoint IDs as 1, 2, 3 ...

llvm-svn: 151435
This commit is contained in:
Johnny Chen 2012-02-25 06:44:30 +00:00
parent e06a2c1893
commit a4d6bc9ff8
7 changed files with 182 additions and 76 deletions

View File

@ -51,10 +51,10 @@ public:
return m_addr;
}
virtual lldb::addr_t
SetLoadAddress () const
virtual void
SetLoadAddress (lldb::addr_t addr)
{
return m_addr;
m_addr = addr;
}
uint32_t

View File

@ -55,6 +55,7 @@ public:
bool SetCallback (WatchpointHitCallback callback, void *callback_baton);
void ClearCallback();
void SetDeclInfo (std::string &str);
void SetWatchSpec (std::string &str);
void GetDescription (Stream *s, lldb::DescriptionLevel level);
void Dump (Stream *s) const;
void DumpWithLevel (Stream *s, lldb::DescriptionLevel description_level) const;
@ -96,8 +97,11 @@ public:
private:
friend class Target;
friend class WatchpointList;
void SetTarget(Target *target_ptr) { m_target = target_ptr; }
std::string GetWatchSpec() { return m_watch_spec_str; }
void ResetHitCount() { m_hit_count = 0; }
Target *m_target;
bool m_enabled; // Is this watchpoint enabled
@ -110,12 +114,12 @@ private:
WatchpointHitCallback m_callback;
void * m_callback_baton; // Callback user data to pass to callback
std::string m_decl_str; // Declaration information, if any.
std::string m_watch_spec_str; // Spec for the watchpoint (for future use).
Error m_error; // An error object describing errors creating watchpoint.
std::auto_ptr<ClangUserExpression> m_condition_ap; // The condition to test.
static lldb::break_id_t
GetNextID();
void SetID(lldb::watch_id_t id) { m_loc_id = id; }
DISALLOW_COPY_AND_ASSIGN (Watchpoint);
};

View File

@ -12,8 +12,8 @@
// C Includes
// C++ Includes
#include <list>
#include <vector>
#include <map>
// Other libraries and framework includes
// Project includes
#include "lldb/lldb-private.h"
@ -35,6 +35,7 @@ class WatchpointList
// This is not just some random collection of watchpoints. Rather, the act of
// adding the watchpoint to this list sets its ID.
friend class Watchpoint;
friend class Target;
public:
//------------------------------------------------------------------
@ -72,7 +73,8 @@ public:
DumpWithLevel (Stream *s, lldb::DescriptionLevel description_level) const;
//------------------------------------------------------------------
/// Returns a shared pointer to the watchpoint at address /// \a addr -
/// Returns a shared pointer to the watchpoint at address
/// \a addr -
/// const version.
///
/// @param[in] addr
@ -86,10 +88,26 @@ public:
FindByAddress (lldb::addr_t addr) const;
//------------------------------------------------------------------
/// Returns a shared pointer to the watchpoint with id /// \a breakID, const
/// Returns a shared pointer to the watchpoint with watchpoint spec
/// \a spec -
/// const version.
///
/// @param[in] spec
/// The watchpoint spec to look for.
///
/// @result
/// A shared pointer to the watchpoint. May contain a NULL
/// pointer if the watchpoint doesn't exist.
//------------------------------------------------------------------
const lldb::WatchpointSP
FindBySpec (std::string spec) const;
//------------------------------------------------------------------
/// Returns a shared pointer to the watchpoint with id
/// \a watchID, const
/// version.
///
/// @param[in] breakID
/// @param[in] watchID
/// The watchpoint location ID to seek for.
///
/// @result
@ -100,7 +118,8 @@ public:
FindByID (lldb::watch_id_t watchID) const;
//------------------------------------------------------------------
/// Returns the watchpoint id to the watchpoint /// at address \a addr.
/// Returns the watchpoint id to the watchpoint
/// at address \a addr.
///
/// @param[in] addr
/// The address to match.
@ -111,6 +130,19 @@ public:
lldb::watch_id_t
FindIDByAddress (lldb::addr_t addr);
//------------------------------------------------------------------
/// Returns the watchpoint id to the watchpoint
/// with watchpoint spec \a spec.
///
/// @param[in] spec
/// The watchpoint spec to match.
///
/// @result
/// The ID of the watchpoint, or LLDB_INVALID_WATCH_ID.
//------------------------------------------------------------------
lldb::watch_id_t
FindIDBySpec (std::string spec);
//------------------------------------------------------------------
/// Returns a shared pointer to the watchpoint with index \a i.
///
@ -186,7 +218,7 @@ public:
GetSize() const
{
Mutex::Locker locker(m_mutex);
return m_address_to_watchpoint.size();
return m_watchpoints.size();
}
//------------------------------------------------------------------
@ -221,16 +253,22 @@ public:
GetListMutex (lldb_private::Mutex::Locker &locker);
protected:
typedef std::map<lldb::addr_t, lldb::WatchpointSP> addr_map;
typedef std::list<lldb::WatchpointSP> wp_collection;
typedef std::vector<lldb::watch_id_t> id_vector;
addr_map::iterator
id_vector
GetWatchpointIDs() const;
wp_collection::iterator
GetIDIterator(lldb::watch_id_t watchID);
addr_map::const_iterator
wp_collection::const_iterator
GetIDConstIterator(lldb::watch_id_t watchID) const;
addr_map m_address_to_watchpoint;
wp_collection m_watchpoints;
mutable Mutex m_mutex;
lldb::watch_id_t m_next_wp_id;
};
} // namespace lldb_private

View File

@ -527,6 +527,9 @@ public:
bool
EnableAllWatchpoints (bool end_to_end = true);
bool
ClearAllWatchpointHitCounts ();
bool
IgnoreAllWatchpoints (uint32_t ignore_count);

View File

@ -24,9 +24,9 @@ using namespace lldb;
using namespace lldb_private;
Watchpoint::Watchpoint (lldb::addr_t addr, size_t size, bool hardware) :
StoppointLocation (GetNextID(), addr, size, hardware),
StoppointLocation (0, addr, size, hardware),
m_target(NULL),
m_enabled(0),
m_enabled(false),
m_is_hardware(hardware),
m_watch_read(0),
m_watch_write(0),
@ -36,6 +36,7 @@ Watchpoint::Watchpoint (lldb::addr_t addr, size_t size, bool hardware) :
m_callback(NULL),
m_callback_baton(NULL),
m_decl_str(),
m_watch_spec_str(),
m_error()
{
}
@ -44,13 +45,6 @@ Watchpoint::~Watchpoint()
{
}
break_id_t
Watchpoint::GetNextID()
{
static break_id_t g_next_ID = 0;
return ++g_next_ID;
}
bool
Watchpoint::SetCallback (WatchpointHitCallback callback, void *callback_baton)
{
@ -66,6 +60,13 @@ Watchpoint::SetDeclInfo (std::string &str)
return;
}
void
Watchpoint::SetWatchSpec (std::string &str)
{
m_watch_spec_str = str;
return;
}
// Override default impl of StoppointLocation::IsHardware() since m_is_hardware
// member field is more accurate.
bool
@ -117,13 +118,15 @@ Watchpoint::DumpWithLevel(Stream *s, lldb::DescriptionLevel description_level) c
GetID(),
GetLoadAddress(),
m_byte_size,
m_enabled ? "enabled" : "disabled",
IsEnabled() ? "enabled" : "disabled",
m_watch_read ? "r" : "",
m_watch_write ? "w" : "");
if (description_level >= lldb::eDescriptionLevelFull) {
if (!m_decl_str.empty())
s->Printf("\n declare @ '%s'", m_decl_str.c_str());
if (!m_watch_spec_str.empty())
s->Printf("\n static watchpoint spec = '%s'", m_watch_spec_str.c_str());
if (GetConditionText())
s->Printf("\n condition = '%s'", GetConditionText());
}

View File

@ -19,8 +19,9 @@ using namespace lldb;
using namespace lldb_private;
WatchpointList::WatchpointList() :
m_address_to_watchpoint (),
m_mutex (Mutex::eMutexTypeRecursive)
m_watchpoints (),
m_mutex (Mutex::eMutexTypeRecursive),
m_next_wp_id (0)
{
}
@ -28,21 +29,13 @@ WatchpointList::~WatchpointList()
{
}
// Add watchpoint loc to the list. However, if the element already exists in the
// list, then replace it with the input one.
// Add a watchpoint to the list.
lldb::watch_id_t
WatchpointList::Add (const WatchpointSP &wp_sp)
{
Mutex::Locker locker (m_mutex);
lldb::addr_t wp_addr = wp_sp->GetLoadAddress();
addr_map::iterator iter = m_address_to_watchpoint.find(wp_addr);
if (iter == m_address_to_watchpoint.end())
m_address_to_watchpoint.insert(iter, addr_map::value_type(wp_addr, wp_sp));
else
m_address_to_watchpoint[wp_addr] = wp_sp;
wp_sp->SetID(++m_next_wp_id);
m_watchpoints.push_back(wp_sp);
return wp_sp->GetID();
}
@ -59,11 +52,11 @@ WatchpointList::DumpWithLevel (Stream *s, lldb::DescriptionLevel description_lev
s->Printf("%p: ", this);
//s->Indent();
s->Printf("WatchpointList with %zu Watchpoints:\n",
m_address_to_watchpoint.size());
m_watchpoints.size());
s->IndentMore();
addr_map::const_iterator pos, end = m_address_to_watchpoint.end();
for (pos = m_address_to_watchpoint.begin(); pos != end; ++pos)
pos->second->DumpWithLevel(s, description_level);
wp_collection::const_iterator pos, end = m_watchpoints.end();
for (pos = m_watchpoints.begin(); pos != end; ++pos)
(*pos)->DumpWithLevel(s, description_level);
s->IndentLess();
}
@ -72,11 +65,32 @@ WatchpointList::FindByAddress (lldb::addr_t addr) const
{
WatchpointSP wp_sp;
Mutex::Locker locker (m_mutex);
if (!m_address_to_watchpoint.empty())
if (!m_watchpoints.empty())
{
addr_map::const_iterator pos = m_address_to_watchpoint.find (addr);
if (pos != m_address_to_watchpoint.end())
wp_sp = pos->second;
wp_collection::const_iterator pos, end = m_watchpoints.end();
for (pos = m_watchpoints.begin(); pos != end; ++pos)
if ((*pos)->GetLoadAddress() == addr) {
wp_sp = *pos;
break;
}
}
return wp_sp;
}
const WatchpointSP
WatchpointList::FindBySpec (std::string spec) const
{
WatchpointSP wp_sp;
Mutex::Locker locker (m_mutex);
if (!m_watchpoints.empty())
{
wp_collection::const_iterator pos, end = m_watchpoints.end();
for (pos = m_watchpoints.begin(); pos != end; ++pos)
if ((*pos)->GetWatchSpec() == spec) {
wp_sp = *pos;
break;
}
}
return wp_sp;
@ -90,27 +104,27 @@ public:
{
}
bool operator() (std::pair <lldb::addr_t, WatchpointSP> val_pair) const
bool operator() (const WatchpointSP &wp) const
{
return m_watch_id == val_pair.second.get()->GetID();
return m_watch_id == wp->GetID();
}
private:
const lldb::watch_id_t m_watch_id;
};
WatchpointList::addr_map::iterator
WatchpointList::wp_collection::iterator
WatchpointList::GetIDIterator (lldb::watch_id_t watch_id)
{
return std::find_if(m_address_to_watchpoint.begin(), m_address_to_watchpoint.end(), // Search full range
WatchpointIDMatches(watch_id)); // Predicate
return std::find_if(m_watchpoints.begin(), m_watchpoints.end(), // Search full range
WatchpointIDMatches(watch_id)); // Predicate
}
WatchpointList::addr_map::const_iterator
WatchpointList::wp_collection::const_iterator
WatchpointList::GetIDConstIterator (lldb::watch_id_t watch_id) const
{
return std::find_if(m_address_to_watchpoint.begin(), m_address_to_watchpoint.end(), // Search full range
WatchpointIDMatches(watch_id)); // Predicate
return std::find_if(m_watchpoints.begin(), m_watchpoints.end(), // Search full range
WatchpointIDMatches(watch_id)); // Predicate
}
WatchpointSP
@ -118,9 +132,9 @@ WatchpointList::FindByID (lldb::watch_id_t watch_id) const
{
WatchpointSP wp_sp;
Mutex::Locker locker (m_mutex);
addr_map::const_iterator pos = GetIDConstIterator(watch_id);
if (pos != m_address_to_watchpoint.end())
wp_sp = pos->second;
wp_collection::const_iterator pos = GetIDConstIterator(watch_id);
if (pos != m_watchpoints.end())
wp_sp = *pos;
return wp_sp;
}
@ -136,16 +150,27 @@ WatchpointList::FindIDByAddress (lldb::addr_t addr)
return LLDB_INVALID_WATCH_ID;
}
lldb::watch_id_t
WatchpointList::FindIDBySpec (std::string spec)
{
WatchpointSP wp_sp = FindBySpec (spec);
if (wp_sp)
{
return wp_sp->GetID();
}
return LLDB_INVALID_WATCH_ID;
}
WatchpointSP
WatchpointList::GetByIndex (uint32_t i)
{
Mutex::Locker locker (m_mutex);
WatchpointSP wp_sp;
if (i < m_address_to_watchpoint.size())
if (i < m_watchpoints.size())
{
addr_map::const_iterator pos = m_address_to_watchpoint.begin();
wp_collection::const_iterator pos = m_watchpoints.begin();
std::advance(pos, i);
wp_sp = pos->second;
wp_sp = *pos;
}
return wp_sp;
}
@ -155,23 +180,33 @@ WatchpointList::GetByIndex (uint32_t i) const
{
Mutex::Locker locker (m_mutex);
WatchpointSP wp_sp;
if (i < m_address_to_watchpoint.size())
if (i < m_watchpoints.size())
{
addr_map::const_iterator pos = m_address_to_watchpoint.begin();
wp_collection::const_iterator pos = m_watchpoints.begin();
std::advance(pos, i);
wp_sp = pos->second;
wp_sp = *pos;
}
return wp_sp;
}
std::vector<lldb::watch_id_t>
WatchpointList::GetWatchpointIDs() const
{
std::vector<lldb::watch_id_t> IDs;
wp_collection::const_iterator pos, end = m_watchpoints.end();
for (pos = m_watchpoints.begin(); pos != end; ++pos)
IDs.push_back((*pos)->GetID());
return IDs;
}
bool
WatchpointList::Remove (lldb::watch_id_t watch_id)
{
Mutex::Locker locker (m_mutex);
addr_map::iterator pos = GetIDIterator(watch_id);
if (pos != m_address_to_watchpoint.end())
wp_collection::iterator pos = GetIDIterator(watch_id);
if (pos != m_watchpoints.end())
{
m_address_to_watchpoint.erase(pos);
m_watchpoints.erase(pos);
return true;
}
return false;
@ -182,9 +217,9 @@ WatchpointList::GetHitCount () const
{
uint32_t hit_count = 0;
Mutex::Locker locker (m_mutex);
addr_map::const_iterator pos, end = m_address_to_watchpoint.end();
for (pos = m_address_to_watchpoint.begin(); pos != end; ++pos)
hit_count += pos->second->GetHitCount();
wp_collection::const_iterator pos, end = m_watchpoints.end();
for (pos = m_watchpoints.begin(); pos != end; ++pos)
hit_count += (*pos)->GetHitCount();
return hit_count;
}
@ -209,12 +244,12 @@ void
WatchpointList::GetDescription (Stream *s, lldb::DescriptionLevel level)
{
Mutex::Locker locker (m_mutex);
addr_map::iterator pos, end = m_address_to_watchpoint.end();
wp_collection::iterator pos, end = m_watchpoints.end();
for (pos = m_address_to_watchpoint.begin(); pos != end; ++pos)
for (pos = m_watchpoints.begin(); pos != end; ++pos)
{
s->Printf(" ");
pos->second->Dump(s);
(*pos)->Dump(s);
}
}
@ -223,16 +258,16 @@ WatchpointList::SetEnabledAll (bool enabled)
{
Mutex::Locker locker(m_mutex);
addr_map::iterator pos, end = m_address_to_watchpoint.end();
for (pos = m_address_to_watchpoint.begin(); pos != end; ++pos)
pos->second->SetEnabled (enabled);
wp_collection::iterator pos, end = m_watchpoints.end();
for (pos = m_watchpoints.begin(); pos != end; ++pos)
(*pos)->SetEnabled (enabled);
}
void
WatchpointList::RemoveAll ()
{
Mutex::Locker locker(m_mutex);
m_address_to_watchpoint.clear();
m_watchpoints.clear();
}
void

View File

@ -138,7 +138,10 @@ Target::DeleteCurrentProcess ()
m_breakpoint_list.ClearAllBreakpointSites();
m_internal_breakpoint_list.ClearAllBreakpointSites();
// Disable watchpoints just on the debugger side.
Mutex::Locker locker;
this->GetWatchpointList().GetListMutex(locker);
DisableAllWatchpoints(false);
ClearAllWatchpointHitCounts();
m_process_sp.reset();
}
}
@ -672,6 +675,26 @@ Target::EnableAllWatchpoints (bool end_to_end)
return true; // Success!
}
// Assumption: Caller holds the list mutex lock for m_watchpoint_list.
bool
Target::ClearAllWatchpointHitCounts ()
{
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_WATCHPOINTS));
if (log)
log->Printf ("Target::%s\n", __FUNCTION__);
size_t num_watchpoints = m_watchpoint_list.GetSize();
for (size_t i = 0; i < num_watchpoints; ++i)
{
WatchpointSP wp_sp = m_watchpoint_list.GetByIndex(i);
if (!wp_sp)
return false;
wp_sp->ResetHitCount();
}
return true; // Success!
}
// Assumption: Caller holds the list mutex lock for m_watchpoint_list
// during these operations.
bool