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