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 BreakpointLocationSP& owner, 27 lldb::addr_t addr, 28 lldb::tid_t tid, 29 bool use_hardware 30 ) : 31 StoppointLocation(GetNextID(), addr, tid, use_hardware), 32 m_type (eSoftware), // Process subclasses need to set this correctly using SetType() 33 m_saved_opcode(), 34 m_trap_opcode(), 35 m_enabled(false), // Need to create it disabled, so the first enable turns it on. 36 m_owners() 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 m_hit_count++; 65 return m_owners.ShouldStop (context); 66 } 67 68 bool 69 BreakpointSite::IsBreakpointAtThisSite (lldb::break_id_t bp_id) 70 { 71 const size_t owner_count = m_owners.GetSize(); 72 for (size_t i = 0; i < owner_count; i++) 73 { 74 if (m_owners.GetByIndex(i)->GetBreakpoint().GetID() == bp_id) 75 return true; 76 } 77 return false; 78 } 79 80 void 81 BreakpointSite::Dump(Stream *s) const 82 { 83 if (s == NULL) 84 return; 85 86 s->Printf("BreakpointSite %u: addr = 0x%8.8llx type = %s breakpoint hw_index = %i hit_count = %-4u", 87 GetID(), 88 (uint64_t)m_addr, 89 IsHardware() ? "hardware" : "software", 90 GetHardwareIndex(), 91 GetHitCount()); 92 } 93 94 void 95 BreakpointSite::GetDescription (Stream *s, lldb::DescriptionLevel level) 96 { 97 if (level != lldb::eDescriptionLevelBrief) 98 s->Printf ("breakpoint site: %d at 0x%8.8llx", GetID(), GetLoadAddress()); 99 m_owners.GetDescription (s, level); 100 } 101 102 uint8_t * 103 BreakpointSite::GetTrapOpcodeBytes() 104 { 105 return &m_trap_opcode[0]; 106 } 107 108 const uint8_t * 109 BreakpointSite::GetTrapOpcodeBytes() const 110 { 111 return &m_trap_opcode[0]; 112 } 113 114 size_t 115 BreakpointSite::GetTrapOpcodeMaxByteSize() const 116 { 117 return sizeof(m_trap_opcode); 118 } 119 120 bool 121 BreakpointSite::SetTrapOpcode (const uint8_t *trap_opcode, size_t trap_opcode_size) 122 { 123 if (trap_opcode_size > 0 && trap_opcode_size <= sizeof(m_trap_opcode)) 124 { 125 m_byte_size = trap_opcode_size; 126 ::memcpy (m_trap_opcode, trap_opcode, trap_opcode_size); 127 return true; 128 } 129 m_byte_size = 0; 130 return false; 131 } 132 133 uint8_t * 134 BreakpointSite::GetSavedOpcodeBytes() 135 { 136 return &m_saved_opcode[0]; 137 } 138 139 const uint8_t * 140 BreakpointSite::GetSavedOpcodeBytes() const 141 { 142 return &m_saved_opcode[0]; 143 } 144 145 bool 146 BreakpointSite::IsEnabled () const 147 { 148 return m_enabled; 149 } 150 151 void 152 BreakpointSite::SetEnabled (bool enabled) 153 { 154 m_enabled = enabled; 155 } 156 157 void 158 BreakpointSite::AddOwner (BreakpointLocationSP &owner) 159 { 160 m_owners.Add(owner); 161 } 162 163 uint32_t 164 BreakpointSite::RemoveOwner (lldb::break_id_t break_id, lldb::break_id_t break_loc_id) 165 { 166 m_owners.Remove(break_id, break_loc_id); 167 return m_owners.GetSize(); 168 } 169 170 uint32_t 171 BreakpointSite::GetNumberOfOwners () 172 { 173 return m_owners.GetSize(); 174 } 175 176 BreakpointLocationSP 177 BreakpointSite::GetOwnerAtIndex (uint32_t index) 178 { 179 return m_owners.GetByIndex (index); 180 } 181 182 bool 183 BreakpointSite::ValidForThisThread (Thread *thread) 184 { 185 return m_owners.ValidForThisThread(thread); 186 } 187 188 bool 189 BreakpointSite::IntersectsRange(lldb::addr_t addr, size_t size, lldb::addr_t *intersect_addr, size_t *intersect_size, size_t *opcode_offset) const 190 { 191 // We only use software traps for software breakpoints 192 if (!IsHardware()) 193 { 194 if (m_byte_size > 0) 195 { 196 const lldb::addr_t bp_end_addr = m_addr + m_byte_size; 197 const lldb::addr_t end_addr = addr + size; 198 // Is the breakpoint end address before the passed in start address? 199 if (bp_end_addr <= addr) 200 return false; 201 // Is the breakpoint start address after passed in end address? 202 if (end_addr <= m_addr) 203 return false; 204 if (intersect_addr || intersect_size || opcode_offset) 205 { 206 if (m_addr < addr) 207 { 208 if (intersect_addr) 209 *intersect_addr = addr; 210 if (intersect_size) 211 *intersect_size = std::min<lldb::addr_t>(bp_end_addr, end_addr) - addr; 212 if (opcode_offset) 213 *opcode_offset = addr - m_addr; 214 } 215 else 216 { 217 if (intersect_addr) 218 *intersect_addr = m_addr; 219 if (intersect_size) 220 *intersect_size = std::min<lldb::addr_t>(bp_end_addr, end_addr) - m_addr; 221 if (opcode_offset) 222 *opcode_offset = 0; 223 } 224 } 225 return true; 226 } 227 } 228 return false; 229 } 230