diff options
| -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; +            }          }      }  | 

