[Lldb-commits] [lldb] r147901 - in /lldb/trunk/tools/debugserver/source/MacOSX/arm: DNBArchImpl.cpp DNBArchImpl.h
Johnny Chen
johnny.chen at apple.com
Tue Jan 10 16:35:13 PST 2012
Author: johnny
Date: Tue Jan 10 18:35:13 2012
New Revision: 147901
URL: http://llvm.org/viewvc/llvm-project?rev=147901&view=rev
Log:
Snapshot of initial work for ARM watchpoint support on the debugserver.
It is incomplete and untested; passes the compilation only.
Modified:
lldb/trunk/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp
lldb/trunk/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h
Modified: lldb/trunk/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp?rev=147901&r1=147900&r2=147901&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/arm/DNBArchImpl.cpp Tue Jan 10 18:35:13 2012
@@ -448,6 +448,36 @@
}
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 @@
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.
//----------------------------------------------------------------------
Modified: lldb/trunk/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h?rev=147901&r1=147900&r2=147901&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h (original)
+++ lldb/trunk/tools/debugserver/source/MacOSX/arm/DNBArchImpl.h Tue Jan 10 18:35:13 2012
@@ -67,6 +67,7 @@
virtual uint64_t GetSP(uint64_t failValue); // Get stack pointer
virtual void ThreadWillResume();
virtual bool ThreadDidStop();
+ virtual bool NotifyException(MachException::Data& exc);
static DNBArchProtocol *Create (MachThread *thread);
static const uint8_t * const SoftwareBreakpointOpcode (nub_size_t byte_size);
@@ -79,6 +80,8 @@
virtual bool DisableHardwareBreakpoint (uint32_t hw_break_index);
virtual bool DisableHardwareWatchpoint (uint32_t hw_break_index);
virtual bool StepNotComplete ();
+ virtual void HardwareWatchpointStateChanged ();
+ virtual uint32_t GetHardwareWatchpointHit(nub_addr_t &addr);
typedef arm_debug_state_t DBG;
@@ -136,6 +139,10 @@
EXC exc;
};
+ // See also HardwareWatchpointStateChanged() which updates this class-wide variable.
+ static DBG Global_Debug_State;
+ static bool Valid_Global_Debug_State;
+
struct State
{
Context context;
@@ -228,10 +235,16 @@
kern_return_t SetVFPState ();
kern_return_t SetEXCState ();
kern_return_t SetDBGState ();
+
+ // Helper functions for watchpoint implementaions.
+ static void ClearWatchpointOccurred();
+ static bool IsWatchpointHit(const DBG &debug_state, uint32_t hw_index);
+ static nub_addr_t GetWatchAddress(const DBG &debug_state, uint32_t hw_index);
+
protected:
MachThread * m_thread;
State m_state;
- arm_debug_state_t m_dbg_save;
+ DBG m_dbg_save;
nub_addr_t m_hw_single_chained_step_addr;
// Software single stepping support
nub_addr_t m_sw_single_step_next_pc;
More information about the lldb-commits
mailing list