blob: 5b946939d80f7996268327fbbddad9ba21364f37 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- DNBBreakpoint.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// Created by Greg Clayton on 6/29/07.
11//
12//===----------------------------------------------------------------------===//
13
14#include "DNBBreakpoint.h"
15#include <algorithm>
Jason Molenda1c739112013-02-22 07:27:08 +000016#include <inttypes.h>
Chris Lattner30fdc8d2010-06-08 16:52:24 +000017#include "DNBLog.h"
18
19
20#pragma mark -- DNBBreakpoint
21DNBBreakpoint::DNBBreakpoint(nub_addr_t addr, nub_size_t byte_size, nub_thread_t tid, bool hardware) :
22 m_breakID(GetNextID()),
23 m_tid(tid),
24 m_byte_size(byte_size),
25 m_opcode(),
26 m_addr(addr),
27 m_enabled(0),
28 m_hw_preferred(hardware),
29 m_is_watchpoint(0),
30 m_watch_read(0),
31 m_watch_write(0),
32 m_hw_index(INVALID_NUB_HW_INDEX),
33 m_hit_count(0),
34 m_ignore_count(0),
35 m_callback(NULL),
36 m_callback_baton(NULL)
37{
38}
39
40DNBBreakpoint::~DNBBreakpoint()
41{
42}
43
44nub_break_t
45DNBBreakpoint::GetNextID()
46{
47 static uint32_t g_nextBreakID = 0;
48 return ++g_nextBreakID;
49}
50
51void
52DNBBreakpoint::SetCallback(DNBCallbackBreakpointHit callback, void *callback_baton)
53{
54 m_callback = callback;
55 m_callback_baton = callback_baton;
56}
57
58
59// RETURNS - true if we should stop at this breakpoint, false if we
60// should continue.
61
62bool
63DNBBreakpoint::BreakpointHit(nub_process_t pid, nub_thread_t tid)
64{
65 m_hit_count++;
66
67 if (m_hit_count > m_ignore_count)
68 {
69 if (m_callback)
70 return m_callback(pid, tid, GetID(), m_callback_baton);
71 return true;
72 }
73 return false;
74}
75
76void
77DNBBreakpoint::Dump() const
78{
79 if (IsBreakpoint())
80 {
Jason Molenda1c739112013-02-22 07:27:08 +000081 DNBLog ("DNBBreakpoint %u: tid = %8.8" PRIx64 " addr = 0x%llx state = %s type = %s breakpoint hw_index = %i hit_count = %-4u ignore_count = %-4u callback = %p baton = %p",
Greg Clayton490fbbe2011-10-28 22:59:14 +000082 m_breakID,
83 m_tid,
84 (uint64_t)m_addr,
85 m_enabled ? "enabled " : "disabled",
86 IsHardware() ? "hardware" : "software",
87 GetHardwareIndex(),
88 GetHitCount(),
89 GetIgnoreCount(),
90 m_callback,
91 m_callback_baton);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000092 }
93 else
94 {
Jason Molenda1c739112013-02-22 07:27:08 +000095 DNBLog ("DNBBreakpoint %u: tid = %8.8" PRIx64 " addr = 0x%llx size = %llu state = %s type = %s watchpoint (%s%s) hw_index = %i hit_count = %-4u ignore_count = %-4u callback = %p baton = %p",
Greg Clayton490fbbe2011-10-28 22:59:14 +000096 m_breakID,
97 m_tid,
98 (uint64_t)m_addr,
Greg Clayton43e0af02012-09-18 18:04:04 +000099 (uint64_t)m_byte_size,
Greg Clayton490fbbe2011-10-28 22:59:14 +0000100 m_enabled ? "enabled " : "disabled",
101 IsHardware() ? "hardware" : "software",
102 m_watch_read ? "r" : "",
103 m_watch_write ? "w" : "",
104 GetHardwareIndex(),
105 GetHitCount(),
106 GetIgnoreCount(),
107 m_callback,
108 m_callback_baton);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000109 }
110}
111
112#pragma mark -- DNBBreakpointList
113
114DNBBreakpointList::DNBBreakpointList()
115{
116}
117
118DNBBreakpointList::~DNBBreakpointList()
119{
120}
121
122
123nub_break_t
124DNBBreakpointList::Add(const DNBBreakpoint& bp)
125{
126 m_breakpoints.push_back(bp);
127 return m_breakpoints.back().GetID();
128}
129
130bool
131DNBBreakpointList::ShouldStop(nub_process_t pid, nub_thread_t tid, nub_break_t breakID)
132{
133 DNBBreakpoint *bp = FindByID (breakID);
134 if (bp)
135 {
136 // Let the breakpoint decide if it should stop here (could not have
137 // reached it's target hit count yet, or it could have a callback
138 // that decided it shouldn't stop (shared library loads/unloads).
139 return bp->BreakpointHit(pid, tid);
140 }
141 // We should stop here since this breakpoint isn't valid anymore or it
142 // doesn't exist.
143 return true;
144}
145
146nub_break_t
147DNBBreakpointList::FindIDByAddress (nub_addr_t addr)
148{
149 DNBBreakpoint *bp = FindByAddress (addr);
150 if (bp)
151 {
Greg Claytone2d4f0d2011-01-19 07:54:15 +0000152 DNBLogThreadedIf(LOG_BREAKPOINTS, "DNBBreakpointList::%s ( addr = 0x%16.16llx ) => %u", __FUNCTION__, (uint64_t)addr, bp->GetID());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000153 return bp->GetID();
154 }
Greg Claytone2d4f0d2011-01-19 07:54:15 +0000155 DNBLogThreadedIf(LOG_BREAKPOINTS, "DNBBreakpointList::%s ( addr = 0x%16.16llx ) => NONE", __FUNCTION__, (uint64_t)addr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000156 return INVALID_NUB_BREAK_ID;
157}
158
159bool
160DNBBreakpointList::Remove (nub_break_t breakID)
161{
162 iterator pos = GetBreakIDIterator(breakID); // Predicate
163 if (pos != m_breakpoints.end())
164 {
165 m_breakpoints.erase(pos);
166 return true;
167 }
168 return false;
169}
170
171
172class BreakpointIDMatches
173{
174public:
175 BreakpointIDMatches (nub_break_t breakID) : m_breakID(breakID) {}
176 bool operator() (const DNBBreakpoint& bp) const
177 {
178 return m_breakID == bp.GetID();
179 }
180 private:
181 const nub_break_t m_breakID;
182};
183
184class BreakpointAddressMatches
185{
186public:
187 BreakpointAddressMatches (nub_addr_t addr) : m_addr(addr) {}
188 bool operator() (const DNBBreakpoint& bp) const
189 {
190 return m_addr == bp.Address();
191 }
192 private:
193 const nub_addr_t m_addr;
194};
195
196DNBBreakpointList::iterator
197DNBBreakpointList::GetBreakIDIterator (nub_break_t breakID)
198{
199 return std::find_if(m_breakpoints.begin(), m_breakpoints.end(), // Search full range
200 BreakpointIDMatches(breakID)); // Predicate
201}
202
203DNBBreakpointList::const_iterator
204DNBBreakpointList::GetBreakIDConstIterator (nub_break_t breakID) const
205{
206 return std::find_if(m_breakpoints.begin(), m_breakpoints.end(), // Search full range
207 BreakpointIDMatches(breakID)); // Predicate
208}
209
210DNBBreakpoint *
211DNBBreakpointList::FindByID (nub_break_t breakID)
212{
213 iterator pos = GetBreakIDIterator(breakID);
214 if (pos != m_breakpoints.end())
215 return &(*pos);
216
217 return NULL;
218}
219
220const DNBBreakpoint *
221DNBBreakpointList::FindByID (nub_break_t breakID) const
222{
223 const_iterator pos = GetBreakIDConstIterator(breakID);
224 if (pos != m_breakpoints.end())
225 return &(*pos);
226
227 return NULL;
228}
229
230DNBBreakpoint *
231DNBBreakpointList::FindByAddress (nub_addr_t addr)
232{
233 iterator end = m_breakpoints.end();
234 iterator pos = std::find_if(m_breakpoints.begin(), end, // Search full range
235 BreakpointAddressMatches(addr)); // Predicate
236 if (pos != end)
237 return &(*pos);
238
239 return NULL;
240}
241
242const DNBBreakpoint *
243DNBBreakpointList::FindByAddress (nub_addr_t addr) const
244{
245 const_iterator end = m_breakpoints.end();
246 const_iterator pos = std::find_if(m_breakpoints.begin(), end, // Search full range
247 BreakpointAddressMatches(addr)); // Predicate
248 if (pos != end)
249 return &(*pos);
250
251 return NULL;
252}
253
254bool
255DNBBreakpointList::SetCallback(nub_break_t breakID, DNBCallbackBreakpointHit callback, void *callback_baton)
256{
257 DNBBreakpoint *bp = FindByID (breakID);
258 if (bp)
259 {
260 bp->SetCallback(callback, callback_baton);
261 return true;
262 }
263 return false;
264}
265
266
267void
268DNBBreakpointList::Dump() const
269{
270 const_iterator pos;
271 const_iterator end = m_breakpoints.end();
272 for (pos = m_breakpoints.begin(); pos != end; ++pos)
273 (*pos).Dump();
274}
275
276
277DNBBreakpoint *
278DNBBreakpointList::GetByIndex (uint32_t i)
279{
280 iterator end = m_breakpoints.end();
281 iterator pos;
282 uint32_t curr_i = 0;
283 for (pos = m_breakpoints.begin(), curr_i = 0; pos != end; ++pos, ++curr_i)
284 {
285 if (curr_i == i)
286 return &(*pos);
287 }
288 return NULL;
289}
290
291const DNBBreakpoint *
292DNBBreakpointList::GetByIndex (uint32_t i) const
293{
294 const_iterator end = m_breakpoints.end();
295 const_iterator pos;
296 uint32_t curr_i = 0;
297 for (pos = m_breakpoints.begin(), curr_i = 0; pos != end; ++pos, ++curr_i)
298 {
299 if (curr_i == i)
300 return &(*pos);
301 }
302 return NULL;
303}
304