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 
BreakpointSite(BreakpointSiteList * list,const BreakpointLocationSP & owner,lldb::addr_t addr,bool use_hardware)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 
~BreakpointSite()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
GetNextID()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
ShouldStop(StoppointCallbackContext * context)61 BreakpointSite::ShouldStop (StoppointCallbackContext *context)
62 {
63     IncrementHitCount();
64     return m_owners.ShouldStop (context);
65 }
66 
67 bool
IsBreakpointAtThisSite(lldb::break_id_t bp_id)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
Dump(Stream * s) const80 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
GetDescription(Stream * s,lldb::DescriptionLevel level)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
IsInternal() const102 BreakpointSite::IsInternal() const
103 {
104     return m_owners.IsInternal();
105 }
106 
107 uint8_t *
GetTrapOpcodeBytes()108 BreakpointSite::GetTrapOpcodeBytes()
109 {
110     return &m_trap_opcode[0];
111 }
112 
113 const uint8_t *
GetTrapOpcodeBytes() const114 BreakpointSite::GetTrapOpcodeBytes() const
115 {
116     return &m_trap_opcode[0];
117 }
118 
119 size_t
GetTrapOpcodeMaxByteSize() const120 BreakpointSite::GetTrapOpcodeMaxByteSize() const
121 {
122     return sizeof(m_trap_opcode);
123 }
124 
125 bool
SetTrapOpcode(const uint8_t * trap_opcode,uint32_t trap_opcode_size)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 *
GetSavedOpcodeBytes()139 BreakpointSite::GetSavedOpcodeBytes()
140 {
141     return &m_saved_opcode[0];
142 }
143 
144 const uint8_t *
GetSavedOpcodeBytes() const145 BreakpointSite::GetSavedOpcodeBytes() const
146 {
147     return &m_saved_opcode[0];
148 }
149 
150 bool
IsEnabled() const151 BreakpointSite::IsEnabled () const
152 {
153     return m_enabled;
154 }
155 
156 void
SetEnabled(bool enabled)157 BreakpointSite::SetEnabled (bool enabled)
158 {
159     m_enabled = enabled;
160 }
161 
162 void
AddOwner(const BreakpointLocationSP & owner)163 BreakpointSite::AddOwner (const BreakpointLocationSP &owner)
164 {
165     m_owners.Add(owner);
166 }
167 
168 size_t
RemoveOwner(lldb::break_id_t break_id,lldb::break_id_t break_loc_id)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
GetNumberOfOwners()176 BreakpointSite::GetNumberOfOwners ()
177 {
178     return m_owners.GetSize();
179 }
180 
181 BreakpointLocationSP
GetOwnerAtIndex(size_t index)182 BreakpointSite::GetOwnerAtIndex (size_t index)
183 {
184     return m_owners.GetByIndex (index);
185 }
186 
187 bool
ValidForThisThread(Thread * thread)188 BreakpointSite::ValidForThisThread (Thread *thread)
189 {
190     return m_owners.ValidForThisThread(thread);
191 }
192 
193 bool
IntersectsRange(lldb::addr_t addr,size_t size,lldb::addr_t * intersect_addr,size_t * intersect_size,size_t * opcode_offset) const194 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