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