[Lldb-commits] [lldb] [LLDB][Process/Utility] Introduce NativeRegisterContextDBReg class (PR #118043)

David Spickett via lldb-commits lldb-commits at lists.llvm.org
Fri Dec 6 02:42:39 PST 2024


================
@@ -272,199 +57,27 @@ uint32_t NativeRegisterContextDBReg_arm64::SetHardwareWatchpoint(
 
     addr = addr & (~0x07);
   }
-
-  // Setup control value
-  control_value = g_enable_bit | g_pac_bits | GetSizeBits(size);
-  control_value |= watch_flags << 3;
-
-  // Iterate over stored watchpoints and find a free wp_index
-  wp_index = LLDB_INVALID_INDEX32;
-  for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
-    if (!WatchpointIsEnabled(i))
-      wp_index = i; // Mark last free slot
-    else if (m_hwp_regs[i].address == addr) {
-      return LLDB_INVALID_INDEX32; // We do not support duplicate watchpoints.
-    }
-  }
-
-  if (wp_index == LLDB_INVALID_INDEX32)
-    return LLDB_INVALID_INDEX32;
-
-  // Update watchpoint in local cache
-  m_hwp_regs[wp_index].real_addr = real_addr;
-  m_hwp_regs[wp_index].address = addr;
-  m_hwp_regs[wp_index].control = control_value;
-
-  // PTRACE call to set corresponding watchpoint register.
-  error = WriteHardwareDebugRegs(eDREGTypeWATCH);
-
-  if (error) {
-    m_hwp_regs[wp_index].address = 0;
-    m_hwp_regs[wp_index].control &= ~g_enable_bit;
-
-    LLDB_LOG_ERROR(
-        log, std::move(error),
-        "unable to set watchpoint: failed to write debug registers: {0}");
-    return LLDB_INVALID_INDEX32;
-  }
-
-  return wp_index;
-}
-
-bool NativeRegisterContextDBReg_arm64::ClearHardwareWatchpoint(
-    uint32_t wp_index) {
-  Log *log = GetLog(LLDBLog::Watchpoints);
-  LLDB_LOG(log, "wp_index: {0}", wp_index);
-
-  // Read hardware breakpoint and watchpoint information.
-  llvm::Error error = ReadHardwareDebugInfo();
-  if (error) {
-    LLDB_LOG_ERROR(
-        log, std::move(error),
-        "unable to clear watchpoint: failed to read debug registers: {0}");
-    return false;
-  }
-
-  if (wp_index >= m_max_hwp_supported)
-    return false;
-
-  // 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;
-
-  // Update watchpoint in local cache
-  m_hwp_regs[wp_index].control &= ~g_enable_bit;
-  m_hwp_regs[wp_index].address = 0;
-
-  // Ptrace call to update hardware debug registers
-  error = WriteHardwareDebugRegs(eDREGTypeWATCH);
-
-  if (error) {
-    m_hwp_regs[wp_index].control = tempControl;
-    m_hwp_regs[wp_index].address = tempAddr;
-
-    LLDB_LOG_ERROR(
-        log, std::move(error),
-        "unable to clear watchpoint: failed to write debug registers: {0}");
-    return false;
-  }
-
   return true;
 }
 
-Status NativeRegisterContextDBReg_arm64::ClearAllHardwareWatchpoints() {
-  // Read hardware breakpoint and watchpoint information.
-  llvm::Error error = ReadHardwareDebugInfo();
-  if (error)
-    return Status::FromError(std::move(error));
-
-  for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
-    if (WatchpointIsEnabled(i)) {
-      // Create a backup we can revert to in case of failure.
-      lldb::addr_t tempAddr = m_hwp_regs[i].address;
-      uint32_t tempControl = m_hwp_regs[i].control;
-
-      // Clear watchpoints in local cache
-      m_hwp_regs[i].control &= ~g_enable_bit;
-      m_hwp_regs[i].address = 0;
-
-      // Ptrace call to update hardware debug registers
-      error = WriteHardwareDebugRegs(eDREGTypeWATCH);
-
-      if (error) {
-        m_hwp_regs[i].control = tempControl;
-        m_hwp_regs[i].address = tempAddr;
-
-        return Status::FromError(std::move(error));
-      }
-    }
-  }
-
-  return Status();
-}
-
 uint32_t
-NativeRegisterContextDBReg_arm64::GetWatchpointSize(uint32_t wp_index) {
-  Log *log = GetLog(LLDBLog::Watchpoints);
-  LLDB_LOG(log, "wp_index: {0}", wp_index);
+NativeRegisterContextDBReg_arm64::MakeControlValue(size_t size,
+                                                   uint32_t *watch_flags) {
+  // PAC (bits 2:1): 0b10
+  uint32_t pac_bits = (2 << 1);
 
-  switch ((m_hwp_regs[wp_index].control >> 5) & 0xff) {
-  case 0x01:
-    return 1;
-  case 0x03:
-    return 2;
-  case 0x0f:
-    return 4;
-  case 0xff:
-    return 8;
-  default:
-    return 0;
-  }
-}
-
-bool NativeRegisterContextDBReg_arm64::WatchpointIsEnabled(uint32_t wp_index) {
-  Log *log = GetLog(LLDBLog::Watchpoints);
-  LLDB_LOG(log, "wp_index: {0}", wp_index);
-
-  if ((m_hwp_regs[wp_index].control & g_enable_bit) != 0)
-    return true;
-  else
-    return false;
-}
-
-Status NativeRegisterContextDBReg_arm64::GetWatchpointHitIndex(
-    uint32_t &wp_index, lldb::addr_t trap_addr) {
-  Log *log = GetLog(LLDBLog::Watchpoints);
-  LLDB_LOG(log, "wp_index: {0}, trap_addr: {1:x}", wp_index, trap_addr);
-
-  // Read hardware breakpoint and watchpoint information.
-  llvm::Error error = ReadHardwareDebugInfo();
-  if (error)
-    return Status::FromError(std::move(error));
-
-  // Mask off ignored bits from watchpoint trap address.
-  trap_addr = FixWatchpointHitAddress(trap_addr);
-
-  uint32_t watch_size;
-  lldb::addr_t watch_addr;
-
-  for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index) {
-    watch_size = GetWatchpointSize(wp_index);
-    watch_addr = m_hwp_regs[wp_index].address;
-
-    if (WatchpointIsEnabled(wp_index) && trap_addr >= watch_addr &&
-        trap_addr < watch_addr + watch_size) {
-      m_hwp_regs[wp_index].hit_addr = trap_addr;
-      return Status();
-    }
-  }
-
-  wp_index = LLDB_INVALID_INDEX32;
-  return Status();
-}
-
-lldb::addr_t
-NativeRegisterContextDBReg_arm64::GetWatchpointAddress(uint32_t wp_index) {
-  Log *log = GetLog(LLDBLog::Watchpoints);
-  LLDB_LOG(log, "wp_index: {0}", wp_index);
-
-  if (wp_index >= m_max_hwp_supported)
-    return LLDB_INVALID_ADDRESS;
-
-  if (WatchpointIsEnabled(wp_index))
-    return m_hwp_regs[wp_index].real_addr;
-  return LLDB_INVALID_ADDRESS;
-}
-
-lldb::addr_t
-NativeRegisterContextDBReg_arm64::GetWatchpointHitAddress(uint32_t wp_index) {
-  Log *log = GetLog(LLDBLog::Watchpoints);
-  LLDB_LOG(log, "wp_index: {0}", wp_index);
+  // BAS (bits 12:5) hold a bit-mask of addresses to watch
+  // e.g. 0b00000001 means 1 byte at address
+  //      0b00000011 means 2 bytes (addr..addr+1)
+  //      ...
+  //      0b11111111 means 8 bytes (addr..addr+7)
+  auto EncodingSizeBits = [](size_t size) { return ((1 << size) - 1) << 5; };
----------------
DavidSpickett wrote:

We can avoid the overhead of a lambda (or making the compiler remove the overhead) by doing:
```
size_t encoded_size = ((1 << size) - 1) << 5;
```

https://github.com/llvm/llvm-project/pull/118043


More information about the lldb-commits mailing list