BreakpointSiteList.cpp revision 7e5fa7fc1f8efd24c078e063b2c4b5e13ba5be20
1//===-- BreakpointSiteList.cpp ----------------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/Breakpoint/BreakpointSiteList.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
16#include "lldb/Core/Stream.h"
17#include <algorithm>
18
19using namespace lldb;
20using namespace lldb_private;
21
22BreakpointSiteList::BreakpointSiteList() :
23    m_bp_site_list()
24{
25}
26
27BreakpointSiteList::~BreakpointSiteList()
28{
29}
30
31// Add breakpoint site to the list.  However, if the element already exists in the
32// list, then we don't add it, and return LLDB_INVALID_BREAK_ID.
33
34lldb::break_id_t
35BreakpointSiteList::Add(const BreakpointSiteSP &bp)
36{
37    lldb::addr_t bp_site_load_addr = bp->GetLoadAddress();
38    collection::iterator iter = m_bp_site_list.find (bp_site_load_addr);
39
40    if (iter == m_bp_site_list.end())
41    {
42        m_bp_site_list.insert (iter, collection::value_type (bp_site_load_addr, bp));
43        return bp->GetID();
44    }
45    else
46    {
47        return LLDB_INVALID_BREAK_ID;
48    }
49}
50
51bool
52BreakpointSiteList::ShouldStop (StoppointCallbackContext *context, lldb::break_id_t site_id)
53{
54    BreakpointSiteSP site_sp (FindByID (site_id));
55    if (site_sp)
56    {
57        // Let the BreakpointSite decide if it should stop here (could not have
58        // reached it's target hit count yet, or it could have a callback
59        // that decided it shouldn't stop (shared library loads/unloads).
60        return site_sp->ShouldStop (context);
61    }
62    // We should stop here since this BreakpointSite isn't valid anymore or it
63    // doesn't exist.
64    return true;
65}
66lldb::break_id_t
67BreakpointSiteList::FindIDByAddress (lldb::addr_t addr)
68{
69    BreakpointSiteSP bp = FindByAddress (addr);
70    if (bp)
71    {
72        //DBLogIf(PD_LOG_BREAKPOINTS, "BreakpointSiteList::%s ( addr = 0x%8.8llx ) => %u", __FUNCTION__, (uint64_t)addr, bp->GetID());
73        return bp.get()->GetID();
74    }
75    //DBLogIf(PD_LOG_BREAKPOINTS, "BreakpointSiteList::%s ( addr = 0x%8.8llx ) => NONE", __FUNCTION__, (uint64_t)addr);
76    return LLDB_INVALID_BREAK_ID;
77}
78
79bool
80BreakpointSiteList::Remove (lldb::break_id_t break_id)
81{
82    collection::iterator pos = GetIDIterator(break_id);    // Predicate
83    if (pos != m_bp_site_list.end())
84    {
85        m_bp_site_list.erase(pos);
86        return true;
87    }
88    return false;
89}
90
91bool
92BreakpointSiteList::RemoveByAddress (lldb::addr_t address)
93{
94    collection::iterator pos =  m_bp_site_list.find(address);
95    if (pos != m_bp_site_list.end())
96    {
97        m_bp_site_list.erase(pos);
98        return true;
99    }
100    return false;
101}
102
103class BreakpointSiteIDMatches
104{
105public:
106    BreakpointSiteIDMatches (lldb::break_id_t break_id) :
107        m_break_id(break_id)
108    {
109    }
110
111    bool operator() (std::pair <lldb::addr_t, BreakpointSiteSP> val_pair) const
112    {
113        return m_break_id == val_pair.second.get()->GetID();
114    }
115
116private:
117   const lldb::break_id_t m_break_id;
118};
119
120BreakpointSiteList::collection::iterator
121BreakpointSiteList::GetIDIterator (lldb::break_id_t break_id)
122{
123    return std::find_if(m_bp_site_list.begin(), m_bp_site_list.end(),   // Search full range
124                        BreakpointSiteIDMatches(break_id));             // Predicate
125}
126
127BreakpointSiteList::collection::const_iterator
128BreakpointSiteList::GetIDConstIterator (lldb::break_id_t break_id) const
129{
130    return std::find_if(m_bp_site_list.begin(), m_bp_site_list.end(),   // Search full range
131                        BreakpointSiteIDMatches(break_id));             // Predicate
132}
133
134BreakpointSiteSP
135BreakpointSiteList::FindByID (lldb::break_id_t break_id)
136{
137    BreakpointSiteSP stop_sp;
138    collection::iterator pos = GetIDIterator(break_id);
139    if (pos != m_bp_site_list.end())
140        stop_sp = pos->second;
141
142    return stop_sp;
143}
144
145const BreakpointSiteSP
146BreakpointSiteList::FindByID (lldb::break_id_t break_id) const
147{
148    BreakpointSiteSP stop_sp;
149    collection::const_iterator pos = GetIDConstIterator(break_id);
150    if (pos != m_bp_site_list.end())
151        stop_sp = pos->second;
152
153    return stop_sp;
154}
155
156BreakpointSiteSP
157BreakpointSiteList::FindByAddress (lldb::addr_t addr)
158{
159    BreakpointSiteSP found_sp;
160
161    collection::iterator iter =  m_bp_site_list.find(addr);
162    if (iter != m_bp_site_list.end())
163        found_sp = iter->second;
164    return found_sp;
165}
166
167void
168BreakpointSiteList::Dump (Stream *s) const
169{
170    s->Printf("%p: ", this);
171    //s->Indent();
172    s->Printf("BreakpointSiteList with %u BreakpointSites:\n", (uint32_t)m_bp_site_list.size());
173    s->IndentMore();
174    collection::const_iterator pos;
175    collection::const_iterator end = m_bp_site_list.end();
176    for (pos = m_bp_site_list.begin(); pos != end; ++pos)
177        pos->second.get()->Dump(s);
178    s->IndentLess();
179}
180
181
182BreakpointSiteSP
183BreakpointSiteList::GetByIndex (uint32_t i)
184{
185    BreakpointSiteSP stop_sp;
186    collection::iterator end = m_bp_site_list.end();
187    collection::iterator pos;
188    uint32_t curr_i = 0;
189    for (pos = m_bp_site_list.begin(), curr_i = 0; pos != end; ++pos, ++curr_i)
190    {
191        if (curr_i == i)
192            stop_sp = pos->second;
193    }
194    return stop_sp;
195}
196
197const BreakpointSiteSP
198BreakpointSiteList::GetByIndex (uint32_t i) const
199{
200    BreakpointSiteSP stop_sp;
201    collection::const_iterator end = m_bp_site_list.end();
202    collection::const_iterator pos;
203    uint32_t curr_i = 0;
204    for (pos = m_bp_site_list.begin(), curr_i = 0; pos != end; ++pos, ++curr_i)
205    {
206        if (curr_i == i)
207            stop_sp = pos->second;
208    }
209    return stop_sp;
210}
211
212bool
213BreakpointSiteList::FindInRange (lldb::addr_t lower_bound, lldb::addr_t upper_bound, BreakpointSiteList &bp_site_list) const
214{
215
216    if (lower_bound > upper_bound)
217        return false;
218
219    collection::const_iterator lower, upper, pos;
220    lower = m_bp_site_list.lower_bound(lower_bound);
221    if (lower == m_bp_site_list.end()
222            || (*lower).first >= upper_bound)
223        return false;
224
225    // This is one tricky bit.  The breakpoint might overlap the bottom end of the range.  So we grab the
226    // breakpoint prior to the lower bound, and check that that + its byte size isn't in our range.
227    if (lower != m_bp_site_list.begin())
228    {
229        collection::const_iterator prev_pos = lower;
230        prev_pos--;
231        const BreakpointSiteSP &prev_bp = (*prev_pos).second;
232        if (prev_bp->GetLoadAddress() + prev_bp->GetByteSize() > lower_bound)
233            bp_site_list.Add (prev_bp);
234
235    }
236
237    upper = m_bp_site_list.upper_bound(upper_bound);
238
239    for (pos = lower; pos != upper; pos++)
240    {
241        bp_site_list.Add ((*pos).second);
242    }
243    return true;
244}
245
246
247void
248BreakpointSiteList::SetEnabledForAll (const bool enabled, const lldb::break_id_t except_id)
249{
250    collection::iterator end = m_bp_site_list.end();
251    collection::iterator pos;
252    for (pos = m_bp_site_list.begin(); pos != end; ++pos)
253    {
254        if (except_id != LLDB_INVALID_BREAK_ID && except_id != pos->second->GetID())
255            pos->second->SetEnabled (enabled);
256        else
257            pos->second->SetEnabled (!enabled);
258    }
259}
260
261const BreakpointSiteList::collection *
262BreakpointSiteList::GetMap ()
263{
264    return &m_bp_site_list;
265}
266