LLDB mainline
RegisterContextPOSIXCore_arm64.cpp
Go to the documentation of this file.
1//===-- RegisterContextPOSIXCore_arm64.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
11
13#include "lldb/Target/Thread.h"
15
16#include <memory>
17
18using namespace lldb_private;
19
20std::unique_ptr<RegisterContextCorePOSIX_arm64>
22 const DataExtractor &gpregset,
23 llvm::ArrayRef<CoreNote> notes) {
25
26 DataExtractor sve_data = getRegset(notes, arch.GetTriple(), AARCH64_SVE_Desc);
27 if (sve_data.GetByteSize() > sizeof(sve::user_sve_header))
29
30 // Pointer Authentication register set data is based on struct
31 // user_pac_mask declared in ptrace.h. See reference implementation
32 // in Linux kernel source at arch/arm64/include/uapi/asm/ptrace.h.
33 DataExtractor pac_data = getRegset(notes, arch.GetTriple(), AARCH64_PAC_Desc);
34 if (pac_data.GetByteSize() >= sizeof(uint64_t) * 2)
36
37 auto register_info_up =
38 std::make_unique<RegisterInfoPOSIX_arm64>(arch, opt_regsets);
39 return std::unique_ptr<RegisterContextCorePOSIX_arm64>(
40 new RegisterContextCorePOSIX_arm64(thread, std::move(register_info_up),
41 gpregset, notes));
42}
43
45 Thread &thread, std::unique_ptr<RegisterInfoPOSIX_arm64> register_info,
46 const DataExtractor &gpregset, llvm::ArrayRef<CoreNote> notes)
47 : RegisterContextPOSIX_arm64(thread, std::move(register_info)) {
48 m_gpr_data.SetData(std::make_shared<DataBufferHeap>(gpregset.GetDataStart(),
49 gpregset.GetByteSize()));
51
52 const llvm::Triple &target_triple =
53 m_register_info_up->GetTargetArchitecture().GetTriple();
54 m_fpr_data = getRegset(notes, target_triple, FPR_Desc);
55
56 if (m_register_info_up->IsSVEEnabled())
57 m_sve_data = getRegset(notes, target_triple, AARCH64_SVE_Desc);
58
59 if (m_register_info_up->IsPAuthEnabled())
60 m_pac_data = getRegset(notes, target_triple, AARCH64_PAC_Desc);
61
63}
64
66
68
70
72 assert(0);
73 return false;
74}
75
77 assert(0);
78 return false;
79}
80
81const uint8_t *RegisterContextCorePOSIX_arm64::GetSVEBuffer(uint64_t offset) {
82 return m_sve_data.GetDataStart() + offset;
83}
84
87 uint64_t sve_header_field_offset = 8;
88 m_sve_vector_length = m_sve_data.GetU16(&sve_header_field_offset);
89 sve_header_field_offset = 12;
90 uint16_t sve_header_flags_field =
91 m_sve_data.GetU16(&sve_header_field_offset);
92 if ((sve_header_flags_field & sve::ptrace_regs_mask) ==
94 m_sve_state = SVEState::FPSIMD;
95 else if ((sve_header_flags_field & sve::ptrace_regs_mask) ==
97 m_sve_state = SVEState::Full;
98
100 m_sve_state = SVEState::Disabled;
102 }
103 } else
104 m_sve_state = SVEState::Disabled;
105
106 if (m_sve_state != SVEState::Disabled)
107 m_register_info_up->ConfigureVectorLength(
109}
110
112 const RegisterInfo *reg_info) {
113 // Start of Z0 data is after GPRs plus 8 bytes of vg register
114 uint32_t sve_reg_offset = LLDB_INVALID_INDEX32;
115 if (m_sve_state == SVEState::FPSIMD) {
116 const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
117 sve_reg_offset = sve::ptrace_fpsimd_offset + (reg - GetRegNumSVEZ0()) * 16;
118 } else if (m_sve_state == SVEState::Full) {
119 uint32_t sve_z0_offset = GetGPRSize() + 16;
120 sve_reg_offset =
121 sve::SigRegsOffset() + reg_info->byte_offset - sve_z0_offset;
122 }
123
124 return sve_reg_offset;
125}
126
127bool RegisterContextCorePOSIX_arm64::ReadRegister(const RegisterInfo *reg_info,
128 RegisterValue &value) {
130 lldb::offset_t offset;
131
132 offset = reg_info->byte_offset;
133 if (offset + reg_info->byte_size <= GetGPRSize()) {
134 uint64_t v = m_gpr_data.GetMaxU64(&offset, reg_info->byte_size);
135 if (offset == reg_info->byte_offset + reg_info->byte_size) {
136 value = v;
137 return true;
138 }
139 }
140
141 const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
142 if (reg == LLDB_INVALID_REGNUM)
143 return false;
144
145 if (IsFPR(reg)) {
146 if (m_sve_state == SVEState::Disabled) {
147 // SVE is disabled take legacy route for FPU register access
148 offset -= GetGPRSize();
149 if (offset < m_fpr_data.GetByteSize()) {
150 value.SetFromMemoryData(*reg_info, m_fpr_data.GetDataStart() + offset,
151 reg_info->byte_size, lldb::eByteOrderLittle,
152 error);
153 return error.Success();
154 }
155 } else {
156 // FPSR and FPCR will be located right after Z registers in
157 // SVEState::FPSIMD while in SVEState::Full they will be located at the
158 // end of register data after an alignment correction based on currently
159 // selected vector length.
160 uint32_t sve_reg_num = LLDB_INVALID_REGNUM;
161 if (reg == GetRegNumFPSR()) {
162 sve_reg_num = reg;
163 if (m_sve_state == SVEState::Full)
165 else if (m_sve_state == SVEState::FPSIMD)
166 offset = sve::ptrace_fpsimd_offset + (32 * 16);
167 } else if (reg == GetRegNumFPCR()) {
168 sve_reg_num = reg;
169 if (m_sve_state == SVEState::Full)
171 else if (m_sve_state == SVEState::FPSIMD)
172 offset = sve::ptrace_fpsimd_offset + (32 * 16) + 4;
173 } else {
174 // Extract SVE Z register value register number for this reg_info
175 if (reg_info->value_regs &&
176 reg_info->value_regs[0] != LLDB_INVALID_REGNUM)
177 sve_reg_num = reg_info->value_regs[0];
178 offset = CalculateSVEOffset(GetRegisterInfoAtIndex(sve_reg_num));
179 }
180
181 assert(sve_reg_num != LLDB_INVALID_REGNUM);
182 assert(offset < m_sve_data.GetByteSize());
183 value.SetFromMemoryData(*reg_info, GetSVEBuffer(offset),
184 reg_info->byte_size, lldb::eByteOrderLittle,
185 error);
186 }
187 } else if (IsSVE(reg)) {
188 if (IsSVEVG(reg)) {
189 value = GetSVERegVG();
190 return true;
191 }
192
193 switch (m_sve_state) {
194 case SVEState::FPSIMD: {
195 // In FPSIMD state SVE payload mirrors legacy fpsimd struct and so just
196 // copy 16 bytes of v register to the start of z register. All other
197 // SVE register will be set to zero.
198 uint64_t byte_size = 1;
199 uint8_t zeros = 0;
200 const uint8_t *src = &zeros;
201 if (IsSVEZ(reg)) {
202 byte_size = 16;
203 offset = CalculateSVEOffset(reg_info);
204 assert(offset < m_sve_data.GetByteSize());
205 src = GetSVEBuffer(offset);
206 }
207 value.SetFromMemoryData(*reg_info, src, byte_size, lldb::eByteOrderLittle,
208 error);
209 } break;
210 case SVEState::Full:
211 offset = CalculateSVEOffset(reg_info);
212 assert(offset < m_sve_data.GetByteSize());
213 value.SetFromMemoryData(*reg_info, GetSVEBuffer(offset),
214 reg_info->byte_size, lldb::eByteOrderLittle,
215 error);
216 break;
217 case SVEState::Disabled:
218 default:
219 return false;
220 }
221 } else if (IsPAuth(reg)) {
222 offset = reg_info->byte_offset - m_register_info_up->GetPAuthOffset();
223 assert(offset < m_pac_data.GetByteSize());
224 value.SetFromMemoryData(*reg_info, m_pac_data.GetDataStart() + offset,
225 reg_info->byte_size, lldb::eByteOrderLittle, error);
226 } else
227 return false;
228
229 return error.Success();
230}
231
233 lldb::WritableDataBufferSP &data_sp) {
234 return false;
235}
236
237bool RegisterContextCorePOSIX_arm64::WriteRegister(const RegisterInfo *reg_info,
238 const RegisterValue &value) {
239 return false;
240}
241
243 const lldb::DataBufferSP &data_sp) {
244 return false;
245}
246
248 return false;
249}
static llvm::raw_ostream & error(Stream &strm)
static std::unique_ptr< RegisterContextCorePOSIX_arm64 > Create(lldb_private::Thread &thread, const lldb_private::ArchSpec &arch, const lldb_private::DataExtractor &gpregset, llvm::ArrayRef< lldb_private::CoreNote > notes)
~RegisterContextCorePOSIX_arm64() override
RegisterContextCorePOSIX_arm64(lldb_private::Thread &thread, std::unique_ptr< RegisterInfoPOSIX_arm64 > register_info, const lldb_private::DataExtractor &gpregset, llvm::ArrayRef< lldb_private::CoreNote > notes)
uint32_t CalculateSVEOffset(const lldb_private::RegisterInfo *reg_info)
bool ReadAllRegisterValues(lldb::WritableDataBufferSP &data_sp) override
const uint8_t * GetSVEBuffer(uint64_t offset=0)
bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override
bool WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value) override
bool ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value) override
const lldb_private::RegisterInfo * GetRegisterInfoAtIndex(size_t reg) override
std::unique_ptr< RegisterInfoPOSIX_arm64 > m_register_info_up
bool IsSVEVG(unsigned reg) const
An architecture specification class.
Definition: ArchSpec.h:31
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition: ArchSpec.h:450
An data extractor class.
Definition: DataExtractor.h:48
void SetByteOrder(lldb::ByteOrder byte_order)
Set the byte_order value.
uint64_t GetByteSize() const
Get the number of bytes contained in this object.
uint16_t GetU16(lldb::offset_t *offset_ptr) const
Extract a uint16_t value from *offset_ptr.
const uint8_t * GetDataStart() const
Get the data start pointer.
lldb::offset_t SetData(const void *bytes, lldb::offset_t length, lldb::ByteOrder byte_order)
Set data with a buffer that is caller owned.
uint64_t GetMaxU64(lldb::offset_t *offset_ptr, size_t byte_size) const
Extract an unsigned integer of size byte_size from *offset_ptr.
lldb::ByteOrder GetByteOrder() const
Get the current byte order value.
A class to manage flags.
Definition: Flags.h:22
ValueType Set(ValueType mask)
Set one or more flags by logical OR'ing mask with the current flags.
Definition: Flags.h:73
uint32_t SetFromMemoryData(const RegisterInfo &reg_info, const void *src, uint32_t src_len, lldb::ByteOrder src_byte_order, Status &error)
An error handling class.
Definition: Status.h:44
#define LLDB_INVALID_INDEX32
Definition: lldb-defines.h:75
#define LLDB_INVALID_REGNUM
Definition: lldb-defines.h:79
uint16_t vq_from_vl(uint16_t vl)
uint32_t PTraceFPSROffset(uint16_t vq)
uint32_t PTraceFPCROffset(uint16_t vq)
uint16_t vl_valid(uint16_t vl)
A class that represents a running process on the host machine.
Definition: SBAttachInfo.h:14
DataExtractor getRegset(llvm::ArrayRef< CoreNote > Notes, const llvm::Triple &Triple, llvm::ArrayRef< RegsetDesc > RegsetDescs)
constexpr RegsetDesc FPR_Desc[]
constexpr RegsetDesc AARCH64_SVE_Desc[]
constexpr RegsetDesc AARCH64_PAC_Desc[]
uint64_t offset_t
Definition: lldb-types.h:83
@ eByteOrderLittle
@ eRegisterKindLLDB
lldb's internal register numbers