brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.3 KiB · 803fed5 Raw
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