LLDB mainline
ArchitectureAArch64.cpp
Go to the documentation of this file.
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-exception
6//
7//===----------------------------------------------------------------------===//
8
15
16#include "llvm/Support/Endian.h"
17
18using namespace lldb_private;
19using namespace lldb;
20
22
28
32
33std::unique_ptr<Architecture>
35 auto machine = arch.GetMachine();
36 if (machine != llvm::Triple::aarch64 && machine != llvm::Triple::aarch64_be &&
37 machine != llvm::Triple::aarch64_32) {
38 return nullptr;
39 }
40 return std::unique_ptr<Architecture>(new ArchitectureAArch64());
41}
42
43static void
45 uint64_t vg) {
46 // SVE Z register size is vg x 8 bytes.
47 uint32_t z_reg_byte_size = vg * 8;
48
49 // SVE vector length has changed, accordingly set size of Z, P and FFR
50 // registers. Also invalidate register offsets it will be recalculated
51 // after SVE register size update.
52 for (auto &reg : regs) {
53 if (reg.value_regs == nullptr) {
54 if (reg.name[0] == 'z' && isdigit(reg.name[1]))
55 reg.byte_size = z_reg_byte_size;
56 else if (reg.name[0] == 'p' && isdigit(reg.name[1]))
57 reg.byte_size = vg;
58 else if (strcmp(reg.name, "ffr") == 0)
59 reg.byte_size = vg;
60 }
61 reg.byte_offset = LLDB_INVALID_INDEX32;
62 }
63}
64
65static void
67 uint64_t svg) {
68 for (auto &reg : regs) {
69 if (strcmp(reg.name, "za") == 0) {
70 // ZA is a register with size (svg*8) * (svg*8). A square essentially.
71 reg.byte_size = (svg * 8) * (svg * 8);
72 }
73 reg.byte_offset = LLDB_INVALID_INDEX32;
74 }
75}
76
78 DataExtractor &reg_data,
79 RegisterContext &reg_context
80
81) const {
82 // Once we start to reconfigure registers, we cannot read any of them.
83 // So we must read VG and SVG up front.
84
85 const uint64_t fail_value = LLDB_INVALID_ADDRESS;
86 std::optional<uint64_t> vg_reg_value;
87 const RegisterInfo *vg_reg_info = reg_info.GetRegisterInfo("vg");
88 if (vg_reg_info) {
89 uint32_t vg_reg_num = vg_reg_info->kinds[eRegisterKindLLDB];
90 uint64_t reg_value =
91 reg_context.ReadRegisterAsUnsigned(vg_reg_num, fail_value);
92 if (reg_value != fail_value && reg_value <= 32)
93 vg_reg_value = reg_value;
94 }
95
96 std::optional<uint64_t> svg_reg_value;
97 const RegisterInfo *svg_reg_info = reg_info.GetRegisterInfo("svg");
98 if (svg_reg_info) {
99 uint32_t svg_reg_num = svg_reg_info->kinds[eRegisterKindLLDB];
100 uint64_t reg_value =
101 reg_context.ReadRegisterAsUnsigned(svg_reg_num, fail_value);
102 if (reg_value != fail_value && reg_value <= 32)
103 svg_reg_value = reg_value;
104 }
105 if (!svg_reg_value) {
106 const RegisterInfo *darwin_svg_reg_info = reg_info.GetRegisterInfo("svl");
107 if (darwin_svg_reg_info) {
108 uint32_t svg_reg_num = darwin_svg_reg_info->kinds[eRegisterKindLLDB];
109 uint64_t reg_value =
110 reg_context.ReadRegisterAsUnsigned(svg_reg_num, fail_value);
111 // UpdateARM64SVERegistersInfos and UpdateARM64SMERegistersInfos
112 // expect the number of 8-byte granules; darwin provides number of
113 // bytes.
114 if (reg_value != fail_value && reg_value <= 256) {
115 svg_reg_value = reg_value / 8;
116 // Apple hardware only implements Streaming SVE mode, so
117 // the non-streaming Vector Length is not reported by the
118 // kernel. Set both svg and vg to this svl value.
119 if (!vg_reg_value)
120 vg_reg_value = reg_value / 8;
121 }
122 }
123 }
124
125 if (!vg_reg_value && !svg_reg_value)
126 return false;
127
128 if (!vg_reg_value) {
129 // This must be an SME only system, so VG == SVG.
130 vg_reg_value = svg_reg_value;
131 }
132
134 if (vg_reg_value)
135 UpdateARM64SVERegistersInfos(regs, *vg_reg_value);
136 if (svg_reg_value)
137 UpdateARM64SMERegistersInfos(regs, *svg_reg_value);
138
139 // At this point if we have updated any registers, their offsets will all be
140 // invalid. If we did, we need to update them all.
141 reg_info.ConfigureOffsets();
142 // From here we are able to read registers again.
143
144 // Make a heap based buffer that is big enough to store all registers
145 reg_data.SetData(
146 std::make_shared<DataBufferHeap>(reg_info.GetRegisterDataByteSize(), 0));
147 reg_data.SetByteOrder(reg_context.GetByteOrder());
148
149 return true;
150}
151
153 llvm::ArrayRef<uint8_t> reference, llvm::ArrayRef<uint8_t> observed) const {
154 if (reference.size() < 4 || observed.size() < 4)
155 return false;
156 auto ref_bytes = llvm::support::endian::read32le(reference.data());
157 auto bytes = llvm::support::endian::read32le(observed.data());
158 // Only the 11 highest bits define the breakpoint instruction, the others
159 // include an immediate value that we will explicitly check against.
160 uint32_t mask = 0xFFE00000;
161 // Check that the masked bytes match the reference, but also check that the
162 // immediate in the instruction is the default output by llvm.debugtrap.
163 // The reference has the immediate set as all-zero, so mask and check here.
164 return (ref_bytes == (bytes & mask)) && ((bytes & ~mask) >> 5 == 0xF000);
165}
static void UpdateARM64SMERegistersInfos(DynamicRegisterInfo::reg_collection_range regs, uint64_t svg)
static void UpdateARM64SVERegistersInfos(DynamicRegisterInfo::reg_collection_range regs, uint64_t vg)
#define LLDB_PLUGIN_DEFINE(PluginName)
An architecture specification class.
Definition ArchSpec.h:32
llvm::Triple::ArchType GetMachine() const
Returns a machine family for the current architecture.
Definition ArchSpec.cpp:682
static llvm::StringRef GetPluginNameStatic()
static std::unique_ptr< Architecture > Create(const ArchSpec &arch)
bool ReconfigureRegisterInfo(DynamicRegisterInfo &reg_info, DataExtractor &reg_data, RegisterContext &reg_context) const override
bool IsValidTrapInstruction(llvm::ArrayRef< uint8_t > reference, llvm::ArrayRef< uint8_t > observed) const override
Returns whether a given byte sequence is a valid trap instruction for the architecture.
An data extractor class.
void SetByteOrder(lldb::ByteOrder byte_order)
Set the byte_order value.
virtual lldb::offset_t SetData(const void *bytes, lldb::offset_t length, lldb::ByteOrder byte_order)
Set data with a buffer that is caller owned.
llvm::iterator_range< reg_collection::iterator > reg_collection_range
const lldb_private::RegisterInfo * GetRegisterInfo(uint32_t kind, uint32_t num) const
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ABICreateInstance create_callback)
static bool UnregisterPlugin(ABICreateInstance create_callback)
uint64_t ReadRegisterAsUnsigned(uint32_t reg, uint64_t fail_value)
virtual lldb::ByteOrder GetByteOrder()
#define LLDB_INVALID_INDEX32
#define LLDB_INVALID_ADDRESS
A class that represents a running process on the host machine.
@ eRegisterKindLLDB
lldb's internal register numbers
Every register is described in detail including its name, alternate name (optional),...
uint32_t kinds[lldb::kNumRegisterKinds]
Holds all of the various register numbers for all register kinds.