1061da546Spatrick //===-- NativeRegisterContextOpenBSD_arm64.cpp ---------------*- C++ -*-===//
2061da546Spatrick //
3061da546Spatrick // The LLVM Compiler Infrastructure
4061da546Spatrick //
5061da546Spatrick // This file is distributed under the University of Illinois Open Source
6061da546Spatrick // License. See LICENSE.TXT for details.
7061da546Spatrick //
8061da546Spatrick //===----------------------------------------------------------------------===//
9061da546Spatrick
10a0747c9fSpatrick #if defined(__arm64__) || defined(__aarch64__)
11a0747c9fSpatrick
12061da546Spatrick #include <elf.h>
13061da546Spatrick #include <err.h>
14061da546Spatrick #include <stdint.h>
15061da546Spatrick #include <stdlib.h>
16061da546Spatrick
17061da546Spatrick #include "NativeRegisterContextOpenBSD_arm64.h"
18061da546Spatrick
19061da546Spatrick #include "lldb/Host/HostInfo.h"
20061da546Spatrick #include "lldb/Utility/DataBufferHeap.h"
21061da546Spatrick #include "lldb/Utility/RegisterValue.h"
22061da546Spatrick #include "lldb/Utility/Status.h"
23061da546Spatrick #include "llvm/ADT/APInt.h"
24061da546Spatrick
25061da546Spatrick #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
26*101d251dSrobert #include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
27061da546Spatrick
28061da546Spatrick // clang-format off
29061da546Spatrick #include <sys/types.h>
30a955d53bSkettenis #include <sys/ptrace.h>
31061da546Spatrick #include <sys/sysctl.h>
32061da546Spatrick #include <sys/time.h>
33061da546Spatrick #include <machine/cpu.h>
34061da546Spatrick // clang-format on
35061da546Spatrick
36061da546Spatrick using namespace lldb_private;
37061da546Spatrick using namespace lldb_private::process_openbsd;
38061da546Spatrick
39061da546Spatrick #define REG_CONTEXT_SIZE (GetGPRSize() + GetFPRSize())
40061da546Spatrick
410f45e296Smortimer std::unique_ptr<NativeRegisterContextOpenBSD>
CreateHostNativeRegisterContextOpenBSD(const ArchSpec & target_arch,NativeThreadProtocol & native_thread)42061da546Spatrick NativeRegisterContextOpenBSD::CreateHostNativeRegisterContextOpenBSD(
43061da546Spatrick const ArchSpec &target_arch, NativeThreadProtocol &native_thread) {
440f45e296Smortimer return std::make_unique<NativeRegisterContextOpenBSD_arm64>(target_arch, native_thread);
45061da546Spatrick }
46061da546Spatrick
47061da546Spatrick // ----------------------------------------------------------------------------
48061da546Spatrick // NativeRegisterContextOpenBSD_arm64 members.
49061da546Spatrick // ----------------------------------------------------------------------------
50061da546Spatrick
51061da546Spatrick static RegisterInfoInterface *
CreateRegisterInfoInterface(const ArchSpec & target_arch)52061da546Spatrick CreateRegisterInfoInterface(const ArchSpec &target_arch) {
53061da546Spatrick assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
54061da546Spatrick "Register setting path assumes this is a 64-bit host");
55a955d53bSkettenis
56a955d53bSkettenis Flags opt_regsets = RegisterInfoPOSIX_arm64::eRegsetMaskPAuth;
57a955d53bSkettenis return new RegisterInfoPOSIX_arm64(target_arch, opt_regsets);
58061da546Spatrick }
59061da546Spatrick
uint128ToAPInt(__uint128_t in)60061da546Spatrick static llvm::APInt uint128ToAPInt(__uint128_t in) {
61061da546Spatrick uint64_t *pair = (uint64_t *)∈
62061da546Spatrick llvm::APInt out(128, 2, pair);
63061da546Spatrick return out;
64061da546Spatrick }
65061da546Spatrick
APIntTouint128(llvm::APInt in)66061da546Spatrick static __uint128_t APIntTouint128(llvm::APInt in) {
67061da546Spatrick assert(in.getBitWidth() == 128);
68061da546Spatrick __uint128_t out = 0;
69061da546Spatrick const uint64_t *data = in.getRawData();
70061da546Spatrick ::memcpy((uint64_t *)&out, data, sizeof(__uint128_t));
71061da546Spatrick return out;
72061da546Spatrick }
73061da546Spatrick
NativeRegisterContextOpenBSD_arm64(const ArchSpec & target_arch,NativeThreadProtocol & native_thread)74061da546Spatrick NativeRegisterContextOpenBSD_arm64::NativeRegisterContextOpenBSD_arm64(
75061da546Spatrick const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
76061da546Spatrick : NativeRegisterContextOpenBSD(native_thread,
77061da546Spatrick CreateRegisterInfoInterface(target_arch)),
78061da546Spatrick m_gpr(), m_fpr() {}
79061da546Spatrick
80a955d53bSkettenis RegisterInfoPOSIX_arm64 &
GetRegisterInfo() const81a955d53bSkettenis NativeRegisterContextOpenBSD_arm64::GetRegisterInfo() const {
82a955d53bSkettenis return static_cast<RegisterInfoPOSIX_arm64 &>(*m_register_info_interface_up);
83061da546Spatrick }
84061da546Spatrick
GetRegisterSetCount() const85061da546Spatrick uint32_t NativeRegisterContextOpenBSD_arm64::GetRegisterSetCount() const {
86a955d53bSkettenis return GetRegisterInfo().GetRegisterSetCount();
87061da546Spatrick }
88061da546Spatrick
89061da546Spatrick const RegisterSet *
GetRegisterSet(uint32_t set_index) const90061da546Spatrick NativeRegisterContextOpenBSD_arm64::GetRegisterSet(uint32_t set_index) const {
91a955d53bSkettenis return GetRegisterInfo().GetRegisterSet(set_index);
92a955d53bSkettenis }
93061da546Spatrick
GetUserRegisterCount() const94a955d53bSkettenis uint32_t NativeRegisterContextOpenBSD_arm64::GetUserRegisterCount() const {
95a955d53bSkettenis uint32_t count = 0;
96a955d53bSkettenis for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index)
97a955d53bSkettenis count += GetRegisterSet(set_index)->num_registers;
98a955d53bSkettenis return count;
99061da546Spatrick }
100061da546Spatrick
101061da546Spatrick Status
ReadRegister(const RegisterInfo * reg_info,RegisterValue & reg_value)102061da546Spatrick NativeRegisterContextOpenBSD_arm64::ReadRegister(const RegisterInfo *reg_info,
103061da546Spatrick RegisterValue ®_value) {
104061da546Spatrick Status error;
105*101d251dSrobert Log *log = GetLog(POSIXLog::Registers);
106061da546Spatrick
107061da546Spatrick if (!reg_info) {
108061da546Spatrick error.SetErrorString("reg_info NULL");
109061da546Spatrick return error;
110061da546Spatrick }
111061da546Spatrick
112061da546Spatrick const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
113061da546Spatrick if (reg == LLDB_INVALID_REGNUM) {
114061da546Spatrick // This is likely an internal register for lldb use only and should not be
115061da546Spatrick // directly queried.
116061da546Spatrick error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb "
117061da546Spatrick "register, cannot read directly",
118061da546Spatrick reg_info->name);
119061da546Spatrick return error;
120061da546Spatrick }
121061da546Spatrick
122061da546Spatrick int set = GetSetForNativeRegNum(reg);
123061da546Spatrick if (set == -1) {
124061da546Spatrick // This is likely an internal register for lldb use only and should not be
125061da546Spatrick // directly queried.
126061da546Spatrick error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set",
127061da546Spatrick reg_info->name);
128061da546Spatrick return error;
129061da546Spatrick }
130061da546Spatrick
131061da546Spatrick if (ReadRegisterSet(set) != 0) {
132061da546Spatrick // This is likely an internal register for lldb use only and should not be
133061da546Spatrick // directly queried.
134061da546Spatrick error.SetErrorStringWithFormat(
135061da546Spatrick "reading register set for register \"%s\" failed", reg_info->name);
136061da546Spatrick return error;
137061da546Spatrick }
138061da546Spatrick
139a955d53bSkettenis if (GetRegisterInfo().IsPAuthReg(reg)) {
140a955d53bSkettenis uint32_t offset;
141a955d53bSkettenis
142a955d53bSkettenis offset = reg_info->byte_offset - GetRegisterInfo().GetPAuthOffset();
143a955d53bSkettenis reg_value = (uint64_t)m_pacmask[offset > 0];
144a955d53bSkettenis if (reg_value.GetByteSize() > reg_info->byte_size) {
145*101d251dSrobert reg_value.SetType(*reg_info);
146a955d53bSkettenis }
147a955d53bSkettenis
148a955d53bSkettenis return error;
149a955d53bSkettenis }
150a955d53bSkettenis
151061da546Spatrick switch (reg) {
152061da546Spatrick case gpr_x0_arm64:
153061da546Spatrick case gpr_x1_arm64:
154061da546Spatrick case gpr_x2_arm64:
155061da546Spatrick case gpr_x3_arm64:
156061da546Spatrick case gpr_x4_arm64:
157061da546Spatrick case gpr_x5_arm64:
158061da546Spatrick case gpr_x6_arm64:
159061da546Spatrick case gpr_x7_arm64:
160061da546Spatrick case gpr_x8_arm64:
161061da546Spatrick case gpr_x9_arm64:
162061da546Spatrick case gpr_x10_arm64:
163061da546Spatrick case gpr_x11_arm64:
164061da546Spatrick case gpr_x12_arm64:
165061da546Spatrick case gpr_x13_arm64:
166061da546Spatrick case gpr_x14_arm64:
167061da546Spatrick case gpr_x15_arm64:
168061da546Spatrick case gpr_x16_arm64:
169061da546Spatrick case gpr_x17_arm64:
170061da546Spatrick case gpr_x18_arm64:
171061da546Spatrick case gpr_x19_arm64:
172061da546Spatrick case gpr_x20_arm64:
173061da546Spatrick case gpr_x21_arm64:
174061da546Spatrick case gpr_x22_arm64:
175061da546Spatrick case gpr_x23_arm64:
176061da546Spatrick case gpr_x24_arm64:
177061da546Spatrick case gpr_x25_arm64:
178061da546Spatrick case gpr_x26_arm64:
179061da546Spatrick case gpr_x27_arm64:
180061da546Spatrick case gpr_x28_arm64:
181061da546Spatrick reg_value = (uint64_t)m_gpr.r_reg[reg - gpr_x0_arm64];
182061da546Spatrick break;
183061da546Spatrick case gpr_fp_arm64:
184061da546Spatrick reg_value = (uint64_t)m_gpr.r_reg[29];
185061da546Spatrick break;
186061da546Spatrick case gpr_lr_arm64:
187061da546Spatrick reg_value = (uint64_t)m_gpr.r_lr;
188061da546Spatrick break;
189061da546Spatrick case gpr_sp_arm64:
190061da546Spatrick reg_value = (uint64_t)m_gpr.r_sp;
191061da546Spatrick break;
192061da546Spatrick case gpr_pc_arm64:
193061da546Spatrick reg_value = (uint64_t)m_gpr.r_pc;
194061da546Spatrick break;
195061da546Spatrick case gpr_cpsr_arm64:
196061da546Spatrick reg_value = (uint64_t)m_gpr.r_spsr;
197061da546Spatrick break;
198061da546Spatrick case fpu_v0_arm64:
199061da546Spatrick case fpu_v1_arm64:
200061da546Spatrick case fpu_v2_arm64:
201061da546Spatrick case fpu_v3_arm64:
202061da546Spatrick case fpu_v4_arm64:
203061da546Spatrick case fpu_v5_arm64:
204061da546Spatrick case fpu_v6_arm64:
205061da546Spatrick case fpu_v7_arm64:
206061da546Spatrick case fpu_v8_arm64:
207061da546Spatrick case fpu_v9_arm64:
208061da546Spatrick case fpu_v10_arm64:
209061da546Spatrick case fpu_v11_arm64:
210061da546Spatrick case fpu_v12_arm64:
211061da546Spatrick case fpu_v13_arm64:
212061da546Spatrick case fpu_v14_arm64:
213061da546Spatrick case fpu_v15_arm64:
214061da546Spatrick case fpu_v16_arm64:
215061da546Spatrick case fpu_v17_arm64:
216061da546Spatrick case fpu_v18_arm64:
217061da546Spatrick case fpu_v19_arm64:
218061da546Spatrick case fpu_v20_arm64:
219061da546Spatrick case fpu_v21_arm64:
220061da546Spatrick case fpu_v22_arm64:
221061da546Spatrick case fpu_v23_arm64:
222061da546Spatrick case fpu_v24_arm64:
223061da546Spatrick case fpu_v25_arm64:
224061da546Spatrick case fpu_v26_arm64:
225061da546Spatrick case fpu_v27_arm64:
226061da546Spatrick case fpu_v28_arm64:
227061da546Spatrick case fpu_v29_arm64:
228061da546Spatrick case fpu_v30_arm64:
229061da546Spatrick case fpu_v31_arm64:
230061da546Spatrick reg_value = uint128ToAPInt(m_fpr.fp_reg[reg - fpu_v0_arm64]);
231061da546Spatrick break;
232061da546Spatrick case fpu_fpsr_arm64:
233061da546Spatrick reg_value = (uint32_t)m_fpr.fp_sr;
234061da546Spatrick break;
235061da546Spatrick case fpu_fpcr_arm64:
236061da546Spatrick reg_value = (uint32_t)m_fpr.fp_cr;
237061da546Spatrick break;
238061da546Spatrick default:
239061da546Spatrick log->Printf("Requested read to unhandled reg: %u", reg);
240061da546Spatrick break;
241061da546Spatrick }
242061da546Spatrick
243061da546Spatrick if (reg_value.GetByteSize() > reg_info->byte_size) {
244*101d251dSrobert reg_value.SetType(*reg_info);
245061da546Spatrick }
246061da546Spatrick
247061da546Spatrick return error;
248061da546Spatrick }
249061da546Spatrick
WriteRegister(const RegisterInfo * reg_info,const RegisterValue & reg_value)250061da546Spatrick Status NativeRegisterContextOpenBSD_arm64::WriteRegister(
251061da546Spatrick const RegisterInfo *reg_info, const RegisterValue ®_value) {
252061da546Spatrick
253061da546Spatrick Status error;
254*101d251dSrobert Log *log = GetLog(POSIXLog::Registers);
255061da546Spatrick
256061da546Spatrick if (!reg_info) {
257061da546Spatrick error.SetErrorString("reg_info NULL");
258061da546Spatrick return error;
259061da546Spatrick }
260061da546Spatrick
261061da546Spatrick const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
262061da546Spatrick if (reg == LLDB_INVALID_REGNUM) {
263061da546Spatrick // This is likely an internal register for lldb use only and should not be
264061da546Spatrick // directly queried.
265061da546Spatrick error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb "
266061da546Spatrick "register, cannot read directly",
267061da546Spatrick reg_info->name);
268061da546Spatrick return error;
269061da546Spatrick }
270061da546Spatrick
271061da546Spatrick int set = GetSetForNativeRegNum(reg);
272061da546Spatrick if (set == -1) {
273061da546Spatrick // This is likely an internal register for lldb use only and should not be
274061da546Spatrick // directly queried.
275061da546Spatrick error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set",
276061da546Spatrick reg_info->name);
277061da546Spatrick return error;
278061da546Spatrick }
279061da546Spatrick
280061da546Spatrick if (ReadRegisterSet(set) != 0) {
281061da546Spatrick // This is likely an internal register for lldb use only and should not be
282061da546Spatrick // directly queried.
283061da546Spatrick error.SetErrorStringWithFormat(
284061da546Spatrick "reading register set for register \"%s\" failed", reg_info->name);
285061da546Spatrick return error;
286061da546Spatrick }
287061da546Spatrick
288061da546Spatrick switch (reg) {
289061da546Spatrick case gpr_x0_arm64:
290061da546Spatrick case gpr_x1_arm64:
291061da546Spatrick case gpr_x2_arm64:
292061da546Spatrick case gpr_x3_arm64:
293061da546Spatrick case gpr_x4_arm64:
294061da546Spatrick case gpr_x5_arm64:
295061da546Spatrick case gpr_x6_arm64:
296061da546Spatrick case gpr_x7_arm64:
297061da546Spatrick case gpr_x8_arm64:
298061da546Spatrick case gpr_x9_arm64:
299061da546Spatrick case gpr_x10_arm64:
300061da546Spatrick case gpr_x11_arm64:
301061da546Spatrick case gpr_x12_arm64:
302061da546Spatrick case gpr_x13_arm64:
303061da546Spatrick case gpr_x14_arm64:
304061da546Spatrick case gpr_x15_arm64:
305061da546Spatrick case gpr_x16_arm64:
306061da546Spatrick case gpr_x17_arm64:
307061da546Spatrick case gpr_x18_arm64:
308061da546Spatrick case gpr_x19_arm64:
309061da546Spatrick case gpr_x20_arm64:
310061da546Spatrick case gpr_x21_arm64:
311061da546Spatrick case gpr_x22_arm64:
312061da546Spatrick case gpr_x23_arm64:
313061da546Spatrick case gpr_x24_arm64:
314061da546Spatrick case gpr_x25_arm64:
315061da546Spatrick case gpr_x26_arm64:
316061da546Spatrick case gpr_x27_arm64:
317061da546Spatrick case gpr_x28_arm64:
318061da546Spatrick m_gpr.r_reg[reg - gpr_x0_arm64] = reg_value.GetAsUInt64();
319061da546Spatrick break;
320061da546Spatrick case gpr_fp_arm64:
321061da546Spatrick m_gpr.r_reg[29] = reg_value.GetAsUInt64();
322061da546Spatrick break;
323061da546Spatrick case gpr_lr_arm64:
324061da546Spatrick m_gpr.r_lr = reg_value.GetAsUInt64();
325061da546Spatrick break;
326061da546Spatrick case gpr_sp_arm64:
327061da546Spatrick m_gpr.r_sp = reg_value.GetAsUInt64();
328061da546Spatrick break;
329061da546Spatrick case gpr_pc_arm64:
330061da546Spatrick m_gpr.r_pc = reg_value.GetAsUInt64();
331061da546Spatrick break;
332061da546Spatrick case gpr_cpsr_arm64:
333061da546Spatrick m_gpr.r_spsr = reg_value.GetAsUInt64();
334061da546Spatrick break;
335061da546Spatrick case fpu_v0_arm64:
336061da546Spatrick case fpu_v1_arm64:
337061da546Spatrick case fpu_v2_arm64:
338061da546Spatrick case fpu_v3_arm64:
339061da546Spatrick case fpu_v4_arm64:
340061da546Spatrick case fpu_v5_arm64:
341061da546Spatrick case fpu_v6_arm64:
342061da546Spatrick case fpu_v7_arm64:
343061da546Spatrick case fpu_v8_arm64:
344061da546Spatrick case fpu_v9_arm64:
345061da546Spatrick case fpu_v10_arm64:
346061da546Spatrick case fpu_v11_arm64:
347061da546Spatrick case fpu_v12_arm64:
348061da546Spatrick case fpu_v13_arm64:
349061da546Spatrick case fpu_v14_arm64:
350061da546Spatrick case fpu_v15_arm64:
351061da546Spatrick case fpu_v16_arm64:
352061da546Spatrick case fpu_v17_arm64:
353061da546Spatrick case fpu_v18_arm64:
354061da546Spatrick case fpu_v19_arm64:
355061da546Spatrick case fpu_v20_arm64:
356061da546Spatrick case fpu_v21_arm64:
357061da546Spatrick case fpu_v22_arm64:
358061da546Spatrick case fpu_v23_arm64:
359061da546Spatrick case fpu_v24_arm64:
360061da546Spatrick case fpu_v25_arm64:
361061da546Spatrick case fpu_v26_arm64:
362061da546Spatrick case fpu_v27_arm64:
363061da546Spatrick case fpu_v28_arm64:
364061da546Spatrick case fpu_v29_arm64:
365061da546Spatrick case fpu_v30_arm64:
366061da546Spatrick case fpu_v31_arm64:
367061da546Spatrick m_fpr.fp_reg[reg - fpu_v0_arm64] =
368061da546Spatrick APIntTouint128(reg_value.GetAsUInt128(llvm::APInt(128, 0, false)));
369061da546Spatrick break;
370061da546Spatrick case fpu_fpsr_arm64:
371061da546Spatrick m_fpr.fp_sr = reg_value.GetAsUInt32();
372061da546Spatrick break;
373061da546Spatrick case fpu_fpcr_arm64:
374061da546Spatrick m_fpr.fp_cr = reg_value.GetAsUInt32();
375061da546Spatrick break;
376061da546Spatrick default:
377061da546Spatrick log->Printf("Requested write of unhandled reg: %u", reg);
378061da546Spatrick break;
379061da546Spatrick }
380061da546Spatrick
381061da546Spatrick if (WriteRegisterSet(set) != 0)
382061da546Spatrick error.SetErrorStringWithFormat("failed to write register set");
383061da546Spatrick
384061da546Spatrick return error;
385061da546Spatrick }
386061da546Spatrick
ReadAllRegisterValues(lldb::WritableDataBufferSP & data_sp)387061da546Spatrick Status NativeRegisterContextOpenBSD_arm64::ReadAllRegisterValues(
388*101d251dSrobert lldb::WritableDataBufferSP &data_sp) {
389061da546Spatrick Status error;
390061da546Spatrick
391061da546Spatrick data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
392061da546Spatrick if (!data_sp) {
393061da546Spatrick error.SetErrorStringWithFormat(
394061da546Spatrick "failed to allocate DataBufferHeap instance of size %zu",
395061da546Spatrick REG_CONTEXT_SIZE);
396061da546Spatrick return error;
397061da546Spatrick }
398061da546Spatrick
399061da546Spatrick error = ReadGPR();
400061da546Spatrick if (error.Fail())
401061da546Spatrick return error;
402061da546Spatrick
403061da546Spatrick error = ReadFPR();
404061da546Spatrick if (error.Fail())
405061da546Spatrick return error;
406061da546Spatrick
407061da546Spatrick uint8_t *dst = data_sp->GetBytes();
408061da546Spatrick if (dst == nullptr) {
409061da546Spatrick error.SetErrorStringWithFormat("DataBufferHeap instance of size %zu"
410061da546Spatrick " returned a null pointer",
411061da546Spatrick REG_CONTEXT_SIZE);
412061da546Spatrick return error;
413061da546Spatrick }
414061da546Spatrick
415061da546Spatrick ::memcpy(dst, &m_gpr, GetGPRSize());
416061da546Spatrick dst += GetGPRSize();
417061da546Spatrick
418061da546Spatrick ::memcpy(dst, &m_fpr, GetFPRSize());
419061da546Spatrick dst += GetFPRSize();
420061da546Spatrick
421061da546Spatrick return error;
422061da546Spatrick }
423061da546Spatrick
WriteAllRegisterValues(const lldb::DataBufferSP & data_sp)424061da546Spatrick Status NativeRegisterContextOpenBSD_arm64::WriteAllRegisterValues(
425061da546Spatrick const lldb::DataBufferSP &data_sp) {
426061da546Spatrick Status error;
427061da546Spatrick
428061da546Spatrick if (!data_sp) {
429061da546Spatrick error.SetErrorStringWithFormat(
430061da546Spatrick "NativeRegisterContextOpenBSD_arm64::%s invalid data_sp provided",
431061da546Spatrick __FUNCTION__);
432061da546Spatrick return error;
433061da546Spatrick }
434061da546Spatrick
435061da546Spatrick if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) {
436061da546Spatrick error.SetErrorStringWithFormat(
437061da546Spatrick "NativeRegisterContextOpenBSD_arm64::%s data_sp contained mismatched "
438061da546Spatrick "data size, expected %zu, actual %llu",
439061da546Spatrick __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize());
440061da546Spatrick return error;
441061da546Spatrick }
442061da546Spatrick
443*101d251dSrobert const uint8_t *src = data_sp->GetBytes();
444061da546Spatrick if (src == nullptr) {
445061da546Spatrick error.SetErrorStringWithFormat("NativeRegisterContextOpenBSD_arm64::%s "
446061da546Spatrick "DataBuffer::GetBytes() returned a null "
447061da546Spatrick "pointer",
448061da546Spatrick __FUNCTION__);
449061da546Spatrick return error;
450061da546Spatrick }
451061da546Spatrick // TODO ?
452061da546Spatrick // Do we need to make a custom RegisterInfoOpenBSD_arm64
453061da546Spatrick // because the RegisterInfoPOSIX_arm64 doesn't quite match
454061da546Spatrick // our machine/reg.h?
455061da546Spatrick ::memcpy(&m_gpr, src, GetGPRSize());
456061da546Spatrick error = WriteGPR();
457061da546Spatrick if (error.Fail())
458061da546Spatrick return error;
459061da546Spatrick src += GetGPRSize();
460061da546Spatrick
461061da546Spatrick ::memcpy(&m_fpr, src, GetFPRSize());
462061da546Spatrick error = WriteFPR();
463061da546Spatrick if (error.Fail())
464061da546Spatrick return error;
465061da546Spatrick src += GetFPRSize();
466061da546Spatrick
467061da546Spatrick return error;
468061da546Spatrick }
469061da546Spatrick
GetSetForNativeRegNum(int reg_num) const470061da546Spatrick int NativeRegisterContextOpenBSD_arm64::GetSetForNativeRegNum(
471061da546Spatrick int reg_num) const {
472061da546Spatrick if (reg_num >= k_first_gpr_arm64 && reg_num <= k_last_gpr_arm64)
473061da546Spatrick return GPRegSet;
474061da546Spatrick else if (reg_num >= k_first_fpr_arm64 && reg_num <= k_last_fpr_arm64)
475061da546Spatrick return FPRegSet;
476a955d53bSkettenis else if (GetRegisterInfo().IsPAuthReg(reg_num))
477a955d53bSkettenis return PACMaskRegSet;
478061da546Spatrick else
479061da546Spatrick return -1;
480061da546Spatrick }
481061da546Spatrick
ReadRegisterSet(uint32_t set)482061da546Spatrick int NativeRegisterContextOpenBSD_arm64::ReadRegisterSet(uint32_t set) {
483061da546Spatrick switch (set) {
484061da546Spatrick case GPRegSet:
485061da546Spatrick ReadGPR();
486061da546Spatrick return 0;
487061da546Spatrick case FPRegSet:
488061da546Spatrick ReadFPR();
489061da546Spatrick return 0;
490a955d53bSkettenis case PACMaskRegSet:
491a955d53bSkettenis ReadPACMask();
492a955d53bSkettenis return 0;
493061da546Spatrick default:
494061da546Spatrick break;
495061da546Spatrick }
496061da546Spatrick return -1;
497061da546Spatrick }
498061da546Spatrick
WriteRegisterSet(uint32_t set)499061da546Spatrick int NativeRegisterContextOpenBSD_arm64::WriteRegisterSet(uint32_t set) {
500061da546Spatrick switch (set) {
501061da546Spatrick case GPRegSet:
502061da546Spatrick WriteGPR();
503061da546Spatrick return 0;
504061da546Spatrick case FPRegSet:
505061da546Spatrick WriteFPR();
506061da546Spatrick return 0;
507061da546Spatrick default:
508061da546Spatrick break;
509061da546Spatrick }
510061da546Spatrick return -1;
511061da546Spatrick }
512a955d53bSkettenis
ReadPACMask()513a955d53bSkettenis Status NativeRegisterContextOpenBSD_arm64::ReadPACMask() {
514a955d53bSkettenis #ifdef PT_PACMASK
515a955d53bSkettenis return NativeProcessOpenBSD::PtraceWrapper(PT_PACMASK, GetProcessPid(),
516a955d53bSkettenis &m_pacmask, sizeof(m_pacmask));
517a955d53bSkettenis #else
518a955d53bSkettenis Status error;
519a955d53bSkettenis ::memset(&m_pacmask, 0, sizeof(m_pacmask));
520a955d53bSkettenis return error;
521a955d53bSkettenis #endif
522a955d53bSkettenis }
523a955d53bSkettenis
524a0747c9fSpatrick #endif
525