summaryrefslogtreecommitdiffstats
path: root/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp
diff options
context:
space:
mode:
authorJohnny Chen <johnny.chen@apple.com>2012-01-11 00:35:13 +0000
committerJohnny Chen <johnny.chen@apple.com>2012-01-11 00:35:13 +0000
commit17b4ea54bf04aa1a448c477c32552f3394b1e2ed (patch)
tree2a9127819edaf03d9a0ba85669965075d84d869a /lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp
parent9b80c2186f5ecdd25436adc513e4d18e81f18049 (diff)
downloadbcm5719-llvm-17b4ea54bf04aa1a448c477c32552f3394b1e2ed.tar.gz
bcm5719-llvm-17b4ea54bf04aa1a448c477c32552f3394b1e2ed.zip
Snapshot of initial work for ARM watchpoint support on the debugserver.
It is incomplete and untested; passes the compilation only. llvm-svn: 147901
Diffstat (limited to 'lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp')
-rw-r--r--lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp115
1 files changed, 115 insertions, 0 deletions
diff --git a/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp b/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp
index ba1133ca10a..4c931424c15 100644
--- a/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp
+++ b/lldb/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp
@@ -448,6 +448,36 @@ DNBArchMachARM::ThreadDidStop()
}
bool
+DNBArchMachARM::NotifyException(MachException::Data& exc)
+{
+ switch (exc.exc_type)
+ {
+ default:
+ break;
+ case EXC_BREAKPOINT:
+ if (exc.exc_data.size() >= 2 && exc.exc_data[0] == 1)
+ {
+ // exc_code = EXC_ARM_WATCHPOINT
+ //
+ // Check whether this corresponds to a watchpoint hit event.
+ // If yes, set the exc_sub_code to the data break address.
+ nub_addr_t addr = 0;
+ uint32_t hw_index = GetHardwareWatchpointHit(addr);
+ if (hw_index != INVALID_NUB_HW_INDEX)
+ {
+ exc.exc_data[1] = addr;
+ // Piggyback the hw_index in the exc.data.
+ exc.exc_data.push_back(hw_index);
+ }
+
+ return true;
+ }
+ break;
+ }
+ return false;
+}
+
+bool
DNBArchMachARM::StepNotComplete ()
{
if (m_hw_single_chained_step_addr != INVALID_NUB_ADDRESS)
@@ -2375,6 +2405,91 @@ DNBArchMachARM::DisableHardwareWatchpoint (uint32_t hw_index)
return false;
}
+// {0} -> __bvr[16], {0} -> __bcr[16], {0} --> __wvr[16], {0} -> __wcr{16}
+DNBArchMachARM::DBG DNBArchMachARM::Global_Debug_State = {{0},{0},{0},{0}};
+bool DNBArchMachARM::Valid_Global_Debug_State = false;
+
+// Use this callback from MachThread, which in turn was called from MachThreadList, to update
+// the global view of the hardware watchpoint state, so that when new thread comes along, they
+// get to inherit the existing hardware watchpoint state.
+void
+DNBArchMachARM::HardwareWatchpointStateChanged ()
+{
+ Global_Debug_State = m_state.dbg;
+ Valid_Global_Debug_State = true;
+}
+
+// Iterate through the debug status register; return the index of the first hit.
+uint32_t
+DNBArchMachARM::GetHardwareWatchpointHit(nub_addr_t &addr)
+{
+ // Read the debug state
+ kern_return_t kret = GetDBGState(true);
+ DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchMachARM::GetHardwareWatchpointHit() GetDBGState() => 0x%8.8x.", kret);
+ if (kret == KERN_SUCCESS)
+ {
+ DBG &debug_state = m_state.dbg;
+ uint32_t i, num = NumSupportedHardwareWatchpoints();
+ for (i = 0; i < num; ++i)
+ {
+ // FIXME: IsWatchpointHit() currently returns the first enabled watchpoint,
+ // instead of finding the watchpoint that actually triggered.
+ if (IsWatchpointHit(debug_state, i))
+ {
+ addr = GetWatchAddress(debug_state, i);
+ DNBLogThreadedIf(LOG_WATCHPOINTS,
+ "DNBArchMachARM::GetHardwareWatchpointHit() found => %u (addr = 0x%llx).",
+ i,
+ (uint64_t)addr);
+ return i;
+ }
+ }
+ }
+ return INVALID_NUB_HW_INDEX;
+}
+
+// ThreadWillResume() calls this to clear bits[5:2] (Method of entry bits) of
+// the Debug Status and Control Register (DSCR).
+//
+// b0010 = a watchpoint occurred
+// b0000 is the reset value
+void
+DNBArchMachARM::ClearWatchpointOccurred()
+{
+ // See also IsWatchpointHit().
+ uint32_t register_DBGDSCR;
+ asm("mrc p14, 0, %0, c0, c1, 0" : "=r" (register_DBGDSCR));
+ if (bits(register_DBGDSCR, 5, 2) == 0x2)
+ {
+ uint32_t mask = ~(0xF << 2);
+ register_DBGDSCR &= mask;
+ asm("mcr p14, 0, %0, c0, c1, 0" : "=r" (register_DBGDSCR));
+ }
+ return;
+}
+
+// FIXME: IsWatchpointHit() currently returns the first enabled watchpoint,
+// instead of finding the watchpoint that actually triggered.
+bool
+DNBArchMachARM::IsWatchpointHit(const DBG &debug_state, uint32_t hw_index)
+{
+ // Watchpoint Control Registers, bitfield definitions
+ // ...
+ // Bits Value Description
+ // [0] 0 Watchpoint disabled
+ // 1 Watchpoint enabled.
+ return (debug_state.__wcr[hw_index] & 1u);
+}
+
+nub_addr_t
+DNBArchMachARM::GetWatchAddress(const DBG &debug_state, uint32_t hw_index)
+{
+ // Watchpoint Value Registers, bitfield definitions
+ // Bits Description
+ // [31:2] Watchpoint address
+ return bits(debug_state.__wvr[hw_index], 31, 2);
+}
+
//----------------------------------------------------------------------
// Register information defintions for 32 bit ARMV6.
//----------------------------------------------------------------------
OpenPOWER on IntegriCloud