Files
clang-p2996/lldb/source/Breakpoint/BreakpointSiteList.cpp
Greg Clayton f4b47e1579 Abtracted the old "lldb_private::Thread::StopInfo" into an abtract class.
This will allow debugger plug-ins to make any instance of "lldb_private::StopInfo"
that can completely describe any stop reason. It also provides a framework for
doing intelligent things with the stop info at important times in the lifetime
of the inferior. 

Examples include the signal stop info in StopInfoUnixSignal. It will check with
the process to see that the current action is for the signal. These actions
include wether to stop for the signal, wether the notify that the signal was
hit, and wether to pass the signal along to the inferior process. The 
StopInfoUnixSignal class overrides the "ShouldStop()" method of StopInfo and
this allows the stop info to determine if it should stop at the signal or 
continue the process. 


StopInfo subclasses must override the following functions:

    virtual lldb::StopReason
    GetStopReason () const = 0;

    virtual const char *
    GetDescription () = 0;


StopInfo subclasses can override the following functions:


    // If the subclass returns "false", the inferior will resume. The default
    // version of this function returns "true" which means the default stop
    // info will stop the process. The breakpoint subclass will check if
    // the breakpoint wants us to stop by calling any installed callback on
    // the breakpoint, and also checking if the breakpoint is for the current
    // thread. Signals will check if they should stop based off of the 
    // UnixSignal settings in the process.
    virtual bool
    ShouldStop (Event *event_ptr);

    // Sublasses can state if they want to notify the debugger when "ShouldStop"
    // returns false. This would be handy for breakpoints where you want to
    // log information and continue and is also used by the signal stop info
    // to notify that a signal was received (after it checks with the process
    // signal settings).
    virtual bool
    ShouldNotify (Event *event_ptr)
    {
        return false;
    }

    // Allow subclasses to do something intelligent right before we resume.
    // The signal class will figure out if the signal should be propagated
    // to the inferior process and pass that along to the debugger plug-ins.
    virtual void
    WillResume (lldb::StateType resume_state)
    {
        // By default, don't do anything
    }


The support the Mach exceptions was moved into the lldb/source/Plugins/Process/Utility
folder and now doesn't polute the lldb_private::Thread class with platform
specific code.

llvm-svn: 110184
2010-08-04 01:40:35 +00:00

231 lines
6.2 KiB
C++

//===-- BreakpointSiteList.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/BreakpointSiteList.h"
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Core/Stream.h"
#include <algorithm>
using namespace lldb;
using namespace lldb_private;
BreakpointSiteList::BreakpointSiteList() :
m_bp_site_list()
{
}
BreakpointSiteList::~BreakpointSiteList()
{
}
// Add breakpoint site to the list. However, if the element already exists in the
// list, then we don't add it, and return LLDB_INVALID_BREAK_ID.
lldb::break_id_t
BreakpointSiteList::Add(const BreakpointSiteSP &bp)
{
lldb::addr_t bp_site_load_addr = bp->GetLoadAddress();
collection::iterator iter = m_bp_site_list.find (bp_site_load_addr);
if (iter == m_bp_site_list.end())
{
m_bp_site_list.insert (iter, collection::value_type (bp_site_load_addr, bp));
return bp->GetID();
}
else
{
return LLDB_INVALID_BREAK_ID;
}
}
bool
BreakpointSiteList::ShouldStop (StoppointCallbackContext *context, lldb::break_id_t site_id)
{
BreakpointSiteSP site_sp (FindByID (site_id));
if (site_sp)
{
// Let the BreakpointSite 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 BreakpointSite isn't valid anymore or it
// doesn't exist.
return true;
}
lldb::break_id_t
BreakpointSiteList::FindIDByAddress (lldb::addr_t addr)
{
BreakpointSiteSP bp = FindByAddress (addr);
if (bp)
{
//DBLogIf(PD_LOG_BREAKPOINTS, "BreakpointSiteList::%s ( addr = 0x%8.8llx ) => %u", __FUNCTION__, (uint64_t)addr, bp->GetID());
return bp.get()->GetID();
}
//DBLogIf(PD_LOG_BREAKPOINTS, "BreakpointSiteList::%s ( addr = 0x%8.8llx ) => NONE", __FUNCTION__, (uint64_t)addr);
return LLDB_INVALID_BREAK_ID;
}
bool
BreakpointSiteList::Remove (lldb::break_id_t break_id)
{
collection::iterator pos = GetIDIterator(break_id); // Predicate
if (pos != m_bp_site_list.end())
{
m_bp_site_list.erase(pos);
return true;
}
return false;
}
bool
BreakpointSiteList::RemoveByAddress (lldb::addr_t address)
{
collection::iterator pos = m_bp_site_list.find(address);
if (pos != m_bp_site_list.end())
{
m_bp_site_list.erase(pos);
return true;
}
return false;
}
class BreakpointSiteIDMatches
{
public:
BreakpointSiteIDMatches (lldb::break_id_t break_id) :
m_break_id(break_id)
{
}
bool operator() (std::pair <lldb::addr_t, BreakpointSiteSP> val_pair) const
{
return m_break_id == val_pair.second.get()->GetID();
}
private:
const lldb::break_id_t m_break_id;
};
BreakpointSiteList::collection::iterator
BreakpointSiteList::GetIDIterator (lldb::break_id_t break_id)
{
return std::find_if(m_bp_site_list.begin(), m_bp_site_list.end(), // Search full range
BreakpointSiteIDMatches(break_id)); // Predicate
}
BreakpointSiteList::collection::const_iterator
BreakpointSiteList::GetIDConstIterator (lldb::break_id_t break_id) const
{
return std::find_if(m_bp_site_list.begin(), m_bp_site_list.end(), // Search full range
BreakpointSiteIDMatches(break_id)); // Predicate
}
BreakpointSiteSP
BreakpointSiteList::FindByID (lldb::break_id_t break_id)
{
BreakpointSiteSP stop_sp;
collection::iterator pos = GetIDIterator(break_id);
if (pos != m_bp_site_list.end())
stop_sp = pos->second;
return stop_sp;
}
const BreakpointSiteSP
BreakpointSiteList::FindByID (lldb::break_id_t break_id) const
{
BreakpointSiteSP stop_sp;
collection::const_iterator pos = GetIDConstIterator(break_id);
if (pos != m_bp_site_list.end())
stop_sp = pos->second;
return stop_sp;
}
BreakpointSiteSP
BreakpointSiteList::FindByAddress (lldb::addr_t addr)
{
BreakpointSiteSP found_sp;
collection::iterator iter = m_bp_site_list.find(addr);
if (iter != m_bp_site_list.end())
found_sp = iter->second;
return found_sp;
}
void
BreakpointSiteList::Dump (Stream *s) const
{
s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
s->Indent();
s->Printf("BreakpointSiteList with %u BreakpointSites:\n", (uint32_t)m_bp_site_list.size());
s->IndentMore();
collection::const_iterator pos;
collection::const_iterator end = m_bp_site_list.end();
for (pos = m_bp_site_list.begin(); pos != end; ++pos)
pos->second.get()->Dump(s);
s->IndentLess();
}
BreakpointSiteSP
BreakpointSiteList::GetByIndex (uint32_t i)
{
BreakpointSiteSP stop_sp;
collection::iterator end = m_bp_site_list.end();
collection::iterator pos;
uint32_t curr_i = 0;
for (pos = m_bp_site_list.begin(), curr_i = 0; pos != end; ++pos, ++curr_i)
{
if (curr_i == i)
stop_sp = pos->second;
}
return stop_sp;
}
const BreakpointSiteSP
BreakpointSiteList::GetByIndex (uint32_t i) const
{
BreakpointSiteSP stop_sp;
collection::const_iterator end = m_bp_site_list.end();
collection::const_iterator pos;
uint32_t curr_i = 0;
for (pos = m_bp_site_list.begin(), curr_i = 0; pos != end; ++pos, ++curr_i)
{
if (curr_i == i)
stop_sp = pos->second;
}
return stop_sp;
}
void
BreakpointSiteList::SetEnabledForAll (const bool enabled, const lldb::break_id_t except_id)
{
collection::iterator end = m_bp_site_list.end();
collection::iterator pos;
for (pos = m_bp_site_list.begin(); pos != end; ++pos)
{
if (except_id != LLDB_INVALID_BREAK_ID && except_id != pos->second->GetID())
pos->second->SetEnabled (enabled);
else
pos->second->SetEnabled (!enabled);
}
}
const BreakpointSiteList::collection *
BreakpointSiteList::GetMap ()
{
return &m_bp_site_list;
}