xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1 //===-- NativeRegisterContextLinux_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 
9 #if defined(__arm64__) || defined(__aarch64__)
10 
11 #include "NativeRegisterContextLinux_arm.h"
12 #include "NativeRegisterContextLinux_arm64.h"
13 
14 #include "lldb/Host/HostInfo.h"
15 #include "lldb/Host/common/NativeProcessProtocol.h"
16 #include "lldb/Host/linux/Ptrace.h"
17 #include "lldb/Utility/DataBufferHeap.h"
18 #include "lldb/Utility/Log.h"
19 #include "lldb/Utility/RegisterValue.h"
20 #include "lldb/Utility/Status.h"
21 
22 #include "Plugins/Process/Linux/NativeProcessLinux.h"
23 #include "Plugins/Process/Linux/Procfs.h"
24 #include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
25 #include "Plugins/Process/Utility/MemoryTagManagerAArch64MTE.h"
26 #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
27 
28 // System includes - They have to be included after framework includes because
29 // they define some macros which collide with variable names in other modules
30 #include <sys/uio.h>
31 // NT_PRSTATUS and NT_FPREGSET definition
32 #include <elf.h>
33 #include <optional>
34 
35 #ifndef NT_ARM_SVE
36 #define NT_ARM_SVE 0x405 /* ARM Scalable Vector Extension */
37 #endif
38 
39 #ifndef NT_ARM_PAC_MASK
40 #define NT_ARM_PAC_MASK 0x406 /* Pointer authentication code masks */
41 #endif
42 
43 #ifndef NT_ARM_TAGGED_ADDR_CTRL
44 #define NT_ARM_TAGGED_ADDR_CTRL 0x409 /* Tagged address control register */
45 #endif
46 
47 #define HWCAP_PACA (1 << 30)
48 #define HWCAP2_MTE (1 << 18)
49 
50 using namespace lldb;
51 using namespace lldb_private;
52 using namespace lldb_private::process_linux;
53 
54 std::unique_ptr<NativeRegisterContextLinux>
CreateHostNativeRegisterContextLinux(const ArchSpec & target_arch,NativeThreadLinux & native_thread)55 NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
56     const ArchSpec &target_arch, NativeThreadLinux &native_thread) {
57   switch (target_arch.GetMachine()) {
58   case llvm::Triple::arm:
59     return std::make_unique<NativeRegisterContextLinux_arm>(target_arch,
60                                                             native_thread);
61   case llvm::Triple::aarch64: {
62     // Configure register sets supported by this AArch64 target.
63     // Read SVE header to check for SVE support.
64     struct user_sve_header sve_header;
65     struct iovec ioVec;
66     ioVec.iov_base = &sve_header;
67     ioVec.iov_len = sizeof(sve_header);
68     unsigned int regset = NT_ARM_SVE;
69 
70     Flags opt_regsets;
71     if (NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET,
72                                           native_thread.GetID(), &regset,
73                                           &ioVec, sizeof(sve_header))
74             .Success())
75       opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskSVE);
76 
77     NativeProcessLinux &process = native_thread.GetProcess();
78 
79     std::optional<uint64_t> auxv_at_hwcap =
80         process.GetAuxValue(AuxVector::AUXV_AT_HWCAP);
81     if (auxv_at_hwcap && (*auxv_at_hwcap & HWCAP_PACA))
82       opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskPAuth);
83 
84     std::optional<uint64_t> auxv_at_hwcap2 =
85         process.GetAuxValue(AuxVector::AUXV_AT_HWCAP2);
86     if (auxv_at_hwcap2 && (*auxv_at_hwcap2 & HWCAP2_MTE))
87       opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskMTE);
88 
89     auto register_info_up =
90         std::make_unique<RegisterInfoPOSIX_arm64>(target_arch, opt_regsets);
91     return std::make_unique<NativeRegisterContextLinux_arm64>(
92         target_arch, native_thread, std::move(register_info_up));
93   }
94   default:
95     llvm_unreachable("have no register context for architecture");
96   }
97 }
98 
99 llvm::Expected<ArchSpec>
DetermineArchitecture(lldb::tid_t tid)100 NativeRegisterContextLinux::DetermineArchitecture(lldb::tid_t tid) {
101   return DetermineArchitectureViaGPR(
102       tid, RegisterInfoPOSIX_arm64::GetGPRSizeStatic());
103 }
104 
NativeRegisterContextLinux_arm64(const ArchSpec & target_arch,NativeThreadProtocol & native_thread,std::unique_ptr<RegisterInfoPOSIX_arm64> register_info_up)105 NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64(
106     const ArchSpec &target_arch, NativeThreadProtocol &native_thread,
107     std::unique_ptr<RegisterInfoPOSIX_arm64> register_info_up)
108     : NativeRegisterContextRegisterInfo(native_thread,
109                                         register_info_up.release()),
110       NativeRegisterContextLinux(native_thread) {
111   ::memset(&m_fpr, 0, sizeof(m_fpr));
112   ::memset(&m_gpr_arm64, 0, sizeof(m_gpr_arm64));
113   ::memset(&m_hwp_regs, 0, sizeof(m_hwp_regs));
114   ::memset(&m_hbp_regs, 0, sizeof(m_hbp_regs));
115   ::memset(&m_sve_header, 0, sizeof(m_sve_header));
116   ::memset(&m_pac_mask, 0, sizeof(m_pac_mask));
117 
118   m_mte_ctrl_reg = 0;
119 
120   // 16 is just a maximum value, query hardware for actual watchpoint count
121   m_max_hwp_supported = 16;
122   m_max_hbp_supported = 16;
123 
124   m_refresh_hwdebug_info = true;
125 
126   m_gpr_is_valid = false;
127   m_fpu_is_valid = false;
128   m_sve_buffer_is_valid = false;
129   m_sve_header_is_valid = false;
130   m_pac_mask_is_valid = false;
131   m_mte_ctrl_is_valid = false;
132 
133   if (GetRegisterInfo().IsSVEEnabled())
134     m_sve_state = SVEState::Unknown;
135   else
136     m_sve_state = SVEState::Disabled;
137 }
138 
139 RegisterInfoPOSIX_arm64 &
GetRegisterInfo() const140 NativeRegisterContextLinux_arm64::GetRegisterInfo() const {
141   return static_cast<RegisterInfoPOSIX_arm64 &>(*m_register_info_interface_up);
142 }
143 
GetRegisterSetCount() const144 uint32_t NativeRegisterContextLinux_arm64::GetRegisterSetCount() const {
145   return GetRegisterInfo().GetRegisterSetCount();
146 }
147 
148 const RegisterSet *
GetRegisterSet(uint32_t set_index) const149 NativeRegisterContextLinux_arm64::GetRegisterSet(uint32_t set_index) const {
150   return GetRegisterInfo().GetRegisterSet(set_index);
151 }
152 
GetUserRegisterCount() const153 uint32_t NativeRegisterContextLinux_arm64::GetUserRegisterCount() const {
154   uint32_t count = 0;
155   for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index)
156     count += GetRegisterSet(set_index)->num_registers;
157   return count;
158 }
159 
160 Status
ReadRegister(const RegisterInfo * reg_info,RegisterValue & reg_value)161 NativeRegisterContextLinux_arm64::ReadRegister(const RegisterInfo *reg_info,
162                                                RegisterValue &reg_value) {
163   Status error;
164 
165   if (!reg_info) {
166     error.SetErrorString("reg_info NULL");
167     return error;
168   }
169 
170   const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
171 
172   if (reg == LLDB_INVALID_REGNUM)
173     return Status("no lldb regnum for %s", reg_info && reg_info->name
174                                                ? reg_info->name
175                                                : "<unknown register>");
176 
177   uint8_t *src;
178   uint32_t offset = LLDB_INVALID_INDEX32;
179   uint64_t sve_vg;
180   std::vector<uint8_t> sve_reg_non_live;
181 
182   if (IsGPR(reg)) {
183     error = ReadGPR();
184     if (error.Fail())
185       return error;
186 
187     offset = reg_info->byte_offset;
188     assert(offset < GetGPRSize());
189     src = (uint8_t *)GetGPRBuffer() + offset;
190 
191   } else if (IsFPR(reg)) {
192     if (m_sve_state == SVEState::Disabled) {
193       // SVE is disabled take legacy route for FPU register access
194       error = ReadFPR();
195       if (error.Fail())
196         return error;
197 
198       offset = CalculateFprOffset(reg_info);
199       assert(offset < GetFPRSize());
200       src = (uint8_t *)GetFPRBuffer() + offset;
201     } else {
202       // SVE enabled, we will read and cache SVE ptrace data
203       error = ReadAllSVE();
204       if (error.Fail())
205         return error;
206 
207       // FPSR and FPCR will be located right after Z registers in
208       // SVEState::FPSIMD while in SVEState::Full they will be located at the
209       // end of register data after an alignment correction based on currently
210       // selected vector length.
211       uint32_t sve_reg_num = LLDB_INVALID_REGNUM;
212       if (reg == GetRegisterInfo().GetRegNumFPSR()) {
213         sve_reg_num = reg;
214         if (m_sve_state == SVEState::Full)
215           offset = sve::PTraceFPSROffset(sve::vq_from_vl(m_sve_header.vl));
216         else if (m_sve_state == SVEState::FPSIMD)
217           offset = sve::ptrace_fpsimd_offset + (32 * 16);
218       } else if (reg == GetRegisterInfo().GetRegNumFPCR()) {
219         sve_reg_num = reg;
220         if (m_sve_state == SVEState::Full)
221           offset = sve::PTraceFPCROffset(sve::vq_from_vl(m_sve_header.vl));
222         else if (m_sve_state == SVEState::FPSIMD)
223           offset = sve::ptrace_fpsimd_offset + (32 * 16) + 4;
224       } else {
225         // Extract SVE Z register value register number for this reg_info
226         if (reg_info->value_regs &&
227             reg_info->value_regs[0] != LLDB_INVALID_REGNUM)
228           sve_reg_num = reg_info->value_regs[0];
229         offset = CalculateSVEOffset(GetRegisterInfoAtIndex(sve_reg_num));
230       }
231 
232       assert(offset < GetSVEBufferSize());
233       src = (uint8_t *)GetSVEBuffer() + offset;
234     }
235   } else if (IsSVE(reg)) {
236 
237     if (m_sve_state == SVEState::Disabled || m_sve_state == SVEState::Unknown)
238       return Status("SVE disabled or not supported");
239 
240     if (GetRegisterInfo().IsSVERegVG(reg)) {
241       sve_vg = GetSVERegVG();
242       src = (uint8_t *)&sve_vg;
243     } else {
244       // SVE enabled, we will read and cache SVE ptrace data
245       error = ReadAllSVE();
246       if (error.Fail())
247         return error;
248 
249       if (m_sve_state == SVEState::FPSIMD) {
250         // In FPSIMD state SVE payload mirrors legacy fpsimd struct and so
251         // just copy 16 bytes of v register to the start of z register. All
252         // other SVE register will be set to zero.
253         sve_reg_non_live.resize(reg_info->byte_size, 0);
254         src = sve_reg_non_live.data();
255 
256         if (GetRegisterInfo().IsSVEZReg(reg)) {
257           offset = CalculateSVEOffset(reg_info);
258           assert(offset < GetSVEBufferSize());
259           ::memcpy(sve_reg_non_live.data(), (uint8_t *)GetSVEBuffer() + offset,
260                    16);
261         }
262       } else {
263         offset = CalculateSVEOffset(reg_info);
264         assert(offset < GetSVEBufferSize());
265         src = (uint8_t *)GetSVEBuffer() + offset;
266       }
267     }
268   } else if (IsPAuth(reg)) {
269     error = ReadPAuthMask();
270     if (error.Fail())
271       return error;
272 
273     offset = reg_info->byte_offset - GetRegisterInfo().GetPAuthOffset();
274     assert(offset < GetPACMaskSize());
275     src = (uint8_t *)GetPACMask() + offset;
276   } else if (IsMTE(reg)) {
277     error = ReadMTEControl();
278     if (error.Fail())
279       return error;
280 
281     offset = reg_info->byte_offset - GetRegisterInfo().GetMTEOffset();
282     assert(offset < GetMTEControlSize());
283     src = (uint8_t *)GetMTEControl() + offset;
284   } else
285     return Status("failed - register wasn't recognized to be a GPR or an FPR, "
286                   "write strategy unknown");
287 
288   reg_value.SetFromMemoryData(*reg_info, src, reg_info->byte_size,
289                               eByteOrderLittle, error);
290 
291   return error;
292 }
293 
WriteRegister(const RegisterInfo * reg_info,const RegisterValue & reg_value)294 Status NativeRegisterContextLinux_arm64::WriteRegister(
295     const RegisterInfo *reg_info, const RegisterValue &reg_value) {
296   Status error;
297 
298   if (!reg_info)
299     return Status("reg_info NULL");
300 
301   const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
302 
303   if (reg == LLDB_INVALID_REGNUM)
304     return Status("no lldb regnum for %s", reg_info && reg_info->name
305                                                ? reg_info->name
306                                                : "<unknown register>");
307 
308   uint8_t *dst;
309   uint32_t offset = LLDB_INVALID_INDEX32;
310   std::vector<uint8_t> sve_reg_non_live;
311 
312   if (IsGPR(reg)) {
313     error = ReadGPR();
314     if (error.Fail())
315       return error;
316 
317     assert(reg_info->byte_offset < GetGPRSize());
318     dst = (uint8_t *)GetGPRBuffer() + reg_info->byte_offset;
319     ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size);
320 
321     return WriteGPR();
322   } else if (IsFPR(reg)) {
323     if (m_sve_state == SVEState::Disabled) {
324       // SVE is disabled take legacy route for FPU register access
325       error = ReadFPR();
326       if (error.Fail())
327         return error;
328 
329       offset = CalculateFprOffset(reg_info);
330       assert(offset < GetFPRSize());
331       dst = (uint8_t *)GetFPRBuffer() + offset;
332       ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size);
333 
334       return WriteFPR();
335     } else {
336       // SVE enabled, we will read and cache SVE ptrace data
337       error = ReadAllSVE();
338       if (error.Fail())
339         return error;
340 
341       // FPSR and FPCR will be located right after Z registers in
342       // SVEState::FPSIMD while in SVEState::Full they will be located at the
343       // end of register data after an alignment correction based on currently
344       // selected vector length.
345       uint32_t sve_reg_num = LLDB_INVALID_REGNUM;
346       if (reg == GetRegisterInfo().GetRegNumFPSR()) {
347         sve_reg_num = reg;
348         if (m_sve_state == SVEState::Full)
349           offset = sve::PTraceFPSROffset(sve::vq_from_vl(m_sve_header.vl));
350         else if (m_sve_state == SVEState::FPSIMD)
351           offset = sve::ptrace_fpsimd_offset + (32 * 16);
352       } else if (reg == GetRegisterInfo().GetRegNumFPCR()) {
353         sve_reg_num = reg;
354         if (m_sve_state == SVEState::Full)
355           offset = sve::PTraceFPCROffset(sve::vq_from_vl(m_sve_header.vl));
356         else if (m_sve_state == SVEState::FPSIMD)
357           offset = sve::ptrace_fpsimd_offset + (32 * 16) + 4;
358       } else {
359         // Extract SVE Z register value register number for this reg_info
360         if (reg_info->value_regs &&
361             reg_info->value_regs[0] != LLDB_INVALID_REGNUM)
362           sve_reg_num = reg_info->value_regs[0];
363         offset = CalculateSVEOffset(GetRegisterInfoAtIndex(sve_reg_num));
364       }
365 
366       assert(offset < GetSVEBufferSize());
367       dst = (uint8_t *)GetSVEBuffer() + offset;
368       ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size);
369       return WriteAllSVE();
370     }
371   } else if (IsSVE(reg)) {
372     if (m_sve_state == SVEState::Disabled || m_sve_state == SVEState::Unknown)
373       return Status("SVE disabled or not supported");
374     else {
375       // Target has SVE enabled, we will read and cache SVE ptrace data
376       error = ReadAllSVE();
377       if (error.Fail())
378         return error;
379 
380       if (GetRegisterInfo().IsSVERegVG(reg)) {
381         uint64_t vg_value = reg_value.GetAsUInt64();
382 
383         if (sve_vl_valid(vg_value * 8)) {
384           if (m_sve_header_is_valid && vg_value == GetSVERegVG())
385             return error;
386 
387           SetSVERegVG(vg_value);
388 
389           error = WriteSVEHeader();
390           if (error.Success())
391             ConfigureRegisterContext();
392 
393           if (m_sve_header_is_valid && vg_value == GetSVERegVG())
394             return error;
395         }
396 
397         return Status("SVE vector length update failed.");
398       }
399 
400       // If target supports SVE but currently in FPSIMD mode.
401       if (m_sve_state == SVEState::FPSIMD) {
402         // Here we will check if writing this SVE register enables
403         // SVEState::Full
404         bool set_sve_state_full = false;
405         const uint8_t *reg_bytes = (const uint8_t *)reg_value.GetBytes();
406         if (GetRegisterInfo().IsSVEZReg(reg)) {
407           for (uint32_t i = 16; i < reg_info->byte_size; i++) {
408             if (reg_bytes[i]) {
409               set_sve_state_full = true;
410               break;
411             }
412           }
413         } else if (GetRegisterInfo().IsSVEPReg(reg) ||
414                    reg == GetRegisterInfo().GetRegNumSVEFFR()) {
415           for (uint32_t i = 0; i < reg_info->byte_size; i++) {
416             if (reg_bytes[i]) {
417               set_sve_state_full = true;
418               break;
419             }
420           }
421         }
422 
423         if (!set_sve_state_full && GetRegisterInfo().IsSVEZReg(reg)) {
424           // We are writing a Z register which is zero beyond 16 bytes so copy
425           // first 16 bytes only as SVE payload mirrors legacy fpsimd structure
426           offset = CalculateSVEOffset(reg_info);
427           assert(offset < GetSVEBufferSize());
428           dst = (uint8_t *)GetSVEBuffer() + offset;
429           ::memcpy(dst, reg_value.GetBytes(), 16);
430 
431           return WriteAllSVE();
432         } else
433           return Status("SVE state change operation not supported");
434       } else {
435         offset = CalculateSVEOffset(reg_info);
436         assert(offset < GetSVEBufferSize());
437         dst = (uint8_t *)GetSVEBuffer() + offset;
438         ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size);
439         return WriteAllSVE();
440       }
441     }
442   } else if (IsMTE(reg)) {
443     error = ReadMTEControl();
444     if (error.Fail())
445       return error;
446 
447     offset = reg_info->byte_offset - GetRegisterInfo().GetMTEOffset();
448     assert(offset < GetMTEControlSize());
449     dst = (uint8_t *)GetMTEControl() + offset;
450     ::memcpy(dst, reg_value.GetBytes(), reg_info->byte_size);
451 
452     return WriteMTEControl();
453   }
454 
455   return Status("Failed to write register value");
456 }
457 
ReadAllRegisterValues(lldb::WritableDataBufferSP & data_sp)458 Status NativeRegisterContextLinux_arm64::ReadAllRegisterValues(
459     lldb::WritableDataBufferSP &data_sp) {
460   // AArch64 register data must contain GPRs, either FPR or SVE registers
461   // and optional MTE register. Pointer Authentication (PAC) registers are
462   // read-only and will be skiped.
463 
464   // In order to create register data checkpoint we first read all register
465   // values if not done already and calculate total size of register set data.
466   // We store all register values in data_sp by copying full PTrace data that
467   // corresponds to register sets enabled by current register context.
468 
469   Status error;
470   uint32_t reg_data_byte_size = GetGPRBufferSize();
471   error = ReadGPR();
472   if (error.Fail())
473     return error;
474 
475   // If SVE is enabled we need not copy FPR separately.
476   if (GetRegisterInfo().IsSVEEnabled()) {
477     reg_data_byte_size += GetSVEBufferSize();
478     error = ReadAllSVE();
479   } else {
480     reg_data_byte_size += GetFPRSize();
481     error = ReadFPR();
482   }
483   if (error.Fail())
484     return error;
485 
486   if (GetRegisterInfo().IsMTEEnabled()) {
487     reg_data_byte_size += GetMTEControlSize();
488     error = ReadMTEControl();
489     if (error.Fail())
490       return error;
491   }
492 
493   data_sp.reset(new DataBufferHeap(reg_data_byte_size, 0));
494   uint8_t *dst = data_sp->GetBytes();
495 
496   ::memcpy(dst, GetGPRBuffer(), GetGPRBufferSize());
497   dst += GetGPRBufferSize();
498 
499   if (GetRegisterInfo().IsSVEEnabled()) {
500     ::memcpy(dst, GetSVEBuffer(), GetSVEBufferSize());
501     dst += GetSVEBufferSize();
502   } else {
503     ::memcpy(dst, GetFPRBuffer(), GetFPRSize());
504     dst += GetFPRSize();
505   }
506 
507   if (GetRegisterInfo().IsMTEEnabled())
508     ::memcpy(dst, GetMTEControl(), GetMTEControlSize());
509 
510   return error;
511 }
512 
WriteAllRegisterValues(const lldb::DataBufferSP & data_sp)513 Status NativeRegisterContextLinux_arm64::WriteAllRegisterValues(
514     const lldb::DataBufferSP &data_sp) {
515   // AArch64 register data must contain GPRs, either FPR or SVE registers
516   // and optional MTE register. Pointer Authentication (PAC) registers are
517   // read-only and will be skiped.
518 
519   // We store all register values in data_sp by copying full PTrace data that
520   // corresponds to register sets enabled by current register context. In order
521   // to restore from register data checkpoint we will first restore GPRs, based
522   // on size of remaining register data either SVE or FPRs should be restored
523   // next. SVE is not enabled if we have register data size less than or equal
524   // to size of GPR + FPR + MTE.
525 
526   Status error;
527   if (!data_sp) {
528     error.SetErrorStringWithFormat(
529         "NativeRegisterContextLinux_arm64::%s invalid data_sp provided",
530         __FUNCTION__);
531     return error;
532   }
533 
534   const uint8_t *src = data_sp->GetBytes();
535   if (src == nullptr) {
536     error.SetErrorStringWithFormat("NativeRegisterContextLinux_arm64::%s "
537                                    "DataBuffer::GetBytes() returned a null "
538                                    "pointer",
539                                    __FUNCTION__);
540     return error;
541   }
542 
543   uint64_t reg_data_min_size = GetGPRBufferSize() + GetFPRSize();
544   if (data_sp->GetByteSize() < reg_data_min_size) {
545     error.SetErrorStringWithFormat(
546         "NativeRegisterContextLinux_arm64::%s data_sp contained insufficient "
547         "register data bytes, expected at least %" PRIu64 ", actual %" PRIu64,
548         __FUNCTION__, reg_data_min_size, data_sp->GetByteSize());
549     return error;
550   }
551 
552   // Register data starts with GPRs
553   ::memcpy(GetGPRBuffer(), src, GetGPRBufferSize());
554   m_gpr_is_valid = true;
555 
556   error = WriteGPR();
557   if (error.Fail())
558     return error;
559 
560   src += GetGPRBufferSize();
561 
562   // Verify if register data may contain SVE register values.
563   bool contains_sve_reg_data =
564       (data_sp->GetByteSize() > (reg_data_min_size + GetSVEHeaderSize()));
565 
566   if (contains_sve_reg_data) {
567     // We have SVE register data first write SVE header.
568     ::memcpy(GetSVEHeader(), src, GetSVEHeaderSize());
569     if (!sve_vl_valid(m_sve_header.vl)) {
570       m_sve_header_is_valid = false;
571       error.SetErrorStringWithFormat("NativeRegisterContextLinux_arm64::%s "
572                                      "Invalid SVE header in data_sp",
573                                      __FUNCTION__);
574       return error;
575     }
576     m_sve_header_is_valid = true;
577     error = WriteSVEHeader();
578     if (error.Fail())
579       return error;
580 
581     // SVE header has been written configure SVE vector length if needed.
582     ConfigureRegisterContext();
583 
584     // Make sure data_sp contains sufficient data to write all SVE registers.
585     reg_data_min_size = GetGPRBufferSize() + GetSVEBufferSize();
586     if (data_sp->GetByteSize() < reg_data_min_size) {
587       error.SetErrorStringWithFormat(
588           "NativeRegisterContextLinux_arm64::%s data_sp contained insufficient "
589           "register data bytes, expected %" PRIu64 ", actual %" PRIu64,
590           __FUNCTION__, reg_data_min_size, data_sp->GetByteSize());
591       return error;
592     }
593 
594     ::memcpy(GetSVEBuffer(), src, GetSVEBufferSize());
595     m_sve_buffer_is_valid = true;
596     error = WriteAllSVE();
597     src += GetSVEBufferSize();
598   } else {
599     ::memcpy(GetFPRBuffer(), src, GetFPRSize());
600     m_fpu_is_valid = true;
601     error = WriteFPR();
602     src += GetFPRSize();
603   }
604 
605   if (error.Fail())
606     return error;
607 
608   if (GetRegisterInfo().IsMTEEnabled() &&
609       data_sp->GetByteSize() > reg_data_min_size) {
610     ::memcpy(GetMTEControl(), src, GetMTEControlSize());
611     m_mte_ctrl_is_valid = true;
612     error = WriteMTEControl();
613   }
614 
615   return error;
616 }
617 
IsGPR(unsigned reg) const618 bool NativeRegisterContextLinux_arm64::IsGPR(unsigned reg) const {
619   if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) ==
620       RegisterInfoPOSIX_arm64::GPRegSet)
621     return true;
622   return false;
623 }
624 
IsFPR(unsigned reg) const625 bool NativeRegisterContextLinux_arm64::IsFPR(unsigned reg) const {
626   if (GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) ==
627       RegisterInfoPOSIX_arm64::FPRegSet)
628     return true;
629   return false;
630 }
631 
IsSVE(unsigned reg) const632 bool NativeRegisterContextLinux_arm64::IsSVE(unsigned reg) const {
633   return GetRegisterInfo().IsSVEReg(reg);
634 }
635 
IsPAuth(unsigned reg) const636 bool NativeRegisterContextLinux_arm64::IsPAuth(unsigned reg) const {
637   return GetRegisterInfo().IsPAuthReg(reg);
638 }
639 
IsMTE(unsigned reg) const640 bool NativeRegisterContextLinux_arm64::IsMTE(unsigned reg) const {
641   return GetRegisterInfo().IsMTEReg(reg);
642 }
643 
ReadHardwareDebugInfo()644 llvm::Error NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo() {
645   if (!m_refresh_hwdebug_info) {
646     return llvm::Error::success();
647   }
648 
649   ::pid_t tid = m_thread.GetID();
650 
651   int regset = NT_ARM_HW_WATCH;
652   struct iovec ioVec;
653   struct user_hwdebug_state dreg_state;
654   Status error;
655 
656   ioVec.iov_base = &dreg_state;
657   ioVec.iov_len = sizeof(dreg_state);
658   error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, &regset,
659                                             &ioVec, ioVec.iov_len);
660 
661   if (error.Fail())
662     return error.ToError();
663 
664   m_max_hwp_supported = dreg_state.dbg_info & 0xff;
665 
666   regset = NT_ARM_HW_BREAK;
667   error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, &regset,
668                                             &ioVec, ioVec.iov_len);
669 
670   if (error.Fail())
671     return error.ToError();
672 
673   m_max_hbp_supported = dreg_state.dbg_info & 0xff;
674   m_refresh_hwdebug_info = false;
675 
676   return llvm::Error::success();
677 }
678 
679 llvm::Error
WriteHardwareDebugRegs(DREGType hwbType)680 NativeRegisterContextLinux_arm64::WriteHardwareDebugRegs(DREGType hwbType) {
681   struct iovec ioVec;
682   struct user_hwdebug_state dreg_state;
683   int regset;
684 
685   memset(&dreg_state, 0, sizeof(dreg_state));
686   ioVec.iov_base = &dreg_state;
687 
688   switch (hwbType) {
689   case eDREGTypeWATCH:
690     regset = NT_ARM_HW_WATCH;
691     ioVec.iov_len = sizeof(dreg_state.dbg_info) + sizeof(dreg_state.pad) +
692                     (sizeof(dreg_state.dbg_regs[0]) * m_max_hwp_supported);
693 
694     for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
695       dreg_state.dbg_regs[i].addr = m_hwp_regs[i].address;
696       dreg_state.dbg_regs[i].ctrl = m_hwp_regs[i].control;
697     }
698     break;
699   case eDREGTypeBREAK:
700     regset = NT_ARM_HW_BREAK;
701     ioVec.iov_len = sizeof(dreg_state.dbg_info) + sizeof(dreg_state.pad) +
702                     (sizeof(dreg_state.dbg_regs[0]) * m_max_hbp_supported);
703 
704     for (uint32_t i = 0; i < m_max_hbp_supported; i++) {
705       dreg_state.dbg_regs[i].addr = m_hbp_regs[i].address;
706       dreg_state.dbg_regs[i].ctrl = m_hbp_regs[i].control;
707     }
708     break;
709   }
710 
711   return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(),
712                                            &regset, &ioVec, ioVec.iov_len)
713       .ToError();
714 }
715 
ReadGPR()716 Status NativeRegisterContextLinux_arm64::ReadGPR() {
717   Status error;
718 
719   if (m_gpr_is_valid)
720     return error;
721 
722   struct iovec ioVec;
723   ioVec.iov_base = GetGPRBuffer();
724   ioVec.iov_len = GetGPRBufferSize();
725 
726   error = ReadRegisterSet(&ioVec, GetGPRBufferSize(), NT_PRSTATUS);
727 
728   if (error.Success())
729     m_gpr_is_valid = true;
730 
731   return error;
732 }
733 
WriteGPR()734 Status NativeRegisterContextLinux_arm64::WriteGPR() {
735   Status error = ReadGPR();
736   if (error.Fail())
737     return error;
738 
739   struct iovec ioVec;
740   ioVec.iov_base = GetGPRBuffer();
741   ioVec.iov_len = GetGPRBufferSize();
742 
743   m_gpr_is_valid = false;
744 
745   return WriteRegisterSet(&ioVec, GetGPRBufferSize(), NT_PRSTATUS);
746 }
747 
ReadFPR()748 Status NativeRegisterContextLinux_arm64::ReadFPR() {
749   Status error;
750 
751   if (m_fpu_is_valid)
752     return error;
753 
754   struct iovec ioVec;
755   ioVec.iov_base = GetFPRBuffer();
756   ioVec.iov_len = GetFPRSize();
757 
758   error = ReadRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET);
759 
760   if (error.Success())
761     m_fpu_is_valid = true;
762 
763   return error;
764 }
765 
WriteFPR()766 Status NativeRegisterContextLinux_arm64::WriteFPR() {
767   Status error = ReadFPR();
768   if (error.Fail())
769     return error;
770 
771   struct iovec ioVec;
772   ioVec.iov_base = GetFPRBuffer();
773   ioVec.iov_len = GetFPRSize();
774 
775   m_fpu_is_valid = false;
776 
777   return WriteRegisterSet(&ioVec, GetFPRSize(), NT_FPREGSET);
778 }
779 
InvalidateAllRegisters()780 void NativeRegisterContextLinux_arm64::InvalidateAllRegisters() {
781   m_gpr_is_valid = false;
782   m_fpu_is_valid = false;
783   m_sve_buffer_is_valid = false;
784   m_sve_header_is_valid = false;
785   m_pac_mask_is_valid = false;
786   m_mte_ctrl_is_valid = false;
787 
788   // Update SVE registers in case there is change in configuration.
789   ConfigureRegisterContext();
790 }
791 
ReadSVEHeader()792 Status NativeRegisterContextLinux_arm64::ReadSVEHeader() {
793   Status error;
794 
795   if (m_sve_header_is_valid)
796     return error;
797 
798   struct iovec ioVec;
799   ioVec.iov_base = GetSVEHeader();
800   ioVec.iov_len = GetSVEHeaderSize();
801 
802   error = ReadRegisterSet(&ioVec, GetSVEHeaderSize(), NT_ARM_SVE);
803 
804   if (error.Success())
805     m_sve_header_is_valid = true;
806 
807   return error;
808 }
809 
ReadPAuthMask()810 Status NativeRegisterContextLinux_arm64::ReadPAuthMask() {
811   Status error;
812 
813   if (m_pac_mask_is_valid)
814     return error;
815 
816   struct iovec ioVec;
817   ioVec.iov_base = GetPACMask();
818   ioVec.iov_len = GetPACMaskSize();
819 
820   error = ReadRegisterSet(&ioVec, GetPACMaskSize(), NT_ARM_PAC_MASK);
821 
822   if (error.Success())
823     m_pac_mask_is_valid = true;
824 
825   return error;
826 }
827 
WriteSVEHeader()828 Status NativeRegisterContextLinux_arm64::WriteSVEHeader() {
829   Status error;
830 
831   error = ReadSVEHeader();
832   if (error.Fail())
833     return error;
834 
835   struct iovec ioVec;
836   ioVec.iov_base = GetSVEHeader();
837   ioVec.iov_len = GetSVEHeaderSize();
838 
839   m_sve_buffer_is_valid = false;
840   m_sve_header_is_valid = false;
841   m_fpu_is_valid = false;
842 
843   return WriteRegisterSet(&ioVec, GetSVEHeaderSize(), NT_ARM_SVE);
844 }
845 
ReadAllSVE()846 Status NativeRegisterContextLinux_arm64::ReadAllSVE() {
847   Status error;
848 
849   if (m_sve_buffer_is_valid)
850     return error;
851 
852   struct iovec ioVec;
853   ioVec.iov_base = GetSVEBuffer();
854   ioVec.iov_len = GetSVEBufferSize();
855 
856   error = ReadRegisterSet(&ioVec, GetSVEBufferSize(), NT_ARM_SVE);
857 
858   if (error.Success())
859     m_sve_buffer_is_valid = true;
860 
861   return error;
862 }
863 
WriteAllSVE()864 Status NativeRegisterContextLinux_arm64::WriteAllSVE() {
865   Status error;
866 
867   error = ReadAllSVE();
868   if (error.Fail())
869     return error;
870 
871   struct iovec ioVec;
872 
873   ioVec.iov_base = GetSVEBuffer();
874   ioVec.iov_len = GetSVEBufferSize();
875 
876   m_sve_buffer_is_valid = false;
877   m_sve_header_is_valid = false;
878   m_fpu_is_valid = false;
879 
880   return WriteRegisterSet(&ioVec, GetSVEBufferSize(), NT_ARM_SVE);
881 }
882 
ReadMTEControl()883 Status NativeRegisterContextLinux_arm64::ReadMTEControl() {
884   Status error;
885 
886   if (m_mte_ctrl_is_valid)
887     return error;
888 
889   struct iovec ioVec;
890   ioVec.iov_base = GetMTEControl();
891   ioVec.iov_len = GetMTEControlSize();
892 
893   error = ReadRegisterSet(&ioVec, GetMTEControlSize(), NT_ARM_TAGGED_ADDR_CTRL);
894 
895   if (error.Success())
896     m_mte_ctrl_is_valid = true;
897 
898   return error;
899 }
900 
WriteMTEControl()901 Status NativeRegisterContextLinux_arm64::WriteMTEControl() {
902   Status error;
903 
904   error = ReadMTEControl();
905   if (error.Fail())
906     return error;
907 
908   struct iovec ioVec;
909   ioVec.iov_base = GetMTEControl();
910   ioVec.iov_len = GetMTEControlSize();
911 
912   m_mte_ctrl_is_valid = false;
913 
914   return WriteRegisterSet(&ioVec, GetMTEControlSize(), NT_ARM_TAGGED_ADDR_CTRL);
915 }
916 
ConfigureRegisterContext()917 void NativeRegisterContextLinux_arm64::ConfigureRegisterContext() {
918   // ConfigureRegisterContext gets called from InvalidateAllRegisters
919   // on every stop and configures SVE vector length.
920   // If m_sve_state is set to SVEState::Disabled on first stop, code below will
921   // be deemed non operational for the lifetime of current process.
922   if (!m_sve_header_is_valid && m_sve_state != SVEState::Disabled) {
923     Status error = ReadSVEHeader();
924     if (error.Success()) {
925       // If SVE is enabled thread can switch between SVEState::FPSIMD and
926       // SVEState::Full on every stop.
927       if ((m_sve_header.flags & sve::ptrace_regs_mask) ==
928           sve::ptrace_regs_fpsimd)
929         m_sve_state = SVEState::FPSIMD;
930       else if ((m_sve_header.flags & sve::ptrace_regs_mask) ==
931                sve::ptrace_regs_sve)
932         m_sve_state = SVEState::Full;
933 
934       // On every stop we configure SVE vector length by calling
935       // ConfigureVectorLength regardless of current SVEState of this thread.
936       uint32_t vq = RegisterInfoPOSIX_arm64::eVectorQuadwordAArch64SVE;
937       if (sve_vl_valid(m_sve_header.vl))
938         vq = sve::vq_from_vl(m_sve_header.vl);
939 
940       GetRegisterInfo().ConfigureVectorLength(vq);
941       m_sve_ptrace_payload.resize(sve::PTraceSize(vq, sve::ptrace_regs_sve));
942     }
943   }
944 }
945 
CalculateFprOffset(const RegisterInfo * reg_info) const946 uint32_t NativeRegisterContextLinux_arm64::CalculateFprOffset(
947     const RegisterInfo *reg_info) const {
948   return reg_info->byte_offset - GetGPRSize();
949 }
950 
CalculateSVEOffset(const RegisterInfo * reg_info) const951 uint32_t NativeRegisterContextLinux_arm64::CalculateSVEOffset(
952     const RegisterInfo *reg_info) const {
953   // Start of Z0 data is after GPRs plus 8 bytes of vg register
954   uint32_t sve_reg_offset = LLDB_INVALID_INDEX32;
955   if (m_sve_state == SVEState::FPSIMD) {
956     const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
957     sve_reg_offset = sve::ptrace_fpsimd_offset +
958                      (reg - GetRegisterInfo().GetRegNumSVEZ0()) * 16;
959   } else if (m_sve_state == SVEState::Full) {
960     uint32_t sve_z0_offset = GetGPRSize() + 16;
961     sve_reg_offset =
962         sve::SigRegsOffset() + reg_info->byte_offset - sve_z0_offset;
963   }
964   return sve_reg_offset;
965 }
966 
GetExpeditedRegisters(ExpeditedRegs expType) const967 std::vector<uint32_t> NativeRegisterContextLinux_arm64::GetExpeditedRegisters(
968     ExpeditedRegs expType) const {
969   std::vector<uint32_t> expedited_reg_nums =
970       NativeRegisterContext::GetExpeditedRegisters(expType);
971   if (m_sve_state == SVEState::FPSIMD || m_sve_state == SVEState::Full)
972     expedited_reg_nums.push_back(GetRegisterInfo().GetRegNumSVEVG());
973 
974   return expedited_reg_nums;
975 }
976 
977 llvm::Expected<NativeRegisterContextLinux::MemoryTaggingDetails>
GetMemoryTaggingDetails(int32_t type)978 NativeRegisterContextLinux_arm64::GetMemoryTaggingDetails(int32_t type) {
979   if (type == MemoryTagManagerAArch64MTE::eMTE_allocation) {
980     return MemoryTaggingDetails{std::make_unique<MemoryTagManagerAArch64MTE>(),
981                                 PTRACE_PEEKMTETAGS, PTRACE_POKEMTETAGS};
982   }
983 
984   return llvm::createStringError(llvm::inconvertibleErrorCode(),
985                                  "Unknown AArch64 memory tag type %d", type);
986 }
987 
FixWatchpointHitAddress(lldb::addr_t hit_addr)988 lldb::addr_t NativeRegisterContextLinux_arm64::FixWatchpointHitAddress(
989     lldb::addr_t hit_addr) {
990   // Linux configures user-space virtual addresses with top byte ignored.
991   // We set default value of mask such that top byte is masked out.
992   lldb::addr_t mask = ~((1ULL << 56) - 1);
993 
994   // Try to read pointer authentication data_mask register and calculate a
995   // consolidated data address mask after ignoring the top byte.
996   if (ReadPAuthMask().Success())
997     mask |= m_pac_mask.data_mask;
998 
999   return hit_addr & ~mask;
1000   ;
1001 }
1002 
1003 #endif // defined (__arm64__) || defined (__aarch64__)
1004