BreakpointLocationList.cpp revision 258054
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 21using namespace lldb; 22using namespace lldb_private; 23 24BreakpointLocationList::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 34BreakpointLocationList::~BreakpointLocationList() 35{ 36} 37 38BreakpointLocationSP 39BreakpointLocationList::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 50bool 51BreakpointLocationList::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 66lldb::break_id_t 67BreakpointLocationList::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 77BreakpointLocationSP 78BreakpointLocationList::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 92size_t 93BreakpointLocationList::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 112const BreakpointLocationSP 113BreakpointLocationList::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 144void 145BreakpointLocationList::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 159BreakpointLocationSP 160BreakpointLocationList::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 170const BreakpointLocationSP 171BreakpointLocationList::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 181void 182BreakpointLocationList::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 190void 191BreakpointLocationList::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 203uint32_t 204BreakpointLocationList::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 214size_t 215BreakpointLocationList::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 228void 229BreakpointLocationList::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 241BreakpointLocationSP 242BreakpointLocationList::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 267bool 268BreakpointLocationList::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 291void 292BreakpointLocationList::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 299void 300BreakpointLocationList::StopRecordingNewLocations () 301{ 302 Mutex::Locker locker (m_mutex); 303 m_new_location_recorder = NULL; 304} 305 306