130fdc8d8SChris Lattner //===-- BreakpointSite.cpp --------------------------------------*- C++ -*-===// 230fdc8d8SChris Lattner // 330fdc8d8SChris Lattner // The LLVM Compiler Infrastructure 430fdc8d8SChris Lattner // 530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source 630fdc8d8SChris Lattner // License. See LICENSE.TXT for details. 730fdc8d8SChris Lattner // 830fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 930fdc8d8SChris Lattner 1030fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointSite.h" 1130fdc8d8SChris Lattner 1230fdc8d8SChris Lattner // C Includes 1330fdc8d8SChris Lattner // C++ Includes 14fc858813SZachary Turner #include <inttypes.h> 15fc858813SZachary Turner 1630fdc8d8SChris Lattner // Other libraries and framework includes 1730fdc8d8SChris Lattner // Project includes 184e78f606SGreg Clayton #include "lldb/Breakpoint/Breakpoint.h" 1930fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointLocation.h" 2030fdc8d8SChris Lattner #include "lldb/Breakpoint/BreakpointSiteList.h" 21fc858813SZachary Turner #include "lldb/Core/Stream.h" 2230fdc8d8SChris Lattner 2330fdc8d8SChris Lattner using namespace lldb; 2430fdc8d8SChris Lattner using namespace lldb_private; 2530fdc8d8SChris Lattner 2630fdc8d8SChris Lattner BreakpointSite::BreakpointSite 2730fdc8d8SChris Lattner ( 2830fdc8d8SChris Lattner BreakpointSiteList *list, 29e1cd1be6SGreg Clayton const BreakpointLocationSP& owner, 3030fdc8d8SChris Lattner lldb::addr_t addr, 3130fdc8d8SChris Lattner bool use_hardware 3230fdc8d8SChris Lattner ) : 33c7bece56SGreg Clayton StoppointLocation(GetNextID(), addr, 0, use_hardware), 3430fdc8d8SChris Lattner m_type (eSoftware), // Process subclasses need to set this correctly using SetType() 3530fdc8d8SChris Lattner m_saved_opcode(), 3630fdc8d8SChris Lattner m_trap_opcode(), 3730fdc8d8SChris Lattner m_enabled(false), // Need to create it disabled, so the first enable turns it on. 385799e291SJim Ingham m_owners(), 395799e291SJim Ingham m_owners_mutex(Mutex::eMutexTypeRecursive) 4030fdc8d8SChris Lattner { 4130fdc8d8SChris Lattner m_owners.Add(owner); 4230fdc8d8SChris Lattner } 4330fdc8d8SChris Lattner 4430fdc8d8SChris Lattner BreakpointSite::~BreakpointSite() 4530fdc8d8SChris Lattner { 4630fdc8d8SChris Lattner BreakpointLocationSP bp_loc_sp; 47c982c768SGreg Clayton const size_t owner_count = m_owners.GetSize(); 48c982c768SGreg Clayton for (size_t i = 0; i < owner_count; i++) 4930fdc8d8SChris Lattner { 5030fdc8d8SChris Lattner m_owners.GetByIndex(i)->ClearBreakpointSite(); 5130fdc8d8SChris Lattner } 5230fdc8d8SChris Lattner } 5330fdc8d8SChris Lattner 5430fdc8d8SChris Lattner break_id_t 5530fdc8d8SChris Lattner BreakpointSite::GetNextID() 5630fdc8d8SChris Lattner { 5730fdc8d8SChris Lattner static break_id_t g_next_id = 0; 5830fdc8d8SChris Lattner return ++g_next_id; 5930fdc8d8SChris Lattner } 6030fdc8d8SChris Lattner 6130fdc8d8SChris Lattner // RETURNS - true if we should stop at this breakpoint, false if we 6230fdc8d8SChris Lattner // should continue. 6330fdc8d8SChris Lattner 6430fdc8d8SChris Lattner bool 6530fdc8d8SChris Lattner BreakpointSite::ShouldStop (StoppointCallbackContext *context) 6630fdc8d8SChris Lattner { 672dfa00f6SJim Ingham Mutex::Locker locker(m_owners_mutex); 68fab7a91dSJohnny Chen IncrementHitCount(); 6930fdc8d8SChris Lattner return m_owners.ShouldStop (context); 7030fdc8d8SChris Lattner } 7130fdc8d8SChris Lattner 7230fdc8d8SChris Lattner bool 7330fdc8d8SChris Lattner BreakpointSite::IsBreakpointAtThisSite (lldb::break_id_t bp_id) 7430fdc8d8SChris Lattner { 752dfa00f6SJim Ingham Mutex::Locker locker(m_owners_mutex); 76c982c768SGreg Clayton const size_t owner_count = m_owners.GetSize(); 77c982c768SGreg Clayton for (size_t i = 0; i < owner_count; i++) 7830fdc8d8SChris Lattner { 7930fdc8d8SChris Lattner if (m_owners.GetByIndex(i)->GetBreakpoint().GetID() == bp_id) 8030fdc8d8SChris Lattner return true; 8130fdc8d8SChris Lattner } 8230fdc8d8SChris Lattner return false; 8330fdc8d8SChris Lattner } 8430fdc8d8SChris Lattner 8530fdc8d8SChris Lattner void 8630fdc8d8SChris Lattner BreakpointSite::Dump(Stream *s) const 8730fdc8d8SChris Lattner { 8830fdc8d8SChris Lattner if (s == NULL) 8930fdc8d8SChris Lattner return; 9030fdc8d8SChris Lattner 91d01b2953SDaniel Malea s->Printf("BreakpointSite %u: addr = 0x%8.8" PRIx64 " type = %s breakpoint hw_index = %i hit_count = %-4u", 9230fdc8d8SChris Lattner GetID(), 9330fdc8d8SChris Lattner (uint64_t)m_addr, 9430fdc8d8SChris Lattner IsHardware() ? "hardware" : "software", 9530fdc8d8SChris Lattner GetHardwareIndex(), 9630fdc8d8SChris Lattner GetHitCount()); 9730fdc8d8SChris Lattner } 9830fdc8d8SChris Lattner 9930fdc8d8SChris Lattner void 10030fdc8d8SChris Lattner BreakpointSite::GetDescription (Stream *s, lldb::DescriptionLevel level) 10130fdc8d8SChris Lattner { 1022dfa00f6SJim Ingham Mutex::Locker locker(m_owners_mutex); 10330fdc8d8SChris Lattner if (level != lldb::eDescriptionLevelBrief) 104d01b2953SDaniel Malea s->Printf ("breakpoint site: %d at 0x%8.8" PRIx64, GetID(), GetLoadAddress()); 10530fdc8d8SChris Lattner m_owners.GetDescription (s, level); 10630fdc8d8SChris Lattner } 10730fdc8d8SChris Lattner 1082995077dSJim Ingham bool 1092995077dSJim Ingham BreakpointSite::IsInternal() const 1102995077dSJim Ingham { 1112995077dSJim Ingham return m_owners.IsInternal(); 1122995077dSJim Ingham } 1132995077dSJim Ingham 11430fdc8d8SChris Lattner uint8_t * 11530fdc8d8SChris Lattner BreakpointSite::GetTrapOpcodeBytes() 11630fdc8d8SChris Lattner { 11730fdc8d8SChris Lattner return &m_trap_opcode[0]; 11830fdc8d8SChris Lattner } 11930fdc8d8SChris Lattner 12030fdc8d8SChris Lattner const uint8_t * 12130fdc8d8SChris Lattner BreakpointSite::GetTrapOpcodeBytes() const 12230fdc8d8SChris Lattner { 12330fdc8d8SChris Lattner return &m_trap_opcode[0]; 12430fdc8d8SChris Lattner } 12530fdc8d8SChris Lattner 12630fdc8d8SChris Lattner size_t 12730fdc8d8SChris Lattner BreakpointSite::GetTrapOpcodeMaxByteSize() const 12830fdc8d8SChris Lattner { 12930fdc8d8SChris Lattner return sizeof(m_trap_opcode); 13030fdc8d8SChris Lattner } 13130fdc8d8SChris Lattner 13230fdc8d8SChris Lattner bool 133c7bece56SGreg Clayton BreakpointSite::SetTrapOpcode (const uint8_t *trap_opcode, uint32_t trap_opcode_size) 13430fdc8d8SChris Lattner { 13530fdc8d8SChris Lattner if (trap_opcode_size > 0 && trap_opcode_size <= sizeof(m_trap_opcode)) 13630fdc8d8SChris Lattner { 13730fdc8d8SChris Lattner m_byte_size = trap_opcode_size; 13830fdc8d8SChris Lattner ::memcpy (m_trap_opcode, trap_opcode, trap_opcode_size); 13930fdc8d8SChris Lattner return true; 14030fdc8d8SChris Lattner } 14130fdc8d8SChris Lattner m_byte_size = 0; 14230fdc8d8SChris Lattner return false; 14330fdc8d8SChris Lattner } 14430fdc8d8SChris Lattner 14530fdc8d8SChris Lattner uint8_t * 14630fdc8d8SChris Lattner BreakpointSite::GetSavedOpcodeBytes() 14730fdc8d8SChris Lattner { 14830fdc8d8SChris Lattner return &m_saved_opcode[0]; 14930fdc8d8SChris Lattner } 15030fdc8d8SChris Lattner 15130fdc8d8SChris Lattner const uint8_t * 15230fdc8d8SChris Lattner BreakpointSite::GetSavedOpcodeBytes() const 15330fdc8d8SChris Lattner { 15430fdc8d8SChris Lattner return &m_saved_opcode[0]; 15530fdc8d8SChris Lattner } 15630fdc8d8SChris Lattner 15730fdc8d8SChris Lattner bool 15830fdc8d8SChris Lattner BreakpointSite::IsEnabled () const 15930fdc8d8SChris Lattner { 16030fdc8d8SChris Lattner return m_enabled; 16130fdc8d8SChris Lattner } 16230fdc8d8SChris Lattner 16330fdc8d8SChris Lattner void 16430fdc8d8SChris Lattner BreakpointSite::SetEnabled (bool enabled) 16530fdc8d8SChris Lattner { 16630fdc8d8SChris Lattner m_enabled = enabled; 16730fdc8d8SChris Lattner } 16830fdc8d8SChris Lattner 16930fdc8d8SChris Lattner void 170e1cd1be6SGreg Clayton BreakpointSite::AddOwner (const BreakpointLocationSP &owner) 17130fdc8d8SChris Lattner { 1722dfa00f6SJim Ingham Mutex::Locker locker(m_owners_mutex); 17330fdc8d8SChris Lattner m_owners.Add(owner); 17430fdc8d8SChris Lattner } 17530fdc8d8SChris Lattner 176c7bece56SGreg Clayton size_t 177c982c768SGreg Clayton BreakpointSite::RemoveOwner (lldb::break_id_t break_id, lldb::break_id_t break_loc_id) 17830fdc8d8SChris Lattner { 1792dfa00f6SJim Ingham Mutex::Locker locker(m_owners_mutex); 18030fdc8d8SChris Lattner m_owners.Remove(break_id, break_loc_id); 18130fdc8d8SChris Lattner return m_owners.GetSize(); 18230fdc8d8SChris Lattner } 18330fdc8d8SChris Lattner 184c7bece56SGreg Clayton size_t 18530fdc8d8SChris Lattner BreakpointSite::GetNumberOfOwners () 18630fdc8d8SChris Lattner { 1872dfa00f6SJim Ingham Mutex::Locker locker(m_owners_mutex); 18830fdc8d8SChris Lattner return m_owners.GetSize(); 18930fdc8d8SChris Lattner } 19030fdc8d8SChris Lattner 19130fdc8d8SChris Lattner BreakpointLocationSP 192c7bece56SGreg Clayton BreakpointSite::GetOwnerAtIndex (size_t index) 19330fdc8d8SChris Lattner { 1942dfa00f6SJim Ingham Mutex::Locker locker(m_owners_mutex); 19530fdc8d8SChris Lattner return m_owners.GetByIndex (index); 19630fdc8d8SChris Lattner } 19730fdc8d8SChris Lattner 19830fdc8d8SChris Lattner bool 1991b54c88cSJim Ingham BreakpointSite::ValidForThisThread (Thread *thread) 2001b54c88cSJim Ingham { 2012dfa00f6SJim Ingham Mutex::Locker locker(m_owners_mutex); 2021b54c88cSJim Ingham return m_owners.ValidForThisThread(thread); 2031b54c88cSJim Ingham } 2041b54c88cSJim Ingham 205a672ecefSJim Ingham void 206a672ecefSJim Ingham BreakpointSite::BumpHitCounts() 207a672ecefSJim Ingham { 208ff244c1dSJim Ingham Mutex::Locker locker(m_owners_mutex); 209a672ecefSJim Ingham for (BreakpointLocationSP loc_sp : m_owners.BreakpointLocations()) 210a672ecefSJim Ingham { 211a672ecefSJim Ingham loc_sp->BumpHitCount(); 212a672ecefSJim Ingham } 213a672ecefSJim Ingham } 214a672ecefSJim Ingham 2151b54c88cSJim Ingham bool 21630fdc8d8SChris Lattner BreakpointSite::IntersectsRange(lldb::addr_t addr, size_t size, lldb::addr_t *intersect_addr, size_t *intersect_size, size_t *opcode_offset) const 21730fdc8d8SChris Lattner { 21830fdc8d8SChris Lattner // We only use software traps for software breakpoints 21930fdc8d8SChris Lattner if (!IsHardware()) 22030fdc8d8SChris Lattner { 22130fdc8d8SChris Lattner if (m_byte_size > 0) 22230fdc8d8SChris Lattner { 22330fdc8d8SChris Lattner const lldb::addr_t bp_end_addr = m_addr + m_byte_size; 22430fdc8d8SChris Lattner const lldb::addr_t end_addr = addr + size; 22530fdc8d8SChris Lattner // Is the breakpoint end address before the passed in start address? 22630fdc8d8SChris Lattner if (bp_end_addr <= addr) 22730fdc8d8SChris Lattner return false; 22830fdc8d8SChris Lattner // Is the breakpoint start address after passed in end address? 22930fdc8d8SChris Lattner if (end_addr <= m_addr) 23030fdc8d8SChris Lattner return false; 23130fdc8d8SChris Lattner if (intersect_addr || intersect_size || opcode_offset) 23230fdc8d8SChris Lattner { 23330fdc8d8SChris Lattner if (m_addr < addr) 23430fdc8d8SChris Lattner { 23530fdc8d8SChris Lattner if (intersect_addr) 23630fdc8d8SChris Lattner *intersect_addr = addr; 23730fdc8d8SChris Lattner if (intersect_size) 23830fdc8d8SChris Lattner *intersect_size = std::min<lldb::addr_t>(bp_end_addr, end_addr) - addr; 23930fdc8d8SChris Lattner if (opcode_offset) 24030fdc8d8SChris Lattner *opcode_offset = addr - m_addr; 24130fdc8d8SChris Lattner } 24230fdc8d8SChris Lattner else 24330fdc8d8SChris Lattner { 24430fdc8d8SChris Lattner if (intersect_addr) 24530fdc8d8SChris Lattner *intersect_addr = m_addr; 24630fdc8d8SChris Lattner if (intersect_size) 24730fdc8d8SChris Lattner *intersect_size = std::min<lldb::addr_t>(bp_end_addr, end_addr) - m_addr; 24830fdc8d8SChris Lattner if (opcode_offset) 24930fdc8d8SChris Lattner *opcode_offset = 0; 25030fdc8d8SChris Lattner } 25130fdc8d8SChris Lattner } 25230fdc8d8SChris Lattner return true; 25330fdc8d8SChris Lattner } 25430fdc8d8SChris Lattner } 25530fdc8d8SChris Lattner return false; 25630fdc8d8SChris Lattner } 257*9d1ccdafSJim Ingham 258*9d1ccdafSJim Ingham size_t 259*9d1ccdafSJim Ingham BreakpointSite::CopyOwnersList (BreakpointLocationCollection &out_collection) 260*9d1ccdafSJim Ingham { 261*9d1ccdafSJim Ingham Mutex::Locker locker(m_owners_mutex); 262*9d1ccdafSJim Ingham for (BreakpointLocationSP loc_sp : m_owners.BreakpointLocations()) 263*9d1ccdafSJim Ingham { 264*9d1ccdafSJim Ingham out_collection.Add(loc_sp); 265*9d1ccdafSJim Ingham } 266*9d1ccdafSJim Ingham return out_collection.GetSize(); 267*9d1ccdafSJim Ingham } 268