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/Core/ModuleList.h"
18 #include "lldb/Target/Target.h"
19 
20 using namespace lldb;
21 using namespace lldb_private;
22 
23 BreakpointLocationList::BreakpointLocationList() :
24     m_locations(),
25     m_address_to_location (),
26     m_mutex (Mutex::eMutexTypeRecursive)
27 {
28 }
29 
30 BreakpointLocationList::~BreakpointLocationList()
31 {
32 }
33 
34 BreakpointLocationSP
35 BreakpointLocationList::Create (Breakpoint &bp, const Address &addr)
36 {
37     Mutex::Locker locker (m_mutex);
38     // The location ID is just the size of the location list + 1
39     lldb::break_id_t bp_loc_id = m_locations.size() + 1;
40     BreakpointLocationSP bp_loc_sp (new BreakpointLocation (bp_loc_id, bp, addr));
41     m_locations.push_back (bp_loc_sp);
42     m_address_to_location[addr] = bp_loc_sp;
43     return bp_loc_sp;
44 }
45 
46 bool
47 BreakpointLocationList::ShouldStop (StoppointCallbackContext *context, lldb::break_id_t break_id)
48 {
49     BreakpointLocationSP bp = FindByID (break_id);
50     if (bp)
51     {
52         // Let the BreakpointLocation decide if it should stop here (could not have
53         // reached it's target hit count yet, or it could have a callback
54         // that decided it shouldn't stop (shared library loads/unloads).
55         return bp->ShouldStop (context);
56     }
57     // We should stop here since this BreakpointLocation isn't valid anymore or it
58     // doesn't exist.
59     return true;
60 }
61 
62 lldb::break_id_t
63 BreakpointLocationList::FindIDByAddress (const Address &addr)
64 {
65     BreakpointLocationSP bp_loc_sp = FindByAddress (addr);
66     if (bp_loc_sp)
67     {
68         return bp_loc_sp->GetID();
69     }
70     return LLDB_INVALID_BREAK_ID;
71 }
72 
73 BreakpointLocationSP
74 BreakpointLocationList::FindByID (lldb::break_id_t break_id) const
75 {
76     BreakpointLocationSP bp_loc_sp;
77     Mutex::Locker locker (m_mutex);
78     // We never remove a breakpoint locations, so the ID can be translated into
79     // the location index by subtracting 1
80     uint32_t idx = break_id - 1;
81     if (idx <= m_locations.size())
82     {
83         bp_loc_sp = m_locations[idx];
84     }
85     return bp_loc_sp;
86 }
87 
88 size_t
89 BreakpointLocationList::FindInModule (Module *module,
90                                       BreakpointLocationCollection& bp_loc_list)
91 {
92     Mutex::Locker locker (m_mutex);
93     const size_t orig_size = bp_loc_list.GetSize();
94     collection::iterator pos, end = m_locations.end();
95 
96     for (pos = m_locations.begin(); pos != end; ++pos)
97     {
98         bool seen = false;
99         BreakpointLocationSP break_loc = (*pos);
100         const Section *section = break_loc->GetAddress().GetSection();
101         if (section)
102         {
103             if (section->GetModule() == module)
104             {
105                 if (!seen)
106                 {
107                     seen = true;
108                     bp_loc_list.Add (break_loc);
109                 }
110 
111             }
112         }
113     }
114     return bp_loc_list.GetSize() - orig_size;
115 }
116 
117 const BreakpointLocationSP
118 BreakpointLocationList::FindByAddress (const Address &addr) const
119 {
120     Mutex::Locker locker (m_mutex);
121     BreakpointLocationSP bp_loc_sp;
122     if (!m_locations.empty())
123     {
124         addr_map::const_iterator pos = m_address_to_location.find (addr);
125         if (pos != m_address_to_location.end())
126             bp_loc_sp = pos->second;
127     }
128 
129     return bp_loc_sp;
130 }
131 
132 void
133 BreakpointLocationList::Dump (Stream *s) const
134 {
135     s->Printf("%.*p: ", (int)sizeof(void*) * 2, this);
136     //s->Indent();
137     Mutex::Locker locker (m_mutex);
138     s->Printf("BreakpointLocationList with %zu BreakpointLocations:\n", m_locations.size());
139     s->IndentMore();
140     collection::const_iterator pos, end = m_locations.end();
141     for (pos = m_locations.begin(); pos != end; ++pos)
142         (*pos).get()->Dump(s);
143     s->IndentLess();
144 }
145 
146 
147 BreakpointLocationSP
148 BreakpointLocationList::GetByIndex (uint32_t i)
149 {
150     Mutex::Locker locker (m_mutex);
151     BreakpointLocationSP bp_loc_sp;
152     if (i < m_locations.size())
153         bp_loc_sp = m_locations[i];
154 
155     return bp_loc_sp;
156 }
157 
158 const BreakpointLocationSP
159 BreakpointLocationList::GetByIndex (uint32_t i) const
160 {
161     Mutex::Locker locker (m_mutex);
162     BreakpointLocationSP bp_loc_sp;
163     if (i < m_locations.size())
164         bp_loc_sp = m_locations[i];
165 
166     return bp_loc_sp;
167 }
168 
169 void
170 BreakpointLocationList::ClearAllBreakpointSites ()
171 {
172     Mutex::Locker locker (m_mutex);
173     collection::iterator pos, end = m_locations.end();
174     for (pos = m_locations.begin(); pos != end; ++pos)
175         (*pos)->ClearBreakpointSite();
176 }
177 
178 void
179 BreakpointLocationList::ResolveAllBreakpointSites ()
180 {
181     Mutex::Locker locker (m_mutex);
182     collection::iterator pos, end = m_locations.end();
183 
184     for (pos = m_locations.begin(); pos != end; ++pos)
185     {
186         if ((*pos)->IsEnabled())
187             (*pos)->ResolveBreakpointSite();
188     }
189 }
190 
191 uint32_t
192 BreakpointLocationList::GetHitCount () const
193 {
194     uint32_t hit_count = 0;
195     Mutex::Locker locker (m_mutex);
196     collection::const_iterator pos, end = m_locations.end();
197     for (pos = m_locations.begin(); pos != end; ++pos)
198         hit_count += (*pos)->GetHitCount();
199     return hit_count;
200 }
201 
202 size_t
203 BreakpointLocationList::GetNumResolvedLocations() const
204 {
205     Mutex::Locker locker (m_mutex);
206     size_t resolve_count = 0;
207     collection::const_iterator pos, end = m_locations.end();
208     for (pos = m_locations.begin(); pos != end; ++pos)
209     {
210         if ((*pos)->IsResolved())
211             ++resolve_count;
212     }
213     return resolve_count;
214 }
215 
216 void
217 BreakpointLocationList::GetDescription (Stream *s, lldb::DescriptionLevel level)
218 {
219     Mutex::Locker locker (m_mutex);
220     collection::iterator pos, end = m_locations.end();
221 
222     for (pos = m_locations.begin(); pos != end; ++pos)
223     {
224         s->Printf(" ");
225         (*pos)->GetDescription(s, level);
226     }
227 }
228 
229