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