forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			222 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			222 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C++
		
	
	
	
//===-- NativeBreakpointList.cpp --------------------------------*- C++ -*-===//
 | 
						|
//
 | 
						|
//                     The LLVM Compiler Infrastructure
 | 
						|
//
 | 
						|
// This file is distributed under the University of Illinois Open Source
 | 
						|
// License. See LICENSE.TXT for details.
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#include "lldb/Host/common/NativeBreakpointList.h"
 | 
						|
 | 
						|
#include "lldb/Core/Log.h"
 | 
						|
 | 
						|
#include "lldb/Host/common/NativeBreakpoint.h"
 | 
						|
#include "lldb/Host/common/SoftwareBreakpoint.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 ();
 | 
						|
}
 | 
						|
 | 
						|
Error
 | 
						|
NativeBreakpointList::RemoveTrapsFromBuffer(lldb::addr_t addr, void *buf, size_t size) const
 | 
						|
{
 | 
						|
    for (const auto &map : m_breakpoints)
 | 
						|
    {
 | 
						|
        lldb::addr_t bp_addr = map.first;
 | 
						|
        // Breapoint not in range, ignore
 | 
						|
        if (bp_addr < addr || addr + size <= bp_addr)
 | 
						|
            continue;
 | 
						|
        const auto &bp_sp = map.second;
 | 
						|
        // Not software breakpoint, ignore
 | 
						|
        if (!bp_sp->IsSoftwareBreakpoint())
 | 
						|
            continue;
 | 
						|
        auto software_bp_sp = std::static_pointer_cast<SoftwareBreakpoint>(bp_sp);
 | 
						|
        auto opcode_addr = static_cast<char *>(buf) + bp_addr - addr;
 | 
						|
        auto saved_opcodes = software_bp_sp->m_saved_opcodes;
 | 
						|
        auto opcode_size = software_bp_sp->m_opcode_size;
 | 
						|
        ::memcpy(opcode_addr, saved_opcodes, opcode_size);
 | 
						|
    }
 | 
						|
    return Error();
 | 
						|
}
 |