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