diff options
Diffstat (limited to 'lldb/tools/debugserver/source/DNBBreakpoint.cpp')
-rw-r--r-- | lldb/tools/debugserver/source/DNBBreakpoint.cpp | 303 |
1 files changed, 303 insertions, 0 deletions
diff --git a/lldb/tools/debugserver/source/DNBBreakpoint.cpp b/lldb/tools/debugserver/source/DNBBreakpoint.cpp new file mode 100644 index 00000000000..837f53260cf --- /dev/null +++ b/lldb/tools/debugserver/source/DNBBreakpoint.cpp @@ -0,0 +1,303 @@ +//===-- DNBBreakpoint.cpp ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Created by Greg Clayton on 6/29/07. +// +//===----------------------------------------------------------------------===// + +#include "DNBBreakpoint.h" +#include <algorithm> +#include "DNBLog.h" + + +#pragma mark -- DNBBreakpoint +DNBBreakpoint::DNBBreakpoint(nub_addr_t addr, nub_size_t byte_size, nub_thread_t tid, bool hardware) : + m_breakID(GetNextID()), + m_tid(tid), + m_byte_size(byte_size), + m_opcode(), + m_addr(addr), + m_enabled(0), + m_hw_preferred(hardware), + m_is_watchpoint(0), + m_watch_read(0), + m_watch_write(0), + m_hw_index(INVALID_NUB_HW_INDEX), + m_hit_count(0), + m_ignore_count(0), + m_callback(NULL), + m_callback_baton(NULL) +{ +} + +DNBBreakpoint::~DNBBreakpoint() +{ +} + +nub_break_t +DNBBreakpoint::GetNextID() +{ + static uint32_t g_nextBreakID = 0; + return ++g_nextBreakID; +} + +void +DNBBreakpoint::SetCallback(DNBCallbackBreakpointHit callback, void *callback_baton) +{ + m_callback = callback; + m_callback_baton = callback_baton; +} + + +// RETURNS - true if we should stop at this breakpoint, false if we +// should continue. + +bool +DNBBreakpoint::BreakpointHit(nub_process_t pid, nub_thread_t tid) +{ + m_hit_count++; + + if (m_hit_count > m_ignore_count) + { + if (m_callback) + return m_callback(pid, tid, GetID(), m_callback_baton); + return true; + } + return false; +} + +void +DNBBreakpoint::Dump() const +{ + if (IsBreakpoint()) + { + DNBLog("DNBBreakpoint %u: tid = %4.4x addr = %8.8p state = %s type = %s breakpoint hw_index = %i hit_count = %-4u ignore_count = %-4u callback = %8.8p baton = %8.8p", + m_breakID, + m_tid, + m_addr, + m_enabled ? "enabled " : "disabled", + IsHardware() ? "hardware" : "software", + GetHardwareIndex(), + GetHitCount(), + GetIgnoreCount(), + m_callback, + m_callback_baton); + } + else + { + DNBLog("DNBBreakpoint %u: tid = %4.4x addr = %8.8p size = %u state = %s type = %s watchpoint (%s%s) hw_index = %i hit_count = %-4u ignore_count = %-4u callback = %8.8p baton = %8.8p", + m_breakID, + m_tid, + m_addr, + m_byte_size, + m_enabled ? "enabled " : "disabled", + IsHardware() ? "hardware" : "software", + m_watch_read ? "r" : "", + m_watch_write ? "w" : "", + GetHardwareIndex(), + GetHitCount(), + GetIgnoreCount(), + m_callback, + m_callback_baton); + } +} + +#pragma mark -- DNBBreakpointList + +DNBBreakpointList::DNBBreakpointList() +{ +} + +DNBBreakpointList::~DNBBreakpointList() +{ +} + + +nub_break_t +DNBBreakpointList::Add(const DNBBreakpoint& bp) +{ + m_breakpoints.push_back(bp); + return m_breakpoints.back().GetID(); +} + +bool +DNBBreakpointList::ShouldStop(nub_process_t pid, nub_thread_t tid, nub_break_t breakID) +{ + DNBBreakpoint *bp = FindByID (breakID); + if (bp) + { + // Let the breakpoint decide if it should stop here (could not have + // reached it's target hit count yet, or it could have a callback + // that decided it shouldn't stop (shared library loads/unloads). + return bp->BreakpointHit(pid, tid); + } + // We should stop here since this breakpoint isn't valid anymore or it + // doesn't exist. + return true; +} + +nub_break_t +DNBBreakpointList::FindIDByAddress (nub_addr_t addr) +{ + DNBBreakpoint *bp = FindByAddress (addr); + if (bp) + { + DNBLogThreadedIf(LOG_BREAKPOINTS, "DNBBreakpointList::%s ( addr = 0x%8.8llx ) => %u", __FUNCTION__, (uint64_t)addr, bp->GetID()); + return bp->GetID(); + } + DNBLogThreadedIf(LOG_BREAKPOINTS, "DNBBreakpointList::%s ( addr = 0x%8.8llx ) => NONE", __FUNCTION__, (uint64_t)addr); + return INVALID_NUB_BREAK_ID; +} + +bool +DNBBreakpointList::Remove (nub_break_t breakID) +{ + iterator pos = GetBreakIDIterator(breakID); // Predicate + if (pos != m_breakpoints.end()) + { + m_breakpoints.erase(pos); + return true; + } + return false; +} + + +class BreakpointIDMatches +{ +public: + BreakpointIDMatches (nub_break_t breakID) : m_breakID(breakID) {} + bool operator() (const DNBBreakpoint& bp) const + { + return m_breakID == bp.GetID(); + } + private: + const nub_break_t m_breakID; +}; + +class BreakpointAddressMatches +{ +public: + BreakpointAddressMatches (nub_addr_t addr) : m_addr(addr) {} + bool operator() (const DNBBreakpoint& bp) const + { + return m_addr == bp.Address(); + } + private: + const nub_addr_t m_addr; +}; + +DNBBreakpointList::iterator +DNBBreakpointList::GetBreakIDIterator (nub_break_t breakID) +{ + return std::find_if(m_breakpoints.begin(), m_breakpoints.end(), // Search full range + BreakpointIDMatches(breakID)); // Predicate +} + +DNBBreakpointList::const_iterator +DNBBreakpointList::GetBreakIDConstIterator (nub_break_t breakID) const +{ + return std::find_if(m_breakpoints.begin(), m_breakpoints.end(), // Search full range + BreakpointIDMatches(breakID)); // Predicate +} + +DNBBreakpoint * +DNBBreakpointList::FindByID (nub_break_t breakID) +{ + iterator pos = GetBreakIDIterator(breakID); + if (pos != m_breakpoints.end()) + return &(*pos); + + return NULL; +} + +const DNBBreakpoint * +DNBBreakpointList::FindByID (nub_break_t breakID) const +{ + const_iterator pos = GetBreakIDConstIterator(breakID); + if (pos != m_breakpoints.end()) + return &(*pos); + + return NULL; +} + +DNBBreakpoint * +DNBBreakpointList::FindByAddress (nub_addr_t addr) +{ + iterator end = m_breakpoints.end(); + iterator pos = std::find_if(m_breakpoints.begin(), end, // Search full range + BreakpointAddressMatches(addr)); // Predicate + if (pos != end) + return &(*pos); + + return NULL; +} + +const DNBBreakpoint * +DNBBreakpointList::FindByAddress (nub_addr_t addr) const +{ + const_iterator end = m_breakpoints.end(); + const_iterator pos = std::find_if(m_breakpoints.begin(), end, // Search full range + BreakpointAddressMatches(addr)); // Predicate + if (pos != end) + return &(*pos); + + return NULL; +} + +bool +DNBBreakpointList::SetCallback(nub_break_t breakID, DNBCallbackBreakpointHit callback, void *callback_baton) +{ + DNBBreakpoint *bp = FindByID (breakID); + if (bp) + { + bp->SetCallback(callback, callback_baton); + return true; + } + return false; +} + + +void +DNBBreakpointList::Dump() const +{ + const_iterator pos; + const_iterator end = m_breakpoints.end(); + for (pos = m_breakpoints.begin(); pos != end; ++pos) + (*pos).Dump(); +} + + +DNBBreakpoint * +DNBBreakpointList::GetByIndex (uint32_t i) +{ + iterator end = m_breakpoints.end(); + iterator pos; + uint32_t curr_i = 0; + for (pos = m_breakpoints.begin(), curr_i = 0; pos != end; ++pos, ++curr_i) + { + if (curr_i == i) + return &(*pos); + } + return NULL; +} + +const DNBBreakpoint * +DNBBreakpointList::GetByIndex (uint32_t i) const +{ + const_iterator end = m_breakpoints.end(); + const_iterator pos; + uint32_t curr_i = 0; + for (pos = m_breakpoints.begin(), curr_i = 0; pos != end; ++pos, ++curr_i) + { + if (curr_i == i) + return &(*pos); + } + return NULL; +} + |