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