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