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 { 37 m_owners.Add(owner); 38 } 39 40 BreakpointSite::~BreakpointSite() 41 { 42 BreakpointLocationSP bp_loc_sp; 43 const size_t owner_count = m_owners.GetSize(); 44 for (size_t i = 0; i < owner_count; i++) 45 { 46 m_owners.GetByIndex(i)->ClearBreakpointSite(); 47 } 48 } 49 50 break_id_t 51 BreakpointSite::GetNextID() 52 { 53 static break_id_t g_next_id = 0; 54 return ++g_next_id; 55 } 56 57 // RETURNS - true if we should stop at this breakpoint, false if we 58 // should continue. 59 60 bool 61 BreakpointSite::ShouldStop (StoppointCallbackContext *context) 62 { 63 IncrementHitCount(); 64 return m_owners.ShouldStop (context); 65 } 66 67 bool 68 BreakpointSite::IsBreakpointAtThisSite (lldb::break_id_t bp_id) 69 { 70 const size_t owner_count = m_owners.GetSize(); 71 for (size_t i = 0; i < owner_count; i++) 72 { 73 if (m_owners.GetByIndex(i)->GetBreakpoint().GetID() == bp_id) 74 return true; 75 } 76 return false; 77 } 78 79 void 80 BreakpointSite::Dump(Stream *s) const 81 { 82 if (s == NULL) 83 return; 84 85 s->Printf("BreakpointSite %u: addr = 0x%8.8" PRIx64 " type = %s breakpoint hw_index = %i hit_count = %-4u", 86 GetID(), 87 (uint64_t)m_addr, 88 IsHardware() ? "hardware" : "software", 89 GetHardwareIndex(), 90 GetHitCount()); 91 } 92 93 void 94 BreakpointSite::GetDescription (Stream *s, lldb::DescriptionLevel level) 95 { 96 if (level != lldb::eDescriptionLevelBrief) 97 s->Printf ("breakpoint site: %d at 0x%8.8" PRIx64, GetID(), GetLoadAddress()); 98 m_owners.GetDescription (s, level); 99 } 100 101 bool 102 BreakpointSite::IsInternal() const 103 { 104 return m_owners.IsInternal(); 105 } 106 107 uint8_t * 108 BreakpointSite::GetTrapOpcodeBytes() 109 { 110 return &m_trap_opcode[0]; 111 } 112 113 const uint8_t * 114 BreakpointSite::GetTrapOpcodeBytes() const 115 { 116 return &m_trap_opcode[0]; 117 } 118 119 size_t 120 BreakpointSite::GetTrapOpcodeMaxByteSize() const 121 { 122 return sizeof(m_trap_opcode); 123 } 124 125 bool 126 BreakpointSite::SetTrapOpcode (const uint8_t *trap_opcode, uint32_t trap_opcode_size) 127 { 128 if (trap_opcode_size > 0 && trap_opcode_size <= sizeof(m_trap_opcode)) 129 { 130 m_byte_size = trap_opcode_size; 131 ::memcpy (m_trap_opcode, trap_opcode, trap_opcode_size); 132 return true; 133 } 134 m_byte_size = 0; 135 return false; 136 } 137 138 uint8_t * 139 BreakpointSite::GetSavedOpcodeBytes() 140 { 141 return &m_saved_opcode[0]; 142 } 143 144 const uint8_t * 145 BreakpointSite::GetSavedOpcodeBytes() const 146 { 147 return &m_saved_opcode[0]; 148 } 149 150 bool 151 BreakpointSite::IsEnabled () const 152 { 153 return m_enabled; 154 } 155 156 void 157 BreakpointSite::SetEnabled (bool enabled) 158 { 159 m_enabled = enabled; 160 } 161 162 void 163 BreakpointSite::AddOwner (const BreakpointLocationSP &owner) 164 { 165 m_owners.Add(owner); 166 } 167 168 size_t 169 BreakpointSite::RemoveOwner (lldb::break_id_t break_id, lldb::break_id_t break_loc_id) 170 { 171 m_owners.Remove(break_id, break_loc_id); 172 return m_owners.GetSize(); 173 } 174 175 size_t 176 BreakpointSite::GetNumberOfOwners () 177 { 178 return m_owners.GetSize(); 179 } 180 181 BreakpointLocationSP 182 BreakpointSite::GetOwnerAtIndex (size_t index) 183 { 184 return m_owners.GetByIndex (index); 185 } 186 187 bool 188 BreakpointSite::ValidForThisThread (Thread *thread) 189 { 190 return m_owners.ValidForThisThread(thread); 191 } 192 193 bool 194 BreakpointSite::IntersectsRange(lldb::addr_t addr, size_t size, lldb::addr_t *intersect_addr, size_t *intersect_size, size_t *opcode_offset) const 195 { 196 // We only use software traps for software breakpoints 197 if (!IsHardware()) 198 { 199 if (m_byte_size > 0) 200 { 201 const lldb::addr_t bp_end_addr = m_addr + m_byte_size; 202 const lldb::addr_t end_addr = addr + size; 203 // Is the breakpoint end address before the passed in start address? 204 if (bp_end_addr <= addr) 205 return false; 206 // Is the breakpoint start address after passed in end address? 207 if (end_addr <= m_addr) 208 return false; 209 if (intersect_addr || intersect_size || opcode_offset) 210 { 211 if (m_addr < addr) 212 { 213 if (intersect_addr) 214 *intersect_addr = addr; 215 if (intersect_size) 216 *intersect_size = std::min<lldb::addr_t>(bp_end_addr, end_addr) - addr; 217 if (opcode_offset) 218 *opcode_offset = addr - m_addr; 219 } 220 else 221 { 222 if (intersect_addr) 223 *intersect_addr = m_addr; 224 if (intersect_size) 225 *intersect_size = std::min<lldb::addr_t>(bp_end_addr, end_addr) - m_addr; 226 if (opcode_offset) 227 *opcode_offset = 0; 228 } 229 } 230 return true; 231 } 232 } 233 return false; 234 } 235