BreakpointLocationList.cpp revision 263363
1//===-- BreakpointLocationList.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
11// C Includes
12// C++ Includes
13// Other libraries and framework includes
14// Project includes
15#include "lldb/Breakpoint/BreakpointLocationList.h"
16#include "lldb/Breakpoint/BreakpointLocation.h"
17#include "lldb/Breakpoint/Breakpoint.h"
18#include "lldb/Core/Section.h"
19#include "lldb/Target/Target.h"
20
21using namespace lldb;
22using namespace lldb_private;
23
24BreakpointLocationList::BreakpointLocationList(Breakpoint &owner) :
25    m_owner (owner),
26    m_locations(),
27    m_address_to_location (),
28    m_mutex (Mutex::eMutexTypeRecursive),
29    m_next_id (0),
30    m_new_location_recorder (NULL)
31{
32}
33
34BreakpointLocationList::~BreakpointLocationList()
35{
36}
37
38BreakpointLocationSP
39BreakpointLocationList::Create (const Address &addr)
40{
41    Mutex::Locker locker (m_mutex);
42    // The location ID is just the size of the location list + 1
43    lldb::break_id_t bp_loc_id = ++m_next_id;
44    BreakpointLocationSP bp_loc_sp (new BreakpointLocation (bp_loc_id, m_owner, addr, LLDB_INVALID_THREAD_ID, m_owner.IsHardware()));
45    m_locations.push_back (bp_loc_sp);
46    m_address_to_location[addr] = bp_loc_sp;
47    return bp_loc_sp;
48}
49
50bool
51BreakpointLocationList::ShouldStop (StoppointCallbackContext *context, lldb::break_id_t break_id)
52{
53    BreakpointLocationSP bp = FindByID (break_id);
54    if (bp)
55    {
56        // Let the BreakpointLocation decide if it should stop here (could not have
57        // reached it's target hit count yet, or it could have a callback
58        // that decided it shouldn't stop (shared library loads/unloads).
59        return bp->ShouldStop (context);
60    }
61    // We should stop here since this BreakpointLocation isn't valid anymore or it
62    // doesn't exist.
63    return true;
64}
65
66lldb::break_id_t
67BreakpointLocationList::FindIDByAddress (const Address &addr)
68{
69    BreakpointLocationSP bp_loc_sp = FindByAddress (addr);
70    if (bp_loc_sp)
71    {
72        return bp_loc_sp->GetID();
73    }
74    return LLDB_INVALID_BREAK_ID;
75}
76
77BreakpointLocationSP
78BreakpointLocationList::FindByID (lldb::break_id_t break_id) const
79{
80    BreakpointLocationSP bp_loc_sp;
81    Mutex::Locker locker (m_mutex);
82    // We never remove a breakpoint locations, so the ID can be translated into
83    // the location index by subtracting 1
84    uint32_t idx = break_id - 1;
85    if (idx <= m_locations.size())
86    {
87        bp_loc_sp = m_locations[idx];
88    }
89    return bp_loc_sp;
90}
91
92size_t
93BreakpointLocationList::FindInModule (Module *module,
94                                      BreakpointLocationCollection& bp_loc_list)
95{
96    Mutex::Locker locker (m_mutex);
97    const size_t orig_size = bp_loc_list.GetSize();
98    collection::iterator pos, end = m_locations.end();
99
100    for (pos = m_locations.begin(); pos != end; ++pos)
101    {
102        BreakpointLocationSP break_loc = (*pos);
103        SectionSP section_sp (break_loc->GetAddress().GetSection());
104        if (section_sp && section_sp->GetModule().get() == module)
105        {
106            bp_loc_list.Add (break_loc);
107        }
108    }
109    return bp_loc_list.GetSize() - orig_size;
110}
111
112const BreakpointLocationSP
113BreakpointLocationList::FindByAddress (const Address &addr) const
114{
115    Mutex::Locker locker (m_mutex);
116    BreakpointLocationSP bp_loc_sp;
117    if (!m_locations.empty())
118    {
119        Address so_addr;
120
121        if (addr.IsSectionOffset())
122        {
123            so_addr = addr;
124        }
125        else
126        {
127            // Try and resolve as a load address if possible.
128            m_owner.GetTarget().GetSectionLoadList().ResolveLoadAddress (addr.GetOffset(), so_addr);
129            if (!so_addr.IsValid())
130            {
131                // The address didn't resolve, so just set to passed in addr.
132                so_addr = addr;
133            }
134        }
135
136        addr_map::const_iterator pos = m_address_to_location.find (so_addr);
137        if (pos != m_address_to_location.end())
138            bp_loc_sp = pos->second;
139    }
140
141    return bp_loc_sp;
142}
143
144void
145BreakpointLocationList::Dump (Stream *s) const
146{
147    s->Printf("%p: ", this);
148    //s->Indent();
149    Mutex::Locker locker (m_mutex);
150    s->Printf("BreakpointLocationList with %" PRIu64 " BreakpointLocations:\n", (uint64_t)m_locations.size());
151    s->IndentMore();
152    collection::const_iterator pos, end = m_locations.end();
153    for (pos = m_locations.begin(); pos != end; ++pos)
154        (*pos).get()->Dump(s);
155    s->IndentLess();
156}
157
158
159BreakpointLocationSP
160BreakpointLocationList::GetByIndex (size_t i)
161{
162    Mutex::Locker locker (m_mutex);
163    BreakpointLocationSP bp_loc_sp;
164    if (i < m_locations.size())
165        bp_loc_sp = m_locations[i];
166
167    return bp_loc_sp;
168}
169
170const BreakpointLocationSP
171BreakpointLocationList::GetByIndex (size_t i) const
172{
173    Mutex::Locker locker (m_mutex);
174    BreakpointLocationSP bp_loc_sp;
175    if (i < m_locations.size())
176        bp_loc_sp = m_locations[i];
177
178    return bp_loc_sp;
179}
180
181void
182BreakpointLocationList::ClearAllBreakpointSites ()
183{
184    Mutex::Locker locker (m_mutex);
185    collection::iterator pos, end = m_locations.end();
186    for (pos = m_locations.begin(); pos != end; ++pos)
187        (*pos)->ClearBreakpointSite();
188}
189
190void
191BreakpointLocationList::ResolveAllBreakpointSites ()
192{
193    Mutex::Locker locker (m_mutex);
194    collection::iterator pos, end = m_locations.end();
195
196    for (pos = m_locations.begin(); pos != end; ++pos)
197    {
198        if ((*pos)->IsEnabled())
199            (*pos)->ResolveBreakpointSite();
200    }
201}
202
203uint32_t
204BreakpointLocationList::GetHitCount () const
205{
206    uint32_t hit_count = 0;
207    Mutex::Locker locker (m_mutex);
208    collection::const_iterator pos, end = m_locations.end();
209    for (pos = m_locations.begin(); pos != end; ++pos)
210        hit_count += (*pos)->GetHitCount();
211    return hit_count;
212}
213
214size_t
215BreakpointLocationList::GetNumResolvedLocations() const
216{
217    Mutex::Locker locker (m_mutex);
218    size_t resolve_count = 0;
219    collection::const_iterator pos, end = m_locations.end();
220    for (pos = m_locations.begin(); pos != end; ++pos)
221    {
222        if ((*pos)->IsResolved())
223            ++resolve_count;
224    }
225    return resolve_count;
226}
227
228void
229BreakpointLocationList::GetDescription (Stream *s, lldb::DescriptionLevel level)
230{
231    Mutex::Locker locker (m_mutex);
232    collection::iterator pos, end = m_locations.end();
233
234    for (pos = m_locations.begin(); pos != end; ++pos)
235    {
236        s->Printf(" ");
237        (*pos)->GetDescription(s, level);
238    }
239}
240
241BreakpointLocationSP
242BreakpointLocationList::AddLocation (const Address &addr, bool *new_location)
243{
244    Mutex::Locker locker (m_mutex);
245
246    if (new_location)
247        *new_location = false;
248    BreakpointLocationSP bp_loc_sp (FindByAddress(addr));
249    if (!bp_loc_sp)
250	{
251		bp_loc_sp = Create (addr);
252		if (bp_loc_sp)
253		{
254	    	bp_loc_sp->ResolveBreakpointSite();
255
256		    if (new_location)
257	    	    *new_location = true;
258            if(m_new_location_recorder)
259            {
260                m_new_location_recorder->Add(bp_loc_sp);
261            }
262		}
263	}
264    return bp_loc_sp;
265}
266
267bool
268BreakpointLocationList::RemoveLocation (const lldb::BreakpointLocationSP &bp_loc_sp)
269{
270    if (bp_loc_sp)
271    {
272        Mutex::Locker locker (m_mutex);
273
274        m_address_to_location.erase (bp_loc_sp->GetAddress());
275
276        collection::iterator pos, end = m_locations.end();
277        for (pos = m_locations.begin(); pos != end; ++pos)
278        {
279            if ((*pos).get() == bp_loc_sp.get())
280            {
281                m_locations.erase (pos);
282                return true;
283            }
284        }
285	}
286    return false;
287}
288
289
290
291void
292BreakpointLocationList::StartRecordingNewLocations (BreakpointLocationCollection &new_locations)
293{
294    Mutex::Locker locker (m_mutex);
295    assert (m_new_location_recorder == NULL);
296    m_new_location_recorder = &new_locations;
297}
298
299void
300BreakpointLocationList::StopRecordingNewLocations ()
301{
302    Mutex::Locker locker (m_mutex);
303    m_new_location_recorder = NULL;
304}
305
306