Initial import of lldb
Change-Id: Ib244e837bee349effa12b2ff6ffffbe3d730e929
This commit is contained in:
225
external/bsd/llvm/dist/lldb/tools/debugserver/source/DNBBreakpoint.cpp
vendored
Normal file
225
external/bsd/llvm/dist/lldb/tools/debugserver/source/DNBBreakpoint.cpp
vendored
Normal file
@@ -0,0 +1,225 @@
|
||||
//===-- 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 "MachProcess.h"
|
||||
#include <assert.h>
|
||||
#include <algorithm>
|
||||
#include <inttypes.h>
|
||||
#include "DNBLog.h"
|
||||
|
||||
|
||||
#pragma mark -- DNBBreakpoint
|
||||
DNBBreakpoint::DNBBreakpoint(nub_addr_t addr, nub_size_t byte_size, bool hardware) :
|
||||
m_retain_count (1),
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
DNBBreakpoint::~DNBBreakpoint()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
DNBBreakpoint::Dump() const
|
||||
{
|
||||
if (IsBreakpoint())
|
||||
{
|
||||
DNBLog ("DNBBreakpoint addr = 0x%llx state = %s type = %s breakpoint hw_index = %i",
|
||||
(uint64_t)m_addr,
|
||||
m_enabled ? "enabled " : "disabled",
|
||||
IsHardware() ? "hardware" : "software",
|
||||
GetHardwareIndex());
|
||||
}
|
||||
else
|
||||
{
|
||||
DNBLog ("DNBBreakpoint addr = 0x%llx size = %llu state = %s type = %s watchpoint (%s%s) hw_index = %i",
|
||||
(uint64_t)m_addr,
|
||||
(uint64_t)m_byte_size,
|
||||
m_enabled ? "enabled " : "disabled",
|
||||
IsHardware() ? "hardware" : "software",
|
||||
m_watch_read ? "r" : "",
|
||||
m_watch_write ? "w" : "",
|
||||
GetHardwareIndex());
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -- DNBBreakpointList
|
||||
|
||||
DNBBreakpointList::DNBBreakpointList()
|
||||
{
|
||||
}
|
||||
|
||||
DNBBreakpointList::~DNBBreakpointList()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
DNBBreakpoint *
|
||||
DNBBreakpointList::Add(nub_addr_t addr, nub_size_t length, bool hardware)
|
||||
{
|
||||
m_breakpoints.insert(std::make_pair(addr, DNBBreakpoint(addr, length, hardware)));
|
||||
iterator pos = m_breakpoints.find (addr);
|
||||
return &pos->second;
|
||||
}
|
||||
|
||||
bool
|
||||
DNBBreakpointList::Remove (nub_addr_t addr)
|
||||
{
|
||||
iterator pos = m_breakpoints.find(addr);
|
||||
if (pos != m_breakpoints.end())
|
||||
{
|
||||
m_breakpoints.erase(pos);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
DNBBreakpoint *
|
||||
DNBBreakpointList::FindByAddress (nub_addr_t addr)
|
||||
{
|
||||
iterator pos = m_breakpoints.find(addr);
|
||||
if (pos != m_breakpoints.end())
|
||||
return &pos->second;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const DNBBreakpoint *
|
||||
DNBBreakpointList::FindByAddress (nub_addr_t addr) const
|
||||
{
|
||||
const_iterator pos = m_breakpoints.find(addr);
|
||||
if (pos != m_breakpoints.end())
|
||||
return &pos->second;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Finds the next breakpoint at an address greater than or equal to "addr"
|
||||
size_t
|
||||
DNBBreakpointList::FindBreakpointsThatOverlapRange (nub_addr_t addr,
|
||||
nub_addr_t size,
|
||||
std::vector<DNBBreakpoint *> &bps)
|
||||
{
|
||||
bps.clear();
|
||||
iterator end = m_breakpoints.end();
|
||||
// Find the first breakpoint with an address >= to "addr"
|
||||
iterator pos = m_breakpoints.lower_bound(addr);
|
||||
if (pos != end)
|
||||
{
|
||||
if (pos != m_breakpoints.begin())
|
||||
{
|
||||
// Watch out for a breakpoint at an address less than "addr" that might still overlap
|
||||
iterator prev_pos = pos;
|
||||
--prev_pos;
|
||||
if (prev_pos->second.IntersectsRange (addr, size, NULL, NULL, NULL))
|
||||
bps.push_back (&pos->second);
|
||||
|
||||
}
|
||||
|
||||
while (pos != end)
|
||||
{
|
||||
// When we hit a breakpoint whose start address is greater than "addr + size" we are done.
|
||||
// Do the math in a way that doesn't risk unsigned overflow with bad input.
|
||||
if ((pos->second.Address() - addr) >= size)
|
||||
break;
|
||||
|
||||
// Check if this breakpoint overlaps, and if it does, add it to the list
|
||||
if (pos->second.IntersectsRange (addr, size, NULL, NULL, NULL))
|
||||
{
|
||||
bps.push_back (&pos->second);
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
return bps.size();
|
||||
}
|
||||
|
||||
void
|
||||
DNBBreakpointList::Dump() const
|
||||
{
|
||||
const_iterator pos;
|
||||
const_iterator end = m_breakpoints.end();
|
||||
for (pos = m_breakpoints.begin(); pos != end; ++pos)
|
||||
pos->second.Dump();
|
||||
}
|
||||
|
||||
void
|
||||
DNBBreakpointList::DisableAll ()
|
||||
{
|
||||
iterator pos, end = m_breakpoints.end();
|
||||
for (pos = m_breakpoints.begin(); pos != end; ++pos)
|
||||
pos->second.SetEnabled(false);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DNBBreakpointList::RemoveTrapsFromBuffer (nub_addr_t addr, nub_size_t size, void *p) const
|
||||
{
|
||||
uint8_t *buf = (uint8_t *)p;
|
||||
const_iterator end = m_breakpoints.end();
|
||||
const_iterator pos = m_breakpoints.lower_bound(addr);
|
||||
while (pos != end && (pos->first < (addr + size)))
|
||||
{
|
||||
nub_addr_t intersect_addr;
|
||||
nub_size_t intersect_size;
|
||||
nub_size_t opcode_offset;
|
||||
const DNBBreakpoint &bp = pos->second;
|
||||
if (bp.IntersectsRange(addr, size, &intersect_addr, &intersect_size, &opcode_offset))
|
||||
{
|
||||
assert(addr <= intersect_addr && intersect_addr < addr + size);
|
||||
assert(addr < intersect_addr + intersect_size && intersect_addr + intersect_size <= addr + size);
|
||||
assert(opcode_offset + intersect_size <= bp.ByteSize());
|
||||
nub_size_t buf_offset = intersect_addr - addr;
|
||||
::memcpy(buf + buf_offset, bp.SavedOpcodeBytes() + opcode_offset, intersect_size);
|
||||
}
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DNBBreakpointList::DisableAllBreakpoints(MachProcess *process)
|
||||
{
|
||||
iterator pos, end = m_breakpoints.end();
|
||||
for (pos = m_breakpoints.begin(); pos != end; ++pos)
|
||||
process->DisableBreakpoint(pos->second.Address(), false);
|
||||
}
|
||||
|
||||
void
|
||||
DNBBreakpointList::DisableAllWatchpoints(MachProcess *process)
|
||||
{
|
||||
iterator pos, end = m_breakpoints.end();
|
||||
for (pos = m_breakpoints.begin(); pos != end; ++pos)
|
||||
process->DisableWatchpoint(pos->second.Address(), false);
|
||||
}
|
||||
|
||||
void
|
||||
DNBBreakpointList::RemoveDisabled()
|
||||
{
|
||||
iterator pos = m_breakpoints.begin();
|
||||
while (pos != m_breakpoints.end())
|
||||
{
|
||||
if (!pos->second.IsEnabled())
|
||||
pos = m_breakpoints.erase(pos);
|
||||
else
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user