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