diff options
| author | Johnny Chen <johnny.chen@apple.com> | 2011-09-08 01:16:50 +0000 |
|---|---|---|
| committer | Johnny Chen <johnny.chen@apple.com> | 2011-09-08 01:16:50 +0000 |
| commit | af3d4af4ebec2c519823a745665729ded3f9bbce (patch) | |
| tree | 4d04e8e2c4e48ed30a0e578370541cf36b7c381d | |
| parent | 213b454698ed53fc00203d0ea7be34f46dd0858d (diff) | |
| download | bcm5719-llvm-af3d4af4ebec2c519823a745665729ded3f9bbce.tar.gz bcm5719-llvm-af3d4af4ebec2c519823a745665729ded3f9bbce.zip | |
Add logic to the DNBArchImplX86_64/DNBArchImplI386::NotifyException() callback method
in order to distinguish the real single step exception from a watchpoint exception
which uses the same exc_type of EXC_BREAKPOINT and exc_code of EXC_I386_SGL.
This is done by checking the debug status register to find out whether the watchpoint
data break event has fired, and, if yes, stuff the data break address into the exception's
exc_sub_code field on the debugserver side for lldb to consume on the other end.
llvm-svn: 139274
4 files changed, 95 insertions, 27 deletions
diff --git a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp index 153f1e50bc3..54c339deb3e 100644 --- a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp +++ b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp @@ -625,6 +625,19 @@ DNBArchImplI386::NotifyException(MachException::Data& exc) return true; } } + else if (exc.exc_data.size() >= 2 && exc.exc_data[0] == 1) + { + // exc_code = EXC_I386_SGL + // + // 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; + + return true; + } break; case EXC_SYSCALL: break; @@ -636,29 +649,6 @@ DNBArchImplI386::NotifyException(MachException::Data& exc) return false; } -// Iterate through the debug status register; return the index of the first hit. -uint32_t -DNBArchImplI386::GetHardwareWatchpointHit() -{ - // Read the debug state - kern_return_t kret = GetDBGState(false); - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::GetHardwareWatchpointHit() GetDBGState() => 0x%8.8x.", kret); - if (kret == KERN_SUCCESS) - { - DBG debug_state = m_state.context.dbg; - uint32_t i, num = NumSupportedHardwareWatchpoints(); - for (i = 0; i < num; ++i) - { - if (IsWatchpointHit(debug_state, i)) - { - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::GetHardwareWatchpointHit() found => %u.", i); - return i; - } - } - } - return INVALID_NUB_HW_INDEX; -} - uint32_t DNBArchImplI386::NumSupportedHardwareWatchpoints() { @@ -790,6 +780,23 @@ DNBArchImplI386::IsWatchpointHit(const DBG &debug_state, uint32_t hw_index) return (debug_state.__dr6 & (1 << hw_index)); } +nub_addr_t +DNBArchImplI386::GetWatchAddress(const DBG &debug_state, uint32_t hw_index) +{ + switch (hw_index) { + case 0: + return debug_state.__dr0; + case 1: + return debug_state.__dr1; + case 2: + return debug_state.__dr2; + case 3: + return debug_state.__dr3; + default: + assert(0 && "invalid hardware register index, must be one of 0, 1, 2, or 3"); + } +} + uint32_t DNBArchImplI386::EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write) { @@ -865,6 +872,32 @@ DNBArchImplI386::DisableHardwareWatchpoint (uint32_t hw_index) return false; } +// Iterate through the debug status register; return the index of the first hit. +uint32_t +DNBArchImplI386::GetHardwareWatchpointHit(nub_addr_t &addr) +{ + // Read the debug state + kern_return_t kret = GetDBGState(false); + DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::GetHardwareWatchpointHit() GetDBGState() => 0x%8.8x.", kret); + if (kret == KERN_SUCCESS) + { + DBG debug_state = m_state.context.dbg; + uint32_t i, num = NumSupportedHardwareWatchpoints(); + for (i = 0; i < num; ++i) + { + if (IsWatchpointHit(debug_state, i)) + { + addr = GetWatchAddress(debug_state, i); + DNBLogThreadedIf(LOG_WATCHPOINTS, + "DNBArchImplI386::GetHardwareWatchpointHit() found => %u (addr = %8.8p).", + i, addr); + return i; + } + } + } + return INVALID_NUB_HW_INDEX; +} + // Set the single step bit in the processor status register. kern_return_t DNBArchImplI386::EnableHardwareSingleStep (bool enable) diff --git a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h index 9a00e004466..bbe3643ecab 100644 --- a/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h +++ b/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.h @@ -54,7 +54,7 @@ public: virtual uint32_t NumSupportedHardwareWatchpoints(); virtual uint32_t EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write); virtual bool DisableHardwareWatchpoint (uint32_t hw_break_index); - virtual uint32_t GetHardwareWatchpointHit(); + virtual uint32_t GetHardwareWatchpointHit(nub_addr_t &addr); protected: kern_return_t EnableHardwareSingleStep (bool enable); @@ -233,6 +233,7 @@ protected: static bool IsWatchpointVacant(const DBG &debug_state, uint32_t hw_index); static void ClearWatchpointHits(DBG &debug_state); static bool IsWatchpointHit(const DBG &debug_state, uint32_t hw_index); + static nub_addr_t GetWatchAddress(const DBG &debug_state, uint32_t hw_index); MachThread *m_thread; State m_state; diff --git a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp index 014aff9606d..87400d3d5b8 100644 --- a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp +++ b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.cpp @@ -554,6 +554,19 @@ DNBArchImplX86_64::NotifyException(MachException::Data& exc) return true; } } + else if (exc.exc_data.size() >= 2 && exc.exc_data[0] == 1) + { + // exc_code = EXC_I386_SGL + // + // 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; + + return true; + } break; case EXC_SYSCALL: break; @@ -695,6 +708,23 @@ DNBArchImplX86_64::IsWatchpointHit(const DBG &debug_state, uint32_t hw_index) return (debug_state.__dr6 & (1 << hw_index)); } +nub_addr_t +DNBArchImplX86_64::GetWatchAddress(const DBG &debug_state, uint32_t hw_index) +{ + switch (hw_index) { + case 0: + return debug_state.__dr0; + case 1: + return debug_state.__dr1; + case 2: + return debug_state.__dr2; + case 3: + return debug_state.__dr3; + default: + assert(0 && "invalid hardware register index, must be one of 0, 1, 2, or 3"); + } +} + uint32_t DNBArchImplX86_64::EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write) { @@ -772,7 +802,7 @@ DNBArchImplX86_64::DisableHardwareWatchpoint (uint32_t hw_index) // Iterate through the debug status register; return the index of the first hit. uint32_t -DNBArchImplX86_64::GetHardwareWatchpointHit() +DNBArchImplX86_64::GetHardwareWatchpointHit(nub_addr_t &addr) { // Read the debug state kern_return_t kret = GetDBGState(false); @@ -785,7 +815,10 @@ DNBArchImplX86_64::GetHardwareWatchpointHit() { if (IsWatchpointHit(debug_state, i)) { - DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::GetHardwareWatchpointHit() found => %u.", i); + addr = GetWatchAddress(debug_state, i); + DNBLogThreadedIf(LOG_WATCHPOINTS, + "DNBArchImplX86_64::GetHardwareWatchpointHit() found => %u (addr = %8.8p).", + i, addr); return i; } } diff --git a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h index ac1def91621..661a9d894a6 100644 --- a/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h +++ b/lldb/tools/debugserver/source/MacOSX/x86_64/DNBArchImplX86_64.h @@ -53,7 +53,7 @@ public: virtual uint32_t NumSupportedHardwareWatchpoints(); virtual uint32_t EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write); virtual bool DisableHardwareWatchpoint (uint32_t hw_break_index); - virtual uint32_t GetHardwareWatchpointHit(); + virtual uint32_t GetHardwareWatchpointHit(nub_addr_t &addr); protected: kern_return_t EnableHardwareSingleStep (bool enable); @@ -240,6 +240,7 @@ protected: static bool IsWatchpointVacant(const DBG &debug_state, uint32_t hw_index); static void ClearWatchpointHits(DBG &debug_state); static bool IsWatchpointHit(const DBG &debug_state, uint32_t hw_index); + static nub_addr_t GetWatchAddress(const DBG &debug_state, uint32_t hw_index); MachThread *m_thread; State m_state; |

