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 ® : 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 ® : 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 ®_info,76 DataExtractor ®_data,77 RegisterContext ®_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