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