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