mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-23 22:00:10 +00:00
[lldb/debugserver] Implement hardware breakpoints for x86_64 and i386
This implements hardware breakpoints for x86_64 and i386 in debugserver. It's based on Pedro's patch sent to lldb-commits [1] although most of it is the same as the existing hardware watchpoint implementation. [1] http://lists.llvm.org/pipermail/lldb-commits/Week-of-Mon-20200113/060327.html Differential revision: https://reviews.llvm.org/D72985
This commit is contained in:
parent
9902c8e3c6
commit
96f3ea0d21
@ -9,26 +9,47 @@ from lldbsuite.test.decorators import *
|
||||
from lldbsuite.test.lldbtest import *
|
||||
from lldbsuite.test import lldbutil
|
||||
|
||||
# Hardware breakpoints are supported only by platforms mentioned in oslist.
|
||||
@skipUnlessPlatform(oslist=['linux'])
|
||||
class HardwareBreakpointMultiThreadTestCase(TestBase):
|
||||
NO_DEBUG_INFO_TESTCASE = True
|
||||
|
||||
mydir = TestBase.compute_mydir(__file__)
|
||||
|
||||
# LLDB supports hardware breakpoints for arm and aarch64 architectures.
|
||||
# LLDB on linux supports hardware breakpoints for arm and aarch64
|
||||
# architectures.
|
||||
@skipUnlessPlatform(oslist=['linux'])
|
||||
@skipIf(archs=no_match(['arm', 'aarch64']))
|
||||
def test_hw_break_set_delete_multi_thread(self):
|
||||
def test_hw_break_set_delete_multi_thread_linux(self):
|
||||
self.build()
|
||||
self.setTearDownCleanup()
|
||||
self.break_multi_thread('delete')
|
||||
self.break_multi_thread('delete', 'breakpoint')
|
||||
|
||||
# LLDB supports hardware breakpoints for arm and aarch64 architectures.
|
||||
# LLDB on linux supports hardware breakpoints for arm and aarch64
|
||||
# architectures.
|
||||
@skipUnlessPlatform(oslist=['linux'])
|
||||
@skipIf(archs=no_match(['arm', 'aarch64']))
|
||||
def test_hw_break_set_disable_multi_thread(self):
|
||||
def test_hw_break_set_disable_multi_thread_linux(self):
|
||||
self.build()
|
||||
self.setTearDownCleanup()
|
||||
self.break_multi_thread('disable')
|
||||
self.break_multi_thread('disable', 'breakpoint')
|
||||
|
||||
# LLDB on darwin supports hardware breakpoints for arm, aarch64, x86_64 and
|
||||
# i386 architectures.
|
||||
@skipUnlessDarwin
|
||||
@skipIfOutOfTreeDebugserver
|
||||
def test_hw_break_set_delete_multi_thread_macos(self):
|
||||
self.build()
|
||||
self.setTearDownCleanup()
|
||||
self.break_multi_thread('delete', 'EXC_BREAKPOINT')
|
||||
|
||||
# LLDB on darwin supports hardware breakpoints for arm, aarch64, x86_64 and
|
||||
# i386 architectures.
|
||||
@skipUnlessDarwin
|
||||
@skipIfOutOfTreeDebugserver
|
||||
def test_hw_break_set_disable_multi_thread_macos(self):
|
||||
self.build()
|
||||
self.setTearDownCleanup()
|
||||
self.break_multi_thread('disable', 'EXC_BREAKPOINT')
|
||||
|
||||
|
||||
def setUp(self):
|
||||
# Call super's setUp().
|
||||
@ -39,7 +60,7 @@ class HardwareBreakpointMultiThreadTestCase(TestBase):
|
||||
self.first_stop = line_number(
|
||||
self.source, 'Starting thread creation with hardware breakpoint set')
|
||||
|
||||
def break_multi_thread(self, removal_type):
|
||||
def break_multi_thread(self, removal_type, stop_reason):
|
||||
"""Test that lldb hardware breakpoints work for multiple threads."""
|
||||
self.runCmd("file " + self.getBuildArtifact("a.out"),
|
||||
CURRENT_EXECUTABLE_SET)
|
||||
@ -54,8 +75,7 @@ class HardwareBreakpointMultiThreadTestCase(TestBase):
|
||||
# We should be stopped again due to the breakpoint.
|
||||
# The stop reason of the thread should be breakpoint.
|
||||
self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
|
||||
substrs=['stopped',
|
||||
'stop reason = breakpoint'])
|
||||
substrs=['stopped', 'stop reason = breakpoint'])
|
||||
|
||||
# Now set a hardware breakpoint in thread function.
|
||||
self.expect("breakpoint set -b hw_break_function --hardware",
|
||||
@ -75,7 +95,7 @@ class HardwareBreakpointMultiThreadTestCase(TestBase):
|
||||
# The stop reason of the thread should be breakpoint.
|
||||
self.expect("thread list", STOPPED_DUE_TO_BREAKPOINT,
|
||||
substrs=[
|
||||
'stop reason = breakpoint',
|
||||
'stop reason = {}'.format(stop_reason),
|
||||
'hw_break_function'])
|
||||
|
||||
# Continue the loop and test that we are stopped 4 times.
|
||||
|
@ -980,7 +980,8 @@ uint32_t DNBArchMachARM::NumSupportedHardwareWatchpoints() {
|
||||
}
|
||||
|
||||
uint32_t DNBArchMachARM::EnableHardwareBreakpoint(nub_addr_t addr,
|
||||
nub_size_t size) {
|
||||
nub_size_t size,
|
||||
bool also_set_on_task) {
|
||||
// Make sure our address isn't bogus
|
||||
if (addr & 1)
|
||||
return INVALID_NUB_HW_INDEX;
|
||||
@ -1052,7 +1053,8 @@ uint32_t DNBArchMachARM::EnableHardwareBreakpoint(nub_addr_t addr,
|
||||
return INVALID_NUB_HW_INDEX;
|
||||
}
|
||||
|
||||
bool DNBArchMachARM::DisableHardwareBreakpoint(uint32_t hw_index) {
|
||||
bool DNBArchMachARM::DisableHardwareBreakpoint(uint32_t hw_index,
|
||||
bool also_set_on_task) {
|
||||
kern_return_t kret = GetDBGState(false);
|
||||
|
||||
const uint32_t num_hw_points = NumSupportedHardwareBreakpoints();
|
||||
|
@ -70,8 +70,10 @@ public:
|
||||
|
||||
virtual uint32_t NumSupportedHardwareBreakpoints();
|
||||
virtual uint32_t NumSupportedHardwareWatchpoints();
|
||||
virtual uint32_t EnableHardwareBreakpoint(nub_addr_t addr, nub_size_t size);
|
||||
virtual bool DisableHardwareBreakpoint(uint32_t hw_break_index);
|
||||
virtual uint32_t EnableHardwareBreakpoint(nub_addr_t addr, nub_size_t size,
|
||||
bool also_set_on_task);
|
||||
virtual bool DisableHardwareBreakpoint(uint32_t hw_break_index,
|
||||
bool also_set_on_task);
|
||||
|
||||
virtual uint32_t EnableHardwareWatchpoint(nub_addr_t addr, nub_size_t size,
|
||||
bool read, bool write,
|
||||
|
@ -718,6 +718,11 @@ bool DNBArchImplI386::NotifyException(MachException::Data &exc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t DNBArchImplI386::NumSupportedHardwareBreakpoints() {
|
||||
// Available debug address registers: dr0, dr1, dr2, dr3.
|
||||
return 4;
|
||||
}
|
||||
|
||||
uint32_t DNBArchImplI386::NumSupportedHardwareWatchpoints() {
|
||||
// Available debug address registers: dr0, dr1, dr2, dr3.
|
||||
return 4;
|
||||
@ -797,6 +802,151 @@ void DNBArchImplI386::SetWatchpoint(DBG &debug_state, uint32_t hw_index,
|
||||
return;
|
||||
}
|
||||
|
||||
void DNBArchImplI386::SetHardwareBreakpoint(DBG &debug_state, uint32_t hw_index,
|
||||
nub_addr_t addr, nub_size_t size) {
|
||||
// Set both dr7 (debug control register) and dri (debug address register).
|
||||
|
||||
// dr7{7-0} encodes the local/gloabl enable bits:
|
||||
// global enable --. .-- local enable
|
||||
// | |
|
||||
// v v
|
||||
// dr0 -> bits{1-0}
|
||||
// dr1 -> bits{3-2}
|
||||
// dr2 -> bits{5-4}
|
||||
// dr3 -> bits{7-6}
|
||||
//
|
||||
// dr7{31-16} encodes the rw/len bits:
|
||||
// b_x+3, b_x+2, b_x+1, b_x
|
||||
// where bits{x+1, x} => rw
|
||||
// 0b00: execute, 0b01: write, 0b11: read-or-write, 0b10: io
|
||||
// read-or-write (unused)
|
||||
// and bits{x+3, x+2} => len
|
||||
// 0b00: 1-byte, 0b01: 2-byte, 0b11: 4-byte, 0b10: 8-byte
|
||||
//
|
||||
// dr0 -> bits{19-16}
|
||||
// dr1 -> bits{23-20}
|
||||
// dr2 -> bits{27-24}
|
||||
// dr3 -> bits{31-28}
|
||||
debug_state.__dr7 |= (1 << (2 * hw_index) | 0 << (16 + 4 * hw_index));
|
||||
uint32_t addr_32 = addr & 0xffffffff;
|
||||
switch (hw_index) {
|
||||
case 0:
|
||||
debug_state.__dr0 = addr_32;
|
||||
break;
|
||||
case 1:
|
||||
debug_state.__dr1 = addr_32;
|
||||
break;
|
||||
case 2:
|
||||
debug_state.__dr2 = addr_32;
|
||||
break;
|
||||
case 3:
|
||||
debug_state.__dr3 = addr_32;
|
||||
break;
|
||||
default:
|
||||
assert(0 &&
|
||||
"invalid hardware register index, must be one of 0, 1, 2, or 3");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t DNBArchImplI386::EnableHardwareBreakpoint(nub_addr_t addr,
|
||||
nub_size_t size,
|
||||
bool also_set_on_task) {
|
||||
DNBLogThreadedIf(LOG_BREAKPOINTS,
|
||||
"DNBArchImplI386::EnableHardwareBreakpoint( addr = "
|
||||
"0x%8.8llx, size = %llu )",
|
||||
(uint64_t)addr, (uint64_t)size);
|
||||
|
||||
const uint32_t num_hw_breakpoints = NumSupportedHardwareBreakpoints();
|
||||
// Read the debug state
|
||||
kern_return_t kret = GetDBGState(false);
|
||||
|
||||
if (kret != KERN_SUCCESS) {
|
||||
return INVALID_NUB_HW_INDEX;
|
||||
}
|
||||
|
||||
// Check to make sure we have the needed hardware support
|
||||
uint32_t i = 0;
|
||||
|
||||
DBG &debug_state = m_state.context.dbg;
|
||||
for (i = 0; i < num_hw_breakpoints; ++i) {
|
||||
if (IsWatchpointVacant(debug_state, i)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// See if we found an available hw breakpoint slot above
|
||||
if (i < num_hw_breakpoints) {
|
||||
DNBLogThreadedIf(
|
||||
LOG_BREAKPOINTS,
|
||||
"DNBArchImplI386::EnableHardwareBreakpoint( free slot = %u )", i);
|
||||
|
||||
StartTransForHWP();
|
||||
|
||||
// Modify our local copy of the debug state, first.
|
||||
SetHardwareBreakpoint(debug_state, i, addr, size);
|
||||
// Now set the watch point in the inferior.
|
||||
kret = SetDBGState(also_set_on_task);
|
||||
|
||||
DNBLogThreadedIf(LOG_BREAKPOINTS,
|
||||
"DNBArchImplI386::"
|
||||
"EnableHardwareBreakpoint() "
|
||||
"SetDBGState() => 0x%8.8x.",
|
||||
kret);
|
||||
|
||||
if (kret == KERN_SUCCESS) {
|
||||
DNBLogThreadedIf(
|
||||
LOG_BREAKPOINTS,
|
||||
"DNBArchImplI386::EnableHardwareBreakpoint( enabled at slot = %u)",
|
||||
i);
|
||||
return i;
|
||||
}
|
||||
// Revert to the previous debug state voluntarily. The transaction
|
||||
// coordinator knows that we have failed.
|
||||
else {
|
||||
m_state.context.dbg = GetDBGCheckpoint();
|
||||
}
|
||||
} else {
|
||||
DNBLogThreadedIf(LOG_BREAKPOINTS,
|
||||
"DNBArchImplI386::EnableHardwareBreakpoint(addr = "
|
||||
"0x%8.8llx, size = %llu) => all hardware breakpoint "
|
||||
"resources are being used.",
|
||||
(uint64_t)addr, (uint64_t)size);
|
||||
}
|
||||
|
||||
return INVALID_NUB_HW_INDEX;
|
||||
}
|
||||
|
||||
bool DNBArchImplI386::DisableHardwareBreakpoint(uint32_t hw_index,
|
||||
bool also_set_on_task) {
|
||||
kern_return_t kret = GetDBGState(false);
|
||||
|
||||
const uint32_t num_hw_points = NumSupportedHardwareBreakpoints();
|
||||
if (kret == KERN_SUCCESS) {
|
||||
DBG &debug_state = m_state.context.dbg;
|
||||
if (hw_index < num_hw_points &&
|
||||
!IsWatchpointVacant(debug_state, hw_index)) {
|
||||
|
||||
StartTransForHWP();
|
||||
|
||||
// Modify our local copy of the debug state, first.
|
||||
ClearWatchpoint(debug_state, hw_index);
|
||||
// Now disable the watch point in the inferior.
|
||||
kret = SetDBGState(true);
|
||||
DNBLogThreadedIf(LOG_WATCHPOINTS,
|
||||
"DNBArchImplI386::DisableHardwareBreakpoint( %u )",
|
||||
hw_index);
|
||||
|
||||
if (kret == KERN_SUCCESS)
|
||||
return true;
|
||||
else // Revert to the previous debug state voluntarily. The transaction
|
||||
// coordinator knows that we have failed.
|
||||
m_state.context.dbg = GetDBGCheckpoint();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DNBArchImplI386::ClearWatchpoint(DBG &debug_state, uint32_t hw_index) {
|
||||
debug_state.__dr7 &= ~(3 << (2 * hw_index));
|
||||
switch (hw_index) {
|
||||
|
@ -51,7 +51,12 @@ public:
|
||||
virtual bool ThreadDidStop();
|
||||
virtual bool NotifyException(MachException::Data &exc);
|
||||
|
||||
virtual uint32_t NumSupportedHardwareBreakpoints();
|
||||
virtual uint32_t NumSupportedHardwareWatchpoints();
|
||||
virtual uint32_t EnableHardwareBreakpoint(nub_addr_t addr, nub_size_t size,
|
||||
bool also_set_on_task);
|
||||
virtual bool DisableHardwareBreakpoint(uint32_t hw_index,
|
||||
bool also_set_on_task);
|
||||
virtual uint32_t EnableHardwareWatchpoint(nub_addr_t addr, nub_size_t size,
|
||||
bool read, bool write,
|
||||
bool also_set_on_task);
|
||||
@ -210,6 +215,9 @@ protected:
|
||||
|
||||
static uint32_t GetRegisterContextSize();
|
||||
|
||||
static void SetHardwareBreakpoint(DBG &debug_state, uint32_t hw_index,
|
||||
nub_addr_t addr, nub_size_t size);
|
||||
|
||||
// Helper functions for watchpoint manipulations.
|
||||
static void SetWatchpoint(DBG &debug_state, uint32_t hw_index,
|
||||
nub_addr_t addr, nub_size_t size, bool read,
|
||||
|
@ -679,6 +679,12 @@ uint32_t DNBArchImplX86_64::NumSupportedHardwareWatchpoints() {
|
||||
return 4;
|
||||
}
|
||||
|
||||
uint32_t DNBArchImplX86_64::NumSupportedHardwareBreakpoints() {
|
||||
DNBLogThreadedIf(LOG_BREAKPOINTS,
|
||||
"DNBArchImplX86_64::NumSupportedHardwareBreakpoints");
|
||||
return 4;
|
||||
}
|
||||
|
||||
static uint32_t size_and_rw_bits(nub_size_t size, bool read, bool write) {
|
||||
uint32_t rw;
|
||||
if (read) {
|
||||
@ -853,6 +859,153 @@ DNBArchImplX86_64::DBG DNBArchImplX86_64::GetDBGCheckpoint() {
|
||||
return m_2pc_dbg_checkpoint;
|
||||
}
|
||||
|
||||
void DNBArchImplX86_64::SetHardwareBreakpoint(DBG &debug_state,
|
||||
uint32_t hw_index,
|
||||
nub_addr_t addr,
|
||||
nub_size_t size) {
|
||||
// Set both dr7 (debug control register) and dri (debug address register).
|
||||
|
||||
// dr7{7-0} encodes the local/gloabl enable bits:
|
||||
// global enable --. .-- local enable
|
||||
// | |
|
||||
// v v
|
||||
// dr0 -> bits{1-0}
|
||||
// dr1 -> bits{3-2}
|
||||
// dr2 -> bits{5-4}
|
||||
// dr3 -> bits{7-6}
|
||||
//
|
||||
// dr7{31-16} encodes the rw/len bits:
|
||||
// b_x+3, b_x+2, b_x+1, b_x
|
||||
// where bits{x+1, x} => rw
|
||||
// 0b00: execute, 0b01: write, 0b11: read-or-write, 0b10: io
|
||||
// read-or-write (unused)
|
||||
// and bits{x+3, x+2} => len
|
||||
// 0b00: 1-byte, 0b01: 2-byte, 0b11: 4-byte, 0b10: 8-byte
|
||||
//
|
||||
// dr0 -> bits{19-16}
|
||||
// dr1 -> bits{23-20}
|
||||
// dr2 -> bits{27-24}
|
||||
// dr3 -> bits{31-28}
|
||||
debug_state.__dr7 |= (1 << (2 * hw_index) | 0 << (16 + 4 * hw_index));
|
||||
|
||||
switch (hw_index) {
|
||||
case 0:
|
||||
debug_state.__dr0 = addr;
|
||||
break;
|
||||
case 1:
|
||||
debug_state.__dr1 = addr;
|
||||
break;
|
||||
case 2:
|
||||
debug_state.__dr2 = addr;
|
||||
break;
|
||||
case 3:
|
||||
debug_state.__dr3 = addr;
|
||||
break;
|
||||
default:
|
||||
assert(0 &&
|
||||
"invalid hardware register index, must be one of 0, 1, 2, or 3");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t DNBArchImplX86_64::EnableHardwareBreakpoint(nub_addr_t addr,
|
||||
nub_size_t size,
|
||||
bool also_set_on_task) {
|
||||
DNBLogThreadedIf(LOG_BREAKPOINTS,
|
||||
"DNBArchImplX86_64::EnableHardwareBreakpoint( addr = "
|
||||
"0x%8.8llx, size = %llu )",
|
||||
(uint64_t)addr, (uint64_t)size);
|
||||
|
||||
const uint32_t num_hw_breakpoints = NumSupportedHardwareBreakpoints();
|
||||
// Read the debug state
|
||||
kern_return_t kret = GetDBGState(false);
|
||||
|
||||
if (kret != KERN_SUCCESS) {
|
||||
return INVALID_NUB_HW_INDEX;
|
||||
}
|
||||
|
||||
// Check to make sure we have the needed hardware support
|
||||
uint32_t i = 0;
|
||||
|
||||
DBG &debug_state = m_state.context.dbg;
|
||||
for (i = 0; i < num_hw_breakpoints; ++i) {
|
||||
if (IsWatchpointVacant(debug_state, i)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// See if we found an available hw breakpoint slot above
|
||||
if (i < num_hw_breakpoints) {
|
||||
DNBLogThreadedIf(
|
||||
LOG_BREAKPOINTS,
|
||||
"DNBArchImplX86_64::EnableHardwareBreakpoint( free slot = %u )", i);
|
||||
|
||||
StartTransForHWP();
|
||||
|
||||
// Modify our local copy of the debug state, first.
|
||||
SetHardwareBreakpoint(debug_state, i, addr, size);
|
||||
// Now set the watch point in the inferior.
|
||||
kret = SetDBGState(also_set_on_task);
|
||||
|
||||
DNBLogThreadedIf(LOG_BREAKPOINTS,
|
||||
"DNBArchImplX86_64::"
|
||||
"EnableHardwareBreakpoint() "
|
||||
"SetDBGState() => 0x%8.8x.",
|
||||
kret);
|
||||
|
||||
if (kret == KERN_SUCCESS) {
|
||||
DNBLogThreadedIf(
|
||||
LOG_BREAKPOINTS,
|
||||
"DNBArchImplX86_64::EnableHardwareBreakpoint( enabled at slot = %u)",
|
||||
i);
|
||||
return i;
|
||||
}
|
||||
// Revert to the previous debug state voluntarily. The transaction
|
||||
// coordinator knows that we have failed.
|
||||
else {
|
||||
m_state.context.dbg = GetDBGCheckpoint();
|
||||
}
|
||||
} else {
|
||||
DNBLogThreadedIf(LOG_BREAKPOINTS,
|
||||
"DNBArchImplX86_64::EnableHardwareBreakpoint(addr = "
|
||||
"0x%8.8llx, size = %llu) => all hardware breakpoint "
|
||||
"resources are being used.",
|
||||
(uint64_t)addr, (uint64_t)size);
|
||||
}
|
||||
|
||||
return INVALID_NUB_HW_INDEX;
|
||||
}
|
||||
|
||||
bool DNBArchImplX86_64::DisableHardwareBreakpoint(uint32_t hw_index,
|
||||
bool also_set_on_task) {
|
||||
kern_return_t kret = GetDBGState(false);
|
||||
|
||||
const uint32_t num_hw_points = NumSupportedHardwareBreakpoints();
|
||||
if (kret == KERN_SUCCESS) {
|
||||
DBG &debug_state = m_state.context.dbg;
|
||||
if (hw_index < num_hw_points &&
|
||||
!IsWatchpointVacant(debug_state, hw_index)) {
|
||||
|
||||
StartTransForHWP();
|
||||
|
||||
// Modify our local copy of the debug state, first.
|
||||
ClearWatchpoint(debug_state, hw_index);
|
||||
// Now disable the watch point in the inferior.
|
||||
kret = SetDBGState(true);
|
||||
DNBLogThreadedIf(LOG_WATCHPOINTS,
|
||||
"DNBArchImplX86_64::DisableHardwareBreakpoint( %u )",
|
||||
hw_index);
|
||||
|
||||
if (kret == KERN_SUCCESS)
|
||||
return true;
|
||||
else // Revert to the previous debug state voluntarily. The transaction
|
||||
// coordinator knows that we have failed.
|
||||
m_state.context.dbg = GetDBGCheckpoint();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t DNBArchImplX86_64::EnableHardwareWatchpoint(nub_addr_t addr,
|
||||
nub_size_t size, bool read,
|
||||
bool write,
|
||||
|
@ -50,7 +50,13 @@ public:
|
||||
virtual bool ThreadDidStop();
|
||||
virtual bool NotifyException(MachException::Data &exc);
|
||||
|
||||
virtual uint32_t NumSupportedHardwareBreakpoints();
|
||||
virtual uint32_t NumSupportedHardwareWatchpoints();
|
||||
|
||||
virtual uint32_t EnableHardwareBreakpoint(nub_addr_t addr, nub_size_t size,
|
||||
bool also_set_on_task);
|
||||
virtual bool DisableHardwareBreakpoint(uint32_t hw_break_index,
|
||||
bool also_set_on_task);
|
||||
virtual uint32_t EnableHardwareWatchpoint(nub_addr_t addr, nub_size_t size,
|
||||
bool read, bool write,
|
||||
bool also_set_on_task);
|
||||
@ -213,6 +219,9 @@ protected:
|
||||
|
||||
static uint32_t GetRegisterContextSize();
|
||||
|
||||
static void SetHardwareBreakpoint(DBG &debug_state, uint32_t hw_index,
|
||||
nub_addr_t addr, nub_size_t size);
|
||||
|
||||
// Helper functions for watchpoint manipulations.
|
||||
static void SetWatchpoint(DBG &debug_state, uint32_t hw_index,
|
||||
nub_addr_t addr, nub_size_t size, bool read,
|
||||
|
@ -279,12 +279,10 @@ void RNBRemote::CreatePacketTable() {
|
||||
"x", "Read data from memory"));
|
||||
t.push_back(Packet(write_data_to_memory, &RNBRemote::HandlePacket_X, NULL,
|
||||
"X", "Write data to memory"));
|
||||
// t.push_back (Packet (insert_hardware_bp,
|
||||
// &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "Z1", "Insert hardware
|
||||
// breakpoint"));
|
||||
// t.push_back (Packet (remove_hardware_bp,
|
||||
// &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "z1", "Remove hardware
|
||||
// breakpoint"));
|
||||
t.push_back(Packet(insert_hardware_bp, &RNBRemote::HandlePacket_z, NULL, "Z1",
|
||||
"Insert hardware breakpoint"));
|
||||
t.push_back(Packet(remove_hardware_bp, &RNBRemote::HandlePacket_z, NULL, "z1",
|
||||
"Remove hardware breakpoint"));
|
||||
t.push_back(Packet(insert_write_watch_bp, &RNBRemote::HandlePacket_z, NULL,
|
||||
"Z2", "Insert write watchpoint"));
|
||||
t.push_back(Packet(remove_write_watch_bp, &RNBRemote::HandlePacket_z, NULL,
|
||||
|
Loading…
Reference in New Issue
Block a user