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