BreakpointLocationList.cpp revision 280031
1200483Srwatson//===-- BreakpointLocationList.cpp ------------------------------*- C++ -*-===//
2200483Srwatson//
3200483Srwatson//                     The LLVM Compiler Infrastructure
4200483Srwatson//
5200483Srwatson// This file is distributed under the University of Illinois Open Source
6200483Srwatson// License. See LICENSE.TXT for details.
7200483Srwatson//
8200483Srwatson//===----------------------------------------------------------------------===//
9200483Srwatson
10200483Srwatson
11200483Srwatson// C Includes
12200483Srwatson// C++ Includes
13200483Srwatson// Other libraries and framework includes
14200483Srwatson// Project includes
15200483Srwatson#include "lldb/Breakpoint/BreakpointLocationList.h"
16200483Srwatson
17200483Srwatson#include "lldb/Breakpoint/BreakpointLocation.h"
18200483Srwatson#include "lldb/Breakpoint/Breakpoint.h"
19200483Srwatson#include "lldb/Core/ArchSpec.h"
20200483Srwatson#include "lldb/Core/Module.h"
21200483Srwatson#include "lldb/Core/Section.h"
22200483Srwatson#include "lldb/Target/SectionLoadList.h"
23200483Srwatson#include "lldb/Target/Target.h"
24200483Srwatson
25200483Srwatson
26200483Srwatsonusing namespace lldb;
27200483Srwatsonusing namespace lldb_private;
28200483Srwatson
29200483SrwatsonBreakpointLocationList::BreakpointLocationList(Breakpoint &owner) :
30200483Srwatson    m_owner (owner),
31200483Srwatson    m_locations(),
32200483Srwatson    m_address_to_location (),
33200483Srwatson    m_mutex (Mutex::eMutexTypeRecursive),
34200483Srwatson    m_next_id (0),
35200483Srwatson    m_new_location_recorder (NULL)
36200483Srwatson{
37200483Srwatson}
38200483Srwatson
39200483SrwatsonBreakpointLocationList::~BreakpointLocationList()
40200483Srwatson{
41200483Srwatson}
42200483Srwatson
43200483SrwatsonBreakpointLocationSP
44200483SrwatsonBreakpointLocationList::Create (const Address &addr, bool resolve_indirect_symbols)
45200483Srwatson{
46200483Srwatson    Mutex::Locker locker (m_mutex);
47200483Srwatson    // The location ID is just the size of the location list + 1
48200483Srwatson    lldb::break_id_t bp_loc_id = ++m_next_id;
49200483Srwatson    BreakpointLocationSP bp_loc_sp (new BreakpointLocation (bp_loc_id, m_owner, addr, LLDB_INVALID_THREAD_ID, m_owner.IsHardware(), resolve_indirect_symbols));
50200483Srwatson    m_locations.push_back (bp_loc_sp);
51200483Srwatson    m_address_to_location[addr] = bp_loc_sp;
52200483Srwatson    return bp_loc_sp;
53200483Srwatson}
54200483Srwatson
55200483Srwatsonbool
56200483SrwatsonBreakpointLocationList::ShouldStop (StoppointCallbackContext *context, lldb::break_id_t break_id)
57200483Srwatson{
58200483Srwatson    BreakpointLocationSP bp = FindByID (break_id);
59200483Srwatson    if (bp)
60200483Srwatson    {
61200483Srwatson        // Let the BreakpointLocation decide if it should stop here (could not have
62200483Srwatson        // reached it's target hit count yet, or it could have a callback
63200483Srwatson        // that decided it shouldn't stop (shared library loads/unloads).
64200483Srwatson        return bp->ShouldStop (context);
65200483Srwatson    }
66200483Srwatson    // We should stop here since this BreakpointLocation isn't valid anymore or it
67200483Srwatson    // doesn't exist.
68200483Srwatson    return true;
69200483Srwatson}
70200483Srwatson
71200483Srwatsonlldb::break_id_t
72200483SrwatsonBreakpointLocationList::FindIDByAddress (const Address &addr)
73200483Srwatson{
74200483Srwatson    BreakpointLocationSP bp_loc_sp = FindByAddress (addr);
75200483Srwatson    if (bp_loc_sp)
76200483Srwatson    {
77200483Srwatson        return bp_loc_sp->GetID();
78200483Srwatson    }
79200483Srwatson    return LLDB_INVALID_BREAK_ID;
80200483Srwatson}
81200483Srwatson
82200483Srwatsonstatic bool
83200483SrwatsonCompare (BreakpointLocationSP lhs, lldb::break_id_t val)
84200483Srwatson{
85200483Srwatson    return lhs->GetID() < val;
86200483Srwatson}
87200483Srwatson
88200483SrwatsonBreakpointLocationSP
89200483SrwatsonBreakpointLocationList::FindByID (lldb::break_id_t break_id) const
90200483Srwatson{
91200483Srwatson    Mutex::Locker locker (m_mutex);
92200483Srwatson    collection::const_iterator end = m_locations.end();
93200483Srwatson    collection::const_iterator pos = std::lower_bound(m_locations.begin(), end, break_id, Compare);
94200483Srwatson    if (pos != end && (*pos)->GetID() == break_id)
95200483Srwatson        return *(pos);
96200483Srwatson    else
97200483Srwatson        return BreakpointLocationSP();
98200483Srwatson}
99200483Srwatson
100200483Srwatsonsize_t
101200483SrwatsonBreakpointLocationList::FindInModule (Module *module,
102200483Srwatson                                      BreakpointLocationCollection& bp_loc_list)
103200483Srwatson{
104200483Srwatson    Mutex::Locker locker (m_mutex);
105200483Srwatson    const size_t orig_size = bp_loc_list.GetSize();
106200483Srwatson    collection::iterator pos, end = m_locations.end();
107200483Srwatson
108200483Srwatson    for (pos = m_locations.begin(); pos != end; ++pos)
109200483Srwatson    {
110200483Srwatson        BreakpointLocationSP break_loc = (*pos);
111200483Srwatson        SectionSP section_sp (break_loc->GetAddress().GetSection());
112200483Srwatson        if (section_sp && section_sp->GetModule().get() == module)
113200483Srwatson        {
114200483Srwatson            bp_loc_list.Add (break_loc);
115200483Srwatson        }
116200483Srwatson    }
117200483Srwatson    return bp_loc_list.GetSize() - orig_size;
118200483Srwatson}
119200483Srwatson
120200483Srwatsonconst BreakpointLocationSP
121200483SrwatsonBreakpointLocationList::FindByAddress (const Address &addr) const
122200483Srwatson{
123200483Srwatson    Mutex::Locker locker (m_mutex);
124200483Srwatson    BreakpointLocationSP bp_loc_sp;
125200483Srwatson    if (!m_locations.empty())
126200483Srwatson    {
127200483Srwatson        Address so_addr;
128200483Srwatson
129200483Srwatson        if (addr.IsSectionOffset())
130200483Srwatson        {
131200483Srwatson            so_addr = addr;
132200483Srwatson        }
133200483Srwatson        else
134200483Srwatson        {
135200483Srwatson            // Try and resolve as a load address if possible.
136200483Srwatson            m_owner.GetTarget().GetSectionLoadList().ResolveLoadAddress (addr.GetOffset(), so_addr);
137200483Srwatson            if (!so_addr.IsValid())
138200483Srwatson            {
139200483Srwatson                // The address didn't resolve, so just set to passed in addr.
140200483Srwatson                so_addr = addr;
141200483Srwatson            }
142200483Srwatson        }
143200483Srwatson
144200483Srwatson        addr_map::const_iterator pos = m_address_to_location.find (so_addr);
145200483Srwatson        if (pos != m_address_to_location.end())
146200483Srwatson            bp_loc_sp = pos->second;
147200483Srwatson    }
148200483Srwatson
149200483Srwatson    return bp_loc_sp;
150200483Srwatson}
151200483Srwatson
152200483Srwatsonvoid
153200483SrwatsonBreakpointLocationList::Dump (Stream *s) const
154200483Srwatson{
155200483Srwatson    s->Printf("%p: ", static_cast<const void*>(this));
156200483Srwatson    //s->Indent();
157200483Srwatson    Mutex::Locker locker (m_mutex);
158200483Srwatson    s->Printf("BreakpointLocationList with %" PRIu64 " BreakpointLocations:\n", (uint64_t)m_locations.size());
159200483Srwatson    s->IndentMore();
160200483Srwatson    collection::const_iterator pos, end = m_locations.end();
161200483Srwatson    for (pos = m_locations.begin(); pos != end; ++pos)
162200483Srwatson        (*pos).get()->Dump(s);
163200483Srwatson    s->IndentLess();
164200483Srwatson}
165200483Srwatson
166200483Srwatson
167200483SrwatsonBreakpointLocationSP
168200483SrwatsonBreakpointLocationList::GetByIndex (size_t i)
169200483Srwatson{
170200483Srwatson    Mutex::Locker locker (m_mutex);
171200483Srwatson    BreakpointLocationSP bp_loc_sp;
172200483Srwatson    if (i < m_locations.size())
173200483Srwatson        bp_loc_sp = m_locations[i];
174200483Srwatson
175200483Srwatson    return bp_loc_sp;
176200483Srwatson}
177200483Srwatson
178200483Srwatsonconst BreakpointLocationSP
179200483SrwatsonBreakpointLocationList::GetByIndex (size_t i) const
180200483Srwatson{
181200483Srwatson    Mutex::Locker locker (m_mutex);
182200483Srwatson    BreakpointLocationSP bp_loc_sp;
183200483Srwatson    if (i < m_locations.size())
184200483Srwatson        bp_loc_sp = m_locations[i];
185200483Srwatson
186200483Srwatson    return bp_loc_sp;
187200483Srwatson}
188200483Srwatson
189200483Srwatsonvoid
190200483SrwatsonBreakpointLocationList::ClearAllBreakpointSites ()
191200483Srwatson{
192200483Srwatson    Mutex::Locker locker (m_mutex);
193200483Srwatson    collection::iterator pos, end = m_locations.end();
194200483Srwatson    for (pos = m_locations.begin(); pos != end; ++pos)
195200483Srwatson        (*pos)->ClearBreakpointSite();
196200483Srwatson}
197200483Srwatson
198200483Srwatsonvoid
199200483SrwatsonBreakpointLocationList::ResolveAllBreakpointSites ()
200200483Srwatson{
201200483Srwatson    Mutex::Locker locker (m_mutex);
202200483Srwatson    collection::iterator pos, end = m_locations.end();
203200483Srwatson
204200483Srwatson    for (pos = m_locations.begin(); pos != end; ++pos)
205200483Srwatson    {
206200483Srwatson        if ((*pos)->IsEnabled())
207200483Srwatson            (*pos)->ResolveBreakpointSite();
208200483Srwatson    }
209200483Srwatson}
210200483Srwatson
211200483Srwatsonuint32_t
212200483SrwatsonBreakpointLocationList::GetHitCount () const
213200483Srwatson{
214200483Srwatson    uint32_t hit_count = 0;
215200483Srwatson    Mutex::Locker locker (m_mutex);
216200483Srwatson    collection::const_iterator pos, end = m_locations.end();
217200483Srwatson    for (pos = m_locations.begin(); pos != end; ++pos)
218200483Srwatson        hit_count += (*pos)->GetHitCount();
219200483Srwatson    return hit_count;
220200483Srwatson}
221200483Srwatson
222200483Srwatsonsize_t
223200483SrwatsonBreakpointLocationList::GetNumResolvedLocations() const
224200483Srwatson{
225200483Srwatson    Mutex::Locker locker (m_mutex);
226200483Srwatson    size_t resolve_count = 0;
227200483Srwatson    collection::const_iterator pos, end = m_locations.end();
228200483Srwatson    for (pos = m_locations.begin(); pos != end; ++pos)
229200483Srwatson    {
230200483Srwatson        if ((*pos)->IsResolved())
231200483Srwatson            ++resolve_count;
232200483Srwatson    }
233200483Srwatson    return resolve_count;
234200483Srwatson}
235200483Srwatson
236200483Srwatsonvoid
237200483SrwatsonBreakpointLocationList::GetDescription (Stream *s, lldb::DescriptionLevel level)
238200483Srwatson{
239200483Srwatson    Mutex::Locker locker (m_mutex);
240200483Srwatson    collection::iterator pos, end = m_locations.end();
241200483Srwatson
242200483Srwatson    for (pos = m_locations.begin(); pos != end; ++pos)
243200483Srwatson    {
244200483Srwatson        s->Printf(" ");
245200483Srwatson        (*pos)->GetDescription(s, level);
246200483Srwatson    }
247200483Srwatson}
248200483Srwatson
249200483SrwatsonBreakpointLocationSP
250200483SrwatsonBreakpointLocationList::AddLocation (const Address &addr, bool resolve_indirect_symbols, bool *new_location)
251200483Srwatson{
252200483Srwatson    Mutex::Locker locker (m_mutex);
253200483Srwatson
254200483Srwatson    if (new_location)
255200483Srwatson        *new_location = false;
256200483Srwatson    BreakpointLocationSP bp_loc_sp (FindByAddress(addr));
257200483Srwatson    if (!bp_loc_sp)
258200483Srwatson	{
259200483Srwatson		bp_loc_sp = Create (addr, resolve_indirect_symbols);
260200483Srwatson		if (bp_loc_sp)
261200483Srwatson		{
262200483Srwatson	    	bp_loc_sp->ResolveBreakpointSite();
263200483Srwatson
264200483Srwatson		    if (new_location)
265200483Srwatson	    	    *new_location = true;
266200483Srwatson            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
275void
276BreakpointLocationList::SwapLocation (BreakpointLocationSP to_location_sp, BreakpointLocationSP from_location_sp)
277{
278    if (!from_location_sp || !to_location_sp)
279        return;
280
281    m_address_to_location.erase(to_location_sp->GetAddress());
282    to_location_sp->SwapLocation(from_location_sp);
283    RemoveLocation(from_location_sp);
284    m_address_to_location[to_location_sp->GetAddress()] = to_location_sp;
285    to_location_sp->ResolveBreakpointSite();
286}
287
288
289bool
290BreakpointLocationList::RemoveLocation (const lldb::BreakpointLocationSP &bp_loc_sp)
291{
292    if (bp_loc_sp)
293    {
294        Mutex::Locker locker (m_mutex);
295
296        m_address_to_location.erase (bp_loc_sp->GetAddress());
297
298        collection::iterator pos, end = m_locations.end();
299        for (pos = m_locations.begin(); pos != end; ++pos)
300        {
301            if ((*pos).get() == bp_loc_sp.get())
302            {
303                m_locations.erase (pos);
304                return true;
305            }
306        }
307	}
308    return false;
309}
310
311void
312BreakpointLocationList::RemoveInvalidLocations (const ArchSpec &arch)
313{
314    Mutex::Locker locker (m_mutex);
315    size_t idx = 0;
316    // Don't cache m_location.size() as it will change since we might
317    // remove locations from our vector...
318    while (idx < m_locations.size())
319    {
320        BreakpointLocation *bp_loc = m_locations[idx].get();
321        if (bp_loc->GetAddress().SectionWasDeleted())
322        {
323            // Section was deleted which means this breakpoint comes from a module
324            // that is no longer valid, so we should remove it.
325            m_locations.erase(m_locations.begin() + idx);
326            continue;
327        }
328        if (arch.IsValid())
329        {
330            ModuleSP module_sp (bp_loc->GetAddress().GetModule());
331            if (module_sp)
332            {
333                if (!arch.IsCompatibleMatch(module_sp->GetArchitecture()))
334                {
335                    // The breakpoint was in a module whose architecture is no longer
336                    // compatible with "arch", so we need to remove it
337                    m_locations.erase(m_locations.begin() + idx);
338                    continue;
339                }
340            }
341        }
342        // Only increment the index if we didn't remove the locations at index "idx"
343        ++idx;
344    }
345}
346
347void
348BreakpointLocationList::StartRecordingNewLocations (BreakpointLocationCollection &new_locations)
349{
350    Mutex::Locker locker (m_mutex);
351    assert (m_new_location_recorder == NULL);
352    m_new_location_recorder = &new_locations;
353}
354
355void
356BreakpointLocationList::StopRecordingNewLocations ()
357{
358    Mutex::Locker locker (m_mutex);
359    m_new_location_recorder = NULL;
360}
361
362void
363BreakpointLocationList::Compact()
364{
365    lldb::break_id_t highest_id = 0;
366
367    for (BreakpointLocationSP loc_sp : m_locations)
368    {
369        lldb::break_id_t cur_id = loc_sp->GetID();
370        if (cur_id > highest_id)
371            highest_id = cur_id;
372    }
373    m_next_id = highest_id;
374}
375