diff options
Diffstat (limited to 'source/Host/common/NativeBreakpointList.cpp')
-rw-r--r-- | source/Host/common/NativeBreakpointList.cpp | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/source/Host/common/NativeBreakpointList.cpp b/source/Host/common/NativeBreakpointList.cpp new file mode 100644 index 000000000000..ecd0624bde09 --- /dev/null +++ b/source/Host/common/NativeBreakpointList.cpp @@ -0,0 +1,199 @@ +//===-- NativeBreakpointList.h ----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "NativeBreakpointList.h" + +#include "lldb/Core/Log.h" + +#include "NativeBreakpoint.h" + +using namespace lldb; +using namespace lldb_private; + +NativeBreakpointList::NativeBreakpointList () : + m_mutex (Mutex::eMutexTypeRecursive) +{ +} + +Error +NativeBreakpointList::AddRef (lldb::addr_t addr, size_t size_hint, bool hardware, CreateBreakpointFunc create_func) +{ + Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 ", size_hint = %lu, hardware = %s", __FUNCTION__, addr, size_hint, hardware ? "true" : "false"); + + Mutex::Locker locker (m_mutex); + + // Check if the breakpoint is already set. + auto iter = m_breakpoints.find (addr); + if (iter != m_breakpoints.end ()) + { + // Yes - bump up ref count. + if (log) + log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- already enabled, upping ref count", __FUNCTION__, addr); + + iter->second->AddRef (); + return Error (); + } + + // Create a new breakpoint using the given create func. + if (log) + log->Printf ("NativeBreakpointList::%s creating breakpoint for addr = 0x%" PRIx64 ", size_hint = %lu, hardware = %s", __FUNCTION__, addr, size_hint, hardware ? "true" : "false"); + + NativeBreakpointSP breakpoint_sp; + Error error = create_func (addr, size_hint, hardware, breakpoint_sp); + if (error.Fail ()) + { + if (log) + log->Printf ("NativeBreakpointList::%s creating breakpoint for addr = 0x%" PRIx64 ", size_hint = %lu, hardware = %s -- FAILED: %s", __FUNCTION__, addr, size_hint, hardware ? "true" : "false", error.AsCString ()); + return error; + } + + // Remember the breakpoint. + assert (breakpoint_sp && "NativeBreakpoint create function succeeded but returned NULL breakpoint"); + m_breakpoints.insert (BreakpointMap::value_type (addr, breakpoint_sp)); + + return error; +} + +Error +NativeBreakpointList::DecRef (lldb::addr_t addr) +{ + Error error; + + Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__, addr); + + Mutex::Locker locker (m_mutex); + + // Check if the breakpoint is already set. + auto iter = m_breakpoints.find (addr); + if (iter == m_breakpoints.end ()) + { + // Not found! + if (log) + log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- NOT FOUND", __FUNCTION__, addr); + error.SetErrorString ("breakpoint not found"); + return error; + } + + // Decrement ref count. + const int32_t new_ref_count = iter->second->DecRef (); + assert (new_ref_count >= 0 && "NativeBreakpoint ref count went negative"); + + if (new_ref_count > 0) + { + // Still references to this breakpoint. Leave it alone. + if (log) + log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- new breakpoint ref count %" PRIu32, __FUNCTION__, addr, new_ref_count); + return error; + } + + // Breakpoint has no more references. Disable it if it's not + // already disabled. + if (log) + log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- removing due to no remaining references", __FUNCTION__, addr); + + // If it's enabled, we need to disable it. + if (iter->second->IsEnabled ()) + { + if (log) + log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- currently enabled, now disabling", __FUNCTION__, addr); + error = iter->second->Disable (); + if (error.Fail ()) + { + if (log) + log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- removal FAILED: %s", __FUNCTION__, addr, error.AsCString ()); + // Continue since we still want to take it out of the breakpoint list. + } + } + else + { + if (log) + log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- already disabled, nothing to do", __FUNCTION__, addr); + } + + // Take the breakpoint out of the list. + if (log) + log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- removed from breakpoint map", __FUNCTION__, addr); + + m_breakpoints.erase (iter); + return error; +} + +Error +NativeBreakpointList::EnableBreakpoint (lldb::addr_t addr) +{ + Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__, addr); + + Mutex::Locker locker (m_mutex); + + // Ensure we have said breakpoint. + auto iter = m_breakpoints.find (addr); + if (iter == m_breakpoints.end ()) + { + // Not found! + if (log) + log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- NOT FOUND", __FUNCTION__, addr); + return Error ("breakpoint not found"); + } + + // Enable it. + return iter->second->Enable (); +} + +Error +NativeBreakpointList::DisableBreakpoint (lldb::addr_t addr) +{ + Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__, addr); + + Mutex::Locker locker (m_mutex); + + // Ensure we have said breakpoint. + auto iter = m_breakpoints.find (addr); + if (iter == m_breakpoints.end ()) + { + // Not found! + if (log) + log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- NOT FOUND", __FUNCTION__, addr); + return Error ("breakpoint not found"); + } + + // Disable it. + return iter->second->Disable (); +} + +Error +NativeBreakpointList::GetBreakpoint (lldb::addr_t addr, NativeBreakpointSP &breakpoint_sp) +{ + Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__, addr); + + Mutex::Locker locker (m_mutex); + + // Ensure we have said breakpoint. + auto iter = m_breakpoints.find (addr); + if (iter == m_breakpoints.end ()) + { + // Not found! + breakpoint_sp.reset (); + return Error ("breakpoint not found"); + } + + // Disable it. + breakpoint_sp = iter->second; + return Error (); +} + |