blob: 95b67b03c7b316af64a1b267a0957863a464e08c [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- 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
Zachary Turnerfc858812015-03-04 17:43:00 +000014#include <inttypes.h>
15
Chris Lattner30fdc8d2010-06-08 16:52:24 +000016// Other libraries and framework includes
17// Project includes
Greg Clayton4e78f602010-11-18 18:52:36 +000018#include "lldb/Breakpoint/Breakpoint.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000019#include "lldb/Breakpoint/BreakpointLocation.h"
20#include "lldb/Breakpoint/BreakpointSiteList.h"
Zachary Turnerfc858812015-03-04 17:43:00 +000021#include "lldb/Core/Stream.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000022
23using namespace lldb;
24using namespace lldb_private;
25
26BreakpointSite::BreakpointSite
27(
28 BreakpointSiteList *list,
Greg Claytone1cd1be2012-01-29 20:56:30 +000029 const BreakpointLocationSP& owner,
Chris Lattner30fdc8d2010-06-08 16:52:24 +000030 lldb::addr_t addr,
Chris Lattner30fdc8d2010-06-08 16:52:24 +000031 bool use_hardware
32) :
Greg Claytonc7bece562013-01-25 18:06:21 +000033 StoppointLocation(GetNextID(), addr, 0, use_hardware),
Chris Lattner30fdc8d2010-06-08 16:52:24 +000034 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.
Jim Ingham5799e292014-06-18 01:04:40 +000038 m_owners(),
39 m_owners_mutex(Mutex::eMutexTypeRecursive)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000040{
41 m_owners.Add(owner);
42}
43
44BreakpointSite::~BreakpointSite()
45{
46 BreakpointLocationSP bp_loc_sp;
Greg Claytonc982c762010-07-09 20:39:50 +000047 const size_t owner_count = m_owners.GetSize();
48 for (size_t i = 0; i < owner_count; i++)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000049 {
50 m_owners.GetByIndex(i)->ClearBreakpointSite();
51 }
52}
53
54break_id_t
55BreakpointSite::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
64bool
65BreakpointSite::ShouldStop (StoppointCallbackContext *context)
66{
Jim Ingham2dfa00f2014-06-18 23:40:13 +000067 Mutex::Locker locker(m_owners_mutex);
Johnny Chenfab7a912012-01-23 23:03:59 +000068 IncrementHitCount();
Chris Lattner30fdc8d2010-06-08 16:52:24 +000069 return m_owners.ShouldStop (context);
70}
71
72bool
73BreakpointSite::IsBreakpointAtThisSite (lldb::break_id_t bp_id)
74{
Jim Ingham2dfa00f2014-06-18 23:40:13 +000075 Mutex::Locker locker(m_owners_mutex);
Greg Claytonc982c762010-07-09 20:39:50 +000076 const size_t owner_count = m_owners.GetSize();
77 for (size_t i = 0; i < owner_count; i++)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000078 {
79 if (m_owners.GetByIndex(i)->GetBreakpoint().GetID() == bp_id)
80 return true;
81 }
82 return false;
83}
84
85void
86BreakpointSite::Dump(Stream *s) const
87{
88 if (s == NULL)
89 return;
90
Daniel Malead01b2952012-11-29 21:49:15 +000091 s->Printf("BreakpointSite %u: addr = 0x%8.8" PRIx64 " type = %s breakpoint hw_index = %i hit_count = %-4u",
Chris Lattner30fdc8d2010-06-08 16:52:24 +000092 GetID(),
Chris Lattner30fdc8d2010-06-08 16:52:24 +000093 (uint64_t)m_addr,
94 IsHardware() ? "hardware" : "software",
95 GetHardwareIndex(),
96 GetHitCount());
97}
98
99void
100BreakpointSite::GetDescription (Stream *s, lldb::DescriptionLevel level)
101{
Jim Ingham2dfa00f2014-06-18 23:40:13 +0000102 Mutex::Locker locker(m_owners_mutex);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000103 if (level != lldb::eDescriptionLevelBrief)
Daniel Malead01b2952012-11-29 21:49:15 +0000104 s->Printf ("breakpoint site: %d at 0x%8.8" PRIx64, GetID(), GetLoadAddress());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000105 m_owners.GetDescription (s, level);
106}
107
Jim Ingham29950772013-01-26 02:19:28 +0000108bool
109BreakpointSite::IsInternal() const
110{
111 return m_owners.IsInternal();
112}
113
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000114uint8_t *
115BreakpointSite::GetTrapOpcodeBytes()
116{
117 return &m_trap_opcode[0];
118}
119
120const uint8_t *
121BreakpointSite::GetTrapOpcodeBytes() const
122{
123 return &m_trap_opcode[0];
124}
125
126size_t
127BreakpointSite::GetTrapOpcodeMaxByteSize() const
128{
129 return sizeof(m_trap_opcode);
130}
131
132bool
Greg Claytonc7bece562013-01-25 18:06:21 +0000133BreakpointSite::SetTrapOpcode (const uint8_t *trap_opcode, uint32_t trap_opcode_size)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000134{
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
145uint8_t *
146BreakpointSite::GetSavedOpcodeBytes()
147{
148 return &m_saved_opcode[0];
149}
150
151const uint8_t *
152BreakpointSite::GetSavedOpcodeBytes() const
153{
154 return &m_saved_opcode[0];
155}
156
157bool
158BreakpointSite::IsEnabled () const
159{
160 return m_enabled;
161}
162
163void
164BreakpointSite::SetEnabled (bool enabled)
165{
166 m_enabled = enabled;
167}
168
169void
Greg Claytone1cd1be2012-01-29 20:56:30 +0000170BreakpointSite::AddOwner (const BreakpointLocationSP &owner)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000171{
Jim Ingham2dfa00f2014-06-18 23:40:13 +0000172 Mutex::Locker locker(m_owners_mutex);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000173 m_owners.Add(owner);
174}
175
Greg Claytonc7bece562013-01-25 18:06:21 +0000176size_t
Greg Claytonc982c762010-07-09 20:39:50 +0000177BreakpointSite::RemoveOwner (lldb::break_id_t break_id, lldb::break_id_t break_loc_id)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000178{
Jim Ingham2dfa00f2014-06-18 23:40:13 +0000179 Mutex::Locker locker(m_owners_mutex);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000180 m_owners.Remove(break_id, break_loc_id);
181 return m_owners.GetSize();
182}
183
Greg Claytonc7bece562013-01-25 18:06:21 +0000184size_t
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000185BreakpointSite::GetNumberOfOwners ()
186{
Jim Ingham2dfa00f2014-06-18 23:40:13 +0000187 Mutex::Locker locker(m_owners_mutex);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000188 return m_owners.GetSize();
189}
190
191BreakpointLocationSP
Greg Claytonc7bece562013-01-25 18:06:21 +0000192BreakpointSite::GetOwnerAtIndex (size_t index)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000193{
Jim Ingham2dfa00f2014-06-18 23:40:13 +0000194 Mutex::Locker locker(m_owners_mutex);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000195 return m_owners.GetByIndex (index);
196}
197
198bool
Jim Ingham1b54c882010-06-16 02:00:15 +0000199BreakpointSite::ValidForThisThread (Thread *thread)
200{
Jim Ingham2dfa00f2014-06-18 23:40:13 +0000201 Mutex::Locker locker(m_owners_mutex);
Jim Ingham1b54c882010-06-16 02:00:15 +0000202 return m_owners.ValidForThisThread(thread);
203}
204
Jim Inghama672ece2014-10-22 01:54:17 +0000205void
206BreakpointSite::BumpHitCounts()
207{
Jim Inghamff244c12015-07-29 00:40:36 +0000208 Mutex::Locker locker(m_owners_mutex);
Jim Inghama672ece2014-10-22 01:54:17 +0000209 for (BreakpointLocationSP loc_sp : m_owners.BreakpointLocations())
210 {
211 loc_sp->BumpHitCount();
212 }
213}
214
Jim Ingham1b54c882010-06-16 02:00:15 +0000215bool
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000216BreakpointSite::IntersectsRange(lldb::addr_t addr, size_t size, lldb::addr_t *intersect_addr, size_t *intersect_size, size_t *opcode_offset) const
217{
218 // We only use software traps for software breakpoints
219 if (!IsHardware())
220 {
221 if (m_byte_size > 0)
222 {
223 const lldb::addr_t bp_end_addr = m_addr + m_byte_size;
224 const lldb::addr_t end_addr = addr + size;
225 // Is the breakpoint end address before the passed in start address?
226 if (bp_end_addr <= addr)
227 return false;
228 // Is the breakpoint start address after passed in end address?
229 if (end_addr <= m_addr)
230 return false;
231 if (intersect_addr || intersect_size || opcode_offset)
232 {
233 if (m_addr < addr)
234 {
235 if (intersect_addr)
236 *intersect_addr = addr;
237 if (intersect_size)
238 *intersect_size = std::min<lldb::addr_t>(bp_end_addr, end_addr) - addr;
239 if (opcode_offset)
240 *opcode_offset = addr - m_addr;
241 }
242 else
243 {
244 if (intersect_addr)
245 *intersect_addr = m_addr;
246 if (intersect_size)
247 *intersect_size = std::min<lldb::addr_t>(bp_end_addr, end_addr) - m_addr;
248 if (opcode_offset)
249 *opcode_offset = 0;
250 }
251 }
252 return true;
253 }
254 }
255 return false;
256}