brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.2 KiB · 6a07235 Raw
144 lines · cpp
1//===-- ArchitectureAArch64.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 "Plugins/Architecture/AArch64/ArchitectureAArch64.h"10#include "lldb/Core/PluginManager.h"11#include "lldb/Target/RegisterContext.h"12#include "lldb/Utility/ArchSpec.h"13#include "lldb/Utility/DataBufferHeap.h"14#include "lldb/Utility/DataExtractor.h"15 16using namespace lldb_private;17using namespace lldb;18 19LLDB_PLUGIN_DEFINE(ArchitectureAArch64)20 21void ArchitectureAArch64::Initialize() {22  PluginManager::RegisterPlugin(GetPluginNameStatic(),23                                "AArch64-specific algorithms",24                                &ArchitectureAArch64::Create);25}26 27void ArchitectureAArch64::Terminate() {28  PluginManager::UnregisterPlugin(&ArchitectureAArch64::Create);29}30 31std::unique_ptr<Architecture>32ArchitectureAArch64::Create(const ArchSpec &arch) {33  auto machine = arch.GetMachine();34  if (machine != llvm::Triple::aarch64 && machine != llvm::Triple::aarch64_be &&35      machine != llvm::Triple::aarch64_32) {36    return nullptr;37  }38  return std::unique_ptr<Architecture>(new ArchitectureAArch64());39}40 41static void42UpdateARM64SVERegistersInfos(DynamicRegisterInfo::reg_collection_range regs,43                             uint64_t vg) {44  // SVE Z register size is vg x 8 bytes.45  uint32_t z_reg_byte_size = vg * 8;46 47  // SVE vector length has changed, accordingly set size of Z, P and FFR48  // registers. Also invalidate register offsets it will be recalculated49  // after SVE register size update.50  for (auto &reg : regs) {51    if (reg.value_regs == nullptr) {52      if (reg.name[0] == 'z' && isdigit(reg.name[1]))53        reg.byte_size = z_reg_byte_size;54      else if (reg.name[0] == 'p' && isdigit(reg.name[1]))55        reg.byte_size = vg;56      else if (strcmp(reg.name, "ffr") == 0)57        reg.byte_size = vg;58    }59    reg.byte_offset = LLDB_INVALID_INDEX32;60  }61}62 63static void64UpdateARM64SMERegistersInfos(DynamicRegisterInfo::reg_collection_range regs,65                             uint64_t svg) {66  for (auto &reg : regs) {67    if (strcmp(reg.name, "za") == 0) {68      // ZA is a register with size (svg*8) * (svg*8). A square essentially.69      reg.byte_size = (svg * 8) * (svg * 8);70    }71    reg.byte_offset = LLDB_INVALID_INDEX32;72  }73}74 75bool ArchitectureAArch64::ReconfigureRegisterInfo(DynamicRegisterInfo &reg_info,76                                                  DataExtractor &reg_data,77                                                  RegisterContext &reg_context78 79) const {80  // Once we start to reconfigure registers, we cannot read any of them.81  // So we must read VG and SVG up front.82 83  const uint64_t fail_value = LLDB_INVALID_ADDRESS;84  std::optional<uint64_t> vg_reg_value;85  const RegisterInfo *vg_reg_info = reg_info.GetRegisterInfo("vg");86  if (vg_reg_info) {87    uint32_t vg_reg_num = vg_reg_info->kinds[eRegisterKindLLDB];88    uint64_t reg_value =89        reg_context.ReadRegisterAsUnsigned(vg_reg_num, fail_value);90    if (reg_value != fail_value && reg_value <= 32)91      vg_reg_value = reg_value;92  }93 94  std::optional<uint64_t> svg_reg_value;95  const RegisterInfo *svg_reg_info = reg_info.GetRegisterInfo("svg");96  if (svg_reg_info) {97    uint32_t svg_reg_num = svg_reg_info->kinds[eRegisterKindLLDB];98    uint64_t reg_value =99        reg_context.ReadRegisterAsUnsigned(svg_reg_num, fail_value);100    if (reg_value != fail_value && reg_value <= 32)101      svg_reg_value = reg_value;102  }103  if (!svg_reg_value) {104    const RegisterInfo *darwin_svg_reg_info = reg_info.GetRegisterInfo("svl");105    if (darwin_svg_reg_info) {106      uint32_t svg_reg_num = darwin_svg_reg_info->kinds[eRegisterKindLLDB];107      uint64_t reg_value =108          reg_context.ReadRegisterAsUnsigned(svg_reg_num, fail_value);109      // UpdateARM64SVERegistersInfos and UpdateARM64SMERegistersInfos110      // expect the number of 8-byte granules; darwin provides number of111      // bytes.112      if (reg_value != fail_value && reg_value <= 256) {113        svg_reg_value = reg_value / 8;114        // Apple hardware only implements Streaming SVE mode, so115        // the non-streaming Vector Length is not reported by the116        // kernel. Set both svg and vg to this svl value.117        if (!vg_reg_value)118          vg_reg_value = reg_value / 8;119      }120    }121  }122 123  if (!vg_reg_value && !svg_reg_value)124    return false;125 126  auto regs = reg_info.registers<DynamicRegisterInfo::reg_collection_range>();127  if (vg_reg_value)128    UpdateARM64SVERegistersInfos(regs, *vg_reg_value);129  if (svg_reg_value)130    UpdateARM64SMERegistersInfos(regs, *svg_reg_value);131 132  // At this point if we have updated any registers, their offsets will all be133  // invalid. If we did, we need to update them all.134  reg_info.ConfigureOffsets();135  // From here we are able to read registers again.136 137  // Make a heap based buffer that is big enough to store all registers138  reg_data.SetData(139      std::make_shared<DataBufferHeap>(reg_info.GetRegisterDataByteSize(), 0));140  reg_data.SetByteOrder(reg_context.GetByteOrder());141 142  return true;143}144