1*ae5836f6Swanglei //===-- NativeRegisterContextDBReg.cpp ------------------------------------===// 2*ae5836f6Swanglei // 3*ae5836f6Swanglei // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*ae5836f6Swanglei // See https://llvm.org/LICENSE.txt for license information. 5*ae5836f6Swanglei // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*ae5836f6Swanglei // 7*ae5836f6Swanglei //===----------------------------------------------------------------------===// 8*ae5836f6Swanglei 9*ae5836f6Swanglei #include "NativeRegisterContextDBReg.h" 10*ae5836f6Swanglei 11*ae5836f6Swanglei #include "lldb/Utility/LLDBLog.h" 12*ae5836f6Swanglei #include "lldb/Utility/Log.h" 13*ae5836f6Swanglei #include "lldb/Utility/RegisterValue.h" 14*ae5836f6Swanglei 15*ae5836f6Swanglei using namespace lldb_private; 16*ae5836f6Swanglei 17*ae5836f6Swanglei uint32_t NativeRegisterContextDBReg::NumSupportedHardwareBreakpoints() { 18*ae5836f6Swanglei Log *log = GetLog(LLDBLog::Breakpoints); 19*ae5836f6Swanglei 20*ae5836f6Swanglei // Read hardware breakpoint and watchpoint information. 21*ae5836f6Swanglei llvm::Error error = ReadHardwareDebugInfo(); 22*ae5836f6Swanglei 23*ae5836f6Swanglei if (error) { 24*ae5836f6Swanglei LLDB_LOG_ERROR(log, std::move(error), 25*ae5836f6Swanglei "failed to read debug registers: {0}"); 26*ae5836f6Swanglei return 0; 27*ae5836f6Swanglei } 28*ae5836f6Swanglei 29*ae5836f6Swanglei LLDB_LOG(log, "{0}", m_max_hbp_supported); 30*ae5836f6Swanglei return m_max_hbp_supported; 31*ae5836f6Swanglei } 32*ae5836f6Swanglei 33*ae5836f6Swanglei uint32_t NativeRegisterContextDBReg::SetHardwareBreakpoint(lldb::addr_t addr, 34*ae5836f6Swanglei size_t size) { 35*ae5836f6Swanglei Log *log = GetLog(LLDBLog::Breakpoints); 36*ae5836f6Swanglei LLDB_LOG(log, "addr: {0:x}, size: {1:x}", addr, size); 37*ae5836f6Swanglei 38*ae5836f6Swanglei // Read hardware breakpoint and watchpoint information. 39*ae5836f6Swanglei llvm::Error error = ReadHardwareDebugInfo(); 40*ae5836f6Swanglei if (error) { 41*ae5836f6Swanglei LLDB_LOG_ERROR( 42*ae5836f6Swanglei log, std::move(error), 43*ae5836f6Swanglei "unable to set breakpoint: failed to read debug registers: {0}"); 44*ae5836f6Swanglei return LLDB_INVALID_INDEX32; 45*ae5836f6Swanglei } 46*ae5836f6Swanglei 47*ae5836f6Swanglei uint32_t control_value = 0, bp_index = 0; 48*ae5836f6Swanglei 49*ae5836f6Swanglei if (!ValidateBreakpoint(size, addr)) 50*ae5836f6Swanglei return LLDB_INVALID_INDEX32; 51*ae5836f6Swanglei 52*ae5836f6Swanglei control_value = MakeBreakControlValue(size); 53*ae5836f6Swanglei 54*ae5836f6Swanglei // Iterate over stored breakpoints and find a free bp_index 55*ae5836f6Swanglei bp_index = LLDB_INVALID_INDEX32; 56*ae5836f6Swanglei for (uint32_t i = 0; i < m_max_hbp_supported; i++) { 57*ae5836f6Swanglei if (!BreakpointIsEnabled(i)) 58*ae5836f6Swanglei bp_index = i; // Mark last free slot 59*ae5836f6Swanglei else if (m_hbp_regs[i].address == addr) 60*ae5836f6Swanglei return LLDB_INVALID_INDEX32; // We do not support duplicate breakpoints. 61*ae5836f6Swanglei } 62*ae5836f6Swanglei 63*ae5836f6Swanglei if (bp_index == LLDB_INVALID_INDEX32) 64*ae5836f6Swanglei return LLDB_INVALID_INDEX32; 65*ae5836f6Swanglei 66*ae5836f6Swanglei // Update breakpoint in local cache 67*ae5836f6Swanglei m_hbp_regs[bp_index].real_addr = addr; 68*ae5836f6Swanglei m_hbp_regs[bp_index].address = addr; 69*ae5836f6Swanglei m_hbp_regs[bp_index].control = control_value; 70*ae5836f6Swanglei 71*ae5836f6Swanglei // PTRACE call to set corresponding hardware breakpoint register. 72*ae5836f6Swanglei error = WriteHardwareDebugRegs(eDREGTypeBREAK); 73*ae5836f6Swanglei 74*ae5836f6Swanglei if (error) { 75*ae5836f6Swanglei m_hbp_regs[bp_index].address = 0; 76*ae5836f6Swanglei m_hbp_regs[bp_index].control &= ~m_hw_dbg_enable_bit; 77*ae5836f6Swanglei 78*ae5836f6Swanglei LLDB_LOG_ERROR( 79*ae5836f6Swanglei log, std::move(error), 80*ae5836f6Swanglei "unable to set breakpoint: failed to write debug registers: {0}"); 81*ae5836f6Swanglei return LLDB_INVALID_INDEX32; 82*ae5836f6Swanglei } 83*ae5836f6Swanglei 84*ae5836f6Swanglei return bp_index; 85*ae5836f6Swanglei } 86*ae5836f6Swanglei 87*ae5836f6Swanglei bool NativeRegisterContextDBReg::ClearHardwareBreakpoint(uint32_t hw_idx) { 88*ae5836f6Swanglei Log *log = GetLog(LLDBLog::Breakpoints); 89*ae5836f6Swanglei LLDB_LOG(log, "hw_idx: {0}", hw_idx); 90*ae5836f6Swanglei 91*ae5836f6Swanglei // Read hardware breakpoint and watchpoint information. 92*ae5836f6Swanglei llvm::Error error = ReadHardwareDebugInfo(); 93*ae5836f6Swanglei if (error) { 94*ae5836f6Swanglei LLDB_LOG_ERROR( 95*ae5836f6Swanglei log, std::move(error), 96*ae5836f6Swanglei "unable to clear breakpoint: failed to read debug registers: {0}"); 97*ae5836f6Swanglei return false; 98*ae5836f6Swanglei } 99*ae5836f6Swanglei 100*ae5836f6Swanglei if (hw_idx >= m_max_hbp_supported) 101*ae5836f6Swanglei return false; 102*ae5836f6Swanglei 103*ae5836f6Swanglei // Create a backup we can revert to in case of failure. 104*ae5836f6Swanglei lldb::addr_t tempAddr = m_hbp_regs[hw_idx].address; 105*ae5836f6Swanglei uint32_t tempControl = m_hbp_regs[hw_idx].control; 106*ae5836f6Swanglei 107*ae5836f6Swanglei m_hbp_regs[hw_idx].control &= ~m_hw_dbg_enable_bit; 108*ae5836f6Swanglei m_hbp_regs[hw_idx].address = 0; 109*ae5836f6Swanglei 110*ae5836f6Swanglei // PTRACE call to clear corresponding hardware breakpoint register. 111*ae5836f6Swanglei error = WriteHardwareDebugRegs(eDREGTypeBREAK); 112*ae5836f6Swanglei 113*ae5836f6Swanglei if (error) { 114*ae5836f6Swanglei m_hbp_regs[hw_idx].control = tempControl; 115*ae5836f6Swanglei m_hbp_regs[hw_idx].address = tempAddr; 116*ae5836f6Swanglei 117*ae5836f6Swanglei LLDB_LOG_ERROR( 118*ae5836f6Swanglei log, std::move(error), 119*ae5836f6Swanglei "unable to clear breakpoint: failed to write debug registers: {0}"); 120*ae5836f6Swanglei return false; 121*ae5836f6Swanglei } 122*ae5836f6Swanglei 123*ae5836f6Swanglei return true; 124*ae5836f6Swanglei } 125*ae5836f6Swanglei 126*ae5836f6Swanglei Status 127*ae5836f6Swanglei NativeRegisterContextDBReg::GetHardwareBreakHitIndex(uint32_t &bp_index, 128*ae5836f6Swanglei lldb::addr_t trap_addr) { 129*ae5836f6Swanglei Log *log = GetLog(LLDBLog::Breakpoints); 130*ae5836f6Swanglei 131*ae5836f6Swanglei LLDB_LOGF(log, "NativeRegisterContextDBReg::%s()", __FUNCTION__); 132*ae5836f6Swanglei 133*ae5836f6Swanglei lldb::addr_t break_addr; 134*ae5836f6Swanglei 135*ae5836f6Swanglei for (bp_index = 0; bp_index < m_max_hbp_supported; ++bp_index) { 136*ae5836f6Swanglei break_addr = m_hbp_regs[bp_index].address; 137*ae5836f6Swanglei 138*ae5836f6Swanglei if (BreakpointIsEnabled(bp_index) && trap_addr == break_addr) { 139*ae5836f6Swanglei m_hbp_regs[bp_index].hit_addr = trap_addr; 140*ae5836f6Swanglei return Status(); 141*ae5836f6Swanglei } 142*ae5836f6Swanglei } 143*ae5836f6Swanglei 144*ae5836f6Swanglei bp_index = LLDB_INVALID_INDEX32; 145*ae5836f6Swanglei return Status(); 146*ae5836f6Swanglei } 147*ae5836f6Swanglei 148*ae5836f6Swanglei Status NativeRegisterContextDBReg::ClearAllHardwareBreakpoints() { 149*ae5836f6Swanglei Log *log = GetLog(LLDBLog::Breakpoints); 150*ae5836f6Swanglei 151*ae5836f6Swanglei LLDB_LOGF(log, "NativeRegisterContextDBReg::%s()", __FUNCTION__); 152*ae5836f6Swanglei 153*ae5836f6Swanglei // Read hardware breakpoint and watchpoint information. 154*ae5836f6Swanglei llvm::Error error = ReadHardwareDebugInfo(); 155*ae5836f6Swanglei if (error) 156*ae5836f6Swanglei return Status::FromError(std::move(error)); 157*ae5836f6Swanglei 158*ae5836f6Swanglei for (uint32_t i = 0; i < m_max_hbp_supported; i++) { 159*ae5836f6Swanglei if (!BreakpointIsEnabled(i)) 160*ae5836f6Swanglei continue; 161*ae5836f6Swanglei // Create a backup we can revert to in case of failure. 162*ae5836f6Swanglei lldb::addr_t tempAddr = m_hbp_regs[i].address; 163*ae5836f6Swanglei uint32_t tempControl = m_hbp_regs[i].control; 164*ae5836f6Swanglei 165*ae5836f6Swanglei // Clear watchpoints in local cache 166*ae5836f6Swanglei m_hbp_regs[i].control &= ~m_hw_dbg_enable_bit; 167*ae5836f6Swanglei m_hbp_regs[i].address = 0; 168*ae5836f6Swanglei 169*ae5836f6Swanglei // Ptrace call to update hardware debug registers 170*ae5836f6Swanglei error = WriteHardwareDebugRegs(eDREGTypeBREAK); 171*ae5836f6Swanglei 172*ae5836f6Swanglei if (error) { 173*ae5836f6Swanglei m_hbp_regs[i].control = tempControl; 174*ae5836f6Swanglei m_hbp_regs[i].address = tempAddr; 175*ae5836f6Swanglei 176*ae5836f6Swanglei return Status::FromError(std::move(error)); 177*ae5836f6Swanglei } 178*ae5836f6Swanglei } 179*ae5836f6Swanglei 180*ae5836f6Swanglei return Status(); 181*ae5836f6Swanglei } 182*ae5836f6Swanglei 183*ae5836f6Swanglei bool NativeRegisterContextDBReg::BreakpointIsEnabled(uint32_t bp_index) { 184*ae5836f6Swanglei return ((m_hbp_regs[bp_index].control & m_hw_dbg_enable_bit) != 0); 185*ae5836f6Swanglei } 186*ae5836f6Swanglei 187*ae5836f6Swanglei uint32_t NativeRegisterContextDBReg::NumSupportedHardwareWatchpoints() { 188*ae5836f6Swanglei Log *log = GetLog(LLDBLog::Watchpoints); 189*ae5836f6Swanglei llvm::Error error = ReadHardwareDebugInfo(); 190*ae5836f6Swanglei if (error) { 191*ae5836f6Swanglei LLDB_LOG_ERROR(log, std::move(error), 192*ae5836f6Swanglei "failed to read debug registers: {0}"); 193*ae5836f6Swanglei return 0; 194*ae5836f6Swanglei } 195*ae5836f6Swanglei 196*ae5836f6Swanglei return m_max_hwp_supported; 197*ae5836f6Swanglei } 198*ae5836f6Swanglei 199*ae5836f6Swanglei uint32_t NativeRegisterContextDBReg::SetHardwareWatchpoint( 200*ae5836f6Swanglei lldb::addr_t addr, size_t size, uint32_t watch_flags) { 201*ae5836f6Swanglei Log *log = GetLog(LLDBLog::Watchpoints); 202*ae5836f6Swanglei LLDB_LOG(log, "addr: {0:x}, size: {1:x} watch_flags: {2:x}", addr, size, 203*ae5836f6Swanglei watch_flags); 204*ae5836f6Swanglei 205*ae5836f6Swanglei // Read hardware breakpoint and watchpoint information. 206*ae5836f6Swanglei llvm::Error error = ReadHardwareDebugInfo(); 207*ae5836f6Swanglei if (error) { 208*ae5836f6Swanglei LLDB_LOG_ERROR( 209*ae5836f6Swanglei log, std::move(error), 210*ae5836f6Swanglei "unable to set watchpoint: failed to read debug registers: {0}"); 211*ae5836f6Swanglei return LLDB_INVALID_INDEX32; 212*ae5836f6Swanglei } 213*ae5836f6Swanglei 214*ae5836f6Swanglei uint32_t control_value = 0, wp_index = 0; 215*ae5836f6Swanglei lldb::addr_t real_addr = addr; 216*ae5836f6Swanglei WatchpointDetails details{size, addr}; 217*ae5836f6Swanglei 218*ae5836f6Swanglei auto adjusted = AdjustWatchpoint(details); 219*ae5836f6Swanglei if (adjusted == std::nullopt) 220*ae5836f6Swanglei return LLDB_INVALID_INDEX32; 221*ae5836f6Swanglei size = adjusted->size; 222*ae5836f6Swanglei addr = adjusted->addr; 223*ae5836f6Swanglei 224*ae5836f6Swanglei // Check if we are setting watchpoint other than read/write/access Also 225*ae5836f6Swanglei // update watchpoint flag to match AArch64/LoongArch write-read bit 226*ae5836f6Swanglei // configuration. 227*ae5836f6Swanglei switch (watch_flags) { 228*ae5836f6Swanglei case lldb::eWatchpointKindWrite: 229*ae5836f6Swanglei watch_flags = 2; 230*ae5836f6Swanglei break; 231*ae5836f6Swanglei case lldb::eWatchpointKindRead: 232*ae5836f6Swanglei watch_flags = 1; 233*ae5836f6Swanglei break; 234*ae5836f6Swanglei case (lldb::eWatchpointKindRead | lldb::eWatchpointKindWrite): 235*ae5836f6Swanglei break; 236*ae5836f6Swanglei default: 237*ae5836f6Swanglei return LLDB_INVALID_INDEX32; 238*ae5836f6Swanglei } 239*ae5836f6Swanglei 240*ae5836f6Swanglei control_value = MakeWatchControlValue(size, watch_flags); 241*ae5836f6Swanglei 242*ae5836f6Swanglei // Iterate over stored watchpoints and find a free wp_index 243*ae5836f6Swanglei wp_index = LLDB_INVALID_INDEX32; 244*ae5836f6Swanglei for (uint32_t i = 0; i < m_max_hwp_supported; i++) { 245*ae5836f6Swanglei if (!WatchpointIsEnabled(i)) 246*ae5836f6Swanglei wp_index = i; // Mark last free slot 247*ae5836f6Swanglei else if (m_hwp_regs[i].address == addr) { 248*ae5836f6Swanglei return LLDB_INVALID_INDEX32; // We do not support duplicate watchpoints. 249*ae5836f6Swanglei } 250*ae5836f6Swanglei } 251*ae5836f6Swanglei 252*ae5836f6Swanglei if (wp_index == LLDB_INVALID_INDEX32) 253*ae5836f6Swanglei return LLDB_INVALID_INDEX32; 254*ae5836f6Swanglei 255*ae5836f6Swanglei // Update watchpoint in local cache 256*ae5836f6Swanglei m_hwp_regs[wp_index].real_addr = real_addr; 257*ae5836f6Swanglei m_hwp_regs[wp_index].address = addr; 258*ae5836f6Swanglei m_hwp_regs[wp_index].control = control_value; 259*ae5836f6Swanglei 260*ae5836f6Swanglei // PTRACE call to set corresponding watchpoint register. 261*ae5836f6Swanglei error = WriteHardwareDebugRegs(eDREGTypeWATCH); 262*ae5836f6Swanglei 263*ae5836f6Swanglei if (error) { 264*ae5836f6Swanglei m_hwp_regs[wp_index].address = 0; 265*ae5836f6Swanglei m_hwp_regs[wp_index].control &= ~m_hw_dbg_enable_bit; 266*ae5836f6Swanglei 267*ae5836f6Swanglei LLDB_LOG_ERROR( 268*ae5836f6Swanglei log, std::move(error), 269*ae5836f6Swanglei "unable to set watchpoint: failed to write debug registers: {0}"); 270*ae5836f6Swanglei return LLDB_INVALID_INDEX32; 271*ae5836f6Swanglei } 272*ae5836f6Swanglei 273*ae5836f6Swanglei return wp_index; 274*ae5836f6Swanglei } 275*ae5836f6Swanglei 276*ae5836f6Swanglei bool NativeRegisterContextDBReg::ClearHardwareWatchpoint(uint32_t wp_index) { 277*ae5836f6Swanglei Log *log = GetLog(LLDBLog::Watchpoints); 278*ae5836f6Swanglei LLDB_LOG(log, "wp_index: {0}", wp_index); 279*ae5836f6Swanglei 280*ae5836f6Swanglei // Read hardware breakpoint and watchpoint information. 281*ae5836f6Swanglei llvm::Error error = ReadHardwareDebugInfo(); 282*ae5836f6Swanglei if (error) { 283*ae5836f6Swanglei LLDB_LOG_ERROR( 284*ae5836f6Swanglei log, std::move(error), 285*ae5836f6Swanglei "unable to set watchpoint: failed to read debug registers: {0}"); 286*ae5836f6Swanglei return LLDB_INVALID_INDEX32; 287*ae5836f6Swanglei } 288*ae5836f6Swanglei 289*ae5836f6Swanglei if (wp_index >= m_max_hwp_supported) 290*ae5836f6Swanglei return false; 291*ae5836f6Swanglei 292*ae5836f6Swanglei // Create a backup we can revert to in case of failure. 293*ae5836f6Swanglei lldb::addr_t tempAddr = m_hwp_regs[wp_index].address; 294*ae5836f6Swanglei uint32_t tempControl = m_hwp_regs[wp_index].control; 295*ae5836f6Swanglei 296*ae5836f6Swanglei // Update watchpoint in local cache 297*ae5836f6Swanglei m_hwp_regs[wp_index].control &= ~m_hw_dbg_enable_bit; 298*ae5836f6Swanglei m_hwp_regs[wp_index].address = 0; 299*ae5836f6Swanglei 300*ae5836f6Swanglei // Ptrace call to update hardware debug registers 301*ae5836f6Swanglei error = WriteHardwareDebugRegs(eDREGTypeWATCH); 302*ae5836f6Swanglei 303*ae5836f6Swanglei if (error) { 304*ae5836f6Swanglei m_hwp_regs[wp_index].control = tempControl; 305*ae5836f6Swanglei m_hwp_regs[wp_index].address = tempAddr; 306*ae5836f6Swanglei 307*ae5836f6Swanglei LLDB_LOG_ERROR( 308*ae5836f6Swanglei log, std::move(error), 309*ae5836f6Swanglei "unable to clear watchpoint: failed to read debug registers: {0}"); 310*ae5836f6Swanglei return false; 311*ae5836f6Swanglei } 312*ae5836f6Swanglei 313*ae5836f6Swanglei return true; 314*ae5836f6Swanglei } 315*ae5836f6Swanglei 316*ae5836f6Swanglei Status NativeRegisterContextDBReg::ClearAllHardwareWatchpoints() { 317*ae5836f6Swanglei // Read hardware breakpoint and watchpoint information. 318*ae5836f6Swanglei llvm::Error error = ReadHardwareDebugInfo(); 319*ae5836f6Swanglei if (error) 320*ae5836f6Swanglei return Status::FromError(std::move(error)); 321*ae5836f6Swanglei 322*ae5836f6Swanglei for (uint32_t i = 0; i < m_max_hwp_supported; i++) { 323*ae5836f6Swanglei if (!WatchpointIsEnabled(i)) 324*ae5836f6Swanglei continue; 325*ae5836f6Swanglei // Create a backup we can revert to in case of failure. 326*ae5836f6Swanglei lldb::addr_t tempAddr = m_hwp_regs[i].address; 327*ae5836f6Swanglei uint32_t tempControl = m_hwp_regs[i].control; 328*ae5836f6Swanglei 329*ae5836f6Swanglei // Clear watchpoints in local cache 330*ae5836f6Swanglei m_hwp_regs[i].control = 0; 331*ae5836f6Swanglei m_hwp_regs[i].address = 0; 332*ae5836f6Swanglei 333*ae5836f6Swanglei // Ptrace call to update hardware debug registers 334*ae5836f6Swanglei error = WriteHardwareDebugRegs(eDREGTypeWATCH); 335*ae5836f6Swanglei 336*ae5836f6Swanglei if (error) { 337*ae5836f6Swanglei m_hwp_regs[i].control = tempControl; 338*ae5836f6Swanglei m_hwp_regs[i].address = tempAddr; 339*ae5836f6Swanglei 340*ae5836f6Swanglei return Status::FromError(std::move(error)); 341*ae5836f6Swanglei } 342*ae5836f6Swanglei } 343*ae5836f6Swanglei 344*ae5836f6Swanglei return Status(); 345*ae5836f6Swanglei } 346*ae5836f6Swanglei 347*ae5836f6Swanglei Status 348*ae5836f6Swanglei NativeRegisterContextDBReg::GetWatchpointHitIndex(uint32_t &wp_index, 349*ae5836f6Swanglei lldb::addr_t trap_addr) { 350*ae5836f6Swanglei Log *log = GetLog(LLDBLog::Watchpoints); 351*ae5836f6Swanglei LLDB_LOG(log, "wp_index: {0}, trap_addr: {1:x}", wp_index, trap_addr); 352*ae5836f6Swanglei 353*ae5836f6Swanglei // Read hardware breakpoint and watchpoint information. 354*ae5836f6Swanglei llvm::Error error = ReadHardwareDebugInfo(); 355*ae5836f6Swanglei if (error) 356*ae5836f6Swanglei return Status::FromError(std::move(error)); 357*ae5836f6Swanglei 358*ae5836f6Swanglei // AArch64 need mask off ignored bits from watchpoint trap address. 359*ae5836f6Swanglei trap_addr = FixWatchpointHitAddress(trap_addr); 360*ae5836f6Swanglei 361*ae5836f6Swanglei uint32_t watch_size; 362*ae5836f6Swanglei lldb::addr_t watch_addr; 363*ae5836f6Swanglei 364*ae5836f6Swanglei for (wp_index = 0; wp_index < m_max_hwp_supported; ++wp_index) { 365*ae5836f6Swanglei watch_size = GetWatchpointSize(wp_index); 366*ae5836f6Swanglei watch_addr = m_hwp_regs[wp_index].address; 367*ae5836f6Swanglei 368*ae5836f6Swanglei if (WatchpointIsEnabled(wp_index) && trap_addr >= watch_addr && 369*ae5836f6Swanglei trap_addr < watch_addr + watch_size) { 370*ae5836f6Swanglei m_hwp_regs[wp_index].hit_addr = trap_addr; 371*ae5836f6Swanglei return Status(); 372*ae5836f6Swanglei } 373*ae5836f6Swanglei } 374*ae5836f6Swanglei 375*ae5836f6Swanglei wp_index = LLDB_INVALID_INDEX32; 376*ae5836f6Swanglei return Status(); 377*ae5836f6Swanglei } 378*ae5836f6Swanglei 379*ae5836f6Swanglei bool NativeRegisterContextDBReg::WatchpointIsEnabled(uint32_t wp_index) { 380*ae5836f6Swanglei Log *log = GetLog(LLDBLog::Watchpoints); 381*ae5836f6Swanglei LLDB_LOG(log, "wp_index: {0}", wp_index); 382*ae5836f6Swanglei return ((m_hwp_regs[wp_index].control & m_hw_dbg_enable_bit) != 0); 383*ae5836f6Swanglei } 384*ae5836f6Swanglei 385*ae5836f6Swanglei lldb::addr_t 386*ae5836f6Swanglei NativeRegisterContextDBReg::GetWatchpointAddress(uint32_t wp_index) { 387*ae5836f6Swanglei Log *log = GetLog(LLDBLog::Watchpoints); 388*ae5836f6Swanglei LLDB_LOG(log, "wp_index: {0}", wp_index); 389*ae5836f6Swanglei 390*ae5836f6Swanglei if (wp_index >= m_max_hwp_supported) 391*ae5836f6Swanglei return LLDB_INVALID_ADDRESS; 392*ae5836f6Swanglei 393*ae5836f6Swanglei if (WatchpointIsEnabled(wp_index)) 394*ae5836f6Swanglei return m_hwp_regs[wp_index].real_addr; 395*ae5836f6Swanglei return LLDB_INVALID_ADDRESS; 396*ae5836f6Swanglei } 397*ae5836f6Swanglei 398*ae5836f6Swanglei lldb::addr_t 399*ae5836f6Swanglei NativeRegisterContextDBReg::GetWatchpointHitAddress(uint32_t wp_index) { 400*ae5836f6Swanglei Log *log = GetLog(LLDBLog::Watchpoints); 401*ae5836f6Swanglei LLDB_LOG(log, "wp_index: {0}", wp_index); 402*ae5836f6Swanglei 403*ae5836f6Swanglei if (wp_index >= m_max_hwp_supported) 404*ae5836f6Swanglei return LLDB_INVALID_ADDRESS; 405*ae5836f6Swanglei 406*ae5836f6Swanglei if (WatchpointIsEnabled(wp_index)) 407*ae5836f6Swanglei return m_hwp_regs[wp_index].hit_addr; 408*ae5836f6Swanglei return LLDB_INVALID_ADDRESS; 409*ae5836f6Swanglei } 410