diff options
author | Omair Javaid <omair.javaid@linaro.org> | 2015-11-06 12:56:34 +0000 |
---|---|---|
committer | Omair Javaid <omair.javaid@linaro.org> | 2015-11-06 12:56:34 +0000 |
commit | f24741d9dcaac2b8b80c00b59c8cd0d361c7098f (patch) | |
tree | 689c576ab5323ed36713ddf08352caeab48936de /lldb/source/Plugins/Process/Linux | |
parent | 5762a4f9d17200a7822dd4ea040b576183f8f572 (diff) | |
download | bcm5719-llvm-f24741d9dcaac2b8b80c00b59c8cd0d361c7098f.tar.gz bcm5719-llvm-f24741d9dcaac2b8b80c00b59c8cd0d361c7098f.zip |
Fix for AArch64 watchpoint cache corruption in case of ptrace failure
Same fix has been submitted for Arm.
Review can be found here:
Differential revision: http://reviews.llvm.org/D14051
llvm-svn: 252298
Diffstat (limited to 'lldb/source/Plugins/Process/Linux')
-rw-r--r-- | lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp | 50 |
1 files changed, 49 insertions, 1 deletions
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp index d5d3791524c..e4d26fc640f 100644 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp @@ -435,7 +435,7 @@ NativeRegisterContextLinux_arm64::SetHardwareBreakpoint (lldb::addr_t addr, size if (bp_index == LLDB_INVALID_INDEX32) return LLDB_INVALID_INDEX32; - // Add new or update existing watchpoint + // Add new or update existing breakpoint if ((m_hbr_regs[bp_index].control & 1) == 0) { m_hbr_regs[bp_index].address = addr; @@ -446,7 +446,13 @@ NativeRegisterContextLinux_arm64::SetHardwareBreakpoint (lldb::addr_t addr, size error = WriteHardwareDebugRegs(eDREGTypeBREAK); if (error.Fail()) + { + m_hbr_regs[bp_index].address = 0; + m_hbr_regs[bp_index].control &= ~1; + m_hbr_regs[bp_index].refcount = 0; + return LLDB_INVALID_INDEX32; + } } else m_hbr_regs[bp_index].refcount++; @@ -481,6 +487,11 @@ NativeRegisterContextLinux_arm64::ClearHardwareBreakpoint (uint32_t hw_idx) } else if (m_hbr_regs[hw_idx].refcount == 1) { + // Create a backup we can revert to in case of failure. + lldb::addr_t tempAddr = m_hbr_regs[hw_idx].address; + uint32_t tempControl = m_hbr_regs[hw_idx].control; + uint32_t tempRefCount = m_hbr_regs[hw_idx].refcount; + m_hbr_regs[hw_idx].control &= ~1; m_hbr_regs[hw_idx].address = 0; m_hbr_regs[hw_idx].refcount = 0; @@ -489,7 +500,13 @@ NativeRegisterContextLinux_arm64::ClearHardwareBreakpoint (uint32_t hw_idx) WriteHardwareDebugRegs(eDREGTypeBREAK); if (error.Fail()) + { + m_hbr_regs[hw_idx].control = tempControl; + m_hbr_regs[hw_idx].address = tempAddr; + m_hbr_regs[hw_idx].refcount = tempRefCount; + return false; + } return true; } @@ -595,7 +612,13 @@ NativeRegisterContextLinux_arm64::SetHardwareWatchpoint (lldb::addr_t addr, size error = WriteHardwareDebugRegs(eDREGTypeWATCH); if (error.Fail()) + { + m_hwp_regs[wp_index].address = 0; + m_hwp_regs[wp_index].control &= ~1; + m_hwp_regs[wp_index].refcount = 0; + return LLDB_INVALID_INDEX32; + } } else m_hwp_regs[wp_index].refcount++; @@ -630,6 +653,11 @@ NativeRegisterContextLinux_arm64::ClearHardwareWatchpoint (uint32_t wp_index) } else if (m_hwp_regs[wp_index].refcount == 1) { + // Create a backup we can revert to in case of failure. + lldb::addr_t tempAddr = m_hwp_regs[wp_index].address; + uint32_t tempControl = m_hwp_regs[wp_index].control; + uint32_t tempRefCount = m_hwp_regs[wp_index].refcount; + // Update watchpoint in local cache m_hwp_regs[wp_index].control &= ~1; m_hwp_regs[wp_index].address = 0; @@ -639,7 +667,13 @@ NativeRegisterContextLinux_arm64::ClearHardwareWatchpoint (uint32_t wp_index) error = WriteHardwareDebugRegs(eDREGTypeWATCH); if (error.Fail()) + { + m_hwp_regs[wp_index].control = tempControl; + m_hwp_regs[wp_index].address = tempAddr; + m_hwp_regs[wp_index].refcount = tempRefCount; + return false; + } return true; } @@ -663,10 +697,18 @@ NativeRegisterContextLinux_arm64::ClearAllHardwareWatchpoints () if (error.Fail()) return error; + lldb::addr_t tempAddr = 0; + uint32_t tempControl = 0, tempRefCount = 0; + for (uint32_t i = 0; i < m_max_hwp_supported; i++) { if (m_hwp_regs[i].control & 0x01) { + // Create a backup we can revert to in case of failure. + tempAddr = m_hwp_regs[i].address; + tempControl = m_hwp_regs[i].control; + tempRefCount = m_hwp_regs[i].refcount; + // Clear watchpoints in local cache m_hwp_regs[i].control &= ~1; m_hwp_regs[i].address = 0; @@ -676,7 +718,13 @@ NativeRegisterContextLinux_arm64::ClearAllHardwareWatchpoints () error = WriteHardwareDebugRegs(eDREGTypeWATCH); if (error.Fail()) + { + m_hwp_regs[i].control = tempControl; + m_hwp_regs[i].address = tempAddr; + m_hwp_regs[i].refcount = tempRefCount; + return error; + } } } |