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