//===-- BreakpointSite.cpp --------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "lldb/Breakpoint/BreakpointSite.h" // C Includes // C++ Includes // Other libraries and framework includes // Project includes #include "lldb/Breakpoint/Breakpoint.h" #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Breakpoint/BreakpointSiteList.h" using namespace lldb; using namespace lldb_private; BreakpointSite::BreakpointSite ( BreakpointSiteList *list, const BreakpointLocationSP& owner, lldb::addr_t addr, bool use_hardware ) : StoppointLocation(GetNextID(), addr, 0, use_hardware), m_type (eSoftware), // Process subclasses need to set this correctly using SetType() m_saved_opcode(), m_trap_opcode(), m_enabled(false), // Need to create it disabled, so the first enable turns it on. m_owners() { m_owners.Add(owner); } BreakpointSite::~BreakpointSite() { BreakpointLocationSP bp_loc_sp; const size_t owner_count = m_owners.GetSize(); for (size_t i = 0; i < owner_count; i++) { m_owners.GetByIndex(i)->ClearBreakpointSite(); } } break_id_t BreakpointSite::GetNextID() { static break_id_t g_next_id = 0; return ++g_next_id; } // RETURNS - true if we should stop at this breakpoint, false if we // should continue. bool BreakpointSite::ShouldStop (StoppointCallbackContext *context) { IncrementHitCount(); return m_owners.ShouldStop (context); } bool BreakpointSite::IsBreakpointAtThisSite (lldb::break_id_t bp_id) { const size_t owner_count = m_owners.GetSize(); for (size_t i = 0; i < owner_count; i++) { if (m_owners.GetByIndex(i)->GetBreakpoint().GetID() == bp_id) return true; } return false; } void BreakpointSite::Dump(Stream *s) const { if (s == NULL) return; s->Printf("BreakpointSite %u: addr = 0x%8.8" PRIx64 " type = %s breakpoint hw_index = %i hit_count = %-4u", GetID(), (uint64_t)m_addr, IsHardware() ? "hardware" : "software", GetHardwareIndex(), GetHitCount()); } void BreakpointSite::GetDescription (Stream *s, lldb::DescriptionLevel level) { if (level != lldb::eDescriptionLevelBrief) s->Printf ("breakpoint site: %d at 0x%8.8" PRIx64, GetID(), GetLoadAddress()); m_owners.GetDescription (s, level); } bool BreakpointSite::IsInternal() const { return m_owners.IsInternal(); } uint8_t * BreakpointSite::GetTrapOpcodeBytes() { return &m_trap_opcode[0]; } const uint8_t * BreakpointSite::GetTrapOpcodeBytes() const { return &m_trap_opcode[0]; } size_t BreakpointSite::GetTrapOpcodeMaxByteSize() const { return sizeof(m_trap_opcode); } bool BreakpointSite::SetTrapOpcode (const uint8_t *trap_opcode, uint32_t trap_opcode_size) { if (trap_opcode_size > 0 && trap_opcode_size <= sizeof(m_trap_opcode)) { m_byte_size = trap_opcode_size; ::memcpy (m_trap_opcode, trap_opcode, trap_opcode_size); return true; } m_byte_size = 0; return false; } uint8_t * BreakpointSite::GetSavedOpcodeBytes() { return &m_saved_opcode[0]; } const uint8_t * BreakpointSite::GetSavedOpcodeBytes() const { return &m_saved_opcode[0]; } bool BreakpointSite::IsEnabled () const { return m_enabled; } void BreakpointSite::SetEnabled (bool enabled) { m_enabled = enabled; } void BreakpointSite::AddOwner (const BreakpointLocationSP &owner) { m_owners.Add(owner); } size_t BreakpointSite::RemoveOwner (lldb::break_id_t break_id, lldb::break_id_t break_loc_id) { m_owners.Remove(break_id, break_loc_id); return m_owners.GetSize(); } size_t BreakpointSite::GetNumberOfOwners () { return m_owners.GetSize(); } BreakpointLocationSP BreakpointSite::GetOwnerAtIndex (size_t index) { return m_owners.GetByIndex (index); } bool BreakpointSite::ValidForThisThread (Thread *thread) { return m_owners.ValidForThisThread(thread); } bool BreakpointSite::IntersectsRange(lldb::addr_t addr, size_t size, lldb::addr_t *intersect_addr, size_t *intersect_size, size_t *opcode_offset) const { // We only use software traps for software breakpoints if (!IsHardware()) { if (m_byte_size > 0) { const lldb::addr_t bp_end_addr = m_addr + m_byte_size; const lldb::addr_t end_addr = addr + size; // Is the breakpoint end address before the passed in start address? if (bp_end_addr <= addr) return false; // Is the breakpoint start address after passed in end address? if (end_addr <= m_addr) return false; if (intersect_addr || intersect_size || opcode_offset) { if (m_addr < addr) { if (intersect_addr) *intersect_addr = addr; if (intersect_size) *intersect_size = std::min<lldb::addr_t>(bp_end_addr, end_addr) - addr; if (opcode_offset) *opcode_offset = addr - m_addr; } else { if (intersect_addr) *intersect_addr = m_addr; if (intersect_size) *intersect_size = std::min<lldb::addr_t>(bp_end_addr, end_addr) - m_addr; if (opcode_offset) *opcode_offset = 0; } } return true; } } return false; }