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 // Other libraries and framework includes 15 // Project includes 16 #include "lldb/Breakpoint/Breakpoint.h" 17 #include "lldb/Breakpoint/BreakpointLocation.h" 18 #include "lldb/Breakpoint/BreakpointSiteList.h" 19 20 using namespace lldb; 21 using namespace lldb_private; 22 23 BreakpointSite::BreakpointSite 24 ( 25 BreakpointSiteList *list, 26 const BreakpointLocationSP& owner, 27 lldb::addr_t addr, 28 bool use_hardware 29 ) : 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 == NULL) 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 bool 203 BreakpointSite::IntersectsRange(lldb::addr_t addr, size_t size, lldb::addr_t *intersect_addr, size_t *intersect_size, size_t *opcode_offset) const 204 { 205 // We only use software traps for software breakpoints 206 if (!IsHardware()) 207 { 208 if (m_byte_size > 0) 209 { 210 const lldb::addr_t bp_end_addr = m_addr + m_byte_size; 211 const lldb::addr_t end_addr = addr + size; 212 // Is the breakpoint end address before the passed in start address? 213 if (bp_end_addr <= addr) 214 return false; 215 // Is the breakpoint start address after passed in end address? 216 if (end_addr <= m_addr) 217 return false; 218 if (intersect_addr || intersect_size || opcode_offset) 219 { 220 if (m_addr < addr) 221 { 222 if (intersect_addr) 223 *intersect_addr = addr; 224 if (intersect_size) 225 *intersect_size = std::min<lldb::addr_t>(bp_end_addr, end_addr) - addr; 226 if (opcode_offset) 227 *opcode_offset = addr - m_addr; 228 } 229 else 230 { 231 if (intersect_addr) 232 *intersect_addr = m_addr; 233 if (intersect_size) 234 *intersect_size = std::min<lldb::addr_t>(bp_end_addr, end_addr) - m_addr; 235 if (opcode_offset) 236 *opcode_offset = 0; 237 } 238 } 239 return true; 240 } 241 } 242 return false; 243 } 244