1 //===-- BreakpointSite.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 #include "lldb/Breakpoint/BreakpointSite.h" 11 12 // C Includes 13 // C++ Includes 14 #include <inttypes.h> 15 16 // Other libraries and framework includes 17 // Project includes 18 #include "lldb/Breakpoint/Breakpoint.h" 19 #include "lldb/Breakpoint/BreakpointLocation.h" 20 #include "lldb/Breakpoint/BreakpointSiteList.h" 21 #include "lldb/Core/Stream.h" 22 23 using namespace lldb; 24 using namespace lldb_private; 25 26 BreakpointSite::BreakpointSite 27 ( 28 BreakpointSiteList *list, 29 const BreakpointLocationSP& owner, 30 lldb::addr_t addr, 31 bool use_hardware 32 ) : 33 StoppointLocation(GetNextID(), addr, 0, use_hardware), 34 m_type (eSoftware), // Process subclasses need to set this correctly using SetType() 35 m_saved_opcode(), 36 m_trap_opcode(), 37 m_enabled(false), // Need to create it disabled, so the first enable turns it on. 38 m_owners(), 39 m_owners_mutex(Mutex::eMutexTypeRecursive) 40 { 41 m_owners.Add(owner); 42 } 43 44 BreakpointSite::~BreakpointSite() 45 { 46 BreakpointLocationSP bp_loc_sp; 47 const size_t owner_count = m_owners.GetSize(); 48 for (size_t i = 0; i < owner_count; i++) 49 { 50 m_owners.GetByIndex(i)->ClearBreakpointSite(); 51 } 52 } 53 54 break_id_t 55 BreakpointSite::GetNextID() 56 { 57 static break_id_t g_next_id = 0; 58 return ++g_next_id; 59 } 60 61 // RETURNS - true if we should stop at this breakpoint, false if we 62 // should continue. 63 64 bool 65 BreakpointSite::ShouldStop (StoppointCallbackContext *context) 66 { 67 Mutex::Locker locker(m_owners_mutex); 68 IncrementHitCount(); 69 return m_owners.ShouldStop (context); 70 } 71 72 bool 73 BreakpointSite::IsBreakpointAtThisSite (lldb::break_id_t bp_id) 74 { 75 Mutex::Locker locker(m_owners_mutex); 76 const size_t owner_count = m_owners.GetSize(); 77 for (size_t i = 0; i < owner_count; i++) 78 { 79 if (m_owners.GetByIndex(i)->GetBreakpoint().GetID() == bp_id) 80 return true; 81 } 82 return false; 83 } 84 85 void 86 BreakpointSite::Dump(Stream *s) const 87 { 88 if (s == NULL) 89 return; 90 91 s->Printf("BreakpointSite %u: addr = 0x%8.8" PRIx64 " type = %s breakpoint hw_index = %i hit_count = %-4u", 92 GetID(), 93 (uint64_t)m_addr, 94 IsHardware() ? "hardware" : "software", 95 GetHardwareIndex(), 96 GetHitCount()); 97 } 98 99 void 100 BreakpointSite::GetDescription (Stream *s, lldb::DescriptionLevel level) 101 { 102 Mutex::Locker locker(m_owners_mutex); 103 if (level != lldb::eDescriptionLevelBrief) 104 s->Printf ("breakpoint site: %d at 0x%8.8" PRIx64, GetID(), GetLoadAddress()); 105 m_owners.GetDescription (s, level); 106 } 107 108 bool 109 BreakpointSite::IsInternal() const 110 { 111 return m_owners.IsInternal(); 112 } 113 114 uint8_t * 115 BreakpointSite::GetTrapOpcodeBytes() 116 { 117 return &m_trap_opcode[0]; 118 } 119 120 const uint8_t * 121 BreakpointSite::GetTrapOpcodeBytes() const 122 { 123 return &m_trap_opcode[0]; 124 } 125 126 size_t 127 BreakpointSite::GetTrapOpcodeMaxByteSize() const 128 { 129 return sizeof(m_trap_opcode); 130 } 131 132 bool 133 BreakpointSite::SetTrapOpcode (const uint8_t *trap_opcode, uint32_t trap_opcode_size) 134 { 135 if (trap_opcode_size > 0 && trap_opcode_size <= sizeof(m_trap_opcode)) 136 { 137 m_byte_size = trap_opcode_size; 138 ::memcpy (m_trap_opcode, trap_opcode, trap_opcode_size); 139 return true; 140 } 141 m_byte_size = 0; 142 return false; 143 } 144 145 uint8_t * 146 BreakpointSite::GetSavedOpcodeBytes() 147 { 148 return &m_saved_opcode[0]; 149 } 150 151 const uint8_t * 152 BreakpointSite::GetSavedOpcodeBytes() const 153 { 154 return &m_saved_opcode[0]; 155 } 156 157 bool 158 BreakpointSite::IsEnabled () const 159 { 160 return m_enabled; 161 } 162 163 void 164 BreakpointSite::SetEnabled (bool enabled) 165 { 166 m_enabled = enabled; 167 } 168 169 void 170 BreakpointSite::AddOwner (const BreakpointLocationSP &owner) 171 { 172 Mutex::Locker locker(m_owners_mutex); 173 m_owners.Add(owner); 174 } 175 176 size_t 177 BreakpointSite::RemoveOwner (lldb::break_id_t break_id, lldb::break_id_t break_loc_id) 178 { 179 Mutex::Locker locker(m_owners_mutex); 180 m_owners.Remove(break_id, break_loc_id); 181 return m_owners.GetSize(); 182 } 183 184 size_t 185 BreakpointSite::GetNumberOfOwners () 186 { 187 Mutex::Locker locker(m_owners_mutex); 188 return m_owners.GetSize(); 189 } 190 191 BreakpointLocationSP 192 BreakpointSite::GetOwnerAtIndex (size_t index) 193 { 194 Mutex::Locker locker(m_owners_mutex); 195 return m_owners.GetByIndex (index); 196 } 197 198 bool 199 BreakpointSite::ValidForThisThread (Thread *thread) 200 { 201 Mutex::Locker locker(m_owners_mutex); 202 return m_owners.ValidForThisThread(thread); 203 } 204 205 void 206 BreakpointSite::BumpHitCounts() 207 { 208 Mutex::Locker locker(m_owners_mutex); 209 for (BreakpointLocationSP loc_sp : m_owners.BreakpointLocations()) 210 { 211 loc_sp->BumpHitCount(); 212 } 213 } 214 215 bool 216 BreakpointSite::IntersectsRange(lldb::addr_t addr, size_t size, lldb::addr_t *intersect_addr, size_t *intersect_size, size_t *opcode_offset) const 217 { 218 // We only use software traps for software breakpoints 219 if (!IsHardware()) 220 { 221 if (m_byte_size > 0) 222 { 223 const lldb::addr_t bp_end_addr = m_addr + m_byte_size; 224 const lldb::addr_t end_addr = addr + size; 225 // Is the breakpoint end address before the passed in start address? 226 if (bp_end_addr <= addr) 227 return false; 228 // Is the breakpoint start address after passed in end address? 229 if (end_addr <= m_addr) 230 return false; 231 if (intersect_addr || intersect_size || opcode_offset) 232 { 233 if (m_addr < addr) 234 { 235 if (intersect_addr) 236 *intersect_addr = addr; 237 if (intersect_size) 238 *intersect_size = std::min<lldb::addr_t>(bp_end_addr, end_addr) - addr; 239 if (opcode_offset) 240 *opcode_offset = addr - m_addr; 241 } 242 else 243 { 244 if (intersect_addr) 245 *intersect_addr = m_addr; 246 if (intersect_size) 247 *intersect_size = std::min<lldb::addr_t>(bp_end_addr, end_addr) - m_addr; 248 if (opcode_offset) 249 *opcode_offset = 0; 250 } 251 } 252 return true; 253 } 254 } 255 return false; 256 } 257 258 size_t 259 BreakpointSite::CopyOwnersList (BreakpointLocationCollection &out_collection) 260 { 261 Mutex::Locker locker(m_owners_mutex); 262 for (BreakpointLocationSP loc_sp : m_owners.BreakpointLocations()) 263 { 264 out_collection.Add(loc_sp); 265 } 266 return out_collection.GetSize(); 267 } 268