aboutsummaryrefslogblamecommitdiff
path: root/source/Host/common/NativeBreakpointList.cpp
blob: ecd0624bde09be4befb4e7664ae841bf696646d5 (plain) (tree)






































































































































































































                                                                                                                                                                                                                                
//===-- 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 ();
}