118 lines · cpp
1//===-- NativeRegisterContextDBReg_arm.cpp --------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "NativeRegisterContextDBReg_arm.h"10 11#include "lldb/Utility/LLDBLog.h"12#include "lldb/Utility/Log.h"13#include "lldb/Utility/RegisterValue.h"14 15using namespace lldb_private;16 17uint32_t NativeRegisterContextDBReg_arm::GetWatchpointSize(uint32_t wp_index) {18 Log *log = GetLog(LLDBLog::Watchpoints);19 LLDB_LOG(log, "wp_index: {0}", wp_index);20 21 switch ((m_hwp_regs[wp_index].control >> 5) & 0x0f) {22 case 0x01:23 return 1;24 case 0x03:25 return 2;26 case 0x07:27 return 3;28 case 0x0f:29 return 4;30 default:31 return 0;32 }33}34 35std::optional<NativeRegisterContextDBReg::WatchpointDetails>36NativeRegisterContextDBReg_arm::AdjustWatchpoint(37 const WatchpointDetails &details) {38 auto [size, addr] = details;39 40 if (size == 0 || size > 4)41 return {};42 43 // Check 4-byte alignment for hardware watchpoint target address. Below is a44 // hack to recalculate address and size in order to make sure we can watch45 // non 4-byte aligned addresses as well.46 if (addr & 0x03) {47 uint8_t watch_mask = (addr & 0x03) + size;48 if (watch_mask > 0x04)49 return {};50 else if (watch_mask <= 0x02)51 size = 2;52 else53 size = 4;54 55 addr = addr & (~0x03);56 }57 58 return WatchpointDetails{size, addr};59}60 61NativeRegisterContextDBReg::BreakpointDetails62NativeRegisterContextDBReg_arm::AdjustBreakpoint(63 const BreakpointDetails &details) {64 BreakpointDetails bd = details;65 // Use size to get a hint of arm vs thumb modes.66 // LLDB usually aligns this client side, but other clients may not.67 switch (bd.size) {68 case 2:69 bd.addr &= ~1;70 break;71 case 4:72 bd.addr &= ~3;73 break;74 default:75 // We assume that ValidateBreakpoint would have caught this earlier.76 llvm_unreachable("Invalid breakpoint size!");77 }78 79 return bd;80}81 82uint32_t NativeRegisterContextDBReg_arm::MakeBreakControlValue(size_t size) {83 switch (size) {84 case 2:85 return (0x3 << 5) | 7;86 case 4:87 return (0xfu << 5) | 7;88 default:89 // ValidateBreakpoint would have rejected this earlier.90 llvm_unreachable("Invalid breakpoint size.");91 }92}93 94uint32_t95NativeRegisterContextDBReg_arm::MakeWatchControlValue(size_t size,96 uint32_t watch_flags) {97 // We can only watch up to four bytes that follow a 4 byte aligned address98 // per watchpoint register pair, so make sure we can properly encode this.99 // We assume that the address was 4 byte aligned by AdjustWatchpoint.100 uint32_t byte_mask = (1u << size) - 1u;101 102 // Check if we need multiple watchpoint register103 if (byte_mask > 0xfu)104 return LLDB_INVALID_INDEX32;105 106 // Setup control value107 // Make the byte_mask into a valid Byte Address Select mask108 uint32_t control_value = byte_mask << 5;109 110 // Turn on appropriate watchpoint flags read or write111 control_value |= (watch_flags << 3);112 113 // Enable this watchpoint and make it stop in privileged or user mode;114 control_value |= 7;115 116 return control_value;117}118